From 42f4ee3d2dea538584166551da99e2d4b45ba2e1 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Fri, 14 Oct 2022 10:37:21 -0700 Subject: [PATCH] indexer-agent,-common: Use consistent clear network/epoch var naming --- packages/indexer-agent/src/agent.ts | 58 +++--- packages/indexer-agent/src/commands/start.ts | 10 +- .../indexer-common/src/allocations/types.ts | 172 +----------------- packages/indexer-common/src/epoch-subgraph.ts | 47 +---- .../__tests__/resolvers/actions.ts | 9 +- .../src/indexer-management/actions.ts | 2 +- .../src/indexer-management/allocations.ts | 7 +- .../src/indexer-management/client.ts | 4 +- .../src/indexer-management/index.ts | 1 + .../src/indexer-management/monitor.ts | 69 ++++--- .../src/indexer-management/types.ts | 164 +++++++++++++++++ .../indexer-common/src/indexing-status.ts | 1 + packages/indexer-common/src/subgraphs.ts | 2 +- packages/indexer-common/src/types.ts | 9 + 14 files changed, 264 insertions(+), 291 deletions(-) create mode 100644 packages/indexer-common/src/indexer-management/types.ts diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index fd7aebf0b..9a7a58902 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -165,16 +165,15 @@ class Agent { await this.network.register() } - const currentEpoch = timer(600_000).tryMap( - async () => - (await this.network.contracts.epochManager.currentEpoch()).toNumber(), + const currentEpochNumber = timer(600_000).tryMap( + async () => this.networkMonitor.currentEpochNumber(), { onError: error => this.logger.warn(`Failed to fetch current epoch`, { error }), }, ) - const currentEpochStartBlock = currentEpoch.tryMap( + const currentEpochStartBlock = currentEpochNumber.tryMap( async () => { const startBlockNumber = await this.network.contracts.epochManager.currentEpochBlock() @@ -184,7 +183,7 @@ class Agent { return { number: startBlock.number, hash: startBlock.hash, - } + } as BlockPointer }, { onError: error => @@ -194,11 +193,8 @@ class Agent { }, ) - const protocolChainLatestValidEpoch = timer(600_000).tryMap( - async () => - await this.networkMonitor.latestValidEpoch( - this.networkMonitor.networkAlias, - ), + const networkLatestEpoch = timer(600_000).tryMap( + async () => await this.networkMonitor.networkCurrentEpoch(), { onError: error => this.logger.warn( @@ -357,12 +353,12 @@ class Agent { const recentlyClosedAllocations = join({ activeAllocations, - currentEpoch, + currentEpochNumber, }).tryMap( // eslint-disable-next-line @typescript-eslint/no-unused-vars - ({ activeAllocations, currentEpoch }) => + ({ activeAllocations, currentEpochNumber }) => this.networkMonitor.recentlyClosedAllocations( - currentEpoch, + currentEpochNumber, 1, //TODO: Parameterize with a user provided value ), { @@ -374,11 +370,13 @@ class Agent { ) const claimableAllocations = join({ - currentEpoch, + currentEpochNumber, channelDisputeEpochs, }).tryMap( - ({ currentEpoch, channelDisputeEpochs }) => - this.network.claimableAllocations(currentEpoch - channelDisputeEpochs), + ({ currentEpochNumber, channelDisputeEpochs }) => + this.network.claimableAllocations( + currentEpochNumber - channelDisputeEpochs, + ), { onError: () => this.logger.warn( @@ -389,11 +387,15 @@ class Agent { this.logger.info(`Waiting for network data before reconciling every 120s`) const disputableAllocations = join({ - currentEpoch, + currentEpochNumber, activeDeployments, }).tryMap( - ({ currentEpoch, activeDeployments }) => - this.network.disputableAllocations(currentEpoch, activeDeployments, 0), + ({ currentEpochNumber, activeDeployments }) => + this.network.disputableAllocations( + currentEpochNumber, + activeDeployments, + 0, + ), { onError: () => this.logger.warn( @@ -406,7 +408,7 @@ class Agent { ticker: timer(240_000), paused: this.network.transactionManager.paused, isOperator: this.network.transactionManager.isOperator, - currentEpoch, + currentEpochNumber, currentEpochStartBlock, maxAllocationEpochs, activeDeployments, @@ -416,12 +418,12 @@ class Agent { recentlyClosedAllocations, claimableAllocations, disputableAllocations, - protocolChainLatestValidEpoch, + networkLatestEpoch, }).pipe( async ({ paused, isOperator, - currentEpoch, + currentEpochNumber, currentEpochStartBlock, maxAllocationEpochs, activeDeployments, @@ -431,17 +433,17 @@ class Agent { recentlyClosedAllocations, claimableAllocations, disputableAllocations, - protocolChainLatestValidEpoch, + networkLatestEpoch, }) => { this.logger.info(`Reconcile with the network`, { - protocolChainLatestValidEpoch, + networkLatestEpoch, }) - if (protocolChainLatestValidEpoch.epochNumber != currentEpoch) { + if (networkLatestEpoch.epochNumber != currentEpochNumber) { this.logger.warn( `EBO latest valid epoch differs from the network contract, ping updates to the EBO (After this is stable, can replace currentEpoch)`, { - currentEpoch, + currentEpochNumber, currentEpochStartBlock, }, ) @@ -486,7 +488,7 @@ class Agent { try { const disputableEpoch = - currentEpoch - this.network.indexerConfigs.poiDisputableEpochs + currentEpochNumber - this.network.indexerConfigs.poiDisputableEpochs // Find disputable allocations await this.identifyPotentialDisputes( disputableAllocations, @@ -507,7 +509,7 @@ class Agent { await this.reconcileActions( networkDeploymentAllocationDecisions, activeAllocations, - currentEpoch, + currentEpochNumber, currentEpochStartBlock, maxAllocationEpochs, ) diff --git a/packages/indexer-agent/src/commands/start.ts b/packages/indexer-agent/src/commands/start.ts index 06f55c680..244d99edb 100644 --- a/packages/indexer-agent/src/commands/start.ts +++ b/packages/indexer-agent/src/commands/start.ts @@ -724,11 +724,7 @@ export default { }) const epochSubgraph = argv.epochSubgraphEndpoint - ? await EpochSubgraph.create({ - logger, - endpoint: argv.epochSubgraphEndpoint, - network: networkMeta.name, - }) + ? await EpochSubgraph.create(argv.epochSubgraphEndpoint) : undefined logger.info('Connect to network') @@ -770,10 +766,10 @@ export default { await receiptCollector.queuePendingReceiptsFromDatabase() const networkMonitor = new NetworkMonitor( - CAIPIds[networkMeta.name], + CAIPIds[argv.ethereumNetwork], contracts, toAddress(indexerAddress), - logger, + logger.child({ component: 'NetworkMonitor' }), indexingStatusResolver, networkSubgraph, ethereumProvider, diff --git a/packages/indexer-common/src/allocations/types.ts b/packages/indexer-common/src/allocations/types.ts index b48376631..186d97eef 100644 --- a/packages/indexer-common/src/allocations/types.ts +++ b/packages/indexer-common/src/allocations/types.ts @@ -1,14 +1,6 @@ -import { Address, SubgraphDeploymentID, toAddress } from '@graphprotocol/common-ts' +import { Address } from '@graphprotocol/common-ts' import { BigNumber } from 'ethers' - -export interface SubgraphDeployment { - id: SubgraphDeploymentID - deniedAt: number - stakedTokens: BigNumber - signalledTokens: BigNumber - queryFeesAmount: BigNumber - activeAllocations: number -} +import { SubgraphDeployment } from '@graphprotocol/indexer-common' export interface Allocation { id: Address @@ -34,163 +26,3 @@ export enum AllocationStatus { FINALIZED = 'Finalized', CLAIMED = 'Claimed', } - -export interface CreateAllocationResult { - actionID: number - type: 'allocate' - transactionID: string | undefined - allocation: string - deployment: string - allocatedTokens: string -} - -export interface CloseAllocationResult { - actionID: number - type: 'unallocate' - transactionID: string | undefined - allocation: string - allocatedTokens: string - indexingRewards: string - receiptsWorthCollecting: boolean -} - -export interface ReallocateAllocationResult { - actionID: number - type: 'reallocate' - transactionID: string | undefined - closedAllocation: string - indexingRewardsCollected: string - receiptsWorthCollecting: boolean - createdAllocation: string - createdAllocationStake: string -} - -export interface ActionFailure { - actionID: number - transactionID?: string - failureReason: string -} - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export const isActionFailure = (variableToCheck: any): variableToCheck is ActionFailure => - 'failureReason' in variableToCheck - -export type AllocationResult = - | CreateAllocationResult - | CloseAllocationResult - | ReallocateAllocationResult - | ActionFailure - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export const parseGraphQLSubgraphDeployment = ( - subgraphDeployment: any, -): SubgraphDeployment => ({ - id: new SubgraphDeploymentID(subgraphDeployment.id), - deniedAt: subgraphDeployment.deniedAt, - stakedTokens: BigNumber.from(subgraphDeployment.stakedTokens), - signalledTokens: BigNumber.from(subgraphDeployment.signalledTokens), - queryFeesAmount: BigNumber.from(subgraphDeployment.queryFeesAmount), - activeAllocations: subgraphDeployment.indexerAllocations.length, -}) - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export const parseGraphQLAllocation = (allocation: any): Allocation => ({ - // Ensure the allocation ID (an address) is checksummed - id: toAddress(allocation.id), - status: allocation.status, - subgraphDeployment: { - id: new SubgraphDeploymentID(allocation.subgraphDeployment.id), - deniedAt: allocation.subgraphDeployment.deniedAt, - stakedTokens: BigNumber.from(allocation.subgraphDeployment.stakedTokens), - signalledTokens: BigNumber.from(allocation.subgraphDeployment.signalledTokens), - queryFeesAmount: BigNumber.from(allocation.subgraphDeployment.queryFeesAmount), - activeAllocations: allocation.subgraphDeployment.indexerAllocations - ? allocation.subgraphDeployment.indexerAllocations.length - : 0, - }, - indexer: toAddress(allocation.indexer.id), - allocatedTokens: BigNumber.from(allocation.allocatedTokens), - createdAtBlockHash: allocation.createdAtBlockHash, - createdAtEpoch: allocation.createdAtEpoch, - closedAtEpoch: allocation.closedAtEpoch, - closedAtEpochStartBlockHash: undefined, - previousEpochStartBlockHash: undefined, - closedAtBlockHash: allocation.closedAtBlockHash, - poi: allocation.poi, - queryFeeRebates: allocation.queryFeeRebates, - queryFeesCollected: allocation.queryFeesCollected, -}) - -export interface RewardsPool { - subgraphDeployment: SubgraphDeploymentID - allocationIndexer: Address - allocationCreatedAtBlockHash: string - closedAtEpoch: number - closedAtEpochStartBlockHash: string | undefined - closedAtEpochStartBlockNumber: number | undefined - previousEpochStartBlockHash: string | undefined - previousEpochStartBlockNumber: number | undefined - referencePOI: string | undefined - referencePreviousPOI: string | undefined -} - -export const allocationRewardsPool = (allocation: Allocation): RewardsPool => ({ - subgraphDeployment: allocation.subgraphDeployment.id, - allocationIndexer: allocation.indexer, - allocationCreatedAtBlockHash: allocation.createdAtBlockHash, - closedAtEpoch: allocation.closedAtEpoch, - closedAtEpochStartBlockHash: allocation.closedAtEpochStartBlockHash, - closedAtEpochStartBlockNumber: undefined, - previousEpochStartBlockHash: allocation.previousEpochStartBlockHash, - previousEpochStartBlockNumber: undefined, - referencePOI: undefined, - referencePreviousPOI: undefined, -}) - -export interface Epoch { - id: number - startBlock: number - startBlockHash: string | undefined - endBlock: number - signalledTokens: number - stakeDeposited: number - queryFeeRebates: number - totalRewards: number - totalIndexerRewards: number - totalDelegatorRewards: number -} - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export const parseGraphQLEpochs = (epoch: any): Epoch => ({ - id: epoch.id, - startBlock: epoch.startBlock, - startBlockHash: undefined, - endBlock: epoch.endBlock, - signalledTokens: epoch.signalledTokens, - stakeDeposited: epoch.stakeDeposited, - queryFeeRebates: epoch.queryFeeRebates, - totalRewards: epoch.totalRewards, - totalIndexerRewards: epoch.totalIndexerRewards, - totalDelegatorRewards: epoch.totalDelegatorRewards, -}) - -export interface NetworkEpochBlock { - network: string - epochNumber: number - startBlockNumber: number - startBlockHash: string -} - -export const CAIPIds: { [key: string]: string } = { - mainnet: 'eip155:1', - goerli: 'eip155:5', - gnosis: 'eip155:100', -} - -export const alias = (identifier: string): string => { - try { - return Object.keys(CAIPIds).filter((name) => CAIPIds[name] == identifier)[0] - } catch (error) { - throw new Error(`Failed to match chain ids to a network alias`) - } -} diff --git a/packages/indexer-common/src/epoch-subgraph.ts b/packages/indexer-common/src/epoch-subgraph.ts index 0ed362b54..0f4339888 100644 --- a/packages/indexer-common/src/epoch-subgraph.ts +++ b/packages/indexer-common/src/epoch-subgraph.ts @@ -1,30 +1,14 @@ import axios, { AxiosInstance, AxiosResponse } from 'axios' -import { Logger } from '@graphprotocol/common-ts' import { DocumentNode, print } from 'graphql' import { CombinedError } from '@urql/core' import { QueryResult } from './network-subgraph' -export interface EpochSubgraphCreateOptions { - logger: Logger - endpoint: string - network: string -} - -interface EpochSubgraphOptions { - logger: Logger - endpoint: string - network: string -} export class EpochSubgraph { - logger: Logger - endpointClient: AxiosInstance - network: string + private constructor(private endpointClient: AxiosInstance) {} - private constructor(options: EpochSubgraphOptions) { - this.logger = options.logger - - this.endpointClient = axios.create({ - baseURL: options.endpoint, + public static async create(endpoint: string): Promise { + const endpointClient = axios.create({ + baseURL: endpoint, headers: { 'content-type': 'application/json' }, // Don't parse responses as JSON @@ -33,29 +17,8 @@ export class EpochSubgraph { // Don't transform responses transformResponse: (data) => data, }) - - this.network = options.network - } - - public static async create({ - logger: parentLogger, - endpoint, - network, - }: EpochSubgraphCreateOptions): Promise { - const logger = parentLogger.child({ - component: 'EpochSubgraph', - endpoint, - }) - // Create the Epoch subgraph instance - const epochSubgraph = new EpochSubgraph({ - logger, - endpoint, - network, - }) - // Any checks to be made after creating? - - return epochSubgraph + return new EpochSubgraph(endpointClient) } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/indexer-common/src/indexer-management/__tests__/resolvers/actions.ts b/packages/indexer-common/src/indexer-management/__tests__/resolvers/actions.ts index ee177dbea..a18ff98fc 100644 --- a/packages/indexer-common/src/indexer-management/__tests__/resolvers/actions.ts +++ b/packages/indexer-common/src/indexer-management/__tests__/resolvers/actions.ts @@ -293,12 +293,9 @@ const setup = async () => { voucherRedemptionMaxBatchSize: 100, }) - const epochSubgraph = await EpochSubgraph.create({ - logger, - endpoint: - 'https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-testnet', - network: 'goerli', - }) + const epochSubgraph = await EpochSubgraph.create( + 'https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-testnet', + ) const networkMonitor = new NetworkMonitor( CAIPIds['goerli'], diff --git a/packages/indexer-common/src/indexer-management/actions.ts b/packages/indexer-common/src/indexer-management/actions.ts index 3adf5fcce..462c5ca81 100644 --- a/packages/indexer-common/src/indexer-management/actions.ts +++ b/packages/indexer-common/src/indexer-management/actions.ts @@ -42,7 +42,7 @@ export class ActionManager { ).filter((a) => approvedDeploymentIDs.includes(a.subgraphDeployment.id.ipfsHash)) let affectedAllocationExpiring = false if (affectedAllocations.length) { - const currentEpoch = await this.networkMonitor.currentEpoch() + const currentEpoch = await this.networkMonitor.currentEpochNumber() const maxAllocationEpoch = await this.networkMonitor.maxAllocationEpoch() // affectedAllocations are ordered by creation time so use index 0 for oldest allocation to check expiration affectedAllocationExpiring = diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index da4379dbb..61e96914e 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -8,6 +8,7 @@ import { } from '@graphprotocol/common-ts' import { Action, + ActionFailure, ActionType, allocationIdProof, AllocationResult, @@ -15,8 +16,8 @@ import { CloseAllocationResult, CreateAllocationResult, fetchIndexingRules, - IndexerError, indexerError, + IndexerError, IndexerErrorCode, IndexerManagementModels, IndexingDecisionBasis, @@ -43,7 +44,6 @@ import { NetworkMonitor } from './monitor' import { SubgraphManager } from './subgraphs' import { BytesLike } from '@ethersproject/bytes' import pMap from 'p-map' -import { ActionFailure } from '../allocations/types' export interface AllocateTransactionParams { indexer: string @@ -132,7 +132,7 @@ export class AllocationManager { receipt: ContractReceipt | 'paused' | 'unauthorized', actions: Action[], ): Promise { - const results = pMap( + return pMap( actions, async (action) => { try { @@ -157,7 +157,6 @@ export class AllocationManager { }, { stopOnError: false }, ) - return results } findEvent( diff --git a/packages/indexer-common/src/indexer-management/client.ts b/packages/indexer-common/src/indexer-management/client.ts index 47addfabd..5e7b0c928 100644 --- a/packages/indexer-common/src/indexer-management/client.ts +++ b/packages/indexer-common/src/indexer-management/client.ts @@ -526,7 +526,7 @@ export const createIndexerManagementClient = async ( // TODO: AllocationManager construction inside ActionManager allocationManager = new AllocationManager( contracts, - logger, + logger.child({ component: 'AllocationManager' }), address, models, networkMonitor, @@ -537,7 +537,7 @@ export const createIndexerManagementClient = async ( actionManager = new ActionManager( allocationManager, networkMonitor, - logger, + logger.child({ component: 'ActionManager' }), models, allocationManagementMode, autoAllocationMinBatchSize, diff --git a/packages/indexer-common/src/indexer-management/index.ts b/packages/indexer-common/src/indexer-management/index.ts index ccd6adce4..dd2d8d55a 100644 --- a/packages/indexer-common/src/indexer-management/index.ts +++ b/packages/indexer-common/src/indexer-management/index.ts @@ -6,3 +6,4 @@ export * from './monitor' export * from './server' export * from './subgraphs' export * from './rules' +export * from './types' diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index fef9a564a..74e4bd9b9 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -14,7 +14,7 @@ import { SubgraphDeployment, SubgraphVersion, CAIPIds, - NetworkEpochBlock, + NetworkEpoch, EpochSubgraph, BlockPointer, alias, @@ -35,7 +35,7 @@ import { providers, utils, Wallet } from 'ethers' // The new read only Network class export class NetworkMonitor { constructor( - public networkAlias: string, + public networkCAIPID: string, private contracts: NetworkContracts, private indexer: Address, private logger: Logger, @@ -45,9 +45,10 @@ export class NetworkMonitor { private epochSubgraph?: EpochSubgraph, ) {} - async currentEpoch(): Promise { + async currentEpochNumber(): Promise { return (await this.contracts.epochManager.currentEpoch()).toNumber() } + async maxAllocationEpoch(): Promise { return await this.contracts.staking.maxAllocationEpochs() } @@ -556,38 +557,39 @@ export class NetworkMonitor { return deployments } - async epochManagerCurrentStartBlock(network: string): Promise { - const epochNumber = await this.currentEpoch() + async networkCurrentEpoch(): Promise { + const epochNumber = await this.currentEpochNumber() const startBlockNumber = ( await this.contracts.epochManager.currentEpochBlock() ).toNumber() const startBlockHash = (await this.ethereum.getBlock(startBlockNumber)).hash return { - network: alias(network), + networkID: this.networkCAIPID, epochNumber, startBlockNumber, startBlockHash, } } - async latestValidEpoch(network: string): Promise { + async currentEpoch(networkID: string): Promise { + const networkAlias = alias(networkID) if (!this.epochSubgraph) { - if (network == this.networkAlias) { - return await this.epochManagerCurrentStartBlock(network) + if (networkID == this.networkCAIPID) { + return await this.networkCurrentEpoch() } this.logger.error(`Epoch start block not available for the network`, { - networkName: alias(network), + networkName: networkAlias, }) throw indexerError( IndexerErrorCode.IE071, - `Epoch start block not available for network: ${alias(network)}`, + `Epoch start block not available for network: ${networkAlias}`, ) } try { const result = await this.epochSubgraph.query( gql` - query network($network: String!) { - network(id: $network) { + query network($networkID: String!) { + network(id: $networkID) { latestValidBlockNumber { network { id @@ -606,7 +608,7 @@ export class NetworkMonitor { } `, { - network, + networkID, }, ) @@ -615,22 +617,24 @@ export class NetworkMonitor { } if (!result.data.network || !result.data.network.latestValidBlockNumber) { - throw new Error(`Failed to query EBO for ${network}'s latest valid epoch number`) + throw new Error( + `Failed to query EBO for ${networkAlias}'s latest valid epoch number`, + ) } // Check for validity with epoch manager currentEpoch, and fetch block hash const validBlock = result.data.network.latestValidBlockNumber.epochNumber == - (await this.currentEpoch()) + (await this.currentEpochNumber()) ? result.data.network.latestValidBlockNumber : result.data.network.latestValidBlockNumber.previousBlockNumber const startBlockHash = await this.indexingStatusResolver.blockHashFromNumber( - alias(network), + networkAlias, validBlock.startBlockNumber, ) return { - network, + networkID, epochNumber: +validBlock.epochNumber, startBlockNumber: +validBlock.blockNumber, startBlockHash, @@ -642,7 +646,7 @@ export class NetworkMonitor { this.logger.error(`Failed to query latest epoch number`, { err, msg: err.message, - networkName: alias(network), + networkName: networkAlias, }) throw indexerError(IndexerErrorCode.IE069, err) } @@ -651,10 +655,14 @@ export class NetworkMonitor { async fetchPOIBlockPointer(allocation: Allocation): Promise { try { - const indexingStatuses = await this.indexingStatusResolver.indexingStatus([ - allocation.subgraphDeployment.id, - ]) - if (indexingStatuses.length != 1 || indexingStatuses[0].chains.length != 1) { + const deploymentIndexingStatuses = await this.indexingStatusResolver.indexingStatus( + [allocation.subgraphDeployment.id], + ) + if ( + deploymentIndexingStatuses.length != 1 || + deploymentIndexingStatuses[0].chains.length != 1 || + !deploymentIndexingStatuses[0].chains[0].network + ) { this.logger.error( `Failed to query indexing status for ${allocation.subgraphDeployment.id.ipfsHash}`, ) @@ -663,18 +671,19 @@ export class NetworkMonitor { `Failed to query indexing status for ${allocation.subgraphDeployment.id.ipfsHash}`, ) } - const networkID = indexingStatuses[0].chains[0].network - const epoch = await this.latestValidEpoch(CAIPIds[networkID]) + const deploymentNetworkAlias = deploymentIndexingStatuses[0].chains[0].network + const deploymentNetworkCAIPID = CAIPIds[deploymentNetworkAlias] + const currentEpoch = await this.currentEpoch(deploymentNetworkCAIPID) this.logger.trace(`Fetched block pointer to use in resolving POI`, { deployment: allocation.subgraphDeployment.id.ipfsHash, - networkID, - number: epoch.startBlockNumber, - hash: epoch.startBlockHash, + deploymentNetworkAlias, + currentEpochStartBlockNumber: currentEpoch.startBlockNumber, + currentEpochStartBlockHash: currentEpoch.startBlockHash, }) return { - number: epoch.startBlockNumber, - hash: epoch.startBlockHash, + number: currentEpoch.startBlockNumber, + hash: currentEpoch.startBlockHash, } } catch (error) { this.logger.error(`Failed to fetch block for resolving allocation POI`, { diff --git a/packages/indexer-common/src/indexer-management/types.ts b/packages/indexer-common/src/indexer-management/types.ts new file mode 100644 index 000000000..01582b147 --- /dev/null +++ b/packages/indexer-common/src/indexer-management/types.ts @@ -0,0 +1,164 @@ +import { Address, SubgraphDeploymentID, toAddress } from '@graphprotocol/common-ts' +import { BigNumber } from 'ethers' +import { Allocation } from '../allocations' +import { SubgraphDeployment } from '../types' + +export interface CreateAllocationResult { + actionID: number + type: 'allocate' + transactionID: string | undefined + allocation: string + deployment: string + allocatedTokens: string +} + +export interface CloseAllocationResult { + actionID: number + type: 'unallocate' + transactionID: string | undefined + allocation: string + allocatedTokens: string + indexingRewards: string + receiptsWorthCollecting: boolean +} + +export interface ReallocateAllocationResult { + actionID: number + type: 'reallocate' + transactionID: string | undefined + closedAllocation: string + indexingRewardsCollected: string + receiptsWorthCollecting: boolean + createdAllocation: string + createdAllocationStake: string +} + +export interface ActionFailure { + actionID: number + transactionID?: string + failureReason: string +} + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export const isActionFailure = (variableToCheck: any): variableToCheck is ActionFailure => + 'failureReason' in variableToCheck + +export type AllocationResult = + | CreateAllocationResult + | CloseAllocationResult + | ReallocateAllocationResult + | ActionFailure + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export const parseGraphQLSubgraphDeployment = ( + subgraphDeployment: any, +): SubgraphDeployment => ({ + id: new SubgraphDeploymentID(subgraphDeployment.id), + deniedAt: subgraphDeployment.deniedAt, + stakedTokens: BigNumber.from(subgraphDeployment.stakedTokens), + signalledTokens: BigNumber.from(subgraphDeployment.signalledTokens), + queryFeesAmount: BigNumber.from(subgraphDeployment.queryFeesAmount), + activeAllocations: subgraphDeployment.indexerAllocations.length, +}) + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export const parseGraphQLAllocation = (allocation: any): Allocation => ({ + // Ensure the allocation ID (an address) is checksummed + id: toAddress(allocation.id), + status: allocation.status, + subgraphDeployment: { + id: new SubgraphDeploymentID(allocation.subgraphDeployment.id), + deniedAt: allocation.subgraphDeployment.deniedAt, + stakedTokens: BigNumber.from(allocation.subgraphDeployment.stakedTokens), + signalledTokens: BigNumber.from(allocation.subgraphDeployment.signalledTokens), + queryFeesAmount: BigNumber.from(allocation.subgraphDeployment.queryFeesAmount), + activeAllocations: allocation.subgraphDeployment.indexerAllocations + ? allocation.subgraphDeployment.indexerAllocations.length + : 0, + }, + indexer: toAddress(allocation.indexer.id), + allocatedTokens: BigNumber.from(allocation.allocatedTokens), + createdAtBlockHash: allocation.createdAtBlockHash, + createdAtEpoch: allocation.createdAtEpoch, + closedAtEpoch: allocation.closedAtEpoch, + closedAtEpochStartBlockHash: undefined, + previousEpochStartBlockHash: undefined, + closedAtBlockHash: allocation.closedAtBlockHash, + poi: allocation.poi, + queryFeeRebates: allocation.queryFeeRebates, + queryFeesCollected: allocation.queryFeesCollected, +}) + +export interface RewardsPool { + subgraphDeployment: SubgraphDeploymentID + allocationIndexer: Address + allocationCreatedAtBlockHash: string + closedAtEpoch: number + closedAtEpochStartBlockHash: string | undefined + closedAtEpochStartBlockNumber: number | undefined + previousEpochStartBlockHash: string | undefined + previousEpochStartBlockNumber: number | undefined + referencePOI: string | undefined + referencePreviousPOI: string | undefined +} + +export const allocationRewardsPool = (allocation: Allocation): RewardsPool => ({ + subgraphDeployment: allocation.subgraphDeployment.id, + allocationIndexer: allocation.indexer, + allocationCreatedAtBlockHash: allocation.createdAtBlockHash, + closedAtEpoch: allocation.closedAtEpoch, + closedAtEpochStartBlockHash: allocation.closedAtEpochStartBlockHash, + closedAtEpochStartBlockNumber: undefined, + previousEpochStartBlockHash: allocation.previousEpochStartBlockHash, + previousEpochStartBlockNumber: undefined, + referencePOI: undefined, + referencePreviousPOI: undefined, +}) + +export interface Epoch { + id: number + startBlock: number + startBlockHash: string | undefined + endBlock: number + signalledTokens: number + stakeDeposited: number + queryFeeRebates: number + totalRewards: number + totalIndexerRewards: number + totalDelegatorRewards: number +} + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export const parseGraphQLEpochs = (epoch: any): Epoch => ({ + id: epoch.id, + startBlock: epoch.startBlock, + startBlockHash: undefined, + endBlock: epoch.endBlock, + signalledTokens: epoch.signalledTokens, + stakeDeposited: epoch.stakeDeposited, + queryFeeRebates: epoch.queryFeeRebates, + totalRewards: epoch.totalRewards, + totalIndexerRewards: epoch.totalIndexerRewards, + totalDelegatorRewards: epoch.totalDelegatorRewards, +}) + +export interface NetworkEpoch { + networkID: string + epochNumber: number + startBlockNumber: number + startBlockHash: string +} + +export const CAIPIds: { [key: string]: string } = { + mainnet: 'eip155:1', + goerli: 'eip155:5', + gnosis: 'eip155:100', +} + +export const alias = (identifier: string): string => { + try { + return Object.keys(CAIPIds).filter((name) => CAIPIds[name] == identifier)[0] + } catch (error) { + throw new Error(`Failed to match chain ids to a network alias`) + } +} diff --git a/packages/indexer-common/src/indexing-status.ts b/packages/indexer-common/src/indexing-status.ts index 8c6fd9242..9e7cb54ce 100644 --- a/packages/indexer-common/src/indexing-status.ts +++ b/packages/indexer-common/src/indexing-status.ts @@ -195,6 +195,7 @@ export class IndexingStatusResolver { network: string, blockNumber: number, ): Promise { + this.logger.trace(`Querying blockHashFromNumber`, { network, blockNumber }) try { return await pRetry( async (attempt) => { diff --git a/packages/indexer-common/src/subgraphs.ts b/packages/indexer-common/src/subgraphs.ts index 1257b785a..3cf2524d4 100644 --- a/packages/indexer-common/src/subgraphs.ts +++ b/packages/indexer-common/src/subgraphs.ts @@ -1,7 +1,7 @@ import { base58 } from 'ethers/lib/utils' import { BigNumber, utils } from 'ethers' import { Logger, SubgraphDeploymentID } from '@graphprotocol/common-ts' -import { SubgraphDeployment } from './allocations' +import { SubgraphDeployment } from './types' import { INDEXING_RULE_GLOBAL, IndexingDecisionBasis, diff --git a/packages/indexer-common/src/types.ts b/packages/indexer-common/src/types.ts index f7aa8c765..f6694b9df 100644 --- a/packages/indexer-common/src/types.ts +++ b/packages/indexer-common/src/types.ts @@ -52,6 +52,15 @@ export interface Subgraph { versions: SubgraphVersion[] } +export interface SubgraphDeployment { + id: SubgraphDeploymentID + deniedAt: number + stakedTokens: BigNumber + signalledTokens: BigNumber + queryFeesAmount: BigNumber + activeAllocations: number +} + export enum TransactionType { ZERO, TWO,