diff --git a/packages/indexer-agent/src/__tests__/agent.ts b/packages/indexer-agent/src/__tests__/agent.ts new file mode 100644 index 000000000..e1f764240 --- /dev/null +++ b/packages/indexer-agent/src/__tests__/agent.ts @@ -0,0 +1,168 @@ +import { convertSubgraphBasedRulesToDeploymentBased } from '../agent' +import { + INDEXING_RULE_GLOBAL, + IndexingDecisionBasis, + IndexingRuleAttributes, + SubgraphIdentifierType, + SubgraphVersion, +} from '@graphprotocol/indexer-common' +import { SubgraphDeploymentID } from '@graphprotocol/common-ts' + +describe('Agent convenience function tests', () => { + test('Convert subgraph based rules to deployment based - success', async () => { + const inputRules = [ + { + identifier: INDEXING_RULE_GLOBAL, + identifierType: SubgraphIdentifierType.GROUP, + allocationAmount: '2300', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + { + identifier: '0x0000000000000000000000000000000000000000-0', + identifierType: SubgraphIdentifierType.SUBGRAPH, + allocationAmount: '3000', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + { + identifier: 'QmZZtzZkfzCWMNrajxBf22q7BC9HzoT5iJUK3S8qA6zNZr', + identifierType: SubgraphIdentifierType.DEPLOYMENT, + allocationAmount: '12000', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + ] as IndexingRuleAttributes[] + + const subgraphs = [ + { + id: '0x0000000000000000000000000000000000000000-0', + versionCount: 1, + versions: [ + { + version: 0, + createdAt: 1, + deployment: new SubgraphDeploymentID( + 'QmbvTyvmxqHLahZwS7fZtVWGM85VCpCiKHiagPxQJp5ktS', + ), + } as SubgraphVersion, + ], + }, + ] + const expectedRules = [ + { + identifier: INDEXING_RULE_GLOBAL, + identifierType: SubgraphIdentifierType.GROUP, + allocationAmount: '2300', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + { + identifier: + '0xc9d18c59e4aaf2c1f86dfef16fbdc0f81eae8ada58d87a23d2666c45704b8823', + identifierType: SubgraphIdentifierType.DEPLOYMENT, + allocationAmount: '3000', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + { + identifier: 'QmZZtzZkfzCWMNrajxBf22q7BC9HzoT5iJUK3S8qA6zNZr', + identifierType: SubgraphIdentifierType.DEPLOYMENT, + allocationAmount: '12000', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + ] as IndexingRuleAttributes[] + + expect( + convertSubgraphBasedRulesToDeploymentBased(inputRules, subgraphs, 1000), + ).toEqual(expectedRules) + }) + + test('Convert subgraph based rules to deployment based - no op', async () => { + const inputRules = [ + { + identifier: INDEXING_RULE_GLOBAL, + identifierType: SubgraphIdentifierType.GROUP, + allocationAmount: '2300', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + { + identifier: 'QmZZtzZkfzCWMNrajxBf22q7BC9HzoT5iJUK3S8qA6zNZr', + identifierType: SubgraphIdentifierType.DEPLOYMENT, + allocationAmount: '12000', + parallelAllocations: null, + maxAllocationPercentage: null, + minSignal: null, + maxSignal: null, + minStake: null, + minAverageQueryFees: null, + custom: null, + decisionBasis: IndexingDecisionBasis.RULES, + }, + ] as IndexingRuleAttributes[] + + const subgraphs = [ + { + id: '0x0000000000000000000000000000000000000000-0', + versionCount: 1, + versions: [ + { + version: 0, + createdAt: 1, + deployment: new SubgraphDeploymentID( + 'QmbvTyvmxqHLahZwS7fZtVWGM85VCpCiKHiagPxQJp5ktS', + ), + } as SubgraphVersion, + ], + }, + ] + + expect( + convertSubgraphBasedRulesToDeploymentBased(inputRules, subgraphs, 1000), + ).toEqual(inputRules) + }) +}) diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index d7f594938..77710b558 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -50,7 +50,8 @@ const deploymentRuleInList = ( list.find( rule => rule.identifierType == SubgraphIdentifierType.DEPLOYMENT && - rule.identifier == deployment.ipfsHash, + new SubgraphDeploymentID(rule.identifier).toString() == + deployment.toString(), ) !== undefined const uniqueDeploymentsOnly = ( @@ -63,13 +64,16 @@ const uniqueDeployments = ( deployments: SubgraphDeploymentID[], ): SubgraphDeploymentID[] => deployments.filter(uniqueDeploymentsOnly) -const convertSubgraphBasedRulesToDeploymentBased = ( +export const convertSubgraphBasedRulesToDeploymentBased = ( rules: IndexingRuleAttributes[], subgraphs: Subgraph[], previousVersionBuffer: number, ): IndexingRuleAttributes[] => { const toAdd: IndexingRuleAttributes[] = [] rules.map(rule => { + if (rule.identifierType !== SubgraphIdentifierType.SUBGRAPH) { + return rule + } const ruleSubgraph = subgraphs.find( subgraph => subgraph.id == rule.identifier, ) @@ -106,6 +110,7 @@ const convertSubgraphBasedRulesToDeploymentBased = ( } } } + return rule }) rules.push(...toAdd) return rules @@ -591,8 +596,11 @@ class Agent { deploymentIDSet(activeDeployments) != deploymentIDSet(targetDeployments) ) { this.logger.info('Reconcile deployments', { - active: activeDeployments.map(id => id.display), + syncing: activeDeployments.map(id => id.display), target: targetDeployments.map(id => id.display), + withActiveOrRecentlyClosedAllocation: eligibleAllocationDeployments.map( + id => id.display, + ), }) } @@ -653,8 +661,10 @@ class Agent { currentEpoch, maxAllocationEpochs, allocationLifetime, - targetDeployments, - active: activeAllocations.map(allocation => ({ + targetDeployments: targetDeployments.map( + deployment => deployment.display, + ), + activeAllocations: activeAllocations.map(allocation => ({ id: allocation.id, deployment: allocation.subgraphDeployment.id.display, createdAtEpoch: allocation.createdAtEpoch, @@ -700,8 +710,12 @@ class Agent { deploymentInList(targetDeployments, deployment), // Indexing rule for the deployment (if any) - rules.find(rule => rule.identifier === deployment.bytes32) || - rules.find(rule => rule.identifier === INDEXING_RULE_GLOBAL), + rules.find( + rule => + rule.identifierType === SubgraphIdentifierType.DEPLOYMENT && + new SubgraphDeploymentID(rule.identifier).toString() === + deployment.toString(), + ) || rules.find(rule => rule.identifier === INDEXING_RULE_GLOBAL), currentEpoch, currentEpochStartBlock, diff --git a/packages/indexer-agent/src/network.ts b/packages/indexer-agent/src/network.ts index a705d579a..07de3151f 100644 --- a/packages/indexer-agent/src/network.ts +++ b/packages/indexer-agent/src/network.ts @@ -1,41 +1,42 @@ import { + Address, + Eventual, + formatGRT, Logger, + mutable, NetworkContracts, SubgraphDeploymentID, - formatGRT, timer, - Eventual, - Address, toAddress, - mutable, } from '@graphprotocol/common-ts' import { Allocation, AllocationStatus, Epoch, - IndexingRuleAttributes, - IndexingDecisionBasis, - INDEXING_RULE_GLOBAL, - parseGraphQLAllocation, - parseGraphQLEpochs, - uniqueAllocationID, - indexerError, - IndexerErrorCode, INDEXER_ERROR_MESSAGES, + indexerError, IndexerError, + IndexerErrorCode, + INDEXING_RULE_GLOBAL, + IndexingDecisionBasis, + IndexingRuleAttributes, NetworkSubgraph, + parseGraphQLAllocation, + parseGraphQLEpochs, Subgraph, + SubgraphIdentifierType, SubgraphVersion, + uniqueAllocationID, } from '@graphprotocol/indexer-common' import { - ContractTransaction, - ContractReceipt, BigNumber, + BigNumberish, + ContractReceipt, + ContractTransaction, providers, - Wallet, - utils, Signer, - BigNumberish, + utils, + Wallet, } from 'ethers' import { strict as assert } from 'assert' import gql from 'graphql-tag' @@ -651,9 +652,16 @@ export class Network { // eslint-disable-next-line @typescript-eslint/no-explicit-any .filter((deployment: any) => { const deploymentRule = - rules.find(rule => rule.identifier === deployment.id) || - globalRule - + rules + .filter( + rule => + rule.identifierType == SubgraphIdentifierType.DEPLOYMENT, + ) + .find( + rule => + new SubgraphDeploymentID(rule.identifier).toString() === + deployment.id, + ) || globalRule // The deployment is not eligible for deployment if it doesn't have an allocation amount if (!deploymentRule?.allocationAmount) { this.logger.debug( @@ -665,17 +673,6 @@ export class Network { return false } - // Skip the indexing rules checks if the decision basis is 'always' or 'never' - if ( - deploymentRule?.decisionBasis === IndexingDecisionBasis.ALWAYS - ) { - return true - } else if ( - deploymentRule?.decisionBasis === IndexingDecisionBasis.NEVER - ) { - return false - } - if (deploymentRule) { const stakedTokens = BigNumber.from(deployment.stakedTokens) const signalAmount = BigNumber.from(deployment.signalAmount) @@ -689,12 +686,13 @@ export class Network { this.logger.trace('Deciding whether to allocate and index', { deployment: { - id: deployment.id.display, + id: deployment.id, stakedTokens: stakedTokens.toString(), signalAmount: signalAmount.toString(), avgQueryFees: avgQueryFees.toString(), }, indexingRule: { + decisionBasis: deploymentRule.decisionBasis, deployment: deploymentRule.identifier, minStake: deploymentRule.minStake ? BigNumber.from(deploymentRule.minStake).toString() @@ -713,6 +711,17 @@ export class Network { }, }) + // Skip the indexing rules checks if the decision basis is 'always' or 'never' + if ( + deploymentRule.decisionBasis === IndexingDecisionBasis.ALWAYS + ) { + return true + } else if ( + deploymentRule.decisionBasis === IndexingDecisionBasis.NEVER + ) { + return false + } + return ( // stake >= minStake? (deploymentRule.minStake &&