Skip to content

chore: horizon allocation commands #1128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ Manage indexer configuration
indexer rules delete Remove one or many indexing rules
indexer rules clear (reset) Clear one or more indexing rules
indexer rules Configure indexing rules
indexer provision thaw Thaw stake from the indexer's provision
indexer provision remove Remove thawed stake from the indexer's provision
indexer provision list-thaw List thaw requests for the indexer's provision
indexer provision get List indexer provision details
indexer provision add Add stake to the indexer's provision
indexer provision Manage indexer's provision
indexer disputes get Cross-check POIs submitted in the network
indexer disputes Configure allocation POI monitoring
indexer cost set model Update a cost model
Expand Down
6 changes: 6 additions & 0 deletions packages/indexer-cli/src/__tests__/references/indexer.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ Manage indexer configuration
indexer rules delete Remove one or many indexing rules
indexer rules clear (reset) Clear one or more indexing rules
indexer rules Configure indexing rules
indexer provision thaw Thaw stake from the indexer's provision
indexer provision remove Remove thawed stake from the indexer's provision
indexer provision list-thaw List thaw requests for the indexer's provision
indexer provision get List indexer provision details
indexer provision add Add stake to the indexer's provision
indexer provision Manage indexer's provision
indexer disputes get Cross-check POIs submitted in the network
indexer disputes Configure allocation POI monitoring
indexer cost set model Update a cost model
Expand Down
21 changes: 19 additions & 2 deletions packages/indexer-cli/src/allocations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface IndexerAllocation {
queryFeesCollected: bigint
status: string
protocolNetwork: string
isLegacy: boolean
}

const ALLOCATION_CONVERTERS_FROM_GRAPHQL: Record<
Expand All @@ -53,6 +54,7 @@ const ALLOCATION_CONVERTERS_FROM_GRAPHQL: Record<
queryFeesCollected: nullPassThrough((x: string) => BigInt(x)),
status: x => x,
protocolNetwork: x => x,
isLegacy: x => x,
}

const ALLOCATION_FORMATTERS: Record<
Expand All @@ -76,6 +78,7 @@ const ALLOCATION_FORMATTERS: Record<
queryFeesCollected: x => commify(formatGRT(x)),
status: x => x,
protocolNetwork: resolveChainAlias,
isLegacy: x => (x ? 'Yes' : 'No'),
}

/**
Expand Down Expand Up @@ -218,6 +221,8 @@ export const closeAllocation = async (
client: IndexerManagementClient,
allocationID: string,
poi: string | undefined,
blockNumber: number | undefined,
publicPOI: string | undefined,
force: boolean,
protocolNetwork: string,
): Promise<CloseAllocationResult> => {
Expand All @@ -227,26 +232,31 @@ export const closeAllocation = async (
mutation closeAllocation(
$allocation: String!
$poi: String
$blockNumber: Int
$publicPOI: String
$force: Boolean
$protocolNetwork: String!
) {
closeAllocation(
allocation: $allocation
poi: $poi
blockNumber: $blockNumber
publicPOI: $publicPOI
force: $force
protocolNetwork: $protocolNetwork
) {
allocation
allocatedTokens
indexingRewards
receiptsWorthCollecting
protocolNetwork
}
}
`,
{
allocation: allocationID,
poi,
blockNumber,
publicPOI,
force,
protocolNetwork,
},
Expand All @@ -264,6 +274,8 @@ export const reallocateAllocation = async (
client: IndexerManagementClient,
allocationID: string,
poi: string | undefined,
blockNumber: number | undefined,
publicPOI: string | undefined,
amount: bigint,
force: boolean,
protocolNetwork: string,
Expand All @@ -274,20 +286,23 @@ export const reallocateAllocation = async (
mutation reallocateAllocation(
$allocation: String!
$poi: String
$blockNumber: Int
$publicPOI: String
$amount: String!
$force: Boolean
$protocolNetwork: String!
) {
reallocateAllocation(
allocation: $allocation
poi: $poi
blockNumber: $blockNumber
publicPOI: $publicPOI
amount: $amount
force: $force
protocolNetwork: $protocolNetwork
) {
closedAllocation
indexingRewardsCollected
receiptsWorthCollecting
createdAllocation
createdAllocationStake
protocolNetwork
Expand All @@ -297,6 +312,8 @@ export const reallocateAllocation = async (
{
allocation: allocationID,
poi,
blockNumber,
publicPOI,
amount: amount.toString(),
force,
protocolNetwork,
Expand Down
32 changes: 25 additions & 7 deletions packages/indexer-cli/src/commands/indexer/allocations/close.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ import { validatePOI, printObjectOrArray } from '../../../command-helpers'
import { validateNetworkIdentifier } from '@graphprotocol/indexer-common'

const HELP = `
${chalk.bold('graph indexer allocations close')} [options] <network> <id> <poi>
${chalk.bold(
'graph indexer allocations close',
)} [options] <network> <id> <poi> <blockNumber> <publicPOI>

${chalk.dim('Options:')}

-h, --help Show usage information
-f, --force Bypass POIaccuracy checks and submit transaction with provided data
-f, --force Bypass POI accuracy checks and submit transaction with provided data
-o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML

${chalk.dim('Networks:')}
mainnet, arbitrum-one, sepolia or arbitrum sepolia
${chalk.dim('Arguments:')}
<network> The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia
<id> The allocation id to close
<poi> The POI to close the allocation with
<blockNumber> The block number the POI was computed at
<publicPOI> [Horizon] The public POI to close the allocation with. Must be same block height as POI.
`

module.exports = {
Expand Down Expand Up @@ -46,7 +52,8 @@ module.exports = {
return
}

const [network, id, unformattedPoi] = parameters.array || []
const [network, id, unformattedPoi, unformattedBlockNumber, unformattedPublicPOI] =
parameters.array || []

if (id === undefined) {
spinner.fail(`Missing required argument: 'id'`)
Expand All @@ -72,8 +79,12 @@ module.exports = {
}

let poi: string | undefined
let blockNumber: number | undefined
let publicPOI: string | undefined
try {
poi = validatePOI(unformattedPoi)
publicPOI = validatePOI(unformattedPublicPOI)
blockNumber = Number(unformattedBlockNumber)
} catch (error) {
spinner.fail(`Invalid POI provided, '${unformattedPoi}'. ` + error.message)
process.exitCode = 1
Expand All @@ -84,14 +95,21 @@ module.exports = {
try {
const config = loadValidatedConfig()
const client = await createIndexerManagementClient({ url: config.api })
const closeResult = await closeAllocation(client, id, poi, toForce, protocolNetwork)
const closeResult = await closeAllocation(
client,
id,
poi,
blockNumber,
publicPOI,
toForce,
protocolNetwork,
)

spinner.succeed('Allocation closed')
printObjectOrArray(print, outputFormat, closeResult, [
'allocation',
'allocatedTokens',
'indexingRewards',
'receiptsWorthCollecting',
])
} catch (error) {
spinner.fail(error.toString())
Expand Down
2 changes: 2 additions & 0 deletions packages/indexer-cli/src/commands/indexer/allocations/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ module.exports = {
query allocations($filter: AllocationFilter!) {
allocations(filter: $filter) {
id
isLegacy
protocolNetwork
indexer
subgraphDeployment
Expand Down Expand Up @@ -145,6 +146,7 @@ module.exports = {

let displayProperties: (keyof IndexerAllocation)[] = [
'id',
'isLegacy',
'protocolNetwork',
'indexer',
'subgraphDeployment',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ ${chalk.dim('Options:')}
-h, --help Show usage information
-f, --force Bypass POI accuracy checks and submit transaction with provided data

${chalk.dim('Networks:')}
mainnet, arbitrum-one, sepolia or arbitrum sepolia
${chalk.dim('Arguments:')}
<network> The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia
<id> The allocation id to close
<poi> The POI to close the allocation with
<blockNumber> The block number the POI was computed at
<publicPOI> [Horizon] The public POI to close the allocation with. Must be same block height as POI.
`

module.exports = {
Expand Down Expand Up @@ -47,7 +51,8 @@ module.exports = {
}

// eslint-disable-next-line prefer-const
let [network, id, amount, poi] = parameters.array || []
let [network, id, amount, poi, unformattedBlockNumber, publicPOI] =
parameters.array || []

if (network === undefined) {
spinner.fail(`Missing required argument: 'network'`)
Expand All @@ -72,6 +77,7 @@ module.exports = {

try {
validatePOI(poi)
validatePOI(publicPOI)
const allocationAmount = BigInt(amount)
const config = loadValidatedConfig()
const client = await createIndexerManagementClient({ url: config.api })
Expand All @@ -81,6 +87,8 @@ module.exports = {
client,
id,
poi,
Number(unformattedBlockNumber),
publicPOI,
allocationAmount,
toForce,
network,
Expand All @@ -94,7 +102,6 @@ module.exports = {
[
'closedAllocation',
'indexingRewardsCollected',
'receiptsWorthCollecting',
'createdAllocation',
'createdAllocationStake',
],
Expand Down
2 changes: 1 addition & 1 deletion packages/indexer-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"dependencies": {
"@pinax/graph-networks-registry": "0.6.7",
"@graphprotocol/common-ts": "3.0.1",
"@graphprotocol/toolshed": "0.5.0",
"@graphprotocol/toolshed": "0.5.5",
"@semiotic-labs/tap-contracts-bindings": "2.0.0",
"@thi.ng/heaps": "1.2.38",
"@types/lodash.clonedeep": "^4.5.7",
Expand Down
1 change: 0 additions & 1 deletion packages/indexer-common/src/allocations/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export * from './escrow-accounts'
export * from './keys'
export * from './query-fees'
export * from './tap-collector'
export * from './monitor'
export * from './types'
32 changes: 30 additions & 2 deletions packages/indexer-common/src/allocations/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const deriveKeyPair = (
deployment: SubgraphDeploymentID,
index: number,
): { publicKey: string; privateKey: string; address: Address } => {
const path = 'm/' + [epoch, ...Buffer.from(deployment.ipfsHash), index].join('/')
const path = [epoch, ...Buffer.from(deployment.ipfsHash), index].join('/')
const derivedKey = hdNode.derivePath(path)
return {
publicKey: derivedKey.publicKey,
Expand Down Expand Up @@ -82,7 +82,7 @@ export const uniqueAllocationID = (
throw new Error(`Exhausted limit of 100 parallel allocations`)
}

export const allocationIdProof = (
export const legacyAllocationIdProof = (
signer: Signer,
indexerAddress: string,
allocationId: string,
Expand All @@ -95,6 +95,34 @@ export const allocationIdProof = (
return signer.signMessage(messageHashBytes)
}

export const EIP712_ALLOCATION_ID_PROOF_TYPES = {
AllocationIdProof: [
{ name: 'indexer', type: 'address' },
{ name: 'allocationId', type: 'address' },
],
}

// For new allocations in the subgraph service
export const horizonAllocationIdProof = (
signer: Signer,
chainId: number,
indexerAddress: Address,
allocationId: Address,
subgraphServiceAddress: string,
): Promise<string> => {
const domain = {
name: 'SubgraphService',
version: '1.0',
chainId: chainId,
verifyingContract: subgraphServiceAddress,
}

return signer.signTypedData(domain, EIP712_ALLOCATION_ID_PROOF_TYPES, {
indexer: indexerAddress,
allocationId: allocationId,
})
}

export const tapAllocationIdProof = (
signer: Signer,
chainId: number,
Expand Down
Loading
Loading