From c49ebe805320a12fbce919f86e88f90b6c4dedcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 16 May 2025 15:11:04 -0300 Subject: [PATCH 01/28] feat: upgrade to ethers v6, bump common-ts and use toolshed for contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- package.json | 8 +- packages/indexer-agent/jest.config.js | 1 + packages/indexer-agent/package.json | 10 +- .../indexer-agent/src/__tests__/indexer.ts | 3 +- packages/indexer-agent/src/agent.ts | 41 +- packages/indexer-agent/src/commands/start.ts | 3 +- .../db/migrations/14-cost-models-history.ts | 4 +- packages/indexer-cli/jest.config.js | 1 + packages/indexer-cli/package.json | 6 +- packages/indexer-cli/src/actions.ts | 6 +- packages/indexer-cli/src/allocations.ts | 37 +- packages/indexer-cli/src/command-helpers.ts | 8 +- .../commands/indexer/allocations/create.ts | 3 +- .../src/commands/indexer/allocations/get.ts | 4 +- .../indexer/allocations/reallocate.ts | 3 +- packages/indexer-cli/src/rules.ts | 39 +- packages/indexer-common/jest.config.js | 2 +- packages/indexer-common/package.json | 10 +- .../indexer-common/src/__tests__/ipfs.test.ts | 6 +- .../__tests__/tap-pagination.test.ts | 8 +- .../src/allocations/__tests__/tap.test.ts | 6 +- .../indexer-common/src/allocations/keys.ts | 23 +- .../src/allocations/query-fees.ts | 34 +- .../src/allocations/tap-collector.ts | 40 +- .../indexer-common/src/allocations/types.ts | 7 +- .../__tests__/allocations.test.ts | 12 +- .../__tests__/helpers.test.ts | 32 +- .../src/indexer-management/allocations.ts | 172 +- .../src/indexer-management/client.ts | 3 +- .../indexer-management/models/cost-model.ts | 4 +- .../indexer-management/models/poi-dispute.ts | 16 +- .../src/indexer-management/monitor.ts | 58 +- .../resolvers/allocations.ts | 101 +- .../resolvers/indexer-status.ts | 6 +- .../src/indexer-management/types.ts | 15 +- .../src/network-specification.ts | 13 +- packages/indexer-common/src/network.ts | 135 +- packages/indexer-common/src/operator.ts | 10 +- .../indexer-common/src/parsers/test-utils.ts | 2 +- packages/indexer-common/src/subgraphs.ts | 25 +- packages/indexer-common/src/transactions.ts | 171 +- packages/indexer-common/src/types.ts | 20 +- packages/indexer-common/src/utils.ts | 15 +- yarn.lock | 4671 +++++++++-------- 44 files changed, 3133 insertions(+), 2661 deletions(-) diff --git a/package.json b/package.json index 4db1da91b..3d54f2fad 100644 --- a/package.json +++ b/package.json @@ -23,20 +23,16 @@ "lerna": "6.1.0" }, "resolutions": { - "ethers": "5.7.0", + "ethers": "6.13.7", "sequelize": "6.33.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/providers": "5.7.0", "@urql/core": "3.1.0", "@urql/exchange-execute": "2.1.0", "punycode": "2.3.1", "uri-js": "4.2.2" }, "overrides": { - "ethers": "5.7.0", + "ethers": "6.13.7", "sequelize": "6.33.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/providers": "5.7.0", "@urql/core": "3.1.0", "@urql/exchange-execute": "2.1.0", "graphql": "16.8.0" diff --git a/packages/indexer-agent/jest.config.js b/packages/indexer-agent/jest.config.js index a48b3273c..1530aea77 100644 --- a/packages/indexer-agent/jest.config.js +++ b/packages/indexer-agent/jest.config.js @@ -11,6 +11,7 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', testPathIgnorePatterns: ['/node_modules/', '/dist/', '.yalc'], + transformIgnorePatterns: ['!node_modules/'], globals: { __DATABASE__: { host: diff --git a/packages/indexer-agent/package.json b/packages/indexer-agent/package.json index e29502a83..506a08a9f 100644 --- a/packages/indexer-agent/package.json +++ b/packages/indexer-agent/package.json @@ -29,13 +29,13 @@ "graph-indexer-agent": "bin/graph-indexer-agent" }, "dependencies": { - "@graphprotocol/common-ts": "2.0.11", + "@graphprotocol/common-ts": "3.0.1", "@graphprotocol/indexer-common": "^0.23.5", "@thi.ng/heaps": "^1.3.1", "axios": "0.26.1", "bs58": "5.0.0", "delay": "^5.0.0", - "ethers": "5.7.0", + "ethers": "6.13.7", "evt": "1.9.12", "global": "4.4.0", "graphql": "16.8.0", @@ -80,10 +80,8 @@ "typescript": "5.2.2" }, "resolutions": { - "ethers": "5.7.0", - "sequelize": "6.33.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/providers": "5.7.0" + "ethers": "6.13.7", + "sequelize": "6.33.0" }, "gitHead": "972ab96774007b2aee15b1da169d2ff4be9f9d27" } diff --git a/packages/indexer-agent/src/__tests__/indexer.ts b/packages/indexer-agent/src/__tests__/indexer.ts index 69b3789bf..7ddfb0175 100644 --- a/packages/indexer-agent/src/__tests__/indexer.ts +++ b/packages/indexer-agent/src/__tests__/indexer.ts @@ -21,7 +21,6 @@ import { MultiNetworks, loadTestYamlConfig, } from '@graphprotocol/indexer-common' -import { BigNumber } from 'ethers' import { Sequelize } from 'sequelize' const TEST_DISPUTE_1: POIDisputeAttributes = { @@ -69,7 +68,7 @@ const TEST_DISPUTE_2: POIDisputeAttributes = { const POI_DISPUTES_CONVERTERS_FROM_GRAPHQL: Record< keyof POIDisputeAttributes, - (x: never) => string | BigNumber | number | undefined + (x: never) => string | bigint | number | undefined > = { allocationID: x => x, subgraphDeploymentID: x => x, diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index 82e14c57e..519653d73 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -47,7 +47,7 @@ import mapValues from 'lodash.mapvalues' import zip from 'lodash.zip' import { AgentConfigs, NetworkAndOperator } from './types' -type ActionReconciliationContext = [AllocationDecision[], number, number] +type ActionReconciliationContext = [AllocationDecision[], number, bigint] const deploymentInList = ( list: SubgraphDeploymentID[], @@ -270,7 +270,7 @@ export class Agent { }, ) - const maxAllocationEpochs: Eventual> = + const maxAllocationEpochs: Eventual> = sequentialTimerMap( { logger, milliseconds: requestIntervalLarge }, () => @@ -278,7 +278,7 @@ export class Agent { logger.trace('Fetching max allocation epochs', { protocolNetwork: network.specification.networkIdentifier, }) - return network.contracts.staking.maxAllocationEpochs() + return network.contracts.LegacyStaking.maxAllocationEpochs() }), { onError: error => @@ -304,9 +304,9 @@ export class Agent { await network.networkMonitor.subgraphs(subgraphRuleIds) if (subgraphsMatchingRules.length >= 1) { const epochLength = - await network.contracts.epochManager.epochLength() + await network.contracts.EpochManager.epochLength() const blockPeriod = 15 - const bufferPeriod = epochLength.toNumber() * blockPeriod * 100 // 100 epochs + const bufferPeriod = Number(epochLength) * blockPeriod * 100 // 100 epochs rules = convertSubgraphBasedRulesToDeploymentBased( rules, subgraphsMatchingRules, @@ -486,7 +486,7 @@ export class Agent { const matchingTransfer = eligibleTransferDeployments.find( deployment => deployment.ipfsHash == decision.deployment.ipfsHash && - deployment.startedTransferToL2At.toNumber() > oneWeekAgo, + Number(deployment.startedTransferToL2At) > oneWeekAgo, ) if (matchingTransfer) { logger.debug('Found a matching subgraph transfer', { @@ -682,7 +682,8 @@ export class Agent { currentEpochNumber: number, ) => currentEpochNumber - - network.specification.indexerOptions.poiDisputableEpochs, + (network.specification.indexerOptions + .poiDisputableEpochs as number), ) // Find disputable allocations @@ -821,22 +822,22 @@ export class Agent { await network.networkProvider.getBlock( pool.previousEpochStartBlockHash!, ) - pool.closedAtEpochStartBlockNumber = closedAtEpochStartBlock.number + pool.closedAtEpochStartBlockNumber = closedAtEpochStartBlock!.number pool.referencePOI = await this.graphNode.proofOfIndexing( pool.subgraphDeployment, { - number: closedAtEpochStartBlock.number, - hash: closedAtEpochStartBlock.hash, + number: closedAtEpochStartBlock!.number, + hash: closedAtEpochStartBlock!.hash!, }, pool.allocationIndexer, ) - pool.previousEpochStartBlockHash = previousEpochStartBlock.hash - pool.previousEpochStartBlockNumber = previousEpochStartBlock.number + pool.previousEpochStartBlockHash = previousEpochStartBlock!.hash! + pool.previousEpochStartBlockNumber = previousEpochStartBlock!.number pool.referencePreviousPOI = await this.graphNode.proofOfIndexing( pool.subgraphDeployment, { - number: previousEpochStartBlock.number, - hash: previousEpochStartBlock.hash, + number: previousEpochStartBlock!.number, + hash: previousEpochStartBlock!.hash!, }, pool.allocationIndexer, ) @@ -1006,13 +1007,13 @@ export class Agent { activeAllocations: Allocation[], deploymentAllocationDecision: AllocationDecision, epoch: number, - maxAllocationEpochs: number, + maxAllocationEpochs: bigint, network: Network, ): Promise { const desiredAllocationLifetime = deploymentAllocationDecision.ruleMatch .rule?.allocationLifetime ? deploymentAllocationDecision.ruleMatch.rule.allocationLifetime - : Math.max(1, maxAllocationEpochs - 1) + : Math.max(1, Number(maxAllocationEpochs) - 1) // Identify expiring allocations let expiredAllocations = activeAllocations.filter( @@ -1028,8 +1029,8 @@ export class Agent { async (allocation: Allocation) => { try { const onChainAllocation = - await network.contracts.staking.getAllocation(allocation.id) - return onChainAllocation.closedAtEpoch.eq('0') + await network.contracts.LegacyStaking.getAllocation(allocation.id) + return onChainAllocation.closedAtEpoch == 0n } catch (err) { this.logger.warn( `Failed to cross-check allocation state with contracts; assuming it needs to be closed`, @@ -1050,7 +1051,7 @@ export class Agent { deploymentAllocationDecision: AllocationDecision, activeAllocations: Allocation[], epoch: number, - maxAllocationEpochs: number, + maxAllocationEpochs: bigint, network: Network, operator: Operator, ): Promise { @@ -1145,7 +1146,7 @@ export class Agent { async reconcileActions( networkDeploymentAllocationDecisions: NetworkMapped, epoch: NetworkMapped, - maxAllocationEpochs: NetworkMapped, + maxAllocationEpochs: NetworkMapped, ): Promise { // -------------------------------------------------------------------------------- // Filter out networks set to `manual` allocation management mode, and ensure the diff --git a/packages/indexer-agent/src/commands/start.ts b/packages/indexer-agent/src/commands/start.ts index bf688485f..9d62af24e 100644 --- a/packages/indexer-agent/src/commands/start.ts +++ b/packages/indexer-agent/src/commands/start.ts @@ -31,7 +31,6 @@ import { createSyncingServer } from '../syncing-server' import { injectCommonStartupOptions } from './common-options' import pMap from 'p-map' import { NetworkSpecification } from '@graphprotocol/indexer-common/dist/network-specification' -import { BigNumber } from 'ethers' import { displayZodParsingError } from '@graphprotocol/indexer-common' import { readFileSync } from 'fs' import { AgentConfigs } from '../types' @@ -601,7 +600,7 @@ export async function run( defaults: { globalIndexingRule: { // TODO: Update this, there will be defaults per network - allocationAmount: BigNumber.from(100), + allocationAmount: BigInt(100), parallelAllocations: 1, }, }, diff --git a/packages/indexer-agent/src/db/migrations/14-cost-models-history.ts b/packages/indexer-agent/src/db/migrations/14-cost-models-history.ts index dab5cc23f..90bb5e7a0 100644 --- a/packages/indexer-agent/src/db/migrations/14-cost-models-history.ts +++ b/packages/indexer-agent/src/db/migrations/14-cost-models-history.ts @@ -1,5 +1,5 @@ import { Logger } from '@graphprotocol/common-ts' -import { utils } from 'ethers' +import { isHexString } from 'ethers' import { QueryInterface, DataTypes } from 'sequelize' interface MigrationContext { @@ -45,7 +45,7 @@ export async function up({ context }: Context): Promise { throw new Error('Deployment ID must be a string') } // "0x..." and "global" is ok - if (utils.isHexString(value, 32) || value === COST_MODEL_GLOBAL) { + if (isHexString(value, 32) || value === COST_MODEL_GLOBAL) { return } diff --git a/packages/indexer-cli/jest.config.js b/packages/indexer-cli/jest.config.js index 0eeafcaef..d20b4b76f 100644 --- a/packages/indexer-cli/jest.config.js +++ b/packages/indexer-cli/jest.config.js @@ -13,6 +13,7 @@ module.exports = { // The glob patterns Jest uses to detect test files testMatch: ['**/?(*.)+(spec|test).ts?(x)'], testPathIgnorePatterns: ['/node_modules/', '/dist/', '.yalc'], + transformIgnorePatterns: ['!node_modules/'], testTimeout: 60000, globals: { __DATABASE__: { diff --git a/packages/indexer-cli/package.json b/packages/indexer-cli/package.json index fb6a0d3e9..000821e00 100644 --- a/packages/indexer-cli/package.json +++ b/packages/indexer-cli/package.json @@ -26,14 +26,14 @@ "test:watch": "jest --watch --detectOpenHandles --verbose" }, "dependencies": { - "@graphprotocol/common-ts": "2.0.11", + "@graphprotocol/common-ts": "3.0.1", "@graphprotocol/indexer-common": "^0.23.5", "@iarna/toml": "2.2.5", "@thi.ng/iterators": "5.1.74", "@urql/core": "3.1.0", "chalk": "4.1.2", "env-paths": "2.2.1", - "ethers": "5.7.0", + "ethers": "6.13.7", "gluegun": "4.7.0", "graphql-tag": "2.12.6", "isomorphic-fetch": "3.0.0", @@ -53,7 +53,7 @@ "typescript": "5.2.2" }, "resolutions": { - "ethers": "5.7.0", + "ethers": "6.13.7", "sequelize": "6.33.0" }, "gitHead": "972ab96774007b2aee15b1da169d2ff4be9f9d27" diff --git a/packages/indexer-cli/src/actions.ts b/packages/indexer-cli/src/actions.ts index f7ccab61c..fbf3f501a 100644 --- a/packages/indexer-cli/src/actions.ts +++ b/packages/indexer-cli/src/actions.ts @@ -14,7 +14,7 @@ import { } from '@graphprotocol/indexer-common' import { validatePOI, validateRequiredParams } from './command-helpers' import gql from 'graphql-tag' -import { utils } from 'ethers' +import { hexlify } from 'ethers' import { parseGRT } from '@graphprotocol/common-ts' export interface GenericActionInputParams { @@ -51,7 +51,7 @@ export async function buildActionInput( case ActionType.UNALLOCATE: { let poi = actionParams.param2 if (poi == '0' || poi == '0x0') { - poi = utils.hexlify(Array(32).fill(0)) + poi = hexlify(new Uint8Array(32).fill(0)) } return { deploymentID: actionParams.targetDeployment, @@ -69,7 +69,7 @@ export async function buildActionInput( case ActionType.REALLOCATE: { let poi = actionParams.param3 if (poi == '0' || poi == '0x0') { - poi = utils.hexlify(Array(32).fill(0)) + poi = hexlify(new Uint8Array(32).fill(0)) } return { deploymentID: actionParams.targetDeployment, diff --git a/packages/indexer-cli/src/allocations.ts b/packages/indexer-cli/src/allocations.ts index 16cd86fdd..879fb653b 100644 --- a/packages/indexer-cli/src/allocations.ts +++ b/packages/indexer-cli/src/allocations.ts @@ -1,8 +1,7 @@ -import { SubgraphDeploymentID, formatGRT } from '@graphprotocol/common-ts' +import { SubgraphDeploymentID, formatGRT, commify } from '@graphprotocol/common-ts' import yaml from 'yaml' import { GluegunPrint } from 'gluegun' import { table, getBorderCharacters } from 'table' -import { BigNumber, utils } from 'ethers' import { OutputFormat, parseOutputFormat, pickFields } from './command-helpers' import { IndexerManagementClient } from '@graphprotocol/indexer-common' import gql from 'graphql-tag' @@ -17,17 +16,17 @@ export interface IndexerAllocation { id: number indexer: string subgraphDeployment: string - allocatedTokens: BigNumber - signalledTokens: BigNumber - stakedTokens: BigNumber + allocatedTokens: bigint + signalledTokens: bigint + stakedTokens: bigint createdAtEpoch: number closedAtEpoch: number | null ageInEpochs: number closeDeadlineEpoch: number closeDeadlineBlocksRemaining: number closeDeadlineTimeRemaining: number - indexingRewards: BigNumber - queryFeesCollected: BigNumber + indexingRewards: bigint + queryFeesCollected: bigint status: string protocolNetwork: string } @@ -41,17 +40,17 @@ const ALLOCATION_CONVERTERS_FROM_GRAPHQL: Record< indexer: x => x, subgraphDeployment: (d: SubgraphDeploymentID) => typeof d === 'string' ? d : d.ipfsHash, - allocatedTokens: nullPassThrough((x: string) => BigNumber.from(x)), - signalledTokens: nullPassThrough((x: string) => BigNumber.from(x)), - stakedTokens: nullPassThrough((x: string) => BigNumber.from(x)), + allocatedTokens: nullPassThrough((x: string) => BigInt(x)), + signalledTokens: nullPassThrough((x: string) => BigInt(x)), + stakedTokens: nullPassThrough((x: string) => BigInt(x)), createdAtEpoch: nullPassThrough((x: string) => parseInt(x)), closedAtEpoch: nullPassThrough((x: string) => parseInt(x)), ageInEpochs: nullPassThrough((x: string) => parseInt(x)), closeDeadlineEpoch: nullPassThrough((x: string) => parseInt(x)), closeDeadlineBlocksRemaining: nullPassThrough((x: string) => parseInt(x)), closeDeadlineTimeRemaining: nullPassThrough((x: string) => parseInt(x)), - indexingRewards: nullPassThrough((x: string) => BigNumber.from(x)), - queryFeesCollected: nullPassThrough((x: string) => BigNumber.from(x)), + indexingRewards: nullPassThrough((x: string) => BigInt(x)), + queryFeesCollected: nullPassThrough((x: string) => BigInt(x)), status: x => x, protocolNetwork: x => x, } @@ -64,17 +63,17 @@ const ALLOCATION_FORMATTERS: Record< indexer: nullPassThrough(x => x), subgraphDeployment: (d: SubgraphDeploymentID) => typeof d === 'string' ? d : d.ipfsHash, - allocatedTokens: x => utils.commify(formatGRT(x)), - signalledTokens: x => utils.commify(formatGRT(x)), - stakedTokens: x => utils.commify(formatGRT(x)), + allocatedTokens: x => commify(formatGRT(x)), + signalledTokens: x => commify(formatGRT(x)), + stakedTokens: x => commify(formatGRT(x)), createdAtEpoch: x => x, closedAtEpoch: x => x, ageInEpochs: x => x, closeDeadlineEpoch: x => x, closeDeadlineBlocksRemaining: x => x, closeDeadlineTimeRemaining: x => x, - indexingRewards: x => utils.commify(formatGRT(x)), - queryFeesCollected: x => utils.commify(formatGRT(x)), + indexingRewards: x => commify(formatGRT(x)), + queryFeesCollected: x => commify(formatGRT(x)), status: x => x, protocolNetwork: resolveChainAlias, } @@ -173,7 +172,7 @@ function nullPassThrough(fn: (x: T) => U): (x: T | null) => U | null { export const createAllocation = async ( client: IndexerManagementClient, deployment: string, - amount: BigNumber, + amount: bigint, indexNode: string | undefined, protocolNetwork: string, ): Promise => { @@ -265,7 +264,7 @@ export const reallocateAllocation = async ( client: IndexerManagementClient, allocationID: string, poi: string | undefined, - amount: BigNumber, + amount: bigint, force: boolean, protocolNetwork: string, ): Promise => { diff --git a/packages/indexer-cli/src/command-helpers.ts b/packages/indexer-cli/src/command-helpers.ts index 2d8b1aef8..99d74a649 100644 --- a/packages/indexer-cli/src/command-helpers.ts +++ b/packages/indexer-cli/src/command-helpers.ts @@ -35,8 +35,8 @@ export enum OutputFormat { } import yaml from 'yaml' import { GluegunParameters, GluegunPrint } from 'gluegun' -import { utils } from 'ethers' import { validateNetworkIdentifier } from '@graphprotocol/indexer-common' +import { hexlify, isHexString } from 'ethers' export const fixParameters = ( parameters: GluegunParameters, @@ -159,13 +159,13 @@ export async function validateRequiredParams( export function validatePOI(poi: string | undefined): string | undefined { if (poi !== undefined) { if (typeof poi == 'number' && poi == 0) { - poi = utils.hexlify(Array(32).fill(0)) + poi = hexlify(new Uint8Array(32).fill(0)) } if (typeof poi == 'string' && poi == '0') { - poi = utils.hexlify(Array(32).fill(0)) + poi = hexlify(new Uint8Array(32).fill(0)) } // Ensure user provided POI is formatted properly - '0x...' (32 bytes) - const isHex = utils.isHexString(poi, 32) + const isHex = isHexString(poi, 32) if (!isHex) { throw new Error( `Invalid POI provided ('${poi}'): Must be a 32 byte length hex string`, diff --git a/packages/indexer-cli/src/commands/indexer/allocations/create.ts b/packages/indexer-cli/src/commands/indexer/allocations/create.ts index 6986bfbe2..28244a408 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/create.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/create.ts @@ -3,7 +3,6 @@ import chalk from 'chalk' import { loadValidatedConfig } from '../../../config' import { createIndexerManagementClient } from '../../../client' -import { BigNumber } from 'ethers' import { createAllocation } from '../../../allocations' import { processIdentifier, @@ -78,7 +77,7 @@ module.exports = { `Invalid 'deploymentID' provided (${deploymentID}), must be bytes32 or base58 formatted)`, ) } - const allocationAmount = BigNumber.from(amount) + const allocationAmount = BigInt(amount) const config = loadValidatedConfig() const client = await createIndexerManagementClient({ url: config.api }) diff --git a/packages/indexer-cli/src/commands/indexer/allocations/get.ts b/packages/indexer-cli/src/commands/indexer/allocations/get.ts index 2ab707567..f5708e9b0 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/get.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/get.ts @@ -8,7 +8,7 @@ import gql from 'graphql-tag' import { SubgraphDeploymentID } from '@graphprotocol/common-ts' import { processIdentifier, SubgraphIdentifierType } from '@graphprotocol/indexer-common' import { IndexerAllocation, printIndexerAllocations } from '../../../allocations' -import { utils } from 'ethers' +import { isHexString } from 'ethers' const HELP = ` ${chalk.bold('graph indexer allocations get')} [options] @@ -59,7 +59,7 @@ module.exports = { } if (allocation) { - if (allocation !== 'all' && !utils.isHexString(allocation, 20)) { + if (allocation !== 'all' && !isHexString(allocation, 20)) { throw Error( `Invalid 'allocation-id' provided ('${allocation}'), must be a bytes20 string or 'all'`, ) diff --git a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts index 08abaccc2..d42b9a320 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts @@ -3,7 +3,6 @@ import chalk from 'chalk' import { loadValidatedConfig } from '../../../config' import { createIndexerManagementClient } from '../../../client' -import { BigNumber } from 'ethers' import { reallocateAllocation } from '../../../allocations' import { printObjectOrArray, validatePOI } from '../../../command-helpers' @@ -73,7 +72,7 @@ module.exports = { try { validatePOI(poi) - const allocationAmount = BigNumber.from(amount) + const allocationAmount = BigInt(amount) const config = loadValidatedConfig() const client = await createIndexerManagementClient({ url: config.api }) diff --git a/packages/indexer-cli/src/rules.ts b/packages/indexer-cli/src/rules.ts index e50027849..e37fc9da3 100644 --- a/packages/indexer-cli/src/rules.ts +++ b/packages/indexer-cli/src/rules.ts @@ -1,4 +1,9 @@ -import { SubgraphDeploymentID, parseGRT, formatGRT } from '@graphprotocol/common-ts' +import { + SubgraphDeploymentID, + parseGRT, + formatGRT, + commify, +} from '@graphprotocol/common-ts' import { nullPassThrough, parseBoolean, @@ -12,7 +17,7 @@ import { import gql from 'graphql-tag' import yaml from 'yaml' import { table, getBorderCharacters } from 'table' -import { BigNumber, utils } from 'ethers' + import { OutputFormat, pickFields } from './command-helpers' import chalk from 'chalk' @@ -47,15 +52,15 @@ const INDEXING_RULE_FORMATTERS: Record< //deployment: (d: SubgraphDeploymentIDIsh) => (typeof d === 'string' ? d : d.ipfsHash), identifier: x => x, identifierType: x => x, - allocationAmount: nullPassThrough(x => utils.commify(formatGRT(x))), + allocationAmount: nullPassThrough(x => commify(formatGRT(x))), allocationLifetime: nullPassThrough((x: number) => x.toString()), autoRenewal: x => x, parallelAllocations: nullPassThrough((x: number) => x.toString()), - maxSignal: nullPassThrough(x => utils.commify(formatGRT(x))), - minSignal: nullPassThrough(x => utils.commify(formatGRT(x))), - minStake: nullPassThrough(x => utils.commify(formatGRT(x))), + maxSignal: nullPassThrough(x => commify(formatGRT(x))), + minSignal: nullPassThrough(x => commify(formatGRT(x))), + minStake: nullPassThrough(x => commify(formatGRT(x))), maxAllocationPercentage: nullPassThrough((x: number) => x.toPrecision(2)), - minAverageQueryFees: nullPassThrough(x => utils.commify(formatGRT(x))), + minAverageQueryFees: nullPassThrough(x => commify(formatGRT(x))), decisionBasis: x => x, custom: nullPassThrough(JSON.stringify), requireSupported: x => x, @@ -71,15 +76,15 @@ const INDEXING_RULE_CONVERTERS_FROM_GRAPHQL: Record< id: x => x, identifier: x => x, identifierType: x => x, - allocationAmount: nullPassThrough((x: string) => BigNumber.from(x)), + allocationAmount: nullPassThrough((x: string) => BigInt(x)), allocationLifetime: nullPassThrough((x: string) => parseInt(x)), autoRenewal: x => x, parallelAllocations: nullPassThrough((x: string) => parseInt(x)), - minSignal: nullPassThrough((x: string) => BigNumber.from(x)), - maxSignal: nullPassThrough((x: string) => BigNumber.from(x)), - minStake: nullPassThrough((x: string) => BigNumber.from(x)), + minSignal: nullPassThrough((x: string) => BigInt(x)), + maxSignal: nullPassThrough((x: string) => BigInt(x)), + minStake: nullPassThrough((x: string) => BigInt(x)), maxAllocationPercentage: nullPassThrough((x: string) => parseFloat(x)), - minAverageQueryFees: nullPassThrough((x: string) => BigNumber.from(x)), + minAverageQueryFees: nullPassThrough((x: string) => BigInt(x)), decisionBasis: x => x, custom: nullPassThrough(JSON.stringify), requireSupported: x => x, @@ -95,15 +100,15 @@ const INDEXING_RULE_CONVERTERS_TO_GRAPHQL: Record< id: x => x, identifier: x => x, identifierType: x => x, - allocationAmount: nullPassThrough((x: BigNumber) => x.toString()), + allocationAmount: nullPassThrough((x: bigint) => x.toString()), allocationLifetime: nullPassThrough((x: number) => x), autoRenewal: x => x, parallelAllocations: nullPassThrough((x: number) => x), - minSignal: nullPassThrough((x: BigNumber) => x.toString()), - maxSignal: nullPassThrough((x: BigNumber) => x.toString()), - minStake: nullPassThrough((x: BigNumber) => x.toString()), + minSignal: nullPassThrough((x: bigint) => x.toString()), + maxSignal: nullPassThrough((x: bigint) => x.toString()), + minStake: nullPassThrough((x: bigint) => x.toString()), maxAllocationPercentage: nullPassThrough((x: number) => x), - minAverageQueryFees: nullPassThrough((x: BigNumber) => x.toString()), + minAverageQueryFees: nullPassThrough((x: bigint) => x.toString()), decisionBasis: x => x, custom: nullPassThrough(JSON.stringify), requireSupported: x => x, diff --git a/packages/indexer-common/jest.config.js b/packages/indexer-common/jest.config.js index bca010358..26ebe5fde 100644 --- a/packages/indexer-common/jest.config.js +++ b/packages/indexer-common/jest.config.js @@ -6,7 +6,7 @@ const bail = (s) => { process.env.NODE_NO_WARNINGS = '1' module.exports = { - collectCoverage: true, + collectCoverage: false, preset: 'ts-jest', forceExit: true, testEnvironment: 'node', diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index 7f43d61bd..d68c34fbb 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -23,8 +23,9 @@ }, "dependencies": { "@pinax/graph-networks-registry": "0.6.7", - "@graphprotocol/common-ts": "2.0.11", - "@semiotic-labs/tap-contracts-bindings": "^1.2.1", + "@graphprotocol/common-ts": "3.0.1", + "@graphprotocol/toolshed": "0.3.2", + "@semiotic-labs/tap-contracts-bindings": "2.0.0", "@thi.ng/heaps": "1.2.38", "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.intersection": "^4.4.7", @@ -35,7 +36,7 @@ "axios": "1.6.2", "body-parser": "1.20.2", "cors": "2.8.5", - "ethers": "5.7.0", + "ethers": "6.13.7", "evt": "1.10.1", "express": "4.18.2", "fastify": "3.25.0", @@ -82,9 +83,8 @@ "typescript": "5.2.2" }, "resolutions": { - "ethers": "5.7.0", + "ethers": "6.13.7", "sequelize": "6.33.0", - "@ethersproject/bignumber": "5.7.0", "@urql/exchange-execute/@urql/core": "3.1.0" }, "babel": { diff --git a/packages/indexer-common/src/__tests__/ipfs.test.ts b/packages/indexer-common/src/__tests__/ipfs.test.ts index 8e94fe8cc..7432a7cb6 100644 --- a/packages/indexer-common/src/__tests__/ipfs.test.ts +++ b/packages/indexer-common/src/__tests__/ipfs.test.ts @@ -2,15 +2,15 @@ import { createLogger, SubgraphDeploymentID } from '@graphprotocol/common-ts' import { SubgraphDependencies, SubgraphManifestResolver } from '../graph-node' import express, { Request, Response } from 'express' import { AddressInfo } from 'net' -import { utils } from 'ethers' +import { keccak256, toUtf8Bytes } from 'ethers' const EXAMPLE_VALID_IPFS_HASH = 'Qmd9nZKCH8UZU1pBzk7G8ECJr3jX3a2vAf3vowuTwFvrQg' const EXAMPLE_NON_MANIFEST_VALID_IPFS_HASH = 'QmddQDkcHHM7mGvYrrnoGnQ1q9GdHQfbTvj2mfbyz2Q49K' function mockManifestHash(input: string): string { - const utf8Bytes = utils.toUtf8Bytes(input) - const hash = utils.keccak256(utf8Bytes) // Generate a keccak256 hash of the input + const utf8Bytes = toUtf8Bytes(input) + const hash = keccak256(utf8Bytes) // Generate a keccak256 hash of the input return new SubgraphDeploymentID(hash).ipfsHash } diff --git a/packages/indexer-common/src/allocations/__tests__/tap-pagination.test.ts b/packages/indexer-common/src/allocations/__tests__/tap-pagination.test.ts index cbddb3fc5..ea2f387f1 100644 --- a/packages/indexer-common/src/allocations/__tests__/tap-pagination.test.ts +++ b/packages/indexer-common/src/allocations/__tests__/tap-pagination.test.ts @@ -10,10 +10,10 @@ import { TapTransaction, TransactionManager, } from '@graphprotocol/indexer-common' -import { NetworkContracts as TapContracts } from '@semiotic-labs/tap-contracts-bindings' import { NetworkSpecification } from 'indexer-common/src/network-specification' import { createMockAllocation } from '../../indexer-management/__tests__/helpers.test' -import { getContractAddress } from 'ethers/lib/utils' +import { getCreateAddress } from 'ethers' +import { NetworkContracts as TapContracts } from '@semiotic-labs/tap-contracts-bindings' const timeout = 30_000 @@ -29,7 +29,7 @@ for (let i = 0; i < 2999; i++) { const mockAllocation = createMockAllocation() allocations.push({ ...mockAllocation, - id: getContractAddress({ from, nonce: i }) as Address, + id: getCreateAddress({ from, nonce: i }) as Address, }) } @@ -191,7 +191,7 @@ describe.skip('TAP Pagination', () => { const mockAllocation = createMockAllocation() allocations.push({ ...mockAllocation, - id: getContractAddress({ from, nonce: 3000 }) as Address, + id: getCreateAddress({ from, nonce: 3000 }) as Address, }) { const allocations = await tapCollector['getAllocationsfromAllocationIds']([]) diff --git a/packages/indexer-common/src/allocations/__tests__/tap.test.ts b/packages/indexer-common/src/allocations/__tests__/tap.test.ts index d85e50c8f..b13ecace6 100644 --- a/packages/indexer-common/src/allocations/__tests__/tap.test.ts +++ b/packages/indexer-common/src/allocations/__tests__/tap.test.ts @@ -19,7 +19,7 @@ import { } from '@graphprotocol/common-ts' import { testNetworkSpecification } from '../../indexer-management/__tests__/util' import { Op, Sequelize } from 'sequelize' -import { utils } from 'ethers' +import { hexlify, verifyTypedData } from 'ethers' // Make global Jest variables available // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -482,7 +482,7 @@ describe('TAP', () => { const [first] = await queryFeeModels.receiptAggregateVouchers.findAll() const signedRav = first.getSignedRAV() - const signerAddress = utils.verifyTypedData( + const signerAddress = verifyTypedData( domain, { ReceiptAggregateVoucher: [ @@ -492,7 +492,7 @@ describe('TAP', () => { ], }, signedRav.rav, - signedRav.signature, + hexlify(signedRav.signature), ) expect(signerAddress).toEqual('0x886574712d0ca20C36FD090A594Df7eCa17cd38e') diff --git a/packages/indexer-common/src/allocations/keys.ts b/packages/indexer-common/src/allocations/keys.ts index 0f7aaaddf..b7b3b8d39 100644 --- a/packages/indexer-common/src/allocations/keys.ts +++ b/packages/indexer-common/src/allocations/keys.ts @@ -1,9 +1,9 @@ -import { Wallet, utils, Signer } from 'ethers' +import { Wallet, Signer, HDNodeWallet, solidityPackedKeccak256, getBytes } from 'ethers' import { Address, SubgraphDeploymentID, toAddress } from '@graphprotocol/common-ts' import { Allocation } from './types' const deriveKeyPair = ( - hdNode: utils.HDNode, + hdNode: HDNodeWallet, epoch: number, deployment: SubgraphDeploymentID, index: number, @@ -19,10 +19,10 @@ const deriveKeyPair = ( // Returns the private key of allocation signer export const allocationSignerPrivateKey = ( - wallet: Wallet, + wallet: HDNodeWallet, allocation: Allocation, ): string => { - const hdNode = utils.HDNode.fromMnemonic(wallet.mnemonic.phrase) + const hdNode = HDNodeWallet.fromPhrase(wallet.mnemonic!.phrase) // The allocation was either created at the epoch it intended to or one // epoch later. So try both both. @@ -43,7 +43,10 @@ export const allocationSignerPrivateKey = ( } // Returns allocation signer wallet -export const allocationSigner = (wallet: Wallet, allocation: Allocation): Signer => { +export const allocationSigner = ( + wallet: HDNodeWallet, + allocation: Allocation, +): Signer => { return new Wallet(allocationSignerPrivateKey(wallet, allocation)) } @@ -66,7 +69,7 @@ export const uniqueAllocationID = ( existingIDs: Address[], ): { allocationSigner: Signer; allocationId: Address } => { for (let i = 0; i < 100; i++) { - const hdNode = utils.HDNode.fromMnemonic(indexerMnemonic) + const hdNode = HDNodeWallet.fromPhrase(indexerMnemonic) const keyPair = deriveKeyPair(hdNode, epoch, deployment, i) if (!existingIDs.includes(keyPair.address)) { return { @@ -84,11 +87,11 @@ export const allocationIdProof = ( indexerAddress: string, allocationId: string, ): Promise => { - const messageHash = utils.solidityKeccak256( + const messageHash = solidityPackedKeccak256( ['address', 'address'], [indexerAddress, allocationId], ) - const messageHashBytes = utils.arrayify(messageHash) + const messageHashBytes = getBytes(messageHash) return signer.signMessage(messageHashBytes) } @@ -99,10 +102,10 @@ export const tapAllocationIdProof = ( allocationId: Address, escrowContract: Address, ): Promise => { - const messageHash = utils.solidityKeccak256( + const messageHash = solidityPackedKeccak256( ['uint256', 'address', 'address', 'address'], [chainId, sender, allocationId, escrowContract], ) - const messageHashBytes = utils.arrayify(messageHash) + const messageHashBytes = getBytes(messageHash) return signer.signMessage(messageHashBytes) } diff --git a/packages/indexer-common/src/allocations/query-fees.ts b/packages/indexer-common/src/allocations/query-fees.ts index a6565620a..69c62486e 100644 --- a/packages/indexer-common/src/allocations/query-fees.ts +++ b/packages/indexer-common/src/allocations/query-fees.ts @@ -23,7 +23,7 @@ import { SubgraphClient, } from '..' import { DHeap } from '@thi.ng/heaps' -import { BigNumber, BigNumberish, Contract } from 'ethers' +import { BigNumberish, Contract } from 'ethers' import { Op } from 'sequelize' import pReduce from 'p-reduce' @@ -90,8 +90,8 @@ export class AllocationReceiptCollector implements ReceiptCollector { declare partialVoucherEndpoint: URL declare voucherEndpoint: URL declare receiptsToCollect: DHeap - declare voucherRedemptionThreshold: BigNumber - declare voucherRedemptionBatchThreshold: BigNumber + declare voucherRedemptionThreshold: bigint + declare voucherRedemptionBatchThreshold: bigint declare voucherRedemptionMaxBatchSize: number declare protocolNetwork: string declare networkSubgraph: SubgraphClient @@ -317,7 +317,7 @@ export class AllocationReceiptCollector implements ReceiptCollector { } return results } - if (BigNumber.from(voucher.amount).lt(this.voucherRedemptionThreshold)) { + if (BigInt(voucher.amount) < this.voucherRedemptionThreshold) { results.belowThreshold.push(voucher) } else { results.eligible.push(voucher) @@ -330,8 +330,8 @@ export class AllocationReceiptCollector implements ReceiptCollector { if (vouchers.belowThreshold.length > 0) { const totalValueGRT = formatGRT( vouchers.belowThreshold.reduce( - (total, voucher) => total.add(BigNumber.from(voucher.amount)), - BigNumber.from(0), + (total, voucher) => total + BigInt(voucher.amount), + 0n, ), ) logger.info(`Query vouchers below the redemption threshold`, { @@ -349,11 +349,11 @@ export class AllocationReceiptCollector implements ReceiptCollector { // Already ordered by value const voucherBatch = vouchers.eligible.slice(0, this.voucherRedemptionMaxBatchSize), batchValueGRT = voucherBatch.reduce( - (total, voucher) => total.add(BigNumber.from(voucher.amount)), - BigNumber.from(0), + (total, voucher) => total + BigInt(voucher.amount), + 0n, ) - if (batchValueGRT.gt(this.voucherRedemptionBatchThreshold)) { + if (batchValueGRT > this.voucherRedemptionBatchThreshold) { this.metrics.vouchersBatchRedeemSize.set(voucherBatch.length) logger.info(`Query voucher batch is ready for redemption`, { batchSize: voucherBatch.length, @@ -392,7 +392,7 @@ export class AllocationReceiptCollector implements ReceiptCollector { encodedReceipts.writeHex(receipts[0].allocation) for (const receipt of receipts) { // [fee, id, signature] - const fee = BigNumber.from(receipt.fees).toHexString() + const fee = '0x' + BigInt(receipt.fees).toString(16) const feePadding = 33 - fee.length / 2 encodedReceipts.writeZeroes(feePadding) encodedReceipts.writeHex(fee) @@ -521,9 +521,9 @@ export class AllocationReceiptCollector implements ReceiptCollector { transaction, this.protocolNetwork, ) - summary.collectedFees = BigNumber.from(summary.collectedFees) - .add(voucher.fees) - .toString() + summary.collectedFees = ( + BigInt(summary.collectedFees) + BigInt(voucher.fees) + ).toString() await summary.save({ transaction }) // Add the voucher to the database @@ -577,7 +577,7 @@ export class AllocationReceiptCollector implements ReceiptCollector { try { // Submit the voucher on chain const txReceipt = await this.transactionManager.executeTransaction( - () => this.allocationExchange.estimateGas.redeemMany(onchainVouchers), + () => this.allocationExchange.redeemMany.estimateGas(onchainVouchers), async (gasLimit: BigNumberish) => this.allocationExchange.redeemMany(onchainVouchers, { gasLimit, @@ -600,9 +600,9 @@ export class AllocationReceiptCollector implements ReceiptCollector { transaction, this.protocolNetwork, ) - summary.withdrawnFees = BigNumber.from(summary.withdrawnFees) - .add(voucher.amount) - .toString() + summary.withdrawnFees = ( + BigInt(summary.withdrawnFees) + BigInt(voucher.amount) + ).toString() await summary.save({ transaction }) } }, diff --git a/packages/indexer-common/src/allocations/tap-collector.ts b/packages/indexer-common/src/allocations/tap-collector.ts index 9431fff84..f7ab896a9 100644 --- a/packages/indexer-common/src/allocations/tap-collector.ts +++ b/packages/indexer-common/src/allocations/tap-collector.ts @@ -23,7 +23,6 @@ import { parseGraphQLAllocation, sequentialTimerMap, } from '..' -import { BigNumber } from 'ethers' import pReduce from 'p-reduce' import { SubgraphClient, QueryResult } from '../subgraph-client' import gql from 'graphql-tag' @@ -104,7 +103,7 @@ export class TapCollector { declare transactionManager: TransactionManager declare tapContracts: TapContracts declare allocations: Eventual - declare ravRedemptionThreshold: BigNumber + declare ravRedemptionThreshold: bigint declare protocolNetwork: string declare tapSubgraph: SubgraphClient declare networkSubgraph: SubgraphClient @@ -156,9 +155,8 @@ export class TapCollector { const logger = this.logger.child({ function: 'startRAVProcessing()' }) const totalValueGRT = formatGRT( signedRavs.belowThreshold.reduce( - (total, signedRav) => - total.add(BigNumber.from(signedRav.rav.rav.valueAggregate)), - BigNumber.from(0), + (total, signedRav) => total + BigInt(signedRav.rav.rav.valueAggregate), + 0n, ), ) logger.info(`Query RAVs below the redemption threshold`, { @@ -208,7 +206,7 @@ export class TapCollector { return { rav: signedRav, allocation: allocations.find( - (a) => a.id === toAddress(signedRav.rav.allocationId), + (a) => a.id === toAddress(signedRav.rav.allocationId.toString()), ), sender: rav.senderAddress, } @@ -223,7 +221,7 @@ export class TapCollector { ravs: ReceiptAggregateVoucher[], ): Promise { const allocationIds: string[] = ravs.map((rav) => - rav.getSignedRAV().rav.allocationId.toLowerCase(), + rav.getSignedRAV().rav.allocationId.toString().toLowerCase(), ) let block: { hash: string } | undefined = undefined @@ -309,9 +307,7 @@ export class TapCollector { return await pReduce( pendingRAVs, async (results, rav) => { - if ( - BigNumber.from(rav.rav.rav.valueAggregate).lt(this.ravRedemptionThreshold) - ) { + if (BigInt(rav.rav.rav.valueAggregate) < this.ravRedemptionThreshold) { results.belowThreshold.push(rav) } else { results.eligible.push(rav) @@ -582,7 +578,7 @@ export class TapCollector { } const stopTimer = this.metrics.ravsRedeemDuration.startTimer({ - allocation: rav.allocationId, + allocation: rav.allocationId.toString(), }) try { await this.redeemRav(logger, allocation, sender, signedRav) @@ -590,7 +586,7 @@ export class TapCollector { // THIS IS A MUT OPERATION escrowAccounts.subtractSenderBalance(sender, ravValue) } catch (err) { - this.metrics.ravRedeemsFailed.inc({ allocation: rav.allocationId }) + this.metrics.ravRedeemsFailed.inc({ allocation: rav.allocationId.toString() }) logger.error(`Failed to redeem RAV`, { err: indexerError(IndexerErrorCode.IE055, err), }) @@ -607,13 +603,13 @@ export class TapCollector { const { rav } = signedRav const [summary] = await ensureAllocationSummary( this.models, - toAddress(rav.allocationId), + toAddress(rav.allocationId.toString()), transaction, this.protocolNetwork, ) - summary.withdrawnFees = BigNumber.from(summary.withdrawnFees) - .add(rav.valueAggregate) - .toString() + summary.withdrawnFees = ( + BigInt(summary.withdrawnFees) + BigInt(rav.valueAggregate) + ).toString() await summary.save({ transaction }) } }, @@ -645,8 +641,8 @@ export class TapCollector { allocationSigner(this.transactionManager.wallet, allocation), parseInt(this.protocolNetwork.split(':')[1]), sender, - toAddress(rav.allocationId), - toAddress(escrow.escrow.address), + toAddress(rav.allocationId.toString()), + toAddress(escrow.escrow.target.toString()), ) this.logger.debug(`Computed allocationIdProof`, { allocationId: rav.allocationId, @@ -654,7 +650,7 @@ export class TapCollector { }) // Submit the signed RAV on chain const txReceipt = await this.transactionManager.executeTransaction( - () => escrow.escrow.estimateGas.redeem(signedRav, proof), + () => escrow.escrow.redeem.estimateGas(signedRav, proof), (gasLimit) => escrow.escrow.redeem(signedRav, proof, { gasLimit, @@ -664,17 +660,17 @@ export class TapCollector { // get tx receipt and post process if (txReceipt === 'paused' || txReceipt === 'unauthorized') { - this.metrics.ravRedeemsInvalid.inc({ allocation: rav.allocationId }) + this.metrics.ravRedeemsInvalid.inc({ allocation: rav.allocationId.toString() }) return } this.metrics.ravCollectedFees.set( - { allocation: rav.allocationId }, + { allocation: rav.allocationId.toString() }, parseFloat(rav.valueAggregate.toString()), ) try { - await this.markRavAsRedeemed(toAddress(rav.allocationId), sender) + await this.markRavAsRedeemed(toAddress(rav.allocationId.toString()), sender) logger.info( `Updated receipt aggregate vouchers table with redeemed_at for allocation ${rav.allocationId} and sender ${sender}`, ) diff --git a/packages/indexer-common/src/allocations/types.ts b/packages/indexer-common/src/allocations/types.ts index b31c6c71f..a18ba241b 100644 --- a/packages/indexer-common/src/allocations/types.ts +++ b/packages/indexer-common/src/allocations/types.ts @@ -1,4 +1,3 @@ -import { BigNumber } from 'ethers' import { SubgraphClient, SubgraphDeployment } from '@graphprotocol/indexer-common' import { Logger, Address } from '@graphprotocol/common-ts' @@ -8,7 +7,7 @@ export interface Allocation { status: AllocationStatus subgraphDeployment: SubgraphDeployment indexer: Address - allocatedTokens: BigNumber + allocatedTokens: bigint createdAtEpoch: number createdAtBlockHash: string closedAtEpoch: number @@ -16,8 +15,8 @@ export interface Allocation { previousEpochStartBlockHash: string | undefined closedAtBlockHash: string poi: string | undefined - queryFeeRebates: BigNumber | undefined - queryFeesCollected: BigNumber | undefined + queryFeeRebates: bigint | undefined + queryFeesCollected: bigint | undefined } export enum AllocationStatus { diff --git a/packages/indexer-common/src/indexer-management/__tests__/allocations.test.ts b/packages/indexer-common/src/indexer-management/__tests__/allocations.test.ts index eafd14665..8b2f53191 100644 --- a/packages/indexer-common/src/indexer-management/__tests__/allocations.test.ts +++ b/packages/indexer-common/src/indexer-management/__tests__/allocations.test.ts @@ -141,23 +141,23 @@ describe.skip('Allocation Manager', () => { // Allocate test action expect(allocate.action.type).toBe(ActionType.ALLOCATE) expect(allocate.allocates).toStrictEqual(parseGRT('10000')) - expect(allocate.rewards.isZero()).toBeTruthy() - expect(allocate.unallocates.isZero()).toBeTruthy() + expect(allocate.rewards).toBe(0n) + expect(allocate.unallocates).toBe(0n) expect(allocate.balance).toStrictEqual(parseGRT('10000')) // Unallocate test action expect(unallocate.action.type).toBe(ActionType.UNALLOCATE) - expect(unallocate.allocates.isZero()).toBeTruthy() - expect(unallocate.rewards.isZero()).toBeFalsy() + expect(unallocate.allocates).toBe(0n) + expect(unallocate.rewards).toBe(0n) expect(unallocate.unallocates).toStrictEqual(parseGRT('10000')) expect(unallocate.balance).toStrictEqual( - unallocate.allocates.sub(unallocate.unallocates).sub(unallocate.rewards), + unallocate.allocates - unallocate.unallocates - unallocate.rewards, ) // This Reallocate test Action intentionally uses a null or zeroed POI, so it should not accrue rewards. expect(reallocate.action.type).toBe(ActionType.REALLOCATE) expect(reallocate.allocates).toStrictEqual(parseGRT('10000')) - expect(reallocate.rewards.isZero()).toBeTruthy() + expect(reallocate.rewards).toBe(0n) expect(reallocate.unallocates).toStrictEqual(parseGRT('10000')) expect(reallocate.balance).toStrictEqual(parseGRT('0')) }) diff --git a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts index 58f21dd43..acf018c87 100644 --- a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts +++ b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts @@ -1,9 +1,7 @@ import { - connectContracts, connectDatabase, createLogger, Logger, - NetworkContracts, SubgraphDeploymentID, toAddress, } from '@graphprotocol/common-ts' @@ -34,7 +32,11 @@ import { getTestProvider, } from '@graphprotocol/indexer-common' import { mockLogger, mockProvider } from '../../__tests__/subgraph.test' -import { BigNumber, ethers, utils } from 'ethers' +import { hexlify, Provider } from 'ethers' +import { + connectGraphHorizon, + connectSubgraphService, +} from '@graphprotocol/toolshed/deployments' // Make global Jest variable available // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -44,8 +46,7 @@ declare const __LOG_LEVEL__: any let sequelize: Sequelize let models: IndexerManagementModels -let ethereum: ethers.providers.BaseProvider -let contracts: NetworkContracts +let ethereum: Provider let graphNode: GraphNode let networkSubgraph: SubgraphClient let epochSubgraph: SubgraphClient @@ -71,7 +72,12 @@ const setupMonitor = async () => { level: __LOG_LEVEL__ ?? 'error', }) ethereum = getTestProvider('sepolia') - contracts = await connectContracts(ethereum, 5, undefined) + const horizonContracts = connectGraphHorizon(5, ethereum) + const subgraphServiceContracts = connectSubgraphService(5, ethereum) + const contracts = { + ...horizonContracts, + ...subgraphServiceContracts, + } const subgraphFreshnessChecker = new SubgraphFreshnessChecker( 'Test Subgraph', @@ -130,16 +136,16 @@ export const createMockAllocation = (): Allocation => { const mockDeployment = { id: new SubgraphDeploymentID('QmcpeU4pZxzKB9TJ6fzH6PyZi9h8PJ6pG1c4izb9VAakJq'), deniedAt: 0, - stakedTokens: BigNumber.from(50000), - signalledTokens: BigNumber.from(100000), - queryFeesAmount: BigNumber.from(0), + stakedTokens: 50000n, + signalledTokens: 100000n, + queryFeesAmount: 0n, } as SubgraphDeployment const mockAllocation = { id: toAddress('0xbAd8935f75903A1eF5ea62199d98Fd7c3c1ab20C'), status: AllocationStatus.CLOSED, subgraphDeployment: mockDeployment, indexer: toAddress('0xc61127cdfb5380df4214b0200b9a07c7c49d34f9'), - allocatedTokens: BigNumber.from(1000), + allocatedTokens: 1000n, createdAtEpoch: 3, createdAtBlockHash: '0x675e9411241c431570d07b920321b2ff6aed2359aa8e26109905d34bffd8932a', @@ -339,7 +345,11 @@ describe.skip('Monitor: local', () => { test('Resolve POI using force=true', async () => { await expect( - networkMonitor.resolvePOI(mockAllocation, utils.hexlify(Array(32).fill(0)), true), + networkMonitor.resolvePOI( + mockAllocation, + hexlify(new Uint8Array(32).fill(0)), + true, + ), ).resolves.toEqual( '0x0000000000000000000000000000000000000000000000000000000000000000', ) diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index fcc614f07..cc52ac002 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -35,20 +35,19 @@ import { } from '@graphprotocol/indexer-common' import { - BigNumber, BigNumberish, - ContractReceipt, - PopulatedTransaction, - utils, + BytesLike, + hexlify, + TransactionReceipt, + TransactionRequest, } from 'ethers' -import { BytesLike } from '@ethersproject/bytes' import pMap from 'p-map' export interface TransactionPreparationContext { activeAllocations: Allocation[] recentlyClosedAllocations: Allocation[] - currentEpoch: BigNumber + currentEpoch: bigint indexingStatuses: IndexingStatus[] } @@ -80,19 +79,19 @@ export interface ReallocateTransactionParams { // An Action with resolved Allocation and Unallocation values export interface ActionStakeUsageSummary { action: Action - allocates: BigNumber - unallocates: BigNumber - rewards: BigNumber - balance: BigNumber + allocates: bigint + unallocates: bigint + rewards: bigint + balance: bigint } export type PopulateTransactionResult = - | PopulatedTransaction - | PopulatedTransaction[] + | TransactionRequest + | TransactionRequest[] | ActionFailure export type TransactionResult = - | ContractReceipt + | TransactionReceipt | 'paused' | 'unauthorized' | ActionFailure[] @@ -152,15 +151,15 @@ export class AllocationManager { const callData = populateTransactionsResults .flat() - .map((tx) => tx as PopulatedTransaction) - .filter((tx: PopulatedTransaction) => !!tx.data) + .map((tx) => tx as TransactionRequest) + .filter((tx: TransactionRequest) => !!tx.data) .map((tx) => tx.data as string) logger.trace('Prepared transaction calldata', { callData }) return await this.network.transactionManager.executeTransaction( - async () => this.network.contracts.staking.estimateGas.multicall(callData), + async () => this.network.contracts.HorizonStaking.multicall.estimateGas(callData), async (gasLimit) => - this.network.contracts.staking.multicall(callData, { gasLimit }), + this.network.contracts.HorizonStaking.multicall(callData, { gasLimit }), this.logger.child({ actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, function: 'staking.multicall', @@ -169,7 +168,7 @@ export class AllocationManager { } async confirmTransactions( - receipt: ContractReceipt | 'paused' | 'unauthorized', + receipt: TransactionReceipt | 'paused' | 'unauthorized', actions: Action[], ): Promise { const logger = this.logger.child({ @@ -186,7 +185,7 @@ export class AllocationManager { } catch (error) { let transaction: string | undefined = undefined if (typeof receipt == 'object') { - transaction = receipt.transactionHash ?? undefined + transaction = receipt.hash ?? undefined } this.logger.error('Failed to confirm batch transaction', { error, @@ -207,7 +206,7 @@ export class AllocationManager { } async confirmActionExecution( - receipt: ContractReceipt | 'paused' | 'unauthorized', + receipt: TransactionReceipt | 'paused' | 'unauthorized', action: Action, ): Promise { // Ensure we are handling an action for the same configured network @@ -247,14 +246,14 @@ export class AllocationManager { } async prepareTransactions(actions: Action[]): Promise { - const currentEpoch = await this.network.contracts.epochManager.currentEpoch() + const currentEpoch = await this.network.contracts.EpochManager.currentEpoch() const context: TransactionPreparationContext = { activeAllocations: await this.network.networkMonitor.allocations( AllocationStatus.ACTIVE, ), recentlyClosedAllocations: await this.network.networkMonitor.recentlyClosedAllocations( - currentEpoch.toNumber(), + Number(currentEpoch), 2, ), currentEpoch, @@ -354,7 +353,7 @@ export class AllocationManager { logger: Logger, context: TransactionPreparationContext, deployment: SubgraphDeploymentID, - amount: BigNumber, + amount: bigint, ): Promise { logger.info('Preparing to allocate', { deployment: deployment.ipfsHash, @@ -376,7 +375,7 @@ export class AllocationManager { ) } - if (amount.lt('0')) { + if (amount < 0n) { logger.warn('Cannot allocate a negative amount of GRT', { amount: amount.toString(), }) @@ -405,8 +404,8 @@ export class AllocationManager { ...context.activeAllocations, ] const { allocationSigner, allocationId } = uniqueAllocationID( - this.network.transactionManager.wallet.mnemonic.phrase, - context.currentEpoch.toNumber(), + this.network.transactionManager.wallet.mnemonic!.phrase, + Number(context.currentEpoch), deployment, activeAndRecentlyClosedAllocations.map((allocation) => allocation.id), ) @@ -418,8 +417,9 @@ export class AllocationManager { // enum AllocationState { Null, Active, Closed, Finalized, Claimed } // // in the contracts. - const state = await this.network.contracts.staking.getAllocationState(allocationId) - if (state !== 0) { + const state = + await this.network.contracts.HorizonStaking.getAllocationState(allocationId) + if (state !== 0n) { logger.debug(`Skipping allocation as it already exists onchain`, { indexer: this.network.specification.indexerOptions.address, allocation: allocationId, @@ -452,7 +452,7 @@ export class AllocationManager { subgraphDeploymentID: deployment.bytes32, tokens: amount, allocationID: allocationId, - metadata: utils.hexlify(Array(32).fill(0)), + metadata: hexlify(new Uint8Array(32).fill(0)), proof, } } @@ -461,7 +461,7 @@ export class AllocationManager { actionID: number, deployment: string, amount: string, - receipt: ContractReceipt | 'paused' | 'unauthorized', + receipt: TransactionReceipt | 'paused' | 'unauthorized', ): Promise { const logger = this.logger.child({ action: actionID }) const subgraphDeployment = new SubgraphDeploymentID(deployment) @@ -478,7 +478,7 @@ export class AllocationManager { const createAllocationEventLogs = this.network.transactionManager.findEvent( 'AllocationCreated', - this.network.contracts.staking.interface, + this.network.contracts.LegacyStaking.interface, 'subgraphDeploymentID', subgraphDeployment.bytes32, receipt, @@ -522,7 +522,7 @@ export class AllocationManager { return { actionID, type: 'allocate', - transactionID: receipt.transactionHash, + transactionID: receipt.hash, deployment: deployment, allocation: createAllocationEventLogs.allocationID, allocatedTokens: amount, @@ -534,8 +534,8 @@ export class AllocationManager { logger: Logger, context: TransactionPreparationContext, deployment: SubgraphDeploymentID, - amount: BigNumber, - ): Promise { + amount: bigint, + ): Promise { const params = await this.prepareAllocateParams(logger, context, deployment, amount) logger.debug(`Populating allocateFrom transaction`, { indexer: params.indexer, @@ -544,7 +544,8 @@ export class AllocationManager { allocation: params.allocationID, proof: params.proof, }) - return await this.network.contracts.staking.populateTransaction.allocateFrom( + // TODO HORIZON: split into pre-post horizon + return await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( params.indexer, params.subgraphDeploymentID, params.tokens, @@ -576,8 +577,10 @@ export class AllocationManager { // enum AllocationState { Null, Active, Closed, Finalized, Claimed } // // in the contracts. - const state = await this.network.contracts.staking.getAllocationState(allocation.id) - if (state !== 1) { + const state = await this.network.contracts.HorizonStaking.getAllocationState( + allocation.id, + ) + if (state !== 1n) { throw indexerError(IndexerErrorCode.IE065) } @@ -591,7 +594,7 @@ export class AllocationManager { async confirmUnallocate( actionID: number, allocationID: string, - receipt: ContractReceipt | 'paused' | 'unauthorized', + receipt: TransactionReceipt | 'paused' | 'unauthorized', ): Promise { const logger = this.logger.child({ action: actionID }) logger.info(`Confirming 'closeAllocation' transaction`) @@ -605,7 +608,7 @@ export class AllocationManager { const closeAllocationEventLogs = this.network.transactionManager.findEvent( 'AllocationClosed', - this.network.contracts.staking.interface, + this.network.contracts.LegacyStaking.interface, 'allocationID', allocationID, receipt, @@ -621,7 +624,7 @@ export class AllocationManager { const rewardsEventLogs = this.network.transactionManager.findEvent( 'RewardsAssigned', - this.network.contracts.rewardsManager.interface, + this.network.contracts.RewardsManager.interface, 'allocationID', allocationID, receipt, @@ -644,7 +647,7 @@ export class AllocationManager { indexer: closeAllocationEventLogs.indexer, amountGRT: formatGRT(closeAllocationEventLogs.tokens), poi: closeAllocationEventLogs.poi, - transaction: receipt.transactionHash, + transaction: receipt.hash, indexingRewards: rewardsAssigned, }) @@ -678,7 +681,7 @@ export class AllocationManager { return { actionID, type: 'unallocate', - transactionID: receipt.transactionHash, + transactionID: receipt.hash, allocation: closeAllocationEventLogs.allocationID, allocatedTokens: formatGRT(closeAllocationEventLogs.tokens), indexingRewards: formatGRT(rewardsAssigned), @@ -690,12 +693,13 @@ export class AllocationManager { async populateUnallocateTransaction( logger: Logger, params: UnallocateTransactionParams, - ): Promise { + ): Promise { logger.debug(`Populating closeAllocation transaction`, { allocationID: params.allocationID, POI: params.poi, }) - return await this.network.contracts.staking.populateTransaction.closeAllocation( + // TODO HORIZON: split into pre-post horizon + return await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( params.allocationID, params.poi, ) @@ -707,7 +711,7 @@ export class AllocationManager { allocationID: string, poi: string | undefined, force: boolean, - ): Promise { + ): Promise { const params = await this.prepareUnallocateParams( logger, context, @@ -723,7 +727,7 @@ export class AllocationManager { context: TransactionPreparationContext, allocationID: string, poi: string | undefined, - amount: BigNumber, + amount: bigint, force: boolean, ): Promise { logger.info('Preparing to reallocate', { @@ -768,13 +772,15 @@ export class AllocationManager { // enum AllocationState { Null, Active, Closed, Finalized, Claimed } // // in the this.contracts. - const state = await this.network.contracts.staking.getAllocationState(allocation.id) - if (state !== 1) { + const state = await this.network.contracts.HorizonStaking.getAllocationState( + allocation.id, + ) + if (state !== 1n) { logger.warn(`Allocation has already been closed`) throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) } - if (amount.lt('0')) { + if (amount < 0n) { logger.warn('Cannot reallocate a negative amount of GRT', { amount: amount.toString(), }) @@ -786,8 +792,8 @@ export class AllocationManager { logger.debug('Generating a new unique Allocation ID') const { allocationSigner, allocationId: newAllocationId } = uniqueAllocationID( - this.network.transactionManager.wallet.mnemonic.phrase, - context.currentEpoch.toNumber(), + this.network.transactionManager.wallet.mnemonic!.phrase, + Number(context.currentEpoch), allocation.subgraphDeployment.id, context.activeAllocations.map((allocation) => allocation.id), ) @@ -805,8 +811,8 @@ export class AllocationManager { // // in the this.contracts. const newAllocationState = - await this.network.contracts.staking.getAllocationState(newAllocationId) - if (newAllocationState !== 0) { + await this.network.contracts.HorizonStaking.getAllocationState(newAllocationId) + if (newAllocationState !== 0n) { logger.warn(`Skipping Allocation as it already exists onchain`, { indexer: this.network.specification.indexerOptions.address, allocation: newAllocationId, @@ -848,7 +854,7 @@ export class AllocationManager { subgraphDeploymentID: allocation.subgraphDeployment.id.bytes32, tokens: amount, newAllocationID: newAllocationId, - metadata: utils.hexlify(Array(32).fill(0)), + metadata: hexlify(new Uint8Array(32).fill(0)), proof, } } @@ -856,7 +862,7 @@ export class AllocationManager { async confirmReallocate( actionID: number, allocationID: string, - receipt: ContractReceipt | 'paused' | 'unauthorized', + receipt: TransactionReceipt | 'paused' | 'unauthorized', ): Promise { const logger = this.logger.child({ action: actionID }) logger.info(`Confirming close and allocate 'multicall' transaction`, { @@ -871,7 +877,7 @@ export class AllocationManager { const closeAllocationEventLogs = this.network.transactionManager.findEvent( 'AllocationClosed', - this.network.contracts.staking.interface, + this.network.contracts.LegacyStaking.interface, 'allocationID', allocationID, receipt, @@ -887,7 +893,7 @@ export class AllocationManager { const createAllocationEventLogs = this.network.transactionManager.findEvent( 'AllocationCreated', - this.network.contracts.staking.interface, + this.network.contracts.LegacyStaking.interface, 'subgraphDeploymentID', closeAllocationEventLogs.subgraphDeploymentID, receipt, @@ -903,7 +909,7 @@ export class AllocationManager { const rewardsEventLogs = this.network.transactionManager.findEvent( 'RewardsAssigned', - this.network.contracts.rewardsManager.interface, + this.network.contracts.RewardsManager.interface, 'allocationID', allocationID, receipt, @@ -931,7 +937,7 @@ export class AllocationManager { createdAllocationStakeGRT: formatGRT(createAllocationEventLogs.tokens), indexer: createAllocationEventLogs.indexer, epoch: createAllocationEventLogs.epoch.toString(), - transaction: receipt.transactionHash, + transaction: receipt.hash, }) logger.info('Identifying receipts worth collecting', { @@ -977,7 +983,7 @@ export class AllocationManager { return { actionID, type: 'reallocate', - transactionID: receipt.transactionHash, + transactionID: receipt.hash, closedAllocation: closeAllocationEventLogs.allocationID, indexingRewardsCollected: formatGRT(rewardsAssigned), receiptsWorthCollecting: isCollectingQueryFees, @@ -992,9 +998,9 @@ export class AllocationManager { context: TransactionPreparationContext, allocationID: string, poi: string | undefined, - amount: BigNumber, + amount: bigint, force: boolean, - ): Promise { + ): Promise { const params = await this.prepareReallocateParams( logger, context, @@ -1004,12 +1010,13 @@ export class AllocationManager { force, ) + // TODO HORIZON: split into pre-post horizon return [ - await this.network.contracts.staking.populateTransaction.closeAllocation( + await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( params.closingAllocationID, params.poi, ), - await this.network.contracts.staking.populateTransaction.allocateFrom( + await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( params.indexer, params.subgraphDeploymentID, params.tokens, @@ -1043,15 +1050,15 @@ export class AllocationManager { // Calculates the balance (GRT delta) of a single Action. async stakeUsageSummary(action: Action): Promise { - let unallocates = BigNumber.from(0) - let rewards = BigNumber.from(0) + let unallocates = 0n + let rewards = 0n // Handle allocations let allocates if (action.amount) { allocates = parseGRT(action.amount) } else { - allocates = BigNumber.from(0) + allocates = 0n } // Handle unallocations. @@ -1070,16 +1077,19 @@ export class AllocationManager { const allocation = await this.network.networkMonitor.allocation(action.allocationID) // Accrue rewards, except for zeroed POI - const zeroHexString = utils.hexlify(Array(32).fill(0)) + const zeroHexString = hexlify(new Uint8Array(32).fill(0)) rewards = action.poi === zeroHexString - ? BigNumber.from(0) - : await this.network.contracts.rewardsManager.getRewards(action.allocationID) + ? 0n + : await this.network.contracts.RewardsManager.getRewards( + this.network.contracts.HorizonStaking.target, + action.allocationID, + ) - unallocates = unallocates.add(allocation.allocatedTokens) + unallocates = unallocates + allocation.allocatedTokens } - const balance = allocates.sub(unallocates).sub(rewards) + const balance = allocates - unallocates - rewards return { action, allocates, @@ -1094,16 +1104,18 @@ export class AllocationManager { logger.debug(`Validating action batch`, { size: batch.length }) // Validate stake feasibility - const indexerFreeStake = await this.network.contracts.staking.getIndexerCapacity( - this.network.specification.indexerOptions.address, - ) + // TODO HORIZON: this call will be deprecated after horizon + const indexerFreeStake = + await this.network.contracts.LegacyStaking.getIndexerCapacity( + this.network.specification.indexerOptions.address, + ) const actionsBatchStakeUsageSummaries = await pMap(batch, async (action: Action) => this.stakeUsageSummary(action), ) - const batchDelta: BigNumber = actionsBatchStakeUsageSummaries + const batchDelta = actionsBatchStakeUsageSummaries .map((summary: ActionStakeUsageSummary) => summary.balance) - .reduce((a: BigNumber, b: BigNumber) => a.add(b)) - const indexerNewBalance = indexerFreeStake.sub(batchDelta) + .reduce((a: bigint, b: bigint) => a + b) + const indexerNewBalance = indexerFreeStake - batchDelta logger.trace('Action batch stake usage summary', { indexerFreeStake: indexerFreeStake.toString(), @@ -1120,7 +1132,7 @@ export class AllocationManager { indexerNewBalance: indexerNewBalance.toString(), }) - if (indexerNewBalance.isNegative()) { + if (indexerNewBalance < 0n) { { throw indexerError( IndexerErrorCode.IE013, @@ -1136,7 +1148,7 @@ export class AllocationManager { * first and larger allocations are processed last */ return actionsBatchStakeUsageSummaries .sort((a: ActionStakeUsageSummary, b: ActionStakeUsageSummary) => - a.balance.gt(b.balance) ? 1 : -1, + a.balance > b.balance ? 1 : -1, ) .map((a: ActionStakeUsageSummary) => a.action) } diff --git a/packages/indexer-common/src/indexer-management/client.ts b/packages/indexer-common/src/indexer-management/client.ts index fba61436a..822486e80 100644 --- a/packages/indexer-common/src/indexer-management/client.ts +++ b/packages/indexer-common/src/indexer-management/client.ts @@ -12,7 +12,6 @@ import costModelResolvers from './resolvers/cost-models' import indexingRuleResolvers from './resolvers/indexing-rules' import poiDisputeResolvers from './resolvers/poi-disputes' import statusResolvers from './resolvers/indexer-status' -import { BigNumber } from 'ethers' import { GraphNode } from '../graph-node' import { ActionManager, MultiNetworks, Network } from '@graphprotocol/indexer-common' @@ -445,7 +444,7 @@ export interface IndexerManagementDefaults { globalIndexingRule: Omit< IndexingRuleCreationAttributes, 'identifier' | 'allocationAmount' - > & { allocationAmount: BigNumber } + > & { allocationAmount: bigint } } export interface IndexerManagementClientOptions { diff --git a/packages/indexer-common/src/indexer-management/models/cost-model.ts b/packages/indexer-common/src/indexer-management/models/cost-model.ts index 5c719dad7..df2a71e4b 100644 --- a/packages/indexer-common/src/indexer-management/models/cost-model.ts +++ b/packages/indexer-common/src/indexer-management/models/cost-model.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-empty-interface */ import { Optional, Model, DataTypes, Sequelize } from 'sequelize' -import { utils } from 'ethers' +import { isHexString } from 'ethers' export interface GraphQLCostModel { deployment: string @@ -80,7 +80,7 @@ export const defineCostModelModels = (sequelize: Sequelize): CostModelModels => } // "0x..." and "global" is ok - if (utils.isHexString(value, 32) || value === COST_MODEL_GLOBAL) { + if (isHexString(value, 32) || value === COST_MODEL_GLOBAL) { return } diff --git a/packages/indexer-common/src/indexer-management/models/poi-dispute.ts b/packages/indexer-common/src/indexer-management/models/poi-dispute.ts index 3be43835b..8f7e1bb99 100644 --- a/packages/indexer-common/src/indexer-management/models/poi-dispute.ts +++ b/packages/indexer-common/src/indexer-management/models/poi-dispute.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-empty-interface */ import { Optional, Model, DataTypes, Sequelize } from 'sequelize' -import { utils } from 'ethers' +import { isHexString } from 'ethers' import { caip2IdRegex } from '../../parsers' export interface POIDisputeAttributes { @@ -95,7 +95,7 @@ export const definePOIDisputeModels = (sequelize: Sequelize): POIDisputeModels = } // "0x..." is ok - if (utils.isHexString(value, 20)) { + if (isHexString(value, 20)) { return } @@ -128,7 +128,7 @@ export const definePOIDisputeModels = (sequelize: Sequelize): POIDisputeModels = } // "0x..." is ok - if (utils.isHexString(value, 20)) { + if (isHexString(value, 20)) { return } @@ -155,7 +155,7 @@ export const definePOIDisputeModels = (sequelize: Sequelize): POIDisputeModels = } // "0x..." is ok - if (utils.isHexString(value, 32)) { + if (isHexString(value, 32)) { return } @@ -178,7 +178,7 @@ export const definePOIDisputeModels = (sequelize: Sequelize): POIDisputeModels = } // null or "0x..." is ok - if (!value || utils.isHexString(value, 32)) { + if (!value || isHexString(value, 32)) { return } @@ -197,7 +197,7 @@ export const definePOIDisputeModels = (sequelize: Sequelize): POIDisputeModels = } // "0x..." is ok - if (utils.isHexString(value, 32)) { + if (isHexString(value, 32)) { return } @@ -220,7 +220,7 @@ export const definePOIDisputeModels = (sequelize: Sequelize): POIDisputeModels = } // null or "0x..." is ok - if (!value || utils.isHexString(value, 32)) { + if (!value || isHexString(value, 32)) { return } @@ -239,7 +239,7 @@ export const definePOIDisputeModels = (sequelize: Sequelize): POIDisputeModels = } // "0x..." is ok - if (utils.isHexString(value, 32)) { + if (isHexString(value, 32)) { return } diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index e09e43fef..28e57f88c 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -19,19 +19,21 @@ import { TransferredSubgraphDeployment, sequentialTimerReduce, } from '@graphprotocol/indexer-common' +import { + GraphHorizonContracts, + SubgraphServiceContracts, +} from '@graphprotocol/toolshed/deployments' import { Address, Eventual, Logger, mutable, - NetworkContracts, SubgraphDeploymentID, toAddress, formatGRT, } from '@graphprotocol/common-ts' -import { BigNumber } from 'ethers' +import { HDNodeWallet, hexlify, Provider } from 'ethers' import gql from 'graphql-tag' -import { providers, utils, Wallet } from 'ethers' import pRetry, { Options } from 'p-retry' import { IndexerOptions } from '../network-specification' import pMap from 'p-map' @@ -41,12 +43,12 @@ import { SubgraphClient } from '../subgraph-client' export class NetworkMonitor { constructor( public networkCAIPID: string, - private contracts: NetworkContracts, + private contracts: GraphHorizonContracts & SubgraphServiceContracts, private indexerOptions: IndexerOptions, private logger: Logger, private graphNode: GraphNode, private networkSubgraph: SubgraphClient, - private ethereum: providers.BaseProvider, + private ethereum: Provider, private epochSubgraph: SubgraphClient, ) {} @@ -55,11 +57,12 @@ export class NetworkMonitor { } async currentEpochNumber(): Promise { - return (await this.contracts.epochManager.currentEpoch()).toNumber() + return Number(await this.contracts.EpochManager.currentEpoch()) } async maxAllocationEpoch(): Promise { - return await this.contracts.staking.maxAllocationEpochs() + // TODO HORIZON: this call will fail in Horizon, return 0 or something else? + return Number(await this.contracts.LegacyStaking.maxAllocationEpochs()) } /** @@ -620,18 +623,18 @@ export class NetworkMonitor { idOnL1: deployment.idOnL1, idOnL2: deployment.idOnL2, startedTransferToL2: deployment.startedTransferToL2, - startedTransferToL2At: BigNumber.from(deployment.startedTransferToL2At), - startedTransferToL2AtBlockNumber: BigNumber.from( + startedTransferToL2At: BigInt(deployment.startedTransferToL2At), + startedTransferToL2AtBlockNumber: BigInt( deployment.startedTransferToL2AtBlockNumber, ), startedTransferToL2AtTx: deployment.startedTransferToL2AtTx, transferredToL2: deployment.transferredToL2, transferredToL2At: deployment.transferredToL2At - ? BigNumber.from(deployment.transferredToL2At) + ? BigInt(deployment.transferredToL2At) : null, transferredToL2AtTx: deployment.transferredToL2AtTx, transferredToL2AtBlockNumber: deployment.transferredToL2AtBlockNumber - ? BigNumber.from(deployment.transferredToL2AtBlockNumber) + ? BigInt(deployment.transferredToL2AtBlockNumber) : null, ipfsHash: version.subgraphDeployment.ipfsHash, protocolNetwork: this.networkCAIPID, @@ -832,7 +835,8 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n // Calls the configured provider for blocks from protocol chain, or Graph Node otherwise. let startBlockHash: string if (networkID == this.networkCAIPID) { - startBlockHash = (await this.ethereum.getBlock(+validBlock.blockNumber)).hash + const block = await this.ethereum.getBlock(+validBlock.blockNumber) + startBlockHash = block!.hash! } else { startBlockHash = await this.graphNode.blockHashFromNumber( networkAlias, @@ -919,7 +923,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n const supportedNetworkAlias = await this.allocationNetworkAlias(allocation) if (null === supportedNetworkAlias) { this.logger.info("Network is not supported, can't resolve POI") - return utils.hexlify(Array(32).fill(0)) + return hexlify(new Uint8Array(32).fill(0)) } // poi = undefined, force=true -- submit even if poi is 0x0 @@ -938,7 +942,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n allocation.subgraphDeployment.id, await this.fetchPOIBlockPointer(supportedNetworkAlias, allocation), allocation.indexer, - )) || utils.hexlify(Array(32).fill(0)) + )) || hexlify(new Uint8Array(32).fill(0)) ) } break @@ -991,11 +995,11 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async monitorNetworkPauses( logger: Logger, - contracts: NetworkContracts, + contracts: GraphHorizonContracts & SubgraphServiceContracts, networkSubgraph: SubgraphClient, ): Promise> { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const initialPauseValue = await contracts.controller.paused().catch((_) => { + const initialPauseValue = await contracts.Controller.paused().catch((_) => { return false }) return sequentialTimerReduce( @@ -1043,9 +1047,9 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async monitorIsOperator( logger: Logger, - contracts: NetworkContracts, + contracts: GraphHorizonContracts & SubgraphServiceContracts, indexerAddress: Address, - wallet: Wallet, + wallet: HDNodeWallet, ): Promise> { // If indexer and operator address are identical, operator status is // implicitly granted => we'll never have to check again @@ -1062,7 +1066,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async (isOperator) => { try { logger.debug('Check operator status') - return await contracts.staking.isOperator(wallet.address, indexerAddress) + return await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress) } catch (err) { logger.warn( `Failed to check operator status for indexer, assuming it has not changed`, @@ -1071,7 +1075,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n return isOperator } }, - await contracts.staking.isOperator(wallet.address, indexerAddress), + await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress), ).map((isOperator) => { logger.info( isOperator @@ -1134,11 +1138,11 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n throw result.error } - const totalFees: BigNumber = result.data.allocations.reduce( - (total: BigNumber, rawAlloc: { queryFeesCollected: string }) => { - return total.add(BigNumber.from(rawAlloc.queryFeesCollected)) + const totalFees: bigint = result.data.allocations.reduce( + (total: bigint, rawAlloc: { queryFeesCollected: string }) => { + return total + BigInt(rawAlloc.queryFeesCollected) }, - BigNumber.from(0), + 0n, ) const parsedAllocs: Allocation[] = @@ -1147,7 +1151,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n // If the total fees claimable do not meet the minimum required for batching, return an empty array if ( parsedAllocs.length > 0 && - totalFees.lt(this.indexerOptions.rebateClaimBatchThreshold) + totalFees < this.indexerOptions.rebateClaimBatchThreshold ) { this.logger.info( `Allocation rebate batch value does not meet minimum for claiming`, @@ -1198,7 +1202,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n let allocations: Allocation[] = [] try { - const zeroPOI = utils.hexlify(Array(32).fill(0)) + const zeroPOI = hexlify(new Uint8Array(32).fill(0)) const disputableEpoch = currentEpoch - this.indexerOptions.poiDisputableEpochs let lastId = '' while (dataRemaining) { @@ -1278,7 +1282,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async (epoch) => { try { const startBlock = await this.ethereum.getBlock(epoch.startBlock) - epoch.startBlockHash = startBlock?.hash + epoch.startBlockHash = startBlock!.hash! } catch { logger.debug('Failed to fetch block hash for startBlock of epoch', { epoch: epoch.id, diff --git a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts index 5d2e72690..93151e540 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts @@ -4,7 +4,7 @@ import { epochElapsedBlocks, Network } from '@graphprotocol/indexer-common' import pMap from 'p-map' import gql from 'graphql-tag' -import { BigNumber, utils } from 'ethers' +import { hexlify } from 'ethers' import { Address, @@ -277,7 +277,7 @@ async function queryAllocations( .ipfsHash, signalledTokens: allocation.subgraphDeployment.signalledTokens, stakedTokens: allocation.subgraphDeployment.stakedTokens, - allocatedTokens: BigNumber.from(allocation.allocatedTokens).toString(), + allocatedTokens: allocation.allocatedTokens.toString(), createdAtEpoch: allocation.createdAtEpoch, closedAtEpoch: allocation.closedAtEpoch, ageInEpochs: allocation.closedAtEpoch @@ -330,8 +330,8 @@ export default { const [currentEpoch, maxAllocationEpochs, epochLength] = await Promise.all([ networkMonitor.networkCurrentEpoch(), - contracts.staking.maxAllocationEpochs(), - contracts.epochManager.epochLength(), + contracts.LegacyStaking.maxAllocationEpochs(), + contracts.EpochManager.epochLength(), ]) const allocation = filter.allocation @@ -351,8 +351,8 @@ export default { currentEpochStartBlock: currentEpoch.startBlockNumber, currentEpochElapsedBlocks: epochElapsedBlocks(currentEpoch), latestBlock: currentEpoch.latestBlock, - maxAllocationEpochs, - blocksPerEpoch: epochLength.toNumber(), + maxAllocationEpochs: Number(maxAllocationEpochs), + blocksPerEpoch: Number(epochLength), avgBlockTime: 13000, protocolNetwork: network.specification.networkIdentifier, } @@ -412,7 +412,7 @@ export default { ) } - if (allocationAmount.lt('0')) { + if (allocationAmount < 0n) { logger.warn('Cannot allocate a negative amount of GRT', { amount: formatGRT(allocationAmount), }) @@ -423,13 +423,13 @@ export default { } try { - const currentEpoch = await contracts.epochManager.currentEpoch() + const currentEpoch = await contracts.EpochManager.currentEpoch() // Identify how many GRT the indexer has staked - const freeStake = await contracts.staking.getIndexerCapacity(address) + const freeStake = await contracts.LegacyStaking.getIndexerCapacity(address) // If there isn't enough left for allocating, abort - if (freeStake.lt(allocationAmount)) { + if (freeStake < allocationAmount) { logger.error( `Allocation of ${formatGRT( allocationAmount, @@ -457,8 +457,8 @@ export default { // Obtain a unique allocation ID const { allocationSigner, allocationId } = uniqueAllocationID( - transactionManager.wallet.mnemonic.phrase, - currentEpoch.toNumber(), + transactionManager.wallet.mnemonic!.phrase, + Number(currentEpoch), subgraphDeployment, activeAllocations.map((allocation) => allocation.id), ) @@ -470,8 +470,8 @@ export default { // enum AllocationState { Null, Active, Closed, Finalized } // // in the contracts. - const state = await contracts.staking.getAllocationState(allocationId) - if (state !== 0) { + const state = await contracts.HorizonStaking.getAllocationState(allocationId) + if (state !== 0n) { logger.debug(`Skipping allocation as it already exists onchain`, { indexer: address, allocation: allocationId, @@ -506,21 +506,21 @@ export default { const receipt = await transactionManager.executeTransaction( async () => - contracts.staking.estimateGas.allocateFrom( + contracts.LegacyStaking.allocateFrom.estimateGas( address, subgraphDeployment.bytes32, allocationAmount, allocationId, - utils.hexlify(Array(32).fill(0)), + hexlify(new Uint8Array(32).fill(0)), proof, ), async (gasLimit) => - contracts.staking.allocateFrom( + contracts.LegacyStaking.allocateFrom( address, subgraphDeployment.bytes32, allocationAmount, allocationId, - utils.hexlify(Array(32).fill(0)), + hexlify(new Uint8Array(32).fill(0)), proof, { gasLimit }, ), @@ -538,7 +538,7 @@ export default { const createAllocationEventLogs = network.transactionManager.findEvent( 'AllocationCreated', - network.contracts.staking.interface, + network.contracts.LegacyStaking.interface, 'subgraphDeploymentID', subgraphDeployment.toString(), receipt, @@ -556,7 +556,7 @@ export default { amountGRT: formatGRT(createAllocationEventLogs.tokens), allocation: createAllocationEventLogs.allocationID, epoch: createAllocationEventLogs.epoch.toString(), - transaction: receipt.transactionHash, + transaction: receipt.hash, }) logger.debug( @@ -584,7 +584,7 @@ export default { return { actionID: 0, type: 'allocate', - transactionID: receipt.transactionHash, + transactionID: receipt.hash, deployment, allocation: createAllocationEventLogs.allocationID, allocatedTokens: formatGRT(allocationAmount.toString()), @@ -640,18 +640,19 @@ export default { // enum AllocationState { Null, Active, Closed, Finalized } // // in the contracts. - const state = await contracts.staking.getAllocationState(allocationData.id) - if (state !== 1) { + const state = await contracts.HorizonStaking.getAllocationState(allocationData.id) + if (state !== 1n) { throw indexerError(IndexerErrorCode.IE065, 'Allocation has already been closed') } logger.debug('Sending closeAllocation transaction') const receipt = await transactionManager.executeTransaction( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - () => contracts.staking.estimateGas.closeAllocation(allocationData.id, poi!), + () => + contracts.LegacyStaking.closeAllocation.estimateGas(allocationData.id, poi!), (gasLimit) => // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - contracts.staking.closeAllocation(allocationData.id, poi!, { + contracts.LegacyStaking.closeAllocation(allocationData.id, poi!, { gasLimit, }), logger, @@ -666,7 +667,7 @@ export default { const closeAllocationEventLogs = transactionManager.findEvent( 'AllocationClosed', - contracts.staking.interface, + contracts.LegacyStaking.interface, 'allocationID', allocation, receipt, @@ -682,7 +683,7 @@ export default { const rewardsEventLogs = transactionManager.findEvent( 'RewardsAssigned', - contracts.rewardsManager.interface, + contracts.RewardsManager.interface, 'allocationID', allocation, receipt, @@ -703,7 +704,7 @@ export default { effectiveAllocation: closeAllocationEventLogs.effectiveAllocation.toString(), poi: closeAllocationEventLogs.poi, epoch: closeAllocationEventLogs.epoch.toString(), - transaction: receipt.transactionHash, + transaction: receipt.hash, indexingRewards: rewardsAssigned, }) @@ -742,7 +743,7 @@ export default { return { actionID: 0, type: 'unallocate', - transactionID: receipt.transactionHash, + transactionID: receipt.hash, allocation: closeAllocationEventLogs.allocationID, allocatedTokens: formatGRT(closeAllocationEventLogs.tokens), indexingRewards: formatGRT(rewardsAssigned), @@ -813,7 +814,7 @@ export default { } try { - const currentEpoch = await contracts.epochManager.currentEpoch() + const currentEpoch = await contracts.EpochManager.currentEpoch() logger.debug('Resolving POI') const allocationPOI = await networkMonitor.resolvePOI(allocationData, poi, force) @@ -829,13 +830,13 @@ export default { // enum AllocationState { Null, Active, Closed, Finalized } // // in the contracts. - const state = await contracts.staking.getAllocationState(allocationData.id) - if (state !== 1) { + const state = await contracts.HorizonStaking.getAllocationState(allocationData.id) + if (state !== 1n) { logger.warn(`Allocation has already been closed`) throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) } - if (allocationAmount.lt('0')) { + if (allocationAmount < 0n) { logger.warn('Cannot reallocate a negative amount of GRT', { amount: allocationAmount.toString(), }) @@ -852,14 +853,14 @@ export default { }) // Identify how many GRT the indexer has staked - const freeStake = await contracts.staking.getIndexerCapacity(address) + const freeStake = await contracts.LegacyStaking.getIndexerCapacity(address) // When reallocating, we will first close the old allocation and free up the GRT in that allocation // This GRT will be available in addition to freeStake for the new allocation - const postCloseFreeStake = freeStake.add(allocationData.allocatedTokens) + const postCloseFreeStake = freeStake + allocationData.allocatedTokens // If there isn't enough left for allocating, abort - if (postCloseFreeStake.lt(allocationAmount)) { + if (postCloseFreeStake < allocationAmount) { throw indexerError( IndexerErrorCode.IE013, `Unable to allocate ${formatGRT( @@ -874,8 +875,8 @@ export default { logger.debug('Generating a new unique Allocation ID') const { allocationSigner, allocationId: newAllocationId } = uniqueAllocationID( - transactionManager.wallet.mnemonic.phrase, - currentEpoch.toNumber(), + transactionManager.wallet.mnemonic!.phrase, + Number(currentEpoch), allocationData.subgraphDeployment.id, activeAllocations.map((allocation) => allocation.id), ) @@ -893,8 +894,8 @@ export default { // // in the contracts. const newAllocationState = - await contracts.staking.getAllocationState(newAllocationId) - if (newAllocationState !== 0) { + await contracts.HorizonStaking.getAllocationState(newAllocationId) + if (newAllocationState !== 0n) { logger.warn(`Skipping Allocation as it already exists onchain`, { indexer: address, allocation: newAllocationId, @@ -926,23 +927,23 @@ export default { }) const callData = [ - await contracts.staking.populateTransaction.closeAllocation( + await contracts.LegacyStaking.closeAllocation.populateTransaction( allocationData.id, allocationPOI, ), - await contracts.staking.populateTransaction.allocateFrom( + await contracts.LegacyStaking.allocateFrom.populateTransaction( address, allocationData.subgraphDeployment.id.bytes32, allocationAmount, newAllocationId, - utils.hexlify(Array(32).fill(0)), // metadata + hexlify(new Uint8Array(32).fill(0)), // metadata proof, ), ].map((tx) => tx.data as string) const receipt = await transactionManager.executeTransaction( - async () => contracts.staking.estimateGas.multicall(callData), - async (gasLimit) => contracts.staking.multicall(callData, { gasLimit }), + async () => contracts.LegacyStaking.multicall.estimateGas(callData), + async (gasLimit) => contracts.LegacyStaking.multicall(callData, { gasLimit }), logger.child({ function: 'closeAndAllocate', }), @@ -957,7 +958,7 @@ export default { const createAllocationEventLogs = transactionManager.findEvent( 'AllocationCreated', - contracts.staking.interface, + contracts.LegacyStaking.interface, 'subgraphDeploymentID', allocationData.subgraphDeployment.id.toString(), receipt, @@ -970,7 +971,7 @@ export default { const closeAllocationEventLogs = transactionManager.findEvent( 'AllocationClosed', - contracts.staking.interface, + contracts.LegacyStaking.interface, 'allocationID', allocation, receipt, @@ -986,7 +987,7 @@ export default { const rewardsEventLogs = transactionManager.findEvent( 'RewardsAssigned', - contracts.rewardsManager.interface, + contracts.RewardsManager.interface, 'allocationID', allocation, receipt, @@ -1010,7 +1011,7 @@ export default { createdAllocationStakeGRT: formatGRT(createAllocationEventLogs.tokens), indexer: createAllocationEventLogs.indexer, epoch: createAllocationEventLogs.epoch.toString(), - transaction: receipt.transactionHash, + transaction: receipt.hash, }) logger.info('Identifying receipts worth collecting', { @@ -1049,7 +1050,7 @@ export default { return { actionID: 0, type: 'reallocate', - transactionID: receipt.transactionHash, + transactionID: receipt.hash, closedAllocation: closeAllocationEventLogs.allocationID, indexingRewardsCollected: formatGRT(rewardsAssigned), receiptsWorthCollecting: isCollectingQueryFees, diff --git a/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts b/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts index 3c3461d12..5a8ee8f14 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts @@ -75,10 +75,10 @@ export default { const protocolNetwork = network.specification.networkIdentifier const address = network.specification.indexerOptions.address const contracts = network.contracts - const registered = await contracts.serviceRegistry.isRegistered(address) + const registered = await contracts.LegacyServiceRegistry.isRegistered(address) if (registered) { - const service = await contracts.serviceRegistry.services(address) + const service = await contracts.LegacyServiceRegistry.services(address) return { address, protocolNetwork, @@ -264,7 +264,7 @@ async function endpointForNetwork(network: Network): Promise { const contracts = network.contracts const address = network.specification.indexerOptions.address const endpoints = defaultEndpoints(network.specification.networkIdentifier) - const service = await contracts.serviceRegistry.services(address) + const service = await contracts.LegacyServiceRegistry.services(address) if (service) { { const { url, tests, ok } = await testURL(service.url, [ diff --git a/packages/indexer-common/src/indexer-management/types.ts b/packages/indexer-common/src/indexer-management/types.ts index 67dcc4fa2..0985038eb 100644 --- a/packages/indexer-common/src/indexer-management/types.ts +++ b/packages/indexer-common/src/indexer-management/types.ts @@ -4,7 +4,6 @@ import { SubgraphDeploymentID, toAddress, } from '@graphprotocol/common-ts' -import { BigNumber } from 'ethers' import { Allocation } from '../allocations' import { GraphNode } from '../graph-node' import { SubgraphDeployment } from '../types' @@ -74,9 +73,9 @@ export const parseGraphQLSubgraphDeployment = ( ): SubgraphDeployment => ({ id: new SubgraphDeploymentID(subgraphDeployment.id), deniedAt: subgraphDeployment.deniedAt, - stakedTokens: BigNumber.from(subgraphDeployment.stakedTokens), - signalledTokens: BigNumber.from(subgraphDeployment.signalledTokens), - queryFeesAmount: BigNumber.from(subgraphDeployment.queryFeesAmount), + stakedTokens: BigInt(subgraphDeployment.stakedTokens), + signalledTokens: BigInt(subgraphDeployment.signalledTokens), + queryFeesAmount: BigInt(subgraphDeployment.queryFeesAmount), protocolNetwork, }) @@ -91,13 +90,13 @@ export const parseGraphQLAllocation = ( 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), + stakedTokens: BigInt(allocation.subgraphDeployment.stakedTokens), + signalledTokens: BigInt(allocation.subgraphDeployment.signalledTokens), + queryFeesAmount: BigInt(allocation.subgraphDeployment.queryFeesAmount), protocolNetwork, }, indexer: toAddress(allocation.indexer.id), - allocatedTokens: BigNumber.from(allocation.allocatedTokens), + allocatedTokens: BigInt(allocation.allocatedTokens), createdAtBlockHash: allocation.createdAtBlockHash, createdAtEpoch: allocation.createdAtEpoch, closedAtEpoch: allocation.closedAtEpoch, diff --git a/packages/indexer-common/src/network-specification.ts b/packages/indexer-common/src/network-specification.ts index f683cdec5..162ae5335 100644 --- a/packages/indexer-common/src/network-specification.ts +++ b/packages/indexer-common/src/network-specification.ts @@ -1,9 +1,8 @@ import { toAddress, parseGRT } from '@graphprotocol/common-ts' -import { BigNumber } from 'ethers' import { validateNetworkIdentifier, validateIpfsHash } from './parsers' import { AllocationManagementMode } from './types' import { z } from 'zod' -import { utils } from 'ethers' +import { isAddress } from 'ethers' // TODO: make sure those values are always in sync with the AllocationManagementMode enum. Can we do this in compile time? const ALLOCATION_MANAGEMENT_MODE = ['auto', 'manual', 'oversight'] as const @@ -12,7 +11,7 @@ function positiveNumber(): z.ZodNumber { return z.number().positive().finite() } -function GRT(): z.ZodEffects { +function GRT(): z.ZodEffects { return z .number() .nonnegative() @@ -33,7 +32,7 @@ export const IndexerOptions = z .object({ address: z .string() - .refine((val) => utils.isAddress(val), { + .refine((val) => isAddress(val), { message: 'Invalid contract address', }) .transform(toAddress), @@ -145,13 +144,13 @@ export const TapContracts = z .record( z.string(), z.object({ - TAPVerifier: z.string().refine((val) => utils.isAddress(val), { + TAPVerifier: z.string().refine((val) => isAddress(val), { message: 'Invalid contract address', }), - AllocationIDTracker: z.string().refine((val) => utils.isAddress(val), { + AllocationIDTracker: z.string().refine((val) => isAddress(val), { message: 'Invalid contract address', }), - Escrow: z.string().refine((val) => utils.isAddress(val), { + Escrow: z.string().refine((val) => isAddress(val), { message: 'Invalid contract address', }), }), diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index 1b8d436e2..4217f84b5 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -1,18 +1,21 @@ import { Logger, Metrics, - NetworkContracts, SubgraphDeploymentID, - connectContracts, Eventual, - AddressBook, toAddress, } from '@graphprotocol/common-ts' +import { + connectGraphHorizon, + connectSubgraphService, + GraphHorizonContracts, + SubgraphServiceContracts, +} from '@graphprotocol/toolshed/deployments' import { connectContracts as connectTapContracts, NetworkContracts as TapContracts, } from '@semiotic-labs/tap-contracts-bindings' -import { providers, Wallet } from 'ethers' +import { FetchRequest, HDNodeWallet, JsonRpcProvider, Provider, Wallet } from 'ethers' import { strict as assert } from 'assert' import geohash from 'ngeohash' import pRetry, { Options } from 'p-retry' @@ -33,15 +36,14 @@ import { import { resolveChainId } from './indexer-management' import { monitorEthBalance } from './utils' import { QueryFeeModels } from './query-fees' -import { readFileSync } from 'fs' import { TapCollector } from './allocations/tap-collector' export class Network { logger: Logger networkSubgraph: SubgraphClient - contracts: NetworkContracts - wallet: Wallet - networkProvider: providers.StaticJsonRpcProvider + contracts: GraphHorizonContracts & SubgraphServiceContracts + wallet: HDNodeWallet + networkProvider: JsonRpcProvider transactionManager: TransactionManager networkMonitor: NetworkMonitor @@ -55,10 +57,10 @@ export class Network { private constructor( logger: Logger, - contracts: NetworkContracts, - wallet: Wallet, + contracts: GraphHorizonContracts & SubgraphServiceContracts, + wallet: HDNodeWallet, networkSubgraph: SubgraphClient, - networkProvider: providers.StaticJsonRpcProvider, + networkProvider: JsonRpcProvider, transactionManager: TransactionManager, networkMonitor: NetworkMonitor, receiptCollector: AllocationReceiptCollector | undefined, @@ -268,7 +270,7 @@ export class Network { try { tapContracts = await connectTapContracts( wallet, - networkIdentifier.chainId, + Number(networkIdentifier.chainId), specification.tapAddressBook, ) } catch (err) { @@ -283,29 +285,29 @@ export class Network { indexer: toAddress(specification.indexerOptions.address), logger, networkSubgraph, - protocolNetwork: resolveChainId(networkIdentifier.chainId), + protocolNetwork: resolveChainId(Number(networkIdentifier.chainId)), interval: specification.allocationSyncInterval, }) // -------------------------------------------------------------------------------- // * Allocation Receipt Collector // -------------------------------------------------------------------------------- - let scalarCollector: AllocationReceiptCollector | undefined = undefined - if (!(tapContracts && tapSubgraph)) { - logger.warn( - "deprecated scalar voucher collector is enabled - you probably don't want this", - ) - scalarCollector = await AllocationReceiptCollector.create({ - logger, - metrics, - transactionManager: transactionManager, - models: queryFeeModels, - allocationExchange: contracts.allocationExchange, - allocations, - networkSpecification: specification, - networkSubgraph, - }) - } + const scalarCollector: AllocationReceiptCollector | undefined = undefined + // if (!(tapContracts && tapSubgraph)) { + // logger.warn( + // "deprecated scalar voucher collector is enabled - you probably don't want this", + // ) + // scalarCollector = await AllocationReceiptCollector.create({ + // logger, + // metrics, + // transactionManager: transactionManager, + // models: queryFeeModels, + // allocationExchange: contracts.allocationExchange, + // allocations, + // networkSpecification: specification, + // networkSubgraph, + // }) + // } // -------------------------------------------------------------------------------- // * TAP Collector @@ -354,7 +356,7 @@ export class Network { networkIdentifier: string, networkURL: string, pollingInterval: number, - ): Promise { + ): Promise { logger.info(`Connect to Network chain`, { provider: networkURL, pollingInterval, @@ -398,12 +400,13 @@ export class Network { password = providerUrl.password } - const networkProvider = new providers.StaticJsonRpcProvider({ - url: providerUrl.toString(), - user: username, - password: password, - allowInsecureAuthentication: true, - }) + const providerFetchRequest = new FetchRequest(providerUrl.toString()) + if (username !== undefined && password !== undefined) { + providerFetchRequest.setCredentials(username, password) + providerFetchRequest.allowInsecureAuthentication = true + } + + const networkProvider = new JsonRpcProvider(providerFetchRequest) networkProvider.pollingInterval = pollingInterval networkProvider.on('debug', (info) => { @@ -428,9 +431,9 @@ export class Network { }) logger.info(`Connected to network`, { - provider: networkProvider.connection.url, + provider: providerFetchRequest.url, pollingInterval: networkProvider.pollingInterval, - network: await networkProvider.detectNetwork(), + network: await networkProvider.getNetwork(), }) return networkProvider @@ -464,11 +467,11 @@ export class Network { // Register the indexer (only if it hasn't been registered yet or // if its URL is different from what is registered on chain) - const isRegistered = await this.contracts.serviceRegistry.isRegistered( + const isRegistered = await this.contracts.LegacyServiceRegistry.isRegistered( this.specification.indexerOptions.address, ) if (isRegistered) { - const service = await this.contracts.serviceRegistry.services( + const service = await this.contracts.LegacyServiceRegistry.services( this.specification.indexerOptions.address, ) if ( @@ -485,13 +488,13 @@ export class Network { } const receipt = await this.transactionManager.executeTransaction( () => - this.contracts.serviceRegistry.estimateGas.registerFor( + this.contracts.LegacyServiceRegistry.registerFor.estimateGas( this.specification.indexerOptions.address, this.specification.indexerOptions.url, geoHash, ), (gasLimit) => - this.contracts.serviceRegistry.registerFor( + this.contracts.LegacyServiceRegistry.registerFor( this.specification.indexerOptions.address, this.specification.indexerOptions.url, geoHash, @@ -504,10 +507,12 @@ export class Network { if (receipt === 'paused' || receipt === 'unauthorized') { return } - const events = receipt.events || receipt.logs + const events = receipt.logs const event = events.find((event) => event.topics.includes( - this.contracts.serviceRegistry.interface.getEventTopic('ServiceRegistered'), + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain + this.contracts.LegacyServiceRegistry.interface.getEvent('ServiceRegistered') + ?.topicHash!, ), ) assert.ok(event) @@ -527,26 +532,26 @@ export class Network { } async function connectWallet( - networkProvider: providers.Provider, + networkProvider: Provider, networkIdentifier: string, mnemonic: string, logger: Logger, -): Promise { +): Promise { logger.info(`Connect wallet`, { networkIdentifier: networkIdentifier, }) - let wallet = Wallet.fromMnemonic(mnemonic) + let wallet = Wallet.fromPhrase(mnemonic) wallet = wallet.connect(networkProvider) logger.info(`Connected wallet`) return wallet } async function connectToProtocolContracts( - wallet: Wallet, + wallet: HDNodeWallet, networkIdentifier: string, logger: Logger, addressBook?: string, -): Promise { +): Promise { const numericNetworkId = parseInt(networkIdentifier.split(':')[1]) // Confidence check: Should be unreachable since NetworkSpecification was validated before @@ -558,12 +563,18 @@ async function connectToProtocolContracts( network: networkIdentifier, }) - let contracts + let contracts: GraphHorizonContracts & SubgraphServiceContracts try { - const contractAddresses = addressBook - ? (JSON.parse(readFileSync(addressBook).toString()) as AddressBook) - : undefined - contracts = await connectContracts(wallet, numericNetworkId, contractAddresses) + const horizonContracts = connectGraphHorizon(numericNetworkId, wallet, addressBook) + const subgraphServiceContracts = connectSubgraphService( + numericNetworkId, + wallet, + addressBook, + ) + contracts = { + ...horizonContracts, + ...subgraphServiceContracts, + } } catch (error) { const errorMessage = 'Failed to connect to contracts, please ensure you are using the intended protocol network.' @@ -571,14 +582,14 @@ async function connectToProtocolContracts( throw new Error(`${errorMessage} Error: ${error}`) } logger.info(`Successfully connected to contracts`, { - curation: contracts.curation.address, - disputeManager: contracts.disputeManager.address, - epochManager: contracts.epochManager.address, - gns: contracts.gns.address, - rewardsManager: contracts.rewardsManager.address, - serviceRegistry: contracts.serviceRegistry.address, - staking: contracts.staking.address, - token: contracts.token.address, + curation: contracts.L2Curation.target, + disputeManager: contracts.DisputeManager.target, + epochManager: contracts.EpochManager.target, + gns: contracts.L2GNS.target, + rewardsManager: contracts.RewardsManager.target, + serviceRegistry: contracts.LegacyServiceRegistry.target, + staking: contracts.HorizonStaking.target, + token: contracts.GraphToken.target, }) return contracts } diff --git a/packages/indexer-common/src/operator.ts b/packages/indexer-common/src/operator.ts index 1d97904c4..8f6c49323 100644 --- a/packages/indexer-common/src/operator.ts +++ b/packages/indexer-common/src/operator.ts @@ -18,14 +18,14 @@ import { POIDisputeAttributes, } from '@graphprotocol/indexer-common' import { Logger, formatGRT } from '@graphprotocol/common-ts' -import { BigNumber, utils } from 'ethers' +import { hexlify } from 'ethers' import gql from 'graphql-tag' import pMap from 'p-map' import { CombinedError } from '@urql/core' const POI_DISPUTES_CONVERTERS_FROM_GRAPHQL: Record< keyof POIDisputeAttributes, - (x: never) => string | BigNumber | number | null + (x: never) => string | bigint | number | null > = { allocationID: (x) => x, subgraphDeploymentID: (x) => x, @@ -339,7 +339,7 @@ export class Operator { ): Promise { const desiredAllocationAmount = deploymentAllocationDecision.ruleMatch.rule ?.allocationAmount - ? BigNumber.from(deploymentAllocationDecision.ruleMatch.rule.allocationAmount) + ? BigInt(deploymentAllocationDecision.ruleMatch.rule.allocationAmount) : this.specification.indexerOptions.defaultAllocationAmount logger.info(`No active allocation for deployment, creating one now`, { @@ -350,7 +350,7 @@ export class Operator { if ( deploymentAllocationDecision.ruleMatch.rule?.safety && mostRecentlyClosedAllocation && - mostRecentlyClosedAllocation.poi === utils.hexlify(Array(32).fill(0)) + mostRecentlyClosedAllocation.poi === hexlify(new Uint8Array(32).fill(0)) ) { logger.warn( `Skipping allocation to this deployment as the last allocation to it was closed with a zero POI`, @@ -430,7 +430,7 @@ export class Operator { const desiredAllocationAmount = deploymentAllocationDecision.ruleMatch.rule ?.allocationAmount - ? BigNumber.from(deploymentAllocationDecision.ruleMatch.rule.allocationAmount) + ? BigInt(deploymentAllocationDecision.ruleMatch.rule.allocationAmount) : this.specification.indexerOptions.defaultAllocationAmount // Queue reallocate actions to be picked up by the worker diff --git a/packages/indexer-common/src/parsers/test-utils.ts b/packages/indexer-common/src/parsers/test-utils.ts index 3463cbdec..e1bc167ad 100644 --- a/packages/indexer-common/src/parsers/test-utils.ts +++ b/packages/indexer-common/src/parsers/test-utils.ts @@ -6,7 +6,7 @@ import { displayZodParsingError } from './error-handling' import path from 'path' export function loadTestYamlConfig() { - const PUBLIC_JSON_RPC_ENDPOINT = 'https://ethereum-sepolia.publicnode.com' + const PUBLIC_JSON_RPC_ENDPOINT = 'https://sepolia-rollup.arbitrum.io/rpc' const testProviderUrl = process.env.INDEXER_TEST_JRPC_PROVIDER_URL ?? PUBLIC_JSON_RPC_ENDPOINT const INDEXER_TEST_API_KEY: string = process.env['INDEXER_TEST_API_KEY'] || '' diff --git a/packages/indexer-common/src/subgraphs.ts b/packages/indexer-common/src/subgraphs.ts index 9ffb3fb06..02a47292b 100644 --- a/packages/indexer-common/src/subgraphs.ts +++ b/packages/indexer-common/src/subgraphs.ts @@ -1,5 +1,4 @@ -import { base58 } from 'ethers/lib/utils' -import { BigNumber, utils } from 'ethers' +import { decodeBase58, isHexString } from 'ethers' import { Logger, SubgraphDeploymentID } from '@graphprotocol/common-ts' import { SubgraphDeployment } from './types' import { @@ -32,11 +31,7 @@ export async function validateSubgraphID( } const values = s.split('-') - if ( - values.length == 2 && - utils.isHexString(values[0], 20) && - !isNaN(parseInt(values[1])) - ) { + if (values.length == 2 && isHexString(values[0], 20) && !isNaN(parseInt(values[1]))) { return type } @@ -57,7 +52,7 @@ export async function validateDeploymentID( // Case 4: 'Qm...' try { // This will throw if it's not valid - base58.decode(s) + decodeBase58(s) if (s.length === 46) { return type @@ -68,7 +63,7 @@ export async function validateDeploymentID( // Case 5: '0x...' (32 bytes) try { - if (utils.isHexString(s, 32)) { + if (isHexString(s, 32)) { return type } } catch { @@ -281,11 +276,11 @@ export function isDeploymentWorthAllocatingTowards( deployment.protocolNetwork, ) case IndexingDecisionBasis.RULES: { - const stakedTokens = BigNumber.from(deployment.stakedTokens) - const signalledTokens = BigNumber.from(deployment.signalledTokens) - const avgQueryFees = BigNumber.from(deployment.queryFeesAmount) + const stakedTokens = deployment.stakedTokens + const signalledTokens = deployment.signalledTokens + const avgQueryFees = deployment.queryFeesAmount - if (deploymentRule.minStake && stakedTokens.gte(deploymentRule.minStake)) { + if (deploymentRule.minStake && stakedTokens >= BigInt(deploymentRule.minStake)) { return new AllocationDecision( deployment.id, deploymentRule, @@ -295,7 +290,7 @@ export function isDeploymentWorthAllocatingTowards( ) } else if ( deploymentRule.minSignal && - signalledTokens.gte(deploymentRule.minSignal) + signalledTokens >= BigInt(deploymentRule.minSignal) ) { return new AllocationDecision( deployment.id, @@ -306,7 +301,7 @@ export function isDeploymentWorthAllocatingTowards( ) } else if ( deploymentRule.minAverageQueryFees && - avgQueryFees.gte(deploymentRule.minAverageQueryFees) + avgQueryFees >= BigInt(deploymentRule.minAverageQueryFees) ) { return new AllocationDecision( deployment.id, diff --git a/packages/indexer-common/src/transactions.ts b/packages/indexer-common/src/transactions.ts index ba3db3309..52866935c 100644 --- a/packages/indexer-common/src/transactions.ts +++ b/packages/indexer-common/src/transactions.ts @@ -1,20 +1,18 @@ import { - BigNumber, BigNumberish, - ContractReceipt, - ContractTransaction, - providers, - utils, - Wallet, + HDNodeWallet, + parseUnits, + Provider, + TransactionReceipt, + TransactionRequest, + ContractTransactionResponse, + TransactionResponse, + toUtf8String, + FeeData, + Interface, + Result, } from 'ethers' -import { - Address, - Eventual, - Logger, - mutable, - NetworkContracts, - toAddress, -} from '@graphprotocol/common-ts' +import { Address, Eventual, Logger, mutable, toAddress } from '@graphprotocol/common-ts' import delay from 'delay' import { TransactionMonitoring } from './network-specification' import { IndexerError, indexerError, IndexerErrorCode } from './errors' @@ -22,19 +20,23 @@ import { TransactionConfig, TransactionType } from './types' import { SubgraphClient } from './subgraph-client' import gql from 'graphql-tag' import { sequentialTimerReduce } from './sequential-timer' +import { + GraphHorizonContracts, + SubgraphServiceContracts, +} from '@graphprotocol/toolshed/deployments' export class TransactionManager { - ethereum: providers.BaseProvider - wallet: Wallet + ethereum: Provider + wallet: HDNodeWallet paused: Eventual isOperator: Eventual specification: TransactionMonitoring - adjustedGasIncreaseFactor: BigNumber + adjustedGasIncreaseFactor: bigint adjustedBaseFeePerGasMax: number constructor( - ethereum: providers.BaseProvider, - wallet: Wallet, + ethereum: Provider, + wallet: HDNodeWallet, paused: Eventual, isOperator: Eventual, specification: TransactionMonitoring, @@ -44,7 +46,7 @@ export class TransactionManager { this.paused = paused this.isOperator = isOperator this.specification = specification - this.adjustedGasIncreaseFactor = utils.parseUnits( + this.adjustedGasIncreaseFactor = parseUnits( specification.gasIncreaseFactor.toString(), 3, ) @@ -53,10 +55,10 @@ export class TransactionManager { } async executeTransaction( - gasEstimation: () => Promise, - transaction: (gasLimit: BigNumberish) => Promise, + gasEstimation: () => Promise, + transaction: (gasLimit: BigNumberish) => Promise, logger: Logger, - ): Promise { + ): Promise { if (await this.paused.value()) { logger.info(`Network is paused, skipping this action`) return 'paused' @@ -68,14 +70,14 @@ export class TransactionManager { } let pending = true - let output: providers.TransactionReceipt | undefined = undefined + let output: TransactionReceipt | undefined = undefined const feeData = await this.waitForGasPricesBelowThreshold(logger) - const paddedGasLimit = Math.ceil((await gasEstimation()).toNumber() * 1.5) + const paddedGasLimit = Math.ceil(Number(await gasEstimation()) * 1.5) const txPromise = transaction(paddedGasLimit) - let tx = await txPromise - let txRequest: providers.TransactionRequest | undefined = undefined + let tx: TransactionResponse = await txPromise + let txRequest: TransactionRequest | undefined = undefined let txConfig: TransactionConfig = { attempt: 1, @@ -130,10 +132,14 @@ export class TransactionManager { this.specification.gasIncreaseTimeout, ) + if (receipt === null) { + throw indexerError(IndexerErrorCode.IE057) + } + if (receipt.status == 0) { const revertReason = await this.getRevertReason( logger, - txRequest as providers.TransactionRequest, + txRequest as TransactionRequest, ) if (revertReason === 'out of gas') { throw indexerError(IndexerErrorCode.IE050) @@ -159,14 +165,11 @@ export class TransactionManager { return output! } - async getRevertReason( - logger: Logger, - txRequest: providers.TransactionRequest, - ): Promise { + async getRevertReason(logger: Logger, txRequest: TransactionRequest): Promise { let revertReason = 'unknown' try { const code = await this.ethereum.call(txRequest) - revertReason = utils.toUtf8String(`0x${code.substr(138)}`) + revertReason = toUtf8String(`0x${code.substr(138)}`) } catch (e) { if (e.body.includes('out of gas')) { revertReason = 'out of gas' @@ -188,10 +191,12 @@ export class TransactionManager { }) if (error instanceof IndexerError) { if (error.code == IndexerErrorCode.IE050) { - txConfig.gasLimit = BigNumber.from(txConfig.gasLimit) - .mul(txConfig.gasBump) - .div(1000) - txConfig.nonce = BigNumber.from(txConfig.nonce).add(1) + if (txConfig.gasLimit) { + txConfig.gasLimit = (BigInt(txConfig.gasLimit) * txConfig.gasBump) / 1000n + } + if (txConfig.nonce) { + txConfig.nonce = txConfig.nonce + 1 + } } else if (error.code == IndexerErrorCode.IE051) { throw error } @@ -213,7 +218,9 @@ export class TransactionManager { 'Transaction nonce is too low. Try incrementing the nonce.', ) ) { - txConfig.nonce = BigNumber.from(txConfig.nonce).add(1) + if (txConfig.nonce) { + txConfig.nonce = txConfig.nonce + 1 + } } else if ( error.message.includes('Try increasing the fee') || error.message.includes('gas price supplied is too low') || @@ -221,24 +228,26 @@ export class TransactionManager { ) { // Transaction timed out or failed due to a low gas price estimation, bump gas price and retry if (txConfig.type === TransactionType.ZERO) { - txConfig.gasPrice = BigNumber.from(txConfig.gasPrice) - .mul(txConfig.gasBump) - .div(1000) + if (txConfig.gasPrice) { + txConfig.gasPrice = (BigInt(txConfig.gasPrice) * txConfig.gasBump) / 1000n + } } else if (txConfig.type == TransactionType.TWO) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - txConfig.maxFeePerGas = BigNumber.from(txConfig.maxFeePerGas) - .mul(txConfig.gasBump) - .div(1000) - txConfig.maxPriorityFeePerGas = BigNumber.from(txConfig.maxPriorityFeePerGas) - .mul(txConfig.gasBump) - .div(1000) + if (txConfig.maxFeePerGas) { + txConfig.maxFeePerGas = + (BigInt(txConfig.maxFeePerGas) * txConfig.gasBump) / 1000n + } + if (txConfig.maxPriorityFeePerGas) { + txConfig.maxPriorityFeePerGas = + (BigInt(txConfig.maxPriorityFeePerGas) * txConfig.gasBump) / 1000n + } } } } txConfig.attempt += 1 return txConfig } - async transactionType(data: providers.FeeData): Promise { + async transactionType(data: FeeData): Promise { if (data.maxPriorityFeePerGas && data.maxFeePerGas) { return TransactionType.TWO } else if (data.gasPrice) { @@ -249,28 +258,37 @@ export class TransactionManager { ) } } - async waitForGasPricesBelowThreshold(logger: Logger): Promise { + async waitForGasPricesBelowThreshold(logger: Logger): Promise { let attempt = 1 let aboveThreshold = true let feeData = { gasPrice: null, maxFeePerGas: null, maxPriorityFeePerGas: null, - } as providers.FeeData + } as { + gasPrice: bigint | null + maxFeePerGas: bigint | null + maxPriorityFeePerGas: bigint | null + } while (aboveThreshold) { - feeData = await this.ethereum.getFeeData() - const type = await this.transactionType(feeData) + const providerFeeData = await this.ethereum.getFeeData() + feeData = { + gasPrice: providerFeeData.gasPrice, + maxFeePerGas: providerFeeData.maxFeePerGas, + maxPriorityFeePerGas: providerFeeData.maxPriorityFeePerGas, + } + const type = await this.transactionType(providerFeeData) if (type === TransactionType.TWO) { // Type 0x02 transaction // This baseFeePerGas calculation is based off how maxFeePerGas is calculated in getFeeData() // https://github.com/ethers-io/ethers.js/blob/68229ac0aff790b083717dc73cd84f38d32a3926/packages/abstract-provider/src.ts/index.ts#L247 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const baseFeePerGas = feeData - .maxFeePerGas! // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - .sub(feeData.maxPriorityFeePerGas!) - .div(2) - if (baseFeePerGas.toNumber() >= this.adjustedBaseFeePerGasMax) { + const baseFeePerGas = + (feeData.maxFeePerGas! - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + feeData.maxPriorityFeePerGas!) / + 2n + if (Number(baseFeePerGas) >= this.adjustedBaseFeePerGasMax) { if (attempt === 1) { logger.warning( `Max base fee per gas has been reached, waiting until the base fee falls below to resume transaction execution.`, @@ -279,7 +297,7 @@ export class TransactionManager { } else { logger.info(`Base gas fee per gas estimation still above max threshold`, { maxBaseFeePerGas: this.specification.baseFeePerGasMax, - baseFeePerGas: baseFeePerGas.toNumber(), + baseFeePerGas: Number(baseFeePerGas), priceEstimateAttempt: attempt, }) } @@ -292,19 +310,19 @@ export class TransactionManager { } else if (type === TransactionType.ZERO) { // Legacy transaction type // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - if (feeData.gasPrice!.toNumber() >= this.adjustedBaseFeePerGasMax) { + if (Number(feeData.gasPrice!) >= this.adjustedBaseFeePerGasMax) { if (attempt === 1) { logger.warning( `Max gas price has been reached, waiting until gas price estimates fall below to resume transaction execution.`, { baseFeePerGasMax: this.specification.baseFeePerGasMax, - currentGasPriceEstimate: feeData.gasPrice!.toNumber(), + currentGasPriceEstimate: Number(feeData.gasPrice!), }, ) } else { logger.info(`Gas price estimation still above max threshold`, { baseFeePerGasMax: this.specification.baseFeePerGasMax, - currentGasPriceEstimate: feeData.gasPrice!.toNumber(), + currentGasPriceEstimate: Number(feeData.gasPrice!), priceEstimateAttempt: attempt, }) } @@ -315,12 +333,12 @@ export class TransactionManager { } } } - return feeData + return feeData as FeeData } async monitorNetworkPauses( logger: Logger, - contracts: NetworkContracts, + contracts: GraphHorizonContracts & SubgraphServiceContracts, networkSubgraph: SubgraphClient, ): Promise> { return sequentialTimerReduce( @@ -355,7 +373,7 @@ export class TransactionManager { return currentlyPaused } }, - await contracts.controller.paused(), + await contracts.Controller.paused(), ).map((paused) => { logger.info(paused ? `Network paused` : `Network active`) return paused @@ -364,9 +382,9 @@ export class TransactionManager { async monitorIsOperator( logger: Logger, - contracts: NetworkContracts, + contracts: GraphHorizonContracts & SubgraphServiceContracts, indexerAddress: Address, - wallet: Wallet, + wallet: HDNodeWallet, ): Promise> { // If indexer and operator address are identical, operator status is // implicitly granted => we'll never have to check again @@ -382,7 +400,7 @@ export class TransactionManager { }, async (isOperator) => { try { - return await contracts.staking.isOperator(wallet.address, indexerAddress) + return await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress) } catch (err) { logger.warn( `Failed to check operator status for indexer, assuming it has not changed`, @@ -391,7 +409,7 @@ export class TransactionManager { return isOperator } }, - await contracts.staking.isOperator(wallet.address, indexerAddress), + await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress), ).map((isOperator) => { logger.info( isOperator @@ -404,15 +422,20 @@ export class TransactionManager { findEvent( eventType: string, - contractInterface: utils.Interface, + contractInterface: Interface, logKey: string, logValue: string, - receipt: ContractReceipt, + receipt: TransactionReceipt, logger: Logger, - ): utils.Result | undefined { - const events: Event[] | providers.Log[] = receipt.events || receipt.logs - const decodedEvents: utils.Result[] = [] - const expectedTopic = contractInterface.getEventTopic(eventType) + ): Result | undefined { + const events = receipt.logs + const decodedEvents: Result[] = [] + const expectedTopic = contractInterface.getEvent(eventType)?.topicHash + + // TODO HORIZON - throw indexer error here + if (!expectedTopic) { + throw new Error(`Event type ${eventType} not found in contract interface`) + } const result = events .filter((event) => event.topics.includes(expectedTopic)) diff --git a/packages/indexer-common/src/types.ts b/packages/indexer-common/src/types.ts index cfd62747a..8b142b5f6 100644 --- a/packages/indexer-common/src/types.ts +++ b/packages/indexer-common/src/types.ts @@ -1,5 +1,5 @@ import { SubgraphDeploymentID } from '@graphprotocol/common-ts' -import { BigNumber, providers } from 'ethers' +import { TransactionRequest } from 'ethers' export enum AllocationManagementMode { AUTO = 'auto', @@ -60,9 +60,9 @@ export interface Subgraph { export interface SubgraphDeployment { id: SubgraphDeploymentID deniedAt: number - stakedTokens: BigNumber - signalledTokens: BigNumber - queryFeesAmount: BigNumber + stakedTokens: bigint + signalledTokens: bigint + queryFeesAmount: bigint protocolNetwork: string } @@ -73,13 +73,13 @@ export interface TransferredSubgraphDeployment { idOnL1: string idOnL2: string startedTransferToL2L: boolean - startedTransferToL2At: BigNumber - startedTransferToL2AtBlockNumber: BigNumber + startedTransferToL2At: bigint + startedTransferToL2AtBlockNumber: bigint startedTransferToL2AtTx: string transferredToL2: boolean | null - transferredToL2At: BigNumber | null + transferredToL2At: bigint | null transferredToL2AtTx: string | null - transferredToL2AtBlockNumber: BigNumber | null + transferredToL2AtBlockNumber: bigint | null ipfsHash: string protocolNetwork: string ready: boolean | null @@ -90,9 +90,9 @@ export enum TransactionType { TWO, } -export interface TransactionConfig extends providers.TransactionRequest { +export interface TransactionConfig extends TransactionRequest { attempt: number - gasBump: BigNumber + gasBump: bigint type: TransactionType } diff --git a/packages/indexer-common/src/utils.ts b/packages/indexer-common/src/utils.ts index f9c4b014d..42ed703ff 100644 --- a/packages/indexer-common/src/utils.ts +++ b/packages/indexer-common/src/utils.ts @@ -1,9 +1,10 @@ -import { Wallet, utils } from 'ethers' import { - BaseProvider, + Provider, JsonRpcProvider, getDefaultProvider, -} from '@ethersproject/providers' + formatEther, + HDNodeWallet, +} from 'ethers' import { Logger, Metrics } from '@graphprotocol/common-ts' import { indexerError, IndexerErrorCode } from './errors' import { DocumentNode, SelectionSetNode, Kind } from 'graphql' @@ -21,7 +22,7 @@ export function nullPassThrough(fn: (x: T) => U): (x: T | null) => U | nul return (x: T | null) => (x === null ? null : fn(x)) } -export function getTestProvider(network: string): BaseProvider { +export function getTestProvider(network: string): Provider { const testJsonRpcProviderUrl = process.env.INDEXER_TEST_JRPC_PROVIDER_URL if (testJsonRpcProviderUrl) { return new JsonRpcProvider(testJsonRpcProviderUrl) @@ -40,7 +41,7 @@ const registerMetrics = (metrics: Metrics, networkIdentifier: string) => ({ export async function monitorEthBalance( logger: Logger, - wallet: Wallet, + wallet: HDNodeWallet, metrics: Metrics, networkIdentifier: string, ): Promise { @@ -52,8 +53,8 @@ export async function monitorEthBalance( sequentialTimerMap({ logger, milliseconds: 120_000 }, async () => { try { - const balance = await wallet.getBalance() - const eth = parseFloat(utils.formatEther(balance)) + const balance = await wallet.provider!.getBalance(wallet.address) + const eth = parseFloat(formatEther(balance)) balanceMetrics.operatorEthBalance.set(eth) logger.info('Current operator ETH balance', { balance: eth, diff --git a/yarn.lock b/yarn.lock index 1536852f1..d18e60837 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -10,178 +15,114 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0": - version "7.22.13" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz" - integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== - dependencies: - "@babel/highlight" "^7.22.13" - chalk "^2.4.2" - -"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.2": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== dependencies: - "@babel/highlight" "^7.24.2" - picocolors "^1.0.0" + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.23.5": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" - integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== +"@babel/compat-data@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.2.tgz#4183f9e642fd84e74e3eea7ffa93a412e3b102c9" + integrity sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ== "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.5.tgz#15ab5b98e101972d171aeef92ac70d8d6718f06a" - integrity sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6" + integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.2" - "@babel/generator" "^7.24.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.24.5" - "@babel/helpers" "^7.24.5" - "@babel/parser" "^7.24.5" - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.5" - "@babel/types" "^7.24.5" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helpers" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.24.5", "@babel/generator@^7.7.2": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.5.tgz#e5afc068f932f05616b66713e28d0f04e99daeb3" - integrity sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA== +"@babel/generator@^7.27.1", "@babel/generator@^7.7.2": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230" + integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w== dependencies: - "@babel/types" "^7.24.5" + "@babel/parser" "^7.27.1" + "@babel/types" "^7.27.1" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" + jsesc "^3.0.2" -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== +"@babel/helper-compilation-targets@^7.27.1": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.24.3": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" - integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== - dependencies: - "@babel/types" "^7.24.0" - -"@babel/helper-module-transforms@^7.23.3", "@babel/helper-module-transforms@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz#ea6c5e33f7b262a0ae762fd5986355c45f54a545" - integrity sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.24.3" - "@babel/helper-simple-access" "^7.24.5" - "@babel/helper-split-export-declaration" "^7.24.5" - "@babel/helper-validator-identifier" "^7.24.5" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz#a924607dd254a65695e5bd209b98b902b3b2f11a" - integrity sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ== - -"@babel/helper-simple-access@^7.22.5", "@babel/helper-simple-access@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz#50da5b72f58c16b07fbd992810be6049478e85ba" - integrity sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ== - dependencies: - "@babel/types" "^7.24.5" - -"@babel/helper-split-export-declaration@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz#b9a67f06a46b0b339323617c8c6213b9055a78b6" - integrity sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q== - dependencies: - "@babel/types" "^7.24.5" - -"@babel/helper-string-parser@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" - integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-identifier@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" - integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.5.tgz#fedeb87eeafa62b621160402181ad8585a22a40a" - integrity sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q== - dependencies: - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.5" - "@babel/types" "^7.24.5" - -"@babel/highlight@^7.22.13": - version "7.22.20" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz" - integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/highlight@^7.24.2": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e" - integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw== +"@babel/helper-module-transforms@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f" + integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g== dependencies: - "@babel/helper-validator-identifier" "^7.24.5" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.27.1" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0", "@babel/parser@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.5.tgz#4a4d5ab4315579e5398a82dcf636ca80c3392790" - integrity sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg== +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4" + integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ== + dependencies: + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.27.1", "@babel/parser@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" + integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw== + dependencies: + "@babel/types" "^7.27.1" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -197,14 +138,28 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -219,13 +174,13 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" - integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" + integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -239,7 +194,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -267,7 +222,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== @@ -275,54 +237,49 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844" - integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" + integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-transform-modules-commonjs@^7.23.3": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" - integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== - dependencies: - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-simple-access" "^7.22.5" - -"@babel/template@^7.22.15", "@babel/template@^7.24.0", "@babel/template@^7.3.3": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" - integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - -"@babel/traverse@^7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.5.tgz#972aa0bc45f16983bf64aa1f877b2dd0eea7e6f8" - integrity sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA== - dependencies: - "@babel/code-frame" "^7.24.2" - "@babel/generator" "^7.24.5" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.24.5" - "@babel/parser" "^7.24.5" - "@babel/types" "^7.24.5" + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz#8e44ed37c2787ecc23bdc367f49977476614e832" + integrity sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw== + dependencies: + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/template@^7.27.1", "@babel/template@^7.3.3": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291" + integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.27.1" + "@babel/parser" "^7.27.1" + "@babel/template" "^7.27.1" + "@babel/types" "^7.27.1" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.24.5", "@babel/types@^7.3.3": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7" - integrity sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.3.3": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" + integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== dependencies: - "@babel/helper-string-parser" "^7.24.1" - "@babel/helper-validator-identifier" "^7.24.5" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -342,16 +299,16 @@ "@cspotcode/source-map-consumer" "0.8.0" "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + version "4.7.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" + integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== dependencies: - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.3" "@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== "@eslint/eslintrc@^2.1.2", "@eslint/eslintrc@^2.1.4": version "2.1.4" @@ -378,384 +335,218 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.55.0.tgz#b721d52060f369aa259cf97392403cb9ce892ec6" integrity sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA== -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" +"@ethereumjs/rlp@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-5.0.2.tgz#c89bd82f2f3bec248ab2d517ae25f5bbc4aac842" + integrity sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA== + +"@ethereumjs/util@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-9.1.0.tgz#75e3898a3116d21c135fa9e29886565609129bce" + integrity sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog== + dependencies: + "@ethereumjs/rlp" "^5.0.2" + ethereum-cryptography "^2.2.1" + +"@ethersproject/abi@^5.1.2": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.8.0.tgz#e79bb51940ac35fe6f3262d7fe2cdb25ad5f07d9" + integrity sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q== + dependencies: + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/abstract-provider@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz#7581f9be601afa1d02b95d26b9d9840926a35b0c" + integrity sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/networks" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/web" "^5.8.0" + +"@ethersproject/abstract-signer@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz#8d7417e95e4094c1797a9762e6789c7356db0754" + integrity sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA== + dependencies: + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + +"@ethersproject/address@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.8.0.tgz#3007a2c352eee566ad745dca1dbbebdb50a6a983" + integrity sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + +"@ethersproject/base64@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.8.0.tgz#61c669c648f6e6aad002c228465d52ac93ee83eb" + integrity sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ== + dependencies: + "@ethersproject/bytes" "^5.8.0" + +"@ethersproject/bignumber@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.8.0.tgz#c381d178f9eeb370923d389284efa19f69efa5d7" + integrity sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" +"@ethersproject/bytes@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.8.0.tgz#9074820e1cac7507a34372cadeb035461463be34" + integrity sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/constants@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.8.0.tgz#12f31c2f4317b113a4c19de94e50933648c90704" + integrity sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + +"@ethersproject/hash@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.8.0.tgz#b8893d4629b7f8462a90102572f8cd65a0192b4c" + integrity sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/keccak256@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.8.0.tgz#d2123a379567faf2d75d2aaea074ffd4df349e6a" + integrity sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng== + dependencies: + "@ethersproject/bytes" "^5.8.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== +"@ethersproject/logger@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.8.0.tgz#f0232968a4f87d29623a0481690a2732662713d6" + integrity sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA== -"@ethersproject/networks@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.0.tgz" - integrity sha512-MG6oHSQHd4ebvJrleEQQ4HhVu8Ichr0RDYEfHzsVAVjHNM+w36x9wp9r+hf1JstMXtseXDtkiVoARAG6M959AA== +"@ethersproject/networks@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.8.0.tgz#8b4517a3139380cba9fb00b63ffad0a979671fde" + integrity sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg== dependencies: - "@ethersproject/logger" "^5.7.0" + "@ethersproject/logger" "^5.8.0" -"@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.0.tgz" - integrity sha512-+TTrrINMzZ0aXtlwO/95uhAggKm4USLm1PbeCBR/3XZ7+Oey+3pMyddzZEyRhizHpy1HXV0FRWRMI1O3EGYibA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" +"@ethersproject/properties@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.8.0.tgz#405a8affb6311a49a91dabd96aeeae24f477020e" + integrity sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw== + dependencies: + "@ethersproject/logger" "^5.8.0" -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== +"@ethersproject/rlp@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.8.0.tgz#5a0d49f61bc53e051532a5179472779141451de5" + integrity sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q== dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/signing-key@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.8.0.tgz#9797e02c717b68239c6349394ea85febf8893119" + integrity sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" bn.js "^5.2.1" - elliptic "6.5.4" + elliptic "6.6.1" hash.js "1.1.7" -"@ethersproject/solidity@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.0.tgz" - integrity sha512-ApHcbbj+muRASVDSCl/tgxaH2LBkRMEYfLOLVa0COipx0+nlu0QKet7U2lEg0vdkh8XRSLf2nd1f1Uk9SrVSGA== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/web@^5.7.0": - version "5.7.1" - resolved "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": - version "5.7.0" - resolved "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" +"@ethersproject/strings@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.8.0.tgz#ad79fafbf0bd272d9765603215ac74fd7953908f" + integrity sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/transactions@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.8.0.tgz#1e518822403abc99def5a043d1c6f6fe0007e46b" + integrity sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg== + dependencies: + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + +"@ethersproject/web@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.8.0.tgz#3e54badc0013b7a801463a7008a87988efce8a37" + integrity sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw== + dependencies: + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" "@fastify/ajv-compiler@^1.0.0": version "1.1.0" - resolved "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz#5ce80b1fc8bebffc8c5ba428d5e392d0f9ed10a1" integrity sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg== dependencies: ajv "^6.12.6" +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + "@gar/promisify@^1.1.3": version "1.1.3" - resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@graphprotocol/common-ts@2.0.11": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@graphprotocol/common-ts/-/common-ts-2.0.11.tgz#29f92e7a9666a6b8baccd15e51281d87658978c9" - integrity sha512-WtQGYMGVwaXDIli+OCAZUSqh8+ql9THzjztqvLGeSbAIPKxysvej9vua0voMguqEkI/RyEEMBajelodMzzZlEw== +"@graphprotocol/common-ts@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@graphprotocol/common-ts/-/common-ts-3.0.1.tgz#c20428a5c2c7cf8f6631fea9fc304e203b0e7483" + integrity sha512-VtNFdTaZsS9vR/IX3aav7Dk6FUT+Lplmfp3d00ErjNf87kj2whT2LMG3tcZta/czcTi42Z9SOX95GsPJSxbM7Q== dependencies: - "@graphprotocol/contracts" "5.3.3" "@graphprotocol/pino-sentry-simple" "0.7.1" "@urql/core" "3.1.0" "@urql/exchange-execute" "2.1.0" @@ -763,7 +554,7 @@ bs58 "5.0.0" cors "2.8.5" cross-fetch "4.0.0" - ethers "5.7.0" + ethers "6.13.7" express "4.18.2" graphql "16.8.0" graphql-tag "2.12.6" @@ -777,17 +568,19 @@ prom-client "14.2.0" sequelize "6.33.0" -"@graphprotocol/contracts@5.3.3": - version "5.3.3" - resolved "https://registry.npmjs.org/@graphprotocol/contracts/-/contracts-5.3.3.tgz" - integrity sha512-fmFSKr+VDinWWotj2q/Ztn92PppcRrYXeO/62gLgkLos/DcYa7bGWKbcOWyMUw0vsUvXxk6QAtr5o/LG3yQ1WQ== - dependencies: - console-table-printer "^2.11.1" - ethers "^5.6.0" +"@graphprotocol/contracts@^7.1.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@graphprotocol/contracts/-/contracts-7.1.2.tgz#919cf6747d25cb52855d01be6582c06695ae3b83" + integrity sha512-t8o0nA+cs5HEKLxjaV0zELBtDLAPm6hoXi0o5tnpw7vigyMPoP92QQkVfbjAt9eMnkC7/AyGRWOMBfAZV9l8Og== + +"@graphprotocol/horizon@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@graphprotocol/horizon/-/horizon-0.3.2.tgz#a236fe9f114d62346a3068edbb7631f9f30d67c8" + integrity sha512-0XHbLPk4su0h0i0Oc4SkoiH2+7fx7eF3DsM7GvExOtNRDe258lXs2KrHsp2Oiv19HOFy4mryb6E2mdB/ijRhbQ== "@graphprotocol/pino-sentry-simple@0.7.1": version "0.7.1" - resolved "https://registry.npmjs.org/@graphprotocol/pino-sentry-simple/-/pino-sentry-simple-0.7.1.tgz" + resolved "https://registry.yarnpkg.com/@graphprotocol/pino-sentry-simple/-/pino-sentry-simple-0.7.1.tgz#ac08b978bfa33178b9e809f53ae0983ff5f724d8" integrity sha512-iccKFdFBjarSp8/liXuK1EtGq8Vwn118tqymbOJBxblecRsi4rOebk63qnL+dK/a0IvxH6h2+RjjWDbRt7UsUA== dependencies: "@sentry/node" "^5.21.1" @@ -795,6 +588,26 @@ split2 "^3.1.1" through2 "^3.0.1" +"@graphprotocol/subgraph-service@^0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.3.4.tgz#38929c04d03ad06823f9a867c8a4aef4c7f581e7" + integrity sha512-POepREau0ExCz4ZJrlhzIS3RigEuzlbp/xlurpHkgaOn97cFAv3x9ZaE5a9uwh1azRm3Djz8RUBmXpqmwoK9NA== + +"@graphprotocol/toolshed@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.3.2.tgz#3808687e4bf16373a1ec363fc5cb43ec7977023c" + integrity sha512-bp7RWbcUZQcZW6Wn4EcN5DLYFO0hLDGXTLWeahq1HdkLEhcyHiTBqKmZKV98OG4TPJPJ7piCvsoJLuGj/btyRw== + dependencies: + "@graphprotocol/contracts" "^7.1.2" + "@graphprotocol/horizon" "^0.3.2" + "@graphprotocol/subgraph-service" "^0.3.4" + "@nomicfoundation/hardhat-ethers" "3.0.8" + debug "^4.4.0" + ethers "6.13.7" + glob "^11.0.1" + hardhat "^2.22.16" + json5 "^2.2.3" + "@humanwhocodes/config-array@^0.11.11", "@humanwhocodes/config-array@^0.11.13": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -816,17 +629,17 @@ "@hutson/parse-repository-url@^3.0.0": version "3.0.2" - resolved "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== "@iarna/toml@2.2.5": version "2.2.5" - resolved "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== "@isaacs/cliui@^8.0.2": version "8.0.2" - resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== dependencies: string-width "^5.1.2" @@ -838,7 +651,7 @@ "@isaacs/string-locale-compare@^1.1.0": version "1.1.0" - resolved "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ== "@istanbuljs/load-nyc-config@^1.0.0": @@ -1050,9 +863,9 @@ chalk "^4.0.0" "@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== dependencies: "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" @@ -1069,9 +882,9 @@ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" @@ -1083,7 +896,7 @@ "@lerna/add@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/add/-/add-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/add/-/add-6.1.0.tgz#0f09495c5e1af4c4f316344af34b6d1a91b15b19" integrity sha512-f2cAeS1mE/p7QvSRn5TCgdUXw6QVbu8PeRxaTOxTThhTdJIWdXZfY00QjAsU6jw1PdYXK1qGUSwWOPkdR16mBg== dependencies: "@lerna/bootstrap" "6.1.0" @@ -1099,7 +912,7 @@ "@lerna/bootstrap@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-6.1.0.tgz#81738f32cd431814c9943dfffe28752587d90830" integrity sha512-aDxKqgxexVj/Z0B1aPu7P1iPbPqhk1FPkl/iayCmPlkAh90pYEH0uVytGzi1hFB5iXEfG7Pa6azGQywUodx/1g== dependencies: "@lerna/command" "6.1.0" @@ -1127,7 +940,7 @@ "@lerna/changed@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/changed/-/changed-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-6.1.0.tgz#4fa480cbb0e7106ea9dad30d315e953975118d06" integrity sha512-p7C2tf1scmvoUC1Osck/XIKVKXAQ8m8neL8/rfgKSYsvUVjsOB1LbF5HH1VUZntE6S4OxkRxUQGkAHVf5xrGqw== dependencies: "@lerna/collect-updates" "6.1.0" @@ -1137,7 +950,7 @@ "@lerna/check-working-tree@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-6.1.0.tgz#b8970fd27a26449b12456d5d0ece60477aa54e15" integrity sha512-hSciDmRqsNPevMhAD+SYbnhjatdb7UUu9W8vTyGtUXkrq2xtRZU0vAOgqovV8meirRkbC41pZePYKqyQtF0y3w== dependencies: "@lerna/collect-uncommitted" "6.1.0" @@ -1146,7 +959,7 @@ "@lerna/child-process@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/child-process/-/child-process-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-6.1.0.tgz#6361f7945cd5b36e983f819de3cd91c315707302" integrity sha512-jhr3sCFeps6Y15SCrWEPvqE64i+QLOTSh+OzxlziCBf7ZEUu7sF0yA4n5bAqw8j43yCKhhjkf/ZLYxZe+pnl3Q== dependencies: chalk "^4.1.0" @@ -1155,7 +968,7 @@ "@lerna/clean@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/clean/-/clean-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-6.1.0.tgz#1114fd90ad82438123726e2493d3550e73abebbc" integrity sha512-LRK2hiNUiBhPe5tmJiefOVpkaX2Yob0rp15IFNIbuteRWUJg0oERFQo62WvnxwElfzKSOhr8OGuEq/vN4bMrRA== dependencies: "@lerna/command" "6.1.0" @@ -1169,7 +982,7 @@ "@lerna/cli@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/cli/-/cli-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-6.1.0.tgz#41214331fa4c1ea5f41125befdd81b009fe12640" integrity sha512-p4G/OSPIrHiNkEl8bXrQdFOh4ORAZp2+ljvbXmAxpdf2qmopaUdr+bZYtIAxd+Z42SxRnDNz9IEyR0kOsARRQQ== dependencies: "@lerna/global-options" "6.1.0" @@ -1179,7 +992,7 @@ "@lerna/collect-uncommitted@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/collect-uncommitted/-/collect-uncommitted-6.1.0.tgz#b6ffd7adda24d73b70304210967d3518caa3529d" integrity sha512-VvWvqDZG+OiF4PwV4Ro695r3+8ty4w+11Bnq8tbsbu5gq8qZiam8Fkc/TQLuNNqP0SPi4qmMPaIzWvSze3SmDg== dependencies: "@lerna/child-process" "6.1.0" @@ -1188,7 +1001,7 @@ "@lerna/collect-updates@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-6.1.0.tgz#75fcc0733b5a9ac318a6484b890aa4061b7859c2" integrity sha512-dgH7kgstwCXFctylQ4cxuCmhwSIE6VJZfHdh2bOaLuncs6ATMErKWN/mVuFHuUWEqPDRyy5Ky40Cu9S40nUq5w== dependencies: "@lerna/child-process" "6.1.0" @@ -1199,7 +1012,7 @@ "@lerna/command@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/command/-/command-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/command/-/command-6.1.0.tgz#bcb12516f2c181822b3b5be46c18eadc9b61e885" integrity sha512-OnMqBDaEBY0C8v9CXIWFbGGKgsiUtZrnKVvQRbupMSZDKMpVGWIUd3X98Is9j9MAmk1ynhBMWE9Fwai5ML/mcA== dependencies: "@lerna/child-process" "6.1.0" @@ -1215,7 +1028,7 @@ "@lerna/conventional-commits@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-6.1.0.tgz#1157bb66d84d48880dc5c5026d743cedf0f47094" integrity sha512-Tipo3cVr8mNVca4btzrCIzct59ZJWERT8/ZCZ/TQWuI4huUJZs6LRofLtB0xsGJAVZ7Vz2WRXAeH4XYgeUxutQ== dependencies: "@lerna/validation-error" "6.1.0" @@ -1231,7 +1044,7 @@ "@lerna/create-symlink@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-6.1.0.tgz#d4260831f5d10abc0c70f0a8f39bea91db87e640" integrity sha512-ulMa5OUJEwEWBHSgCUNGxrcsJllq1YMYWqhufvIigmMPJ0Zv3TV1Hha5i2MsqLJAakxtW0pNuwdutkUTtUdgxQ== dependencies: cmd-shim "^5.0.0" @@ -1240,7 +1053,7 @@ "@lerna/create@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/create/-/create-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/create/-/create-6.1.0.tgz#cde219da46a7c5062c558366b4ffce2134f13845" integrity sha512-ZqlknXu0L29cV5mcfNgBLl+1RbKTWmNk8mj545zgXc7qQDgmrY+EVvrs8Cirey8C7bBpVkzP7Brzze0MSoB4rQ== dependencies: "@lerna/child-process" "6.1.0" @@ -1262,7 +1075,7 @@ "@lerna/describe-ref@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-6.1.0.tgz#60f0b8297b912aa5fe5e6ab8ef6c4127813681a7" integrity sha512-0RQAYnxBaMz1SrEb/rhfR+8VeZx5tvCNYKRee5oXIDZdQ2c6/EPyrKCp3WcqiuOWY50SfGOVfxJEcxpK8Y3FNA== dependencies: "@lerna/child-process" "6.1.0" @@ -1270,7 +1083,7 @@ "@lerna/diff@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/diff/-/diff-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-6.1.0.tgz#bfa9bc35894d88a33fa0a3a5787082dea45d8cb2" integrity sha512-GhP+jPDbcp9QcAMSAjFn4lzM8MKpLR1yt5jll+zUD831U1sL0I5t8HUosFroe5MoRNffEL/jHuI3SbC3jjqWjQ== dependencies: "@lerna/child-process" "6.1.0" @@ -1280,7 +1093,7 @@ "@lerna/exec@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/exec/-/exec-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-6.1.0.tgz#a2d165576471ff61e33c49952d40a5dbc36fc78f" integrity sha512-Ej6WlPHXLF6hZHsfD+J/dxeuTrnc0HIfIXR1DU//msHW5RNCdi9+I7StwreCAQH/dLEsdBjPg5chNmuj2JLQRg== dependencies: "@lerna/child-process" "6.1.0" @@ -1293,7 +1106,7 @@ "@lerna/filter-options@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-6.1.0.tgz#f4ee65d0db0273ce490ce6c72c9dbb1d23268ca6" integrity sha512-kPf92Z7uLsR6MUiXnyXWebaUWArLa15wLfpfTwIp5H3MNk1lTbuG7QnrxE7OxQj+ozFmBvXeV9fuwfLsYTfmOw== dependencies: "@lerna/collect-updates" "6.1.0" @@ -1303,7 +1116,7 @@ "@lerna/filter-packages@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-6.1.0.tgz#1ddac63a6ffdf5f058d206be5adfb39ad7aaf4f9" integrity sha512-zW2avsZHs/ITE/37AEMhegGVHjiD0rgNk9bguNDfz6zaPa90UaW6PWDH6Tf4ThPRlbkl2Go48N3bFYHYSJKbcw== dependencies: "@lerna/validation-error" "6.1.0" @@ -1312,14 +1125,14 @@ "@lerna/get-npm-exec-opts@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-6.1.0.tgz#22351e2ebc4adbef21ca4b86187278e15e4cb38a" integrity sha512-10Pdf+W0z7RT34o0SWlf+WVzz2/WbnTIJ1tQqXvXx6soj2L/xGLhOPvhJiKNtl4WlvUiO/zQ91yb83ESP4TZaA== dependencies: npmlog "^6.0.2" "@lerna/get-packed@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-6.1.0.tgz#b6d1c1dd1e068212e784b8dfc2e5fe64741ea8db" integrity sha512-lg0wPpV0wPekcD0mebJp619hMxsOgbZDOH5AkL/bCR217391eha0iPhQ0dU/G0Smd2vv6Cg443+J5QdI4LGRTg== dependencies: fs-extra "^9.1.0" @@ -1328,7 +1141,7 @@ "@lerna/github-client@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/github-client/-/github-client-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-6.1.0.tgz#cd33743e4529a0b822ae6716cb4b981e1d8ffe8f" integrity sha512-+/4PtDgsjt0VRRZtOCN2Piyu0asU/16gSZZy/opVb8dlT44lTrH/ZghrJLE4tSL8Nuv688kx0kSgbUG8BY54jQ== dependencies: "@lerna/child-process" "6.1.0" @@ -1339,7 +1152,7 @@ "@lerna/gitlab-client@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/gitlab-client/-/gitlab-client-6.1.0.tgz#bbcbf80d937e5980798ac1e0edd1f769101057d8" integrity sha512-fUI/ppXzxJafN9ceSl+FDgsYvu3iTsO6UW0WTD63pS32CfM+PiCryLQHzuc4RkyVW8WQH3aCR/GbaKCqbu52bw== dependencies: node-fetch "^2.6.1" @@ -1347,12 +1160,12 @@ "@lerna/global-options@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/global-options/-/global-options-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-6.1.0.tgz#268e1de924369102e47babd9288086764ec6f9e6" integrity sha512-1OyJ/N1XJh3ZAy8S20c6th9C4yBm/k3bRIdC+z0XxpDaHwfNt8mT9kUIDt6AIFCUvVKjSwnIsMHwhzXqBnwYSA== "@lerna/has-npm-version@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-6.1.0.tgz#a5d960213d1a7ca5374eb3c551a17b322b9a9e62" integrity sha512-up5PVuP6BmKQ5/UgH/t2c5B1q4HhjwW3/bqbNayX6V0qNz8OijnMYvEUbxFk8fOdeN41qVnhAk0Tb5kbdtYh2A== dependencies: "@lerna/child-process" "6.1.0" @@ -1360,7 +1173,7 @@ "@lerna/import@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/import/-/import-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/import/-/import-6.1.0.tgz#1c64281e3431c43c9cd140b66a6a51427afe7095" integrity sha512-xsBhiKLUavATR32dAFL+WFY0yuab0hsM1eztKtRKk4wy7lSyxRfA5EIUcNCsLXx2xaDOKoMncCTXgNcpeYuqcQ== dependencies: "@lerna/child-process" "6.1.0" @@ -1374,7 +1187,7 @@ "@lerna/info@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/info/-/info-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/info/-/info-6.1.0.tgz#a5d66a9c1f18398dc020a6f6073c399013081587" integrity sha512-CsrWdW/Wyb4kcvHSnrsm7KYWFvjUNItu+ryeyWBZJtWYQOv45jNmWix6j2L4/w1+mMlWMjsfLmBscg82UBrF5w== dependencies: "@lerna/command" "6.1.0" @@ -1383,7 +1196,7 @@ "@lerna/init@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/init/-/init-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/init/-/init-6.1.0.tgz#b178775693b9c38c0f3fe3300eeb574cf76e0297" integrity sha512-z8oUeVjn+FQYAtepAw6G47cGodLyBAyNoEjO3IsJjQLWE1yH3r83L2sjyD/EckgR3o2VTEzrKo4ArhxLp2mNmg== dependencies: "@lerna/child-process" "6.1.0" @@ -1395,7 +1208,7 @@ "@lerna/link@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/link/-/link-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/link/-/link-6.1.0.tgz#f6f0cfd0b02aecdeb304ce614e4e4e89fe0a3ad5" integrity sha512-7OD2lYNQHl6Kl1KYmplt8KoWjVHdiaqpYqwD38AwcB09YN58nGmo4aJgC12Fdx8DSNjkumgM0ROg/JOjMCTIzQ== dependencies: "@lerna/command" "6.1.0" @@ -1407,7 +1220,7 @@ "@lerna/list@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/list/-/list-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/list/-/list-6.1.0.tgz#a7625bceb5224c4bf1154e715c07ea29f9698bac" integrity sha512-7/g2hjizkvVnBGpVm+qC7lUFGhZ/0GIMUbGQwnE6yXDGm8yP9aEcNVkU4JGrDWW+uIklf9oodnMHaLXd/FJe6Q== dependencies: "@lerna/command" "6.1.0" @@ -1417,7 +1230,7 @@ "@lerna/listable@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/listable/-/listable-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-6.1.0.tgz#2510045fde7bc568b18172a5d24372a719bb5c4c" integrity sha512-3KZ9lQ9AtNfGNH/mYJYaMKCiF2EQvLLBGYkWHeIzIs6foegcZNXe0Cyv3LNXuo5WslMNr5RT4wIgy3BOoAxdtg== dependencies: "@lerna/query-graph" "6.1.0" @@ -1426,7 +1239,7 @@ "@lerna/log-packed@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/log-packed/-/log-packed-6.1.0.tgz#18ae946e8b7881f2fc5b973cc6682cc599b1759b" integrity sha512-Sq2HZJAcPuoNeEHeIutcPYQCyWBxLyVGvEhgsP3xTe6XkBGQCG8piCp9wX+sc2zT+idPdpI6qLqdh85yYIMMhA== dependencies: byte-size "^7.0.0" @@ -1436,7 +1249,7 @@ "@lerna/npm-conf@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-6.1.0.tgz#79697260c9d14ffb9d892927f37fcde75b89ec58" integrity sha512-+RD3mmJe9XSQj7Diibs0+UafAHPcrFCd29ODpDI+tzYl4MmYZblfrlL6mbSCiVYCZQneQ8Uku3P0r+DlbYBaFw== dependencies: config-chain "^1.1.12" @@ -1444,7 +1257,7 @@ "@lerna/npm-dist-tag@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-6.1.0.tgz#29f843aa628687a29dc3a9b905dd3002db7a3820" integrity sha512-1zo+Yww/lvWJWZnEXpke9dZSb5poDzhUM/pQNqAQYSlbZ96o18SuCR6TEi5isMPiw63Aq1MMzbUqttQfJ11EOA== dependencies: "@lerna/otplease" "6.1.0" @@ -1454,7 +1267,7 @@ "@lerna/npm-install@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-6.1.0.tgz#b75d1f152540a144bd6c81586a9f6010ed7f3046" integrity sha512-1SHmOHZA1YJuUctLQBRjA2+yMp+UNYdOBsFb3xUVT7MjWnd1Zl0toT3jxGu96RNErD9JKkk/cGo/Aq+DU3s9pg== dependencies: "@lerna/child-process" "6.1.0" @@ -1467,7 +1280,7 @@ "@lerna/npm-publish@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-6.1.0.tgz#8fe561e639e6a06380354271aeca7cbc39acf7dd" integrity sha512-N0LdR1ImZQw1r4cYaKtVbBhBPtj4Zu9NbvygzizEP5HuTfxZmE1Ans3w93Kks9VTXZXob8twNbXnzBwzTyEpEA== dependencies: "@lerna/otplease" "6.1.0" @@ -1481,7 +1294,7 @@ "@lerna/npm-run-script@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-6.1.0.tgz#bc5bd414ee9696168d88d8ce78f8e8b715967100" integrity sha512-7p13mvdxdY5+VqWvvtMsMDeyCRs0PrrTmSHRO+FKuLQuGhBvUo05vevcMEOQNDvEvl/tXPrOVbeGCiGubYTCLg== dependencies: "@lerna/child-process" "6.1.0" @@ -1490,21 +1303,21 @@ "@lerna/otplease@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/otplease/-/otplease-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/otplease/-/otplease-6.1.0.tgz#d25dbe2d867215b69f06de12ab4ff559d83d1d01" integrity sha512-gqSE6IbaD4IeNJePkaDLaFLoGp0Ceu35sn7z0AHAOoHiQGGorOmvM+h1Md3xZZRSXQmY9LyJVhG5eRa38SoG4g== dependencies: "@lerna/prompt" "6.1.0" "@lerna/output@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/output/-/output-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/output/-/output-6.1.0.tgz#d470146c6ee8ee063fd416081c1ca64fb132c4d8" integrity sha512-mgCIzLKIuroytXuxjTB689ERtpfgyNXW0rMv9WHOa6ufQc+QJPjh3L4jVsOA0l+/OxZyi97PUXotduNj+0cbnA== dependencies: npmlog "^6.0.2" "@lerna/pack-directory@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-6.1.0.tgz#3252ba7250d826b9922238c775abf5004e7580c4" integrity sha512-Xsixqm2nkGXs9hvq08ClbGpRlCYnlBV4TwSrLttIDL712RlyXoPe2maJzTUqo9OXBbOumFSahUEInCMT2OS05g== dependencies: "@lerna/get-packed" "6.1.0" @@ -1517,7 +1330,7 @@ "@lerna/package-graph@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-6.1.0.tgz#2373617605f48f53b5fa9d13188838b6c09022b0" integrity sha512-yGyxd/eHTDjkpnBbDhTV0hwKF+i01qZc+6/ko65wOsh8xtgqpQeE6mtdgbvsLKcuMcIQ7PDy1ntyIv9phg14gQ== dependencies: "@lerna/prerelease-id-from-version" "6.1.0" @@ -1528,7 +1341,7 @@ "@lerna/package@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/package/-/package-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/package/-/package-6.1.0.tgz#e9e33876c0509a86c1b676045b19fd3f7f1c77e2" integrity sha512-PyNFtdH2IcLasp/nyMDshmeXotriOSlhbeFIxhdl1XuGj5v1so3utMSOrJMO5kzZJQg5zyx8qQoxL+WH/hkrVQ== dependencies: load-json-file "^6.2.0" @@ -1537,14 +1350,14 @@ "@lerna/prerelease-id-from-version@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-6.1.0.tgz#4ee5beeef4e81d77001e94ec5613c140b6615616" integrity sha512-ngC4I6evvZztB6aOaSDEnhUgRTlqX3TyBXwWwLGTOXCPaCQBTPaLNokhmRdJ+ZVdZ4iHFbzEDSL07ubZrYUcmQ== dependencies: semver "^7.3.4" "@lerna/profiler@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/profiler/-/profiler-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/profiler/-/profiler-6.1.0.tgz#aae2249f1a39c79db72a548ce50bf32f86a0f3a5" integrity sha512-WFDQNpuqPqMJLg8llvrBHF8Ib5Asgp23lMeNUe89T62NUX6gkjVBTYdjsduxM0tZH6Pa0GAGaQcha97P6fxfdQ== dependencies: fs-extra "^9.1.0" @@ -1553,7 +1366,7 @@ "@lerna/project@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/project/-/project-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/project/-/project-6.1.0.tgz#605afe28fb15d8b8b890fafe0ec1da2700964056" integrity sha512-EOkfjjrTM16c3GUxGqcfYD2stV35p9mBEmkF41NPmyjfbzjol/irDF1r6Q7BsQSRsdClMJRCeZ168xdSxC2X0A== dependencies: "@lerna/package" "6.1.0" @@ -1572,7 +1385,7 @@ "@lerna/prompt@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/prompt/-/prompt-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-6.1.0.tgz#98e228220428d33620822f77e39f592ce29c776c" integrity sha512-981J/C53TZ2l2mFVlWJN7zynSzf5GEHKvKQa12Td9iknhASZOuwTAWb6eq46246Ant6W5tWwb0NSPu3I5qtcrA== dependencies: inquirer "^8.2.4" @@ -1580,7 +1393,7 @@ "@lerna/publish@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/publish/-/publish-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-6.1.0.tgz#9d62c327bc3541a0430951d726b39a2fb17b7925" integrity sha512-XtvuydtU0IptbAapLRgoN1AZj/WJR+e3UKnx9BQ1Dwc+Fpg2oqPxR/vi+6hxAsr95pdQ5CnWBdgS+dg2wEUJ7Q== dependencies: "@lerna/check-working-tree" "6.1.0" @@ -1614,21 +1427,21 @@ "@lerna/pulse-till-done@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-6.1.0.tgz#df0112a9a5b8547b53d18742ce21104eb360d731" integrity sha512-a2RVT82E4R9nVXtehzp2TQL6iXp0QfEM3bu8tBAR/SfI1A9ggZWQhuuUqtRyhhVCajdQDOo7rS0UG7R5JzK58w== dependencies: npmlog "^6.0.2" "@lerna/query-graph@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/query-graph/-/query-graph-6.1.0.tgz#e78c47c78d4691231fc379570e036bc2753cf6fa" integrity sha512-YkyCc+6aR7GlCOcZXEKPcl5o5L2v+0YUNs59JrfAS0mctFosZ/2tP7pkdu2SI4qXIi5D0PMNsh/0fRni56znsQ== dependencies: "@lerna/package-graph" "6.1.0" "@lerna/resolve-symlink@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-6.1.0.tgz#5a8686b99c838bc6e869930e5b5fd582607ebbe7" integrity sha512-8ILO+h5fsE0q8MSLfdL+MT1GEsNhAB1fDyMkSsYgLRCsssN/cViZbffpclZyT/EfAhpyKfBCHZ0CmT1ZGofU1A== dependencies: fs-extra "^9.1.0" @@ -1637,7 +1450,7 @@ "@lerna/rimraf-dir@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-6.1.0.tgz#75559585d5921563eff0e206bb9ec8ab0cc967c6" integrity sha512-J9YeGHkCCeAIzsnKURYeGECBexiIii6HA+Bbd+rAgoKPsNCOj6ql4+qJE8Jbd7fQEFNDPQeBCYvM7JcdMc0WSA== dependencies: "@lerna/child-process" "6.1.0" @@ -1647,7 +1460,7 @@ "@lerna/run-lifecycle@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-6.1.0.tgz#e1fa6cd300842ef1d688af77648fed05ec2d5345" integrity sha512-GbTdKxL+hWHEPgyBEKtqY9Nf+jFlt6YLtP5VjEVc5SdLkm+FeRquar9/YcZVUbzr3c+NJwWNgVjHuePfowdpUA== dependencies: "@lerna/npm-conf" "6.1.0" @@ -1657,7 +1470,7 @@ "@lerna/run-topologically@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/run-topologically/-/run-topologically-6.1.0.tgz#8f1a428b5d4b800bced178edabfa2262b328572f" integrity sha512-kpTaSBKdKjtf61be8Z1e7TIaMt/aksfxswQtpFxEuKDsPsdHfR8htSkADO4d/3SZFtmcAHIHNCQj9CaNj4O4Xw== dependencies: "@lerna/query-graph" "6.1.0" @@ -1665,7 +1478,7 @@ "@lerna/run@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/run/-/run-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/run/-/run-6.1.0.tgz#efaea1acc78cb7fc73b4906be70002e118628d64" integrity sha512-vlEEKPcTloiob6EK7gxrjEdB6fQQ/LNfWhSJCGxJlvNVbrMpoWIu0Kpp20b0nE+lzX7rRJ4seWr7Wdo/Fjub4Q== dependencies: "@lerna/command" "6.1.0" @@ -1681,7 +1494,7 @@ "@lerna/symlink-binary@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-6.1.0.tgz#7d476499b86ae5fcb853c510603cff9a27acf105" integrity sha512-DaiRNZk/dvomNxgEaTW145PyL7vIGP7rvnfXV2FO+rjX8UUSNUOjmVmHlYfs64gV9Eqx/dLfQClIbKcwYMD83A== dependencies: "@lerna/create-symlink" "6.1.0" @@ -1691,7 +1504,7 @@ "@lerna/symlink-dependencies@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-6.1.0.tgz#f44d33e043fed21a366c4ced2cbde8fa8be0c5fc" integrity sha512-hrTvtY1Ek+fLA4JjXsKsvwPjuJD0rwB/+K4WY57t00owj//BpCsJ37w3kkkS7f/PcW/5uRjCuHcY67LOEwsRxw== dependencies: "@lerna/create-symlink" "6.1.0" @@ -1703,7 +1516,7 @@ "@lerna/temp-write@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/temp-write/-/temp-write-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/temp-write/-/temp-write-6.1.0.tgz#a5d532090dd7b2d4f8965fbb475376aae06b9242" integrity sha512-ZcQl88H9HbQ/TeWUOVt+vDYwptm7kwprGvj9KkZXr9S5Bn6SiKRQOeydCCfCrQT+9Q3dm7QZXV6rWzLsACcAlQ== dependencies: graceful-fs "^4.1.15" @@ -1714,19 +1527,19 @@ "@lerna/timer@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/timer/-/timer-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/timer/-/timer-6.1.0.tgz#245b02c05b2dec6d2aed2da8a0962cf0343d83d5" integrity sha512-du+NQ9q7uO4d2nVU4AD2DSPuAZqUapA/bZKuVpFVxvY9Qhzb8dQKLsFISe4A9TjyoNAk8ZeWK0aBc/6N+Qer9A== "@lerna/validation-error@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-6.1.0.tgz#03bd46f6219b6db7c4420528d5aaf047f92693e3" integrity sha512-q0c3XCi5OpyTr8AcfbisS6e3svZaJF/riCvBDqRMaQUT4A8QOPzB4fVF3/+J2u54nidBuTlIk0JZu9aOdWTUkQ== dependencies: npmlog "^6.0.2" "@lerna/version@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/version/-/version-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/version/-/version-6.1.0.tgz#44d8649e978df9d6a14d97c9d7631a7dcd4a9cbf" integrity sha512-RUxVFdzHt0739lRNMrAbo6HWcFrcyG7atM1pn+Eo61fUoA5R/9N4bCk4m9xUGkJ/mOcROjuwAGe+wT1uOs58Bg== dependencies: "@lerna/check-working-tree" "6.1.0" @@ -1759,15 +1572,66 @@ "@lerna/write-log-file@6.1.0": version "6.1.0" - resolved "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-6.1.0.tgz#b811cffd2ea2b3be6239a756c64dac9a3795707a" integrity sha512-09omu2w4NCt8mJH/X9ZMuToQQ3xu/KpC7EU4yDl2Qy8nxKf8HiG8Oe+YYNprngmkdsq60F5eUZvoiFDZ5JeGIg== dependencies: npmlog "^6.0.2" write-file-atomic "^4.0.1" +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@~1.8.1": + version "1.8.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7" + integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== + dependencies: + "@noble/hashes" "1.7.2" + +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.2.tgz#d53c65a21658fb02f3303e7ee3ba89d6754c64b4" + integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== + +"@noble/secp256k1@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@noble/secp256k1@~1.7.0": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.2.tgz#c2c3343e2dce80e15a914d7442147507f8a98e7f" + integrity sha512-/qzwYl5eFLH8OWIecQWM31qld2g1NfjgylK+TNhqtaUKP37Nm+Y+z30Fjhw0Ct8p9yCQEm2N3W/AckdIb3SMcQ== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -1775,20 +1639,124 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nomicfoundation/edr-darwin-arm64@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.11.0.tgz#fa791451c5ce2acf6634143bca9fe8f1b5c66603" + integrity sha512-aYTVdcSs27XG7ayTzvZ4Yn9z/ABSaUwicrtrYK2NR8IH0ik4N4bWzo/qH8rax6rewVLbHUkGyGYnsy5ZN4iiMw== + +"@nomicfoundation/edr-darwin-x64@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.11.0.tgz#b1aaf0bfb331f6d136a92cbe31f184e2209e7a4f" + integrity sha512-RxX7UYgvJrfcyT/uHUn44Nsy1XaoW+Q1khKMdHKxeW7BrgIi+Lz+siz3bX5vhSoAnKilDPhIVLrnC8zxQhjR2A== + +"@nomicfoundation/edr-linux-arm64-gnu@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.11.0.tgz#fef6763c5d42bb68b4fc95df45c4745a0e31df93" + integrity sha512-J0j+rs0s11FuSipt/ymqrFmpJ7c0FSz1/+FohCIlUXDxFv//+1R/8lkGPjEYFmy8DPpk/iO8mcpqHTGckREbqA== + +"@nomicfoundation/edr-linux-arm64-musl@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.11.0.tgz#ef89d5d2aefc1f8d4f7c699c59b8897a645d33eb" + integrity sha512-4r32zkGMN7WT/CMEuW0VjbuEdIeCskHNDMW4SSgQSJOE/N9L1KSLJCSsAbPD3aYE+e4WRDTyOwmuLjeUTcLZKQ== + +"@nomicfoundation/edr-linux-x64-gnu@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.11.0.tgz#97432126110aa805b761d4743ab158698cae6d66" + integrity sha512-SmdncQHLYtVNWLIMyGaY6LpAfamzTDe3fxjkirmJv3CWR5tcEyC6LMui/GsIVnJzXeNJBXAzwl8hTUAxHTM6kQ== + +"@nomicfoundation/edr-linux-x64-musl@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.11.0.tgz#7605fddbada22dfdd14b15f4ac562014d9c82332" + integrity sha512-w6hUqpn/trwiH6SRuRGysj37LsQVCX5XDCA3Xi81sbOaLhbHrNvK9TXWyZmcuzbdTKQQW6VNywcSxDdOiChcJg== + +"@nomicfoundation/edr-win32-x64-msvc@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.11.0.tgz#6766175f3ec47bfbda0429ca00fed4ae5632a3c4" + integrity sha512-BLmULjRKoH9BsX+c4Na2ypV7NGeJ+M6Zpqj/faPOwleVscDdSr/IhriyPaXCe8dyfwbge7lWsbekiADtPSnB2Q== + +"@nomicfoundation/edr@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.11.0.tgz#d8b0ba4dfd7d93b9c54762e72eb9cd4e8244ce46" + integrity sha512-36WERf8ldvyHR6UAbcYsa+vpbW7tCrJGBwF4gXSsb8+STj1n66Hz85Y/O7B9+8AauX3PhglvV5dKl91tk43mWw== + dependencies: + "@nomicfoundation/edr-darwin-arm64" "0.11.0" + "@nomicfoundation/edr-darwin-x64" "0.11.0" + "@nomicfoundation/edr-linux-arm64-gnu" "0.11.0" + "@nomicfoundation/edr-linux-arm64-musl" "0.11.0" + "@nomicfoundation/edr-linux-x64-gnu" "0.11.0" + "@nomicfoundation/edr-linux-x64-musl" "0.11.0" + "@nomicfoundation/edr-win32-x64-msvc" "0.11.0" + +"@nomicfoundation/hardhat-ethers@3.0.8": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz#af078f566373abeb77e11cbe69fe3dd47f8bfc27" + integrity sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA== + dependencies: + debug "^4.1.1" + lodash.isequal "^4.5.0" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" + integrity sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz#74dcfabeb4ca373d95bd0d13692f44fcef133c28" + integrity sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz#4af5849a89e5a8f511acc04f28eb5d4460ba2b6a" + integrity sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz#54036808a9a327b2ff84446c130a6687ee702a8e" + integrity sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz#466cda0d6e43691986c944b909fc6dbb8cfc594e" + integrity sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz#2b35826987a6e94444140ac92310baa088ee7f94" + integrity sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz#e6363d13b8709ca66f330562337dbc01ce8bbbd9" + integrity sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz#8bcea7d300157bf3a770a851d9f5c5e2db34ac55" + integrity sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.2" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.2" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" + "@npmcli/arborist@5.3.0": version "5.3.0" - resolved "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-5.3.0.tgz#321d9424677bfc08569e98a5ac445ee781f32053" integrity sha512-+rZ9zgL1lnbl8Xbb1NQdMjveOMwj4lIYfcDtyJHHi5x4X8jtR6m8SXooJMZy5vmFVZ8w7A2Bnd/oX9eTuU8w5A== dependencies: "@isaacs/string-locale-compare" "^1.1.0" @@ -1828,22 +1796,15 @@ "@npmcli/fs@^2.1.0": version "2.1.2" - resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865" integrity sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ== dependencies: "@gar/promisify" "^1.1.3" semver "^7.3.5" -"@npmcli/fs@^3.1.0": - version "3.1.0" - resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz" - integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== - dependencies: - semver "^7.3.5" - "@npmcli/git@^3.0.0": version "3.0.2" - resolved "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-3.0.2.tgz#5c5de6b4d70474cf2d09af149ce42e4e1dacb931" integrity sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w== dependencies: "@npmcli/promise-spawn" "^3.0.0" @@ -1858,7 +1819,7 @@ "@npmcli/installed-package-contents@^1.0.7": version "1.0.7" - resolved "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz#ab7408c6147911b970a8abe261ce512232a3f4fa" integrity sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw== dependencies: npm-bundled "^1.1.1" @@ -1866,7 +1827,7 @@ "@npmcli/map-workspaces@^2.0.3": version "2.0.4" - resolved "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-2.0.4.tgz#9e5e8ab655215a262aefabf139782b894e0504fc" integrity sha512-bMo0aAfwhVwqoVM5UzX1DJnlvVvzDCHae821jv48L1EsrYwfOZChlqWYXEtto/+BkBXetPbEWgau++/brh4oVg== dependencies: "@npmcli/name-from-folder" "^1.0.1" @@ -1876,7 +1837,7 @@ "@npmcli/metavuln-calculator@^3.0.1": version "3.1.1" - resolved "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.1.tgz#9359bd72b400f8353f6a28a25c8457b562602622" integrity sha512-n69ygIaqAedecLeVH3KnO39M6ZHiJ2dEv5A7DGvcqCB8q17BGUgW8QaanIkbWUo2aYGZqJaOORTLAlIvKjNDKA== dependencies: cacache "^16.0.0" @@ -1886,7 +1847,7 @@ "@npmcli/move-file@^2.0.0": version "2.0.1" - resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.1.tgz#26f6bdc379d87f75e55739bab89db525b06100e4" integrity sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ== dependencies: mkdirp "^1.0.4" @@ -1894,31 +1855,31 @@ "@npmcli/name-from-folder@^1.0.1": version "1.0.1" - resolved "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz#77ecd0a4fcb772ba6fe927e2e2e155fbec2e6b1a" integrity sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA== "@npmcli/node-gyp@^2.0.0": version "2.0.0" - resolved "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz#8c20e53e34e9078d18815c1d2dda6f2420d75e35" integrity sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A== "@npmcli/package-json@^2.0.0": version "2.0.0" - resolved "https://registry.npmjs.org/@npmcli/package-json/-/package-json-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-2.0.0.tgz#3bbcf4677e21055adbe673d9f08c9f9cde942e4a" integrity sha512-42jnZ6yl16GzjWSH7vtrmWyJDGVa/LXPdpN2rcUWolFjc9ON2N3uz0qdBbQACfmhuJZ2lbKYtmK5qx68ZPLHMA== dependencies: json-parse-even-better-errors "^2.3.1" "@npmcli/promise-spawn@^3.0.0": version "3.0.0" - resolved "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz#53283b5f18f855c6925f23c24e67c911501ef573" integrity sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g== dependencies: infer-owner "^1.0.4" "@npmcli/run-script@^4.1.0", "@npmcli/run-script@^4.1.3", "@npmcli/run-script@^4.1.7": version "4.2.1" - resolved "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.2.1.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-4.2.1.tgz#c07c5c71bc1c70a5f2a06b0d4da976641609b946" integrity sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg== dependencies: "@npmcli/node-gyp" "^2.0.0" @@ -1929,14 +1890,14 @@ "@nrwl/cli@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/cli/-/cli-15.9.7.tgz" + resolved "https://registry.yarnpkg.com/@nrwl/cli/-/cli-15.9.7.tgz#1db113f5cb1cfe63213097be1ece041eef33da1f" integrity sha512-1jtHBDuJzA57My5nLzYiM372mJW0NY6rFKxlWt5a0RLsAZdPTHsd8lE3Gs9XinGC1jhXbruWmhhnKyYtZvX/zA== dependencies: nx "15.9.7" "@nrwl/devkit@>=14.8.6 < 16": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.9.7.tgz" + resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-15.9.7.tgz#14d19ec82ff4209c12147a97f1cdea05d8f6c087" integrity sha512-Sb7Am2TMT8AVq8e+vxOlk3AtOA2M0qCmhBzoM1OJbdHaPKc0g0UgSnWRml1kPGg5qfPk72tWclLoZJ5/ut0vTg== dependencies: ejs "^3.1.7" @@ -1947,71 +1908,71 @@ "@nrwl/nx-darwin-arm64@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-darwin-arm64/-/nx-darwin-arm64-15.9.7.tgz#a2cb7390c782b8acf3bb8806a3002620226a933d" + resolved "https://registry.yarnpkg.com/@nrwl/nx-darwin-arm64/-/nx-darwin-arm64-15.9.7.tgz#a2cb7390c782b8acf3bb8806a3002620226a933d" integrity sha512-aBUgnhlkrgC0vu0fK6eb9Vob7eFnkuknrK+YzTjmLrrZwj7FGNAeyGXSlyo1dVokIzjVKjJg2saZZ0WQbfuCJw== "@nrwl/nx-darwin-x64@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-darwin-x64/-/nx-darwin-x64-15.9.7.tgz" + resolved "https://registry.yarnpkg.com/@nrwl/nx-darwin-x64/-/nx-darwin-x64-15.9.7.tgz#af0437e726aeb97eb660646bfd9a7da5ba7a0a6f" integrity sha512-L+elVa34jhGf1cmn38Z0sotQatmLovxoASCIw5r1CBZZeJ5Tg7Y9nOwjRiDixZxNN56hPKXm6xl9EKlVHVeKlg== "@nrwl/nx-linux-arm-gnueabihf@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-15.9.7.tgz#e29f4d31afa903bfb4d0fd7421e19be1086eae87" + resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-15.9.7.tgz#e29f4d31afa903bfb4d0fd7421e19be1086eae87" integrity sha512-pqmfqqEUGFu6PmmHKyXyUw1Al0Ki8PSaR0+ndgCAb1qrekVDGDfznJfaqxN0JSLeolPD6+PFtLyXNr9ZyPFlFg== "@nrwl/nx-linux-arm64-gnu@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-15.9.7.tgz#eb2880a24d3268dd93583d21a6a0b9ff96bb23b4" + resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-15.9.7.tgz#eb2880a24d3268dd93583d21a6a0b9ff96bb23b4" integrity sha512-NYOa/eRrqmM+In5g3M0rrPVIS9Z+q6fvwXJYf/KrjOHqqan/KL+2TOfroA30UhcBrwghZvib7O++7gZ2hzwOnA== "@nrwl/nx-linux-arm64-musl@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-linux-arm64-musl/-/nx-linux-arm64-musl-15.9.7.tgz#5d04913c4672a96cefa78491824620d8a8bcfd7f" + resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-arm64-musl/-/nx-linux-arm64-musl-15.9.7.tgz#5d04913c4672a96cefa78491824620d8a8bcfd7f" integrity sha512-zyStqjEcmbvLbejdTOrLUSEdhnxNtdQXlmOuymznCzYUEGRv+4f7OAepD3yRoR0a/57SSORZmmGQB7XHZoYZJA== "@nrwl/nx-linux-x64-gnu@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-linux-x64-gnu/-/nx-linux-x64-gnu-15.9.7.tgz#cf7f61fd87f35a793e6824952a6eb12242fe43fd" + resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-x64-gnu/-/nx-linux-x64-gnu-15.9.7.tgz#cf7f61fd87f35a793e6824952a6eb12242fe43fd" integrity sha512-saNK5i2A8pKO3Il+Ejk/KStTApUpWgCxjeUz9G+T8A+QHeDloZYH2c7pU/P3jA9QoNeKwjVO9wYQllPL9loeVg== "@nrwl/nx-linux-x64-musl@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-linux-x64-musl/-/nx-linux-x64-musl-15.9.7.tgz#2bec23c3696780540eb47fa1358dda780c84697f" + resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-x64-musl/-/nx-linux-x64-musl-15.9.7.tgz#2bec23c3696780540eb47fa1358dda780c84697f" integrity sha512-extIUThYN94m4Vj4iZggt6hhMZWQSukBCo8pp91JHnDcryBg7SnYmnikwtY1ZAFyyRiNFBLCKNIDFGkKkSrZ9Q== "@nrwl/nx-win32-arm64-msvc@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-15.9.7.tgz#21b56ef3ab4190370effea71bd83fdc3e47ec69c" + resolved "https://registry.yarnpkg.com/@nrwl/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-15.9.7.tgz#21b56ef3ab4190370effea71bd83fdc3e47ec69c" integrity sha512-GSQ54hJ5AAnKZb4KP4cmBnJ1oC4ILxnrG1mekxeM65c1RtWg9NpBwZ8E0gU3xNrTv8ZNsBeKi/9UhXBxhsIh8A== "@nrwl/nx-win32-x64-msvc@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/nx-win32-x64-msvc/-/nx-win32-x64-msvc-15.9.7.tgz#1677ab1dcce921706b5677dc2844e3e0027f8bd5" + resolved "https://registry.yarnpkg.com/@nrwl/nx-win32-x64-msvc/-/nx-win32-x64-msvc-15.9.7.tgz#1677ab1dcce921706b5677dc2844e3e0027f8bd5" integrity sha512-x6URof79RPd8AlapVbPefUD3ynJZpmah3tYaYZ9xZRMXojVtEHV8Qh5vysKXQ1rNYJiiB8Ah6evSKWLbAH60tw== "@nrwl/tao@15.9.7": version "15.9.7" - resolved "https://registry.npmjs.org/@nrwl/tao/-/tao-15.9.7.tgz" + resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-15.9.7.tgz#c0e78c99caa6742762f7558f20d8524bc9015e97" integrity sha512-OBnHNvQf3vBH0qh9YnvBQQWyyFZ+PWguF6dJ8+1vyQYlrLVk/XZ8nJ4ukWFb+QfPv/O8VBmqaofaOI9aFC4yTw== dependencies: nx "15.9.7" "@octokit/auth-token@^2.4.0": version "2.5.0" - resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g== dependencies: "@octokit/types" "^6.0.3" "@octokit/auth-token@^3.0.0": version "3.0.4" - resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.4.tgz#70e941ba742bdd2b49bdb7393e821dea8520a3db" integrity sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ== "@octokit/core@3.2.0": version "3.2.0" - resolved "https://registry.npmjs.org/@octokit/core/-/core-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.2.0.tgz#7a872ad4cb8d8d2f417dd7fe1aaff3919c09dc04" integrity sha512-42jzu1GWlCr4KUo52X4hD3if2AwjNJLzsS8mqUs9JkJbsM3vzvSx8AqTnVBQjOM0hQMYBqR7/7SAUTfH7IZqIg== dependencies: "@octokit/auth-token" "^2.4.0" @@ -2023,7 +1984,7 @@ "@octokit/core@^4.2.1": version "4.2.4" - resolved "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.2.4.tgz#d8769ec2b43ff37cc3ea89ec4681a20ba58ef907" integrity sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ== dependencies: "@octokit/auth-token" "^3.0.0" @@ -2036,7 +1997,7 @@ "@octokit/endpoint@^6.0.1": version "6.0.12" - resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA== dependencies: "@octokit/types" "^6.0.3" @@ -2045,7 +2006,7 @@ "@octokit/endpoint@^7.0.0": version "7.0.6" - resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.6.tgz#791f65d3937555141fb6c08f91d618a7d645f1e2" integrity sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg== dependencies: "@octokit/types" "^9.0.0" @@ -2054,7 +2015,7 @@ "@octokit/graphql@^4.3.1": version "4.8.0" - resolved "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg== dependencies: "@octokit/request" "^5.6.0" @@ -2063,7 +2024,7 @@ "@octokit/graphql@^5.0.0": version "5.0.6" - resolved "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.6.tgz#9eac411ac4353ccc5d3fca7d76736e6888c5d248" integrity sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw== dependencies: "@octokit/request" "^6.0.0" @@ -2072,22 +2033,22 @@ "@octokit/openapi-types@^12.11.0": version "12.11.0" - resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== "@octokit/openapi-types@^18.0.0": - version "18.0.0" - resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz" - integrity sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw== + version "18.1.1" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-18.1.1.tgz#09bdfdabfd8e16d16324326da5148010d765f009" + integrity sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw== "@octokit/plugin-enterprise-rest@^6.0.1": version "6.0.1" - resolved "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw== "@octokit/plugin-paginate-rest@^6.1.2": version "6.1.2" - resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz#f86456a7a1fe9e58fec6385a85cf1b34072341f8" integrity sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ== dependencies: "@octokit/tsconfig" "^1.0.2" @@ -2095,19 +2056,19 @@ "@octokit/plugin-request-log@^1.0.4": version "1.0.4" - resolved "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== "@octokit/plugin-rest-endpoint-methods@^7.1.2": version "7.2.3" - resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz#37a84b171a6cb6658816c82c4082ac3512021797" integrity sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA== dependencies: "@octokit/types" "^10.0.0" "@octokit/request-error@^2.1.0": version "2.1.0" - resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg== dependencies: "@octokit/types" "^6.0.3" @@ -2116,7 +2077,7 @@ "@octokit/request-error@^3.0.0": version "3.0.3" - resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.3.tgz#ef3dd08b8e964e53e55d471acfe00baa892b9c69" integrity sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ== dependencies: "@octokit/types" "^9.0.0" @@ -2125,7 +2086,7 @@ "@octokit/request@^5.4.0", "@octokit/request@^5.6.0": version "5.6.3" - resolved "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== dependencies: "@octokit/endpoint" "^6.0.1" @@ -2137,7 +2098,7 @@ "@octokit/request@^6.0.0": version "6.2.8" - resolved "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.2.8.tgz#aaf480b32ab2b210e9dadd8271d187c93171d8eb" integrity sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw== dependencies: "@octokit/endpoint" "^7.0.0" @@ -2149,7 +2110,7 @@ "@octokit/rest@^19.0.3": version "19.0.13" - resolved "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.13.tgz#e799393264edc6d3c67eeda9e5bd7832dcf974e4" integrity sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA== dependencies: "@octokit/core" "^4.2.1" @@ -2159,40 +2120,40 @@ "@octokit/tsconfig@^1.0.2": version "1.0.2" - resolved "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/@octokit/tsconfig/-/tsconfig-1.0.2.tgz#59b024d6f3c0ed82f00d08ead5b3750469125af7" integrity sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA== "@octokit/types@^10.0.0": version "10.0.0" - resolved "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-10.0.0.tgz#7ee19c464ea4ada306c43f1a45d444000f419a4a" integrity sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg== dependencies: "@octokit/openapi-types" "^18.0.0" "@octokit/types@^5.0.0": version "5.5.0" - resolved "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== dependencies: "@types/node" ">= 8" "@octokit/types@^6.0.3", "@octokit/types@^6.16.1": version "6.41.0" - resolved "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== dependencies: "@octokit/openapi-types" "^12.11.0" "@octokit/types@^9.0.0", "@octokit/types@^9.2.3": version "9.3.2" - resolved "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-9.3.2.tgz#3f5f89903b69f6a2d196d78ec35f888c0013cac5" integrity sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA== dependencies: "@octokit/openapi-types" "^18.0.0" "@parcel/watcher@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.4.tgz#f300fef4cc38008ff4b8c29d92588eced3ce014b" integrity sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg== dependencies: node-addon-api "^3.2.1" @@ -2203,33 +2164,94 @@ resolved "https://registry.yarnpkg.com/@pinax/graph-networks-registry/-/graph-networks-registry-0.6.7.tgz#ceb994f3b31e2943b9c9d9b09dd86eb00d067c0e" integrity sha512-xogeCEZ50XRMxpBwE3TZjJ8RCO8Guv39gDRrrKtlpDEDEMLm0MzD3A0SQObgj7aF7qTZNRTWzsuvQdxgzw25wQ== -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@rushstack/node-core-library@5.13.0": + version "5.13.0" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-5.13.0.tgz#f79d6868b74be102eee75b93c37be45fb9b47ead" + integrity sha512-IGVhy+JgUacAdCGXKUrRhwHMTzqhWwZUI+qEPcdzsb80heOw0QPbhhoVsoiMF7Klp8eYsp7hzpScMXmOa3Uhfg== + dependencies: + ajv "~8.13.0" + ajv-draft-04 "~1.0.0" + ajv-formats "~3.0.1" + fs-extra "~11.3.0" + import-lazy "~4.0.0" + jju "~1.4.0" + resolve "~1.22.1" + semver "~7.5.4" + +"@rushstack/terminal@0.15.2": + version "0.15.2" + resolved "https://registry.yarnpkg.com/@rushstack/terminal/-/terminal-0.15.2.tgz#8fa030409603a22db606ecb18709050e46517add" + integrity sha512-7Hmc0ysK5077R/IkLS9hYu0QuNafm+TbZbtYVzCMbeOdMjaRboLKrhryjwZSRJGJzu+TV1ON7qZHeqf58XfLpA== + dependencies: + "@rushstack/node-core-library" "5.13.0" + supports-color "~8.1.1" "@rushstack/ts-command-line@^4.7.7": - version "4.16.0" - resolved "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.16.0.tgz" - integrity sha512-WJKhdR9ThK9Iy7t78O3at7I3X4Ssp5RRZay/IQa8NywqkFy/DQbT3iLouodMMdUwLZD9n8n++xLubVd3dkmpkg== + version "4.23.7" + resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.23.7.tgz#9c6f05a00f776c7b8ea3321e2b5a03acc5e9efa8" + integrity sha512-Gr9cB7DGe6uz5vq2wdr89WbVDKz0UeuFEn5H2CfWDe7JvjFFaiV15gi6mqDBTbHhHCWS7w8mF1h3BnIfUndqdA== dependencies: + "@rushstack/terminal" "0.15.2" "@types/argparse" "1.0.38" argparse "~1.0.9" - colors "~1.2.1" string-argv "~0.3.1" -"@semiotic-labs/tap-contracts-bindings@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@semiotic-labs/tap-contracts-bindings/-/tap-contracts-bindings-1.2.1.tgz#4aa0b009b761bbb9aafb1ea0cbd89ccf7a7cb801" - integrity sha512-VwpKOxsJq2mrWZQ9y2kvwxNKqHtigmibH2uXoFxekIO8jfBjC69J8c/avzYNU3YBccAVEbLvfyNoDUs26c0XeQ== +"@scure/base@~1.1.0", "@scure/base@~1.1.6": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/base@~1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.5.tgz#f9d1b232425b367d0dcb81c96611dcc651d58671" + integrity sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw== + +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== dependencies: - "@typechain/ethers-v5" "^11.1.2" + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== + dependencies: + "@noble/hashes" "~1.2.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@semiotic-labs/tap-contracts-bindings@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@semiotic-labs/tap-contracts-bindings/-/tap-contracts-bindings-2.0.0.tgz#f0e348fef79e54f36e27502483c02267ebbcaec8" + integrity sha512-CPYsX3DSSPY98VMRDH4xoEZAiQSVVynXssWvbzcj4H1NRfc3O+T/jFxSUQG/1LCAnHanOEhoH9hevfjULGZSgg== + dependencies: + "@typechain/ethers-v6" "^0.5.1" abitype "^0.10.3" - ethers "5.7.0" + ethers "6.13.7" "@sentry/core@5.30.0": version "5.30.0" - resolved "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== dependencies: "@sentry/hub" "5.30.0" @@ -2240,7 +2262,7 @@ "@sentry/hub@5.30.0": version "5.30.0" - resolved "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== dependencies: "@sentry/types" "5.30.0" @@ -2249,16 +2271,16 @@ "@sentry/minimal@5.30.0": version "5.30.0" - resolved "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== dependencies: "@sentry/hub" "5.30.0" "@sentry/types" "5.30.0" tslib "^1.9.3" -"@sentry/node@^5.21.1": +"@sentry/node@^5.18.1", "@sentry/node@^5.21.1": version "5.30.0" - resolved "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== dependencies: "@sentry/core" "5.30.0" @@ -2273,7 +2295,7 @@ "@sentry/tracing@5.30.0": version "5.30.0" - resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== dependencies: "@sentry/hub" "5.30.0" @@ -2284,12 +2306,12 @@ "@sentry/types@5.30.0": version "5.30.0" - resolved "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== "@sentry/utils@5.30.0": version "5.30.0" - resolved "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== dependencies: "@sentry/types" "5.30.0" @@ -2316,12 +2338,12 @@ "@thi.ng/api@^7.1.4", "@thi.ng/api@^7.2.0": version "7.2.0" - resolved "https://registry.npmjs.org/@thi.ng/api/-/api-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/api/-/api-7.2.0.tgz#ed3d7c70aca157a8f53613f7359be7d2e31d6f18" integrity sha512-4NcwHXxwPF/JgJG/jSFd9rjfQNguF0QrHvd6e+CEf4T0sFChqetW6ZmJ6/a2X+noDVntgulegA+Bx0HHzw+Tyw== "@thi.ng/arrays@^1.0.3": version "1.0.3" - resolved "https://registry.npmjs.org/@thi.ng/arrays/-/arrays-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/arrays/-/arrays-1.0.3.tgz#f4d26184f6da3ff30beb2488a131e19f187fd920" integrity sha512-ZUB27bdpTwcvxYJTlt/eWKrj98nWXo0lAUPwRwubk4GlH8rTKKkc7qZr9/4LCKPsNjnZdQqbBtNvNf3HjYxCzw== dependencies: "@thi.ng/api" "^7.2.0" @@ -2333,21 +2355,21 @@ "@thi.ng/checks@^2.9.11": version "2.9.11" - resolved "https://registry.npmjs.org/@thi.ng/checks/-/checks-2.9.11.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/checks/-/checks-2.9.11.tgz#b7e4c78828f553613d2af025ce7ae3f9306f27bb" integrity sha512-fBvWod32w24JlJsrrOdl+tlx+UNehCORi4rHaJ7l7HH+SEhD/lYTCXOBjwu9D/ztIUjMP5Q+n8cAqI5iPhbvAQ== dependencies: tslib "^2.3.1" "@thi.ng/compare@^1.3.28", "@thi.ng/compare@^1.3.34": version "1.3.34" - resolved "https://registry.npmjs.org/@thi.ng/compare/-/compare-1.3.34.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/compare/-/compare-1.3.34.tgz#321e10780955b18a4bcf7876d0fe0323be9d7be8" integrity sha512-E+UWhmo8l5yeHDuriPUsfrnk/Mj5kSDNRX7lPfv2zNdAQ7N8UDzc0IXu46U6EpqtCReo+2n5N8qzfD3TjerFRw== dependencies: "@thi.ng/api" "^7.2.0" "@thi.ng/compose@^1.4.36": version "1.4.36" - resolved "https://registry.npmjs.org/@thi.ng/compose/-/compose-1.4.36.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/compose/-/compose-1.4.36.tgz#d9b737d16c80f9355cf598e41f71529acba564aa" integrity sha512-iaij+nAwgeyQTMAiGldAB0dfBBl77kcwJ8HPBFJxDDWsLCS3lIcywTcJPcXxZaL0nw49VJpPrgt0Qw17Q8Y+6g== dependencies: "@thi.ng/api" "^7.2.0" @@ -2355,7 +2377,7 @@ "@thi.ng/dcons@^2.3.34": version "2.3.34" - resolved "https://registry.npmjs.org/@thi.ng/dcons/-/dcons-2.3.34.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/dcons/-/dcons-2.3.34.tgz#eae63aaa7f2ef981dbf520fa9dc9f11ad4574cd8" integrity sha512-NTgwtZsB+3X4Hh3cp1KyY0GFwi/dMoX1FSpJhOhEiOa2REX33O5cryo8FUgSasGC7TeKBlLB9UADI84g+4mNlQ== dependencies: "@thi.ng/api" "^7.2.0" @@ -2368,17 +2390,17 @@ "@thi.ng/equiv@^1.0.45": version "1.0.45" - resolved "https://registry.npmjs.org/@thi.ng/equiv/-/equiv-1.0.45.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/equiv/-/equiv-1.0.45.tgz#02bf71a630939c8f61a2a7b9e83cca9569ead7f3" integrity sha512-tdXaJfF0pFvT80Q7BOlhc7H7ja/RbVGzlGpE4LqjDWfXPPbLYwmq6EbQuHWeXuvT0qe+BsGnuO5UXAR5B8oGGQ== "@thi.ng/errors@^1.3.4": version "1.3.4" - resolved "https://registry.npmjs.org/@thi.ng/errors/-/errors-1.3.4.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/errors/-/errors-1.3.4.tgz#8f7675f7a895a87f0f609d64db69bc04483e0b29" integrity sha512-hTk71OPKnioN349sdj2DAoY+69eSerB3MN4Zwz6mosr1QFzIMkfkNOtBeC+Gm0yi0V0EY5LeBYFgqb3oXbtTbw== "@thi.ng/heaps@1.2.38": version "1.2.38" - resolved "https://registry.npmjs.org/@thi.ng/heaps/-/heaps-1.2.38.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/heaps/-/heaps-1.2.38.tgz#c5027c02bedb41644fc71d109cd16a878a48ad0b" integrity sha512-lWDQsGmt6YuHgmog4wpSKa7wqawt0JVyCREWc/J2bA9vcg/cYfljda2teVTA3rTUhKWs/S2htorN8On7+Rxt5A== dependencies: "@thi.ng/api" "^7.1.4" @@ -2386,7 +2408,7 @@ "@thi.ng/heaps@^1.3.1": version "1.3.1" - resolved "https://registry.npmjs.org/@thi.ng/heaps/-/heaps-1.3.1.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/heaps/-/heaps-1.3.1.tgz#307d0673afb0a66362485f2ef639c029ec74d9ed" integrity sha512-0vPYpMTbPlfr1uCp+ebqsUzZkPyKFo1/owqQV2naTYU8dmSJ0wK3uP6aiU/UYrnnb0zVtY6xy72ucGOyapu0Rg== dependencies: "@thi.ng/api" "^7.2.0" @@ -2395,12 +2417,12 @@ "@thi.ng/hex@^1.0.4": version "1.0.4" - resolved "https://registry.npmjs.org/@thi.ng/hex/-/hex-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/hex/-/hex-1.0.4.tgz#5c5c86d3aef0422709b4aa8cfadd3b3f01a4a808" integrity sha512-9ofIG4nXhEskGeOJthpi/9LXFIPrlZ/MmHpgLWa3wNqTVhODP/o++mu9jDKojHEpKvswkkFCE+mSVmMu8xo4mQ== "@thi.ng/iterators@5.1.74": version "5.1.74" - resolved "https://registry.npmjs.org/@thi.ng/iterators/-/iterators-5.1.74.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/iterators/-/iterators-5.1.74.tgz#8e42ca092049ae4aa45e24e1a9649149fc5916b3" integrity sha512-dv7ExN1ygkHuPz0f2pFPoE1Ged+B3e3qgQ4n0iHDV386qDkYRgOFMGnSFaBDnNaKNlhyAXT8Kbb+jy/zbV+P4g== dependencies: "@thi.ng/api" "^7.2.0" @@ -2409,14 +2431,14 @@ "@thi.ng/math@^4.0.6": version "4.0.6" - resolved "https://registry.npmjs.org/@thi.ng/math/-/math-4.0.6.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/math/-/math-4.0.6.tgz#14f57425ceed922a3b22f6fc7b0f90a3a9a12f22" integrity sha512-MCXMW9Bzlgt8uqOkz1UB+gTvnB1viK5R/5c+z/1lmH2/rFa5TY8TKAByCsr1P+Rc+F7AbFoJlefFMSS7f5CDlg== dependencies: "@thi.ng/api" "^7.2.0" "@thi.ng/random@^2.4.8": version "2.4.8" - resolved "https://registry.npmjs.org/@thi.ng/random/-/random-2.4.8.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/random/-/random-2.4.8.tgz#428950e501c5a76907e3e6cb93985db07322012e" integrity sha512-4JJB8zbaPxjlAp1kCqsBbs6eN4Ivd/5fs1e4GlvmNkyGSucHIDTWvw6NnQWqUx2oPaAEDB9CFCH7SOcGC/cwkw== dependencies: "@thi.ng/api" "^7.2.0" @@ -2425,7 +2447,7 @@ "@thi.ng/transducers@^7.9.2": version "7.9.2" - resolved "https://registry.npmjs.org/@thi.ng/transducers/-/transducers-7.9.2.tgz" + resolved "https://registry.yarnpkg.com/@thi.ng/transducers/-/transducers-7.9.2.tgz#890166abe47dfbbd1497d6da7e2a1b2402bc4616" integrity sha512-FrC0cCdaQZ9di2sbLbwkQaweLUEvpaSVSwdbEhS77Pn/uoyZe+U+SnBAoyxKFgXHImtBpKFxu8Zd0is3ogrKNQ== dependencies: "@thi.ng/api" "^7.2.0" @@ -2439,7 +2461,7 @@ "@tootallnate/once@2": version "2.0.0" - resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== "@tsconfig/node10@^1.0.7": @@ -2462,17 +2484,17 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@typechain/ethers-v5@^11.1.2": - version "11.1.2" - resolved "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-11.1.2.tgz" - integrity sha512-ID6pqWkao54EuUQa0P5RgjvfA3MYqxUQKpbGKERbsjBW5Ra7EIXvbMlPp2pcP5IAdUkyMCFYsP2SN5q7mPdLDQ== +"@typechain/ethers-v6@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz#42fe214a19a8b687086c93189b301e2b878797ea" + integrity sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA== dependencies: lodash "^4.17.15" ts-essentials "^7.0.1" "@types/argparse@1.0.38": version "1.0.38" - resolved "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz" + resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== "@types/babel__core@^7.1.14": @@ -2487,9 +2509,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== dependencies: "@babel/types" "^7.0.0" @@ -2502,9 +2524,9 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== + version "7.20.7" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.7.tgz#968cdc2366ec3da159f61166428ee40f370e56c2" + integrity sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng== dependencies: "@babel/types" "^7.20.7" @@ -2513,6 +2535,13 @@ resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.42.tgz#7ec05f1ce9986d920313c1377a5662b1b563d366" integrity sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A== +"@types/bn.js@^5.1.0": + version "5.1.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" + integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== + dependencies: + "@types/node" "*" + "@types/body-parser@*": version "1.19.5" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" @@ -2528,20 +2557,13 @@ dependencies: base-x "^3.0.6" -"@types/connect@*": +"@types/connect@*", "@types/connect@^3.4.33": version "3.4.38" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" -"@types/connect@^3.4.33": - version "3.4.36" - resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz" - integrity sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w== - dependencies: - "@types/node" "*" - "@types/continuation-local-storage@*": version "3.2.7" resolved "https://registry.yarnpkg.com/@types/continuation-local-storage/-/continuation-local-storage-3.2.7.tgz#363bbeb1ef35ee2298cc371e34c74eb1b0a0b52c" @@ -2557,26 +2579,16 @@ "@types/node" "*" "@types/debug@^4.1.8": - version "4.1.8" - resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz" - integrity sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ== + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== dependencies: "@types/ms" "*" -"@types/express-serve-static-core@^4.17.33": - version "4.19.0" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz#3ae8ab3767d98d0b682cda063c3339e1e86ccfaa" - integrity sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - -"@types/express-serve-static-core@^4.17.9": - version "4.17.36" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz" - integrity sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q== +"@types/express-serve-static-core@^4.17.33", "@types/express-serve-static-core@^4.17.9": + version "4.19.6" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" + integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== dependencies: "@types/node" "*" "@types/qs" "*" @@ -2643,9 +2655,9 @@ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/lodash.clonedeep@^4.5.7": - version "4.5.7" - resolved "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.7.tgz" - integrity sha512-ccNqkPptFIXrpVqUECi60/DFxjNKsfoQxSQsgcBJCX/fuX1wgyQieojkcWH/KpE3xzLoWN/2k+ZeGqIN3paSvw== + version "4.5.9" + resolved "https://registry.yarnpkg.com/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.9.tgz#ea48276c7cc18d080e00bb56cf965bcceb3f0fc1" + integrity sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q== dependencies: "@types/lodash" "*" @@ -2665,7 +2677,7 @@ "@types/lodash.intersection@^4.4.7": version "4.4.9" - resolved "https://registry.npmjs.org/@types/lodash.intersection/-/lodash.intersection-4.4.9.tgz#24afb3177f0100d3772eedd0bdc331510d72d75d" + resolved "https://registry.yarnpkg.com/@types/lodash.intersection/-/lodash.intersection-4.4.9.tgz#24afb3177f0100d3772eedd0bdc331510d72d75d" integrity sha512-AenZXU5mbikacV1LyGTFIP7s94s0UyscACObGMrqDvKjZfRj+PpmAVvhNeLUMCBLi7RMlLgHic53J/LbaciEmg== dependencies: "@types/lodash" "*" @@ -2686,7 +2698,7 @@ "@types/lodash.xor@^4.5.7": version "4.5.9" - resolved "https://registry.npmjs.org/@types/lodash.xor/-/lodash.xor-4.5.9.tgz#8e533b21f7530f134cfffe8e2470127c797d9fa6" + resolved "https://registry.yarnpkg.com/@types/lodash.xor/-/lodash.xor-4.5.9.tgz#8e533b21f7530f134cfffe8e2470127c797d9fa6" integrity sha512-XCuHoMz2zVC8IBTRetsL9XRyy0zpnTtpqioG4nHWwtnt0RLbKjtdpCwU0/BfRszP+sMQkIEy1cDFydMhKOeDlg== dependencies: "@types/lodash" "*" @@ -2699,24 +2711,29 @@ "@types/lodash" "*" "@types/lodash@*", "@types/lodash@^4.14.159": - version "4.14.198" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.198.tgz" - integrity sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg== + version "4.17.16" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.16.tgz#94ae78fab4a38d73086e962d0b65c30d816bfb0a" + integrity sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g== + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== "@types/mime@^1": - version "1.3.2" - resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== "@types/minimatch@^3.0.3": version "3.0.5" - resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== "@types/minimist@^1.2.0": - version "1.2.2" - resolved "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz" - integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" + integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/morgan@1.9.5": version "1.9.5" @@ -2726,9 +2743,9 @@ "@types/node" "*" "@types/ms@*": - version "0.7.31" - resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz" - integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== "@types/ngeohash@0.6.4": version "0.6.4" @@ -2736,29 +2753,38 @@ integrity sha512-rr20mmx41OkWx4q5du2dv2sESR/6xH2tzScUQXwO8SiaQWa6PYTuan1nqBtA76FR9qkVfZY7nwQwZNC9StX/Ww== "@types/node@*", "@types/node@>= 8": - version "20.6.2" - resolved "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz" - integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw== + version "22.15.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.18.tgz#2f8240f7e932f571c2d45f555ba0b6c3f7a75963" + integrity sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg== + dependencies: + undici-types "~6.21.0" "@types/node@20.6.1": version "20.6.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.1.tgz#8b589bba9b2af0128796461a0979764562687e6f" integrity sha512-4LcJvuXQlv4lTHnxwyHQZ3uR9Zw2j7m1C9DfuwoTFQQP4Pmu04O6IfLYgMmHoOCt0nosItLLZAH+sOrRE0Bo8g== +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + "@types/node@^12.12.54": version "12.20.55" - resolved "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== "@types/normalize-package-data@^2.4.0": - version "2.4.1" - resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz" - integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== "@types/parsimmon@^1.10.6": version "1.10.9" @@ -2771,29 +2797,29 @@ integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== "@types/qs@*": - version "6.9.8" - resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz" - integrity sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg== + version "6.9.18" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.18.tgz#877292caa91f7c1b213032b34626505b746624c2" + integrity sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA== "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/retry@^0.12.0": - version "0.12.2" - resolved "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz" - integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== + version "0.12.5" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.5.tgz#f090ff4bd8d2e5b940ff270ab39fd5ca1834a07e" + integrity sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw== "@types/semver@^7.5.0": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + version "7.7.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.0.tgz#64c441bdae033b378b6eef7d0c3d77c329b9378e" + integrity sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA== "@types/send@*": - version "0.17.1" - resolved "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz" - integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== dependencies: "@types/mime" "^1" "@types/node" "*" @@ -2822,24 +2848,19 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== -"@types/validator@*": - version "13.12.3" - resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.12.3.tgz#af160ddaf1e43ab66fe69473a90b14bb9f435d29" - integrity sha512-2ipwZ2NydGQJImne+FhNdhgRM37e9lCev99KnqkbFHd94Xn/mErARWI1RSLem1QA19ch5kOhzIZd7e8CA2FI8g== - -"@types/validator@^13.7.17": - version "13.11.1" - resolved "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz" - integrity sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A== +"@types/validator@*", "@types/validator@^13.7.17": + version "13.15.0" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.15.0.tgz#d4643730536900190bb476a1dda0a4897c8881e2" + integrity sha512-nh7nrWhLr6CBq9ldtw0wx+z9wKnnv/uTVLA9g/3/TcOYxbpOSZE+MhKPmWqU+K0NvThjhv12uD8MuqijB0WzEA== "@types/verror@^1.10.4": - version "1.10.6" - resolved "https://registry.npmjs.org/@types/verror/-/verror-1.10.6.tgz" - integrity sha512-NNm+gdePAX1VGvPcGZCDKQZKYSiAWigKhKaz5KF94hG6f2s8de9Ow5+7AbXoeKxL8gavZfk4UquSAygOF2duEQ== + version "1.10.11" + resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.11.tgz#d3d6b418978c8aa202d41e5bb3483227b6ecc1bb" + integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg== "@types/ws@^7.4.4": version "7.4.7" - resolved "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== dependencies: "@types/node" "*" @@ -2857,9 +2878,9 @@ "@types/yargs-parser" "*" "@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + version "17.0.33" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" + integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== dependencies: "@types/yargs-parser" "*" @@ -3034,9 +3055,9 @@ eslint-visitor-keys "^3.4.1" "@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + version "1.3.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== "@urql/core@3.1.0", "@urql/core@>=3.1.0": version "3.1.0" @@ -3055,12 +3076,12 @@ "@yarnpkg/lockfile@^1.1.0": version "1.1.0" - resolved "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== "@yarnpkg/parsers@3.0.0-rc.46": version "3.0.0-rc.46" - resolved "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz" + resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz#03f8363111efc0ea670e53b0282cd3ef62de4e01" integrity sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q== dependencies: js-yaml "^3.10.0" @@ -3068,14 +3089,14 @@ "@zkochan/js-yaml@0.0.6": version "0.0.6" - resolved "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz" + resolved "https://registry.yarnpkg.com/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz#975f0b306e705e28b8068a07737fa46d3fc04826" integrity sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg== dependencies: argparse "^2.0.1" JSONStream@^1.0.4, JSONStream@^1.3.5: version "1.3.5" - resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== dependencies: jsonparse "^1.2.0" @@ -3083,22 +3104,22 @@ JSONStream@^1.0.4, JSONStream@^1.3.5: abbrev@1, abbrev@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abitype@^0.10.3: version "0.10.3" - resolved "https://registry.npmjs.org/abitype/-/abitype-0.10.3.tgz" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.10.3.tgz#27ce7a7cdb9a80ccd732a3f3cf1ce6ff05266fce" integrity sha512-tRN+7XIa7J9xugdbRzFv/95ka5ivR/sRe01eiWvM0HWWjHuigSZEACgKa0sj4wGuekTDtghCx+5Izk/cOi78pQ== abstract-logging@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== accepts@~1.3.8: version "1.3.8" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: mime-types "~2.1.34" @@ -3110,50 +3131,69 @@ acorn-jsx@^5.3.2: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" -acorn@^8.4.1, acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: + version "8.14.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== add-stream@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ== -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== agent-base@6, agent-base@^6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" agentkeepalive@^4.2.1: - version "4.5.0" - resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz" - integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + version "4.6.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a" + integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ== dependencies: humanize-ms "^1.2.1" aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv-draft-04@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + +ajv-formats@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + ajv@^6.11.0, ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -3161,29 +3201,46 @@ ajv@^6.11.0, ajv@^6.12.4, ajv@^6.12.6: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.1, ajv@^8.1.0: - version "8.12.0" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== +ajv@^8.0.0, ajv@^8.0.1, ajv@^8.1.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.2.2" + +ajv@~8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.13.0.tgz#a3939eaec9fb80d217ddf0c3376948c023f28c91" + integrity sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" ansi-colors@^3.2.1: version "3.2.4" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== -ansi-colors@^4.1.1: +ansi-colors@^4.1.1, ansi-colors@^4.1.3: version "4.1.3" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^4.2.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" @@ -3195,18 +3252,18 @@ ansi-regex@^2.0.0: ansi-regex@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== ansi-styles@^2.2.1: version "2.2.1" @@ -3215,14 +3272,14 @@ ansi-styles@^2.2.1: ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" @@ -3234,7 +3291,7 @@ ansi-styles@^5.0.0: ansi-styles@^6.1.0: version "6.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== anymatch@^1.3.0: @@ -3245,7 +3302,7 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" -anymatch@^3.0.3: +anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -3255,29 +3312,29 @@ anymatch@^3.0.3: apisauce@^2.0.1: version "2.1.6" - resolved "https://registry.npmjs.org/apisauce/-/apisauce-2.1.6.tgz" + resolved "https://registry.yarnpkg.com/apisauce/-/apisauce-2.1.6.tgz#94887f335bf3d735305fc895c8a191c9c2608a7f" integrity sha512-MdxR391op/FucS2YQRfB/NMRyCnHEPDd4h17LRIuVYi0BpGmMhpxc0shbOpfs5ahABuBEffNCGal5EcsydbBWg== dependencies: axios "^0.21.4" app-module-path@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" integrity sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ== "aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== archy@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== are-we-there-yet@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== dependencies: delegates "^1.0.0" @@ -3290,14 +3347,14 @@ arg@^4.1.0: argparse@^1.0.7, argparse@~1.0.9: version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== arr-diff@^2.0.0: @@ -3334,22 +3391,22 @@ array-back@^4.0.1, array-back@^4.0.2: array-differ@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== array-flatten@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== array-ify@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array-unique@^0.2.1: @@ -3364,22 +3421,22 @@ array-unique@^0.3.2: arrify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== arrify@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== asap@^2.0.0: version "2.0.6" - resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== assert-plus@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== assign-symbols@^1.0.0: @@ -3389,7 +3446,7 @@ assign-symbols@^1.0.0: astral-regex@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async-each@^1.0.0: @@ -3398,18 +3455,18 @@ async-each@^1.0.0: integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== async@^3.2.3: - version "3.2.4" - resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz" - integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== at-least-node@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== atob@^2.1.2: @@ -3419,12 +3476,12 @@ atob@^2.1.2: atomic-sleep@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== avvio@^7.1.2: version "7.2.5" - resolved "https://registry.npmjs.org/avvio/-/avvio-7.2.5.tgz" + resolved "https://registry.yarnpkg.com/avvio/-/avvio-7.2.5.tgz#65ba255f10b0bea7ac6eded71a5344cd88f5de19" integrity sha512-AOhBxyLVdpOad3TujtC9kL/9r3HnTkxwQ5ggOsYrvvZP1cCFvzHWJd5XxZDFuTn+IN8vkKSG5SEJrd27vCSbeA== dependencies: archy "^1.0.0" @@ -3434,14 +3491,14 @@ avvio@^7.1.2: axios@0.26.1: version "0.26.1" - resolved "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== dependencies: follow-redirects "^1.14.8" axios@1.6.2: version "1.6.2" - resolved "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2" integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A== dependencies: follow-redirects "^1.15.0" @@ -3450,17 +3507,17 @@ axios@1.6.2: axios@^0.21.4: version "0.21.4" - resolved "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: follow-redirects "^1.14.0" axios@^1.0.0: - version "1.5.0" - resolved "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz" - integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.9.0.tgz#25534e3b72b54540077d33046f77e3b8d7081901" + integrity sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg== dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.6" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -3593,22 +3650,25 @@ babel-polyfill@^6.26.0: regenerator-runtime "^0.10.5" babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz#9a929eafece419612ef4ae4f60b1862ebad8ef30" + integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" babel-preset-jest@^29.6.3: version "29.6.3" @@ -3682,24 +3742,24 @@ babylon@^6.18.0: balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base-x@^3.0.6: - version "3.0.9" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" - integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + version "3.0.11" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.11.tgz#40d80e2a1aeacba29792ccc6c5354806421287ff" + integrity sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA== dependencies: safe-buffer "^5.0.1" base-x@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz" - integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== + version "4.0.1" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.1.tgz#817fb7b57143c501f649805cb247617ad016a885" + integrity sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw== base64-js@^1.3.1: version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base@^0.11.1: @@ -3717,24 +3777,19 @@ base@^0.11.1: basic-auth@~2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== dependencies: safe-buffer "5.1.2" -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - before-after-hook@^2.1.0, before-after-hook@^2.2.0: version "2.2.3" - resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== bin-links@^3.0.0: version "3.0.3" - resolved "https://registry.npmjs.org/bin-links/-/bin-links-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-3.0.3.tgz#3842711ef3db2cd9f16a5f404a996a12db355a6e" integrity sha512-zKdnMPWEdh4F5INR07/eBrodC7QrF5JKvqskjz/ZZRXg5YSAZIbn8zGhbhUrElzHBZ2fvEQdOU59RHcTG3GiwA== dependencies: cmd-shim "^5.0.0" @@ -3749,21 +3804,26 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + bindings@^1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" bintrees@1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw== bl@^4.0.3, bl@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" @@ -3771,18 +3831,18 @@ bl@^4.0.3, bl@^4.1.0: readable-stream "^3.4.0" bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + version "4.12.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.2.tgz#3d8fed6796c24e177737f7cc5172ee04ef39ec99" + integrity sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw== bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + version "5.2.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" + integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== body-parser@1.20.1: version "1.20.1" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== dependencies: bytes "3.1.2" @@ -3800,7 +3860,7 @@ body-parser@1.20.1: body-parser@1.20.2: version "1.20.2" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" @@ -3816,9 +3876,23 @@ body-parser@1.20.2: type-is "~1.6.18" unpipe "1.0.0" +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -3826,7 +3900,7 @@ brace-expansion@^1.1.7: brace-expansion@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== dependencies: balanced-match "^1.0.0" @@ -3856,27 +3930,32 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" brorand@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browserslist@^4.22.2: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserslist@^4.24.0: + version "4.24.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.5.tgz#aa0f5b8560fe81fde84c6dcb38f759bafba0e11b" + integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw== dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + caniuse-lite "^1.0.30001716" + electron-to-chromium "^1.5.149" + node-releases "^2.0.19" + update-browserslist-db "^1.1.3" bs-logger@0.x, bs-logger@^0.2.6: version "0.2.6" @@ -3887,7 +3966,7 @@ bs-logger@0.x, bs-logger@^0.2.6: bs58@5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== dependencies: base-x "^4.0.0" @@ -3901,17 +3980,17 @@ bser@2.1.1: buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer-writer@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== buffer@^5.5.0: version "5.7.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: base64-js "^1.3.1" @@ -3919,29 +3998,29 @@ buffer@^5.5.0: builtins@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== builtins@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz" - integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + version "5.1.0" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.1.0.tgz#6d85eeb360c4ebc166c3fdef922a15aa7316a5e8" + integrity sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg== dependencies: semver "^7.0.0" byte-size@^7.0.0: version "7.0.1" - resolved "https://registry.npmjs.org/byte-size/-/byte-size-7.0.1.tgz" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-7.0.1.tgz#b1daf3386de7ab9d706b941a748dbfc71130dee3" integrity sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A== bytes@3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^16.0.0, cacache@^16.0.6, cacache@^16.1.0: version "16.1.3" - resolved "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e" integrity sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ== dependencies: "@npmcli/fs" "^2.1.0" @@ -3963,24 +4042,6 @@ cacache@^16.0.0, cacache@^16.0.6, cacache@^16.1.0: tar "^6.1.11" unique-filename "^2.0.0" -cacache@^17.0.0: - version "17.1.4" - resolved "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz" - integrity sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A== - dependencies: - "@npmcli/fs" "^3.1.0" - fs-minipass "^3.0.0" - glob "^10.2.2" - lru-cache "^7.7.1" - minipass "^7.0.3" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - p-map "^4.0.0" - ssri "^10.0.0" - tar "^6.1.11" - unique-filename "^3.0.0" - cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -3996,22 +4057,30 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -call-bind@^1.0.0: +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bound@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase-keys@^6.2.2: version "6.2.2" - resolved "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== dependencies: camelcase "^5.3.1" @@ -4020,22 +4089,22 @@ camelcase-keys@^6.2.2: camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.2.0: +camelcase@^6.0.0, camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001587: - version "1.0.30001616" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001616.tgz#4342712750d35f71ebba9fcac65e2cf8870013c3" - integrity sha512-RHVYKov7IcdNjVHJFNY/78RdG4oGVjbayxv8u5IO74Wv7Hlq4PnJE6mo/OjFijjVFNy5ijnCt6H3IIo4t+wfEw== +caniuse-lite@^1.0.30001716: + version "1.0.30001718" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz#dae13a9c80d517c30c6197515a96131c194d8f82" + integrity sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw== chalk@4.1.2, chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -4054,7 +4123,7 @@ chalk@^1.1.3: chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -4063,7 +4132,7 @@ chalk@^2.4.2: chalk@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== dependencies: ansi-styles "^4.1.0" @@ -4076,7 +4145,7 @@ char-regex@^1.0.2: chardet@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== chokidar@^1.6.1: @@ -4095,14 +4164,36 @@ chokidar@^1.6.1: optionalDependencies: fsevents "^1.0.0" +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + chownr@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== ci-info@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0: @@ -4111,9 +4202,9 @@ ci-info@^3.2.0: integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== cjs-module-lexer@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" - integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== + version "1.4.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" + integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== class-utils@^0.3.5: version "0.3.6" @@ -4127,29 +4218,34 @@ class-utils@^0.3.5: clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cli-cursor@3.1.0, cli-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: restore-cursor "^3.1.0" cli-spinners@2.6.1: version "2.6.1" - resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== cli-spinners@^2.2.0, cli-spinners@^2.5.0: - version "2.9.1" - resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz" - integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ== + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== cli-table3@~0.5.0: version "0.5.1" - resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== dependencies: object-assign "^4.1.0" @@ -4159,12 +4255,12 @@ cli-table3@~0.5.0: cli-width@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== cliui@^7.0.2: version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" @@ -4173,7 +4269,7 @@ cliui@^7.0.2: cliui@^8.0.1: version "8.0.1" - resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -4182,7 +4278,7 @@ cliui@^8.0.1: clone-deep@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== dependencies: is-plain-object "^2.0.4" @@ -4191,12 +4287,12 @@ clone-deep@^4.0.1: clone@^1.0.2: version "1.0.4" - resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== cmd-shim@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/cmd-shim/-/cmd-shim-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-5.0.0.tgz#8d0aaa1a6b0708630694c4dbde070ed94c707724" integrity sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw== dependencies: mkdirp-infer-owner "^2.0.0" @@ -4221,46 +4317,41 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-support@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== colors@^1.1.2, colors@^1.3.3: version "1.4.0" - resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -colors@~1.2.1: - version "1.2.5" - resolved "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz" - integrity sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg== - columnify@^1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" integrity sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q== dependencies: strip-ansi "^6.0.1" @@ -4268,11 +4359,16 @@ columnify@^1.6.0: combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + command-line-args@^5.1.1: version "5.2.1" resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" @@ -4295,17 +4391,22 @@ command-line-usage@^6.1.0: commander@^2.11.0, commander@^2.20.3: version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^8.1.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + common-ancestor-path@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== compare-func@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA== dependencies: array-ify "^1.0.0" @@ -4318,12 +4419,12 @@ component-emitter@^1.2.1: concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== dependencies: buffer-from "^1.0.0" @@ -4333,7 +4434,7 @@ concat-stream@^2.0.0: config-chain@^1.1.12: version "1.1.13" - resolved "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== dependencies: ini "^1.3.4" @@ -4341,31 +4442,24 @@ config-chain@^1.1.12: console-control-strings@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -console-table-printer@^2.11.1: - version "2.11.2" - resolved "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.11.2.tgz" - integrity sha512-uuUHie0sfPP542TKGzPFal0W1wo1beuKAqIZdaavcONx8OoqdnJRKjkinbRTOta4FaCa1RcIL+7mMJWX3pQGVg== - dependencies: - simple-wcswidth "^1.0.1" - content-disposition@0.5.4: version "0.5.4" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: safe-buffer "5.2.1" content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== conventional-changelog-angular@^5.0.12: version "5.0.13" - resolved "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c" integrity sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA== dependencies: compare-func "^2.0.0" @@ -4373,7 +4467,7 @@ conventional-changelog-angular@^5.0.12: conventional-changelog-core@^4.2.4: version "4.2.4" - resolved "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz" + resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz#e50d047e8ebacf63fac3dc67bf918177001e1e9f" integrity sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg== dependencies: add-stream "^1.0.0" @@ -4393,12 +4487,12 @@ conventional-changelog-core@^4.2.4: conventional-changelog-preset-loader@^2.3.4: version "2.3.4" - resolved "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz" + resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c" integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== conventional-changelog-writer@^5.0.0: version "5.0.1" - resolved "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359" integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ== dependencies: conventional-commits-filter "^2.0.7" @@ -4413,7 +4507,7 @@ conventional-changelog-writer@^5.0.0: conventional-commits-filter@^2.0.7: version "2.0.7" - resolved "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz#f8d9b4f182fce00c9af7139da49365b136c8a0b3" integrity sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA== dependencies: lodash.ismatch "^4.4.0" @@ -4421,7 +4515,7 @@ conventional-commits-filter@^2.0.7: conventional-commits-parser@^3.2.0: version "3.2.4" - resolved "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== dependencies: JSONStream "^1.0.4" @@ -4433,7 +4527,7 @@ conventional-commits-parser@^3.2.0: conventional-recommended-bump@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz#cfa623285d1de554012f2ffde70d9c8a22231f55" integrity sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw== dependencies: concat-stream "^2.0.0" @@ -4457,17 +4551,17 @@ convert-source-map@^2.0.0: cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== cookie@0.5.0, cookie@^0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== cookie@^0.4.1: version "0.4.2" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== copy-descriptor@^0.1.0: @@ -4480,14 +4574,19 @@ core-js@^2.4.0, core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-util-is@1.0.2, core-util-is@~1.0.0: +core-util-is@1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cors@2.8.5: version "2.8.5" - resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" @@ -4495,7 +4594,7 @@ cors@2.8.5: cosmiconfig@6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== dependencies: "@types/parse-json" "^4.0.0" @@ -4506,7 +4605,7 @@ cosmiconfig@6.0.0: cosmiconfig@^7.0.0: version "7.1.0" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" @@ -4535,15 +4634,15 @@ create-require@^1.1.0: cross-fetch@4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== dependencies: node-fetch "^2.6.12" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -4551,36 +4650,36 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: dargs@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== dateformat@^3.0.0: version "3.0.3" - resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@^4.4.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: - ms "2.1.2" + ms "^2.1.3" debuglog@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw== decamelize-keys@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== dependencies: decamelize "^1.1.0" @@ -4588,9 +4687,14 @@ decamelize-keys@^1.1.0: decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + decode-uri-component@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" @@ -4598,13 +4702,13 @@ decode-uri-component@^0.2.0: dedent@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== dedent@^1.0.0: - version "1.5.3" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" - integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== + version "1.6.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.6.0.tgz#79d52d6389b1ffa67d2bcef59ba51847a9d503b2" + integrity sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA== deep-extend@~0.6.0: version "0.6.0" @@ -4618,19 +4722,19 @@ deep-is@^0.1.3: deepmerge@^4.2.2: version "4.3.1" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== defaults@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== dependencies: clone "^1.0.2" define-lazy-prop@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== define-property@^0.2.5: @@ -4657,32 +4761,32 @@ define-property@^2.0.2: delay@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== depd@2.0.0, depd@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== deprecation@^2.0.0: version "2.3.1" - resolved "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== destroy@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-indent@^4.0.0: @@ -4694,12 +4798,12 @@ detect-indent@^4.0.0: detect-indent@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g== detect-indent@^6.0.0: version "6.1.0" - resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== detect-newline@^3.0.0: @@ -4709,7 +4813,7 @@ detect-newline@^3.0.0: dezalgo@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== dependencies: asap "^2.0.0" @@ -4725,9 +4829,14 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" @@ -4741,86 +4850,88 @@ doctrine@^3.0.0: dom-walk@^0.1.0: version "0.1.2" - resolved "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== dot-prop@^5.1.0: version "5.3.0" - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" dot-prop@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== dependencies: is-obj "^2.0.0" dotenv@~10.0.0: version "10.0.0" - resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== dottie@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.6.tgz#34564ebfc6ec5e5772272d466424ad5b696484d4" integrity sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA== +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + duplexer@^0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^4.1.1, duplexify@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz" - integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + version "4.1.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== dependencies: end-of-stream "^1.4.1" inherits "^2.0.3" readable-stream "^3.1.1" - stream-shift "^1.0.0" + stream-shift "^1.0.2" eastasianwidth@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== ee-first@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== ejs@^2.6.1: version "2.7.4" - resolved "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -ejs@^3.1.10: +ejs@^3.1.10, ejs@^3.1.7: version "3.1.10" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== dependencies: jake "^10.8.5" -ejs@^3.1.7: - version "3.1.9" - resolved "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz" - integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ== - dependencies: - jake "^10.8.5" +electron-to-chromium@^1.5.149: + version "1.5.155" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz#809dd0ae9ae1db87c358e0c0c17c09a2ffc432d1" + integrity sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng== -electron-to-chromium@^1.4.668: - version "1.4.758" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.758.tgz#f39e530cae2ca4329a0f0e1840629d8d1da73156" - integrity sha512-/o9x6TCdrYZBMdGeTifAP3wlF/gVT+TtWJe3BSmtNh92Mw81U9hrYwW9OAGUh+sEOX/yz5e34sksqRruZbjYrw== - -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== +elliptic@6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -4832,7 +4943,7 @@ elliptic@6.5.4: emittery@^0.10.0: version "0.10.2" - resolved "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== emittery@^0.13.1: @@ -4842,99 +4953,129 @@ emittery@^0.13.1: emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.2.2: version "9.2.2" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== encoding@^0.1.13: version "0.1.13" - resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: iconv-lite "^0.6.2" end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" - resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" enquirer@2.3.4: version "2.3.4" - resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.4.tgz" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.4.tgz#c608f2e1134c7f68c1c9ee056de13f9b31076de9" integrity sha512-pkYrrDZumL2VS6VBGDhqbajCM2xpkUNLuKfGPjfKaSIBKYopQbqEFyrOkRMIb2HDR/rO1kGhEt/5twBwtzKBXw== dependencies: ansi-colors "^3.2.1" +enquirer@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + enquirer@~2.3.6: version "2.3.6" - resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== dependencies: ansi-colors "^4.1.1" env-paths@2.2.1, env-paths@^2.2.0: version "2.2.1" - resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== envinfo@^7.7.4: - version "7.10.0" - resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz" - integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw== + version "7.14.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" + integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== err-code@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + es6-promise@^4.0.3: version "4.2.8" - resolved "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== es6-promisify@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== dependencies: es6-promise "^4.0.3" -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escalade@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: @@ -4970,7 +5111,7 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -5073,13 +5214,13 @@ espree@^9.6.0, espree@^9.6.1: esprima@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" @@ -5102,53 +5243,50 @@ esutils@^2.0.2: etag@~1.8.1: version "1.8.1" - resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -ethers@5.7.0, ethers@^5.6.0: - version "5.7.0" - resolved "https://registry.npmjs.org/ethers/-/ethers-5.7.0.tgz" - integrity sha512-5Xhzp2ZQRi0Em+0OkOcRHxPzCfoBfgtOQA+RUylSkuHbhTEaQklnYi2hsWbRgs3ztJsXVXd9VKBcO1ScWL8YfA== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.0" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.0" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.0" - "@ethersproject/wordlists" "5.7.0" +ethereum-cryptography@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + +ethereum-cryptography@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== + dependencies: + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + +ethers@6.13.7: + version "6.13.7" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.7.tgz#7457fcb32413b441a3ee6e9f4cd63bf782de6226" + integrity sha512-qbaJ0uIrjh+huP1Lad2f2QtzW5dcqSVjIzVH6yWB4dKoMuj2WqYz5aMeeQTCNpAKgTJBM5J9vcc2cYJ23UAimQ== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" eventemitter3@^4.0.4: version "4.0.7" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== evt@1.10.1: version "1.10.1" - resolved "https://registry.npmjs.org/evt/-/evt-1.10.1.tgz" + resolved "https://registry.yarnpkg.com/evt/-/evt-1.10.1.tgz#2f25b6f9588f4a8951aa541d968e2d5d1ea94fd8" integrity sha512-0vkCFzH3Q2Qb9gs3yav4p3uu+l4mcIfKPTRFTO1WHYZd0+O/ZR7BgzpuF+FbqOJ6r9q20/sDL/5TQM+de0/hyg== dependencies: minimal-polyfills "^2.1.5" @@ -5156,7 +5294,7 @@ evt@1.10.1: evt@1.9.12: version "1.9.12" - resolved "https://registry.npmjs.org/evt/-/evt-1.9.12.tgz" + resolved "https://registry.yarnpkg.com/evt/-/evt-1.9.12.tgz#8d06177259cbcb09ef936e18945bf7ddd087170c" integrity sha512-u8wC4Xif2pcDJ9cEm0wzWCIQb+Y214m1eUgsgm2hVIuXuvC6LToryA0Ecl1O8Slii2E9l6USLsyxXWntjlnIbw== dependencies: minimal-polyfills "^2.1.5" @@ -5164,7 +5302,7 @@ evt@1.9.12: execa@^3.0.0: version "3.4.0" - resolved "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz" + resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== dependencies: cross-spawn "^7.0.0" @@ -5180,7 +5318,7 @@ execa@^3.0.0: execa@^5.0.0: version "5.1.1" - resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" @@ -5237,13 +5375,13 @@ expect@^29.0.0, expect@^29.7.0: jest-util "^29.7.0" exponential-backoff@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz" - integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91" + integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA== express@4.18.2: version "4.18.2" - resolved "https://registry.npmjs.org/express/-/express-4.18.2.tgz" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: accepts "~1.3.8" @@ -5295,7 +5433,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: external-editor@^3.0.3: version "3.1.0" - resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: chardet "^0.7.0" @@ -5325,27 +5463,27 @@ extglob@^2.0.4: extsprintf@^1.2.0: version "1.4.1" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== eyes@^0.1.8: version "0.1.8" - resolved "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== fast-decode-uri-component@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-glob@3.2.7: version "3.2.7" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -5355,24 +5493,24 @@ fast-glob@3.2.7: micromatch "^4.0.4" fast-glob@^3.2.9: - version "3.3.1" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.4" + micromatch "^4.0.8" fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-json-stringify@^2.5.2: version "2.7.13" - resolved "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz#277aa86c2acba4d9851bd6108ed657aa327ed8c0" integrity sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA== dependencies: ajv "^6.11.0" @@ -5386,28 +5524,33 @@ fast-levenshtein@^2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-redact@^3.0.0: - version "3.3.0" - resolved "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz" - integrity sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ== + version "3.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== fast-safe-stringify@^2.0.8: version "2.1.1" - resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== +fast-uri@^3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" + integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== + fastify-error@^0.3.0: version "0.3.1" - resolved "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz" + resolved "https://registry.yarnpkg.com/fastify-error/-/fastify-error-0.3.1.tgz#8eb993e15e3cf57f0357fc452af9290f1c1278d2" integrity sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ== fastify-warning@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/fastify-warning/-/fastify-warning-0.2.0.tgz#e717776026a4493dc9a2befa44db6d17f618008f" integrity sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw== fastify@3.25.0: version "3.25.0" - resolved "https://registry.npmjs.org/fastify/-/fastify-3.25.0.tgz" + resolved "https://registry.yarnpkg.com/fastify/-/fastify-3.25.0.tgz#04b682fa738c6468bc36efba9f1e943609502111" integrity sha512-GblpjS7yuJ9jpkz1guHTyzlVQn9NYvGrMkDLtoxctEt7n1d6MSwA9i3p10HjNiY+zVurPf3YdOqXsJmVgAR3cg== dependencies: "@fastify/ajv-compiler" "^1.0.0" @@ -5427,9 +5570,9 @@ fastify@3.25.0: tiny-lru "^7.0.0" fastq@^1.6.0, fastq@^1.6.1: - version "1.15.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== dependencies: reusify "^1.0.4" @@ -5440,9 +5583,14 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fdir@^6.4.4: + version "6.4.4" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9" + integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== + figures@3.2.0, figures@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== dependencies: escape-string-regexp "^1.0.5" @@ -5456,12 +5604,12 @@ file-entry-cache@^6.0.1: file-uri-to-path@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== filelist@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== dependencies: minimatch "^5.0.1" @@ -5492,16 +5640,16 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" finalhandler@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" @@ -5514,7 +5662,7 @@ finalhandler@1.2.0: find-my-way@^4.1.0: version "4.5.1" - resolved "https://registry.npmjs.org/find-my-way/-/find-my-way-4.5.1.tgz" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-4.5.1.tgz#758e959194b90aea0270db18fff75e2fceb2239f" integrity sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg== dependencies: fast-decode-uri-component "^1.0.1" @@ -5531,14 +5679,14 @@ find-replace@^3.0.0: find-up@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -5563,23 +5711,23 @@ flat-cache@^3.0.4: flat@^5.0.2: version "5.0.2" - resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatstr@^1.0.12: version "1.0.12" - resolved "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz" + resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== -follow-redirects@^1.14.0, follow-redirects@^1.14.8, follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.8, follow-redirects@^1.15.0, follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" @@ -5594,27 +5742,38 @@ for-own@^0.1.4: for-in "^1.0.1" foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== dependencies: - cross-spawn "^7.0.0" + cross-spawn "^7.0.6" signal-exit "^4.0.1" form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + version "4.0.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" + integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" mime-types "^2.1.12" forwarded@0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -5624,24 +5783,24 @@ fragment-cache@^0.2.1: fresh@0.5.2: version "0.5.2" - resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs-constants@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-extra@^11.1.0: - version "11.1.1" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz" - integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== +fs-extra@^11.1.0, fs-extra@~11.3.0: + version "11.3.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" + integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^7.0.0: +fs-extra@^7.0.0, fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -5652,7 +5811,7 @@ fs-extra@^7.0.0: fs-extra@^9.1.0: version "9.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== dependencies: at-least-node "^1.0.0" @@ -5662,7 +5821,7 @@ fs-extra@^9.1.0: fs-jetpack@^2.2.2: version "2.4.0" - resolved "https://registry.npmjs.org/fs-jetpack/-/fs-jetpack-2.4.0.tgz" + resolved "https://registry.yarnpkg.com/fs-jetpack/-/fs-jetpack-2.4.0.tgz#6080c4ab464a019d37a404baeb47f32af8835026" integrity sha512-S/o9Dd7K9A7gicVU32eT8G0kHcmSu0rCVdP79P0MWInKFb8XpTc8Syhoo66k9no+HDshtlh4pUJTws8X+8fdFQ== dependencies: minimatch "^3.0.2" @@ -5670,7 +5829,7 @@ fs-jetpack@^2.2.2: fs-jetpack@^4.1.0: version "4.3.1" - resolved "https://registry.npmjs.org/fs-jetpack/-/fs-jetpack-4.3.1.tgz" + resolved "https://registry.yarnpkg.com/fs-jetpack/-/fs-jetpack-4.3.1.tgz#cdfd4b64e6bfdec7c7dc55c76b39efaa7853bb20" integrity sha512-dbeOK84F6BiQzk2yqqCVwCPWTxAvVGJ3fMQc6E2wuEohS28mR6yHngbrKuVCK1KHRx/ccByDylqu4H5PCP2urQ== dependencies: minimatch "^3.0.2" @@ -5678,18 +5837,11 @@ fs-jetpack@^4.1.0: fs-minipass@^2.0.0, fs-minipass@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" -fs-minipass@^3.0.0: - version "3.0.3" - resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz" - integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== - dependencies: - minipass "^7.0.3" - fs-readdir-recursive@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" @@ -5697,7 +5849,7 @@ fs-readdir-recursive@^1.0.0: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^1.0.0: @@ -5708,19 +5860,19 @@ fsevents@^1.0.0: bindings "^1.5.0" nan "^2.12.1" -fsevents@^2.3.2: +fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1, function-bind@^1.1.2: +function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gauge@^4.0.3: version "4.0.4" - resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== dependencies: aproba "^1.0.3 || ^2.0.0" @@ -5739,18 +5891,24 @@ gensync@^1.0.0-beta.2: get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2: - version "1.2.1" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== +get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" get-package-type@^0.1.0: version "0.1.0" @@ -5759,7 +5917,7 @@ get-package-type@^0.1.0: get-pkg-repo@^4.0.0: version "4.2.1" - resolved "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz" + resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz#75973e1c8050c73f48190c52047c4cee3acbf385" integrity sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA== dependencies: "@hutson/parse-repository-url" "^3.0.0" @@ -5769,19 +5927,27 @@ get-pkg-repo@^4.0.0: get-port@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" get-stream@^6.0.0: version "6.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== get-value@^2.0.3, get-value@^2.0.6: @@ -5791,7 +5957,7 @@ get-value@^2.0.3, get-value@^2.0.6: git-raw-commits@^2.0.8: version "2.0.11" - resolved "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== dependencies: dargs "^7.0.0" @@ -5802,7 +5968,7 @@ git-raw-commits@^2.0.8: git-remote-origin-url@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" integrity sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw== dependencies: gitconfiglocal "^1.0.0" @@ -5810,7 +5976,7 @@ git-remote-origin-url@^2.0.0: git-semver-tags@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-4.1.1.tgz#63191bcd809b0ec3e151ba4751c16c444e5b5780" integrity sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA== dependencies: meow "^8.0.0" @@ -5818,22 +5984,22 @@ git-semver-tags@^4.1.1: git-up@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/git-up/-/git-up-7.0.0.tgz#bace30786e36f56ea341b6f69adfd83286337467" integrity sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ== dependencies: is-ssh "^1.4.0" parse-url "^8.1.0" git-url-parse@^13.1.0: - version "13.1.0" - resolved "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz" - integrity sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA== + version "13.1.1" + resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-13.1.1.tgz#664bddf0857c6a75b3c1f0ae6239abb08a1486d4" + integrity sha512-PCFJyeSSdtnbfhSNRw9Wk96dDCNx+sogTe4YNXeXSJxt7xz5hvXekuRn9JX7m+Mf4OscCu8h+mtAl3+h5Fo8lQ== dependencies: git-up "^7.0.0" gitconfiglocal@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" integrity sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ== dependencies: ini "^1.3.2" @@ -5853,9 +6019,9 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob-parent@^5.1.1, glob-parent@^5.1.2: +glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -5869,7 +6035,7 @@ glob-parent@^6.0.2: glob@7.1.4: version "7.1.4" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== dependencies: fs.realpath "^1.0.0" @@ -5891,20 +6057,21 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^10.2.2: - version "10.3.4" - resolved "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz" - integrity sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ== +glob@^11.0.1: + version "11.0.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.2.tgz#3261e3897bbc603030b041fd77ba636022d51ce0" + integrity sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ== dependencies: foreground-child "^3.1.0" - jackspeak "^2.0.3" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" + jackspeak "^4.0.1" + minimatch "^10.0.0" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^2.0.0" glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -5914,9 +6081,9 @@ glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.1: +glob@^8.0.1, glob@^8.1.0: version "8.1.0" - resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: fs.realpath "^1.0.0" @@ -5927,7 +6094,7 @@ glob@^8.0.1: global@4.4.0: version "4.4.0" - resolved "https://registry.npmjs.org/global/-/global-4.4.0.tgz" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== dependencies: min-document "^2.19.0" @@ -5952,7 +6119,7 @@ globals@^9.18.0: globby@^11.0.2, globby@^11.1.0: version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -5964,7 +6131,7 @@ globby@^11.0.2, globby@^11.1.0: gluegun@4.7.0: version "4.7.0" - resolved "https://registry.npmjs.org/gluegun/-/gluegun-4.7.0.tgz" + resolved "https://registry.yarnpkg.com/gluegun/-/gluegun-4.7.0.tgz#d1e88828ec6737d966619fff07c04f7e689dc59e" integrity sha512-St+J/rly0FoWLeISgBGDuymwF3/b8OdmxBCbSvK1hXEoRbaaATiRpPepJSJWuRYR7cGR7Hy9drgQwGFBAolhbQ== dependencies: apisauce "^2.0.1" @@ -5999,9 +6166,14 @@ gluegun@4.7.0: which "^2.0.0" yargs-parser "^16.1.0" +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphemer@^1.4.0: @@ -6011,19 +6183,19 @@ graphemer@^1.4.0: graphql-tag@2.12.6: version "2.12.6" - resolved "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== dependencies: tslib "^2.1.0" graphql@16.8.0: version "16.8.0" - resolved "https://registry.npmjs.org/graphql/-/graphql-16.8.0.tgz" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.0.tgz#374478b7f27b2dc6153c8f42c1b80157f79d79d4" integrity sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg== handlebars@^4.7.7: version "4.7.8" - resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" @@ -6035,9 +6207,56 @@ handlebars@^4.7.7: hard-rejection@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== +hardhat@^2.22.16: + version "2.24.0" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.24.0.tgz#33dbe8c3972c2d2db6206966e19466571a937932" + integrity sha512-wDkD5GPmttYv21MR7tGDkyQ22tO2V86OEV8pA7NcXWYUpibe8XZ2EanXCeRHO61vwEx0f7/M+NqrhJwasaNMJg== + dependencies: + "@ethereumjs/util" "^9.1.0" + "@ethersproject/abi" "^5.1.2" + "@nomicfoundation/edr" "^0.11.0" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chokidar "^4.0.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + find-up "^5.0.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + json-stream-stringify "^3.1.4" + keccak "^3.0.2" + lodash "^4.17.11" + micro-eth-signer "^0.14.0" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + picocolors "^1.1.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.8.26" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tinyglobby "^0.2.6" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -6047,27 +6266,29 @@ has-ansi@^2.0.0: has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" has-unicode@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== has-value@^0.3.1: @@ -6101,36 +6322,34 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hasown@^2.0.0: +hasown@^2.0.0, hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + helmet@7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/helmet/-/helmet-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/helmet/-/helmet-7.0.0.tgz#ac3011ba82fa2467f58075afa58a49427ba6212d" integrity sha512-MsIgYmdBh460ZZ8cJC81q4XJknjG567wzEmv46WOBblDb6TUd3z8/GhgmsM9pn8g2B80tAJ4m5/d3Bi1KrSUBQ== hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" @@ -6147,26 +6366,26 @@ home-or-tmp@^2.0.0: hosted-git-info@^2.1.4: version "2.8.9" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== hosted-git-info@^3.0.6: version "3.0.8" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d" integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw== dependencies: lru-cache "^6.0.0" hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: version "4.1.0" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" hosted-git-info@^5.0.0: version "5.2.1" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-5.2.1.tgz#0ba1c97178ef91f3ab30842ae63d6a272341156f" integrity sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw== dependencies: lru-cache "^7.5.1" @@ -6176,14 +6395,14 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== +http-cache-semantics@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" + integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== http-errors@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: depd "2.0.0" @@ -6194,7 +6413,7 @@ http-errors@2.0.0: http-proxy-agent@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== dependencies: "@tootallnate/once" "2" @@ -6203,7 +6422,7 @@ http-proxy-agent@^5.0.0: https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -6211,96 +6430,101 @@ https-proxy-agent@^5.0.0: human-signals@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== human-signals@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== humanize-ms@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== dependencies: ms "^2.0.0" iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.6.2: version "0.6.3" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" ieee754@^1.1.13: version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore-walk@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776" integrity sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw== dependencies: minimatch "^5.0.1" -ignore@^5.0.4, ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -ignore@^5.2.4: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== +immutable@^4.0.0-rc.12: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== import-fresh@^3.1.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" +import-lazy@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== + import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== infer-owner@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflection@^1.13.4: version "1.13.4" - resolved "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32" integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -6308,17 +6532,17 @@ inflight@^1.0.4: inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== ini@^1.3.2, ini@^1.3.4: version "1.3.8" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== init-package-json@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/init-package-json/-/init-package-json-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-3.0.2.tgz#f5bc9bac93f2bdc005778bc2271be642fecfcd69" integrity sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A== dependencies: npm-package-arg "^9.0.1" @@ -6331,7 +6555,7 @@ init-package-json@^3.0.2: inquirer@^8.2.4: version "8.2.6" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== dependencies: ansi-escapes "^4.2.1" @@ -6357,14 +6581,24 @@ invariant@^2.2.2: dependencies: loose-envify "^1.0.0" -ip@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz" - integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== is-accessor-descriptor@^1.0.1: @@ -6376,7 +6610,7 @@ is-accessor-descriptor@^1.0.1: is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-binary-path@^1.0.0: @@ -6386,6 +6620,13 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -6393,17 +6634,17 @@ is-buffer@^1.1.5: is-ci@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== dependencies: ci-info "^2.0.0" -is-core-module@^2.13.0, is-core-module@^2.5.0, is-core-module@^2.8.1: - version "2.13.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== +is-core-module@^2.16.0, is-core-module@^2.5.0, is-core-module@^2.8.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - has "^1.0.3" + hasown "^2.0.2" is-data-descriptor@^1.0.1: version "1.0.1" @@ -6430,7 +6671,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" - resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== is-dotfile@^1.0.0: @@ -6464,7 +6705,7 @@ is-extglob@^1.0.0: is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-finite@^1.0.0: @@ -6474,12 +6715,12 @@ is-finite@^1.0.0: is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-generator-fn@^2.0.0: @@ -6494,21 +6735,21 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-interactive@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== is-lambda@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== is-number@^2.1.0: @@ -6532,12 +6773,12 @@ is-number@^4.0.0: is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-obj@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-path-inside@^3.0.3: @@ -6547,24 +6788,24 @@ is-path-inside@^3.0.3: is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== -is-plain-obj@^2.0.0: +is-plain-obj@^2.0.0, is-plain-obj@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-plain-object@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== is-posix-bracket@^0.1.0: @@ -6578,32 +6819,32 @@ is-primitive@^2.0.0: integrity sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q== is-ssh@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz" - integrity sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ== + version "1.4.1" + resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.4.1.tgz#76de1cdbe8f92a8b905d1a172b6bc09704c20396" + integrity sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg== dependencies: protocols "^2.0.1" is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== is-text-path@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w== dependencies: text-extensions "^1.0.0" is-typedarray@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== is-windows@^1.0.2: @@ -6613,19 +6854,19 @@ is-windows@^1.0.2: is-wsl@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== dependencies: is-docker "^2.0.0" isarray@1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^2.0.0: @@ -6637,12 +6878,12 @@ isobject@^2.0.0: isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== isomorphic-fetch@3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== dependencies: node-fetch "^2.6.1" @@ -6650,7 +6891,7 @@ isomorphic-fetch@3.0.0: isomorphic-ws@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: @@ -6670,9 +6911,9 @@ istanbul-lib-instrument@^5.0.4: semver "^6.3.0" istanbul-lib-instrument@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" - integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== dependencies: "@babel/core" "^7.23.9" "@babel/parser" "^7.23.9" @@ -6706,19 +6947,17 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jackspeak@^2.0.3: - version "2.3.3" - resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.3.tgz" - integrity sha512-R2bUw+kVZFS/h1AZqBKrSgDmdmjApzgY0AlCPumopFiAlbUxE2gf+SCuBzQ0cP5hHmUmFYF5yw55T97Th5Kstg== +jackspeak@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.0.tgz#c489c079f2b636dc4cbe9b0312a13ff1282e561b" + integrity sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw== dependencies: "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" jake@^10.8.5: - version "10.8.7" - resolved "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz" - integrity sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w== + version "10.9.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" + integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== dependencies: async "^3.2.3" chalk "^4.0.2" @@ -6727,7 +6966,7 @@ jake@^10.8.5: jayson@3.6.6: version "3.6.6" - resolved "https://registry.npmjs.org/jayson/-/jayson-3.6.6.tgz" + resolved "https://registry.yarnpkg.com/jayson/-/jayson-3.6.6.tgz#189984f624e398f831bd2be8e8c80eb3abf764a1" integrity sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ== dependencies: "@types/connect" "^3.4.33" @@ -7104,14 +7343,19 @@ jest@<30.0.0-0: import-local "^3.0.2" jest-cli "^29.7.0" +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== + js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" - resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-tokens@^3.0.2: @@ -7121,28 +7365,33 @@ js-tokens@^3.0.2: js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" js-yaml@^3.10.0, js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" esprima "^4.0.0" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== json-buffer@3.0.1: version "3.0.1" @@ -7151,22 +7400,22 @@ json-buffer@3.0.1: json-parse-better-errors@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-stable-stringify-without-jsonify@^1.0.1: @@ -7174,14 +7423,19 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stream-stringify@^3.1.4: + version "3.1.6" + resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" + integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== + json-stringify-nice@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== json-stringify-safe@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== json5@^0.5.1: @@ -7191,12 +7445,12 @@ json5@^0.5.1: json5@^2.2.2, json5@^2.2.3: version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonc-parser@3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== jsonfile@^4.0.0: @@ -7208,7 +7462,7 @@ jsonfile@^4.0.0: jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" @@ -7217,19 +7471,28 @@ jsonfile@^6.0.1: jsonparse@^1.2.0, jsonparse@^1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== just-diff-apply@^5.2.0: version "5.5.0" - resolved "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-5.5.0.tgz#771c2ca9fa69f3d2b54e7c3f5c1dfcbcc47f9f0f" integrity sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw== just-diff@^5.0.1: version "5.2.0" - resolved "https://registry.npmjs.org/just-diff/-/just-diff-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-5.2.0.tgz#60dca55891cf24cd4a094e33504660692348a241" integrity sha512-6ufhP9SHjb7jibNFrNxyFZ6od3g+An6Ai9mhGRvcYe8UJlH0prseN64M+6ZBBUoKYHZsitDP42gAJ8+eVWr3lw== +keccak@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -7253,7 +7516,7 @@ kind-of@^4.0.0: kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== kleur@^3.0.3: @@ -7263,7 +7526,7 @@ kleur@^3.0.3: lerna@6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/lerna/-/lerna-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/lerna/-/lerna-6.1.0.tgz#693145393ec22fd3ca98d817deab2246c1e2b107" integrity sha512-3qAjIj8dgBwHtCAiLbq4VU/C1V9D1tvTLm2owZubdGAN72aB5TxuCu2mcw+yeEorOcXuR9YWx7EXIkAf+G0N2w== dependencies: "@lerna/add" "6.1.0" @@ -7305,7 +7568,7 @@ levn@^0.4.1: libnpmaccess@^6.0.3: version "6.0.4" - resolved "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-6.0.4.tgz" + resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-6.0.4.tgz#2dd158bd8a071817e2207d3b201d37cf1ad6ae6b" integrity sha512-qZ3wcfIyUoW0+qSFkMBovcTrSGJ3ZeyvpR7d5N9pEYv/kXs8sHP2wiqEIXBKLFrZlmM0kR0RJD7mtfLngtlLag== dependencies: aproba "^2.0.0" @@ -7315,7 +7578,7 @@ libnpmaccess@^6.0.3: libnpmpublish@^6.0.4: version "6.0.5" - resolved "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-6.0.5.tgz" + resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-6.0.5.tgz#5a894f3de2e267d62f86be2a508e362599b5a4b1" integrity sha512-LUR08JKSviZiqrYTDfywvtnsnxr+tOvBU0BF8H+9frt7HMvc6Qn6F8Ubm72g5hDTHbq8qupKfDvDAln2TVPvFg== dependencies: normalize-package-data "^4.0.0" @@ -7326,7 +7589,7 @@ libnpmpublish@^6.0.4: light-my-request@^4.2.0: version "4.12.0" - resolved "https://registry.npmjs.org/light-my-request/-/light-my-request-4.12.0.tgz" + resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-4.12.0.tgz#fd59329a7b4f794842103c7bef69e12252478831" integrity sha512-0y+9VIfJEsPVzK5ArSIJ8Dkxp8QMP7/aCuxCUtG/tr9a2NoOf/snATE/OUc05XUplJCEnRh6gTkH7xh9POt1DQ== dependencies: ajv "^8.1.0" @@ -7336,17 +7599,17 @@ light-my-request@^4.2.0: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== lines-and-columns@~2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz" - integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== + version "2.0.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.4.tgz#d00318855905d2660d8c0822e3f5a4715855fc42" + integrity sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A== load-json-file@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== dependencies: graceful-fs "^4.1.2" @@ -7356,7 +7619,7 @@ load-json-file@^4.0.0: load-json-file@^6.2.0: version "6.2.0" - resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1" integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ== dependencies: graceful-fs "^4.1.15" @@ -7366,7 +7629,7 @@ load-json-file@^6.2.0: locate-path@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" @@ -7374,7 +7637,7 @@ locate-path@^2.0.0: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" @@ -7388,47 +7651,47 @@ locate-path@^6.0.0: lodash.camelcase@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== lodash.clonedeep@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== lodash.groupby@^4.6.0: version "4.6.0" - resolved "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.groupby/-/lodash.groupby-4.6.0.tgz#0b08a1dcf68397c397855c3239783832df7403d1" integrity sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw== -lodash.isequal@4.5.0: +lodash.isequal@4.5.0, lodash.isequal@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== lodash.ismatch@^4.4.0: version "4.4.0" - resolved "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g== lodash.kebabcase@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== lodash.lowercase@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz#46515aced4acb0b7093133333af068e4c3b14e9d" integrity sha512-UcvP1IZYyDKyEL64mmrwoA1AbFu5ahojhTtkOUr1K9dbuxzS9ev8i4TxMMGCqRC9TE8uDaSoufNAXxRPNTseVA== lodash.lowerfirst@^4.3.1: version "4.3.1" - resolved "https://registry.npmjs.org/lodash.lowerfirst/-/lodash.lowerfirst-4.3.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.lowerfirst/-/lodash.lowerfirst-4.3.1.tgz#de3c7b12e02c6524a0059c2f6cb7c5c52655a13d" integrity sha512-UUKX7VhP1/JL54NXg2aq/E1Sfnjjes8fNYTNkPU8ZmsaVeBvPHKdbNaN79Re5XRL01u6wbq3j0cbYZj71Fcu5w== lodash.mapvalues@^4.6.0: version "4.6.0" - resolved "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" integrity sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ== lodash.memoize@4.x, lodash.memoize@^4.1.2: @@ -7443,89 +7706,89 @@ lodash.merge@^4.6.2: lodash.pad@^4.5.1: version "4.5.1" - resolved "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" integrity sha512-mvUHifnLqM+03YNzeTBS1/Gr6JRFjd3rRx88FHWUvamVaT9k2O/kXha3yBSOwB9/DTQrSTLJNHvLBBt2FdX7Mg== lodash.padend@^4.6.1: version "4.6.1" - resolved "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" integrity sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw== lodash.padstart@^4.6.1: version "4.6.1" - resolved "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" integrity sha512-sW73O6S8+Tg66eY56DBk85aQzzUJDtpoXFBgELMd5P/SotAguo+1kYO6RuYgXxA4HJH3LFTFPASX6ET6bjfriw== lodash.repeat@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/lodash.repeat/-/lodash.repeat-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44" integrity sha512-eWsgQW89IewS95ZOcr15HHCX6FVDxq3f2PNUIng3fyzsPev9imFQxIYdFZ6crl8L56UR6ZlGDLcEb3RZsCSSqw== lodash.snakecase@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== lodash.startcase@^4.4.0: version "4.4.0" - resolved "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz#9436e34ed26093ed7ffae1936144350915d9add8" integrity sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg== lodash.trim@^4.5.1: version "4.5.1" - resolved "https://registry.npmjs.org/lodash.trim/-/lodash.trim-4.5.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.trim/-/lodash.trim-4.5.1.tgz#36425e7ee90be4aa5e27bcebb85b7d11ea47aa57" integrity sha512-nJAlRl/K+eiOehWKDzoBVrSMhK0K3A3YQsUNXHQa5yIrKBAhsZgSu3KoAFoFT+mEgiyBHddZ0pRk1ITpIp90Wg== lodash.trimend@^4.5.1: version "4.5.1" - resolved "https://registry.npmjs.org/lodash.trimend/-/lodash.trimend-4.5.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.trimend/-/lodash.trimend-4.5.1.tgz#12804437286b98cad8996b79414e11300114082f" integrity sha512-lsD+k73XztDsMBKPKvzHXRKFNMohTjoTKIIo4ADLn5dA65LZ1BqlAvSXhR2rPEC3BgAUQnzMnorqDtqn2z4IHA== lodash.trimstart@^4.5.1: version "4.5.1" - resolved "https://registry.npmjs.org/lodash.trimstart/-/lodash.trimstart-4.5.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.trimstart/-/lodash.trimstart-4.5.1.tgz#8ff4dec532d82486af59573c39445914e944a7f1" integrity sha512-b/+D6La8tU76L/61/aN0jULWHkT0EeJCmVstPBn/K9MtD2qBW83AsBNrr63dKuWYwVMO7ucv13QNO/Ek/2RKaQ== lodash.truncate@^4.4.2: version "4.4.2" - resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== lodash.uppercase@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/lodash.uppercase/-/lodash.uppercase-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.uppercase/-/lodash.uppercase-4.3.0.tgz#c404abfd1469f93931f9bb24cf6cc7d57059bc73" integrity sha512-+Nbnxkj7s8K5U8z6KnEYPGUOGp3woZbB7Ecs7v3LkkjLQSm2kP9SKIILitN1ktn2mB/tmM9oSlku06I+/lH7QA== lodash.upperfirst@^4.3.1: version "4.3.1" - resolved "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz" + resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== lodash.xor@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.xor/-/lodash.xor-4.5.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6" integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ== lodash.zip@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" integrity sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg== -lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-symbols@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== dependencies: chalk "^2.4.2" log-symbols@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: chalk "^4.1.0" @@ -7533,11 +7796,16 @@ log-symbols@^4.1.0: loose-envify@^1.0.0: version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.1.0.tgz#afafb060607108132dbc1cf8ae661afb69486117" + integrity sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -7547,29 +7815,24 @@ lru-cache@^5.1.1: lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: version "7.18.3" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -"lru-cache@^9.1.1 || ^10.0.0": - version "10.0.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz" - integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== - lru_map@^0.3.3: version "0.3.3" - resolved "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== make-dir@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== dependencies: pify "^4.0.1" @@ -7577,7 +7840,7 @@ make-dir@^2.1.0: make-dir@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" @@ -7594,9 +7857,9 @@ make-error@1.x, make-error@^1.1.1, make-error@^1.3.6: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -make-fetch-happen@^10.0.6: +make-fetch-happen@^10.0.3, make-fetch-happen@^10.0.6: version "10.2.1" - resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164" integrity sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w== dependencies: agentkeepalive "^4.2.1" @@ -7616,27 +7879,6 @@ make-fetch-happen@^10.0.6: socks-proxy-agent "^7.0.0" ssri "^9.0.0" -make-fetch-happen@^11.0.3: - version "11.1.1" - resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz" - integrity sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w== - dependencies: - agentkeepalive "^4.2.1" - cacache "^17.0.0" - http-cache-semantics "^4.1.1" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^7.7.1" - minipass "^5.0.0" - minipass-fetch "^3.0.0" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.3" - promise-retry "^2.0.1" - socks-proxy-agent "^7.0.0" - ssri "^10.0.0" - makeerror@1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" @@ -7651,12 +7893,12 @@ map-cache@^0.2.2: map-obj@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== map-obj@^4.0.0: version "4.3.0" - resolved "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== map-visit@^1.0.0: @@ -7666,6 +7908,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + math-random@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" @@ -7673,12 +7920,17 @@ math-random@^1.0.1: media-typer@0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + meow@^8.0.0: version "8.1.2" - resolved "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz" + resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== dependencies: "@types/minimist" "^1.2.0" @@ -7695,24 +7947,40 @@ meow@^8.0.0: merge-descriptors@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== methods@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micro-eth-signer@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz#8aa1fe997d98d6bdf42f2071cef7eb01a66ecb22" + integrity sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw== + dependencies: + "@noble/curves" "~1.8.1" + "@noble/hashes" "~1.7.1" + micro-packed "~0.7.2" + +micro-packed@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/micro-packed/-/micro-packed-0.7.3.tgz#59e96b139dffeda22705c7a041476f24cabb12b6" + integrity sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg== + dependencies: + "@scure/base" "~1.2.5" + micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -7751,94 +8019,94 @@ micromatch@^3.1.10: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== +micromatch@^4.0.4, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" mime-db@1.52.0: version "1.52.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mime@1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== min-document@^2.19.0: version "2.19.0" - resolved "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== dependencies: dom-walk "^0.1.0" min-indent@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== minimal-polyfills@^2.1.5, minimal-polyfills@^2.2.3: version "2.2.3" - resolved "https://registry.npmjs.org/minimal-polyfills/-/minimal-polyfills-2.2.3.tgz" + resolved "https://registry.yarnpkg.com/minimal-polyfills/-/minimal-polyfills-2.2.3.tgz#22af58de16807b325f29b83ca38ffb83e75ec3f4" integrity sha512-oxdmJ9cL+xV72h0xYxp4tP2d5/fTBpP45H8DIOn9pASuF8a3IYTf+25fMGDYGiWW+MFsuog6KD6nfmhZJQ+uUw== minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== minimatch@3.0.5: version "3.0.5" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" integrity sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw== dependencies: brace-expansion "^1.1.7" +minimatch@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: +minimatch@^5.0.1, minimatch@^5.1.6: version "5.1.6" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimist-options@4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== dependencies: arrify "^1.0.1" @@ -7847,19 +8115,19 @@ minimist-options@4.1.0: minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass-collect@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== dependencies: minipass "^3.0.0" minipass-fetch@^2.0.3: version "2.1.2" - resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz#95560b50c472d81a3bc76f20ede80eaed76d8add" integrity sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA== dependencies: minipass "^3.1.6" @@ -7868,66 +8136,55 @@ minipass-fetch@^2.0.3: optionalDependencies: encoding "^0.1.13" -minipass-fetch@^3.0.0: - version "3.0.4" - resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz" - integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== - dependencies: - minipass "^7.0.3" - minipass-sized "^1.0.3" - minizlib "^2.1.2" - optionalDependencies: - encoding "^0.1.13" - minipass-flush@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== dependencies: minipass "^3.0.0" minipass-json-stream@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz" - integrity sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-json-stream/-/minipass-json-stream-1.0.2.tgz#5121616c77a11c406c3ffa77509e0b77bb267ec3" + integrity sha512-myxeeTm57lYs8pH2nxPzmEEg8DGIgW+9mv6D4JZD2pa81I/OBjeU7PtICXV6c9eRGTA5JMDsuIPUZRCyBMYNhg== dependencies: jsonparse "^1.3.1" minipass "^3.0.0" minipass-pipeline@^1.2.4: version "1.2.4" - resolved "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== dependencies: minipass "^3.0.0" minipass-sized@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== dependencies: minipass "^3.0.0" minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: version "3.3.6" - resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: yallist "^4.0.0" minipass@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3: - version "7.0.3" - resolved "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz" - integrity sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg== +minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" @@ -7943,7 +8200,7 @@ mixin-deep@^1.2.0: mkdirp-infer-owner@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz#55d3b368e7d89065c38f32fd38e638f0ab61d316" integrity sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw== dependencies: chownr "^2.0.0" @@ -7959,29 +8216,62 @@ mkdirp@^0.5.1: mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0: + version "10.8.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" + integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== + dependencies: + ansi-colors "^4.1.3" + browser-stdout "^1.3.1" + chokidar "^3.5.3" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^8.1.0" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" + yargs-unparser "^2.0.0" + modify-values@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== moment-timezone@^0.5.43: - version "0.5.43" - resolved "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz" - integrity sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ== + version "0.5.48" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.48.tgz#111727bb274734a518ae154b5ca589283f058967" + integrity sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw== dependencies: moment "^2.29.4" moment@^2.29.4: - version "2.29.4" - resolved "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== morgan@1.10.0: version "1.10.0" - resolved "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== dependencies: basic-auth "~2.0.1" @@ -7992,22 +8282,17 @@ morgan@1.10.0: ms@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.0.0: +ms@2.1.3, ms@^2.0.0, ms@^2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== multimatch@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6" integrity sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA== dependencies: "@types/minimatch" "^3.0.3" @@ -8018,13 +8303,13 @@ multimatch@^5.0.0: mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" - resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== nan@^2.12.1: - version "2.19.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" - integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== + version "2.22.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.2.tgz#6b504fd029fb8f38c0990e52ad5c26772fdacfbb" + integrity sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ== nanomatch@^1.2.9: version "1.2.13" @@ -8048,48 +8333,58 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -negotiator@0.6.3, negotiator@^0.6.3: +negotiator@0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@^0.6.3: + version "0.6.4" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + neo-async@^2.6.2: version "2.6.2" - resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== ngeohash@0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/ngeohash/-/ngeohash-0.6.3.tgz" + resolved "https://registry.yarnpkg.com/ngeohash/-/ngeohash-0.6.3.tgz#10b1e80be5488262ec95c56cf2dbb6c45fbdf245" integrity sha512-kltF0cOxgx1AbmVzKxYZaoB0aj7mOxZeHaerEtQV0YaqnkXNq26WWqMmJ6lTqShYxVRWZ/mwvvTrNeOwdslWiw== +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + node-addon-api@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: version "2.7.0" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" -node-gyp-build@^4.3.0: - version "4.6.1" - resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz" - integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.8.4" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" + integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== node-gyp@^9.0.0: - version "9.4.0" - resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz" - integrity sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg== + version "9.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.1.tgz#8a1023e0d6766ecb52764cc3a734b36ff275e185" + integrity sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ== dependencies: env-paths "^2.2.0" exponential-backoff "^3.1.1" glob "^7.1.4" graceful-fs "^4.2.6" - make-fetch-happen "^11.0.3" + make-fetch-happen "^10.0.3" nopt "^6.0.0" npmlog "^6.0.0" rimraf "^3.0.2" @@ -8102,28 +8397,28 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== nopt@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" nopt@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d" integrity sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g== dependencies: abbrev "^1.0.0" normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: hosted-git-info "^2.1.4" @@ -8133,7 +8428,7 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: normalize-package-data@^3.0.0: version "3.0.3" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== dependencies: hosted-git-info "^4.0.1" @@ -8143,7 +8438,7 @@ normalize-package-data@^3.0.0: normalize-package-data@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-4.0.1.tgz#b46b24e0616d06cadf9d5718b29b6d445a82a62c" integrity sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg== dependencies: hosted-git-info "^5.0.0" @@ -8158,45 +8453,45 @@ normalize-path@^2.0.0, normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== npm-bundled@^1.1.1: version "1.1.2" - resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== dependencies: npm-normalize-package-bin "^1.0.1" npm-bundled@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-2.0.1.tgz#94113f7eb342cd7a67de1e789f896b04d2c600f4" integrity sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw== dependencies: npm-normalize-package-bin "^2.0.0" npm-install-checks@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-5.0.0.tgz#5ff27d209a4e3542b8ac6b0c1db6063506248234" integrity sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA== dependencies: semver "^7.1.1" npm-normalize-package-bin@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== npm-normalize-package-bin@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff" integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ== npm-package-arg@8.1.1: version "8.1.1" - resolved "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.1.tgz" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.1.tgz#00ebf16ac395c63318e67ce66780a06db6df1b04" integrity sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg== dependencies: hosted-git-info "^3.0.6" @@ -8205,7 +8500,7 @@ npm-package-arg@8.1.1: npm-package-arg@^9.0.0, npm-package-arg@^9.0.1: version "9.1.2" - resolved "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-9.1.2.tgz#fc8acecb00235f42270dda446f36926ddd9ac2bc" integrity sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg== dependencies: hosted-git-info "^5.0.0" @@ -8215,7 +8510,7 @@ npm-package-arg@^9.0.0, npm-package-arg@^9.0.1: npm-packlist@^5.1.0, npm-packlist@^5.1.1: version "5.1.3" - resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.3.tgz#69d253e6fd664b9058b85005905012e00e69274b" integrity sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg== dependencies: glob "^8.0.1" @@ -8225,7 +8520,7 @@ npm-packlist@^5.1.0, npm-packlist@^5.1.1: npm-pick-manifest@^7.0.0: version "7.0.2" - resolved "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz#1d372b4e7ea7c6712316c0e99388a73ed3496e84" integrity sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw== dependencies: npm-install-checks "^5.0.0" @@ -8235,7 +8530,7 @@ npm-pick-manifest@^7.0.0: npm-registry-fetch@^13.0.0, npm-registry-fetch@^13.0.1, npm-registry-fetch@^13.3.0: version "13.3.1" - resolved "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz#bb078b5fa6c52774116ae501ba1af2a33166af7e" integrity sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw== dependencies: make-fetch-happen "^10.0.6" @@ -8248,14 +8543,14 @@ npm-registry-fetch@^13.0.0, npm-registry-fetch@^13.0.1, npm-registry-fetch@^13.3 npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" npmlog@^6.0.0, npmlog@^6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== dependencies: are-we-there-yet "^3.0.0" @@ -8265,7 +8560,7 @@ npmlog@^6.0.0, npmlog@^6.0.2: nx@15.9.7, "nx@>=14.8.6 < 16": version "15.9.7" - resolved "https://registry.npmjs.org/nx/-/nx-15.9.7.tgz" + resolved "https://registry.yarnpkg.com/nx/-/nx-15.9.7.tgz#f0e713cedb8637a517d9c4795c99afec4959a1b6" integrity sha512-1qlEeDjX9OKZEryC8i4bA+twNg+lB5RKrozlNwWx/lLJHqWPUfvUTvxh+uxlPYL9KzVReQjUuxMLFMsHNqWUrA== dependencies: "@nrwl/cli" "15.9.7" @@ -8316,7 +8611,7 @@ nx@15.9.7, "nx@>=14.8.6 < 16": object-assign@^4, object-assign@^4.1.0: version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-copy@^0.1.0: @@ -8328,10 +8623,10 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== object-visit@^1.0.0: version "1.0.1" @@ -8355,47 +8650,52 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" +obliterator@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.5.tgz#031e0145354b0c18840336ae51d41e7d6d2c76aa" + integrity sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw== + on-exit-leak-free@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== on-finished@2.4.1: version "2.4.1" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" on-finished@~2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" on-headers@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" open@^8.4.0: version "8.4.2" - resolved "https://registry.npmjs.org/open/-/open-8.4.2.tgz" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== dependencies: define-lazy-prop "^2.0.0" @@ -8416,7 +8716,7 @@ optionator@^0.9.3: ora@^4.0.0: version "4.1.1" - resolved "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/ora/-/ora-4.1.1.tgz#566cc0348a15c36f5f0e979612842e02ba9dddbc" integrity sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A== dependencies: chalk "^3.0.0" @@ -8430,7 +8730,7 @@ ora@^4.0.0: ora@^5.4.1: version "5.4.1" - resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== dependencies: bl "^4.1.0" @@ -8450,7 +8750,7 @@ os-homedir@^1.0.0: os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== output-file-sync@^1.1.2: @@ -8464,52 +8764,52 @@ output-file-sync@^1.1.2: p-filter@2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c" integrity sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw== dependencies: p-map "^2.0.0" p-finally@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-finally@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== p-limit@^1.1.0: version "1.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: p-try "^1.0.0" p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" @@ -8523,29 +8823,29 @@ p-locate@^5.0.0: p-map-series@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-2.1.0.tgz#7560d4c452d9da0c07e692fdbfe6e2c81a2a91f2" integrity sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q== p-map@4.0.0, p-map@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" p-map@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== p-pipe@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/p-pipe/-/p-pipe-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw== p-queue@6.6.2, p-queue@^6.6.2: version "6.6.2" - resolved "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== dependencies: eventemitter3 "^4.0.4" @@ -8553,12 +8853,12 @@ p-queue@6.6.2, p-queue@^6.6.2: p-reduce@2.1.0, p-reduce@^2.0.0, p-reduce@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.1.0.tgz#09408da49507c6c274faa31f28df334bc712b64a" integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== p-retry@4.6.1: version "4.6.1" - resolved "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== dependencies: "@types/retry" "^0.12.0" @@ -8566,41 +8866,46 @@ p-retry@4.6.1: p-timeout@4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-4.1.0.tgz#788253c0452ab0ffecf18a62dff94ff1bd09ca0a" integrity sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw== p-timeout@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== p-waterfall@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/p-waterfall/-/p-waterfall-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-2.1.1.tgz#63153a774f472ccdc4eb281cdb2967fcf158b2ee" integrity sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw== dependencies: p-reduce "^2.0.0" +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + packet-reader@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== pacote@^13.0.3, pacote@^13.6.1: version "13.6.2" - resolved "https://registry.npmjs.org/pacote/-/pacote-13.6.2.tgz" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-13.6.2.tgz#0d444ba3618ab3e5cd330b451c22967bbd0ca48a" integrity sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg== dependencies: "@npmcli/git" "^3.0.0" @@ -8627,14 +8932,14 @@ pacote@^13.0.3, pacote@^13.6.1: parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-conflict-json@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz#3d05bc8ffe07d39600dc6436c6aefe382033d323" integrity sha512-jDbRGb00TAPFsKWCpZZOT93SxVP9nONOSgES3AevqRq/CHvavEBvKAjxX9p5Y5F0RZLxH9Ufd9+RwtCsa+lFDA== dependencies: json-parse-even-better-errors "^2.3.1" @@ -8653,7 +8958,7 @@ parse-glob@^3.0.4: parse-json@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== dependencies: error-ex "^1.3.1" @@ -8661,7 +8966,7 @@ parse-json@^4.0.0: parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -8670,27 +8975,27 @@ parse-json@^5.0.0, parse-json@^5.2.0: lines-and-columns "^1.1.6" parse-path@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz" - integrity sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog== + version "7.1.0" + resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-7.1.0.tgz#41fb513cb122831807a4c7b29c8727947a09d8c6" + integrity sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw== dependencies: protocols "^2.0.0" parse-url@^8.1.0: version "8.1.0" - resolved "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz" + resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-8.1.0.tgz#972e0827ed4b57fc85f0ea6b0d839f0d8a57a57d" integrity sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w== dependencies: parse-path "^7.0.0" parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== parsimmon@^1.18.1: version "1.18.1" - resolved "https://registry.npmjs.org/parsimmon/-/parsimmon-1.18.1.tgz" + resolved "https://registry.yarnpkg.com/parsimmon/-/parsimmon-1.18.1.tgz#d8dd9c28745647d02fc6566f217690897eed7709" integrity sha512-u7p959wLfGAhJpSDJVYXoyMCXWYwHia78HhRBWqk7AIbxdmlrfdp5wX0l3xv/iTSH5HvhN9K7o26hwwpgS5Nmw== pascalcase@^0.1.1: @@ -8700,89 +9005,89 @@ pascalcase@^0.1.1: path-exists@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.7: +path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== +path-scurry@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" + integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== dependencies: - lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + lru-cache "^11.0.0" + minipass "^7.1.2" path-to-regexp@0.1.7: version "0.1.7" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== path-type@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== dependencies: pify "^3.0.0" path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pg-cloudflare@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz" - integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== + version "1.2.5" + resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz#2e3649c38a7a9c74a7e5327c8098a2fd9af595bd" + integrity sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg== pg-connection-string@^2.6.1, pg-connection-string@^2.6.2: - version "2.6.2" - resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz" - integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA== + version "2.9.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.9.0.tgz#f75e06591fdd42ec7636fe2c6a03febeedbec9bf" + integrity sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ== pg-hstore@2.3.4: version "2.3.4" - resolved "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.4.tgz" + resolved "https://registry.yarnpkg.com/pg-hstore/-/pg-hstore-2.3.4.tgz#4425e3e2a3e15d2a334c35581186c27cf2e9b8dd" integrity sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA== dependencies: underscore "^1.13.1" pg-int8@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== pg-pool@^3.6.1: - version "3.6.1" - resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz" - integrity sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og== + version "3.10.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.10.0.tgz#134b0213755c5e7135152976488aa7cd7ee1268d" + integrity sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA== pg-protocol@^1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz" - integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q== + version "1.10.0" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.10.0.tgz#a473afcbb1c6e5dc3ac24869ba3dd563f8a1ae1b" + integrity sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q== pg-types@^2.1.0: version "2.2.0" - resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== dependencies: pg-int8 "1.0.1" @@ -8793,7 +9098,7 @@ pg-types@^2.1.0: pg@8.11.3: version "8.11.3" - resolved "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb" integrity sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g== dependencies: buffer-writer "2.0.0" @@ -8808,44 +9113,49 @@ pg@8.11.3: pgpass@1.x: version "1.0.5" - resolved "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== dependencies: split2 "^4.1.0" -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + pify@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== pify@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== pify@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pify@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== pino-abstract-transport@v0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0" integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ== dependencies: duplexify "^4.1.2" @@ -8853,24 +9163,24 @@ pino-abstract-transport@v0.5.0: pino-multi-stream@6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/pino-multi-stream/-/pino-multi-stream-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/pino-multi-stream/-/pino-multi-stream-6.0.0.tgz#2116bca740cb5eb606f430b20fd480f4944b2b99" integrity sha512-oCuTtaDSUB5xK1S45r9oWE0Dj8RWdHVvaGTft5pO/rmzgIqQRkilf5Ooilz3uRm0IYj8sPRho3lVx48LCmXjvQ== dependencies: pino "^7.0.0" pino-std-serializers@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz#b56487c402d882eb96cd67c257868016b61ad671" integrity sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg== pino-std-serializers@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2" integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q== pino@7.6.0: version "7.6.0" - resolved "https://registry.npmjs.org/pino/-/pino-7.6.0.tgz" + resolved "https://registry.yarnpkg.com/pino/-/pino-7.6.0.tgz#f9abd13e221e15855e3cf6e88a2b6280527b3800" integrity sha512-CCCdryvM/chT0CDt9jQ1//z62RpSXPrzUFUpY4b8eKCVq3T2T3UF6DomoczkPze9d6VFiTyVF6Y8A6F9iAyAxg== dependencies: fast-redact "^3.0.0" @@ -8886,7 +9196,7 @@ pino@7.6.0: pino@^6.13.0: version "6.14.0" - resolved "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz" + resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78" integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg== dependencies: fast-redact "^3.0.0" @@ -8899,7 +9209,7 @@ pino@^6.13.0: pino@^7.0.0: version "7.11.0" - resolved "https://registry.npmjs.org/pino/-/pino-7.11.0.tgz" + resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6" integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg== dependencies: atomic-sleep "^1.0.0" @@ -8915,20 +9225,20 @@ pino@^7.0.0: thread-stream "^0.15.1" pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" pluralize@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== posix-character-classes@^0.1.0: @@ -8938,22 +9248,22 @@ posix-character-classes@^0.1.0: postgres-array@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== postgres-bytea@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== postgres-date@~1.0.4: version "1.0.7" - resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== postgres-interval@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== dependencies: xtend "^4.0.0" @@ -8994,49 +9304,49 @@ private@^0.1.8: proc-log@^2.0.0, proc-log@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685" integrity sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw== process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process-warning@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== process@^0.11.10: version "0.11.10" - resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== prom-client@14.2.0: version "14.2.0" - resolved "https://registry.npmjs.org/prom-client/-/prom-client-14.2.0.tgz" + resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-14.2.0.tgz#ca94504e64156f6506574c25fb1c34df7812cf11" integrity sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA== dependencies: tdigest "^0.1.1" promise-all-reject-late@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2" integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== promise-call-limit@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/promise-call-limit/-/promise-call-limit-1.0.2.tgz#f64b8dd9ef7693c9c7613e7dfe8d6d24de3031ea" integrity sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA== promise-inflight@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== promise-retry@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== dependencies: err-code "^2.0.2" @@ -9052,24 +9362,24 @@ prompts@^2.0.1: promzard@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" integrity sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw== dependencies: read "1" proto-list@~1.2.1: version "1.2.4" - resolved "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== protocols@^2.0.0, protocols@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz" - integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q== + version "2.0.2" + resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.2.tgz#822e8fcdcb3df5356538b3e91bfd890b067fd0a4" + integrity sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ== proxy-addr@^2.0.7, proxy-addr@~2.0.7: version "2.0.7" - resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" @@ -9077,20 +9387,20 @@ proxy-addr@^2.0.7, proxy-addr@~2.0.7: proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== pump@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + version "3.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" + integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== dependencies: end-of-stream "^1.1.0" once "^1.3.1" pumpify@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e" integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw== dependencies: duplexify "^4.1.1" @@ -9109,39 +9419,39 @@ pure-rand@^6.0.0: q@^1.5.1: version "1.5.1" - resolved "https://registry.npmjs.org/q/-/q-1.5.1.tgz" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== qs@6.11.0: version "6.11.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" queue-microtask@^1.1.2, queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== quick-format-unescaped@^4.0.3: version "4.0.4" - resolved "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== quick-lru@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== ramda@^0.24.1: version "0.24.1" - resolved "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" integrity sha512-HEm619G8PaZMfkqCa23qiOe7r3R0brPu7ZgOsgKUsnvLhd0qhc/vTjkUovomgPWa5ECBa08fJZixth9LaoBo5w== ramdasauce@^2.1.0: version "2.1.3" - resolved "https://registry.npmjs.org/ramdasauce/-/ramdasauce-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ramdasauce/-/ramdasauce-2.1.3.tgz#acb45ecc7e4fc4d6f39e19989b4a16dff383e9c2" integrity sha512-Ml3CPim4SKwmg5g9UI77lnRSeKr/kQw7YhQ6rfdMcBYy6DMlwmkEwQqjygJ3OhxPR+NfFfpjKl3Tf8GXckaqqg== dependencies: ramda "^0.24.1" @@ -9155,14 +9465,21 @@ randomatic@^3.0.0: kind-of "^6.0.0" math-random "^1.0.1" +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== raw-body@2.5.1: version "2.5.1" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: bytes "3.1.2" @@ -9170,9 +9487,9 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" -raw-body@2.5.2: +raw-body@2.5.2, raw-body@^2.4.1: version "2.5.2" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" @@ -9187,12 +9504,12 @@ react-is@^18.0.0: read-cmd-shim@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz#868c235ec59d1de2db69e11aec885bc095aea087" integrity sha512-kEmDUoYf/CDy8yZbLTmhB1X9kkjf9Q80PCNsDMb7ufrGd6zZSQA1+UyjrO+pZm5K/S4OXCWJeiIt1JA8kAsa6g== read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" integrity sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ== dependencies: json-parse-even-better-errors "^2.3.0" @@ -9200,7 +9517,7 @@ read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3: read-package-json@^5.0.0, read-package-json@^5.0.1: version "5.0.2" - resolved "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.2.tgz" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-5.0.2.tgz#b8779ccfd169f523b67208a89cc912e3f663f3fa" integrity sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q== dependencies: glob "^8.0.1" @@ -9210,7 +9527,7 @@ read-package-json@^5.0.0, read-package-json@^5.0.1: read-pkg-up@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" integrity sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw== dependencies: find-up "^2.0.0" @@ -9218,7 +9535,7 @@ read-pkg-up@^3.0.0: read-pkg-up@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== dependencies: find-up "^4.1.0" @@ -9227,7 +9544,7 @@ read-pkg-up@^7.0.1: read-pkg@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA== dependencies: load-json-file "^4.0.0" @@ -9236,7 +9553,7 @@ read-pkg@^3.0.0: read-pkg@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== dependencies: "@types/normalize-package-data" "^2.4.0" @@ -9246,14 +9563,14 @@ read-pkg@^5.2.0: read@1, read@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/read/-/read-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ== dependencies: mute-stream "~0.0.4" "readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" @@ -9262,7 +9579,7 @@ read@1, read@^1.0.7: readable-stream@^2.0.2, readable-stream@~2.3.6: version "2.3.8" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" @@ -9275,7 +9592,7 @@ readable-stream@^2.0.2, readable-stream@~2.3.6: readdir-scoped-modules@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== dependencies: debuglog "^1.0.1" @@ -9292,14 +9609,26 @@ readdirp@^2.0.0: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + real-require@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== redent@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== dependencies: indent-string "^4.0.0" @@ -9359,29 +9688,29 @@ repeating@^2.0.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve-url@^0.2.1: @@ -9390,31 +9719,29 @@ resolve-url@^0.2.1: integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f" + integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== -resolve@^1.10.0: - version "1.22.6" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz" - integrity sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw== +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" + path-parse "^1.0.6" -resolve@^1.20.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== +resolve@^1.10.0, resolve@^1.20.0, resolve@~1.22.1: + version "1.22.10" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== dependencies: - is-core-module "^2.13.0" + is-core-module "^2.16.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" restore-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== dependencies: onetime "^5.1.0" @@ -9427,87 +9754,87 @@ ret@~0.1.10: ret@~0.2.0: version "0.2.2" - resolved "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== retry-as-promised@^7.0.4: - version "7.0.4" - resolved "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz" - integrity sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA== + version "7.1.1" + resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.1.1.tgz#3626246f04c1941ff10cebcfa3df0577fd8ab2d7" + integrity sha512-hMD7odLOt3LkTjcif8aRZqi/hybjpLNgSk5oF5FCowfCjok6LukpN2bDX7R5wDmbgBQFn7YoBxSagmtXHaJYJw== retry@^0.12.0: version "0.12.0" - resolved "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== retry@^0.13.1: version "0.13.1" - resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== rfdc@^1.1.4, rfdc@^1.2.0: - version "1.3.0" - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== rimraf@^2.6.3: version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" run-async@^2.4.0: version "2.4.1" - resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== run-exclusive@^2.2.14: version "2.2.19" - resolved "https://registry.npmjs.org/run-exclusive/-/run-exclusive-2.2.19.tgz" + resolved "https://registry.yarnpkg.com/run-exclusive/-/run-exclusive-2.2.19.tgz#37a2fb6e3671f8ae0d63521ebd1865fc796cf307" integrity sha512-K3mdoAi7tjJ/qT7Flj90L7QyPozwUaAG+CVhkdDje4HLKXUYC3N/Jzkau3flHVDLQVhiHBtcimVodMjN9egYbA== dependencies: minimal-polyfills "^2.2.3" run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" rxjs@^7.5.5: - version "7.8.1" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== dependencies: tslib "^2.1.0" safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-regex2@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-2.0.0.tgz#b287524c397c7a2994470367e0185e1916b1f5b9" integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ== dependencies: ret "~0.2.0" @@ -9520,60 +9847,50 @@ safe-regex@^1.1.0: ret "~0.1.10" safe-stable-stringify@^2.1.0: - version "2.4.3" - resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz" - integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scrypt-js@3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - secure-json-parse@^2.0.0: version "2.7.0" - resolved "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== semver-store@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9" integrity sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg== -"semver@2 || 3 || 4 || 5", semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: version "5.7.2" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@7.5.4, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.4: +semver@7.5.4, semver@~7.5.4: version "7.5.4" - resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.3: - version "7.6.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.1.tgz#60bfe090bf907a25aa8119a72b9f90ef7ca281b2" - integrity sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA== - -semver@^7.6.3: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.7.2: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== send@0.18.0: version "0.18.0" - resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" @@ -9592,12 +9909,12 @@ send@0.18.0: sequelize-pool@^7.1.0: version "7.1.0" - resolved "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz" + resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-7.1.0.tgz#210b391af4002762f823188fd6ecfc7413020768" integrity sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg== sequelize@6.33.0: version "6.33.0" - resolved "https://registry.npmjs.org/sequelize/-/sequelize-6.33.0.tgz" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.33.0.tgz#45c70d52687f1c7eae3a0496f21f7055d99b46da" integrity sha512-GkeCbqgaIcpyZ1EyXrDNIwktbfMldHAGOVXHGM4x8bxGSRAOql5htDWofPvwpfL/FoZ59CaFmfO3Mosv1lDbQw== dependencies: "@types/debug" "^4.1.8" @@ -9617,9 +9934,16 @@ sequelize@6.33.0: validator "^13.9.0" wkx "^0.5.0" +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + serve-static@1.15.0: version "1.15.0" - resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" @@ -9629,13 +9953,13 @@ serve-static@1.15.0: set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== set-cookie-parser@^2.4.1: - version "2.6.0" - resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz" - integrity sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ== + version "2.7.1" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" + integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" @@ -9649,52 +9973,78 @@ set-value@^2.0.0, set-value@^2.0.1: setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== shallow-clone@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== dependencies: kind-of "^6.0.2" shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signal-exit@^4.0.1: version "4.1.0" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -simple-wcswidth@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz" - integrity sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg== - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -9707,12 +10057,12 @@ slash@^1.0.0: slash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== slice-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: ansi-styles "^4.0.0" @@ -9721,7 +10071,7 @@ slice-ansi@^4.0.0: smart-buffer@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== snapdragon-node@^2.0.1: @@ -9756,7 +10106,7 @@ snapdragon@^0.8.1: socks-proxy-agent@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6" integrity sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww== dependencies: agent-base "^6.0.2" @@ -9764,16 +10114,29 @@ socks-proxy-agent@^7.0.0: socks "^2.6.2" socks@^2.6.2: - version "2.7.1" - resolved "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz" - integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + version "2.8.4" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.4.tgz#07109755cdd4da03269bda4725baa061ab56d5cc" + integrity sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ== dependencies: - ip "^2.0.0" + ip-address "^9.0.5" smart-buffer "^4.2.0" +solc@0.8.26: + version "0.8.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" + integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== + dependencies: + command-exists "^1.2.8" + commander "^8.1.0" + follow-redirects "^1.12.1" + js-sha3 "0.8.0" + memorystream "^0.3.1" + semver "^5.5.0" + tmp "0.0.33" + sonic-boom@^1.0.2: version "1.4.1" - resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.4.1.tgz#d35d6a74076624f12e6f917ade7b9d75e918f53e" integrity sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg== dependencies: atomic-sleep "^1.0.0" @@ -9781,21 +10144,21 @@ sonic-boom@^1.0.2: sonic-boom@^2.2.1: version "2.8.0" - resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== dependencies: atomic-sleep "^1.0.0" sort-keys@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" integrity sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg== dependencies: is-plain-obj "^1.0.0" sort-keys@^4.0.0: version "4.2.0" - resolved "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.2.0.tgz#6b7638cee42c506fff8c1cecde7376d21315be18" integrity sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg== dependencies: is-plain-obj "^2.0.0" @@ -9826,6 +10189,14 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" @@ -9838,34 +10209,34 @@ source-map@^0.5.6, source-map@^0.5.7: source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== spdx-correct@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.14" - resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.14.tgz" - integrity sha512-U0eS5wcpu/O2/QZk6PcAMOA8H3ZuvRe4mFHA3Q+LNl1SRDmfQ+mD3RoD6tItqnvqubJ32m/zV2Z/ikSmxccD1Q== + version "3.0.21" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz#6d6e980c9df2b6fc905343a3b2d702a6239536c3" + integrity sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -9876,38 +10247,36 @@ split-string@^3.0.1, split-string@^3.0.2: split2@^3.0.0, split2@^3.1.1: version "3.2.2" - resolved "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz" + resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== dependencies: readable-stream "^3.0.0" split2@^4.0.0, split2@^4.1.0: version "4.2.0" - resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== split@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/split/-/split-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== dependencies: through "2" +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -ssri@^10.0.0: - version "10.0.5" - resolved "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz" - integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== - dependencies: - minipass "^7.0.3" - ssri@^9.0.0, ssri@^9.0.1: version "9.0.1" - resolved "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057" integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q== dependencies: minipass "^3.1.1" @@ -9919,6 +10288,13 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stacktrace-parser@^0.1.10: + version "0.1.11" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz#c7c08f9b29ef566b9a6f7b255d7db572f66fabc4" + integrity sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg== + dependencies: + type-fest "^0.7.1" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -9929,17 +10305,17 @@ static-extend@^0.1.1: statuses@2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== string-argv@~0.3.1: version "0.3.2" - resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== string-format@^2.0.0: @@ -9957,21 +10333,21 @@ string-length@^4.0.1: string-similarity@^4.0.1: version "4.0.4" - resolved "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz" + resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -9980,7 +10356,7 @@ string-similarity@^4.0.1: string-width@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" @@ -9988,7 +10364,7 @@ string-width@^2.1.1: string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: eastasianwidth "^0.2.0" @@ -9997,21 +10373,21 @@ string-width@^5.0.1, string-width@^5.1.2: string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" @@ -10025,43 +10401,43 @@ strip-ansi@^3.0.0: strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-ansi@^7.0.1: version "7.1.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: ansi-regex "^6.0.1" strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== strip-indent@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== dependencies: min-indent "^1.0.0" @@ -10073,7 +10449,7 @@ strip-json-comments@^3.1.1: strong-log-transformer@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA== dependencies: duplexer "^0.1.1" @@ -10087,19 +10463,19 @@ supports-color@^2.0.0: supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" -supports-color@^8.0.0: +supports-color@^8.0.0, supports-color@^8.1.1, supports-color@~8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -10108,7 +10484,7 @@ supports-color@^8.0.0: supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== table-layout@^1.0.2: @@ -10123,7 +10499,7 @@ table-layout@^1.0.2: table@6.7.5: version "6.7.5" - resolved "https://registry.npmjs.org/table/-/table-6.7.5.tgz" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.5.tgz#f04478c351ef3d8c7904f0e8be90a1b62417d238" integrity sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw== dependencies: ajv "^8.0.1" @@ -10134,7 +10510,7 @@ table@6.7.5: tar-stream@~2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== dependencies: bl "^4.0.3" @@ -10144,9 +10520,9 @@ tar-stream@~2.2.0: readable-stream "^3.1.1" tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: - version "6.2.0" - resolved "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz" - integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" @@ -10157,14 +10533,14 @@ tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: tdigest@^0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced" integrity sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA== dependencies: bintrees "1.0.2" temp-dir@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== test-exclude@^6.0.0: @@ -10178,7 +10554,7 @@ test-exclude@^6.0.0: text-extensions@^1.0.0: version "1.9.0" - resolved "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz" + resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== text-table@^0.2.0: @@ -10188,21 +10564,21 @@ text-table@^0.2.0: thread-stream@^0.13.0: version "0.13.2" - resolved "https://registry.npmjs.org/thread-stream/-/thread-stream-0.13.2.tgz" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.13.2.tgz#de8ea87584baee625c631947ec73494aa86131c8" integrity sha512-woZFt0cLFkPdhsa+IGpRo1jiSouaHxMIljzTgt30CMjBWoUYbbcHqnunW5Yv+BXko9H05MVIcxMipI3Jblallw== dependencies: real-require "^0.1.0" thread-stream@^0.15.1: version "0.15.2" - resolved "https://registry.npmjs.org/thread-stream/-/thread-stream-0.15.2.tgz" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4" integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA== dependencies: real-require "^0.1.0" through2@^2.0.0: version "2.0.5" - resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== dependencies: readable-stream "~2.3.6" @@ -10210,7 +10586,7 @@ through2@^2.0.0: through2@^3.0.1: version "3.0.2" - resolved "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== dependencies: inherits "^2.0.4" @@ -10218,34 +10594,40 @@ through2@^3.0.1: through2@^4.0.0: version "4.0.2" - resolved "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== dependencies: readable-stream "3" through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== tiny-lru@^7.0.0: version "7.0.6" - resolved "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz" + resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24" integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow== -tmp@^0.0.33: +tinyglobby@^0.2.6: + version "0.2.13" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.13.tgz#a0e46515ce6cbcd65331537e57484af5a7b2ff7e" + integrity sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + +tmp@0.0.33, tmp@^0.0.33: version "0.0.33" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" tmp@~0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== tmpl@1.0.5: version "1.0.5" @@ -10257,11 +10639,6 @@ to-fast-properties@^1.0.3: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" @@ -10279,7 +10656,7 @@ to-regex-range@^2.1.0: to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" @@ -10296,27 +10673,27 @@ to-regex@^3.0.1, to-regex@^3.0.2: toidentifier@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== toposort-class@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" integrity sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg== tr46@~0.0.3: version "0.0.3" - resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== treeverse@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/treeverse/-/treeverse-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-2.0.0.tgz#036dcef04bc3fd79a9b79a68d4da03e882d8a9ca" integrity sha512-N5gJCkLu1aXccpOTtqV6ddSEi6ZmGkh3hjmbu1IjcavJK4qyOVQmi0myQKM7z5jVGmD68SJoliaVrMmVObhj6A== trim-newlines@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== trim-right@^1.0.1: @@ -10325,9 +10702,9 @@ trim-right@^1.0.1: integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== ts-api-utils@^1.0.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + version "1.4.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" + integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== ts-command-line-args@^2.2.0: version "2.5.1" @@ -10341,7 +10718,7 @@ ts-command-line-args@^2.2.0: ts-custom-error@^3.3.1: version "3.3.1" - resolved "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.3.1.tgz" + resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1" integrity sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A== ts-essentials@^7.0.1: @@ -10364,9 +10741,9 @@ ts-jest@29.1.1: yargs-parser "^21.0.1" ts-jest@^29.2.5: - version "29.2.5" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" - integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== + version "29.3.3" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.3.3.tgz#c24c31a9d12268f88899e3eeb05912cab42c574c" + integrity sha512-y6jLm19SL4GroiBmHwFK4dSHUfDNmOrJbRfp6QmDIlI9p5tT5Q8ItccB4pTIslCIqOZuQnBwpTR0bQ5eUMYwkw== dependencies: bs-logger "^0.2.6" ejs "^3.1.10" @@ -10375,7 +10752,8 @@ ts-jest@^29.2.5: json5 "^2.2.3" lodash.memoize "^4.1.2" make-error "^1.3.6" - semver "^7.6.3" + semver "^7.7.2" + type-fest "^4.41.0" yargs-parser "^21.1.1" ts-node@10.7.0: @@ -10399,22 +10777,32 @@ ts-node@10.7.0: tsconfig-paths@^4.1.2: version "4.2.0" - resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== dependencies: json5 "^2.2.2" minimist "^1.2.6" strip-bom "^3.0.0" +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + tslib@^1.9.3: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0: - version "2.6.2" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -10430,7 +10818,7 @@ type-detect@4.0.8: type-fest@^0.18.0: version "0.18.1" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== type-fest@^0.20.2: @@ -10440,32 +10828,42 @@ type-fest@^0.20.2: type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== type-fest@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" integrity sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw== type-fest@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + type-fest@^0.8.1: version "0.8.1" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== type-fest@^2.0.0: version "2.19.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== +type-fest@^4.41.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + type-is@~1.6.18: version "1.6.18" - resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" @@ -10489,14 +10887,14 @@ typechain@8.0.0: typedarray-to-buffer@^3.1.5: version "3.1.5" - resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typescript@5.2.2: @@ -10506,7 +10904,7 @@ typescript@5.2.2: "typescript@^3 || ^4": version "4.9.5" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== typical@^4.0.0: @@ -10520,13 +10918,13 @@ typical@^5.2.0: integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== uglify-js@^3.1.4: - version "3.17.4" - resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== umzug@3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/umzug/-/umzug-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/umzug/-/umzug-3.0.0.tgz#de19183c0bce7e79d432f746ad423b68b38d485a" integrity sha512-uHeJsOJ7qtoIkZmtknpg+iSlI25m7glBA237pYp5fMsEKnRfRY+F4FP8eGx28g6b0VujkniC6Zlz09lbDFuBbw== dependencies: "@rushstack/ts-command-line" "^4.7.7" @@ -10538,9 +10936,26 @@ umzug@3.0.0: verror "^1.10.0" underscore@^1.13.1: - version "1.13.6" - resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz" - integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + version "1.13.7" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.7.tgz#970e33963af9a7dda228f17ebe8399e5fbe63a10" + integrity sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici@^5.14.0: + version "5.29.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.29.0.tgz#419595449ae3f2cdcba3580a2e8903399bd1f5a3" + integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg== + dependencies: + "@fastify/busboy" "^2.0.0" union-value@^1.0.0: version "1.0.1" @@ -10554,36 +10969,22 @@ union-value@^1.0.0: unique-filename@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-2.0.1.tgz#e785f8675a9a7589e0ac77e0b5c34d2eaeac6da2" integrity sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A== dependencies: unique-slug "^3.0.0" -unique-filename@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz" - integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== - dependencies: - unique-slug "^4.0.0" - unique-slug@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-3.0.0.tgz#6d347cf57c8a7a7a6044aabd0e2d74e4d76dc7c9" integrity sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w== dependencies: imurmurhash "^0.1.4" -unique-slug@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz" - integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== - dependencies: - imurmurhash "^0.1.4" - universal-user-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz" - integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + version "6.0.1" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" + integrity sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ== universalify@^0.1.0: version "0.1.2" @@ -10591,13 +10992,13 @@ universalify@^0.1.0: integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unset-value@^1.0.0: @@ -10610,18 +11011,18 @@ unset-value@^1.0.0: upath@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== -update-browserslist-db@^1.0.13: - version "1.0.15" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz#60ed9f8cba4a728b7ecf7356f641a31e3a691d97" - integrity sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA== +update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== dependencies: - escalade "^3.1.2" - picocolors "^1.0.0" + escalade "^3.2.0" + picocolors "^1.1.1" -uri-js@4.2.2, uri-js@^4.2.2: +uri-js@4.2.2, uri-js@^4.2.2, uri-js@^4.4.1: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== @@ -10645,17 +11046,17 @@ user-home@^1.1.1: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== utils-merge@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^8.3.2: version "8.3.2" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache-lib@^3.0.0: @@ -10665,13 +11066,13 @@ v8-compile-cache-lib@^3.0.0: v8-compile-cache@2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" @@ -10686,7 +11087,7 @@ v8flags@^2.1.1: validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" @@ -10694,31 +11095,31 @@ validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: validate-npm-package-name@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw== dependencies: builtins "^1.0.3" validate-npm-package-name@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz#fe8f1c50ac20afdb86f177da85b3600f0ac0d747" integrity sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q== dependencies: builtins "^5.0.0" validator@^13.9.0: - version "13.11.0" - resolved "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz" - integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ== + version "13.15.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.15.0.tgz#2dc7ce057e7513a55585109eec29b2c8e8c1aefd" + integrity sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA== vary@^1, vary@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== verror@^1.10.0: version "1.10.1" - resolved "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.1.tgz#4bf09eeccf4563b109ed4b3d458380c972b0cdeb" integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg== dependencies: assert-plus "^1.0.0" @@ -10727,7 +11128,7 @@ verror@^1.10.0: walk-up-path@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e" integrity sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg== walker@^1.0.8: @@ -10739,24 +11140,24 @@ walker@^1.0.8: wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== dependencies: defaults "^1.0.3" webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-fetch@^3.4.1: - version "3.6.19" - resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz" - integrity sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw== + version "3.6.20" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" @@ -10764,29 +11165,36 @@ whatwg-url@^5.0.0: which@^2.0.0, which@^2.0.1, which@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" wide-align@^1.1.5: version "1.1.5" - resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: string-width "^1.0.2 || 2 || 3 || 4" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + wkx@^0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz" + resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c" integrity sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg== dependencies: "@types/node" "*" wonka@^6.0.0, wonka@^6.1.2: - version "6.3.4" - resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.3.4.tgz#76eb9316e3d67d7febf4945202b5bdb2db534594" - integrity sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg== + version "6.3.5" + resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.3.5.tgz#33fa54ea700ff3e87b56fe32202112a9e8fea1a2" + integrity sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw== word-wrap@^1.2.5: version "1.2.5" @@ -10795,7 +11203,7 @@ word-wrap@^1.2.5: wordwrap@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== wordwrapjs@^4.0.0: @@ -10806,9 +11214,14 @@ wordwrapjs@^4.0.0: reduce-flatten "^2.0.0" typical "^5.2.0" +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -10817,7 +11230,7 @@ wordwrapjs@^4.0.0: wrap-ansi@^6.0.1: version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: ansi-styles "^4.0.0" @@ -10826,7 +11239,7 @@ wrap-ansi@^6.0.1: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -10835,7 +11248,7 @@ wrap-ansi@^7.0.0: wrap-ansi@^8.1.0: version "8.1.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: ansi-styles "^6.1.0" @@ -10844,12 +11257,12 @@ wrap-ansi@^8.1.0: wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^2.4.2: version "2.4.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== dependencies: graceful-fs "^4.1.11" @@ -10858,7 +11271,7 @@ write-file-atomic@^2.4.2: write-file-atomic@^3.0.0: version "3.0.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== dependencies: imurmurhash "^0.1.4" @@ -10868,7 +11281,7 @@ write-file-atomic@^3.0.0: write-file-atomic@^4.0.0, write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== dependencies: imurmurhash "^0.1.4" @@ -10876,7 +11289,7 @@ write-file-atomic@^4.0.0, write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: write-json-file@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" integrity sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ== dependencies: detect-indent "^5.0.0" @@ -10888,7 +11301,7 @@ write-json-file@^3.2.0: write-json-file@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.3.0.tgz#908493d6fd23225344af324016e4ca8f702dd12d" integrity sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ== dependencies: detect-indent "^6.0.0" @@ -10900,31 +11313,31 @@ write-json-file@^4.3.0: write-pkg@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-4.0.0.tgz#675cc04ef6c11faacbbc7771b24c0abbf2a20039" integrity sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA== dependencies: sort-keys "^2.0.0" type-fest "^0.4.1" write-json-file "^3.2.0" -ws@7.4.6: - version "7.4.6" - resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== -ws@^7.4.5: - version "7.5.9" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== +ws@^7.4.5, ws@^7.4.6: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^3.0.2: @@ -10934,7 +11347,7 @@ yallist@^3.0.2: yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@1.10.0: @@ -10944,40 +11357,50 @@ yaml@1.10.0: yaml@1.10.2, yaml@^1.10.0, yaml@^1.7.2: version "1.10.2" - resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yaml@^2.0.0-10: - version "2.3.2" - resolved "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz" - integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== + version "2.8.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.0.tgz#15f8c9866211bdc2d3781a0890e44d4fa1a5fff6" + integrity sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ== yargs-parser@20.2.4: version "20.2.4" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== yargs-parser@21.1.1, yargs-parser@^21.0.0, yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs-parser@^16.1.0: version "16.1.0" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^20.2.2, yargs-parser@^20.2.3: +yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.9: version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + yargs@17.4.1: version "17.4.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.4.1.tgz#ebe23284207bb75cee7c408c33e722bfb27b5284" integrity sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g== dependencies: cliui "^7.0.2" @@ -10990,7 +11413,7 @@ yargs@17.4.1: yargs@^16.2.0: version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -11003,7 +11426,7 @@ yargs@^16.2.0: yargs@^17.3.1, yargs@^17.6.2: version "17.7.2" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -11021,15 +11444,15 @@ yn@3.1.1: yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== zod-validation-error@^1.3.0: version "1.5.0" - resolved "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-1.5.0.tgz" + resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-1.5.0.tgz#2b355007a1c3b7fb04fa476bfad4e7b3fd5491e3" integrity sha512-/7eFkAI4qV0tcxMBB/3+d2c1P6jzzZYdYSlBuAklzMuCrJu5bzJfHS0yVAS87dRHVlhftd6RFJDIvv03JgkSbw== zod@^3.21.4: - version "3.22.2" - resolved "https://registry.npmjs.org/zod/-/zod-3.22.2.tgz" - integrity sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg== + version "3.24.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.4.tgz#e2e2cca5faaa012d76e527d0d36622e0a90c315f" + integrity sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg== From db6b450de7ab4902ac9d481986b2c676fc60db45 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Wed, 21 May 2025 11:42:17 -0300 Subject: [PATCH 02/28] chore: add is horizon ready flag to network monitor (#1118) --- .../__tests__/horizon-ready.test.ts | 150 ++++++++++++++++++ .../src/indexer-management/monitor.ts | 37 +++++ packages/indexer-common/src/network.ts | 6 + scripts/run-tests.sh | 0 4 files changed, 193 insertions(+) create mode 100644 packages/indexer-common/src/indexer-management/__tests__/horizon-ready.test.ts mode change 100644 => 100755 scripts/run-tests.sh diff --git a/packages/indexer-common/src/indexer-management/__tests__/horizon-ready.test.ts b/packages/indexer-common/src/indexer-management/__tests__/horizon-ready.test.ts new file mode 100644 index 000000000..fbffa06c2 --- /dev/null +++ b/packages/indexer-common/src/indexer-management/__tests__/horizon-ready.test.ts @@ -0,0 +1,150 @@ +import { createLogger, Logger } from '@graphprotocol/common-ts' +import { NetworkMonitor } from '../monitor' +import { getTestProvider } from '../../utils' +import { resolveChainId } from '../../indexer-management' +import { GraphNode } from '../../graph-node' +import { SubgraphClient } from '../../subgraph-client' +import { SubgraphFreshnessChecker } from '../../subgraphs' +import { mockLogger, mockProvider } from '../../__tests__/subgraph.test' +import { specification as spec } from '../../index' +import { + connectGraphHorizon, + connectSubgraphService, +} from '@graphprotocol/toolshed/deployments' +import { Provider } from 'ethers' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const __LOG_LEVEL__: any + +describe('Horizon readiness', () => { + let logger: Logger + let ethereum: Provider + let graphNode: GraphNode + let networkSubgraph: SubgraphClient + let epochSubgraph: SubgraphClient + let networkMonitor: NetworkMonitor + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let mockHorizonStaking: any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let contracts: any + + const setupMonitor = async () => { + logger = createLogger({ + name: 'Horizon readiness tests', + async: false, + level: __LOG_LEVEL__ ?? 'error', + }) + ethereum = getTestProvider('sepolia') + + mockHorizonStaking = { + getMaxThawingPeriod: jest.fn(), + connect: jest.fn(), + waitForDeployment: jest.fn(), + interface: {}, + queryFilter: jest.fn(), + } + + const horizonContracts = { + ...connectGraphHorizon(5, ethereum), + HorizonStaking: mockHorizonStaking, + } + contracts = { + ...horizonContracts, + ...connectSubgraphService(5, ethereum), + } + + const subgraphFreshnessChecker = new SubgraphFreshnessChecker( + 'Test Subgraph', + mockProvider, + 10, + 10, + mockLogger, + 1, + ) + + networkSubgraph = await SubgraphClient.create({ + name: 'NetworkSubgraph', + logger, + endpoint: 'http://test-endpoint.xyz', + deployment: undefined, + subgraphFreshnessChecker, + }) + + epochSubgraph = await SubgraphClient.create({ + name: 'EpochSubgraph', + logger, + endpoint: 'http://test-endpoint.xyz', + subgraphFreshnessChecker, + }) + + graphNode = new GraphNode( + logger, + 'http://test-admin-endpoint.xyz', + 'https://test-query-endpoint.xyz', + 'http://test-status-endpoint.xyz', + 'https://test-ipfs-endpoint.xyz', + ) + + const indexerOptions = spec.IndexerOptions.parse({ + address: '0xc61127cdfb5380df4214b0200b9a07c7c49d34f9', + mnemonic: + 'word ivory whale diesel slab pelican voyage oxygen chat find tobacco sport', + url: 'http://test-url.xyz', + }) + + networkMonitor = new NetworkMonitor( + resolveChainId('sepolia'), + contracts, + indexerOptions, + logger, + graphNode, + networkSubgraph, + ethereum, + epochSubgraph, + ) + } + + beforeEach(setupMonitor) + + describe('monitorIsHorizon', () => { + beforeEach(() => { + mockHorizonStaking.getMaxThawingPeriod.mockResolvedValue(0) + }) + + test('should return false when getMaxThawingPeriod returns 0', async () => { + const isHorizon = await networkMonitor.monitorIsHorizon(logger, { + ...contracts, + HorizonStaking: mockHorizonStaking, + }) + const value = await isHorizon.value() + expect(value).toBe(false) + }) + + test('should return true when getMaxThawingPeriod returns > 0', async () => { + mockHorizonStaking.getMaxThawingPeriod.mockResolvedValue(1000) + + const isHorizon = await networkMonitor.monitorIsHorizon(logger, { + ...contracts, + HorizonStaking: mockHorizonStaking, + }) + + const value = await isHorizon.value() + console.log('Final value:', value) + expect(value).toBe(true) + }) + + test('should handle errors and maintain previous state', async () => { + mockHorizonStaking.getMaxThawingPeriod.mockRejectedValue( + new Error('Contract error'), + ) + + const isHorizon = await networkMonitor.monitorIsHorizon(logger, { + ...contracts, + HorizonStaking: mockHorizonStaking, + }) + + const value = await isHorizon.value() + expect(value).toBe(false) + }) + }) +}) diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index 28e57f88c..4323bad12 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -1086,6 +1086,43 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n }) } + async monitorIsHorizon( + logger: Logger, + contracts: GraphHorizonContracts & SubgraphServiceContracts, + interval: number = 300_000, + ): Promise> { + // Get initial value + + const initialValue = await contracts.HorizonStaking.getMaxThawingPeriod() + .then((maxThawingPeriod) => maxThawingPeriod > 0) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .catch((_) => false) + + return sequentialTimerReduce( + { + logger, + milliseconds: interval, + }, + async (isHorizon) => { + try { + logger.debug('Check if network is Horizon ready') + const maxThawingPeriod = await contracts.HorizonStaking.getMaxThawingPeriod() + return maxThawingPeriod > 0 + } catch (err) { + logger.warn( + `Failed to check if network is Horizon ready, assuming it has not changed`, + { err: indexerError(IndexerErrorCode.IE008, err), isHorizon }, + ) + return isHorizon + } + }, + initialValue, + ).map((isHorizon) => { + logger.info(isHorizon ? `Network is Horizon ready` : `Network is not Horizon ready`) + return isHorizon + }) + } + async claimableAllocations(disputableEpoch: number): Promise { try { this.logger.debug('Fetch claimable allocations', { diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index 4217f84b5..f1d9289ff 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -54,6 +54,7 @@ export class Network { specification: spec.NetworkSpecification paused: Eventual isOperator: Eventual + isHorizon: Eventual private constructor( logger: Logger, @@ -68,6 +69,7 @@ export class Network { specification: spec.NetworkSpecification, paused: Eventual, isOperator: Eventual, + isHorizon: Eventual, ) { this.logger = logger this.contracts = contracts @@ -81,6 +83,7 @@ export class Network { this.specification = specification this.paused = paused this.isOperator = isOperator + this.isHorizon = isHorizon } static async create( @@ -253,6 +256,8 @@ export class Network { wallet, ) + const isHorizon = await networkMonitor.monitorIsHorizon(logger, contracts) + const transactionManager = new TransactionManager( networkProvider, wallet, @@ -347,6 +352,7 @@ export class Network { specification, paused, isOperator, + isHorizon, ) } diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh old mode 100644 new mode 100755 From 9fbfaccba802c4f16e457a467c03469dbf5fbfb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 22 May 2025 15:07:01 -0300 Subject: [PATCH 03/28] feat: support split address books (#1119) --- .gitignore | 4 + packages/indexer-agent/src/commands/start.ts | 14 +++- .../src/network-specification.ts | 3 +- packages/indexer-common/src/network.ts | 77 ++++++++++++++----- 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 830a34c77..c2c428850 100644 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,7 @@ yalc.lock .idea/ .envrc .vscode + +# local-network override mode files +tap-contracts.json +config/config.yaml \ No newline at end of file diff --git a/packages/indexer-agent/src/commands/start.ts b/packages/indexer-agent/src/commands/start.ts index 9d62af24e..37d372d72 100644 --- a/packages/indexer-agent/src/commands/start.ts +++ b/packages/indexer-agent/src/commands/start.ts @@ -246,8 +246,13 @@ export const start = { default: 100, group: 'Query Fees', }) - .option('address-book', { - description: 'Graph contracts address book file path', + .option('horizon-address-book', { + description: 'Graph Horizon contracts address book file path', + type: 'string', + required: false, + }) + .option('subgraph-service-address-book', { + description: 'Subgraph Service contracts address book file path', type: 'string', required: false, }) @@ -443,8 +448,9 @@ export async function createNetworkSpecification( transactionMonitoring, subgraphs, networkProvider, - addressBook: argv.addressBook, - tapAddressBook, + horizonAddressBook: argv.horizonAddressBook, + subgraphServiceAddressBook: argv.subgraphServiceAddressBook, + tapAddressBook: tapAddressBook, }) } catch (parsingError) { displayZodParsingError(parsingError) diff --git a/packages/indexer-common/src/network-specification.ts b/packages/indexer-common/src/network-specification.ts index 162ae5335..02a3570b8 100644 --- a/packages/indexer-common/src/network-specification.ts +++ b/packages/indexer-common/src/network-specification.ts @@ -175,7 +175,8 @@ export const NetworkSpecification = z transactionMonitoring: TransactionMonitoring, subgraphs: ProtocolSubgraphs, networkProvider: NetworkProvider, - addressBook: z.string().optional(), + horizonAddressBook: z.string().optional(), + subgraphServiceAddressBook: z.string().optional(), tapAddressBook: TapContracts.optional(), allocationSyncInterval: positiveNumber().default(120000), }) diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index f1d9289ff..5dbae0523 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -134,9 +134,9 @@ export class Network { deployment: networkSubgraphDeploymentId !== undefined ? { - graphNode, - deployment: networkSubgraphDeploymentId, - } + graphNode, + deployment: networkSubgraphDeploymentId, + } : undefined, subgraphFreshnessChecker: networkSubgraphFreshnessChecker, }) @@ -160,9 +160,9 @@ export class Network { deployment: tapSubgraphDeploymentId !== undefined ? { - graphNode, - deployment: tapSubgraphDeploymentId, - } + graphNode, + deployment: tapSubgraphDeploymentId, + } : undefined, endpoint: specification.subgraphs.tapSubgraph!.url, subgraphFreshnessChecker: tapSubgraphFreshnessChecker, @@ -191,7 +191,8 @@ export class Network { wallet, specification.networkIdentifier, logger, - specification.addressBook, + specification.horizonAddressBook, + specification.subgraphServiceAddressBook, ) // * ----------------------------------------------------------------------- @@ -215,9 +216,9 @@ export class Network { deployment: epochSubgraphDeploymentId !== undefined ? { - graphNode, - deployment: epochSubgraphDeploymentId, - } + graphNode, + deployment: epochSubgraphDeploymentId, + } : undefined, endpoint: specification.subgraphs.epochSubgraph.url, subgraphFreshnessChecker: epochSubgraphFreshnessChecker, @@ -556,7 +557,8 @@ async function connectToProtocolContracts( wallet: HDNodeWallet, networkIdentifier: string, logger: Logger, - addressBook?: string, + horizonAddressBook?: string, + subgraphServiceAddressBook?: string ): Promise { const numericNetworkId = parseInt(networkIdentifier.split(':')[1]) @@ -567,15 +569,17 @@ async function connectToProtocolContracts( logger.info(`Connect to contracts`, { network: networkIdentifier, + horizonAddressBook, + subgraphServiceAddressBook, }) let contracts: GraphHorizonContracts & SubgraphServiceContracts try { - const horizonContracts = connectGraphHorizon(numericNetworkId, wallet, addressBook) + const horizonContracts = connectGraphHorizon(numericNetworkId, wallet, horizonAddressBook) const subgraphServiceContracts = connectSubgraphService( numericNetworkId, wallet, - addressBook, + subgraphServiceAddressBook, ) contracts = { ...horizonContracts, @@ -587,15 +591,50 @@ async function connectToProtocolContracts( logger.error(errorMessage, { error, networkIdentifier, numericNetworkId }) throw new Error(`${errorMessage} Error: ${error}`) } - logger.info(`Successfully connected to contracts`, { - curation: contracts.L2Curation.target, - disputeManager: contracts.DisputeManager.target, + + + // Ensure we are connected to all required contracts + const requiredContracts = [ + 'EpochManager', + 'RewardsManager', + 'HorizonStaking', + 'GraphTallyCollector', + 'PaymentsEscrow', + 'SubgraphService', + ] + + // Before horizon we need the LegacyServiceRegistry contract as well + const isHorizon = await contracts.HorizonStaking.getMaxThawingPeriod() + .then((maxThawingPeriod) => maxThawingPeriod > 0) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .catch((_) => false) + if (!isHorizon) { + requiredContracts.push('LegacyServiceRegistry') + } + + const missingContracts = requiredContracts.filter( + (contract) => !(contract in contracts), + ) + if (missingContracts.length > 0) { + logger.fatal(`Missing required contracts`, { + err: indexerError(IndexerErrorCode.IE075), + missingContracts: missingContracts, + }) + process.exit(1) + } + + + // Only list contracts that are used by the indexer + logger.info(`Successfully connected to Horizon contracts`, { epochManager: contracts.EpochManager.target, - gns: contracts.L2GNS.target, rewardsManager: contracts.RewardsManager.target, - serviceRegistry: contracts.LegacyServiceRegistry.target, staking: contracts.HorizonStaking.target, - token: contracts.GraphToken.target, + graphTallyCollector: contracts.GraphTallyCollector.target, + graphPaymentsEscrow: contracts.PaymentsEscrow.target, + }) + logger.info(`Successfully connected to Subgraph Service contracts`, { + ...(isHorizon ? {} : { legacyServiceRegistry: contracts.LegacyServiceRegistry.target }), + subgraphService: contracts.SubgraphService.target, }) return contracts } From 70490e0b40570355a6f7acb0b364816fe369b879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 22 May 2025 15:08:38 -0300 Subject: [PATCH 04/28] feat: update registration to support horizon flow, add provisioning flow at startup (#1120) --- packages/indexer-agent/src/agent.ts | 1 + packages/indexer-agent/src/commands/start.ts | 15 + packages/indexer-common/package.json | 2 +- .../invalid-payments-destination.yml | 36 +++ .../invalid-provision-size.yml | 35 +++ .../valid-missing.yml | 1 + .../network-specification-files/valid.yml | 1 + .../__tests__/network-specification.test.ts | 10 + .../src/network-specification.ts | 12 + packages/indexer-common/src/network.ts | 287 +++++++++++++++--- yarn.lock | 8 +- 11 files changed, 359 insertions(+), 49 deletions(-) create mode 100644 packages/indexer-common/src/__tests__/network-specification-files/invalid-payments-destination.yml create mode 100644 packages/indexer-common/src/__tests__/network-specification-files/invalid-provision-size.yml diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index 519653d73..cbb415837 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -233,6 +233,7 @@ export class Agent { try { await operator.ensureGlobalIndexingRule() await this.ensureAllSubgraphsIndexing(network) + await network.provision() await network.register() } catch (err) { this.logger.critical( diff --git a/packages/indexer-agent/src/commands/start.ts b/packages/indexer-agent/src/commands/start.ts index 37d372d72..ff79e783a 100644 --- a/packages/indexer-agent/src/commands/start.ts +++ b/packages/indexer-agent/src/commands/start.ts @@ -111,6 +111,12 @@ export const start = { required: true, group: 'Ethereum', }) + .option('payments-destination', { + description: + 'Address where payments are sent to. If not provided payments will be restaked.', + type: 'string', + group: 'Ethereum', + }) .option('public-indexer-url', { description: 'Indexer endpoint for receiving requests from the network', type: 'string', @@ -272,6 +278,13 @@ export const start = { default: true, group: 'Protocol', }) + .option('max-provision-initial-size', { + description: + 'The maximum number of tokens for the initial Subgraph Service provision', + type: 'number', + default: 0, + group: 'Protocol', + }) .option('poi-disputable-epochs', { description: 'The number of epochs in the past to look for potential POI disputes', @@ -351,6 +364,7 @@ export async function createNetworkSpecification( const indexerOptions = { address: argv.indexerAddress, + paymentsDestination: argv.paymentsDestination, mnemonic: argv.mnemonic, url: argv.publicIndexerUrl, geoCoordinates: argv.indexerGeoCoordinates, @@ -368,6 +382,7 @@ export async function createNetworkSpecification( autoAllocationMinBatchSize: argv.autoAllocationMinBatchSize, allocateOnNetworkSubgraph: argv.allocateOnNetworkSubgraph, register: argv.register, + maxProvisionInitialSize: argv.maxProvisionInitialSize, finalityTime: argv.chainFinalizeTime, } diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index d68c34fbb..c145e0802 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -24,7 +24,7 @@ "dependencies": { "@pinax/graph-networks-registry": "0.6.7", "@graphprotocol/common-ts": "3.0.1", - "@graphprotocol/toolshed": "0.3.2", + "@graphprotocol/toolshed": "0.4.2", "@semiotic-labs/tap-contracts-bindings": "2.0.0", "@thi.ng/heaps": "1.2.38", "@types/lodash.clonedeep": "^4.5.7", diff --git a/packages/indexer-common/src/__tests__/network-specification-files/invalid-payments-destination.yml b/packages/indexer-common/src/__tests__/network-specification-files/invalid-payments-destination.yml new file mode 100644 index 000000000..67d184698 --- /dev/null +++ b/packages/indexer-common/src/__tests__/network-specification-files/invalid-payments-destination.yml @@ -0,0 +1,36 @@ +networkIdentifier: mainnet +gateway: + url: http://gateway +indexerOptions: + address: "0x4e8a4C63Df58bf59Fef513aB67a76319a9faf448" + paymentsDestination: "0xclearlynotanaddress" + mnemonic: word ivory whale diesel slab pelican voyage oxygen chat find tobacco sport + url: http://indexer + geoCoordinates: [25.1, -71.2] + restakeRewards: true + rebateClaimThreshold: 400 + rebateClaimBatchThreshold: 5000 + rebateClaimMaxBatchSize: 10 + poiDisputeMonitoring: false + poiDisputableEpochs: 5 + defaultAllocationAmount: 0.05 + voucherRedemptionThreshold: 2 + voucherRedemptionBatchThreshold: 2000 + voucherRedemptionMaxBatchSize: 15 + allocationManagementMode: "auto" + autoAllocationMinBatchSize: 20 + maxProvisionInitialSize: 100000 +transactionMonitoring: + gasIncreaseTimeout: 10 + gasIncreaseFactor: 10 + baseFeePerGasMax: 10 + maxTransactionAttempts: 10 +subgraphs: + networkSubgraph: + deployment: QmPK1s3pNYLi9ERiq3BDxKa4XosgWwFRQUydHUtz4YgpqB + epochSubgraph: + url: http://subgraph + tapSubgraph: + url: http://subgraph +networkProvider: + url: http://provider diff --git a/packages/indexer-common/src/__tests__/network-specification-files/invalid-provision-size.yml b/packages/indexer-common/src/__tests__/network-specification-files/invalid-provision-size.yml new file mode 100644 index 000000000..75b6cb2c3 --- /dev/null +++ b/packages/indexer-common/src/__tests__/network-specification-files/invalid-provision-size.yml @@ -0,0 +1,35 @@ +networkIdentifier: mainnet +gateway: + url: http://gateway +indexerOptions: + address: "0x4e8a4C63Df58bf59Fef513aB67a76319a9faf448" + mnemonic: word ivory whale diesel slab pelican voyage oxygen chat find tobacco sport + url: http://indexer + geoCoordinates: [25.1, -71.2] + restakeRewards: true + rebateClaimThreshold: 400 + rebateClaimBatchThreshold: 5000 + rebateClaimMaxBatchSize: 10 + poiDisputeMonitoring: false + poiDisputableEpochs: 5 + defaultAllocationAmount: 0.05 + voucherRedemptionThreshold: 2 + voucherRedemptionBatchThreshold: 2000 + voucherRedemptionMaxBatchSize: 15 + allocationManagementMode: "auto" + autoAllocationMinBatchSize: 20 + maxProvisionInitialSize: 99999 +transactionMonitoring: + gasIncreaseTimeout: 10 + gasIncreaseFactor: 10 + baseFeePerGasMax: 10 + maxTransactionAttempts: 10 +subgraphs: + networkSubgraph: + deployment: QmPK1s3pNYLi9ERiq3BDxKa4XosgWwFRQUydHUtz4YgpqB + epochSubgraph: + url: http://subgraph + tapSubgraph: + url: http://subgraph +networkProvider: + url: http://provider diff --git a/packages/indexer-common/src/__tests__/network-specification-files/valid-missing.yml b/packages/indexer-common/src/__tests__/network-specification-files/valid-missing.yml index 76c051f50..944a88f0a 100644 --- a/packages/indexer-common/src/__tests__/network-specification-files/valid-missing.yml +++ b/packages/indexer-common/src/__tests__/network-specification-files/valid-missing.yml @@ -19,6 +19,7 @@ indexerOptions: voucherRedemptionMaxBatchSize: 15 allocationManagementMode: "auto" autoAllocationMinBatchSize: 20 + maxProvisionInitialSize: 0 subgraphs: networkSubgraph: deployment: QmPK1s3pNYLi9ERiq3BDxKa4XosgWwFRQUydHUtz4YgpqB diff --git a/packages/indexer-common/src/__tests__/network-specification-files/valid.yml b/packages/indexer-common/src/__tests__/network-specification-files/valid.yml index 51538b31a..e3f802e1c 100644 --- a/packages/indexer-common/src/__tests__/network-specification-files/valid.yml +++ b/packages/indexer-common/src/__tests__/network-specification-files/valid.yml @@ -18,6 +18,7 @@ indexerOptions: voucherRedemptionMaxBatchSize: 15 allocationManagementMode: "auto" autoAllocationMinBatchSize: 20 + maxProvisionInitialSize: 100000 transactionMonitoring: gasIncreaseTimeout: 10 gasIncreaseFactor: 10 diff --git a/packages/indexer-common/src/__tests__/network-specification.test.ts b/packages/indexer-common/src/__tests__/network-specification.test.ts index 6c8afefe2..22464e33c 100644 --- a/packages/indexer-common/src/__tests__/network-specification.test.ts +++ b/packages/indexer-common/src/__tests__/network-specification.test.ts @@ -70,6 +70,16 @@ describe('Failed deserialization', () => { path: ['subgraphs', 'maxBlockDistance'], message: 'Number must be greater than or equal to 0', }, + { + file: 'invalid-provision-size.yml', + path: ['indexerOptions', 'maxProvisionInitialSize'], + message: 'Must be greater or equal than 100000 GRT', + }, + { + file: 'invalid-payments-destination.yml', + path: ['indexerOptions', 'paymentsDestination'], + message: 'Invalid contract address', + }, ] test.each(failedTests)( diff --git a/packages/indexer-common/src/network-specification.ts b/packages/indexer-common/src/network-specification.ts index 02a3570b8..c3c01d4f0 100644 --- a/packages/indexer-common/src/network-specification.ts +++ b/packages/indexer-common/src/network-specification.ts @@ -39,6 +39,13 @@ export const IndexerOptions = z mnemonic: z.string(), url: z.string().url(), geoCoordinates: z.number().array().length(2).default([31.780715, -41.179504]), + paymentsDestination: z + .string() + .refine((val) => isAddress(val), { + message: 'Invalid contract address', + }) + .transform(toAddress) + .optional(), restakeRewards: z.boolean().default(true), rebateClaimThreshold: GRT().default(1), rebateClaimBatchThreshold: GRT().default(5), @@ -56,6 +63,11 @@ export const IndexerOptions = z autoAllocationMinBatchSize: positiveNumber().default(1), allocateOnNetworkSubgraph: z.boolean().default(false), register: z.boolean().default(true), + maxProvisionInitialSize: GRT() + .refine((x) => x >= parseGRT('100000') || x === 0n, { + message: 'Must be greater or equal than 100000 GRT', + }) + .default(0), finalityTime: positiveNumber().default(3600), }) .strict() diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index 5dbae0523..d588e73f5 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -4,6 +4,7 @@ import { SubgraphDeploymentID, Eventual, toAddress, + formatGRT, } from '@graphprotocol/common-ts' import { connectGraphHorizon, @@ -37,6 +38,7 @@ import { resolveChainId } from './indexer-management' import { monitorEthBalance } from './utils' import { QueryFeeModels } from './query-fees' import { TapCollector } from './allocations/tap-collector' +import { encodeRegistrationData } from '@graphprotocol/toolshed' export class Network { logger: Logger @@ -447,22 +449,27 @@ export class Network { } // Start of SEND functions - async register(): Promise { - const geoHash = geohash.encode( - +this.specification.indexerOptions.geoCoordinates[0], - +this.specification.indexerOptions.geoCoordinates[1], - ) - + async provision(): Promise { const logger = this.logger.child({ address: this.specification.indexerOptions.address, - url: this.specification.indexerOptions.url, - geoCoordinates: this.specification.indexerOptions.geoCoordinates, - geoHash, }) - if (!this.specification.indexerOptions.register) { - logger.debug( - "Indexer was not registered because it was explicitly disabled in this Network's configuration.", + logger.info('Provision indexer to the Subgraph Service', { + maxProvisionInitialSize: formatGRT( + this.specification.indexerOptions.maxProvisionInitialSize, + ), + }) + + if (!(await this.isHorizon.value())) { + logger.info('Graph Horizon upgrade not detected, skipping provisioning.') + return + } + + const maxProvisionInitialSize = + this.specification.indexerOptions.maxProvisionInitialSize + if (maxProvisionInitialSize === 0n) { + logger.info( + 'Max provision initial size is 0, skipping provisioning. Please set to a non-zero value to enable Graph Horizon functionality.', ) return } @@ -470,46 +477,70 @@ export class Network { await pRetry( async () => { try { - logger.info(`Register indexer`) + const provision = await this.contracts.HorizonStaking.getProvision( + this.specification.indexerOptions.address, + this.contracts.SubgraphService.target, + ) + + if (provision.createdAt > 0n) { + logger.info('Indexer already provisioned, skipping provisioning.') + return + } + + const [thawingPeriod] = + await this.contracts.SubgraphService.getThawingPeriodRange() + const [maxVerifierCut] = + await this.contracts.SubgraphService.getVerifierCutRange() + const [minProvisionTokens] = + await this.contracts.SubgraphService.getProvisionTokensRange() - // Register the indexer (only if it hasn't been registered yet or - // if its URL is different from what is registered on chain) - const isRegistered = await this.contracts.LegacyServiceRegistry.isRegistered( + const indexerIdleStake = await this.contracts.HorizonStaking.getIdleStake( this.specification.indexerOptions.address, ) - if (isRegistered) { - const service = await this.contracts.LegacyServiceRegistry.services( - this.specification.indexerOptions.address, + + if (indexerIdleStake < minProvisionTokens) { + logger.warn( + 'Indexer idle stake is less than minimum provision tokens, skipping provisioning.', + { + indexerIdleStake: formatGRT(indexerIdleStake), + minProvisionTokens: formatGRT(minProvisionTokens), + }, ) - if ( - service.url === this.specification.indexerOptions.url && - service.geohash === geoHash - ) { - if (await this.transactionManager.isOperator.value()) { - logger.info(`Indexer already registered, operator status already granted`) - } else { - logger.info(`Indexer already registered, operator status not yet granted`) - } - return - } + return } + + const provisionTokens = + indexerIdleStake > maxProvisionInitialSize + ? maxProvisionInitialSize + : indexerIdleStake + + logger.info('Creating provision', { + tokens: formatGRT(provisionTokens), + thawingPeriod, + maxVerifierCut, + }) + const receipt = await this.transactionManager.executeTransaction( () => - this.contracts.LegacyServiceRegistry.registerFor.estimateGas( + this.contracts.HorizonStaking.provision.estimateGas( this.specification.indexerOptions.address, - this.specification.indexerOptions.url, - geoHash, + this.contracts.SubgraphService.target, + provisionTokens, + maxVerifierCut, + thawingPeriod, ), (gasLimit) => - this.contracts.LegacyServiceRegistry.registerFor( + this.contracts.HorizonStaking.provision( this.specification.indexerOptions.address, - this.specification.indexerOptions.url, - geoHash, + this.contracts.SubgraphService.target, + provisionTokens, + maxVerifierCut, + thawingPeriod, { gasLimit, }, ), - logger.child({ function: 'serviceRegistry.registerFor' }), + logger.child({ function: 'horizonStaking.provision' }), ) if (receipt === 'paused' || receipt === 'unauthorized') { return @@ -518,13 +549,13 @@ export class Network { const event = events.find((event) => event.topics.includes( // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain - this.contracts.LegacyServiceRegistry.interface.getEvent('ServiceRegistered') + this.contracts.HorizonStaking.interface.getEvent('ProvisionCreated') ?.topicHash!, ), ) assert.ok(event) - logger.info(`Successfully registered indexer`) + logger.info(`Successfully provisioned to the Subgraph Service`) } catch (error) { const err = indexerError(IndexerErrorCode.IE012, error) logger.error(INDEXER_ERROR_MESSAGES[IndexerErrorCode.IE012], { @@ -536,6 +567,170 @@ export class Network { { retries: 5 } as Options, ) } + async register(): Promise { + const geoHash = geohash.encode( + +this.specification.indexerOptions.geoCoordinates[0], + +this.specification.indexerOptions.geoCoordinates[1], + ) + const url = this.specification.indexerOptions.url + + const logger = this.logger.child({ + address: this.specification.indexerOptions.address, + }) + + if (!this.specification.indexerOptions.register) { + logger.debug( + "Indexer was not registered because it was explicitly disabled in this Network's configuration.", + ) + return + } + + await pRetry( + async () => { + try { + if (await this.isHorizon.value()) { + await this._register(logger, geoHash, url) + } else { + await this._registerLegacy(logger, geoHash, url) + } + } catch (error) { + const err = indexerError(IndexerErrorCode.IE012, error) + logger.error(INDEXER_ERROR_MESSAGES[IndexerErrorCode.IE012], { + err, + }) + throw error + } + }, + { retries: 5 } as Options, + ) + } + + private async _register(logger: Logger, geoHash: string, url: string): Promise { + const paymentsDestination = + this.specification.indexerOptions.paymentsDestination?.toString() ?? + '0x0000000000000000000000000000000000000000' + + logger.info(`Register indexer`, { + url, + geoCoordinates: this.specification.indexerOptions.geoCoordinates, + geoHash, + paymentsDestination, + }) + + // Register the indexer (only if it hasn't been registered yet or + // if its URL/geohash is different from what is registered on chain) + const indexerRegistrationData = await this.contracts.SubgraphService.indexers( + this.specification.indexerOptions.address, + ) + const isRegistered = indexerRegistrationData.registeredAt !== 0n + if (isRegistered) { + if ( + indexerRegistrationData.url === url && + indexerRegistrationData.geoHash === geoHash + ) { + if (await this.transactionManager.isOperator.value()) { + logger.info(`Indexer already registered, operator status already granted`) + } else { + logger.info(`Indexer already registered, operator status not yet granted`) + } + return + } + } + const encodedData = encodeRegistrationData(url, geoHash, paymentsDestination) + const receipt = await this.transactionManager.executeTransaction( + () => + this.contracts.SubgraphService.register.estimateGas( + this.specification.indexerOptions.address, + encodedData, + ), + (gasLimit) => + this.contracts.SubgraphService.register( + this.specification.indexerOptions.address, + encodedData, + { + gasLimit, + }, + ), + logger.child({ function: 'subgraphService.register' }), + ) + if (receipt === 'paused' || receipt === 'unauthorized') { + return + } + const events = receipt.logs + const event = events.find((event) => + event.topics.includes( + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain + this.contracts.SubgraphService.interface.getEvent('ServiceProviderRegistered') + ?.topicHash!, + ), + ) + assert.ok(event) + + logger.info(`Successfully registered indexer`) + } + + private async _registerLegacy( + logger: Logger, + geoHash: string, + url: string, + ): Promise { + logger.info(`Register indexer`, { + url, + geoCoordinates: this.specification.indexerOptions.geoCoordinates, + geoHash, + }) + + // Register the indexer (only if it hasn't been registered yet or + // if its URL/geohash is different from what is registered on chain) + const isRegistered = await this.contracts.LegacyServiceRegistry.isRegistered( + this.specification.indexerOptions.address, + ) + if (isRegistered) { + const service = await this.contracts.LegacyServiceRegistry.services( + this.specification.indexerOptions.address, + ) + if (service.url === url && service.geohash === geoHash) { + if (await this.transactionManager.isOperator.value()) { + logger.info(`Indexer already registered, operator status already granted`) + } else { + logger.info(`Indexer already registered, operator status not yet granted`) + } + return + } + } + const receipt = await this.transactionManager.executeTransaction( + () => + this.contracts.LegacyServiceRegistry.registerFor.estimateGas( + this.specification.indexerOptions.address, + this.specification.indexerOptions.url, + geoHash, + ), + (gasLimit) => + this.contracts.LegacyServiceRegistry.registerFor( + this.specification.indexerOptions.address, + this.specification.indexerOptions.url, + geoHash, + { + gasLimit, + }, + ), + logger.child({ function: 'serviceRegistry.registerFor' }), + ) + if (receipt === 'paused' || receipt === 'unauthorized') { + return + } + const events = receipt.logs + const event = events.find((event) => + event.topics.includes( + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain + this.contracts.LegacyServiceRegistry.interface.getEvent('ServiceRegistered') + ?.topicHash!, + ), + ) + assert.ok(event) + + logger.info(`Successfully registered indexer (Legacy registration)`) + } } async function connectWallet( @@ -558,7 +753,7 @@ async function connectToProtocolContracts( networkIdentifier: string, logger: Logger, horizonAddressBook?: string, - subgraphServiceAddressBook?: string + subgraphServiceAddressBook?: string, ): Promise { const numericNetworkId = parseInt(networkIdentifier.split(':')[1]) @@ -575,7 +770,11 @@ async function connectToProtocolContracts( let contracts: GraphHorizonContracts & SubgraphServiceContracts try { - const horizonContracts = connectGraphHorizon(numericNetworkId, wallet, horizonAddressBook) + const horizonContracts = connectGraphHorizon( + numericNetworkId, + wallet, + horizonAddressBook, + ) const subgraphServiceContracts = connectSubgraphService( numericNetworkId, wallet, @@ -592,7 +791,6 @@ async function connectToProtocolContracts( throw new Error(`${errorMessage} Error: ${error}`) } - // Ensure we are connected to all required contracts const requiredContracts = [ 'EpochManager', @@ -623,7 +821,6 @@ async function connectToProtocolContracts( process.exit(1) } - // Only list contracts that are used by the indexer logger.info(`Successfully connected to Horizon contracts`, { epochManager: contracts.EpochManager.target, @@ -633,7 +830,9 @@ async function connectToProtocolContracts( graphPaymentsEscrow: contracts.PaymentsEscrow.target, }) logger.info(`Successfully connected to Subgraph Service contracts`, { - ...(isHorizon ? {} : { legacyServiceRegistry: contracts.LegacyServiceRegistry.target }), + ...(isHorizon + ? {} + : { legacyServiceRegistry: contracts.LegacyServiceRegistry.target }), subgraphService: contracts.SubgraphService.target, }) return contracts diff --git a/yarn.lock b/yarn.lock index d18e60837..cb4678457 100644 --- a/yarn.lock +++ b/yarn.lock @@ -593,10 +593,10 @@ resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.3.4.tgz#38929c04d03ad06823f9a867c8a4aef4c7f581e7" integrity sha512-POepREau0ExCz4ZJrlhzIS3RigEuzlbp/xlurpHkgaOn97cFAv3x9ZaE5a9uwh1azRm3Djz8RUBmXpqmwoK9NA== -"@graphprotocol/toolshed@0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.3.2.tgz#3808687e4bf16373a1ec363fc5cb43ec7977023c" - integrity sha512-bp7RWbcUZQcZW6Wn4EcN5DLYFO0hLDGXTLWeahq1HdkLEhcyHiTBqKmZKV98OG4TPJPJ7piCvsoJLuGj/btyRw== +"@graphprotocol/toolshed@0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.4.2.tgz#511b2c7e1b6fbe229c01de0e5de484877534982b" + integrity sha512-qdIalumrmrh7+X0nVr+v/1ZFD0G0dgtE0W47tKZugiw7YKmwnBFkp9MnpYrNzm9NDbs2lk0hn8WBg3W980+hEw== dependencies: "@graphprotocol/contracts" "^7.1.2" "@graphprotocol/horizon" "^0.3.2" From da8f53db98fe97c708702cd5e52a2d181af502fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 23 May 2025 15:13:12 -0300 Subject: [PATCH 05/28] Horizon fixes (#1121) --- README.md | 239 ++++++++++-------- packages/indexer-agent/src/commands/start.ts | 7 + packages/indexer-common/package.json | 2 +- .../indexer-management/models/cost-model.ts | 10 +- .../models/indexing-rule.ts | 38 +-- .../indexer-management/models/poi-dispute.ts | 32 +-- .../src/network-specification.ts | 1 + packages/indexer-common/src/network.ts | 18 +- packages/indexer-common/src/transactions.ts | 4 +- yarn.lock | 8 +- 10 files changed, 200 insertions(+), 159 deletions(-) diff --git a/README.md b/README.md index 1f02734ff..d58424fc9 100644 --- a/README.md +++ b/README.md @@ -44,107 +44,145 @@ $ graph-indexer-agent start --help Start the agent -Ethereum - --ethereum Ethereum node or provider URL [string] [required] - --ethereum-network Ethereum network [string] [default: "mainnet"] - --ethereum-polling-interval Polling interval for the Ethereum provider (ms) - [number] [default: 4000] - --gas-increase-timeout Time (in seconds) after which transactions will - be resubmitted with a higher gas price - [number] [default: 240] - --gas-increase-factor Factor by which gas prices are increased when - resubmitting transactions [number] [default: 1.2] - --gas-price-max The maximum gas price (gwei) to use for - transactions [deprecated] [number] [default: 100] - --base-fee-per-gas-max The maximum base fee per gas (gwei) to use for - transactions, for legacy transactions this will - be treated as the max gas price [number] - --transaction-attempts The maximum number of transaction attempts (Use 0 - for unlimited) [number] [default: 0] - --mnemonic Mnemonic for the operator wallet +Indexer Infrastructure + --indexer-management-port Port to serve the indexer management API at + [number] [default: 8000] + --metrics-port Port to serve Prometheus metrics at + [number] [default: 7300] + --syncing-port Port to serve the network subgraph and other + syncing data for indexer service at + [number] [default: 8002] + --log-level Log level [string] [default: "debug"] + --polling-interval Polling interval for data collection + [number] [default: 120000] + --ipfs-endpoint IPFS endpoint for querying manifests. + [string] [required] [default: "https://ipfs.network.thegraph.com"] + --graph-node-query-endpoint Graph Node endpoint for querying subgraphs [string] [required] - --indexer-address Ethereum address of the indexer + --graph-node-status-endpoint Graph Node endpoint for indexing statuses + etc. [string] [required] + --graph-node-admin-endpoint Graph Node endpoint for applying and + updating subgraph deployments [string] [required] + --enable-auto-migration-support Auto migrate allocations from L1 to L2 + (multi-network mode must be enabled) + [boolean] [default: false] + --deployment-management Subgraph deployments management mode + [choices: "auto", "manual"] [default: "auto"] + --public-indexer-url Indexer endpoint for receiving requests from + the network [string] [required] + --indexer-geo-coordinates Coordinates describing the Indexer's + location using latitude and longitude + [string] [default: ["31.780715","-41.179504"]] + --restake-rewards Restake claimed indexer rewards, if set to + 'false' rewards will be returned to the + wallet [boolean] [default: true] + --allocation-management Indexer agent allocation management + automation mode (auto|manual) + [string] [default: "auto"] + --auto-allocation-min-batch-size Minimum number of allocation transactions + inside a batch for auto allocation + management. No obvious upperbound, with + default of 1 [number] [default: 1] -Indexer Infrastructure - --graph-node-query-endpoint Graph Node endpoint for querying - subgraphs [string] [required] - --graph-node-status-endpoint Graph Node endpoint for indexing - statuses etc. [string] [required] - --graph-node-admin-endpoint Graph Node endpoint for applying and - updating subgraph deployments +Postgres + --postgres-host Postgres host [string] [required] + --postgres-port Postgres port [number] [default: 5432] + --postgres-username Postgres username [string] [default: "postgres"] + --postgres-password Postgres password [string] [default: ""] + --postgres-sslenabled Postgres SSL Enabled [boolean] [default: "false"] + --postgres-database Postgres database name [string] [required] + --postgres-pool-size Postgres maximum connection pool size + [number] [default: 50] + +Ethereum + --network-provider, --ethereum Ethereum node or provider URL [string] [required] - --public-indexer-url Indexer endpoint for receiving requests - from the network [string] [required] - --indexer-geo-coordinates Coordinates describing the Indexer's - location using latitude and longitude - [array] [default: ["31.780715","-41.179504"]] - --index-node-ids Node IDs of Graph nodes to use for - indexing (separated by commas) - [array] [required] - --indexer-management-port Port to serve the indexer management API - at [number] [default: 8000] - --metrics-port Port to serve Prometheus metrics at - [number] - --syncing-port Port to serve the network subgraph and - other syncing data for indexer service - at [number] [default: 8002] - --restake-rewards Restake claimed indexer rewards, if set - to 'false' rewards will be returned to - the wallet [boolean] [default: true] - --rebate-claim-threshold Minimum value of rebate for a single - allocation (in GRT) in order for it to - be included in a batch rebate claim - on-chain [string] [default: "1"] - --rebate-claim-batch-threshold Minimum total value of all rebates in an - batch (in GRT) before the batch is - claimed on-chain - [string] [default: "5"] - --rebate-claim-max-batch-size Maximum number of rebates inside a - batch. Upper bound is constrained by - available system memory, and by the - block gas limit [number] [default: 100] - --voucher-redemption-threshold Minimum value of rebate for a single - allocation (in GRT) in order for it to - be included in a batch rebate claim - on-chain [string] [default: "1"] - --voucher-redemption-batch-threshold Minimum total value of all rebates in an - batch (in GRT) before the batch is - claimed on-chain - [string] [default: "5"] - --voucher-redemption-max-batch-size Maximum number of rebates inside a - batch. Upper bound is constrained by - available system memory, and by the - block gas limit [number] [default: 100] - --log-level Log level [string] [default: "debug"] - --allocation-management Indexer agent allocation management - automation mode (auto|manual|oversight) - [string] [default: "auto"] - --auto-allocation-min-batch-size Minimum number of allocation - transactions inside a batch for AUTO - management mode [number] [default: 1] + --ethereum-polling-interval Polling interval for the Ethereum provider + (ms) [number] [default: 4000] + --gas-increase-timeout Time (in seconds) after which transactions + will be resubmitted with a higher gas price + [number] [default: 240] + --gas-increase-factor Factor by which gas prices are increased when + resubmitting transactions + [number] [default: 1.2] + --gas-price-max The maximum gas price (gwei) to use for + transactions + [deprecated] [number] [default: 100] + --base-fee-per-gas-max The maximum base fee per gas (gwei) to use for + transactions, for legacy transactions this + will be treated as the max gas price [number] + --transaction-attempts The maximum number of transaction attempts + (Use 0 for unlimited) [number] [default: 0] + --mnemonic Mnemonic for the operator wallet + [string] [required] + --indexer-address Ethereum address of the indexer + [string] [required] + --payments-destination Address where payments are sent to. If not + provided payments will be restaked. [string] Network Subgraph - --network-subgraph-deployment Network subgraph deployment [string] + --network-subgraph-deployment Network subgraph deployment (for local + hosting) [string] --network-subgraph-endpoint Endpoint to query the network subgraph from [string] --allocate-on-network-subgraph Whether to allocate to the network subgraph [boolean] [default: false] + --epoch-subgraph-deployment Epoch subgraph deployment (for local hosting) + [string] + +TAP Subgraph + --tap-subgraph-deployment TAP subgraph deployment (for local hosting)[string] + --tap-subgraph-endpoint Endpoint to query the tap subgraph from [string] Protocol - --default-allocation-amount Default amount of GRT to allocate to a subgraph - deployment [string] [default: "0.01"] - --register Whether to register the indexer on chain - [boolean] [default: true] - --epoch-subgraph-endpoint Endpoint to query epoch start blocks from + --epoch-subgraph-endpoint Endpoint to query the epoch block + oracle subgraph from [string] [required] + --subgraph-max-block-distance How many blocks subgraphs are allowed + to stay behind chain head + [number] [default: 1000] + --subgraph-freshness-sleep-milliseconds How long to wait before retrying + subgraph query if it is not fresh + [number] [default: 5000] + --default-allocation-amount Default amount of GRT to allocate to + a subgraph deployment + [number] [default: 0.01] + --register Whether to register the indexer on + chain [boolean] [default: true] + --max-provision-initial-size The maximum number of tokens for the + initial Subgraph Service provision + [number] [default: 0] -Postgres - --postgres-host Postgres host [string] [required] - --postgres-port Postgres port [number] [default: 5432] - --postgres-username Postgres username [string] [default: "postgres"] - --postgres-password Postgres password [string] [default: ""] - --postgres-database Postgres database name [string] [required] +Query Fees + --rebate-claim-threshold Minimum value of rebate for a single + allocation (in GRT) in order for it + to be included in a batch rebate + claim on-chain [number] [default: 1] + --rebate-claim-batch-threshold Minimum total value of all rebates + in an batch (in GRT) before the + batch is claimed on-chain + [number] [default: 5] + --rebate-claim-max-batch-size Maximum number of rebates inside a + batch. Upper bound is constrained by + available system memory, and by the + block gas limit + [number] [default: 100] + --voucher-redemption-threshold Minimum value of rebate for a single + allocation (in GRT) in order for it + to be included in a batch rebate + claim on-chain [number] [default: 1] + --voucher-redemption-batch-threshold Minimum total value of all rebates + in an batch (in GRT) before the + batch is claimed on-chain + [number] [default: 5] + --voucher-redemption-max-batch-size Maximum number of rebates inside a + batch. Upper bound is constrained by + available system memory, and by the + block gas limit + [number] [default: 100] + --gateway-endpoint, Gateway endpoint base URL + --collect-receipts-endpoint [string] [required] Disputes --poi-disputable-epochs The number of epochs in the past to look for @@ -152,23 +190,18 @@ Disputes --poi-dispute-monitoring Monitor the network for potential POI disputes [boolean] [default: false] -Query Fees - --vector-node URL of a vector node [string] - --vector-router Public identifier of the vector router[string] - --vector-transfer-definition Address of the Graph transfer definition - contract [string] [default: "auto"] - --vector-event-server External URL of the vector event server of the - agent [string] - --vector-event-server-port Port to serve the vector event server at - [number] [default: 8001] - --collect-receipts-endpoint Client endpoint for collecting receipts - [string] - Options: - --version Show version number [boolean] - --help Show help [boolean] - --offchain-subgraphs Subgraphs to index that are not on chain - (comma-separated) [array] [default: []] + --version Show version number [boolean] + --help Show help [boolean] + --offchain-subgraphs Subgraphs to index that are not on chain + (comma-separated) [array] [default: []] + --horizon-address-book Graph Horizon contracts address book file + path [string] + --subgraph-service-address-book Subgraph Service contracts address book file + path [string] + --tap-address-book TAP contracts address book file path [string] + --chain-finalize-time The time in seconds that the chain finalizes + blocks [number] [default: 3600] ``` ### Indexer CLI diff --git a/packages/indexer-agent/src/commands/start.ts b/packages/indexer-agent/src/commands/start.ts index ff79e783a..a80dd317e 100644 --- a/packages/indexer-agent/src/commands/start.ts +++ b/packages/indexer-agent/src/commands/start.ts @@ -99,6 +99,12 @@ export const start = { default: 0, group: 'Ethereum', }) + .option('confirmation-blocks', { + description: 'The number of blocks to wait for a transaction to be confirmed', + type: 'number', + default: 3, + group: 'Ethereum', + }) .option('mnemonic', { description: 'Mnemonic for the operator wallet', type: 'string', @@ -392,6 +398,7 @@ export async function createNetworkSpecification( gasPriceMax: argv.gasPriceMax, baseFeePerGasMax: argv.baseFeeGasMax, maxTransactionAttempts: argv.maxTransactionAttempts, + confirmationBlocks: argv.confirmationBlocks, } const subgraphs = { diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index c145e0802..8e92904c8 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -24,7 +24,7 @@ "dependencies": { "@pinax/graph-networks-registry": "0.6.7", "@graphprotocol/common-ts": "3.0.1", - "@graphprotocol/toolshed": "0.4.2", + "@graphprotocol/toolshed": "0.5.0", "@semiotic-labs/tap-contracts-bindings": "2.0.0", "@thi.ng/heaps": "1.2.38", "@types/lodash.clonedeep": "^4.5.7", diff --git a/packages/indexer-common/src/indexer-management/models/cost-model.ts b/packages/indexer-common/src/indexer-management/models/cost-model.ts index df2a71e4b..ce255fc78 100644 --- a/packages/indexer-common/src/indexer-management/models/cost-model.ts +++ b/packages/indexer-common/src/indexer-management/models/cost-model.ts @@ -39,13 +39,13 @@ export class CostModel extends Model implements CostModelAttributes { - public id!: number - public deployment!: string - public model!: string | null + declare id: number + declare deployment: string + declare model: string | null public variables!: CostModelVariables | null - public createdAt!: Date - public updatedAt!: Date + declare createdAt: Date + declare updatedAt: Date // eslint-disable-next-line @typescript-eslint/ban-types public toGraphQL(): object { diff --git a/packages/indexer-common/src/indexer-management/models/indexing-rule.ts b/packages/indexer-common/src/indexer-management/models/indexing-rule.ts index 76ee2b265..594191537 100644 --- a/packages/indexer-common/src/indexer-management/models/indexing-rule.ts +++ b/packages/indexer-common/src/indexer-management/models/indexing-rule.ts @@ -66,26 +66,26 @@ export class IndexingRule extends Model implements IndexingRuleAttributes { - public id!: number - public identifier!: string - public identifierType!: SubgraphIdentifierType - public allocationAmount!: string | null - public allocationLifetime!: number | null - public autoRenewal!: boolean - public parallelAllocations!: number | null - public maxAllocationPercentage!: number | null - public minSignal!: string | null - public maxSignal!: string | null - public minStake!: string | null - public minAverageQueryFees!: string | null - public custom!: string | null - public decisionBasis!: IndexingDecisionBasis - public requireSupported!: boolean - public safety!: boolean - public protocolNetwork!: string + declare id: number + declare identifier: string + declare identifierType: SubgraphIdentifierType + declare allocationAmount: string | null + declare allocationLifetime: number | null + declare autoRenewal: boolean + declare parallelAllocations: number | null + declare maxAllocationPercentage: number | null + declare minSignal: string | null + declare maxSignal: string | null + declare minStake: string | null + declare minAverageQueryFees: string | null + declare custom: string | null + declare decisionBasis: IndexingDecisionBasis + declare requireSupported: boolean + declare safety: boolean + declare protocolNetwork: string - public createdAt!: Date - public updatedAt!: Date + declare createdAt: Date + declare updatedAt: Date // eslint-disable-next-line @typescript-eslint/ban-types public toGraphQL(): object { diff --git a/packages/indexer-common/src/indexer-management/models/poi-dispute.ts b/packages/indexer-common/src/indexer-management/models/poi-dispute.ts index 8f7e1bb99..a4cd1e862 100644 --- a/packages/indexer-common/src/indexer-management/models/poi-dispute.ts +++ b/packages/indexer-common/src/indexer-management/models/poi-dispute.ts @@ -51,23 +51,23 @@ export class POIDispute extends Model implements POIDisputeAttributes { - public allocationID!: string - public subgraphDeploymentID!: string - public allocationIndexer!: string - public allocationAmount!: string - public allocationProof!: string - public closedEpoch!: number - public closedEpochReferenceProof!: string | null - public closedEpochStartBlockHash!: string - public closedEpochStartBlockNumber!: number - public previousEpochReferenceProof!: string | null - public previousEpochStartBlockHash!: string - public previousEpochStartBlockNumber!: number - public status!: string - public protocolNetwork!: string + declare allocationID: string + declare subgraphDeploymentID: string + declare allocationIndexer: string + declare allocationAmount: string + declare allocationProof: string + declare closedEpoch: number + declare closedEpochReferenceProof: string | null + declare closedEpochStartBlockHash: string + declare closedEpochStartBlockNumber: number + declare previousEpochReferenceProof: string | null + declare previousEpochStartBlockHash: string + declare previousEpochStartBlockNumber: number + declare status: string + declare protocolNetwork: string - public createdAt!: Date - public updatedAt!: Date + declare createdAt: Date + declare updatedAt: Date // eslint-disable-next-line @typescript-eslint/ban-types public toGraphQL(): object { diff --git a/packages/indexer-common/src/network-specification.ts b/packages/indexer-common/src/network-specification.ts index c3c01d4f0..cfcad72d1 100644 --- a/packages/indexer-common/src/network-specification.ts +++ b/packages/indexer-common/src/network-specification.ts @@ -88,6 +88,7 @@ export const TransactionMonitoring = z .transform((x) => x * 10 ** 9) .optional(), maxTransactionAttempts: z.number().nonnegative().finite().default(0), + confirmationBlocks: positiveNumber().default(3), }) .strict() .default({}) // defaults will be used for instantiation when the TransactionMonitoring group is absent. diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index d588e73f5..bb629df1b 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -136,9 +136,9 @@ export class Network { deployment: networkSubgraphDeploymentId !== undefined ? { - graphNode, - deployment: networkSubgraphDeploymentId, - } + graphNode, + deployment: networkSubgraphDeploymentId, + } : undefined, subgraphFreshnessChecker: networkSubgraphFreshnessChecker, }) @@ -162,9 +162,9 @@ export class Network { deployment: tapSubgraphDeploymentId !== undefined ? { - graphNode, - deployment: tapSubgraphDeploymentId, - } + graphNode, + deployment: tapSubgraphDeploymentId, + } : undefined, endpoint: specification.subgraphs.tapSubgraph!.url, subgraphFreshnessChecker: tapSubgraphFreshnessChecker, @@ -218,9 +218,9 @@ export class Network { deployment: epochSubgraphDeploymentId !== undefined ? { - graphNode, - deployment: epochSubgraphDeploymentId, - } + graphNode, + deployment: epochSubgraphDeploymentId, + } : undefined, endpoint: specification.subgraphs.epochSubgraph.url, subgraphFreshnessChecker: epochSubgraphFreshnessChecker, diff --git a/packages/indexer-common/src/transactions.ts b/packages/indexer-common/src/transactions.ts index 52866935c..6d0691591 100644 --- a/packages/indexer-common/src/transactions.ts +++ b/packages/indexer-common/src/transactions.ts @@ -124,11 +124,11 @@ export class TransactionManager { tx = await this.wallet.sendTransaction(txRequest) } - logger.info(`Transaction pending`, { tx: tx }) + logger.info(`Transaction pending`, { tx: tx, confirmationBlocks: this.specification.confirmationBlocks }) const receipt = await this.ethereum.waitForTransaction( tx.hash, - 3, + this.specification.confirmationBlocks, this.specification.gasIncreaseTimeout, ) diff --git a/yarn.lock b/yarn.lock index cb4678457..2e2f8412b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -593,10 +593,10 @@ resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.3.4.tgz#38929c04d03ad06823f9a867c8a4aef4c7f581e7" integrity sha512-POepREau0ExCz4ZJrlhzIS3RigEuzlbp/xlurpHkgaOn97cFAv3x9ZaE5a9uwh1azRm3Djz8RUBmXpqmwoK9NA== -"@graphprotocol/toolshed@0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.4.2.tgz#511b2c7e1b6fbe229c01de0e5de484877534982b" - integrity sha512-qdIalumrmrh7+X0nVr+v/1ZFD0G0dgtE0W47tKZugiw7YKmwnBFkp9MnpYrNzm9NDbs2lk0hn8WBg3W980+hEw== +"@graphprotocol/toolshed@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.5.0.tgz#e1937d59a3d34bc5bacbc825827d6345ba662711" + integrity sha512-8KlLbee8TAhibUGpdSI04iOnI9gkfErchSqrp/SHU1V5RDuATNCuVe3MVmOt+Jdjc747bTU+OLU+7YxLcAa5Aw== dependencies: "@graphprotocol/contracts" "^7.1.2" "@graphprotocol/horizon" "^0.3.2" From 0e6c9621cf3ecbc501cd2710feed9f3e214c716b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 2 Jun 2025 16:26:17 -0300 Subject: [PATCH 06/28] Horizon: allocation management (#1123) Co-authored-by: Maikol <86025070+Maikol@users.noreply.github.com> --- packages/indexer-agent/src/agent.ts | 97 +- packages/indexer-agent/src/commands/start.ts | 3 +- .../__tests__/references/indexer-help.stdout | 6 + .../src/__tests__/references/indexer.stdout | 6 + packages/indexer-cli/src/allocations.ts | 21 +- .../src/commands/indexer/allocations/close.ts | 32 +- .../src/commands/indexer/allocations/get.ts | 2 + .../indexer/allocations/reallocate.ts | 15 +- .../src/commands/indexer/provision.ts | 15 + .../src/commands/indexer/provision/add.ts | 105 ++ .../src/commands/indexer/provision/get.ts | 114 ++ .../commands/indexer/provision/list-thaw.ts | 110 ++ .../src/commands/indexer/provision/remove.ts | 116 ++ .../src/commands/indexer/provision/thaw.ts | 109 ++ .../src/commands/indexer/rules/set.ts | 15 +- .../src/commands/indexer/status.ts | 53 +- packages/indexer-cli/src/provisions.ts | 113 ++ packages/indexer-cli/src/run.ts | 2 + packages/indexer-cli/src/thaw-requests.ts | 106 ++ packages/indexer-common/package.json | 2 +- .../indexer-common/src/allocations/index.ts | 1 - .../indexer-common/src/allocations/keys.ts | 32 +- .../src/allocations/query-fees.test.ts | 79 - .../src/allocations/query-fees.ts | 812 -------- .../indexer-common/src/allocations/types.ts | 14 + packages/indexer-common/src/errors.ts | 12 + .../__tests__/helpers.test.ts | 10 +- .../src/indexer-management/actions.ts | 11 +- .../src/indexer-management/allocations.ts | 77 +- .../src/indexer-management/client.ts | 86 +- .../src/indexer-management/monitor.ts | 385 +++- .../resolvers/allocations.ts | 1676 ++++++++++++----- .../resolvers/indexer-status.ts | 122 +- .../resolvers/indexing-rules.ts | 19 +- .../resolvers/provisions.ts | 642 +++++++ .../src/indexer-management/rules.ts | 102 +- .../src/indexer-management/types.ts | 31 +- packages/indexer-common/src/network.ts | 30 +- packages/indexer-common/src/transactions.ts | 70 +- packages/indexer-common/src/types.ts | 5 + yarn.lock | 28 +- 41 files changed, 3564 insertions(+), 1722 deletions(-) create mode 100644 packages/indexer-cli/src/commands/indexer/provision.ts create mode 100644 packages/indexer-cli/src/commands/indexer/provision/add.ts create mode 100644 packages/indexer-cli/src/commands/indexer/provision/get.ts create mode 100644 packages/indexer-cli/src/commands/indexer/provision/list-thaw.ts create mode 100644 packages/indexer-cli/src/commands/indexer/provision/remove.ts create mode 100644 packages/indexer-cli/src/commands/indexer/provision/thaw.ts create mode 100644 packages/indexer-cli/src/provisions.ts create mode 100644 packages/indexer-cli/src/run.ts create mode 100644 packages/indexer-cli/src/thaw-requests.ts delete mode 100644 packages/indexer-common/src/allocations/query-fees.test.ts delete mode 100644 packages/indexer-common/src/allocations/query-fees.ts create mode 100644 packages/indexer-common/src/indexer-management/resolvers/provisions.ts diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index cbb415837..160fa3a23 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -38,6 +38,7 @@ import { DeploymentManagementMode, SubgraphStatus, sequentialTimerMap, + HorizonTransitionValue, } from '@graphprotocol/indexer-common' import PQueue from 'p-queue' @@ -47,7 +48,11 @@ import mapValues from 'lodash.mapvalues' import zip from 'lodash.zip' import { AgentConfigs, NetworkAndOperator } from './types' -type ActionReconciliationContext = [AllocationDecision[], number, bigint] +type ActionReconciliationContext = [ + AllocationDecision[], + number, + HorizonTransitionValue, +] const deploymentInList = ( list: SubgraphDeploymentID[], @@ -271,21 +276,22 @@ export class Agent { }, ) - const maxAllocationEpochs: Eventual> = - sequentialTimerMap( - { logger, milliseconds: requestIntervalLarge }, - () => - this.multiNetworks.map(({ network }) => { - logger.trace('Fetching max allocation epochs', { - protocolNetwork: network.specification.networkIdentifier, - }) - return network.contracts.LegacyStaking.maxAllocationEpochs() - }), - { - onError: error => - logger.warn(`Failed to fetch max allocation epochs`, { error }), - }, - ) + const maxAllocationDuration: Eventual< + NetworkMapped + > = sequentialTimerMap( + { logger, milliseconds: requestIntervalLarge }, + () => + this.multiNetworks.map(({ network }) => { + logger.trace('Fetching max allocation duration', { + protocolNetwork: network.specification.networkIdentifier, + }) + return network.networkMonitor.maxAllocationDuration() + }), + { + onError: error => + logger.warn(`Failed to fetch max allocation duration`, { error }), + }, + ) const indexingRules: Eventual> = sequentialTimerMap( @@ -653,7 +659,7 @@ export class Agent { join({ ticker: timer(requestIntervalLarge), currentEpochNumber, - maxAllocationEpochs, + maxAllocationDuration, activeDeployments, targetDeployments, activeAllocations, @@ -663,7 +669,7 @@ export class Agent { }).pipe( async ({ currentEpochNumber, - maxAllocationEpochs, + maxAllocationDuration, activeDeployments, targetDeployments, activeAllocations, @@ -746,7 +752,7 @@ export class Agent { await this.reconcileActions( networkDeploymentAllocationDecisions, currentEpochNumber, - maxAllocationEpochs, + maxAllocationDuration, ) } catch (err) { logger.warn(`Exited early while reconciling actions`, { @@ -1008,18 +1014,25 @@ export class Agent { activeAllocations: Allocation[], deploymentAllocationDecision: AllocationDecision, epoch: number, - maxAllocationEpochs: bigint, + maxAllocationDuration: HorizonTransitionValue, network: Network, ): Promise { - const desiredAllocationLifetime = deploymentAllocationDecision.ruleMatch - .rule?.allocationLifetime - ? deploymentAllocationDecision.ruleMatch.rule.allocationLifetime - : Math.max(1, Number(maxAllocationEpochs) - 1) - - // Identify expiring allocations let expiredAllocations = activeAllocations.filter( - allocation => - epoch >= allocation.createdAtEpoch + desiredAllocationLifetime, + async (allocation: Allocation) => { + let desiredAllocationLifetime: number = 0 + if (allocation.isLegacy) { + desiredAllocationLifetime = deploymentAllocationDecision.ruleMatch + .rule?.allocationLifetime + ? deploymentAllocationDecision.ruleMatch.rule.allocationLifetime + : Math.max(1, maxAllocationDuration.legacy - 1) + } else { + desiredAllocationLifetime = deploymentAllocationDecision.ruleMatch + .rule?.allocationLifetime + ? deploymentAllocationDecision.ruleMatch.rule.allocationLifetime + : maxAllocationDuration.horizon + } + return epoch >= allocation.createdAtEpoch + desiredAllocationLifetime + }, ) // The allocations come from the network subgraph; due to short indexing // latencies, this data may be slightly outdated. Cross-check with the @@ -1029,9 +1042,17 @@ export class Agent { expiredAllocations, async (allocation: Allocation) => { try { - const onChainAllocation = - await network.contracts.LegacyStaking.getAllocation(allocation.id) - return onChainAllocation.closedAtEpoch == 0n + if (allocation.isLegacy) { + const onChainAllocation = + await network.contracts.LegacyStaking.getAllocation(allocation.id) + return onChainAllocation.closedAtEpoch == 0n + } else { + const onChainAllocation = + await network.contracts.SubgraphService.getAllocation( + allocation.id, + ) + return onChainAllocation.closedAt == 0n + } } catch (err) { this.logger.warn( `Failed to cross-check allocation state with contracts; assuming it needs to be closed`, @@ -1052,7 +1073,7 @@ export class Agent { deploymentAllocationDecision: AllocationDecision, activeAllocations: Allocation[], epoch: number, - maxAllocationEpochs: bigint, + maxAllocationDuration: HorizonTransitionValue, network: Network, operator: Operator, ): Promise { @@ -1128,7 +1149,7 @@ export class Agent { activeDeploymentAllocations, deploymentAllocationDecision, epoch, - maxAllocationEpochs, + maxAllocationDuration, network, ) if (expiringAllocations.length > 0) { @@ -1147,7 +1168,7 @@ export class Agent { async reconcileActions( networkDeploymentAllocationDecisions: NetworkMapped, epoch: NetworkMapped, - maxAllocationEpochs: NetworkMapped, + maxAllocationDuration: NetworkMapped, ): Promise { // -------------------------------------------------------------------------------- // Filter out networks set to `manual` allocation management mode, and ensure the @@ -1200,14 +1221,14 @@ export class Agent { this.multiNetworks.zip3( validatedAllocationDecisions, epoch, - maxAllocationEpochs, + maxAllocationDuration, ), async ( { network, operator }: NetworkAndOperator, [ allocationDecisions, epoch, - maxAllocationEpochs, + maxAllocationDuration, ]: ActionReconciliationContext, ) => { // Do nothing if there are already approved actions in the queue awaiting execution @@ -1232,7 +1253,7 @@ export class Agent { this.logger.trace(`Reconcile allocation actions`, { protocolNetwork: network.specification.networkIdentifier, epoch, - maxAllocationEpochs, + maxAllocationDuration, targetDeployments: allocationDecisions .filter(decision => decision.toAllocate) .map(decision => decision.deployment.ipfsHash), @@ -1248,7 +1269,7 @@ export class Agent { decision, activeAllocations, epoch, - maxAllocationEpochs, + maxAllocationDuration, network, operator, ), diff --git a/packages/indexer-agent/src/commands/start.ts b/packages/indexer-agent/src/commands/start.ts index a80dd317e..c5e1c4a54 100644 --- a/packages/indexer-agent/src/commands/start.ts +++ b/packages/indexer-agent/src/commands/start.ts @@ -100,7 +100,8 @@ export const start = { group: 'Ethereum', }) .option('confirmation-blocks', { - description: 'The number of blocks to wait for a transaction to be confirmed', + description: + 'The number of blocks to wait for a transaction to be confirmed', type: 'number', default: 3, group: 'Ethereum', diff --git a/packages/indexer-cli/src/__tests__/references/indexer-help.stdout b/packages/indexer-cli/src/__tests__/references/indexer-help.stdout index 86d97c23f..8b6f5671d 100644 --- a/packages/indexer-cli/src/__tests__/references/indexer-help.stdout +++ b/packages/indexer-cli/src/__tests__/references/indexer-help.stdout @@ -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 diff --git a/packages/indexer-cli/src/__tests__/references/indexer.stdout b/packages/indexer-cli/src/__tests__/references/indexer.stdout index dd33b2010..4be8ef97d 100644 --- a/packages/indexer-cli/src/__tests__/references/indexer.stdout +++ b/packages/indexer-cli/src/__tests__/references/indexer.stdout @@ -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 diff --git a/packages/indexer-cli/src/allocations.ts b/packages/indexer-cli/src/allocations.ts index 879fb653b..b6656095b 100644 --- a/packages/indexer-cli/src/allocations.ts +++ b/packages/indexer-cli/src/allocations.ts @@ -29,6 +29,7 @@ export interface IndexerAllocation { queryFeesCollected: bigint status: string protocolNetwork: string + isLegacy: boolean } const ALLOCATION_CONVERTERS_FROM_GRAPHQL: Record< @@ -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< @@ -76,6 +78,7 @@ const ALLOCATION_FORMATTERS: Record< queryFeesCollected: x => commify(formatGRT(x)), status: x => x, protocolNetwork: resolveChainAlias, + isLegacy: x => (x ? 'Yes' : 'No'), } /** @@ -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 => { @@ -227,19 +232,22 @@ 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 } } @@ -247,6 +255,8 @@ export const closeAllocation = async ( { allocation: allocationID, poi, + blockNumber, + publicPOI, force, protocolNetwork, }, @@ -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, @@ -274,6 +286,8 @@ export const reallocateAllocation = async ( mutation reallocateAllocation( $allocation: String! $poi: String + $blockNumber: Int + $publicPOI: String $amount: String! $force: Boolean $protocolNetwork: String! @@ -281,13 +295,14 @@ export const reallocateAllocation = async ( reallocateAllocation( allocation: $allocation poi: $poi + blockNumber: $blockNumber + publicPOI: $publicPOI amount: $amount force: $force protocolNetwork: $protocolNetwork ) { closedAllocation indexingRewardsCollected - receiptsWorthCollecting createdAllocation createdAllocationStake protocolNetwork @@ -297,6 +312,8 @@ export const reallocateAllocation = async ( { allocation: allocationID, poi, + blockNumber, + publicPOI, amount: amount.toString(), force, protocolNetwork, diff --git a/packages/indexer-cli/src/commands/indexer/allocations/close.ts b/packages/indexer-cli/src/commands/indexer/allocations/close.ts index 796493939..05a5a4f09 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/close.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/close.ts @@ -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] +${chalk.bold( + 'graph indexer allocations close', +)} [options] ${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:')} + The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia + The allocation id to close + The POI to close the allocation with + The block number the POI was computed at + [Horizon] The public POI to close the allocation with. Must be same block height as POI. ` module.exports = { @@ -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'`) @@ -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 @@ -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()) diff --git a/packages/indexer-cli/src/commands/indexer/allocations/get.ts b/packages/indexer-cli/src/commands/indexer/allocations/get.ts index f5708e9b0..43f35abe3 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/get.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/get.ts @@ -99,6 +99,7 @@ module.exports = { query allocations($filter: AllocationFilter!) { allocations(filter: $filter) { id + isLegacy protocolNetwork indexer subgraphDeployment @@ -145,6 +146,7 @@ module.exports = { let displayProperties: (keyof IndexerAllocation)[] = [ 'id', + 'isLegacy', 'protocolNetwork', 'indexer', 'subgraphDeployment', diff --git a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts index d42b9a320..01e7c5da5 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts @@ -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:')} + The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia + The allocation id to close + The POI to close the allocation with + The block number the POI was computed at + [Horizon] The public POI to close the allocation with. Must be same block height as POI. ` module.exports = { @@ -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'`) @@ -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 }) @@ -81,6 +87,8 @@ module.exports = { client, id, poi, + Number(unformattedBlockNumber), + publicPOI, allocationAmount, toForce, network, @@ -94,7 +102,6 @@ module.exports = { [ 'closedAllocation', 'indexingRewardsCollected', - 'receiptsWorthCollecting', 'createdAllocation', 'createdAllocationStake', ], diff --git a/packages/indexer-cli/src/commands/indexer/provision.ts b/packages/indexer-cli/src/commands/indexer/provision.ts new file mode 100644 index 000000000..90e214ceb --- /dev/null +++ b/packages/indexer-cli/src/commands/indexer/provision.ts @@ -0,0 +1,15 @@ +import { GluegunToolbox } from 'gluegun' + +module.exports = { + name: 'provision', + alias: [], + description: "Manage indexer's provision", + hidden: false, + dashed: false, + run: async (toolbox: GluegunToolbox) => { + const { print } = toolbox + print.info(toolbox.command?.description) + print.printCommands(toolbox, ['indexer', 'provision']) + process.exitCode = 1 + }, +} diff --git a/packages/indexer-cli/src/commands/indexer/provision/add.ts b/packages/indexer-cli/src/commands/indexer/provision/add.ts new file mode 100644 index 000000000..ce4be5257 --- /dev/null +++ b/packages/indexer-cli/src/commands/indexer/provision/add.ts @@ -0,0 +1,105 @@ +import { GluegunToolbox } from 'gluegun' +import chalk from 'chalk' + +import { loadValidatedConfig } from '../../../config' +import { createIndexerManagementClient } from '../../../client' +import { extractProtocolNetworkOption } from '../../../command-helpers' +import gql from 'graphql-tag' +import { IndexerProvision, printIndexerProvisions } from '../../../provisions' + +const HELP = ` +${chalk.bold('graph indexer provision add')} [options] + +${chalk.dim('Options:')} + + -h, --help Show usage information + -n, --network Filter provisions by their protocol network (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) + -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML +` + +module.exports = { + name: 'add', + alias: [], + description: "Add stake to the indexer's provision", + run: async (toolbox: GluegunToolbox) => { + const { print, parameters } = toolbox + + const spinner = toolbox.print.spin('Processing inputs') + + const { h, help, o, output } = parameters.options + + const outputFormat = o || output || 'table' + + if (help || h) { + spinner.stopAndPersist({ symbol: '💁', text: HELP }) + return + } + + const [amount] = parameters.array || [] + + try { + if (!amount) { + throw new Error('Must provide an amount to add to the provision') + } + + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!['json', 'yaml', 'table'].includes(outputFormat)) { + throw Error( + `Invalid output format "${outputFormat}" must be one of 'json', 'yaml' or 'table'`, + ) + } + + spinner.text = 'Adding stake to the provision' + const config = loadValidatedConfig() + const client = await createIndexerManagementClient({ url: config.api }) + + const result = await client + .mutation( + gql` + mutation addToProvision($protocolNetwork: String!, $amount: String!) { + addToProvision(protocolNetwork: $protocolNetwork, amount: $amount) { + id + dataService + indexer + tokensProvisioned + protocolNetwork + } + } + `, + { + protocolNetwork, + amount: amount.toString(), + }, + ) + .toPromise() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (result.error) { + throw result.error + } + + const displayProperties: (keyof IndexerProvision)[] = [ + 'dataService', + 'protocolNetwork', + 'tokensProvisioned', + ] + + if (result.data.addToProvision) { + spinner.succeed('Stake added to the provision') + printIndexerProvisions( + print, + outputFormat, + result.data.addToProvision, + displayProperties, + ) + } else { + spinner.fail('Failed to add stake to the provision') + } + } catch (error) { + spinner.fail(error.toString()) + process.exitCode = 1 + return + } + }, +} diff --git a/packages/indexer-cli/src/commands/indexer/provision/get.ts b/packages/indexer-cli/src/commands/indexer/provision/get.ts new file mode 100644 index 000000000..31e9dad99 --- /dev/null +++ b/packages/indexer-cli/src/commands/indexer/provision/get.ts @@ -0,0 +1,114 @@ +import { GluegunToolbox } from 'gluegun' +import chalk from 'chalk' + +import { loadValidatedConfig } from '../../../config' +import { createIndexerManagementClient } from '../../../client' +import { extractProtocolNetworkOption } from '../../../command-helpers' +import gql from 'graphql-tag' +import { IndexerProvision, printIndexerProvisions } from '../../../provisions' +import { commify, formatGRT } from '@graphprotocol/common-ts' + +const HELP = ` +${chalk.bold('graph indexer provision get')} [options] + +${chalk.dim('Options:')} + + -h, --help Show usage information + -n, --network Filter provisions by their protocol network (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) + -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML +` + +module.exports = { + name: 'get', + alias: [], + description: 'List indexer provision details', + run: async (toolbox: GluegunToolbox) => { + const { print, parameters } = toolbox + + const spinner = toolbox.print.spin('Processing inputs') + + const { h, help, o, output } = parameters.options + + const outputFormat = o || output || 'table' + + if (help || h) { + spinner.stopAndPersist({ symbol: '💁', text: HELP }) + return + } + + try { + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!['json', 'yaml', 'table'].includes(outputFormat)) { + throw Error( + `Invalid output format "${outputFormat}" must be one of 'json', 'yaml' or 'table'`, + ) + } + + spinner.text = 'Querying indexer management server' + const config = loadValidatedConfig() + const client = await createIndexerManagementClient({ url: config.api }) + + const result = await client + .query( + gql` + query provisions($protocolNetwork: String!) { + provisions(protocolNetwork: $protocolNetwork) { + id + dataService + indexer + tokensProvisioned + tokensAllocated + tokensThawing + thawingPeriod + maxVerifierCut + protocolNetwork + idleStake + } + } + `, + { + protocolNetwork, + }, + ) + .toPromise() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (result.error) { + throw result.error + } + + const displayProperties: (keyof IndexerProvision)[] = [ + 'dataService', + 'protocolNetwork', + 'tokensProvisioned', + 'tokensAllocated', + 'tokensThawing', + 'maxVerifierCut', + 'thawingPeriod', + ] + + spinner.succeed('Provisions') + printIndexerProvisions( + print, + outputFormat, + result.data.provisions, + displayProperties, + ) + + print.info('') + print.info( + `Indexer's idle stake: ${commify( + formatGRT(result.data.provisions[0].idleStake), + )} GRT`, + ) + print.info( + "To add this stake to the Subgraph Service provision, run 'graph indexer provision add '", + ) + } catch (error) { + spinner.fail(error.toString()) + process.exitCode = 1 + return + } + }, +} diff --git a/packages/indexer-cli/src/commands/indexer/provision/list-thaw.ts b/packages/indexer-cli/src/commands/indexer/provision/list-thaw.ts new file mode 100644 index 000000000..167c2844a --- /dev/null +++ b/packages/indexer-cli/src/commands/indexer/provision/list-thaw.ts @@ -0,0 +1,110 @@ +import { GluegunToolbox } from 'gluegun' +import chalk from 'chalk' + +import { loadValidatedConfig } from '../../../config' +import { createIndexerManagementClient } from '../../../client' +import { extractProtocolNetworkOption } from '../../../command-helpers' +import gql from 'graphql-tag' +import { IndexerThawRequest, printIndexerThawRequests } from '../../../thaw-requests' + +const HELP = ` +${chalk.bold('graph indexer provision list-thaw')} [options] + +${chalk.dim('Options:')} + + -h, --help Show usage information + -n, --network Filter provisions by their protocol network (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) + -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML +` + +module.exports = { + name: 'list-thaw', + alias: [], + description: "List thaw requests for the indexer's provision", + run: async (toolbox: GluegunToolbox) => { + const { print, parameters } = toolbox + + const spinner = toolbox.print.spin('Processing inputs') + + const { h, help, o, output } = parameters.options + + const outputFormat = o || output || 'table' + + if (help || h) { + spinner.stopAndPersist({ symbol: '💁', text: HELP }) + return + } + + try { + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!['json', 'yaml', 'table'].includes(outputFormat)) { + throw Error( + `Invalid output format "${outputFormat}" must be one of 'json', 'yaml' or 'table'`, + ) + } + + spinner.text = 'Getting thaw requests for the provision' + const config = loadValidatedConfig() + const client = await createIndexerManagementClient({ url: config.api }) + + const result = await client + .query( + gql` + query thawRequests($protocolNetwork: String!) { + thawRequests(protocolNetwork: $protocolNetwork) { + id + fulfilled + dataService + indexer + shares + thawingUntil + protocolNetwork + currentBlockTimestamp + } + } + `, + { + protocolNetwork, + }, + ) + .toPromise() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (result.error) { + throw result.error + } + + const displayProperties: (keyof IndexerThawRequest)[] = [ + 'id', + 'fulfilled', + 'protocolNetwork', + 'shares', + 'thawingUntil', + ] + + if (result.data.thawRequests) { + spinner.succeed('Got thaw requests') + printIndexerThawRequests( + print, + outputFormat, + result.data.thawRequests, + displayProperties, + ) + + print.info('') + print.info( + `Latest block timestamp: ${new Date( + Number(result.data.thawRequests[0].currentBlockTimestamp) * 1000, + ).toLocaleString()}`, + ) + } else { + spinner.fail('Failed to get thaw requests') + } + } catch (error) { + spinner.fail(error.toString()) + process.exitCode = 1 + return + } + }, +} diff --git a/packages/indexer-cli/src/commands/indexer/provision/remove.ts b/packages/indexer-cli/src/commands/indexer/provision/remove.ts new file mode 100644 index 000000000..c585ef5aa --- /dev/null +++ b/packages/indexer-cli/src/commands/indexer/provision/remove.ts @@ -0,0 +1,116 @@ +import { GluegunToolbox } from 'gluegun' +import chalk from 'chalk' + +import { loadValidatedConfig } from '../../../config' +import { createIndexerManagementClient } from '../../../client' +import { extractProtocolNetworkOption } from '../../../command-helpers' +import gql from 'graphql-tag' +import { IndexerProvision, printIndexerProvisions } from '../../../provisions' +import { commify } from '@graphprotocol/common-ts' +import { formatGRT } from '@graphprotocol/common-ts' + +const HELP = ` +${chalk.bold('graph indexer provision remove')} [options] + +${chalk.dim('Options:')} + + -h, --help Show usage information + -n, --network Filter provisions by their protocol network (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) + -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML +` + +module.exports = { + name: 'remove', + alias: [], + description: "Remove thawed stake from the indexer's provision", + run: async (toolbox: GluegunToolbox) => { + const { print, parameters } = toolbox + + const spinner = toolbox.print.spin('Processing inputs') + + const { h, help, o, output } = parameters.options + + const outputFormat = o || output || 'table' + + if (help || h) { + spinner.stopAndPersist({ symbol: '💁', text: HELP }) + return + } + + try { + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!['json', 'yaml', 'table'].includes(outputFormat)) { + throw Error( + `Invalid output format "${outputFormat}" must be one of 'json', 'yaml' or 'table'`, + ) + } + + spinner.text = 'Removing thawed stake from the provision' + const config = loadValidatedConfig() + const client = await createIndexerManagementClient({ url: config.api }) + + const result = await client + .mutation( + gql` + mutation removeFromProvision($protocolNetwork: String!) { + removeFromProvision(protocolNetwork: $protocolNetwork) { + id + dataService + indexer + tokensProvisioned + tokensThawing + tokensRemoved + protocolNetwork + } + } + `, + { + protocolNetwork, + }, + ) + .toPromise() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (result.error) { + throw result.error + } + + const displayProperties: (keyof IndexerProvision)[] = [ + 'dataService', + 'protocolNetwork', + 'tokensProvisioned', + 'tokensThawing', + ] + + if (result.data.removeFromProvision) { + if (result.data.removeFromProvision.tokensRemoved > 0) { + spinner.succeed('Thawed stake removed from the provision') + printIndexerProvisions( + print, + outputFormat, + result.data.removeFromProvision, + displayProperties, + ) + + print.info('') + print.info( + `Removed ${commify( + formatGRT(result.data.removeFromProvision.tokensRemoved), + )} GRT from the provision`, + ) + } else { + spinner.fail( + 'No thawed stake to remove from the provision. Run `graph indexer provision list-thaw` to see thawing details.', + ) + } + } else { + spinner.fail('Failed to remove thawed stake from the provision') + } + } catch (error) { + spinner.fail(error.toString()) + process.exitCode = 1 + return + } + }, +} diff --git a/packages/indexer-cli/src/commands/indexer/provision/thaw.ts b/packages/indexer-cli/src/commands/indexer/provision/thaw.ts new file mode 100644 index 000000000..2e4dda78a --- /dev/null +++ b/packages/indexer-cli/src/commands/indexer/provision/thaw.ts @@ -0,0 +1,109 @@ +import { GluegunToolbox } from 'gluegun' +import chalk from 'chalk' + +import { loadValidatedConfig } from '../../../config' +import { createIndexerManagementClient } from '../../../client' +import { extractProtocolNetworkOption } from '../../../command-helpers' +import gql from 'graphql-tag' +import { IndexerProvision, printIndexerProvisions } from '../../../provisions' + +const HELP = ` +${chalk.bold('graph indexer provision thaw')} [options] + +${chalk.dim('Options:')} + + -h, --help Show usage information + -n, --network Filter provisions by their protocol network (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) + -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML +` + +module.exports = { + name: 'thaw', + alias: [], + description: "Thaw stake from the indexer's provision", + run: async (toolbox: GluegunToolbox) => { + const { print, parameters } = toolbox + + const spinner = toolbox.print.spin('Processing inputs') + + const { h, help, o, output } = parameters.options + + const outputFormat = o || output || 'table' + + if (help || h) { + spinner.stopAndPersist({ symbol: '💁', text: HELP }) + return + } + + const [amount] = parameters.array || [] + + try { + if (!amount) { + throw new Error('Must provide an amount to thaw from the provision') + } + + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!['json', 'yaml', 'table'].includes(outputFormat)) { + throw Error( + `Invalid output format "${outputFormat}" must be one of 'json', 'yaml' or 'table'`, + ) + } + + spinner.text = 'Thawing stake from the provision' + const config = loadValidatedConfig() + const client = await createIndexerManagementClient({ url: config.api }) + + const result = await client + .mutation( + gql` + mutation thawFromProvision($protocolNetwork: String!, $amount: String!) { + thawFromProvision(protocolNetwork: $protocolNetwork, amount: $amount) { + id + dataService + indexer + tokensThawing + thawingPeriod + thawingUntil + protocolNetwork + } + } + `, + { + protocolNetwork, + amount: amount.toString(), + }, + ) + .toPromise() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (result.error) { + throw result.error + } + + const displayProperties: (keyof IndexerProvision)[] = [ + 'dataService', + 'protocolNetwork', + 'tokensThawing', + 'thawingPeriod', + 'thawingUntil', + ] + + if (result.data.thawFromProvision) { + spinner.succeed('Stake thawed from the provision') + printIndexerProvisions( + print, + outputFormat, + result.data.thawFromProvision, + displayProperties, + ) + } else { + spinner.fail('Failed to thaw stake from the provision') + } + } catch (error) { + spinner.fail(error.toString()) + process.exitCode = 1 + return + } + }, +} diff --git a/packages/indexer-cli/src/commands/indexer/rules/set.ts b/packages/indexer-cli/src/commands/indexer/rules/set.ts index 09de0bbc0..596c5c6ed 100644 --- a/packages/indexer-cli/src/commands/indexer/rules/set.ts +++ b/packages/indexer-cli/src/commands/indexer/rules/set.ts @@ -102,10 +102,17 @@ module.exports = { const valid_commands = Object.keys(tmpRules).filter( c => c != 'parallelAllocations', ) - throw new Error( - `Indexing rule attribute '${error.message}' not supported, did you mean?\n` + - stringify(suggestCommands(error.message, valid_commands)).replace(/\n$/, ''), - ) + if (valid_commands.includes(error.message)) { + throw new Error( + `Indexing rule attribute '${error.message}' not supported, did you mean?\n` + + stringify(suggestCommands(error.message, valid_commands)).replace( + /\n$/, + '', + ), + ) + } else { + throw error + } } } catch (error) { print.error(error.toString()) diff --git a/packages/indexer-cli/src/commands/indexer/status.ts b/packages/indexer-cli/src/commands/indexer/status.ts index 79a9636fa..5c849ad40 100644 --- a/packages/indexer-cli/src/commands/indexer/status.ts +++ b/packages/indexer-cli/src/commands/indexer/status.ts @@ -25,10 +25,12 @@ ${chalk.dim('Options:')} ` interface Endpoint { + name: string url: string | null healthy: boolean protocolNetwork: string tests: any[] + isLegacy: boolean } interface Endpoints { @@ -80,6 +82,7 @@ module.exports = { latitude longitude } + isLegacy } indexerDeployments { @@ -118,6 +121,7 @@ module.exports = { indexerEndpoints(protocolNetwork: $protocolNetwork) { service { + name url healthy protocolNetwork @@ -126,8 +130,10 @@ module.exports = { error possibleActions } + isLegacy } status { + name url healthy protocolNetwork @@ -136,6 +142,7 @@ module.exports = { error possibleActions } + isLegacy } } @@ -181,12 +188,16 @@ module.exports = { } if (result.data.indexerRegistration) { - data.registration = pickFields(result.data.indexerRegistration, []) - if (data.registration.location) { - data.registration.location = `${data.registration.location.latitude},${data.registration.location.longitude}` - } else { - data.registration.location = 'No location specified' - } + data.registration = result.data.indexerRegistration.map((registration: any) => { + return pickFields(registration, []) + }) + data.registration.forEach((registration: any) => { + if (registration.location) { + registration.location = `${registration.location.latitude},${registration.location.longitude}` + } else { + registration.location = 'No location specified' + } + }) } else { data.registration = { error: @@ -199,18 +210,20 @@ module.exports = { const { service, status } = endpoints return [ { - name: 'service', + name: service.name, url: service.url, tests: service.tests, protocolNetwork: resolveChainAlias(service.protocolNetwork), status: formatStatus(outputFormat, service.healthy), + isLegacy: service.isLegacy, }, { - name: 'status', + name: status.name, url: status.url, tests: status.tests, protocolNetwork: resolveChainAlias(status.protocolNetwork), status: formatStatus(outputFormat, status.healthy), + isLegacy: status.isLegacy, }, ] }) @@ -249,7 +262,21 @@ module.exports = { if (outputFormat === 'table') { print.info(chalk.cyan('Registration')) - print.info(formatData(data.registration, outputFormat)) + print.info( + formatData( + data.registration.map((registration: any) => + pickFields(registration, [ + 'url', + 'address', + 'protocolNetwork', + 'registered', + 'isLegacy', + 'location', + ]), + ), + outputFormat, + ), + ) print.info(chalk.cyan('\nEndpoints')) if (data.endpoints.error) { print.error(formatData([data.endpoints], outputFormat)) @@ -257,7 +284,13 @@ module.exports = { print.info( formatData( data.endpoints.map((endpoint: any) => - pickFields(endpoint, ['name', 'protocolNetwork', 'url', 'status']), + pickFields(endpoint, [ + 'name', + 'protocolNetwork', + 'url', + 'status', + 'isLegacy', + ]), ), outputFormat, ), diff --git a/packages/indexer-cli/src/provisions.ts b/packages/indexer-cli/src/provisions.ts new file mode 100644 index 000000000..7540a7cff --- /dev/null +++ b/packages/indexer-cli/src/provisions.ts @@ -0,0 +1,113 @@ +import { formatGRT, commify } from '@graphprotocol/common-ts' +import yaml from 'yaml' +import { GluegunPrint } from 'gluegun' +import { table, getBorderCharacters } from 'table' +import { OutputFormat, parseOutputFormat, pickFields } from './command-helpers' +import { resolveChainAlias } from '@graphprotocol/indexer-common' +import { BigNumberish } from 'ethers' + +function formatPPM(x: BigNumberish): string { + return ((Number(x) / 1_000_000) * 100).toString() +} + +export interface IndexerProvision { + id: string + dataService: string + indexer: string + tokensProvisioned: bigint + tokensAllocated: bigint + tokensThawing: bigint + maxVerifierCut: bigint + thawingPeriod: bigint + + protocolNetwork: string + + // TODO: This is not really a provision property, but useful to avoid creating new types + thawingUntil: string +} + +const PROVISION_FORMATTERS: Record string | null> = + { + id: nullPassThrough(x => x), + dataService: nullPassThrough(x => x), + indexer: nullPassThrough(x => x), + tokensProvisioned: x => commify(formatGRT(x)), + tokensAllocated: x => commify(formatGRT(x)), + tokensThawing: x => commify(formatGRT(x)), + maxVerifierCut: x => commify(formatPPM(x)), + thawingPeriod: x => x, + thawingUntil: x => new Date(Number(x) * 1000).toLocaleString(), + protocolNetwork: resolveChainAlias, + } + +/** + * Formats an indexer provision for display in the console. + */ +export const formatIndexerProvision = ( + provision: Partial, +): Partial => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const obj = {} as any + for (const [key, value] of Object.entries(provision)) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + obj[key] = (PROVISION_FORMATTERS as any)[key](value) + } + + return obj as Partial +} + +export const printIndexerProvisions = ( + print: GluegunPrint, + outputFormat: OutputFormat, + provisionOrProvisions: Partial | Partial[] | null, + keys: (keyof IndexerProvision)[], +): void => { + parseOutputFormat(print, outputFormat) + if (Array.isArray(provisionOrProvisions)) { + const provisions = provisionOrProvisions.map(provision => + formatIndexerProvision(pickFields(provision, keys)), + ) + print.info(displayIndexerProvisions(outputFormat, provisions)) + } else if (provisionOrProvisions) { + const provision = formatIndexerProvision(pickFields(provisionOrProvisions, keys)) + print.info(displayIndexerProvision(outputFormat, provision)) + } else { + print.error(`No provisions found`) + } +} + +export const displayIndexerProvisions = ( + outputFormat: OutputFormat, + provisions: Partial[], +): string => + outputFormat === OutputFormat.Json + ? JSON.stringify(provisions, null, 2) + : outputFormat === OutputFormat.Yaml + ? yaml.stringify(provisions).trim() + : provisions.length === 0 + ? 'No provisions found' + : table( + [ + Object.keys(provisions[0]), + ...provisions.map(provision => Object.values(provision)), + ], + { + border: getBorderCharacters('norc'), + }, + ).trim() + +export const displayIndexerProvision = ( + outputFormat: OutputFormat, + provision: Partial, +): string => + outputFormat === OutputFormat.Json + ? JSON.stringify(provision, null, 2) + : outputFormat === OutputFormat.Yaml + ? yaml.stringify(provision).trim() + : table([Object.keys(provision), Object.values(provision)], { + border: getBorderCharacters('norc'), + }).trim() + +function nullPassThrough(fn: (x: T) => U): (x: T | null) => U | null { + return (x: T | null) => (x === null ? null : fn(x)) +} diff --git a/packages/indexer-cli/src/run.ts b/packages/indexer-cli/src/run.ts new file mode 100644 index 000000000..b59c5b834 --- /dev/null +++ b/packages/indexer-cli/src/run.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +require('./cli').run(process.argv) diff --git a/packages/indexer-cli/src/thaw-requests.ts b/packages/indexer-cli/src/thaw-requests.ts new file mode 100644 index 000000000..47c7465b0 --- /dev/null +++ b/packages/indexer-cli/src/thaw-requests.ts @@ -0,0 +1,106 @@ +import { formatGRT, commify } from '@graphprotocol/common-ts' +import yaml from 'yaml' +import { GluegunPrint } from 'gluegun' +import { table, getBorderCharacters } from 'table' +import { OutputFormat, parseOutputFormat, pickFields } from './command-helpers' +import { resolveChainAlias } from '@graphprotocol/indexer-common' + +export interface IndexerThawRequest { + id: string + fulfilled: string + dataService: string + indexer: string + shares: string + thawingUntil: string + protocolNetwork: string +} + +const THAW_REQUEST_FORMATTERS: Record< + keyof IndexerThawRequest, + (x: never) => string | null +> = { + id: nullPassThrough(x => x), + fulfilled: nullPassThrough(x => x), + dataService: nullPassThrough(x => x), + indexer: nullPassThrough(x => x), + shares: x => commify(formatGRT(x)), + thawingUntil: x => new Date(Number(x) * 1000).toLocaleString(), + protocolNetwork: resolveChainAlias, +} + +/** + * Formats an indexer thaw request for display in the console. + */ +export const formatIndexerThawRequest = ( + thawRequest: Partial, +): Partial => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const obj = {} as any + for (const [key, value] of Object.entries(thawRequest)) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + obj[key] = (THAW_REQUEST_FORMATTERS as any)[key](value) + } + + return obj as Partial +} + +export const printIndexerThawRequests = ( + print: GluegunPrint, + outputFormat: OutputFormat, + thawRequestOrThawRequests: + | Partial + | Partial[] + | null, + keys: (keyof IndexerThawRequest)[], +): void => { + parseOutputFormat(print, outputFormat) + if (Array.isArray(thawRequestOrThawRequests)) { + const thawRequests = thawRequestOrThawRequests.map(thawRequest => + formatIndexerThawRequest(pickFields(thawRequest, keys)), + ) + print.info(displayIndexerThawRequests(outputFormat, thawRequests)) + } else if (thawRequestOrThawRequests) { + const thawRequest = formatIndexerThawRequest( + pickFields(thawRequestOrThawRequests, keys), + ) + print.info(displayIndexerThawRequest(outputFormat, thawRequest)) + } else { + print.error(`No thaw requests found`) + } +} + +export const displayIndexerThawRequests = ( + outputFormat: OutputFormat, + thawRequests: Partial[], +): string => + outputFormat === OutputFormat.Json + ? JSON.stringify(thawRequests, null, 2) + : outputFormat === OutputFormat.Yaml + ? yaml.stringify(thawRequests).trim() + : thawRequests.length === 0 + ? 'No thaw requests found' + : table( + [ + Object.keys(thawRequests[0]), + ...thawRequests.map(thawRequest => Object.values(thawRequest)), + ], + { + border: getBorderCharacters('norc'), + }, + ).trim() + +export const displayIndexerThawRequest = ( + outputFormat: OutputFormat, + thawRequest: Partial, +): string => + outputFormat === OutputFormat.Json + ? JSON.stringify(thawRequest, null, 2) + : outputFormat === OutputFormat.Yaml + ? yaml.stringify(thawRequest).trim() + : table([Object.keys(thawRequest), Object.values(thawRequest)], { + border: getBorderCharacters('norc'), + }).trim() + +function nullPassThrough(fn: (x: T) => U): (x: T | null) => U | null { + return (x: T | null) => (x === null ? null : fn(x)) +} diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index 8e92904c8..50e1606cb 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -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", diff --git a/packages/indexer-common/src/allocations/index.ts b/packages/indexer-common/src/allocations/index.ts index 79e60e617..8db9cdaf1 100644 --- a/packages/indexer-common/src/allocations/index.ts +++ b/packages/indexer-common/src/allocations/index.ts @@ -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' diff --git a/packages/indexer-common/src/allocations/keys.ts b/packages/indexer-common/src/allocations/keys.ts index b7b3b8d39..da11921c8 100644 --- a/packages/indexer-common/src/allocations/keys.ts +++ b/packages/indexer-common/src/allocations/keys.ts @@ -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, @@ -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, @@ -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 => { + 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, diff --git a/packages/indexer-common/src/allocations/query-fees.test.ts b/packages/indexer-common/src/allocations/query-fees.test.ts deleted file mode 100644 index d42342ea4..000000000 --- a/packages/indexer-common/src/allocations/query-fees.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { PartialVoucher, encodePartialVouchers } from './query-fees' - -const TEST_DATA: Array = [ - { - allocation: '0x6aea8894b5ab5a36cdc2d8be9290046801dd5fed', - fees: '1208491688206053754', - receipt_id_max: '0x1321676bb44e606cda1779a8d92af9', - receipt_id_min: '0x01460d518a7b0b278dcd2bf882c11a', - signature: - '0x81140e47bc06819e133735bbd622213d50029d958115e4f905f18fcede2dce0f027669b2a5a6b0303d1692d7f2f01db65236f632f4c02450b102275c2cb816e11c', - }, - { - allocation: '0x6aea8894b5ab5a36cdc2d8be9290046801dd5fed', - fees: '1215330506986176264', - receipt_id_max: '0x1ea67d3d01eb7d6b25e33332e4f5fd', - receipt_id_min: '0x13ce97080acc5acf664404fdb9038f', - signature: - '0x62374ca18ad2713d149e1e90c3771d7fc4e5c643f7f063bacd497b7be2089c72404026ea675e189017c072850811422514a9781c663414f42689f697dc262ad21c', - }, - { - allocation: '0x6aea8894b5ab5a36cdc2d8be9290046801dd5fed', - fees: '1215454440881710511', - receipt_id_max: '0x2e8f582977cbacb24b4fc0d0d52436', - receipt_id_min: '0x217ae93ba26b959edfa33eeb08c0ba', - signature: - '0x657ddb7e0b09c8b0a5938df2d29d5d6d9412c5f153b4a409ca05cb6c62be1cf30016394462eaf2d1b86049f3ad71c0c2162bc97965a98a19a3bbf372106b82c01c', - }, -] - -const TEST_DATA_MULTIPLE_ALLOCATIONS_PARTIAL_VOUCHERS: Array = [ - { - allocation: '0x7bea8894b5ab5a36cdc2d8be9290046801dd5fed', - fees: '1208491688206053754', - receipt_id_max: '0x1321676bb44e606cda1779a8d92af9', - receipt_id_min: '0x01460d518a7b0b278dcd2bf882c11a', - signature: - '0x81140e47bc06819e133735bbd622213d50029d958115e4f905f18fcede2dce0f027669b2a5a6b0303d1692d7f2f01db65236f632f4c02450b102275c2cb816e11c', - }, - { - allocation: '0x6aea8894b5ab5a36cdc2d8be9290046801dd5fed', - fees: '1215330506986176264', - receipt_id_max: '0x1ea67d3d01eb7d6b25e33332e4f5fd', - receipt_id_min: '0x13ce97080acc5acf664404fdb9038f', - signature: - '0x62374ca18ad2713d149e1e90c3771d7fc4e5c643f7f063bacd497b7be2089c72404026ea675e189017c072850811422514a9781c663414f42689f697dc262ad21c', - }, - { - allocation: '0x6aea8894b5ab5a36cdc2d8be9290046801dd5fed', - fees: '1215454440881710511', - receipt_id_max: '0x2e8f582977cbacb24b4fc0d0d52436', - receipt_id_min: '0x217ae93ba26b959edfa33eeb08c0ba', - signature: - '0x657ddb7e0b09c8b0a5938df2d29d5d6d9412c5f153b4a409ca05cb6c62be1cf30016394462eaf2d1b86049f3ad71c0c2162bc97965a98a19a3bbf372106b82c01c', - }, -] - -describe('Encode partial vouchers', () => { - test('encode a single partial voucher', () => { - const partialVoucherData = TEST_DATA.slice(0, 1) - expect(encodePartialVouchers(partialVoucherData)).toEqual({ - allocation: partialVoucherData[0].allocation, - partialVouchers: partialVoucherData, - }) - }) - - test('encode multiple partial vouchers', () => { - expect(encodePartialVouchers(TEST_DATA)).toEqual({ - allocation: TEST_DATA[0].allocation, - partialVouchers: TEST_DATA, - }) - }) - - test('fail to encode vouchers because they are from multiple allocations', () => { - const partialVoucherData = TEST_DATA_MULTIPLE_ALLOCATIONS_PARTIAL_VOUCHERS - expect(() => encodePartialVouchers(partialVoucherData)).toThrowError( - `Partial vouchers set must be for a single allocation, '2' unique allocations represented`, - ) - }) -}) diff --git a/packages/indexer-common/src/allocations/query-fees.ts b/packages/indexer-common/src/allocations/query-fees.ts deleted file mode 100644 index 69c62486e..000000000 --- a/packages/indexer-common/src/allocations/query-fees.ts +++ /dev/null @@ -1,812 +0,0 @@ -import { Counter, Gauge, Histogram } from 'prom-client' -import axios from 'axios' -import { - Logger, - BytesWriter, - toAddress, - formatGRT, - Address, - Metrics, - Eventual, -} from '@graphprotocol/common-ts' -import { - Allocation, - AllocationReceipt, - indexerError, - IndexerErrorCode, - QueryFeeModels, - Voucher, - ensureAllocationSummary, - TransactionManager, - specification as spec, - sequentialTimerMap, - SubgraphClient, -} from '..' -import { DHeap } from '@thi.ng/heaps' -import { BigNumberish, Contract } from 'ethers' -import { Op } from 'sequelize' -import pReduce from 'p-reduce' - -// Receipts are collected with a delay of 20 minutes after -// the corresponding allocation was closed -const RECEIPT_COLLECT_DELAY = 1200_000 - -interface AllocationReceiptsBatch { - receipts: AllocationReceipt[] - timeout: number -} - -export interface PartialVoucher { - allocation: string // (0x-prefixed hex) - fees: string // (0x-prefixed hex) - signature: string // (0x-prefixed hex) - receipt_id_min: string // (0x-prefixed hex) - receipt_id_max: string // (0x-prefixed hex) -} - -interface ReceiptMetrics { - receiptsToCollect: Gauge - failedReceipts: Counter - partialVouchersToExchange: Gauge - receiptsCollectDuration: Histogram - vouchers: Counter - successVoucherRedeems: Counter - invalidVoucherRedeems: Counter - failedVoucherRedeems: Counter - vouchersRedeemDuration: Histogram - vouchersBatchRedeemSize: Gauge - voucherCollectedFees: Gauge -} - -export interface AllocationPartialVouchers { - allocation: string - partialVouchers: PartialVoucher[] -} - -export interface AllocationReceiptCollectorOptions { - logger: Logger - metrics: Metrics - transactionManager: TransactionManager - allocationExchange: Contract - allocations: Eventual - models: QueryFeeModels - networkSpecification: spec.NetworkSpecification - networkSubgraph: SubgraphClient -} - -export interface ReceiptCollector { - rememberAllocations(actionID: number, allocationIDs: Address[]): Promise - collectReceipts(actionID: number, allocation: Allocation): Promise -} - -export class AllocationReceiptCollector implements ReceiptCollector { - declare logger: Logger - declare metrics: ReceiptMetrics - declare models: QueryFeeModels - declare transactionManager: TransactionManager - declare allocationExchange: Contract - declare allocations: Eventual - declare collectEndpoint: URL - declare partialVoucherEndpoint: URL - declare voucherEndpoint: URL - declare receiptsToCollect: DHeap - declare voucherRedemptionThreshold: bigint - declare voucherRedemptionBatchThreshold: bigint - declare voucherRedemptionMaxBatchSize: number - declare protocolNetwork: string - declare networkSubgraph: SubgraphClient - - // eslint-disable-next-line @typescript-eslint/no-empty-function -- Private constructor to prevent direct instantiation - private constructor() {} - - public static async create({ - logger, - metrics, - transactionManager, - models, - allocationExchange, - allocations, - networkSpecification, - networkSubgraph, - }: AllocationReceiptCollectorOptions): Promise { - const collector = new AllocationReceiptCollector() - collector.logger = logger.child({ component: 'AllocationReceiptCollector' }) - collector.metrics = registerReceiptMetrics( - metrics, - networkSpecification.networkIdentifier, - ) - collector.transactionManager = transactionManager - collector.models = models - collector.allocationExchange = allocationExchange - collector.allocations = allocations - collector.protocolNetwork = networkSpecification.networkIdentifier - collector.networkSubgraph = networkSubgraph - - // Process Gateway routes - const gatewayUrls = processGatewayRoutes(networkSpecification.gateway.url) - collector.collectEndpoint = gatewayUrls.collectReceipts - collector.voucherEndpoint = gatewayUrls.voucher - collector.partialVoucherEndpoint = gatewayUrls.partialVoucher - - const { - voucherRedemptionThreshold, - voucherRedemptionBatchThreshold, - voucherRedemptionMaxBatchSize, - } = networkSpecification.indexerOptions - collector.voucherRedemptionThreshold = voucherRedemptionThreshold - collector.voucherRedemptionBatchThreshold = voucherRedemptionBatchThreshold - collector.voucherRedemptionMaxBatchSize = voucherRedemptionMaxBatchSize - - // Start the AllocationReceiptCollector - // TODO: Consider calling methods conditionally based on a boolean - // flag during startup. - collector.startReceiptCollecting() - collector.startVoucherProcessing() - await collector.queuePendingReceiptsFromDatabase() - return collector - } - - async rememberAllocations( - actionID: number, - allocationIDs: Address[], - ): Promise { - const logger = this.logger.child({ - action: actionID, - allocations: allocationIDs, - }) - - try { - logger.info('Remember allocations for collecting receipts later') - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await this.models.allocationSummaries.sequelize!.transaction( - async (transaction) => { - for (const allocation of allocationIDs) { - const [summary] = await ensureAllocationSummary( - this.models, - allocation, - transaction, - this.protocolNetwork, - ) - await summary.save({ transaction }) - } - }, - ) - return true - } catch (err) { - logger.error(`Failed to remember allocations for collecting receipts later`, { - err: indexerError(IndexerErrorCode.IE056, err), - }) - return false - } - } - - async collectReceipts(actionID: number, allocation: Allocation): Promise { - const logger = this.logger.child({ - action: actionID, - allocation: allocation.id, - deployment: allocation.subgraphDeployment.id.display, - }) - - try { - logger.debug(`Queue allocation receipts for collecting`, { actionID, allocation }) - - const now = new Date() - - const receipts = - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await this.models.allocationReceipts.sequelize!.transaction( - async (transaction) => { - // Update the allocation summary - await this.models.allocationSummaries.update( - { closedAt: now }, - { - where: { - allocation: allocation.id, - protocolNetwork: this.protocolNetwork, - }, - transaction, - }, - ) - - // Return all receipts for the just-closed allocation - return this.models.allocationReceipts.findAll({ - where: { allocation: allocation.id, protocolNetwork: this.protocolNetwork }, - order: ['id'], - transaction, - }) - }, - ) - - this.metrics.receiptsToCollect.set( - { allocation: receipts[0]?.allocation }, - receipts.length, - ) - if (receipts.length <= 0) { - logger.debug(`No receipts to collect for allocation`, { actionID, allocation }) - return false - } - - const timeout = now.valueOf() + RECEIPT_COLLECT_DELAY - - // Collect the receipts for this allocation in a bit - this.receiptsToCollect.push({ - receipts, - timeout, - }) - logger.info(`Successfully queued allocation receipts for collecting`, { - receipts: receipts.length, - timeout: new Date(timeout).toLocaleString(), - actionID, - allocation, - }) - return true - } catch (err) { - const error = indexerError(IndexerErrorCode.IE053, err) - this.metrics.failedReceipts.inc({ allocation: allocation.id }) - this.logger.error(`Failed to queue allocation receipts for collecting`, { - error, - actionID, - allocation, - }) - throw error - } - } - - private startReceiptCollecting() { - this.receiptsToCollect = new DHeap(null, { - compare: (t1, t2) => t1.timeout - t2.timeout, - }) - - const hasReceiptsReadyForCollecting = () => { - const batch = this.receiptsToCollect.peek() - return batch && batch.timeout <= Date.now() - } - - // Check if there's another batch of receipts to collect every 10s - sequentialTimerMap({ logger: this.logger, milliseconds: 10_000 }, async () => { - while (hasReceiptsReadyForCollecting()) { - // Remove the batch from the processing queue - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const batch = this.receiptsToCollect.pop()! - - // If the array is empty we cannot know what allocation this group - // belongs to. Should this assertion ever fail, then there is a - // programmer error where empty batches are pushed to the - // `receiptsToCollect` queue. - console.assert(batch.receipts.length > 0) - - // Collect the receipts now - await this.obtainReceiptsVoucher(batch.receipts) - } - }) - } - - private startVoucherProcessing() { - sequentialTimerMap({ logger: this.logger, milliseconds: 30_000 }, async () => { - let pendingVouchers: Voucher[] = [] - try { - pendingVouchers = await this.pendingVouchers() // Ordered by value - } catch (err) { - this.logger.warn(`Failed to query pending vouchers`, { err }) - return - } - - const logger = this.logger.child({}) - - const vouchers = await pReduce( - pendingVouchers, - async (results, voucher) => { - if (await this.allocationExchange.allocationsRedeemed(voucher.allocation)) { - try { - await this.models.vouchers.destroy({ - where: { - allocation: voucher.allocation, - protocolNetwork: this.protocolNetwork, - }, - }) - logger.warn( - `Query fee voucher for allocation already redeemed, deleted local voucher copy`, - { allocation: voucher.allocation }, - ) - } catch (err) { - logger.warn(`Failed to delete local vouchers copy, will try again later`, { - err, - allocation: voucher.allocation, - }) - } - return results - } - if (BigInt(voucher.amount) < this.voucherRedemptionThreshold) { - results.belowThreshold.push(voucher) - } else { - results.eligible.push(voucher) - } - return results - }, - { belowThreshold: [], eligible: [] }, - ) - - if (vouchers.belowThreshold.length > 0) { - const totalValueGRT = formatGRT( - vouchers.belowThreshold.reduce( - (total, voucher) => total + BigInt(voucher.amount), - 0n, - ), - ) - logger.info(`Query vouchers below the redemption threshold`, { - hint: 'If you would like to redeem vouchers like this, reduce the voucher redemption threshold', - voucherRedemptionThreshold: formatGRT(this.voucherRedemptionThreshold), - belowThresholdCount: vouchers.belowThreshold.length, - totalValueGRT, - allocations: vouchers.belowThreshold.map((voucher) => voucher.allocation), - }) - } - - // If there are no eligible vouchers then bail - if (vouchers.eligible.length === 0) return - - // Already ordered by value - const voucherBatch = vouchers.eligible.slice(0, this.voucherRedemptionMaxBatchSize), - batchValueGRT = voucherBatch.reduce( - (total, voucher) => total + BigInt(voucher.amount), - 0n, - ) - - if (batchValueGRT > this.voucherRedemptionBatchThreshold) { - this.metrics.vouchersBatchRedeemSize.set(voucherBatch.length) - logger.info(`Query voucher batch is ready for redemption`, { - batchSize: voucherBatch.length, - voucherRedemptionMaxBatchSize: this.voucherRedemptionMaxBatchSize, - voucherRedemptionBatchThreshold: formatGRT( - this.voucherRedemptionBatchThreshold, - ), - batchValueGRT: formatGRT(batchValueGRT), - }) - await this.submitVouchers(voucherBatch) - } else { - logger.info(`Query voucher batch value too low for redemption`, { - batchSize: voucherBatch.length, - voucherRedemptionMaxBatchSize: this.voucherRedemptionMaxBatchSize, - voucherRedemptionBatchThreshold: formatGRT( - this.voucherRedemptionBatchThreshold, - ), - batchValueGRT: formatGRT(batchValueGRT), - }) - } - }) - } - - private async pendingVouchers(): Promise { - return this.models.vouchers.findAll({ - where: { protocolNetwork: this.protocolNetwork }, - order: [['amount', 'DESC']], // sorted by highest value to maximise the value of the batch - limit: this.voucherRedemptionMaxBatchSize, // limit the number of vouchers to the max batch size - }) - } - - private encodeReceiptBatch(receipts: AllocationReceipt[]): BytesWriter { - // Encode the receipt batch to a buffer - // [allocationId, receipts[]] (in bytes) - const encodedReceipts = new BytesWriter(20 + receipts.length * 112) - encodedReceipts.writeHex(receipts[0].allocation) - for (const receipt of receipts) { - // [fee, id, signature] - const fee = '0x' + BigInt(receipt.fees).toString(16) - const feePadding = 33 - fee.length / 2 - encodedReceipts.writeZeroes(feePadding) - encodedReceipts.writeHex(fee) - encodedReceipts.writeHex(receipt.id) - encodedReceipts.writeHex(receipt.signature) - } - return encodedReceipts - } - - private async obtainReceiptsVoucher(receipts: AllocationReceipt[]): Promise { - const allocation = receipts[0].allocation - const logger = this.logger.child({ - allocation, - function: 'obtainReceiptsVoucher()', - }) - // Gross underestimated number of receipts the gateway take at once - const receiptsThreshold = 25_000 - let response - try { - logger.info(`Collect receipts for allocation`, { - receipts: receipts.length, - }) - const stopTimer = this.metrics.receiptsCollectDuration.startTimer({ allocation }) - - // All receipts can fit the gateway, make a single-shot collection - if (receipts.length <= receiptsThreshold) { - const encodedReceipts = this.encodeReceiptBatch(receipts) - - // Exchange the receipts for a voucher signed by the counterparty (aka the client) - response = await axios.post( - this.collectEndpoint.toString(), - encodedReceipts.unwrap().buffer, - { headers: { 'Content-Type': 'application/octet-stream' } }, - ) - } else { - logger.info( - `Too many receipts to collect in oneshot, collecting in batches of '${receiptsThreshold} receipts`, - { - receipts: receipts.length, - }, - ) - // Split receipts in batches and collect partial vouchers - const partialVouchers: Array = [] - for (let i = 0; i < receipts.length; i += receiptsThreshold) { - const partialReceipts = receipts.slice( - i, - Math.min(i + receiptsThreshold, receipts.length), - ) - const encodedReceipts = this.encodeReceiptBatch(partialReceipts) - - // Exchange the receipts for a partial voucher signed by the counterparty (aka the client) - response = await axios.post( - this.partialVoucherEndpoint.toString(), - encodedReceipts.unwrap().buffer, - { headers: { 'Content-Type': 'application/octet-stream' } }, - ) - const partialVoucher = response.data as PartialVoucher - partialVouchers.push(partialVoucher) - } - - this.metrics.partialVouchersToExchange.set({ allocation }, partialVouchers.length) - logger.debug(`Partial vouchers to exchange`, { - partialVouchers: partialVouchers.length, - }) - - const encodedPartialVouchers = encodePartialVouchers(partialVouchers) - - // Exchange the partial vouchers for a voucher - response = await axios.post( - this.voucherEndpoint.toString(), - encodedPartialVouchers, - { - headers: { 'Content-Type': 'application/json' }, - }, - ) - } - - logger.trace('Gateway response', { - response, - allocation, - }) - - // Depending of which Gateway endpoint was used, fee information can come in different fields - const fees = response.data.fees ?? response.data.amount - if (!fees || !response.data.allocation || !response.data.signature) { - throw new Error('Failed to parse response from Gateay') - } - - const voucher = { ...response.data, fees } as { - allocation: string - fees: string - signature: string - } - - this.metrics.vouchers.inc({ - allocation, - }) - this.metrics.voucherCollectedFees.set({ allocation }, parseFloat(voucher.fees)) - - // Replace the receipts with the voucher in one db transaction; - // should this fail, we'll try to collect these receipts again - // later - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await this.models.vouchers.sequelize!.transaction(async (transaction) => { - logger.debug(`Removing collected receipts from the database`, { - receipts: receipts.length, - }) - - // Remove all receipts in the batch from the database - await this.models.allocationReceipts.destroy({ - where: { - id: receipts.map((receipt) => receipt.id), - protocolNetwork: this.protocolNetwork, - }, - transaction, - }) - - logger.debug(`Add voucher received in exchange for receipts to the database`, { - voucher, - }) - - // Update the query fees tracked against the allocation - const [summary] = await ensureAllocationSummary( - this.models, - toAddress(voucher.allocation), - transaction, - this.protocolNetwork, - ) - summary.collectedFees = ( - BigInt(summary.collectedFees) + BigInt(voucher.fees) - ).toString() - await summary.save({ transaction }) - - // Add the voucher to the database - await this.models.vouchers.findOrCreate({ - where: { - allocation: toAddress(voucher.allocation), - protocolNetwork: this.protocolNetwork, - }, - defaults: { - allocation: toAddress(voucher.allocation), - amount: voucher.fees, - signature: voucher.signature, - protocolNetwork: this.protocolNetwork, - }, - transaction, - }) - }) - stopTimer() - } catch (err) { - logger.error( - `Failed to collect receipts in exchange for an on-chain query fee voucher`, - { err: indexerError(IndexerErrorCode.IE054, err) }, - ) - } - } - - private async submitVouchers(vouchers: Voucher[]): Promise { - const logger = this.logger.child({ - function: 'submitVouchers()', - voucherBatchSize: vouchers.length, - }) - - logger.info(`Redeem query voucher batch on chain`, { - vouchers, - }) - const stopTimer = this.metrics.vouchersRedeemDuration.startTimer({ - allocation: vouchers[0].allocation, - }) - - const hexPrefix = (bytes: string): string => - bytes.startsWith('0x') ? bytes : `0x${bytes}` - - const onchainVouchers = vouchers.map((voucher) => { - return { - allocationID: hexPrefix(voucher.allocation), - amount: voucher.amount, - signature: hexPrefix(voucher.signature), - } - }) - - try { - // Submit the voucher on chain - const txReceipt = await this.transactionManager.executeTransaction( - () => this.allocationExchange.redeemMany.estimateGas(onchainVouchers), - async (gasLimit: BigNumberish) => - this.allocationExchange.redeemMany(onchainVouchers, { - gasLimit, - }), - logger.child({ action: 'redeemMany' }), - ) - - if (txReceipt === 'paused' || txReceipt === 'unauthorized') { - this.metrics.invalidVoucherRedeems.inc({ allocation: vouchers[0].allocation }) - return - } - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await this.models.allocationSummaries.sequelize!.transaction( - async (transaction) => { - for (const voucher of vouchers) { - const [summary] = await ensureAllocationSummary( - this.models, - toAddress(voucher.allocation), - transaction, - this.protocolNetwork, - ) - summary.withdrawnFees = ( - BigInt(summary.withdrawnFees) + BigInt(voucher.amount) - ).toString() - await summary.save({ transaction }) - } - }, - ) - } catch (err) { - this.metrics.failedVoucherRedeems.inc({ allocation: vouchers[0].allocation }) - logger.error(`Failed to redeem query fee voucher`, { - err: indexerError(IndexerErrorCode.IE055, err), - }) - return - } - stopTimer() - - // Remove the now obsolete voucher from the database - logger.info(`Successfully redeemed query fee voucher, delete local copy`) - try { - await this.models.vouchers.destroy({ - where: { - allocation: vouchers.map((voucher) => voucher.allocation), - protocolNetwork: this.protocolNetwork, - }, - }) - this.metrics.successVoucherRedeems.inc({ allocation: vouchers[0].allocation }) - logger.info(`Successfully deleted local voucher copy`) - } catch (err) { - logger.warn(`Failed to delete local voucher copy, will try again later`, { - err, - }) - } - } - - public async queuePendingReceiptsFromDatabase(): Promise { - // Obtain all closed allocations - const closedAllocations = await this.models.allocationSummaries.findAll({ - where: { closedAt: { [Op.not]: null }, protocolNetwork: this.protocolNetwork }, - }) - - // Create a receipts batch for each of these allocations - const batches = new Map( - closedAllocations.map((summary) => [ - summary.allocation, - { - timeout: summary.closedAt.valueOf() + RECEIPT_COLLECT_DELAY, - receipts: [], - }, - ]), - ) - - // Obtain all receipts for these allocations - const uncollectedReceipts = await this.models.allocationReceipts.findAll({ - where: { - allocation: closedAllocations.map((summary) => summary.allocation), - protocolNetwork: this.protocolNetwork, - }, - order: ['id'], - }) - - // Add receipts into the right batches - for (const receipt of uncollectedReceipts) { - const batch = batches.get(receipt.allocation) - - // We can safely assume that we only fetched receipts matching the - // allocations; just asserting this here to be _really_ sure - console.assert(batch !== undefined) - batch?.receipts.push(receipt) - } - - // Queue all batches of uncollected receipts - for (const batch of batches.values()) { - if (batch.receipts.length > 0) { - this.logger.info( - `Queue allocation receipts for collecting again after a restart`, - { - allocation: batch.receipts[0].allocation, - receipts: batch.receipts.length, - }, - ) - this.receiptsToCollect.push(batch) - } - } - } -} - -export function encodePartialVouchers( - partialVouchers: PartialVoucher[], -): AllocationPartialVouchers { - const uniqueAllocations = new Set(partialVouchers.map((voucher) => voucher.allocation)) - .size - if (uniqueAllocations !== 1) { - throw Error( - `Partial vouchers set must be for a single allocation, '${uniqueAllocations}' unique allocations represented`, - ) - } - - return { - allocation: partialVouchers[0].allocation, - partialVouchers, - } -} - -const registerReceiptMetrics = (metrics: Metrics, networkIdentifier: string) => ({ - receiptsToCollect: new metrics.client.Gauge({ - name: `indexer_agent_receipts_to_collect_${networkIdentifier}`, - help: 'Individual receipts to collect', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - failedReceipts: new metrics.client.Counter({ - name: `indexer_agent_receipts_failed_${networkIdentifier}`, - help: 'Failed to queue receipts to collect', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - partialVouchersToExchange: new metrics.client.Gauge({ - name: `indexer_agent_vouchers_to_exchange_${networkIdentifier}`, - help: 'Individual partial vouchers to exchange', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - receiptsCollectDuration: new metrics.client.Histogram({ - name: `indexer_agent_receipts_exchange_duration_${networkIdentifier}`, - help: 'Duration of processing and exchanging receipts to voucher', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - vouchers: new metrics.client.Counter({ - name: `indexer_agent_vouchers_${networkIdentifier}`, - help: 'Individual vouchers to redeem', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - successVoucherRedeems: new metrics.client.Counter({ - name: `indexer_agent_voucher_exchanges_ok_${networkIdentifier}`, - help: 'Successfully redeemed vouchers', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - invalidVoucherRedeems: new metrics.client.Counter({ - name: `indexer_agent_voucher_exchanges_invalid_${networkIdentifier}`, - help: 'Invalid vouchers redeems - tx paused or unauthorized', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - failedVoucherRedeems: new metrics.client.Counter({ - name: `indexer_agent_voucher_redeems_failed_${networkIdentifier}`, - help: 'Failed redeems for vouchers', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - vouchersRedeemDuration: new metrics.client.Histogram({ - name: `indexer_agent_vouchers_redeem_duration_${networkIdentifier}`, - help: 'Duration of redeeming vouchers', - registers: [metrics.registry], - labelNames: ['allocation'], - }), - - vouchersBatchRedeemSize: new metrics.client.Gauge({ - name: `indexer_agent_vouchers_redeem_${networkIdentifier}`, - help: 'Size of redeeming batched vouchers', - registers: [metrics.registry], - }), - - voucherCollectedFees: new metrics.client.Gauge({ - name: `indexer_agent_voucher_collected_fees_${networkIdentifier}`, - help: 'Amount of query fees collected for a voucher', - registers: [metrics.registry], - labelNames: ['allocation'], - }), -}) - -interface GatewayRoutes { - collectReceipts: URL - voucher: URL - partialVoucher: URL -} - -function processGatewayRoutes(input: string): GatewayRoutes { - const GATEWAY_ROUTES = { - collectReceipts: 'collect-receipts', - voucher: 'voucher', - partialVoucher: 'partial-voucher', - } - - // Strip existing information except for protocol and host - const inputURL = new URL(input) - const base = `${inputURL.protocol}//${inputURL.host}` - - function route(pathname: string): URL { - const url = new URL(base) - url.pathname = pathname - return url - } - - return { - collectReceipts: route(GATEWAY_ROUTES.collectReceipts), - voucher: route(GATEWAY_ROUTES.voucher), - partialVoucher: route(GATEWAY_ROUTES.partialVoucher), - } -} diff --git a/packages/indexer-common/src/allocations/types.ts b/packages/indexer-common/src/allocations/types.ts index a18ba241b..63afd6e0a 100644 --- a/packages/indexer-common/src/allocations/types.ts +++ b/packages/indexer-common/src/allocations/types.ts @@ -5,11 +5,14 @@ import { Logger, Address } from '@graphprotocol/common-ts' export interface Allocation { id: Address status: AllocationStatus + isLegacy: boolean subgraphDeployment: SubgraphDeployment indexer: Address allocatedTokens: bigint + createdAt: number createdAtEpoch: number createdAtBlockHash: string + closedAt: number closedAtEpoch: number closedAtEpochStartBlockHash: string | undefined previousEpochStartBlockHash: string | undefined @@ -19,6 +22,17 @@ export interface Allocation { queryFeesCollected: bigint | undefined } +export interface Provision { + id: Address + dataService: Address + indexer: Address + tokensProvisioned: bigint + tokensAllocated: bigint + tokensThawing: bigint + maxVerifierCut: bigint + thawingPeriod: bigint +} + export enum AllocationStatus { NULL = 'Null', ACTIVE = 'Active', diff --git a/packages/indexer-common/src/errors.ts b/packages/indexer-common/src/errors.ts index 34dc610d9..5c69e714d 100644 --- a/packages/indexer-common/src/errors.ts +++ b/packages/indexer-common/src/errors.ts @@ -88,6 +88,12 @@ export enum IndexerErrorCode { IE075 = 'IE075', IE076 = 'IE076', IE077 = 'IE077', + IE078 = 'IE078', + IE079 = 'IE079', + IE080 = 'IE080', + IE081 = 'IE081', + IE082 = 'IE082', + IE083 = 'IE083', } export const INDEXER_ERROR_MESSAGES: Record = { @@ -169,6 +175,12 @@ export const INDEXER_ERROR_MESSAGES: Record = { IE075: 'Failed to connect to network contracts', IE076: 'Failed to resume subgraph deployment', IE077: 'Failed to allocate: subgraph not healthily syncing', + IE078: 'No provision found', + IE079: 'Failed to add stake to provision: Invalid stake amount provided', + IE080: 'Failed to add stake to provision: stake not added on chain', + IE081: 'Multiple provisions found', + IE082: 'Graph Horizon protocol not detected', + IE083: 'Failed to thaw stake from provision', } export type IndexerErrorCause = unknown diff --git a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts index acf018c87..e089afcc5 100644 --- a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts +++ b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts @@ -332,8 +332,11 @@ describe.skip('Monitor: local', () => { await expect(networkMonitor.currentEpochNumber()).resolves.toBeGreaterThan(1500) }) - test('Fetch maxAllocationEpoch', async () => { - await expect(networkMonitor.maxAllocationEpoch()).resolves.toBeGreaterThan(1) + test('Fetch maxAllocationDuration', async () => { + await expect(networkMonitor.maxAllocationDuration()).resolves.toMatchObject({ + legacy: expect.any(Number), + horizon: expect.any(Number), + }) }) test('Fetch network chain current epoch', async () => { @@ -348,6 +351,7 @@ describe.skip('Monitor: local', () => { networkMonitor.resolvePOI( mockAllocation, hexlify(new Uint8Array(32).fill(0)), + 0, true, ), ).resolves.toEqual( @@ -357,7 +361,7 @@ describe.skip('Monitor: local', () => { test('Fail to resolve POI', async () => { await expect( - networkMonitor.resolvePOI(mockAllocation, undefined, false), + networkMonitor.resolvePOI(mockAllocation, undefined, 0, false), ).rejects.toEqual(indexerError(IndexerErrorCode.IE018, `Could not resolve POI`)) }) }) diff --git a/packages/indexer-common/src/indexer-management/actions.ts b/packages/indexer-common/src/indexer-management/actions.ts index a0d89018d..8f43d3d05 100644 --- a/packages/indexer-common/src/indexer-management/actions.ts +++ b/packages/indexer-common/src/indexer-management/actions.ts @@ -92,11 +92,16 @@ export class ActionManager { ).filter((a) => approvedDeploymentIDs.includes(a.subgraphDeployment.id.ipfsHash)) let affectedAllocationExpiring = false if (affectedAllocations.length) { - const currentEpoch = await network.networkMonitor.currentEpochNumber() - const maxAllocationEpoch = await network.networkMonitor.maxAllocationEpoch() + const maxAllocationDuration = await network.networkMonitor.maxAllocationDuration() + // affectedAllocations are ordered by creation time so use index 0 for oldest allocation to check expiration + const currentEpoch = await network.networkMonitor.currentEpochNumber() affectedAllocationExpiring = - currentEpoch >= affectedAllocations[0].createdAtEpoch + maxAllocationEpoch + currentEpoch >= + affectedAllocations[0].createdAtEpoch + + (affectedAllocations[0].isLegacy + ? maxAllocationDuration.legacy + : maxAllocationDuration.horizon) } logger.debug( diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index cc52ac002..4dd0b8953 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -10,7 +10,7 @@ import { ActionFailure, ActionType, Allocation, - allocationIdProof, + legacyAllocationIdProof, AllocationResult, AllocationStatus, CloseAllocationResult, @@ -437,7 +437,7 @@ export class AllocationManager { indexerAddress: this.network.specification.indexerOptions.address, }) - const proof = await allocationIdProof( + const proof = await legacyAllocationIdProof( allocationSigner, this.network.specification.indexerOptions.address, allocationId, @@ -496,12 +496,6 @@ export class AllocationManager { epoch: createAllocationEventLogs.epoch.toString(), }) - // TODO: deprecated - // Remember allocation - await this.network.receiptCollector?.rememberAllocations(actionID, [ - createAllocationEventLogs.allocationID, - ]) - const subgraphDeploymentID = new SubgraphDeploymentID(deployment) // If there is not yet an indexingRule that deems this deployment worth allocating to, make one if (!(await this.matchingRuleExists(logger, subgraphDeploymentID))) { @@ -568,7 +562,12 @@ export class AllocationManager { }) const allocation = await this.network.networkMonitor.allocation(allocationID) - poi = await this.network.networkMonitor.resolvePOI(allocation, poi, force) + ;[poi] = await this.network.networkMonitor.resolvePOI( + allocation, + poi, + undefined, + force, + ) // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. @@ -654,16 +653,7 @@ export class AllocationManager { logger.info('Identifying receipts worth collecting', { allocation: closeAllocationEventLogs.allocationID, }) - let isCollectingQueryFees = false const allocation = await this.network.networkMonitor.allocation(allocationID) - if (this.network.receiptCollector) { - // TODO: deprecated - // Collect query fees for this allocation - isCollectingQueryFees = await this.network.receiptCollector.collectReceipts( - actionID, - allocation, - ) - } // Upsert a rule so the agent keeps the deployment synced but doesn't allocate to it logger.debug( @@ -685,7 +675,6 @@ export class AllocationManager { allocation: closeAllocationEventLogs.allocationID, allocatedTokens: formatGRT(closeAllocationEventLogs.tokens), indexingRewards: formatGRT(rewardsAssigned), - receiptsWorthCollecting: isCollectingQueryFees, protocolNetwork: this.network.specification.networkIdentifier, } } @@ -754,9 +743,10 @@ export class AllocationManager { allocation: allocationID, deployment: allocation.subgraphDeployment.id.ipfsHash, }) - const allocationPOI = await this.network.networkMonitor.resolvePOI( + const [allocationPOI] = await this.network.networkMonitor.resolvePOI( allocation, poi, + undefined, force, ) logger.debug('POI resolved', { @@ -826,7 +816,7 @@ export class AllocationManager { newAllocationID: newAllocationId, indexerAddress: this.network.specification.indexerOptions.address, }) - const proof = await allocationIdProof( + const proof = await legacyAllocationIdProof( allocationSigner, this.network.specification.indexerOptions.address, newAllocationId, @@ -943,26 +933,7 @@ export class AllocationManager { logger.info('Identifying receipts worth collecting', { allocation: closeAllocationEventLogs.allocationID, }) - let allocation - let isCollectingQueryFees = false - try { - allocation = await this.network.networkMonitor.allocation(allocationID) - // Collect query fees for this allocation - - // TODO: deprecated - if (this.network.receiptCollector) { - isCollectingQueryFees = await this.network.receiptCollector.collectReceipts( - actionID, - allocation, - ) - logger.debug('Finished receipt collection') - } - } catch (err) { - logger.error('Failed to collect receipts', { - err, - }) - throw err - } + const allocation = await this.network.networkMonitor.allocation(allocationID) // If there is not yet an indexingRule that deems this deployment worth allocating to, make one if (!(await this.matchingRuleExists(logger, subgraphDeploymentID))) { @@ -986,7 +957,6 @@ export class AllocationManager { transactionID: receipt.hash, closedAllocation: closeAllocationEventLogs.allocationID, indexingRewardsCollected: formatGRT(rewardsAssigned), - receiptsWorthCollecting: isCollectingQueryFees, createdAllocation: createAllocationEventLogs.allocationID, createdAllocationStake: formatGRT(createAllocationEventLogs.tokens), protocolNetwork: this.network.specification.networkIdentifier, @@ -1104,11 +1074,28 @@ export class AllocationManager { logger.debug(`Validating action batch`, { size: batch.length }) // Validate stake feasibility - // TODO HORIZON: this call will be deprecated after horizon - const indexerFreeStake = - await this.network.contracts.LegacyStaking.getIndexerCapacity( + let indexerFreeStake = 0n + if (await this.network.isHorizon.value()) { + const verifier = this.network.contracts.SubgraphService.target.toString() + const delegationRatio = + await this.network.contracts.SubgraphService.getDelegationRatio() + const tokensAvailable = + await this.network.contracts.HorizonStaking.getTokensAvailable( + this.network.specification.indexerOptions.address, + verifier, + delegationRatio, + ) + const lockedStake = + await this.network.contracts.SubgraphService.allocationProvisionTracker( + this.network.specification.indexerOptions.address, + ) + indexerFreeStake = + tokensAvailable > lockedStake ? tokensAvailable - lockedStake : 0n + } else { + indexerFreeStake = await this.network.contracts.LegacyStaking.getIndexerCapacity( this.network.specification.indexerOptions.address, ) + } const actionsBatchStakeUsageSummaries = await pMap(batch, async (action: Action) => this.stakeUsageSummary(action), ) diff --git a/packages/indexer-common/src/indexer-management/client.ts b/packages/indexer-common/src/indexer-management/client.ts index 822486e80..273c0eeb2 100644 --- a/packages/indexer-common/src/indexer-management/client.ts +++ b/packages/indexer-common/src/indexer-management/client.ts @@ -12,8 +12,14 @@ import costModelResolvers from './resolvers/cost-models' import indexingRuleResolvers from './resolvers/indexing-rules' import poiDisputeResolvers from './resolvers/poi-disputes' import statusResolvers from './resolvers/indexer-status' +import provisionResolvers from './resolvers/provisions' import { GraphNode } from '../graph-node' -import { ActionManager, MultiNetworks, Network } from '@graphprotocol/indexer-common' +import { + ActionManager, + MultiNetworks, + Network, + RulesManager, +} from '@graphprotocol/indexer-common' export interface IndexerManagementResolverContext { models: IndexerManagementModels @@ -21,6 +27,7 @@ export interface IndexerManagementResolverContext { logger: Logger defaults: IndexerManagementDefaults actionManager: ActionManager | undefined + rulesManager: RulesManager | undefined multiNetworks: MultiNetworks | undefined } @@ -74,6 +81,7 @@ const SCHEMA_SDL = gql` stakedTokens: BigInt! status: AllocationStatus! protocolNetwork: String! + isLegacy: Boolean! } type CreateAllocationResult { @@ -87,14 +95,12 @@ const SCHEMA_SDL = gql` allocation: String! allocatedTokens: String! indexingRewards: String! - receiptsWorthCollecting: Boolean! protocolNetwork: String! } type ReallocateAllocationResult { closedAllocation: String! indexingRewardsCollected: String! - receiptsWorthCollecting: Boolean! createdAllocation: String! createdAllocationStake: String! protocolNetwork: String! @@ -298,6 +304,7 @@ const SCHEMA_SDL = gql` address: String registered: Boolean! location: GeoLocation + isLegacy: Boolean! } type IndexingError { @@ -343,10 +350,12 @@ const SCHEMA_SDL = gql` } type IndexerEndpoint { + name: String! url: String healthy: Boolean! protocolNetwork: String! tests: [IndexerEndpointTest!]! + isLegacy: Boolean! } type IndexerEndpoints { @@ -365,13 +374,65 @@ const SCHEMA_SDL = gql` model: String } + type Provision { + id: String! + dataService: String! + indexer: String! + tokensProvisioned: String! + tokensAllocated: String! + tokensThawing: String! + maxVerifierCut: String! + thawingPeriod: String! + protocolNetwork: String! + idleStake: String! + } + + type AddToProvisionResult { + id: String! + dataService: String! + indexer: String! + tokensProvisioned: String! + protocolNetwork: String! + } + + type ThawFromProvisionResult { + id: String! + dataService: String! + indexer: String! + tokensThawing: String! + thawingPeriod: String! + thawingUntil: String! + protocolNetwork: String! + } + + type ThawRequest { + id: String! + fulfilled: String! + dataService: String! + indexer: String! + shares: String! + thawingUntil: String! + protocolNetwork: String! + currentBlockTimestamp: String! + } + + type RemoveFromProvisionResult { + id: String! + dataService: String! + indexer: String! + tokensProvisioned: String! + tokensThawing: String! + tokensRemoved: String! + protocolNetwork: String! + } + type Query { indexingRule( identifier: IndexingRuleIdentifier! merged: Boolean! = false ): IndexingRule indexingRules(merged: Boolean! = false, protocolNetwork: String): [IndexingRule!]! - indexerRegistration(protocolNetwork: String!): IndexerRegistration! + indexerRegistration(protocolNetwork: String!): [IndexerRegistration]! indexerDeployments: [IndexerDeployment]! indexerAllocations(protocolNetwork: String!): [IndexerAllocation]! indexerEndpoints(protocolNetwork: String): [IndexerEndpoints!]! @@ -396,6 +457,9 @@ const SCHEMA_SDL = gql` orderDirection: OrderDirection first: Int ): [Action]! + + provisions(protocolNetwork: String!): [Provision!]! + thawRequests(protocolNetwork: String!): [ThawRequest!]! } type Mutation { @@ -418,12 +482,16 @@ const SCHEMA_SDL = gql` closeAllocation( allocation: String! poi: String + blockNumber: String + publicPOI: String force: Boolean protocolNetwork: String! ): CloseAllocationResult! reallocateAllocation( allocation: String! poi: String + blockNumber: String + publicPOI: String amount: String! force: Boolean protocolNetwork: String! @@ -437,6 +505,10 @@ const SCHEMA_SDL = gql` deleteActions(actionIDs: [String!]!): Int! approveActions(actionIDs: [String!]!): [Action]! executeApprovedActions: [ActionResult!]! + + addToProvision(protocolNetwork: String!, amount: String!): AddToProvisionResult! + thawFromProvision(protocolNetwork: String!, amount: String!): ThawFromProvisionResult! + removeFromProvision(protocolNetwork: String!): RemoveFromProvisionResult! } ` @@ -481,12 +553,17 @@ export const createIndexerManagementClient = async ( ...poiDisputeResolvers, ...allocationResolvers, ...actionResolvers, + ...provisionResolvers, } const actionManager = multiNetworks ? await ActionManager.create(multiNetworks, logger, models, graphNode) : undefined + const rulesManager = multiNetworks + ? await RulesManager.create(multiNetworks, logger, models) + : undefined + const context: IndexerManagementResolverContext = { models, graphNode, @@ -494,6 +571,7 @@ export const createIndexerManagementClient = async ( logger: logger.child({ component: 'IndexerManagementClient' }), multiNetworks, actionManager, + rulesManager, } const exchange = executeExchange({ diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index 4323bad12..420d10413 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -18,6 +18,11 @@ import { resolveChainAlias, TransferredSubgraphDeployment, sequentialTimerReduce, + HorizonTransitionValue, + Provision, + parseGraphQLProvision, + POIMetadata, + IndexingStatusCode, } from '@graphprotocol/indexer-common' import { GraphHorizonContracts, @@ -32,7 +37,7 @@ import { toAddress, formatGRT, } from '@graphprotocol/common-ts' -import { HDNodeWallet, hexlify, Provider } from 'ethers' +import { ethers, HDNodeWallet, hexlify, Provider } from 'ethers' import gql from 'graphql-tag' import pRetry, { Options } from 'p-retry' import { IndexerOptions } from '../network-specification' @@ -60,9 +65,69 @@ export class NetworkMonitor { return Number(await this.contracts.EpochManager.currentEpoch()) } - async maxAllocationEpoch(): Promise { - // TODO HORIZON: this call will fail in Horizon, return 0 or something else? - return Number(await this.contracts.LegacyStaking.maxAllocationEpochs()) + // Maximum allocation duration is different for legacy and horizon allocations + // - Legacy allocations - expiration measured in epochs, determined by maxAllocationEpochs + // - Horizon allocations - expiration measured in seconds, determined by maxPOIStaleness. + // To simplify the agent logic, this function converts horizon allocation values, returning epoch values + // regardless of the allocation type. + async maxAllocationDuration(): Promise { + const isHorizon = await this.isHorizon() + + if (isHorizon) { + // TODO: this assumes a block time of 12 seconds which is true for current protocol chain but not always + const BLOCK_IN_SECONDS = 12n + const epochLengthInBlocks = await this.contracts.EpochManager.epochLength() + const epochLengthInSeconds = Number(epochLengthInBlocks * BLOCK_IN_SECONDS) + + // When converting to epochs we give it a bit of leeway since missing the allocation expiration in horizon + // incurs in a severe penalty (missing out on indexing rewards) + const horizonDurationInSeconds = Number( + await this.contracts.SubgraphService.maxPOIStaleness(), + ) + const horizonDurationInEpochs = Math.max( + 1, + Math.floor(horizonDurationInSeconds / epochLengthInSeconds) - 1, + ) + + return { + legacy: 28, // Hardcode to the latest known value. This is required for legacy allos in the transition period. + horizon: horizonDurationInEpochs, + } + } else { + return { + legacy: Number(await this.contracts.LegacyStaking.maxAllocationEpochs()), + horizon: 0, + } + } + } + + /** + * Returns the amount of free stake for the indexer. + * + * The free stake is the amount of tokens that the indexer can use to stake in + * new allocations. It's calculated as the difference between the tokens + * available in the provision and the tokens already locked allocations. + * + * @returns The amount of free stake for the indexer. + */ + async freeStake(): Promise { + const isHorizon = await this.isHorizon() + + if (isHorizon) { + const address = this.indexerOptions.address + const dataService = this.contracts.SubgraphService.target.toString() + const delegationRatio = await this.contracts.SubgraphService.getDelegationRatio() + const tokensAvailable = await this.contracts.HorizonStaking.getTokensAvailable( + address, + dataService, + delegationRatio, + ) + const lockedStake = + await this.contracts.SubgraphService.allocationProvisionTracker(address) + return tokensAvailable > lockedStake ? tokensAvailable - lockedStake : 0n + } else { + return 0n + } } /** @@ -102,12 +167,15 @@ export class NetworkMonitor { allocation(id: $allocation) { id status + isLegacy indexer { id } allocatedTokens + createdAt createdAtEpoch createdAtBlockHash + closedAt closedAtEpoch subgraphDeployment { id @@ -156,11 +224,14 @@ export class NetworkMonitor { orderDirection: asc ) { id + isLegacy indexer { id } allocatedTokens + createdAt createdAtEpoch + closedAt closedAtEpoch createdAtBlockHash subgraphDeployment { @@ -218,6 +289,50 @@ export class NetworkMonitor { } } + async provision(indexer: string, dataService: string): Promise { + const result = await this.networkSubgraph.checkedQuery( + gql` + query provisions($indexer: String!, $dataService: String!) { + provisions(where: { indexer: $indexer, dataService: $dataService }) { + id + indexer { + id + } + dataService { + id + } + tokensProvisioned + tokensAllocated + tokensThawing + thawingPeriod + maxVerifierCut + } + } + `, + { indexer, dataService }, + ) + if (result.error) { + throw result.error + } + + if ( + !result.data.provisions || + result.data.length == 0 || + result.data.provisions.length == 0 + ) { + const errorMessage = `No provision found for indexer '${indexer}' and data service '${dataService}'` + this.logger.warn(errorMessage) + throw indexerError(IndexerErrorCode.IE078, errorMessage) + } + + if (result.data.provisions.length > 1) { + const errorMessage = `Multiple provisions found for indexer '${indexer}' and data service '${dataService}'` + this.logger.warn(errorMessage) + throw indexerError(IndexerErrorCode.IE081, errorMessage) + } + return parseGraphQLProvision(result.data.provisions[0]) + } + async epochs(epochNumbers: number[]): Promise { try { const result = await this.networkSubgraph.checkedQuery( @@ -284,11 +399,14 @@ export class NetworkMonitor { orderDirection: desc ) { id + isLegacy indexer { id } allocatedTokens + createdAt createdAtEpoch + closedAt closedAtEpoch createdAtBlockHash subgraphDeployment { @@ -359,12 +477,15 @@ export class NetworkMonitor { orderDirection: desc ) { id + isLegacy poi indexer { id } allocatedTokens + createdAt createdAtEpoch + closedAt closedAtEpoch createdAtBlockHash subgraphDeployment { @@ -917,80 +1038,58 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async resolvePOI( allocation: Allocation, poi: string | undefined, + blockNumber: number | undefined, force: boolean, - ): Promise { - // If the network is not supported, we can't resolve POI, as there will be no active epoch - const supportedNetworkAlias = await this.allocationNetworkAlias(allocation) - if (null === supportedNetworkAlias) { - this.logger.info("Network is not supported, can't resolve POI") - return hexlify(new Uint8Array(32).fill(0)) - } + ): Promise<[string, number]> { + return this._resolvePOI( + allocation, + poi, + blockNumber, + force, + allocation.indexer.toString(), + ) + } - // poi = undefined, force=true -- submit even if poi is 0x0 - // poi = defined, force=true -- no generatedPOI needed, just submit the POI supplied (with some sanitation?) - // poi = undefined, force=false -- submit with generated POI if one available - // poi = defined, force=false -- submit user defined POI only if generated POI matches - switch (force) { - case true: - switch (!!poi) { - case true: - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return poi! - case false: - return ( - (await this.graphNode.proofOfIndexing( - allocation.subgraphDeployment.id, - await this.fetchPOIBlockPointer(supportedNetworkAlias, allocation), - allocation.indexer, - )) || hexlify(new Uint8Array(32).fill(0)) - ) - } - break - case false: { - const epochStartBlock = await this.fetchPOIBlockPointer( - supportedNetworkAlias, - allocation, - ) - // Obtain the start block of the current epoch - const generatedPOI = await this.graphNode.proofOfIndexing( - allocation.subgraphDeployment.id, - epochStartBlock, - allocation.indexer, - ) - switch (poi == generatedPOI) { - case true: - if (poi == undefined) { - const deploymentStatus = await this.graphNode.indexingStatus([ - allocation.subgraphDeployment.id, - ]) - throw indexerError( - IndexerErrorCode.IE067, - `POI not available for deployment at current epoch start block. - currentEpochStartBlock: ${epochStartBlock.number} - deploymentStatus: ${ - deploymentStatus.length > 0 - ? JSON.stringify(deploymentStatus) - : 'not deployed' - }`, - ) - } else { - return poi - } - case false: - if (poi == undefined && generatedPOI !== undefined) { - return generatedPOI - } else if (poi !== undefined && generatedPOI == undefined) { - return poi - } - throw indexerError( - IndexerErrorCode.IE068, - `User provided POI does not match reference fetched from the graph-node. Use '--force' to bypass this POI accuracy check. - POI: ${poi}, - referencePOI: ${generatedPOI}`, - ) - } + async resolvePOIMetadata( + allocation: Allocation, + publicPOI: string | undefined, + blockNumber: number | undefined, + force: boolean, + ): Promise { + ;[publicPOI, blockNumber] = await this._resolvePOI( + allocation, + publicPOI, + blockNumber, + force, + ethers.ZeroAddress, + ) + const indexingStatus = await this.graphNode.indexingStatus([ + allocation.subgraphDeployment.id, + ]) + + let indexingStatusCode = IndexingStatusCode.Unknown + if (indexingStatus.length === 1) { + switch (indexingStatus[0].health) { + case 'healthy': + indexingStatusCode = IndexingStatusCode.Healthy + break + case 'unhealthy': + indexingStatusCode = IndexingStatusCode.Unhealthy + break + case 'failed': + indexingStatusCode = IndexingStatusCode.Failed + break + default: + indexingStatusCode = IndexingStatusCode.Unknown + break } } + + return { + publicPOI, + blockNumber, + indexingStatus: indexingStatusCode, + } } async monitorNetworkPauses( @@ -1047,7 +1146,6 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async monitorIsOperator( logger: Logger, - contracts: GraphHorizonContracts & SubgraphServiceContracts, indexerAddress: Address, wallet: HDNodeWallet, ): Promise> { @@ -1066,7 +1164,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async (isOperator) => { try { logger.debug('Check operator status') - return await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress) + return await this.isOperator(wallet.address, indexerAddress) } catch (err) { logger.warn( `Failed to check operator status for indexer, assuming it has not changed`, @@ -1075,7 +1173,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n return isOperator } }, - await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress), + await this.isOperator(wallet.address, indexerAddress), ).map((isOperator) => { logger.info( isOperator @@ -1088,16 +1186,8 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async monitorIsHorizon( logger: Logger, - contracts: GraphHorizonContracts & SubgraphServiceContracts, interval: number = 300_000, ): Promise> { - // Get initial value - - const initialValue = await contracts.HorizonStaking.getMaxThawingPeriod() - .then((maxThawingPeriod) => maxThawingPeriod > 0) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .catch((_) => false) - return sequentialTimerReduce( { logger, @@ -1106,8 +1196,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async (isHorizon) => { try { logger.debug('Check if network is Horizon ready') - const maxThawingPeriod = await contracts.HorizonStaking.getMaxThawingPeriod() - return maxThawingPeriod > 0 + return await this.isHorizon() } catch (err) { logger.warn( `Failed to check if network is Horizon ready, assuming it has not changed`, @@ -1116,7 +1205,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n return isHorizon } }, - initialValue, + await this.isHorizon(), ).map((isHorizon) => { logger.info(isHorizon ? `Network is Horizon ready` : `Network is not Horizon ready`) return isHorizon @@ -1146,12 +1235,15 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n first: 1000 ) { id + isLegacy indexer { id } queryFeesCollected allocatedTokens + createdAt createdAtEpoch + closedAt closedAtEpoch createdAtBlockHash closedAtBlockHash @@ -1266,6 +1358,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n orderDirection: asc ) { id + isLegacy createdAt indexer { id @@ -1274,6 +1367,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n allocatedTokens createdAtEpoch closedAtEpoch + closedAt closedAtBlockHash subgraphDeployment { id @@ -1362,4 +1456,119 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n throw err } } + + private async isHorizon() { + try { + const maxThawingPeriod = await this.contracts.HorizonStaking.getMaxThawingPeriod() + return maxThawingPeriod > 0 + } catch (err) { + return false + } + } + + private async isOperator(operatorAddress: string, indexerAddress: string) { + if (await this.isHorizon()) { + return await this.contracts.HorizonStaking.isAuthorized( + indexerAddress, + this.contracts.SubgraphService.target, + operatorAddress, + ) + } else { + return await this.contracts.LegacyStaking.isOperator( + operatorAddress, + indexerAddress, + ) + } + } + + private async _resolvePOI( + allocation: Allocation, + poi: string | undefined, + blockNumber: number | undefined, + force: boolean, + address: string, + ): Promise<[string, number]> { + // If the network is not supported, we can't resolve POI, as there will be no active epoch + const supportedNetworkAlias = await this.allocationNetworkAlias(allocation) + if (null === supportedNetworkAlias) { + this.logger.info("Network is not supported, can't resolve POI") + return [hexlify(new Uint8Array(32).fill(0)), 0] + } + + // poi = undefined, force=true -- submit even if poi is 0x0 + // poi = defined, force=true -- no generatedPOI needed, just submit the POI supplied (with some sanitation?) + // poi = undefined, force=false -- submit with generated POI if one available + // poi = defined, force=false -- submit user defined POI only if generated POI matches + switch (force) { + case true: + switch (!!poi) { + case true: + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return [poi!, blockNumber!] + case false: + // eslint-disable-next-line no-case-declarations + const poiBlockNumber = await this.fetchPOIBlockPointer( + supportedNetworkAlias, + allocation, + ) + return [ + (await this.graphNode.proofOfIndexing( + allocation.subgraphDeployment.id, + poiBlockNumber, + address, + )) || hexlify(new Uint8Array(32).fill(0)), + poiBlockNumber.number, + ] + } + break + case false: { + const epochStartBlock = await this.fetchPOIBlockPointer( + supportedNetworkAlias, + allocation, + ) + // Obtain the start block of the current epoch + const generatedPOI = await this.graphNode.proofOfIndexing( + allocation.subgraphDeployment.id, + epochStartBlock, + address, + ) + switch (poi == generatedPOI && blockNumber == epochStartBlock.number) { + case true: + if (poi == undefined || blockNumber == undefined) { + const deploymentStatus = await this.graphNode.indexingStatus([ + allocation.subgraphDeployment.id, + ]) + throw indexerError( + IndexerErrorCode.IE067, + `POI not available for deployment at current epoch start block. + currentEpochStartBlock: ${epochStartBlock.number} + deploymentStatus: ${ + deploymentStatus.length > 0 + ? JSON.stringify(deploymentStatus) + : 'not deployed' + }`, + ) + } else { + return [poi, blockNumber] + } + case false: + if (poi == undefined && generatedPOI !== undefined) { + return [generatedPOI, epochStartBlock.number] + } else if ( + poi !== undefined && + blockNumber !== undefined && + generatedPOI == undefined + ) { + return [poi, blockNumber] + } + throw indexerError( + IndexerErrorCode.IE068, + `User provided POI does not match reference fetched from the graph-node. Use '--force' to bypass this POI accuracy check. + POI: ${poi}, + referencePOI: ${generatedPOI}`, + ) + } + } + } + } } diff --git a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts index 93151e540..6f998860b 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts @@ -1,10 +1,9 @@ -import { epochElapsedBlocks, Network } from '@graphprotocol/indexer-common' /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/ban-types */ import pMap from 'p-map' import gql from 'graphql-tag' -import { hexlify } from 'ethers' +import { ethers, hexlify } from 'ethers' import { Address, @@ -15,21 +14,35 @@ import { toAddress, } from '@graphprotocol/common-ts' import { - allocationIdProof, + Allocation, AllocationStatus, CloseAllocationResult, CreateAllocationResult, + epochElapsedBlocks, + horizonAllocationIdProof, + HorizonTransitionValue, indexerError, IndexerErrorCode, IndexerManagementResolverContext, IndexingDecisionBasis, IndexingRuleAttributes, + legacyAllocationIdProof, + Network, + POIMetadata, ReallocateAllocationResult, SubgraphClient, SubgraphIdentifierType, uniqueAllocationID, } from '@graphprotocol/indexer-common' +import { + encodeCollectIndexingRewardsData, + encodePOIMetadata, + encodeStartServiceData, + encodeStopServiceData, + PaymentTypes, +} from '@graphprotocol/toolshed' import { extractNetwork } from './utils' +import { GraphNode } from '../../graph-node' interface AllocationFilter { status: 'active' | 'closed' @@ -62,6 +75,7 @@ interface AllocationInfo { queryFeesCollected: string status: string protocolNetwork: string + isLegacy: boolean } const ALLOCATION_QUERIES = { @@ -88,6 +102,7 @@ const ALLOCATION_QUERIES = { indexingRewards queryFeesCollected status + isLegacy } } `, @@ -114,6 +129,7 @@ const ALLOCATION_QUERIES = { indexingRewards queryFeesCollected status + isLegacy } } `, @@ -140,6 +156,7 @@ const ALLOCATION_QUERIES = { indexingRewards queryFeesCollected status + isLegacy } } `, @@ -166,6 +183,7 @@ const ALLOCATION_QUERIES = { indexingRewards queryFeesCollected status + isLegacy } } `, @@ -183,7 +201,7 @@ async function queryAllocations( currentEpoch: number currentEpochStartBlock: number currentEpochElapsedBlocks: number - maxAllocationEpochs: number + maxAllocationDuration: HorizonTransitionValue blocksPerEpoch: number avgBlockTime: number protocolNetwork: string @@ -263,7 +281,10 @@ async function queryAllocations( resultAllocations, // eslint-disable-next-line @typescript-eslint/no-explicit-any async (allocation: any): Promise => { - const deadlineEpoch = allocation.createdAtEpoch + context.maxAllocationEpochs + const maxAllocationDuration = allocation.isLegacy + ? context.maxAllocationDuration.legacy + : context.maxAllocationDuration.horizon + const deadlineEpoch = allocation.createdAtEpoch + maxAllocationDuration const remainingBlocks = // blocks remaining in current epoch context.blocksPerEpoch - @@ -283,18 +304,1043 @@ async function queryAllocations( ageInEpochs: allocation.closedAtEpoch ? allocation.closedAtEpoch - allocation.createdAtEpoch : context.currentEpoch - allocation.createdAtEpoch, - closeDeadlineEpoch: allocation.createdAtEpoch + context.maxAllocationEpochs, + closeDeadlineEpoch: allocation.createdAtEpoch + context.maxAllocationDuration, closeDeadlineBlocksRemaining: remainingBlocks, closeDeadlineTimeRemaining: remainingBlocks * context.avgBlockTime, indexingRewards: allocation.indexingRewards, queryFeesCollected: allocation.queryFeesCollected, status: allocation.status, protocolNetwork: context.protocolNetwork, + isLegacy: allocation.isLegacy, } }, ) } +async function createLegacyAllocation( + network: Network, + graphNode: GraphNode, + allocationAmount: bigint, + logger: Logger, + subgraphDeployment: SubgraphDeploymentID, + currentEpoch: bigint, + activeAllocations: Allocation[], + protocolNetwork: string, +): Promise<{ txHash: string; allocationId: Address }> { + const contracts = network.contracts + const transactionManager = network.transactionManager + const address = network.specification.indexerOptions.address + + // Identify how many GRT the indexer has staked + const freeStake = await contracts.LegacyStaking.getIndexerCapacity(address) + + // If there isn't enough left for allocating, abort + if (freeStake < allocationAmount) { + logger.error( + `Legacy allocation of ${formatGRT( + allocationAmount, + )} GRT cancelled: indexer only has a free stake amount of ${formatGRT( + freeStake, + )} GRT`, + ) + throw indexerError( + IndexerErrorCode.IE013, + `Legacy allocation of ${formatGRT( + allocationAmount, + )} GRT cancelled: indexer only has a free stake amount of ${formatGRT( + freeStake, + )} GRT`, + ) + } + + // Ensure subgraph is deployed before allocating + await graphNode.ensure( + `indexer-agent/${subgraphDeployment.ipfsHash.slice(-10)}`, + subgraphDeployment, + ) + + logger.debug('Obtain a unique legacy Allocation ID') + + // Obtain a unique allocation ID + const recentlyClosedAllocations = + await network.networkMonitor.recentlyClosedAllocations(Number(currentEpoch), 2) + const activeAndRecentlyClosedAllocations: Allocation[] = [ + ...recentlyClosedAllocations, + ...activeAllocations, + ] + const { allocationSigner, allocationId } = uniqueAllocationID( + transactionManager.wallet.mnemonic!.phrase, + Number(currentEpoch), + subgraphDeployment, + activeAndRecentlyClosedAllocations.map((allocation) => allocation.id), + ) + + // Double-check whether the allocationID already exists on chain, to + // avoid unnecessary transactions. + // Note: We're checking the allocation state here, which is defined as + // + // enum AllocationState { Null, Active, Closed, Finalized } + // + // in the contracts. + const state = await contracts.LegacyStaking.getAllocationState(allocationId) + if (state !== 0n) { + logger.debug(`Skipping legacy allocation as it already exists onchain`, { + indexer: address, + allocation: allocationId, + }) + throw indexerError( + IndexerErrorCode.IE066, + `Legacy allocation '${allocationId}' already exists onchain`, + ) + } + + logger.debug('Generating new legacy allocation ID proof', { + newAllocationSigner: allocationSigner, + newAllocationID: allocationId, + indexerAddress: address, + }) + + const proof = await legacyAllocationIdProof(allocationSigner, address, allocationId) + + logger.debug('Successfully generated legacy allocation ID proof', { + allocationIDProof: proof, + }) + + logger.debug(`Sending legacy allocateFrom transaction`, { + indexer: address, + subgraphDeployment: subgraphDeployment.ipfsHash, + amount: formatGRT(allocationAmount), + allocation: allocationId, + proof, + protocolNetwork, + }) + + const receipt = await transactionManager.executeTransaction( + async () => + contracts.LegacyStaking.allocateFrom.estimateGas( + address, + subgraphDeployment.bytes32, + allocationAmount, + allocationId, + hexlify(new Uint8Array(32).fill(0)), + proof, + ), + async (gasLimit) => + contracts.LegacyStaking.allocateFrom( + address, + subgraphDeployment.bytes32, + allocationAmount, + allocationId, + hexlify(new Uint8Array(32).fill(0)), + proof, + { gasLimit }, + ), + logger.child({ action: 'allocate' }), + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Legacy allocation not created. ${ + receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + }`, + ) + } + + const createAllocationEventLogs = network.transactionManager.findEvent( + 'AllocationCreated', + network.contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + subgraphDeployment.toString(), + receipt, + logger, + ) + + if (!createAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE014, + `Legacy allocation create transaction was never mined`, + ) + } + + logger.info(`Successfully legacy allocated to subgraph deployment`, { + amountGRT: formatGRT(createAllocationEventLogs.tokens), + allocation: createAllocationEventLogs.allocationID, + epoch: createAllocationEventLogs.epoch.toString(), + transaction: receipt.hash, + }) + + return { txHash: receipt.hash, allocationId: createAllocationEventLogs.allocationID } +} + +async function createHorizonAllocation( + network: Network, + graphNode: GraphNode, + allocationAmount: bigint, + logger: Logger, + subgraphDeployment: SubgraphDeploymentID, + currentEpoch: bigint, + activeAllocations: Allocation[], + protocolNetwork: string, +): Promise<{ txHash: string; allocationId: Address }> { + const contracts = network.contracts + const transactionManager = network.transactionManager + const address = network.specification.indexerOptions.address + const dataService = contracts.SubgraphService.target.toString() + + // Identify how many GRT the indexer has staked + const freeStake = await network.networkMonitor.freeStake() + + // If there isn't enough left for allocating, abort + if (freeStake < allocationAmount) { + logger.error( + `Allocation of ${formatGRT( + allocationAmount, + )} GRT cancelled: indexer only has a free stake amount of ${formatGRT( + freeStake, + )} GRT`, + ) + throw indexerError( + IndexerErrorCode.IE013, + `Allocation of ${formatGRT( + allocationAmount, + )} GRT cancelled: indexer only has a free stake amount of ${formatGRT( + freeStake, + )} GRT`, + ) + } + + // Ensure subgraph is deployed before allocating + await graphNode.ensure( + `indexer-agent/${subgraphDeployment.ipfsHash.slice(-10)}`, + subgraphDeployment, + ) + + logger.debug('Obtain a unique Allocation ID') + + // Obtain a unique allocation ID + const recentlyClosedAllocations = + await network.networkMonitor.recentlyClosedAllocations(Number(currentEpoch), 2) + const activeAndRecentlyClosedAllocations: Allocation[] = [ + ...recentlyClosedAllocations, + ...activeAllocations, + ] + const { allocationSigner, allocationId } = uniqueAllocationID( + transactionManager.wallet.mnemonic!.phrase, + Number(currentEpoch), + subgraphDeployment, + activeAndRecentlyClosedAllocations.map((allocation) => allocation.id), + ) + + // Double-check whether the allocationID already exists on chain, to + // avoid unnecessary transactions. + const allocation = await contracts.SubgraphService.getAllocation(allocationId) + if (allocation.createdAt !== 0n) { + logger.debug(`Skipping allocation as it already exists onchain`, { + indexer: address, + allocation: allocationId, + }) + throw indexerError( + IndexerErrorCode.IE066, + `Allocation '${allocationId}' already exists onchain`, + ) + } + + logger.debug('Generating new allocation ID proof', { + newAllocationSigner: allocationSigner, + newAllocationID: allocationId, + indexerAddress: address, + }) + + const chainId = Number(protocolNetwork.split(':')[1]) + const proof = await horizonAllocationIdProof( + allocationSigner, + chainId, + address, + allocationId, + dataService, + ) + + logger.debug('Successfully generated allocation ID proof', { + allocationIDProof: proof, + }) + + logger.debug(`Sending startService (allocate) transaction`, { + indexer: address, + subgraphDeployment: subgraphDeployment.ipfsHash, + amount: formatGRT(allocationAmount), + allocation: allocationId, + proof, + protocolNetwork, + }) + + const data = encodeStartServiceData( + subgraphDeployment.bytes32, + allocationAmount, + allocationId, + proof, + ) + const receipt = await transactionManager.executeTransaction( + async () => contracts.SubgraphService.startService.estimateGas(address, data), + async (gasLimit) => + contracts.SubgraphService.startService(address, data, { gasLimit }), + logger.child({ action: 'startService' }), + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Allocation not created. ${ + receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + }`, + ) + } + + const createAllocationEventLogs = network.transactionManager.findEvent( + 'ServiceStarted', + network.contracts.SubgraphService.interface, + 'data', + data, + receipt, + logger, + ) + + if (!createAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE014, + `Allocation create transaction was never mined`, + ) + } + + logger.info(`Successfully allocated to subgraph deployment`, { + amountGRT: formatGRT(allocationAmount), + allocation: allocationId, + epoch: currentEpoch.toString(), + transaction: receipt.hash, + }) + + return { txHash: receipt.hash, allocationId } +} + +async function closeLegacyAllocation( + allocation: Allocation, + poi: string, + network: Network, + logger: Logger, +): Promise<{ txHash: string; rewardsAssigned: bigint }> { + const contracts = network.contracts + const transactionManager = network.transactionManager + + // Double-check whether the allocation is still active on chain, to + // avoid unnecessary transactions. + // Note: We're checking the allocation state here, which is defined as + // + // enum AllocationState { Null, Active, Closed, Finalized } + // + // in the contracts. + const state = await contracts.LegacyStaking.getAllocationState(allocation.id) + if (state !== 1n) { + throw indexerError( + IndexerErrorCode.IE065, + 'Legacy allocation has already been closed', + ) + } + + logger.debug('Sending legacy closeAllocation transaction') + const receipt = await transactionManager.executeTransaction( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + () => contracts.LegacyStaking.closeAllocation.estimateGas(allocation.id, poi!), + (gasLimit) => + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + contracts.LegacyStaking.closeAllocation(allocation.id, poi!, { + gasLimit, + }), + logger, + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Legacy allocation '${allocation.id}' could not be closed: ${receipt}`, + ) + } + + const closeAllocationEventLogs = transactionManager.findEvent( + 'AllocationClosed', + contracts.LegacyStaking.interface, + 'allocationID', + allocation.id, + receipt, + logger, + ) + + if (!closeAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Legacy allocation close transaction was never successfully mined`, + ) + } + + const rewardsEventLogs = transactionManager.findEvent( + 'RewardsAssigned', + contracts.RewardsManager.interface, + 'allocationID', + allocation.id, + receipt, + logger, + ) + + const rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.amount : 0 + if (rewardsAssigned == 0) { + logger.warn('No rewards were distributed upon closing the legacy allocation') + } + + logger.info(`Successfully closed legacy allocation`, { + deployment: closeAllocationEventLogs.subgraphDeploymentID, + allocation: closeAllocationEventLogs.allocationID, + indexer: closeAllocationEventLogs.indexer, + amountGRT: formatGRT(closeAllocationEventLogs.tokens), + effectiveAllocation: closeAllocationEventLogs.effectiveAllocation.toString(), + poi: closeAllocationEventLogs.poi, + epoch: closeAllocationEventLogs.epoch.toString(), + transaction: receipt.hash, + indexingRewards: rewardsAssigned, + }) + + return { txHash: receipt.hash, rewardsAssigned } +} + +async function closeHorizonAllocation( + allocation: Allocation, + poi: string, + poiMetadata: POIMetadata, + network: Network, + logger: Logger, +): Promise<{ txHash: string; rewardsAssigned: bigint }> { + const contracts = network.contracts + const transactionManager = network.transactionManager + const address = network.specification.indexerOptions.address + const currentEpoch = await contracts.EpochManager.currentEpoch() + + // Double-check whether the allocation is still active on chain, to + // avoid unnecessary transactions. + const allocationState = await contracts.SubgraphService.getAllocation(allocation.id) + if (allocationState.closedAt !== 0n) { + throw indexerError(IndexerErrorCode.IE065, 'Allocation has already been closed') + } + + const encodedPOIMetadata = encodePOIMetadata( + poiMetadata.blockNumber, + poiMetadata.publicPOI, + poiMetadata.indexingStatus, + 0, + 0, + ) + const collectIndexingRewardsData = encodeCollectIndexingRewardsData( + allocation.id, + poi, + encodedPOIMetadata, + ) + + const collectCallData = contracts.SubgraphService.interface.encodeFunctionData( + 'collect', + [address, PaymentTypes.IndexingRewards, collectIndexingRewardsData], + ) + const closeAllocationData = encodeStopServiceData(allocation.id) + const stopServiceCallData = contracts.SubgraphService.interface.encodeFunctionData( + 'stopService', + [address, closeAllocationData], + ) + + const receipt = await transactionManager.executeTransaction( + async () => + contracts.SubgraphService.multicall.estimateGas([ + collectCallData, + stopServiceCallData, + ]), + async (gasLimit) => + contracts.SubgraphService.multicall([collectCallData, stopServiceCallData], { + gasLimit, + }), + logger, + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Allocation '${allocation.id}' could not be closed: ${receipt}`, + ) + } + + const collectIndexingRewardsEventLogs = transactionManager.findEvent( + 'ServicePaymentCollected', + contracts.SubgraphService.interface, + 'serviceProvider', + address, + receipt, + logger, + ) + + if (!collectIndexingRewardsEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Collecting indexing rewards for allocation '${allocation.id}' failed`, + ) + } + + const rewardsAssigned = collectIndexingRewardsEventLogs + ? collectIndexingRewardsEventLogs.tokens + : 0n + if (rewardsAssigned === 0n) { + logger.warn('No rewards were distributed upon closing the allocation') + } + + const closeAllocationEventLogs = transactionManager.findEvent( + 'ServiceStopped', + contracts.SubgraphService.interface, + 'data', + closeAllocationData, + receipt, + logger, + ) + + if (!closeAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Allocation close transaction was never successfully mined`, + ) + } + + const allocationStateAfter = await contracts.SubgraphService.getAllocation( + allocation.id, + ) + + logger.info(`Successfully closed allocation`, { + deployment: allocationStateAfter.subgraphDeploymentId, + allocation: allocation.id, + indexer: allocationStateAfter.indexer, + amountGRT: formatGRT(allocationStateAfter.tokens), + poi: poi, + epoch: currentEpoch.toString(), + transaction: receipt.hash, + indexingRewards: rewardsAssigned, + }) + + logger.info('Identifying receipts worth collecting', { + allocation: allocation.id, + }) + + return { txHash: receipt.hash, rewardsAssigned } +} + +async function reallocateLegacyAllocation( + allocation: Allocation, + allocationAmount: bigint, + activeAllocations: Allocation[], + poi: string, + network: Network, + logger: Logger, +): Promise<{ txHash: string; rewardsAssigned: bigint; newAllocationId: Address }> { + const contracts = network.contracts + const transactionManager = network.transactionManager + const address = network.specification.indexerOptions.address + const currentEpoch = await contracts.EpochManager.currentEpoch() + + // Double-check whether the allocation is still active on chain, to + // avoid unnecessary transactions. + // Note: We're checking the allocation state here, which is defined as + // + // enum AllocationState { Null, Active, Closed, Finalized } + // + // in the contracts. + const state = await contracts.LegacyStaking.getAllocationState(allocation.id) + if (state !== 1n) { + logger.warn(`Legacy allocation has already been closed`) + throw indexerError( + IndexerErrorCode.IE065, + `Legacy allocation has already been closed`, + ) + } + + if (allocationAmount < 0n) { + logger.warn('Cannot legacy reallocate a negative amount of GRT', { + amount: allocationAmount.toString(), + }) + throw indexerError( + IndexerErrorCode.IE061, + 'Cannot legacy reallocate a negative amount of GRT', + ) + } + + logger.info(`Legacy reallocate to subgraph deployment`, { + existingAllocationAmount: formatGRT(allocation.allocatedTokens), + newAllocationAmount: formatGRT(allocationAmount), + epoch: currentEpoch.toString(), + }) + + // Identify how many GRT the indexer has staked + const freeStake = await contracts.LegacyStaking.getIndexerCapacity(address) + + // When reallocating, we will first close the old allocation and free up the GRT in that allocation + // This GRT will be available in addition to freeStake for the new allocation + const postCloseFreeStake = freeStake + allocation.allocatedTokens + + // If there isn't enough left for allocating, abort + if (postCloseFreeStake < allocationAmount) { + throw indexerError( + IndexerErrorCode.IE013, + `Unable to legacy allocate ${formatGRT( + allocationAmount, + )} GRT: indexer only has a free stake amount of ${formatGRT( + freeStake, + )} GRT, plus ${formatGRT( + allocation.allocatedTokens, + )} GRT from the existing allocation`, + ) + } + + logger.debug('Generating a new unique legacy Allocation ID') + const recentlyClosedAllocations = + await network.networkMonitor.recentlyClosedAllocations(Number(currentEpoch), 2) + const activeAndRecentlyClosedAllocations: Allocation[] = [ + ...recentlyClosedAllocations, + ...activeAllocations, + ] + const { allocationSigner, allocationId: newAllocationId } = uniqueAllocationID( + transactionManager.wallet.mnemonic!.phrase, + Number(currentEpoch), + allocation.subgraphDeployment.id, + activeAndRecentlyClosedAllocations.map((allocation) => allocation.id), + ) + + logger.debug('New unique legacy Allocation ID generated', { + newAllocationID: newAllocationId, + newAllocationSigner: allocationSigner, + }) + + // Double-check whether the allocationID already exists on chain, to + // avoid unnecessary transactions. + // Note: We're checking the allocation state here, which is defined as + // + // enum AllocationState { Null, Active, Closed, Finalized } + // + // in the contracts. + const newAllocationState = + await contracts.LegacyStaking.getAllocationState(newAllocationId) + if (newAllocationState !== 0n) { + logger.warn(`Skipping legacy Allocation as it already exists onchain`, { + indexer: address, + allocation: newAllocationId, + newAllocationState, + }) + throw indexerError(IndexerErrorCode.IE066, 'AllocationID already exists') + } + + logger.debug('Generating new legacy allocation ID proof', { + newAllocationSigner: allocationSigner, + newAllocationID: newAllocationId, + indexerAddress: address, + }) + const proof = await legacyAllocationIdProof(allocationSigner, address, newAllocationId) + logger.debug('Successfully generated legacy allocation ID proof', { + allocationIDProof: proof, + }) + + logger.info(`Sending legacy close and legacy allocate multicall transaction`, { + indexer: address, + amount: formatGRT(allocationAmount), + oldAllocation: allocation.id, + newAllocation: newAllocationId, + newAllocationAmount: formatGRT(allocationAmount), + deployment: allocation.subgraphDeployment.id.toString(), + poi: poi, + proof, + epoch: currentEpoch.toString(), + }) + + const callData = [ + await contracts.LegacyStaking.closeAllocation.populateTransaction(allocation.id, poi), + await contracts.LegacyStaking.allocateFrom.populateTransaction( + address, + allocation.subgraphDeployment.id.bytes32, + allocationAmount, + newAllocationId, + hexlify(new Uint8Array(32).fill(0)), // metadata + proof, + ), + ].map((tx) => tx.data as string) + + const receipt = await transactionManager.executeTransaction( + async () => contracts.LegacyStaking.multicall.estimateGas(callData), + async (gasLimit) => contracts.LegacyStaking.multicall(callData, { gasLimit }), + logger.child({ + function: 'closeAndAllocate', + }), + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Legacy allocation '${newAllocationId}' could not be closed: ${receipt}`, + ) + } + + const createAllocationEventLogs = transactionManager.findEvent( + 'AllocationCreated', + contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + allocation.subgraphDeployment.id.toString(), + receipt, + logger, + ) + + if (!createAllocationEventLogs) { + throw indexerError(IndexerErrorCode.IE014, `Legacy allocation was never mined`) + } + + const closeAllocationEventLogs = transactionManager.findEvent( + 'AllocationClosed', + contracts.LegacyStaking.interface, + 'allocationID', + allocation.id, + receipt, + logger, + ) + + if (!closeAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Legacy allocation close transaction was never successfully mined`, + ) + } + + const rewardsEventLogs = transactionManager.findEvent( + 'RewardsAssigned', + contracts.RewardsManager.interface, + 'allocationID', + allocation.id, + receipt, + logger, + ) + + const rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.amount : 0 + if (rewardsAssigned == 0) { + logger.warn('No rewards were distributed upon closing the legacy allocation') + } + + logger.info(`Successfully reallocated legacy allocation`, { + deployment: createAllocationEventLogs.subgraphDeploymentID, + closedAllocation: closeAllocationEventLogs.allocationID, + closedAllocationStakeGRT: formatGRT(closeAllocationEventLogs.tokens), + closedAllocationPOI: closeAllocationEventLogs.poi, + closedAllocationEpoch: closeAllocationEventLogs.epoch.toString(), + indexingRewardsCollected: rewardsAssigned, + createdAllocation: createAllocationEventLogs.allocationID, + createdAllocationStakeGRT: formatGRT(createAllocationEventLogs.tokens), + indexer: createAllocationEventLogs.indexer, + epoch: createAllocationEventLogs.epoch.toString(), + transaction: receipt.hash, + }) + + logger.info('Identifying receipts worth collecting', { + allocation: closeAllocationEventLogs.allocationID, + }) + + return { txHash: receipt.hash, rewardsAssigned, newAllocationId } +} + +async function reallocateHorizonAllocation( + allocation: Allocation, + allocationAmount: bigint, + activeAllocations: Allocation[], + poi: string, + poiMetadata: POIMetadata, + network: Network, + logger: Logger, +): Promise<{ txHash: string; rewardsAssigned: bigint; newAllocationId: Address }> { + const contracts = network.contracts + const transactionManager = network.transactionManager + const address = network.specification.indexerOptions.address + const currentEpoch = await contracts.EpochManager.currentEpoch() + const dataService = contracts.SubgraphService.target.toString() + + // Double-check whether the allocation is still active on chain, to + // avoid unnecessary transactions. + const allocationData = await contracts.SubgraphService.getAllocation(allocation.id) + if (allocationData.closedAt !== 0n) { + logger.warn(`Allocation has already been closed`) + throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) + } + + if (allocationAmount < 0n) { + logger.warn('Cannot reallocate a negative amount of GRT', { + amount: allocationAmount.toString(), + }) + throw indexerError( + IndexerErrorCode.IE061, + 'Cannot reallocate a negative amount of GRT', + ) + } + + logger.info(`Reallocate to subgraph deployment`, { + existingAllocationAmount: formatGRT(allocation.allocatedTokens), + newAllocationAmount: formatGRT(allocationAmount), + epoch: currentEpoch.toString(), + }) + + // Identify how many GRT the indexer has staked + const freeStake = await network.networkMonitor.freeStake() + + // When reallocating, we will first close the old allocation and free up the GRT in that allocation + // This GRT will be available in addition to freeStake for the new allocation + const postCloseFreeStake = freeStake + allocationData.tokens + + // If there isn't enough left for allocating, abort + if (postCloseFreeStake < allocationAmount) { + throw indexerError( + IndexerErrorCode.IE013, + `Unable to allocate ${formatGRT( + allocationAmount, + )} GRT: indexer only has a free stake amount of ${formatGRT( + freeStake, + )} GRT, plus ${formatGRT( + allocation.allocatedTokens, + )} GRT from the existing allocation`, + ) + } + + logger.debug('Generating a new unique Allocation ID') + const recentlyClosedAllocations = + await network.networkMonitor.recentlyClosedAllocations(Number(currentEpoch), 2) + const activeAndRecentlyClosedAllocations: Allocation[] = [ + ...recentlyClosedAllocations, + ...activeAllocations, + ] + const { allocationSigner, allocationId: newAllocationId } = uniqueAllocationID( + transactionManager.wallet.mnemonic!.phrase, + Number(currentEpoch), + allocation.subgraphDeployment.id, + activeAndRecentlyClosedAllocations.map((allocation) => allocation.id), + ) + + logger.debug('New unique Allocation ID generated', { + newAllocationID: newAllocationId, + newAllocationSigner: allocationSigner, + }) + + // Double-check whether the allocationID already exists on chain, to + // avoid unnecessary transactions. + const newAllocationData = await contracts.SubgraphService.getAllocation(newAllocationId) + if (newAllocationData.createdAt !== 0n) { + logger.warn(`Skipping Allocation as it already exists onchain`, { + indexer: address, + allocation: newAllocationId, + newAllocationData, + }) + throw indexerError(IndexerErrorCode.IE066, 'AllocationID already exists') + } + + logger.debug('Generating new allocation ID proof', { + newAllocationSigner: allocationSigner, + newAllocationID: newAllocationId, + indexerAddress: address, + }) + const chainId = Number(network.specification.networkIdentifier.split(':')[1]) + const proof = await horizonAllocationIdProof( + allocationSigner, + chainId, + address, + newAllocationId, + dataService, + ) + logger.debug('Successfully generated allocation ID proof', { + allocationIDProof: proof, + }) + + logger.info(`Sending close and allocate multicall transaction`, { + indexer: address, + amount: formatGRT(allocationAmount), + oldAllocation: allocation.id, + newAllocation: newAllocationId, + newAllocationAmount: formatGRT(allocationAmount), + deployment: allocation.subgraphDeployment.id.toString(), + poi: poi, + proof, + epoch: currentEpoch.toString(), + }) + + const encodedPOIMetadata = encodePOIMetadata( + poiMetadata.blockNumber, + poiMetadata.publicPOI, + poiMetadata.indexingStatus, + 0, + 0, + ) + const collectIndexingRewardsData = encodeCollectIndexingRewardsData( + allocation.id, + poi, + encodedPOIMetadata, + ) + const closeAllocationData = ethers.AbiCoder.defaultAbiCoder().encode( + ['address'], + [allocation.id], + ) + const createAllocationData = encodeStartServiceData( + allocation.subgraphDeployment.id.bytes32, + allocationAmount, + newAllocationId, + proof, + ) + + const collectCallData = contracts.SubgraphService.interface.encodeFunctionData( + 'collect', + [address, PaymentTypes.IndexingRewards, collectIndexingRewardsData], + ) + const stopServiceCallData = contracts.SubgraphService.interface.encodeFunctionData( + 'stopService', + [address, closeAllocationData], + ) + const startServiceCallData = contracts.SubgraphService.interface.encodeFunctionData( + 'startService', + [address, createAllocationData], + ) + + const receipt = await transactionManager.executeTransaction( + async () => + contracts.SubgraphService.multicall.estimateGas([ + collectCallData, + stopServiceCallData, + startServiceCallData, + ]), + async (gasLimit) => + contracts.SubgraphService.multicall( + [collectCallData, stopServiceCallData, startServiceCallData], + { gasLimit }, + ), + logger.child({ + function: 'closeAndAllocate', + }), + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Allocation '${newAllocationId}' could not be closed: ${receipt}`, + ) + } + + logger.info('Finding create allocation event logs') + const createAllocationEventLogs = network.transactionManager.findEvent( + 'ServiceStarted', + network.contracts.SubgraphService.interface, + 'data', + createAllocationData, + receipt, + logger, + ) + + if (!createAllocationEventLogs) { + throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) + } + + logger.info('Finding collect indexing rewards event logs') + const collectIndexingRewardsEventLogs = transactionManager.findEvent( + 'ServicePaymentCollected', + contracts.SubgraphService.interface, + 'serviceProvider', + address, + receipt, + logger, + ) + + if (!collectIndexingRewardsEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Collecting indexing rewards for allocation '${allocation.id}' failed`, + ) + } + + const rewardsAssigned = collectIndexingRewardsEventLogs + ? collectIndexingRewardsEventLogs.tokens + : 0n + if (rewardsAssigned === 0n) { + logger.warn('No rewards were distributed upon closing the allocation') + } + + logger.info('Finding close allocation event logs') + const closeAllocationEventLogs = transactionManager.findEvent( + 'ServiceStopped', + contracts.SubgraphService.interface, + 'data', + closeAllocationData, + receipt, + logger, + ) + + if (!closeAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Allocation close transaction was never successfully mined`, + ) + } + + logger.info(`Successfully reallocated allocation`, { + deployment: createAllocationEventLogs.subgraphDeploymentID, + closedAllocation: allocation.id, + closedAllocationStakeGRT: formatGRT(allocation.allocatedTokens), + closedAllocationPOI: poi, + closedAllocationEpoch: currentEpoch.toString(), + indexingRewardsCollected: rewardsAssigned, + createdAllocation: newAllocationId, + createdAllocationStakeGRT: formatGRT(allocationAmount), + indexer: address, + epoch: currentEpoch.toString(), + transaction: receipt.hash, + }) + + return { txHash: receipt.hash, rewardsAssigned, newAllocationId } +} + +async function migrateLegacyAllocationToHorizon( + allocation: Allocation, + allocationAmount: bigint, + activeAllocations: Allocation[], + poi: string, + network: Network, + graphNode: GraphNode, + logger: Logger, +): Promise<{ txHash: string; rewardsAssigned: bigint; newAllocationId: Address }> { + const contracts = network.contracts + const currentEpoch = await contracts.EpochManager.currentEpoch() + + // We want to make sure that we close the legacy allocation even if reallocating to horizon would fail + // so we don't use a multicall but send separate transactions for closing + const closeAllocationResult = await closeLegacyAllocation( + allocation, + poi, + network, + logger, + ) + + // After closing the legacy allocation, we attempt to create a new horizon allocation + const createAllocationResult = await createHorizonAllocation( + network, + graphNode, + allocationAmount, + logger, + allocation.subgraphDeployment.id, + currentEpoch, + activeAllocations, + network.specification.networkIdentifier, + ) + + return { + txHash: createAllocationResult.txHash, + rewardsAssigned: closeAllocationResult.rewardsAssigned, + newAllocationId: createAllocationResult.allocationId, + } +} + export default { allocations: async ( { filter }: { filter: AllocationFilter }, @@ -328,9 +1374,9 @@ export default { }, } = network - const [currentEpoch, maxAllocationEpochs, epochLength] = await Promise.all([ + const [currentEpoch, maxAllocationDuration, epochLength] = await Promise.all([ networkMonitor.networkCurrentEpoch(), - contracts.LegacyStaking.maxAllocationEpochs(), + networkMonitor.maxAllocationDuration(), contracts.EpochManager.epochLength(), ]) @@ -351,7 +1397,7 @@ export default { currentEpochStartBlock: currentEpoch.startBlockNumber, currentEpochElapsedBlocks: epochElapsedBlocks(currentEpoch), latestBlock: currentEpoch.latestBlock, - maxAllocationEpochs: Number(maxAllocationEpochs), + maxAllocationDuration: maxAllocationDuration, blocksPerEpoch: Number(epochLength), avgBlockTime: 13000, protocolNetwork: network.specification.networkIdentifier, @@ -388,10 +1434,6 @@ export default { } const network = extractNetwork(protocolNetwork, multiNetworks) const networkMonitor = network.networkMonitor - const contracts = network.contracts - const transactionManager = network.transactionManager - const address = network.specification.indexerOptions.address - const allocationAmount = parseGRT(amount) const subgraphDeployment = new SubgraphDeploymentID(deployment) @@ -423,142 +1465,39 @@ export default { } try { - const currentEpoch = await contracts.EpochManager.currentEpoch() - - // Identify how many GRT the indexer has staked - const freeStake = await contracts.LegacyStaking.getIndexerCapacity(address) - - // If there isn't enough left for allocating, abort - if (freeStake < allocationAmount) { - logger.error( - `Allocation of ${formatGRT( - allocationAmount, - )} GRT cancelled: indexer only has a free stake amount of ${formatGRT( - freeStake, - )} GRT`, - ) - throw indexerError( - IndexerErrorCode.IE013, - `Allocation of ${formatGRT( - allocationAmount, - )} GRT cancelled: indexer only has a free stake amount of ${formatGRT( - freeStake, - )} GRT`, - ) - } - - // Ensure subgraph is deployed before allocating - await graphNode.ensure( - `indexer-agent/${subgraphDeployment.ipfsHash.slice(-10)}`, - subgraphDeployment, - ) - - logger.debug('Obtain a unique Allocation ID') - - // Obtain a unique allocation ID - const { allocationSigner, allocationId } = uniqueAllocationID( - transactionManager.wallet.mnemonic!.phrase, - Number(currentEpoch), - subgraphDeployment, - activeAllocations.map((allocation) => allocation.id), - ) - - // Double-check whether the allocationID already exists on chain, to - // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized } - // - // in the contracts. - const state = await contracts.HorizonStaking.getAllocationState(allocationId) - if (state !== 0n) { - logger.debug(`Skipping allocation as it already exists onchain`, { - indexer: address, - allocation: allocationId, - state, - }) - throw indexerError( - IndexerErrorCode.IE066, - `Allocation '${allocationId}' already exists onchain`, - ) - } - - logger.debug('Generating new allocation ID proof', { - newAllocationSigner: allocationSigner, - newAllocationID: allocationId, - indexerAddress: address, - }) - - const proof = await allocationIdProof(allocationSigner, address, allocationId) - - logger.debug('Successfully generated allocation ID proof', { - allocationIDProof: proof, - }) - - logger.debug(`Sending allocateFrom transaction`, { - indexer: address, - subgraphDeployment: subgraphDeployment.ipfsHash, - amount: formatGRT(allocationAmount), - allocation: allocationId, - proof, - protocolNetwork, - }) - - const receipt = await transactionManager.executeTransaction( - async () => - contracts.LegacyStaking.allocateFrom.estimateGas( - address, - subgraphDeployment.bytes32, - allocationAmount, - allocationId, - hexlify(new Uint8Array(32).fill(0)), - proof, - ), - async (gasLimit) => - contracts.LegacyStaking.allocateFrom( - address, - subgraphDeployment.bytes32, - allocationAmount, - allocationId, - hexlify(new Uint8Array(32).fill(0)), - proof, - { gasLimit }, - ), - logger.child({ action: 'allocate' }), - ) - - if (receipt === 'paused' || receipt === 'unauthorized') { - throw indexerError( - IndexerErrorCode.IE062, - `Allocation not created. ${ - receipt === 'paused' ? 'Network paused' : 'Operator not authorized' - }`, + const currentEpoch = await network.contracts.EpochManager.currentEpoch() + + let txHash: string + let allocationId: Address + if (await network.isHorizon.value()) { + logger.info('Creating horizon allocation') + const result = await createHorizonAllocation( + network, + graphNode, + allocationAmount, + logger, + subgraphDeployment, + currentEpoch, + activeAllocations, + protocolNetwork, ) - } - - const createAllocationEventLogs = network.transactionManager.findEvent( - 'AllocationCreated', - network.contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - subgraphDeployment.toString(), - receipt, - logger, - ) - - if (!createAllocationEventLogs) { - throw indexerError( - IndexerErrorCode.IE014, - `Allocation create transaction was never mined`, + txHash = result.txHash + allocationId = result.allocationId + } else { + const result = await createLegacyAllocation( + network, + graphNode, + allocationAmount, + logger, + subgraphDeployment, + currentEpoch, + activeAllocations, + protocolNetwork, ) + txHash = result.txHash + allocationId = result.allocationId } - logger.info(`Successfully allocated to subgraph deployment`, { - amountGRT: formatGRT(createAllocationEventLogs.tokens), - allocation: createAllocationEventLogs.allocationID, - epoch: createAllocationEventLogs.epoch.toString(), - transaction: receipt.hash, - }) - logger.debug( `Updating indexing rules, so indexer-agent will now manage the active allocation`, ) @@ -584,9 +1523,9 @@ export default { return { actionID: 0, type: 'allocate', - transactionID: receipt.hash, + transactionID: txHash, deployment, - allocation: createAllocationEventLogs.allocationID, + allocation: allocationId, allocatedTokens: formatGRT(allocationAmount.toString()), protocolNetwork, } @@ -603,11 +1542,15 @@ export default { { allocation, poi, + blockNumber, + publicPOI, force, protocolNetwork, }: { allocation: string poi: string | undefined + blockNumber: number | string | undefined + publicPOI: string | undefined force: boolean protocolNetwork: string }, @@ -616,6 +1559,8 @@ export default { logger.debug('Execute closeAllocation() mutation', { allocationID: allocation, poi: poi || 'none provided', + blockNumber: blockNumber || 'none provided', + publicPOI: publicPOI || 'none provided', }) if (!multiNetworks) { throw Error( @@ -624,99 +1569,42 @@ export default { } const network = extractNetwork(protocolNetwork, multiNetworks) const networkMonitor = network.networkMonitor - const contracts = network.contracts - const transactionManager = network.transactionManager - const receiptCollector = network.receiptCollector - const allocationData = await networkMonitor.allocation(allocation) try { - poi = await networkMonitor.resolvePOI(allocationData, poi, force) - - // Double-check whether the allocation is still active on chain, to - // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized } - // - // in the contracts. - const state = await contracts.HorizonStaking.getAllocationState(allocationData.id) - if (state !== 1n) { - throw indexerError(IndexerErrorCode.IE065, 'Allocation has already been closed') - } - - logger.debug('Sending closeAllocation transaction') - const receipt = await transactionManager.executeTransaction( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - () => - contracts.LegacyStaking.closeAllocation.estimateGas(allocationData.id, poi!), - (gasLimit) => - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - contracts.LegacyStaking.closeAllocation(allocationData.id, poi!, { - gasLimit, - }), - logger, + ;[poi, blockNumber] = await networkMonitor.resolvePOI( + allocationData, + poi, + Number(blockNumber), + force, ) + logger.debug('POI resolved', { + poi: poi, + blockNumber: blockNumber, + }) - if (receipt === 'paused' || receipt === 'unauthorized') { - throw indexerError( - IndexerErrorCode.IE062, - `Allocation '${allocationData.id}' could not be closed: ${receipt}`, + let txHash: string + let rewardsAssigned: bigint + if (allocationData.isLegacy) { + const result = await closeLegacyAllocation(allocationData, poi, network, logger) + txHash = result.txHash + rewardsAssigned = result.rewardsAssigned + } else { + const poiMetadata = await networkMonitor.resolvePOIMetadata( + allocationData, + publicPOI, + blockNumber, + force, ) - } - - const closeAllocationEventLogs = transactionManager.findEvent( - 'AllocationClosed', - contracts.LegacyStaking.interface, - 'allocationID', - allocation, - receipt, - logger, - ) - - if (!closeAllocationEventLogs) { - throw indexerError( - IndexerErrorCode.IE015, - `Allocation close transaction was never successfully mined`, + const result = await closeHorizonAllocation( + allocationData, + poi, + poiMetadata, + network, + logger, ) - } - - const rewardsEventLogs = transactionManager.findEvent( - 'RewardsAssigned', - contracts.RewardsManager.interface, - 'allocationID', - allocation, - receipt, - logger, - ) - - const rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.amount : 0 - - if (rewardsAssigned == 0) { - logger.warn('No rewards were distributed upon closing the allocation') - } - - logger.info(`Successfully closed allocation`, { - deployment: closeAllocationEventLogs.subgraphDeploymentID, - allocation: closeAllocationEventLogs.allocationID, - indexer: closeAllocationEventLogs.indexer, - amountGRT: formatGRT(closeAllocationEventLogs.tokens), - effectiveAllocation: closeAllocationEventLogs.effectiveAllocation.toString(), - poi: closeAllocationEventLogs.poi, - epoch: closeAllocationEventLogs.epoch.toString(), - transaction: receipt.hash, - indexingRewards: rewardsAssigned, - }) - - logger.info('Identifying receipts worth collecting', { - allocation: closeAllocationEventLogs.allocationID, - }) - - // TODO: deprecated - // Collect query fees for this allocation - let isCollectingQueryFees = false - if (receiptCollector) { - isCollectingQueryFees = await receiptCollector.collectReceipts(0, allocationData) + txHash = result.txHash + rewardsAssigned = result.rewardsAssigned } logger.debug( @@ -743,11 +1631,10 @@ export default { return { actionID: 0, type: 'unallocate', - transactionID: receipt.hash, - allocation: closeAllocationEventLogs.allocationID, - allocatedTokens: formatGRT(closeAllocationEventLogs.tokens), + transactionID: txHash, + allocation: allocation, + allocatedTokens: formatGRT(allocationData.allocatedTokens), indexingRewards: formatGRT(rewardsAssigned), - receiptsWorthCollecting: isCollectingQueryFees, protocolNetwork: network.specification.networkIdentifier, } } catch (error) { @@ -760,17 +1647,21 @@ export default { { allocation, poi, + blockNumber, + publicPOI, amount, force, protocolNetwork, }: { allocation: string poi: string | undefined + blockNumber: number | string | undefined + publicPOI: string | undefined amount: string force: boolean protocolNetwork: string }, - { logger, models, multiNetworks }: IndexerManagementResolverContext, + { logger, models, multiNetworks, graphNode }: IndexerManagementResolverContext, ): Promise => { logger = logger.child({ component: 'reallocateAllocationResolver', @@ -792,10 +1683,6 @@ export default { // Obtain the Network object and its associated components and data const network = extractNetwork(protocolNetwork, multiNetworks) const networkMonitor = network.networkMonitor - const contracts = network.contracts - const transactionManager = network.transactionManager - const receiptCollector = network.receiptCollector - const address = network.specification.indexerOptions.address const allocationAmount = parseGRT(amount) @@ -814,215 +1701,67 @@ export default { } try { - const currentEpoch = await contracts.EpochManager.currentEpoch() - logger.debug('Resolving POI') - const allocationPOI = await networkMonitor.resolvePOI(allocationData, poi, force) + const [allocationPOI] = await networkMonitor.resolvePOI( + allocationData, + poi, + Number(blockNumber), + force, + ) logger.debug('POI resolved', { userProvidedPOI: poi, poi: allocationPOI, }) - // Double-check whether the allocation is still active on chain, to - // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized } - // - // in the contracts. - const state = await contracts.HorizonStaking.getAllocationState(allocationData.id) - if (state !== 1n) { - logger.warn(`Allocation has already been closed`) - throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) - } - - if (allocationAmount < 0n) { - logger.warn('Cannot reallocate a negative amount of GRT', { - amount: allocationAmount.toString(), - }) - throw indexerError( - IndexerErrorCode.IE061, - 'Cannot reallocate a negative amount of GRT', - ) - } - - logger.info(`Reallocate to subgraph deployment`, { - existingAllocationAmount: formatGRT(allocationData.allocatedTokens), - newAllocationAmount: formatGRT(allocationAmount), - epoch: currentEpoch.toString(), - }) - - // Identify how many GRT the indexer has staked - const freeStake = await contracts.LegacyStaking.getIndexerCapacity(address) - - // When reallocating, we will first close the old allocation and free up the GRT in that allocation - // This GRT will be available in addition to freeStake for the new allocation - const postCloseFreeStake = freeStake + allocationData.allocatedTokens - - // If there isn't enough left for allocating, abort - if (postCloseFreeStake < allocationAmount) { - throw indexerError( - IndexerErrorCode.IE013, - `Unable to allocate ${formatGRT( - allocationAmount, - )} GRT: indexer only has a free stake amount of ${formatGRT( - freeStake, - )} GRT, plus ${formatGRT( - allocationData.allocatedTokens, - )} GRT from the existing allocation`, - ) - } - - logger.debug('Generating a new unique Allocation ID') - const { allocationSigner, allocationId: newAllocationId } = uniqueAllocationID( - transactionManager.wallet.mnemonic!.phrase, - Number(currentEpoch), - allocationData.subgraphDeployment.id, - activeAllocations.map((allocation) => allocation.id), - ) + const isHorizon = await network.isHorizon.value() - logger.debug('New unique Allocation ID generated', { - newAllocationID: newAllocationId, - newAllocationSigner: allocationSigner, - }) - - // Double-check whether the allocationID already exists on chain, to - // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized } - // - // in the contracts. - const newAllocationState = - await contracts.HorizonStaking.getAllocationState(newAllocationId) - if (newAllocationState !== 0n) { - logger.warn(`Skipping Allocation as it already exists onchain`, { - indexer: address, - allocation: newAllocationId, - newAllocationState, - }) - throw indexerError(IndexerErrorCode.IE066, 'AllocationID already exists') - } - - logger.debug('Generating new allocation ID proof', { - newAllocationSigner: allocationSigner, - newAllocationID: newAllocationId, - indexerAddress: address, - }) - const proof = await allocationIdProof(allocationSigner, address, newAllocationId) - logger.debug('Successfully generated allocation ID proof', { - allocationIDProof: proof, - }) - - logger.info(`Sending close and allocate multicall transaction`, { - indexer: address, - amount: formatGRT(allocationAmount), - oldAllocation: allocationData.id, - newAllocation: newAllocationId, - newAllocationAmount: formatGRT(allocationAmount), - deployment: allocationData.subgraphDeployment.id.toString(), - poi: allocationPOI, - proof, - epoch: currentEpoch.toString(), - }) - - const callData = [ - await contracts.LegacyStaking.closeAllocation.populateTransaction( - allocationData.id, + let txHash: string + let rewardsAssigned: bigint + let newAllocationId: Address + if (!isHorizon) { + const result = await reallocateLegacyAllocation( + allocationData, + allocationAmount, + activeAllocations, allocationPOI, - ), - await contracts.LegacyStaking.allocateFrom.populateTransaction( - address, - allocationData.subgraphDeployment.id.bytes32, + network, + logger, + ) + txHash = result.txHash + rewardsAssigned = result.rewardsAssigned + newAllocationId = result.newAllocationId + } else if (allocationData.isLegacy) { + const result = await migrateLegacyAllocationToHorizon( + allocationData, allocationAmount, - newAllocationId, - hexlify(new Uint8Array(32).fill(0)), // metadata - proof, - ), - ].map((tx) => tx.data as string) - - const receipt = await transactionManager.executeTransaction( - async () => contracts.LegacyStaking.multicall.estimateGas(callData), - async (gasLimit) => contracts.LegacyStaking.multicall(callData, { gasLimit }), - logger.child({ - function: 'closeAndAllocate', - }), - ) - - if (receipt === 'paused' || receipt === 'unauthorized') { - throw indexerError( - IndexerErrorCode.IE062, - `Allocation '${newAllocationId}' could not be closed: ${receipt}`, + activeAllocations, + allocationPOI, + network, + graphNode, + logger, ) - } - - const createAllocationEventLogs = transactionManager.findEvent( - 'AllocationCreated', - contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - allocationData.subgraphDeployment.id.toString(), - receipt, - logger, - ) - - if (!createAllocationEventLogs) { - throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) - } - - const closeAllocationEventLogs = transactionManager.findEvent( - 'AllocationClosed', - contracts.LegacyStaking.interface, - 'allocationID', - allocation, - receipt, - logger, - ) - - if (!closeAllocationEventLogs) { - throw indexerError( - IndexerErrorCode.IE015, - `Allocation close transaction was never successfully mined`, + txHash = result.txHash + rewardsAssigned = result.rewardsAssigned + newAllocationId = result.newAllocationId + } else { + const poiMetadata = await networkMonitor.resolvePOIMetadata( + allocationData, + publicPOI, + Number(blockNumber), + force, ) - } - - const rewardsEventLogs = transactionManager.findEvent( - 'RewardsAssigned', - contracts.RewardsManager.interface, - 'allocationID', - allocation, - receipt, - logger, - ) - - const rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.amount : 0 - - if (rewardsAssigned == 0) { - logger.warn('No rewards were distributed upon closing the allocation') - } - - logger.info(`Successfully reallocated allocation`, { - deployment: createAllocationEventLogs.subgraphDeploymentID, - closedAllocation: closeAllocationEventLogs.allocationID, - closedAllocationStakeGRT: formatGRT(closeAllocationEventLogs.tokens), - closedAllocationPOI: closeAllocationEventLogs.poi, - closedAllocationEpoch: closeAllocationEventLogs.epoch.toString(), - indexingRewardsCollected: rewardsAssigned, - createdAllocation: createAllocationEventLogs.allocationID, - createdAllocationStakeGRT: formatGRT(createAllocationEventLogs.tokens), - indexer: createAllocationEventLogs.indexer, - epoch: createAllocationEventLogs.epoch.toString(), - transaction: receipt.hash, - }) - - logger.info('Identifying receipts worth collecting', { - allocation: closeAllocationEventLogs.allocationID, - }) - - // TODO: deprecated - let isCollectingQueryFees = false - if (receiptCollector) { - // Collect query fees for this allocation - isCollectingQueryFees = await receiptCollector.collectReceipts(0, allocationData) + const result = await reallocateHorizonAllocation( + allocationData, + allocationAmount, + activeAllocations, + allocationPOI, + poiMetadata, + network, + logger, + ) + txHash = result.txHash + rewardsAssigned = result.rewardsAssigned + newAllocationId = result.newAllocationId } logger.debug( @@ -1050,12 +1789,11 @@ export default { return { actionID: 0, type: 'reallocate', - transactionID: receipt.hash, - closedAllocation: closeAllocationEventLogs.allocationID, + transactionID: txHash, + closedAllocation: allocation, indexingRewardsCollected: formatGRT(rewardsAssigned), - receiptsWorthCollecting: isCollectingQueryFees, - createdAllocation: createAllocationEventLogs.allocationID, - createdAllocationStake: formatGRT(createAllocationEventLogs.tokens), + createdAllocation: newAllocationId, + createdAllocationStake: formatGRT(allocationAmount), protocolNetwork, } } catch (error) { @@ -1063,52 +1801,4 @@ export default { throw error } }, - - // TODO: deprecated - submitCollectReceiptsJob: async ( - { - allocation, - protocolNetwork, - }: { - allocation: string - protocolNetwork: string - }, - { logger, multiNetworks }: IndexerManagementResolverContext, - ): Promise => { - logger.debug('Execute collectAllocationReceipts() mutation', { - allocationID: allocation, - protocolNetwork, - }) - if (!multiNetworks) { - throw Error( - 'IndexerManagementClient must be in `network` mode to collect receipts for an allocation', - ) - } - const network = extractNetwork(protocolNetwork, multiNetworks) - const networkMonitor = network.networkMonitor - const receiptCollector = network.receiptCollector - - const allocationData = await networkMonitor.allocation(allocation) - - try { - logger.info('Identifying receipts worth collecting', { - allocation: allocation, - }) - - // Collect query fees for this allocation - let collecting = false - if (receiptCollector) { - collecting = await receiptCollector.collectReceipts(0, allocationData) - } - - logger.info(`Submitted allocation receipt collection job for execution`, { - allocationID: allocation, - protocolNetwork: network.specification.networkIdentifier, - }) - return collecting - } catch (error) { - logger.error(error.toString()) - throw error - } - }, } diff --git a/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts b/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts index 5a8ee8f14..5941f37b1 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts @@ -63,7 +63,7 @@ const URL_VALIDATION_TEST: Test = { export default { indexerRegistration: async ( { protocolNetwork: unvalidatedProtocolNetwork }: { protocolNetwork: string }, - { multiNetworks }: IndexerManagementResolverContext, + { multiNetworks, logger }: IndexerManagementResolverContext, ): Promise => { if (!multiNetworks) { throw Error( @@ -75,28 +75,58 @@ export default { const protocolNetwork = network.specification.networkIdentifier const address = network.specification.indexerOptions.address const contracts = network.contracts - const registered = await contracts.LegacyServiceRegistry.isRegistered(address) - if (registered) { - const service = await contracts.LegacyServiceRegistry.services(address) - return { - address, - protocolNetwork, - url: service.url, - location: geohash.decode(service.geohash), - registered, - __typename: 'IndexerRegistration', + const registrationInfo: RegistrationInfo[] = [] + + // Check if the indexer is registered in the legacy service registry + try { + const registered = await contracts.LegacyServiceRegistry.isRegistered(address) + if (registered) { + const service = await contracts.LegacyServiceRegistry.services(address) + registrationInfo.push({ + address, + protocolNetwork, + url: service.url, + location: geohash.decode(service.geohash), + registered, + isLegacy: true, + __typename: 'IndexerRegistration', + }) + } + } catch (e) { + logger?.debug( + `Could not get legacy service registration for indexer. It's likely that the legacy protocol is not reachable.`, + ) + } + + if (await network.isHorizon.value()) { + const service = await contracts.SubgraphService.indexers(address) + if (service.registeredAt !== 0n) { + registrationInfo.push({ + address, + protocolNetwork, + url: service.url, + location: geohash.decode(service.geoHash), + registered: true, + isLegacy: false, + __typename: 'IndexerRegistration', + }) } - } else { - return { + } + + if (registrationInfo.length === 0) { + registrationInfo.push({ address, url: null, - registered, + registered: false, + isLegacy: false, protocolNetwork, location: null, __typename: 'IndexerRegistration', - } + }) } + + return registrationInfo }, indexerDeployments: async ( @@ -218,8 +248,21 @@ export default { return } try { - const networkEndpoints = await endpointForNetwork(network) - endpoints.push(networkEndpoints) + // Always try to get legacy endpoints, but fail gracefully if they don't exist + try { + const networkEndpoints = await endpointForNetwork(network, false) + endpoints.push(networkEndpoints) + } catch (e) { + logger?.debug( + `Could not get legacy service endpoints for network. It's likely that the legacy protocol is not reachable.`, + ) + } + + // Only get horizon endpoints when horizon is enabled + if (await network.isHorizon.value()) { + const networkEndpoints = await endpointForNetwork(network, true) + endpoints.push(networkEndpoints) + } } catch (err) { // Ignore endpoints for this network logger?.warn(`Failed to detect service endpoints for network`, { @@ -232,12 +275,24 @@ export default { }, } +interface RegistrationInfo { + address: string + protocolNetwork: string + url: string | null + location: { latitude: number; longitude: number } | null + registered: boolean + __typename: 'IndexerRegistration' + isLegacy: boolean +} + interface Endpoint { + name: string | null url: string | null healthy: boolean protocolNetwork: string // eslint-disable-next-line @typescript-eslint/no-explicit-any tests: any[] + isLegacy: boolean } interface Endpoints { @@ -245,26 +300,45 @@ interface Endpoints { status: Endpoint } -function defaultEndpoint(protocolNetwork: string): Endpoint { +function defaultEndpoint( + protocolNetwork: string, + name: string, + isLegacy: boolean, +): Endpoint { return { + name, url: null as string | null, healthy: false, protocolNetwork, tests: [] as TestResult[], + isLegacy, } } -function defaultEndpoints(protocolNetwork: string): Endpoints { +function defaultEndpoints(protocolNetwork: string, isHorizon: boolean): Endpoints { return { - service: defaultEndpoint(protocolNetwork), - status: defaultEndpoint(protocolNetwork), + service: defaultEndpoint( + protocolNetwork, + isHorizon ? 'service' : 'legacy-service', + !isHorizon, + ), + status: defaultEndpoint( + protocolNetwork, + isHorizon ? 'status' : 'legacy-status', + !isHorizon, + ), } } -async function endpointForNetwork(network: Network): Promise { +async function endpointForNetwork( + network: Network, + isHorizon: boolean, +): Promise { const contracts = network.contracts const address = network.specification.indexerOptions.address - const endpoints = defaultEndpoints(network.specification.networkIdentifier) - const service = await contracts.LegacyServiceRegistry.services(address) + const endpoints = defaultEndpoints(network.specification.networkIdentifier, isHorizon) + const service = isHorizon + ? await contracts.SubgraphService.indexers(address) + : await contracts.LegacyServiceRegistry.services(address) if (service) { { const { url, tests, ok } = await testURL(service.url, [ diff --git a/packages/indexer-common/src/indexer-management/resolvers/indexing-rules.ts b/packages/indexer-common/src/indexer-management/resolvers/indexing-rules.ts index acaa5021c..2adcdfe8e 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/indexing-rules.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/indexing-rules.ts @@ -9,9 +9,10 @@ import { import { IndexerManagementDefaults, IndexerManagementResolverContext } from '../client' import { Transaction } from 'sequelize' import { fetchIndexingRules } from '../rules' -import { processIdentifier } from '../../' +import { ensureAllocationLifetime, processIdentifier } from '../../' import { validateNetworkIdentifier } from '../../parsers' import groupBy from 'lodash.groupby' +import { extractNetwork } from './utils' const resetGlobalRule = async ( ruleIdentifier: IndexingRuleIdentifier, @@ -77,7 +78,7 @@ export default { setIndexingRule: async ( { rule }: { rule: IndexingRuleCreationAttributes }, - { models }: IndexerManagementResolverContext, + { multiNetworks, models }: IndexerManagementResolverContext, ): Promise => { if (!rule.identifier) { throw Error('Cannot set indexingRule without identifier') @@ -93,6 +94,20 @@ export default { } } + if (!multiNetworks) { + throw Error( + 'IndexerManagementClient must be in `network` mode to set indexing rules', + ) + } + const network = extractNetwork(rule.protocolNetwork, multiNetworks) + + const [isValid, maxSuggestedLifetime] = await ensureAllocationLifetime(rule, network) + if (!isValid) { + throw Error( + `Allocation lifetime must be at most ${maxSuggestedLifetime} epochs, otherwise indexing rewards will be forefited.`, + ) + } + const [identifier] = await processIdentifier(rule.identifier, { all: false, global: true, diff --git a/packages/indexer-common/src/indexer-management/resolvers/provisions.ts b/packages/indexer-common/src/indexer-management/resolvers/provisions.ts new file mode 100644 index 000000000..cf45ef8f6 --- /dev/null +++ b/packages/indexer-common/src/indexer-management/resolvers/provisions.ts @@ -0,0 +1,642 @@ +import { indexerError, IndexerErrorCode, Network } from '@graphprotocol/indexer-common' +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/ban-types */ + +import gql from 'graphql-tag' + +import { IndexerManagementResolverContext } from '@graphprotocol/indexer-common' +import { extractNetwork } from './utils' +import { formatGRT, parseGRT } from '@graphprotocol/common-ts' +import { ThawRequestType } from '@graphprotocol/toolshed' + +enum ProvisionQuery { + all = 'all', + thawRequests = 'thawRequests', +} + +interface ProvisionInfo { + id: string + dataService: string + indexer: string + tokensProvisioned: string + tokensAllocated: string + tokensThawing: string + maxVerifierCut: string + thawingPeriod: string + protocolNetwork: string + idleStake: string +} + +interface AddToProvisionResult { + id: string + dataService: string + indexer: string + tokensProvisioned: string + protocolNetwork: string +} + +interface ThawFromProvisionResult { + id: string + dataService: string + indexer: string + tokensThawing: string + thawingPeriod: string + thawingUntil: string + protocolNetwork: string +} + +interface ThawRequestInfo { + id: string + fulfilled: string + dataService: string + indexer: string + shares: string + thawingUntil: string + currentBlockTimestamp: string +} + +interface RemoveFromProvisionResult { + id: string + dataService: string + indexer: string + tokensProvisioned: string + tokensThawing: string + tokensRemoved: string + protocolNetwork: string +} + +const PROVISION_QUERIES = { + // No need to paginate, there can only be one provision per (indexer, dataService) pair + [ProvisionQuery.all]: gql` + query provisions($indexer: String!, $dataService: String!) { + provisions( + where: { indexer: $indexer, dataService: $dataService } + orderBy: id + orderDirection: asc + first: 1000 + ) { + id + indexer { + id + } + dataService { + id + } + tokensProvisioned + tokensAllocated + tokensThawing + thawingPeriod + maxVerifierCut + } + } + `, + // No need to paginate, there can be at most 1000 thaw requests for any given (indexer, dataService) pair + [ProvisionQuery.thawRequests]: gql` + query thawRequests($indexer: String!, $dataService: String!) { + thawRequests( + where: { indexer: $indexer, dataService: $dataService, owner: $indexer } + orderBy: thawingUntil + orderDirection: asc + first: 1000 + ) { + id + fulfilled + shares + thawingUntil + } + } + `, +} + +export default { + provisions: async ( + { + protocolNetwork, + }: { + protocolNetwork: string + }, + { multiNetworks, logger }: IndexerManagementResolverContext, + ): Promise => { + logger.debug('Execute provisions() query', { + protocolNetwork, + }) + + if (!multiNetworks) { + throw Error('IndexerManagementClient must be in `network` mode to fetch provisions') + } + + const network = extractNetwork(protocolNetwork, multiNetworks) + + if (!(await network.isHorizon.value())) { + throw indexerError(IndexerErrorCode.IE082) + } + + const indexer = network.specification.indexerOptions.address.toLowerCase() + const dataService = network.contracts.SubgraphService.target.toString().toLowerCase() + const idleStake = await network.contracts.HorizonStaking.getIdleStake(indexer) + + const provisionsByNetwork = await multiNetworks.map( + async (network: Network): Promise => { + // Return early if a different protocol network is specifically requested + if ( + protocolNetwork && + protocolNetwork !== network.specification.networkIdentifier + ) { + return [] + } + + const { networkSubgraph } = network + + logger.trace('Query Provisions', { + indexer, + dataService, + }) + + const result = await networkSubgraph.checkedQuery(PROVISION_QUERIES.all, { + indexer, + dataService, + }) + + if (result.error) { + logger.error('Querying provisions failed', { + error: result.error, + }) + } + + return result.data.provisions.map((provision) => ({ + id: provision.id, + dataService, + indexer, + tokensProvisioned: provision.tokensProvisioned, + tokensAllocated: provision.tokensAllocated, + tokensThawing: provision.tokensThawing, + maxVerifierCut: provision.maxVerifierCut, + thawingPeriod: provision.thawingPeriod, + protocolNetwork: network.specification.networkIdentifier, + idleStake: idleStake.toString(), + })) + }, + ) + + return Object.values(provisionsByNetwork).flat() + }, + addToProvision: async ( + { + protocolNetwork, + amount, + }: { + protocolNetwork: string + amount: string + }, + { multiNetworks, logger }: IndexerManagementResolverContext, + ): Promise => { + logger.debug('Execute addToProvision() mutation', { + protocolNetwork, + amount, + }) + + if (!multiNetworks) { + throw Error( + 'IndexerManagementClient must be in `network` mode to add stake to a provision', + ) + } + + const network = extractNetwork(protocolNetwork, multiNetworks) + const networkMonitor = network.networkMonitor + const contracts = network.contracts + const transactionManager = network.transactionManager + + if (!(await network.isHorizon.value())) { + throw indexerError(IndexerErrorCode.IE082) + } + + const indexer = network.specification.indexerOptions.address.toLowerCase() + const dataService = contracts.SubgraphService.target.toString().toLowerCase() + const provisionAmount = parseGRT(amount) + + if (provisionAmount < 0n) { + logger.warn('Cannot add a negative amount of GRT', { + amount: formatGRT(provisionAmount), + }) + throw indexerError( + IndexerErrorCode.IE079, + `Invalid stake amount provided (${amount.toString()}). Must use positive stake amount`, + ) + } + + try { + // Check if the provision exists - this will throw if it doesn't + const provision = await networkMonitor.provision(indexer, dataService) + + logger.debug('Provision found', { + provision, + }) + + logger.debug(`Sending addToProvision transaction`, { + indexer: indexer, + dataService: dataService, + amount: formatGRT(provisionAmount), + protocolNetwork, + }) + + const receipt = await transactionManager.executeTransaction( + async () => + contracts.HorizonStaking.addToProvision.estimateGas( + indexer, + dataService, + provisionAmount, + ), + async (gasLimit) => + contracts.HorizonStaking.addToProvision(indexer, dataService, provisionAmount, { + gasLimit, + }), + logger.child({ action: 'addToProvision' }), + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Stake not added to provision. ${ + receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + }`, + ) + } + + const addToProvisionEventLogs = network.transactionManager.findEvent( + 'ProvisionIncreased', + network.contracts.HorizonStaking.interface, + 'tokens', + provisionAmount.toString(), + receipt, + logger, + ) + + if (!addToProvisionEventLogs) { + throw indexerError( + IndexerErrorCode.IE080, + `Add to provision transaction was never mined`, + ) + } + + logger.info(`Successfully added stake to provision`, { + amountGRT: formatGRT(addToProvisionEventLogs.tokens), + transaction: receipt.hash, + }) + + return { + id: provision.id, + dataService, + indexer, + tokensProvisioned: (provision.tokensProvisioned + provisionAmount).toString(), // TODO: we could re-fetch the provision instead + protocolNetwork: network.specification.networkIdentifier, + } + } catch (error) { + logger.error('Failed to add stake to provision', { + amount: formatGRT(provisionAmount), + error, + }) + throw error + } + }, + thawFromProvision: async ( + { + protocolNetwork, + amount, + }: { + protocolNetwork: string + amount: string + }, + { multiNetworks, logger }: IndexerManagementResolverContext, + ): Promise => { + logger.debug('Execute thawFromProvision() mutation', { + protocolNetwork, + amount, + }) + + if (!multiNetworks) { + throw Error( + 'IndexerManagementClient must be in `network` mode to add stake to a provision', + ) + } + + const network = extractNetwork(protocolNetwork, multiNetworks) + const networkMonitor = network.networkMonitor + const contracts = network.contracts + const transactionManager = network.transactionManager + + if (!(await network.isHorizon.value())) { + throw indexerError(IndexerErrorCode.IE082) + } + + const indexer = network.specification.indexerOptions.address.toLowerCase() + const dataService = contracts.SubgraphService.target.toString().toLowerCase() + const thawAmount = parseGRT(amount) + + if (thawAmount <= 0n) { + logger.warn('Cannot thaw zero or a negative amount of GRT', { + amount: formatGRT(thawAmount), + }) + throw indexerError( + IndexerErrorCode.IE083, + `Invalid stake amount provided (${amount.toString()}). Must use positive stake amount`, + ) + } + + try { + // Check if the provision exists - this will throw if it doesn't + const provision = await networkMonitor.provision(indexer, dataService) + + logger.debug('Provision found', { + provision, + }) + + const tokensAvailable = await contracts.HorizonStaking.getProviderTokensAvailable( + indexer, + dataService, + ) + + if (thawAmount > tokensAvailable) { + throw indexerError( + IndexerErrorCode.IE083, + `Cannot thaw more stake than is available in the provision: thaw amount (${formatGRT( + thawAmount, + )}) > tokens available (${formatGRT(tokensAvailable)})`, + ) + } + + logger.debug(`Sending thawFromProvision transaction`, { + indexer: indexer, + dataService: dataService, + amount: formatGRT(thawAmount), + protocolNetwork, + }) + + const receipt = await transactionManager.executeTransaction( + async () => + contracts.HorizonStaking.thaw.estimateGas(indexer, dataService, thawAmount), + async (gasLimit) => + contracts.HorizonStaking.thaw(indexer, dataService, thawAmount, { + gasLimit, + }), + logger.child({ action: 'thawFromProvision' }), + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Stake not thawed from provision. ${ + receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + }`, + ) + } + + const thawFromProvisionEventLogs = network.transactionManager.findEvent( + 'ProvisionThawed', + network.contracts.HorizonStaking.interface, + 'tokens', + thawAmount.toString(), + receipt, + logger, + ) + + if (!thawFromProvisionEventLogs) { + throw indexerError( + IndexerErrorCode.IE083, + `Thaw from provision transaction was never mined`, + ) + } + + const thawRequestCreatedTopic = + network.contracts.HorizonStaking.interface.getEvent( + 'ThawRequestCreated', + ).topicHash + const thawRequestCreatedLog = receipt.logs.filter((log) => + log.topics.includes(thawRequestCreatedTopic), + )[0] + const thawRequestCreatedEvent = + network.contracts.HorizonStaking.interface.decodeEventLog( + network.contracts.HorizonStaking.interface.getEvent('ThawRequestCreated'), + thawRequestCreatedLog.data, + thawRequestCreatedLog.topics, + ) + + logger.info(`Successfully thawed stake from provision`, { + amountGRT: formatGRT(thawFromProvisionEventLogs.tokens), + thawingUntil: thawRequestCreatedEvent.thawingUntil, + transaction: receipt.hash, + }) + + return { + id: provision.id, + dataService, + indexer, + tokensThawing: (provision.tokensThawing + thawAmount).toString(), // TODO: we could re-fetch the provision instead + thawingPeriod: provision.thawingPeriod.toString(), + thawingUntil: thawRequestCreatedEvent.thawingUntil.toString(), + protocolNetwork: network.specification.networkIdentifier, + } + } catch (error) { + logger.error('Failed to thaw stake from provision', { + amount: formatGRT(thawAmount), + error, + }) + throw error + } + }, + thawRequests: async ( + { + protocolNetwork, + }: { + protocolNetwork: string + }, + { multiNetworks, logger }: IndexerManagementResolverContext, + ): Promise => { + logger.debug('Execute thawRequests() query', { + protocolNetwork, + }) + + if (!multiNetworks) { + throw Error('IndexerManagementClient must be in `network` mode to fetch provisions') + } + + const network = extractNetwork(protocolNetwork, multiNetworks) + + if (!(await network.isHorizon.value())) { + throw indexerError(IndexerErrorCode.IE082) + } + + const indexer = network.specification.indexerOptions.address.toLowerCase() + const dataService = network.contracts.SubgraphService.target.toString().toLowerCase() + + const thawRequestsByNetwork = await multiNetworks.map( + async (network: Network): Promise => { + // Return early if a different protocol network is specifically requested + if ( + protocolNetwork && + protocolNetwork !== network.specification.networkIdentifier + ) { + return [] + } + + const { networkSubgraph } = network + + logger.trace('Query Thaw Requests', { + indexer, + dataService, + }) + + const result = await networkSubgraph.checkedQuery( + PROVISION_QUERIES.thawRequests, + { + indexer, + dataService, + }, + ) + + if (result.error) { + logger.error('Querying thaw requests failed', { + error: result.error, + }) + } + + const currentBlockTimestamp = + (await network.networkProvider.getBlock('latest'))?.timestamp ?? 0 + + return result.data.thawRequests.map((thawRequest) => ({ + id: thawRequest.id, + fulfilled: thawRequest.fulfilled, + dataService, + indexer, + shares: thawRequest.shares, + thawingUntil: thawRequest.thawingUntil, + currentBlockTimestamp: currentBlockTimestamp.toString(), + protocolNetwork: network.specification.networkIdentifier, + })) + }, + ) + + return Object.values(thawRequestsByNetwork).flat() + }, + removeFromProvision: async ( + { + protocolNetwork, + }: { + protocolNetwork: string + }, + { multiNetworks, logger }: IndexerManagementResolverContext, + ): Promise => { + logger.debug('Execute removeFromProvision() mutation', { + protocolNetwork, + }) + + if (!multiNetworks) { + throw Error( + 'IndexerManagementClient must be in `network` mode to add stake to a provision', + ) + } + + const network = extractNetwork(protocolNetwork, multiNetworks) + const networkMonitor = network.networkMonitor + const contracts = network.contracts + const transactionManager = network.transactionManager + + if (!(await network.isHorizon.value())) { + throw indexerError(IndexerErrorCode.IE082) + } + + const indexer = network.specification.indexerOptions.address.toLowerCase() + const dataService = contracts.SubgraphService.target.toString().toLowerCase() + + try { + // Check if the provision exists - this will throw if it doesn't + const provision = await networkMonitor.provision(indexer, dataService) + + logger.debug('Provision found', { + provision, + }) + + const thawedTokens = await contracts.HorizonStaking.getThawedTokens( + ThawRequestType.Provision, + indexer, + dataService, + indexer, + ) + + // return early if there are no expired thaw requests + if (thawedTokens === 0n) { + return { + id: provision.id, + dataService, + indexer, + tokensProvisioned: provision.tokensProvisioned.toString(), + tokensThawing: provision.tokensThawing.toString(), + tokensRemoved: '0', + protocolNetwork: network.specification.networkIdentifier, + } + } + + logger.debug(`Sending deprovision transaction`, { + indexer: indexer, + dataService: dataService, + protocolNetwork, + }) + + // deprovision all expired thaw requests + const receipt = await transactionManager.executeTransaction( + async () => + contracts.HorizonStaking.deprovision.estimateGas(indexer, dataService, 0), + async (gasLimit) => + contracts.HorizonStaking.deprovision(indexer, dataService, 0, { + gasLimit, + }), + logger.child({ action: 'deprovision' }), + ) + + if (receipt === 'paused' || receipt === 'unauthorized') { + throw indexerError( + IndexerErrorCode.IE062, + `Stake not thawed from provision. ${ + receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + }`, + ) + } + + const thawFromProvisionEventLogs = network.transactionManager.findEvent( + 'TokensDeprovisioned', + network.contracts.HorizonStaking.interface, + 'serviceProvider', + indexer.toString(), + receipt, + logger, + ) + + if (!thawFromProvisionEventLogs) { + throw indexerError( + IndexerErrorCode.IE083, + `Thaw from provision transaction was never mined`, + ) + } + + logger.info(`Successfully deprovisioned stake from provision`, { + amountGRT: formatGRT(thawFromProvisionEventLogs.tokens), + thawedTokens: thawedTokens.toString(), + transaction: receipt.hash, + }) + + return { + id: provision.id, + dataService, + indexer, + tokensProvisioned: provision.tokensProvisioned.toString(), + tokensThawing: (provision.tokensThawing - thawedTokens).toString(), // TODO: we could re-fetch the provision instead + tokensRemoved: thawedTokens.toString(), + protocolNetwork: network.specification.networkIdentifier, + } + } catch (error) { + logger.error('Failed to deprovision stake from provision', { + error, + }) + throw error + } + }, +} diff --git a/packages/indexer-common/src/indexer-management/rules.ts b/packages/indexer-common/src/indexer-management/rules.ts index 656dd532b..55a4d0ccd 100644 --- a/packages/indexer-common/src/indexer-management/rules.ts +++ b/packages/indexer-common/src/indexer-management/rules.ts @@ -1,12 +1,85 @@ -import { Logger } from '@graphprotocol/common-ts' +import { Eventual, join, Logger } from '@graphprotocol/common-ts' import { IndexerManagementModels, INDEXING_RULE_GLOBAL, IndexingRule, IndexingRuleAttributes, + MultiNetworks, + Network, + sequentialTimerMap, } from '@graphprotocol/indexer-common' import { parseIndexingRule } from '../rules' import groupBy from 'lodash.groupby' +import { extractNetwork } from './resolvers/utils' +import { IndexingRuleCreationAttributes } from './models' + +export class RulesManager { + declare multiNetworks: MultiNetworks + declare models: IndexerManagementModels + declare logger: Logger + + static async create( + multiNetworks: MultiNetworks, + logger: Logger, + models: IndexerManagementModels, + ) { + const rulesManager = new RulesManager() + rulesManager.multiNetworks = multiNetworks + rulesManager.logger = logger + rulesManager.models = models + + logger.info('Begin monitoring indexing rules for invalid allocation lifetimes') + await rulesManager.monitorRules() + + return rulesManager + } + + async monitorRules(): Promise { + const logger = this.logger.child({ component: 'RulesMonitor' }) + const rules: Eventual = sequentialTimerMap( + { + logger, + milliseconds: 30_000, + }, + async () => { + logger.trace('Fetching indexing rules') + let rules: IndexingRuleAttributes[] = [] + try { + rules = await fetchIndexingRules(this.models, true) + logger.trace(`Fetched ${rules.length} indexing rules`) + } catch (err) { + logger.warn('Failed to fetch indexing rules', { err }) + } + + return rules + }, + { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + onError: (err: any) => logger.warn('Failed to fetch indexing rules', { err }), + }, + ) + + join({ rules }).pipe(async ({ rules }) => { + logger.info(`Indexing rules found, evaluating allocation lifetime`) + for (const rule of rules) { + const network = extractNetwork(rule.protocolNetwork, this.multiNetworks) + const [isValid, maxSuggestedLifetime] = await ensureAllocationLifetime( + rule, + network, + ) + if (!isValid) { + logger.warn(`Invalid rule allocation lifetime. Indexing rewards at risk!`, { + maxLifetime: maxSuggestedLifetime, + ruleId: rule.id, + ruleIdentifier: rule.identifier, + ruleAllocationAmount: rule.allocationAmount, + ruleAllocationLifetime: rule.allocationLifetime, + }) + } + } + }) + } +} export const fetchIndexingRules = async ( models: IndexerManagementModels, @@ -56,3 +129,30 @@ export const upsertIndexingRule = async ( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return updatedRule! } + +// Enforce max allocation lifetime for Horizon +// This is to prevent indexing rewards from being automatically forefited due to a too long allocation lifetime +// Previously this was not enforced onchain, but anyone could force close expired allocations +export const ensureAllocationLifetime = async ( + rule: IndexingRuleAttributes | IndexingRuleCreationAttributes, + network: Network, +): Promise<[boolean, number]> => { + if (rule.allocationLifetime) { + const maxAllocationDuration = await network.networkMonitor.maxAllocationDuration() + const isHorizon = await network.isHorizon.value() + + if (isHorizon) { + // Don't enforce for altruistic allocations + if ( + rule.allocationLifetime > maxAllocationDuration.horizon && + (rule.allocationAmount === undefined || + rule.allocationAmount === null || + Number(rule.allocationAmount) > 0) + ) { + return [false, maxAllocationDuration.horizon] + } + } + } + + return [true, 0] +} diff --git a/packages/indexer-common/src/indexer-management/types.ts b/packages/indexer-common/src/indexer-management/types.ts index 0985038eb..0aad3e33d 100644 --- a/packages/indexer-common/src/indexer-management/types.ts +++ b/packages/indexer-common/src/indexer-management/types.ts @@ -4,7 +4,7 @@ import { SubgraphDeploymentID, toAddress, } from '@graphprotocol/common-ts' -import { Allocation } from '../allocations' +import { Allocation, Provision } from '../allocations' import { GraphNode } from '../graph-node' import { SubgraphDeployment } from '../types' @@ -33,7 +33,6 @@ export interface CloseAllocationResult { allocation: string allocatedTokens: string indexingRewards: string - receiptsWorthCollecting: boolean protocolNetwork: string } @@ -43,7 +42,6 @@ export interface ReallocateAllocationResult { transactionID: string | undefined closedAllocation: string indexingRewardsCollected: string - receiptsWorthCollecting: boolean createdAllocation: string createdAllocationStake: string protocolNetwork: string @@ -87,6 +85,7 @@ export const parseGraphQLAllocation = ( // Ensure the allocation ID (an address) is checksummed id: toAddress(allocation.id), status: allocation.status, + isLegacy: allocation.isLegacy, subgraphDeployment: { id: new SubgraphDeploymentID(allocation.subgraphDeployment.id), deniedAt: allocation.subgraphDeployment.deniedAt, @@ -97,8 +96,10 @@ export const parseGraphQLAllocation = ( }, indexer: toAddress(allocation.indexer.id), allocatedTokens: BigInt(allocation.allocatedTokens), + createdAt: allocation.createdAt, createdAtBlockHash: allocation.createdAtBlockHash, createdAtEpoch: allocation.createdAtEpoch, + closedAt: allocation.closedAt, closedAtEpoch: allocation.closedAtEpoch, closedAtEpochStartBlockHash: undefined, previousEpochStartBlockHash: undefined, @@ -108,6 +109,17 @@ export const parseGraphQLAllocation = ( queryFeesCollected: allocation.queryFeesCollected, }) +export const parseGraphQLProvision = (provision: any): Provision => ({ + id: provision.id.toString(), + dataService: toAddress(provision.dataService), + indexer: toAddress(provision.indexer), + tokensProvisioned: BigInt(provision.tokensProvisioned), + tokensAllocated: BigInt(provision.tokensAllocated), + tokensThawing: BigInt(provision.tokensThawing), + maxVerifierCut: BigInt(provision.maxVerifierCut), + thawingPeriod: BigInt(provision.thawingPeriod), +}) + export interface RewardsPool { subgraphDeployment: SubgraphDeploymentID allocationIndexer: Address @@ -361,3 +373,16 @@ export function networkIsL2(networkIdentifier: string): boolean { networkIdentifier = resolveChainId(networkIdentifier) return networkIdentifier === 'eip155:42161' || networkIdentifier === 'eip155:421614' } + +export enum IndexingStatusCode { + Unknown = 0, + Healthy = 1, + Unhealthy = 2, + Failed = 3, +} + +export interface POIMetadata { + publicPOI: string + blockNumber: number + indexingStatus: IndexingStatusCode +} diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index bb629df1b..38ecf4cec 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -30,7 +30,6 @@ import { specification as spec, GraphNode, NetworkMonitor, - AllocationReceiptCollector, SubgraphFreshnessChecker, monitorEligibleAllocations, } from '.' @@ -49,9 +48,6 @@ export class Network { transactionManager: TransactionManager networkMonitor: NetworkMonitor - // TODO: deprecated - receiptCollector: AllocationReceiptCollector | undefined - tapCollector: TapCollector | undefined specification: spec.NetworkSpecification paused: Eventual @@ -66,7 +62,6 @@ export class Network { networkProvider: JsonRpcProvider, transactionManager: TransactionManager, networkMonitor: NetworkMonitor, - receiptCollector: AllocationReceiptCollector | undefined, tapCollector: TapCollector | undefined, specification: spec.NetworkSpecification, paused: Eventual, @@ -80,7 +75,6 @@ export class Network { this.networkProvider = networkProvider this.transactionManager = transactionManager this.networkMonitor = networkMonitor - this.receiptCollector = receiptCollector this.tapCollector = tapCollector this.specification = specification this.paused = paused @@ -254,12 +248,11 @@ export class Network { const isOperator = await networkMonitor.monitorIsOperator( logger, - contracts, specification.indexerOptions.address, wallet, ) - const isHorizon = await networkMonitor.monitorIsHorizon(logger, contracts) + const isHorizon = await networkMonitor.monitorIsHorizon(logger) const transactionManager = new TransactionManager( networkProvider, @@ -297,26 +290,6 @@ export class Network { interval: specification.allocationSyncInterval, }) - // -------------------------------------------------------------------------------- - // * Allocation Receipt Collector - // -------------------------------------------------------------------------------- - const scalarCollector: AllocationReceiptCollector | undefined = undefined - // if (!(tapContracts && tapSubgraph)) { - // logger.warn( - // "deprecated scalar voucher collector is enabled - you probably don't want this", - // ) - // scalarCollector = await AllocationReceiptCollector.create({ - // logger, - // metrics, - // transactionManager: transactionManager, - // models: queryFeeModels, - // allocationExchange: contracts.allocationExchange, - // allocations, - // networkSpecification: specification, - // networkSubgraph, - // }) - // } - // -------------------------------------------------------------------------------- // * TAP Collector // -------------------------------------------------------------------------------- @@ -350,7 +323,6 @@ export class Network { networkProvider, transactionManager, networkMonitor, - scalarCollector, tapCollector, specification, paused, diff --git a/packages/indexer-common/src/transactions.ts b/packages/indexer-common/src/transactions.ts index 6d0691591..fc99bbf20 100644 --- a/packages/indexer-common/src/transactions.ts +++ b/packages/indexer-common/src/transactions.ts @@ -12,7 +12,7 @@ import { Interface, Result, } from 'ethers' -import { Address, Eventual, Logger, mutable, toAddress } from '@graphprotocol/common-ts' +import { Eventual, Logger } from '@graphprotocol/common-ts' import delay from 'delay' import { TransactionMonitoring } from './network-specification' import { IndexerError, indexerError, IndexerErrorCode } from './errors' @@ -124,7 +124,10 @@ export class TransactionManager { tx = await this.wallet.sendTransaction(txRequest) } - logger.info(`Transaction pending`, { tx: tx, confirmationBlocks: this.specification.confirmationBlocks }) + logger.info(`Transaction pending`, { + tx: tx, + confirmationBlocks: this.specification.confirmationBlocks, + }) const receipt = await this.ethereum.waitForTransaction( tx.hash, @@ -380,46 +383,6 @@ export class TransactionManager { }) } - async monitorIsOperator( - logger: Logger, - contracts: GraphHorizonContracts & SubgraphServiceContracts, - indexerAddress: Address, - wallet: HDNodeWallet, - ): Promise> { - // If indexer and operator address are identical, operator status is - // implicitly granted => we'll never have to check again - if (indexerAddress === toAddress(wallet.address)) { - logger.info(`Indexer and operator are identical, operator status granted`) - return mutable(true) - } - - return sequentialTimerReduce( - { - logger, - milliseconds: 60_000, - }, - async (isOperator) => { - try { - return await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress) - } catch (err) { - logger.warn( - `Failed to check operator status for indexer, assuming it has not changed`, - { err: indexerError(IndexerErrorCode.IE008, err), isOperator }, - ) - return isOperator - } - }, - await contracts.HorizonStaking.isOperator(wallet.address, indexerAddress), - ).map((isOperator) => { - logger.info( - isOperator - ? `Have operator status for indexer` - : `No operator status for indexer`, - ) - return isOperator - }) - } - findEvent( eventType: string, contractInterface: Interface, @@ -430,32 +393,35 @@ export class TransactionManager { ): Result | undefined { const events = receipt.logs const decodedEvents: Result[] = [] - const expectedTopic = contractInterface.getEvent(eventType)?.topicHash + const expectedEvent = contractInterface.getEvent(eventType) + const expectedTopicHash = expectedEvent?.topicHash - // TODO HORIZON - throw indexer error here - if (!expectedTopic) { + if (!expectedTopicHash) { throw new Error(`Event type ${eventType} not found in contract interface`) } const result = events - .filter((event) => event.topics.includes(expectedTopic)) + .filter((event) => event.topics.includes(expectedTopicHash)) .map((event) => { const decoded = contractInterface.decodeEventLog( - eventType, + expectedEvent, event.data, event.topics, ) decodedEvents.push(decoded) return decoded }) - .find( - (eventLogs) => - eventLogs[logKey].toLocaleLowerCase() === logValue.toLocaleLowerCase(), - ) + .find((eventLogs) => { + return ( + eventLogs[logKey] && + eventLogs[logKey].toString().toLocaleLowerCase() === + logValue.toLocaleLowerCase() + ) + }) logger.trace('Searched for event logs', { function: 'findEvent', - expectedTopic, + expectedTopicHash, events, decodedEvents, eventType, diff --git a/packages/indexer-common/src/types.ts b/packages/indexer-common/src/types.ts index 8b142b5f6..7b3f5039f 100644 --- a/packages/indexer-common/src/types.ts +++ b/packages/indexer-common/src/types.ts @@ -106,3 +106,8 @@ export function parseDeploymentManagementMode(input: string): DeploymentManageme throw new Error(`Invalid value for deployment management mode: ${input}`) } } + +export type HorizonTransitionValue = { + legacy: U + horizon: V +} diff --git a/yarn.lock b/yarn.lock index 2e2f8412b..f2c1a9b2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -573,10 +573,10 @@ resolved "https://registry.yarnpkg.com/@graphprotocol/contracts/-/contracts-7.1.2.tgz#919cf6747d25cb52855d01be6582c06695ae3b83" integrity sha512-t8o0nA+cs5HEKLxjaV0zELBtDLAPm6hoXi0o5tnpw7vigyMPoP92QQkVfbjAt9eMnkC7/AyGRWOMBfAZV9l8Og== -"@graphprotocol/horizon@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@graphprotocol/horizon/-/horizon-0.3.2.tgz#a236fe9f114d62346a3068edbb7631f9f30d67c8" - integrity sha512-0XHbLPk4su0h0i0Oc4SkoiH2+7fx7eF3DsM7GvExOtNRDe258lXs2KrHsp2Oiv19HOFy4mryb6E2mdB/ijRhbQ== +"@graphprotocol/horizon@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@graphprotocol/horizon/-/horizon-0.3.3.tgz#2fe0a9ebf27532b5deea94443d47342e159d43c8" + integrity sha512-aAQ7zOaqGE/nMuu+h2CGwO8Tkho/m1CcezfOz54voBpFSqfxk2WggYe1lUWd+nvHpuynfgaqM4gW+kYTLliWYw== "@graphprotocol/pino-sentry-simple@0.7.1": version "0.7.1" @@ -588,19 +588,19 @@ split2 "^3.1.1" through2 "^3.0.1" -"@graphprotocol/subgraph-service@^0.3.4": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.3.4.tgz#38929c04d03ad06823f9a867c8a4aef4c7f581e7" - integrity sha512-POepREau0ExCz4ZJrlhzIS3RigEuzlbp/xlurpHkgaOn97cFAv3x9ZaE5a9uwh1azRm3Djz8RUBmXpqmwoK9NA== +"@graphprotocol/subgraph-service@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.3.5.tgz#38af1602b73602c57617e915ccf77c89a386a356" + integrity sha512-QmcQ4eOoUkmA+yStnRwIPAjCDyqIyQ0hLTL9IRZPDXs5a0ye7Kd9XIZDikuPlm1Bdqwu+tr2/yYdc3x3t0Sx2Q== -"@graphprotocol/toolshed@0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.5.0.tgz#e1937d59a3d34bc5bacbc825827d6345ba662711" - integrity sha512-8KlLbee8TAhibUGpdSI04iOnI9gkfErchSqrp/SHU1V5RDuATNCuVe3MVmOt+Jdjc747bTU+OLU+7YxLcAa5Aw== +"@graphprotocol/toolshed@0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.5.5.tgz#7fccd11499a5938fb51a1eb822ea8faaed05fdc1" + integrity sha512-fS/FmGAukWq2MjW4uOOJ/y+fXY6vB5kiZORLmKTN36hJnBXJsCOs6u8JNWER2E5MN4iTMSOLd6fj9JgncDNhsg== dependencies: "@graphprotocol/contracts" "^7.1.2" - "@graphprotocol/horizon" "^0.3.2" - "@graphprotocol/subgraph-service" "^0.3.4" + "@graphprotocol/horizon" "^0.3.3" + "@graphprotocol/subgraph-service" "^0.3.5" "@nomicfoundation/hardhat-ethers" "3.0.8" debug "^4.4.0" ethers "6.13.7" From f9cc1ffda755a0a4e434ee959baf5b065b6b4049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 2 Jun 2025 17:50:09 -0300 Subject: [PATCH 07/28] chore: add isLegacy column to actions table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../db/migrations/19-actions-add-islegacy.ts | 52 +++++++++++++++++++ packages/indexer-cli/src/actions.ts | 8 +++ packages/indexer-common/src/actions.ts | 3 ++ .../__tests__/helpers.test.ts | 9 ++++ .../src/indexer-management/actions.ts | 1 + .../src/indexer-management/models/action.ts | 7 +++ .../indexer-management/resolvers/actions.ts | 9 ++++ 7 files changed, 89 insertions(+) create mode 100644 packages/indexer-agent/src/db/migrations/19-actions-add-islegacy.ts diff --git a/packages/indexer-agent/src/db/migrations/19-actions-add-islegacy.ts b/packages/indexer-agent/src/db/migrations/19-actions-add-islegacy.ts new file mode 100644 index 000000000..1bf84cbbe --- /dev/null +++ b/packages/indexer-agent/src/db/migrations/19-actions-add-islegacy.ts @@ -0,0 +1,52 @@ +import { Logger } from '@graphprotocol/common-ts' +import { DataTypes, QueryInterface } from 'sequelize' + +interface MigrationContext { + queryInterface: QueryInterface + logger: Logger +} + +interface Context { + context: MigrationContext +} + +export async function up({ context }: Context): Promise { + const { queryInterface, logger } = context + + logger.debug(`Checking if 'Actions' table exists`) + const tables = await queryInterface.showAllTables() + if (!tables.includes('Actions')) { + logger.info(`Actions table does not exist, migration not necessary`) + return + } + + logger.debug(`Checking if 'Actions' table needs to be migrated`) + const table = await queryInterface.describeTable('Actions') + const isLegacy = table.isLegacy + if (isLegacy) { + logger.info(`'isLegacy' column already exists, migration not necessary`) + return + } + + logger.info(`Add 'isLegacy' column to 'Actions' table`) + await queryInterface.addColumn('Actions', 'isLegacy', { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true, + }) +} + +export async function down({ context }: Context): Promise { + const { queryInterface, logger } = context + + return await queryInterface.sequelize.transaction({}, async transaction => { + const tables = await queryInterface.showAllTables() + + if (tables.includes('Actions')) { + logger.info(`Remove 'isLegacy' column`) + await context.queryInterface.removeColumn('Actions', 'isLegacy', { + transaction, + }) + } + }) +} diff --git a/packages/indexer-cli/src/actions.ts b/packages/indexer-cli/src/actions.ts index fbf3f501a..70842475e 100644 --- a/packages/indexer-cli/src/actions.ts +++ b/packages/indexer-cli/src/actions.ts @@ -36,6 +36,11 @@ export async function buildActionInput( protocolNetwork: string, ): Promise { await validateActionInput(type, actionParams) + + // TODO: we could check isHorizon status here to set the proper value for isLegacy, but it requires multiNetworks + // The IndexerManagementServer will set the correct value anyways + const isLegacy = false + switch (type) { case ActionType.ALLOCATE: return { @@ -47,6 +52,7 @@ export async function buildActionInput( status, priority, protocolNetwork, + isLegacy, } case ActionType.UNALLOCATE: { let poi = actionParams.param2 @@ -64,6 +70,7 @@ export async function buildActionInput( status, priority, protocolNetwork, + isLegacy, } } case ActionType.REALLOCATE: { @@ -83,6 +90,7 @@ export async function buildActionInput( status, priority, protocolNetwork, + isLegacy, } } } diff --git a/packages/indexer-common/src/actions.ts b/packages/indexer-common/src/actions.ts index afa265d02..97bc128f7 100644 --- a/packages/indexer-common/src/actions.ts +++ b/packages/indexer-common/src/actions.ts @@ -46,6 +46,7 @@ export interface ActionInput { status: ActionStatus priority: number | undefined protocolNetwork: string + isLegacy: boolean } export const isValidActionInput = ( @@ -161,6 +162,7 @@ export interface ActionFilter { reason?: string updatedAt?: WhereOperators protocolNetwork?: string + isLegacy?: boolean } export const actionFilterToWhereOptions = (filter: ActionFilter): WhereOptions => { @@ -192,6 +194,7 @@ export interface ActionResult { failureReason: string | null transaction: string | null protocolNetwork: string + isLegacy: boolean } export enum ActionType { diff --git a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts index e089afcc5..dcdef664d 100644 --- a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts +++ b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts @@ -246,6 +246,7 @@ describe('Actions', () => { priority: 0, // When writing directly to the database, `protocolNetwork` must be in the CAIP2-ID format. protocolNetwork: 'eip155:421614', + isLegacy: true, } await models.Action.upsert(action) @@ -283,6 +284,14 @@ describe('Actions', () => { updatedAt: { [Op.lte]: literal("NOW() - INTERVAL '1d'") }, }), ).resolves.toHaveLength(0) + + await expect( + ActionManager.fetchActions(models, null, { + status: ActionStatus.FAILED, + type: ActionType.ALLOCATE, + isLegacy: true, + }), + ).resolves.toHaveLength(1) }) }) describe('Types', () => { diff --git a/packages/indexer-common/src/indexer-management/actions.ts b/packages/indexer-common/src/indexer-management/actions.ts index 8f43d3d05..f37a76fef 100644 --- a/packages/indexer-common/src/indexer-management/actions.ts +++ b/packages/indexer-common/src/indexer-management/actions.ts @@ -112,6 +112,7 @@ export class ActionManager { oldestAffectedAllocationCreatedAtEpoch: affectedAllocations[0]?.createdAtEpoch ?? 'no action in the batch affects existing allocations', + oldestAffectedAllocationIsLegacy: affectedAllocations[0]?.isLegacy, affectedAllocationExpiring, }, ) diff --git a/packages/indexer-common/src/indexer-management/models/action.ts b/packages/indexer-common/src/indexer-management/models/action.ts index f89a644b3..daf35d67a 100644 --- a/packages/indexer-common/src/indexer-management/models/action.ts +++ b/packages/indexer-common/src/indexer-management/models/action.ts @@ -37,6 +37,8 @@ export class Action extends Model< declare protocolNetwork: string + declare isLegacy: boolean + // eslint-disable-next-line @typescript-eslint/ban-types public toGraphQL(): object { return { ...this.toJSON(), __typename: 'Action' } @@ -152,6 +154,11 @@ export const defineActionModels = (sequelize: Sequelize): ActionModels => { is: caip2IdRegex, }, }, + isLegacy: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true, + }, }, { modelName: 'Action', diff --git a/packages/indexer-common/src/indexer-management/resolvers/actions.ts b/packages/indexer-common/src/indexer-management/resolvers/actions.ts index 1e246754c..308e57c3d 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/actions.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/actions.ts @@ -20,6 +20,7 @@ import { import { literal, Op, Transaction } from 'sequelize' import { ActionManager } from '../actions' import groupBy from 'lodash.groupby' +import { extractNetwork } from './utils' // Perform insert, update, or no-op depending on existing queue data // INSERT - No item in the queue yet targeting this deploymentID @@ -170,6 +171,14 @@ export default { } }) + // Set proper value for isLegacy - any new actions in horizon are not legacy + await Promise.all( + actions.map(async (action) => { + const network = extractNetwork(action.protocolNetwork, multiNetworks) + action.isLegacy = !(await network.isHorizon.value()) + }), + ) + // Let Network Monitors validate actions based on their protocol networks await multiNetworks.mapNetworkMapped( groupBy(actions, (action) => action.protocolNetwork), From d2bfd5babe0b55d9dddbf31f56f3c53604621866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 3 Jun 2025 10:29:12 -0300 Subject: [PATCH 08/28] chore: cli support isLegacy for actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-cli/src/actions.ts | 7 +++++++ packages/indexer-cli/src/commands/indexer/actions/get.ts | 1 + packages/indexer-common/src/indexer-management/client.ts | 3 +++ 3 files changed, 11 insertions(+) diff --git a/packages/indexer-cli/src/actions.ts b/packages/indexer-cli/src/actions.ts index 70842475e..d77f5db78 100644 --- a/packages/indexer-cli/src/actions.ts +++ b/packages/indexer-cli/src/actions.ts @@ -261,6 +261,7 @@ export async function executeApprovedActions( reason transaction failureReason + isLegacy } } `, @@ -297,6 +298,7 @@ export async function approveActions( transaction status protocolNetwork + isLegacy } } `, @@ -333,6 +335,7 @@ export async function cancelActions( priority transaction status + isLegacy } } `, @@ -369,6 +372,7 @@ export async function fetchAction( priority transaction status + isLegacy } } `, @@ -419,6 +423,7 @@ export async function fetchActions( transaction status failureReason + isLegacy } } `, @@ -456,6 +461,7 @@ export async function deleteActions( transaction status failureReason + isLegacy } } `, @@ -494,6 +500,7 @@ export async function updateActions( status failureReason protocolNetwork + isLegacy } } `, diff --git a/packages/indexer-cli/src/commands/indexer/actions/get.ts b/packages/indexer-cli/src/commands/indexer/actions/get.ts index f1916eb04..0e106ebeb 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/get.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/get.ts @@ -49,6 +49,7 @@ const actionFields: (keyof Action)[] = [ 'failureReason', 'transaction', 'reason', + 'isLegacy', ] /// Validates input for the `--fieds` option. diff --git a/packages/indexer-common/src/indexer-management/client.ts b/packages/indexer-common/src/indexer-management/client.ts index 273c0eeb2..a0212201d 100644 --- a/packages/indexer-common/src/indexer-management/client.ts +++ b/packages/indexer-common/src/indexer-management/client.ts @@ -139,6 +139,7 @@ const SCHEMA_SDL = gql` createdAt: BigInt! updatedAt: BigInt protocolNetwork: String! + isLegacy: Boolean! } input ActionInput { @@ -153,6 +154,7 @@ const SCHEMA_SDL = gql` reason: String! priority: Int! protocolNetwork: String! + isLegacy: Boolean! } input ActionUpdateInput { @@ -200,6 +202,7 @@ const SCHEMA_SDL = gql` failureReason: String priority: Int protocolNetwork: String! + isLegacy: Boolean! } input ActionFilter { From 2b44aaa2deea33cf08ba36d9b73c7944a450bd32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 6 Jun 2025 16:11:58 -0300 Subject: [PATCH 09/28] wip: full allocation management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-agent/src/agent.ts | 5 +- packages/indexer-cli/src/actions.ts | 29 +- packages/indexer-cli/src/allocations.ts | 4 +- .../src/commands/indexer/actions/queue.ts | 12 +- .../src/commands/indexer/allocations/close.ts | 48 ++- .../commands/indexer/allocations/collect.ts | 32 +- .../commands/indexer/allocations/create.ts | 27 +- .../src/commands/indexer/allocations/get.ts | 4 +- .../indexer/allocations/reallocate.ts | 38 +-- packages/indexer-common/src/actions.ts | 6 + .../__tests__/helpers.test.ts | 5 +- .../src/indexer-management/allocations.ts | 282 +++++++++++++----- .../src/indexer-management/monitor.ts | 253 +++++++++++----- .../resolvers/allocations.ts | 121 +++++--- .../src/indexer-management/types.ts | 8 +- packages/indexer-common/src/operator.ts | 30 +- 16 files changed, 604 insertions(+), 300 deletions(-) diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index 160fa3a23..2e8f37e03 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -252,7 +252,7 @@ export class Agent { }, ) - this.reconciliationLoop() + // this.reconciliationLoop() return this } @@ -1083,6 +1083,8 @@ export class Agent { epoch, }) + const isHorizon = await network.isHorizon.value() + // TODO: Can we replace `filter` for `find` here? Is there such a case when we // would have multiple allocations for the same subgraph? const activeDeploymentAllocations = activeAllocations.filter( @@ -1133,6 +1135,7 @@ export class Agent { logger, deploymentAllocationDecision, mostRecentlyClosedAllocation, + isHorizon, ) } } else if (activeDeploymentAllocations.length > 0) { diff --git a/packages/indexer-cli/src/actions.ts b/packages/indexer-cli/src/actions.ts index d77f5db78..76f47215e 100644 --- a/packages/indexer-cli/src/actions.ts +++ b/packages/indexer-cli/src/actions.ts @@ -23,6 +23,8 @@ export interface GenericActionInputParams { param2: string | undefined param3: string | undefined param4: string | undefined + param5: string | undefined + param6: string | undefined } // Make separate functions for each action type parsing from generic? @@ -35,9 +37,10 @@ export async function buildActionInput( priority: number, protocolNetwork: string, ): Promise { + // TODO HORIZON: validate publicPOI and blockNumber for unallocate and reallocate only for horizon allocations await validateActionInput(type, actionParams) - // TODO: we could check isHorizon status here to set the proper value for isLegacy, but it requires multiNetworks + // TODO HORIZON: we could check isHorizon status here to set the proper value for isLegacy, but it requires multiNetworks // The IndexerManagementServer will set the correct value anyways const isLegacy = false @@ -63,6 +66,8 @@ export async function buildActionInput( deploymentID: actionParams.targetDeployment, allocationID: actionParams.param1, poi: poi, + publicPOI: actionParams.param5, + blockNumber: actionParams.param6, force: actionParams.param3 === 'true', type, source, @@ -83,6 +88,8 @@ export async function buildActionInput( allocationID: actionParams.param1, amount: actionParams.param2?.toString(), poi: poi, + publicPOI: actionParams.param5, + blockNumber: actionParams.param6, force: actionParams.param4 === 'true', type, source, @@ -190,12 +197,15 @@ export async function queueActions( allocationID amount poi + publicPOI + blockNumber force source reason priority status protocolNetwork + isLegacy } } `, @@ -216,11 +226,14 @@ const ACTION_PARAMS_PARSERS: Record any> allocationID: x => x, amount: nullPassThrough(parseGRT), poi: nullPassThrough((x: string) => validatePOI(x)), + publicPOI: nullPassThrough((x: string) => validatePOI(x)), + blockNumber: nullPassThrough((x: string) => Number(x)), force: x => parseBoolean(x), type: x => validateActionType(x), status: x => validateActionStatus(x), reason: nullPassThrough, protocolNetwork: x => validateNetworkIdentifier(x), + isLegacy: x => parseBoolean(x), } /** @@ -256,6 +269,8 @@ export async function executeApprovedActions( allocationID amount poi + publicPOI + blockNumber force source reason @@ -291,6 +306,8 @@ export async function approveActions( deploymentID amount poi + publicPOI + blockNumber force source reason @@ -329,6 +346,8 @@ export async function cancelActions( deploymentID amount poi + publicPOI + blockNumber force source reason @@ -366,6 +385,8 @@ export async function fetchAction( deploymentID amount poi + publicPOI + blockNumber force source reason @@ -416,6 +437,8 @@ export async function fetchActions( deploymentID amount poi + publicPOI + blockNumber force source reason @@ -454,6 +477,8 @@ export async function deleteActions( deploymentID amount poi + publicPOI + blockNumber force source reason @@ -492,6 +517,8 @@ export async function updateActions( deploymentID amount poi + publicPOI + blockNumber force source reason diff --git a/packages/indexer-cli/src/allocations.ts b/packages/indexer-cli/src/allocations.ts index b6656095b..8996b8cc5 100644 --- a/packages/indexer-cli/src/allocations.ts +++ b/packages/indexer-cli/src/allocations.ts @@ -255,7 +255,7 @@ export const closeAllocation = async ( { allocation: allocationID, poi, - blockNumber, + blockNumber: blockNumber, publicPOI, force, protocolNetwork, @@ -312,7 +312,7 @@ export const reallocateAllocation = async ( { allocation: allocationID, poi, - blockNumber, + blockNumber: blockNumber, publicPOI, amount: amount.toString(), force, diff --git a/packages/indexer-cli/src/commands/indexer/actions/queue.ts b/packages/indexer-cli/src/commands/indexer/actions/queue.ts index ef1d74ddb..583486a6f 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/queue.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/queue.ts @@ -21,19 +21,21 @@ ${chalk.bold( ${chalk.bold('graph indexer actions queue')} [options] allocate ${chalk.bold( 'graph indexer actions queue', -)} [options] unallocate +)} [options] unallocate ${chalk.bold( 'graph indexer actions queue', -)} [options] reallocate +)} [options] reallocate ${chalk.dim('Options:')} -h, --help Show usage information - -n, --network [Required] The protocol network for this action (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) + -n, --network The protocol network for this action (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML -s, --source Specify the source of the action decision -r, --reason Specify the reason for the action to be taken -p, --priority Define a priority order for the action + + For action type specific options, see the help for the specific action type. ` module.exports = { @@ -62,7 +64,7 @@ module.exports = { return } - const [type, targetDeployment, param1, param2, param3, param4] = + const [type, targetDeployment, param1, param2, param3, param4, param5, param6] = parameters.array || [] let actionInputParams: ActionInput @@ -77,7 +79,7 @@ module.exports = { actionInputParams = await buildActionInput( validateActionType(type), - { targetDeployment, param1, param2, param3, param4 }, + { targetDeployment, param1, param2, param3, param4, param5, param6 }, decisionSource, decisionReason, ActionStatus.QUEUED, diff --git a/packages/indexer-cli/src/commands/indexer/allocations/close.ts b/packages/indexer-cli/src/commands/indexer/allocations/close.ts index 05a5a4f09..52b286d91 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/close.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/close.ts @@ -4,26 +4,29 @@ import chalk from 'chalk' import { loadValidatedConfig } from '../../../config' import { createIndexerManagementClient } from '../../../client' import { closeAllocation } from '../../../allocations' -import { validatePOI, printObjectOrArray } from '../../../command-helpers' -import { validateNetworkIdentifier } from '@graphprotocol/indexer-common' +import { + validatePOI, + printObjectOrArray, + extractProtocolNetworkOption, +} from '../../../command-helpers' const HELP = ` ${chalk.bold( 'graph indexer allocations close', -)} [options] +)} [options] ${chalk.dim('Options:')} -h, --help Show usage information + -n, --network The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia -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('Arguments:')} - The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia The allocation id to close - The POI to close the allocation with - The block number the POI was computed at - [Horizon] The public POI to close the allocation with. Must be same block height as POI. + (optional) The POI to close the allocation with + (optional, horizon only) The block number the POI was computed at. Must be set if POI is provided. + (optional, horizon only) The public POI to close the allocation with. Must be same block height as POI. ` module.exports = { @@ -52,7 +55,7 @@ module.exports = { return } - const [network, id, unformattedPoi, unformattedBlockNumber, unformattedPublicPOI] = + const [id, unformattedPoi, unformattedBlockNumber, unformattedPublicPOI] = parameters.array || [] if (id === undefined) { @@ -62,37 +65,30 @@ module.exports = { return } - let protocolNetwork: string - if (!network) { - spinner.fail(`Missing required argument: 'network'`) - print.info(HELP) - process.exitCode = 1 - return - } else { - try { - protocolNetwork = validateNetworkIdentifier(network) - } catch (error) { - spinner.fail(`Invalid value for argument 'network': '${network}' `) - process.exitCode = 1 - return - } - } - let poi: string | undefined let blockNumber: number | undefined let publicPOI: string | undefined try { poi = validatePOI(unformattedPoi) publicPOI = validatePOI(unformattedPublicPOI) - blockNumber = Number(unformattedBlockNumber) + blockNumber = + unformattedBlockNumber === undefined ? undefined : Number(unformattedBlockNumber) } catch (error) { - spinner.fail(`Invalid POI provided, '${unformattedPoi}'. ` + error.message) + spinner.fail(`Invalid value provided: ` + error.message) process.exitCode = 1 return } spinner.text = `Closing allocation '${id}` try { + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!protocolNetwork) { + throw new Error( + 'Must provide a network identifier' + `(network: '${protocolNetwork}')`, + ) + } + const config = loadValidatedConfig() const client = await createIndexerManagementClient({ url: config.api }) const closeResult = await closeAllocation( diff --git a/packages/indexer-cli/src/commands/indexer/allocations/collect.ts b/packages/indexer-cli/src/commands/indexer/allocations/collect.ts index 4730988d2..d0b293b17 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/collect.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/collect.ts @@ -4,7 +4,7 @@ import chalk from 'chalk' import { loadValidatedConfig } from '../../../config' import { createIndexerManagementClient } from '../../../client' import { submitCollectReceiptsJob } from '../../../allocations' -import { validateNetworkIdentifier } from '@graphprotocol/indexer-common' +import { extractProtocolNetworkOption } from '../../../command-helpers' const HELP = ` ${chalk.bold('graph indexer allocations collect')} [options] @@ -12,10 +12,8 @@ ${chalk.bold('graph indexer allocations collect')} [options] ${chalk.dim('Options:')} -h, --help Show usage information + -n, --network The protocol network for this action (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML - -${chalk.dim('Networks:')} - mainnet, arbitrum-one, sepolia or arbitrum sepolia ` module.exports = { @@ -43,7 +41,7 @@ module.exports = { return } - const [network, id] = parameters.array || [] + const [id] = parameters.array || [] if (id === undefined) { spinner.fail(`Missing required argument: 'id'`) @@ -52,24 +50,16 @@ module.exports = { return } - let protocolNetwork: string - if (!network) { - spinner.fail(`Missing required argument: 'network'`) - print.info(HELP) - process.exitCode = 1 - return - } else { - try { - protocolNetwork = validateNetworkIdentifier(network) - } catch (error) { - spinner.fail(`Invalid value for argument 'network': '${network}' `) - process.exitCode = 1 - return - } - } - spinner.text = `Collecting receipts for allocation '${id}` try { + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!protocolNetwork) { + throw new Error( + 'Must provide a network identifier' + `(network: '${protocolNetwork}')`, + ) + } + const config = loadValidatedConfig() const client = await createIndexerManagementClient({ url: config.api }) await submitCollectReceiptsJob(client, id, protocolNetwork) diff --git a/packages/indexer-cli/src/commands/indexer/allocations/create.ts b/packages/indexer-cli/src/commands/indexer/allocations/create.ts index 28244a408..d0d84b5d3 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/create.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/create.ts @@ -4,26 +4,22 @@ import chalk from 'chalk' import { loadValidatedConfig } from '../../../config' import { createIndexerManagementClient } from '../../../client' import { createAllocation } from '../../../allocations' +import { processIdentifier, SubgraphIdentifierType } from '@graphprotocol/indexer-common' import { - processIdentifier, - SubgraphIdentifierType, - validateNetworkIdentifier, -} from '@graphprotocol/indexer-common' -import { printObjectOrArray } from '../../../command-helpers' + extractProtocolNetworkOption, + printObjectOrArray, +} from '../../../command-helpers' const HELP = ` ${chalk.bold( 'graph indexer allocations create', -)} [options] +)} [options] ${chalk.dim('Options:')} -h, --help Show usage information - -f, --force Bypass POI accuracy checks and submit transaction with provided data + -n, --network The protocol network for this action (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML - -${chalk.dim('Networks:')} - mainnet, arbitrum-one, sepolia or arbitrum sepolia ` module.exports = { @@ -51,9 +47,11 @@ module.exports = { return } - const [deploymentID, protocolNetwork, amount, indexNode] = parameters.array || [] + const [deploymentID, amount, indexNode] = parameters.array || [] try { + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + if (!deploymentID || !amount || !protocolNetwork) { throw new Error( 'Must provide a deployment ID, a network identifier and allocation amount' + @@ -61,13 +59,6 @@ module.exports = { ) } - // This nested try block is necessary to complement the parsing error with the 'network' field. - try { - validateNetworkIdentifier(protocolNetwork) - } catch (parsingError) { - throw new Error(`Invalid 'network' provided. ${parsingError}`) - } - const [deploymentString, type] = await processIdentifier(deploymentID, { all: false, global: false, diff --git a/packages/indexer-cli/src/commands/indexer/allocations/get.ts b/packages/indexer-cli/src/commands/indexer/allocations/get.ts index 43f35abe3..fe3b804be 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/get.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/get.ts @@ -18,7 +18,7 @@ ${chalk.bold('graph indexer allocations get')} [options] all ${chalk.dim('Options:')} -h, --help Show usage information - -n, --network Filter allocations by their protocol network (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) + -n, --network Filter allocations by their protocol network (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) --status active|closed|claimable Filter by status --deployment Fetch only allocations for a specific subgraph deployment -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML @@ -44,7 +44,7 @@ module.exports = { } try { - const protocolNetwork = extractProtocolNetworkOption(parameters.options) + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) if (!['json', 'yaml', 'table'].includes(outputFormat)) { throw Error( diff --git a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts index 01e7c5da5..4432b2d81 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts @@ -4,24 +4,28 @@ import chalk from 'chalk' import { loadValidatedConfig } from '../../../config' import { createIndexerManagementClient } from '../../../client' import { reallocateAllocation } from '../../../allocations' -import { printObjectOrArray, validatePOI } from '../../../command-helpers' +import { + extractProtocolNetworkOption, + printObjectOrArray, + validatePOI, +} from '../../../command-helpers' const HELP = ` ${chalk.bold( 'graph indexer allocations reallocate', -)} [options] +)} [options] ${chalk.dim('Options:')} -h, --help Show usage information + -n, --network The protocol network for this action (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) -f, --force Bypass POI accuracy checks and submit transaction with provided data ${chalk.dim('Arguments:')} - The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia - The allocation id to close - The POI to close the allocation with - The block number the POI was computed at - [Horizon] The public POI to close the allocation with. Must be same block height as POI. + The allocation id to close + (optional) The POI to close the allocation with + (optional, horizon only) The block number the POI was computed at. Must be set if POI is provided. + (optional, horizon only) The public POI to close the allocation with. Must be same block height as POI. ` module.exports = { @@ -51,15 +55,7 @@ module.exports = { } // eslint-disable-next-line prefer-const - let [network, id, amount, poi, unformattedBlockNumber, publicPOI] = - parameters.array || [] - - if (network === undefined) { - spinner.fail(`Missing required argument: 'network'`) - print.info(HELP) - process.exitCode = 1 - return - } + let [id, amount, poi, unformattedBlockNumber, publicPOI] = parameters.array || [] if (id === undefined) { spinner.fail(`Missing required argument: 'id'`) @@ -76,6 +72,14 @@ module.exports = { } try { + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!protocolNetwork) { + throw new Error( + 'Must provide a network identifier' + `(network: '${protocolNetwork}')`, + ) + } + validatePOI(poi) validatePOI(publicPOI) const allocationAmount = BigInt(amount) @@ -91,7 +95,7 @@ module.exports = { publicPOI, allocationAmount, toForce, - network, + protocolNetwork, ) spinner.succeed('Reallocated') diff --git a/packages/indexer-common/src/actions.ts b/packages/indexer-common/src/actions.ts index 97bc128f7..ba42e3c0d 100644 --- a/packages/indexer-common/src/actions.ts +++ b/packages/indexer-common/src/actions.ts @@ -20,6 +20,7 @@ export interface ActionItem { reason: string status?: ActionStatus protocolNetwork: string + isLegacy?: boolean } export interface ActionUpdateInput { @@ -27,11 +28,14 @@ export interface ActionUpdateInput { allocationID?: string amount?: string poi?: string + publicPOI?: string + blockNumber?: string force?: boolean type?: ActionType status?: ActionStatus reason?: string protocolNetwork?: string + isLegacy?: boolean } export interface ActionInput { @@ -40,6 +44,8 @@ export interface ActionInput { allocationID?: string amount?: string poi?: string + publicPOI?: string + blockNumber?: string force?: boolean source: string reason: string diff --git a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts index dcdef664d..62a9535a7 100644 --- a/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts +++ b/packages/indexer-common/src/indexer-management/__tests__/helpers.test.ts @@ -360,7 +360,8 @@ describe.skip('Monitor: local', () => { networkMonitor.resolvePOI( mockAllocation, hexlify(new Uint8Array(32).fill(0)), - 0, + undefined, + undefined, true, ), ).resolves.toEqual( @@ -370,7 +371,7 @@ describe.skip('Monitor: local', () => { test('Fail to resolve POI', async () => { await expect( - networkMonitor.resolvePOI(mockAllocation, undefined, 0, false), + networkMonitor.resolvePOI(mockAllocation, undefined, undefined, undefined, false), ).rejects.toEqual(indexerError(IndexerErrorCode.IE018, `Could not resolve POI`)) }) }) diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index 4dd0b8953..ac9ad6fe5 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -32,14 +32,19 @@ import { SubgraphStatus, uniqueAllocationID, upsertIndexingRule, + horizonAllocationIdProof, + isActionFailureArray, } from '@graphprotocol/indexer-common' +import { encodeStartServiceData } from '@graphprotocol/toolshed' import { BigNumberish, BytesLike, + ContractTransaction, hexlify, TransactionReceipt, TransactionRequest, + ZeroAddress, } from 'ethers' import pMap from 'p-map' @@ -91,9 +96,7 @@ export type PopulateTransactionResult = | ActionFailure export type TransactionResult = - | TransactionReceipt - | 'paused' - | 'unauthorized' + | (TransactionReceipt | 'paused' | 'unauthorized')[] | ActionFailure[] export class AllocationManager { @@ -111,10 +114,12 @@ export class AllocationManager { const logger = this.logger.child({ function: 'executeBatch' }) logger.trace('Executing action batch', { actions }) const result = await this.executeTransactions(actions, onFinishedDeploying) - if (Array.isArray(result)) { + + if (isActionFailureArray(result)) { logger.trace('Execute batch transaction failed', { actionBatchResult: result }) return result as ActionFailure[] } + return await this.confirmTransactions(result, actions) } @@ -149,38 +154,110 @@ export class AllocationManager { preparedTransactions: populateTransactionsResults, }) - const callData = populateTransactionsResults + const callDataStakingContract = populateTransactionsResults .flat() .map((tx) => tx as TransactionRequest) + .filter( + (tx: TransactionRequest) => + tx.to === this.network.contracts.HorizonStaking.target, + ) .filter((tx: TransactionRequest) => !!tx.data) .map((tx) => tx.data as string) - logger.trace('Prepared transaction calldata', { callData }) - - return await this.network.transactionManager.executeTransaction( - async () => this.network.contracts.HorizonStaking.multicall.estimateGas(callData), - async (gasLimit) => - this.network.contracts.HorizonStaking.multicall(callData, { gasLimit }), - this.logger.child({ - actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, - function: 'staking.multicall', - }), - ) + logger.debug('Found staking contract transactions', { + count: callDataStakingContract.length, + }) + logger.trace('Prepared staking contract transaction calldata', { + callDataStakingContract, + }) + + const callDataSubgraphService = populateTransactionsResults + .flat() + .map((tx) => tx as TransactionRequest) + .filter( + (tx: TransactionRequest) => + tx.to === this.network.contracts.SubgraphService.target, + ) + .filter((tx: TransactionRequest) => !!tx.data) + .map((tx) => tx.data as string) + logger.debug('Found subgraph service transactions', { + count: callDataSubgraphService.length, + }) + logger.trace('Prepared subgraph service transaction calldata', { + callDataSubgraphService, + }) + + const transactionResults: Promise[] = + [] + if (callDataStakingContract.length > 0) { + const stakingTransaction = this.network.transactionManager.executeTransaction( + async () => + this.network.contracts.HorizonStaking.multicall.estimateGas( + callDataStakingContract, + ), + async (gasLimit) => + this.network.contracts.HorizonStaking.multicall(callDataStakingContract, { + gasLimit, + }), + this.logger.child({ + actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, + function: 'staking.multicall', + }), + ) + transactionResults.push(stakingTransaction) + } + + if (callDataSubgraphService.length > 0) { + const subgraphServiceTransaction = + this.network.transactionManager.executeTransaction( + async () => + this.network.contracts.SubgraphService.multicall.estimateGas( + callDataSubgraphService, + ), + async (gasLimit) => + this.network.contracts.SubgraphService.multicall(callDataSubgraphService, { + gasLimit, + }), + this.logger.child({ + actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, + function: 'subgraphService.multicall', + }), + ) + transactionResults.push(subgraphServiceTransaction) + } + + return await Promise.all(transactionResults) } async confirmTransactions( - receipt: TransactionReceipt | 'paused' | 'unauthorized', + receipts: (TransactionReceipt | 'paused' | 'unauthorized')[], actions: Action[], ): Promise { const logger = this.logger.child({ function: 'confirmTransactions', - receipt, + receipts, actions, }) logger.trace('Confirming transaction') + return pMap( actions, async (action: Action) => { + const receipt = receipts.find( + (receipt) => + (receipt as TransactionReceipt).to === + (action.isLegacy + ? this.network.contracts.HorizonStaking.target + : this.network.contracts.SubgraphService.target), + ) + try { + if (receipt === undefined) { + this.logger.error('No receipt found for action', { + action, + receipts, + }) + throw new Error('No receipt found for action') + } return await this.confirmActionExecution(receipt, action) } catch (error) { let transaction: string | undefined = undefined @@ -417,13 +494,29 @@ export class AllocationManager { // enum AllocationState { Null, Active, Closed, Finalized, Claimed } // // in the contracts. - const state = - await this.network.contracts.HorizonStaking.getAllocationState(allocationId) - if (state !== 0n) { + let allocationExistsSubgraphService = false + let allocationExistsStaking = false + const isHorizon = await this.network.isHorizon.value() + if (isHorizon) { + const allocation = + await this.network.contracts.SubgraphService.getAllocation(allocationId) + const legacyAllocation = + await this.network.contracts.SubgraphService.getLegacyAllocation(allocationId) + allocationExistsSubgraphService = allocation.createdAt !== 0n + allocationExistsStaking = legacyAllocation.indexer !== ZeroAddress + } else { + const state = + await this.network.contracts.LegacyStaking.getAllocationState(allocationId) + allocationExistsStaking = state !== 0n + } + + if (allocationExistsSubgraphService || allocationExistsStaking) { logger.debug(`Skipping allocation as it already exists onchain`, { indexer: this.network.specification.indexerOptions.address, allocation: allocationId, - state, + isHorizon, + allocationExistsSubgraphService, + allocationExistsStaking, }) throw indexerError( IndexerErrorCode.IE066, @@ -437,14 +530,23 @@ export class AllocationManager { indexerAddress: this.network.specification.indexerOptions.address, }) - const proof = await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - allocationId, - ) + const proof = isHorizon + ? await horizonAllocationIdProof( + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + allocationId, + this.network.contracts.SubgraphService.target.toString(), + ) + : await legacyAllocationIdProof( + allocationSigner, + this.network.specification.indexerOptions.address, + allocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, + isLegacy: isHorizon, }) return { @@ -465,7 +567,11 @@ export class AllocationManager { ): Promise { const logger = this.logger.child({ action: actionID }) const subgraphDeployment = new SubgraphDeploymentID(deployment) - logger.info(`Confirming 'allocateFrom' transaction`) + const isLegacy = + (receipt as TransactionReceipt).to === this.network.contracts.HorizonStaking.target + logger.info(`Confirming allocation creation transaction`, { + isLegacy, + }) if (receipt === 'paused' || receipt === 'unauthorized') { throw indexerError( IndexerErrorCode.IE062, @@ -476,14 +582,23 @@ export class AllocationManager { ) } - const createAllocationEventLogs = this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - subgraphDeployment.bytes32, - receipt, - this.logger, - ) + const createAllocationEventLogs = isLegacy + ? this.network.transactionManager.findEvent( + 'AllocationCreated', + this.network.contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + subgraphDeployment.bytes32, + receipt, + this.logger, + ) + : this.network.transactionManager.findEvent( + 'ServiceStarted', + this.network.contracts.SubgraphService.interface, + 'serviceProvider', + this.network.specification.indexerOptions.address, + receipt, + logger, + ) if (!createAllocationEventLogs) { throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) @@ -494,6 +609,7 @@ export class AllocationManager { allocation: createAllocationEventLogs.allocationID, deployment: createAllocationEventLogs.subgraphDeploymentID, epoch: createAllocationEventLogs.epoch.toString(), + isLegacy, }) const subgraphDeploymentID = new SubgraphDeploymentID(deployment) @@ -530,23 +646,42 @@ export class AllocationManager { deployment: SubgraphDeploymentID, amount: bigint, ): Promise { + const isHorizon = await this.network.isHorizon.value() const params = await this.prepareAllocateParams(logger, context, deployment, amount) - logger.debug(`Populating allocateFrom transaction`, { + logger.debug(`Populating allocation creation transaction`, { indexer: params.indexer, subgraphDeployment: params.subgraphDeploymentID, amount: formatGRT(params.tokens), allocation: params.allocationID, proof: params.proof, + isLegacy: isHorizon, }) - // TODO HORIZON: split into pre-post horizon - return await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( - params.indexer, - params.subgraphDeploymentID, - params.tokens, - params.allocationID, - params.metadata, - params.proof, - ) + + let populatedTransaction: ContractTransaction + if (isHorizon) { + const encodedData = encodeStartServiceData( + params.subgraphDeploymentID.toString(), + BigInt(params.tokens), + params.allocationID, + params.proof.toString(), + ) + populatedTransaction = + await this.network.contracts.SubgraphService.startService.populateTransaction( + params.indexer, + encodedData, + ) + } else { + populatedTransaction = + await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( + params.indexer, + params.subgraphDeploymentID, + params.tokens, + params.allocationID, + params.metadata, + params.proof, + ) + } + return populatedTransaction } async prepareUnallocateParams( @@ -562,12 +697,14 @@ export class AllocationManager { }) const allocation = await this.network.networkMonitor.allocation(allocationID) - ;[poi] = await this.network.networkMonitor.resolvePOI( + const poiData = await this.network.networkMonitor.resolvePOI( allocation, poi, undefined, + undefined, force, ) + poi = poiData.poi // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. @@ -743,10 +880,11 @@ export class AllocationManager { allocation: allocationID, deployment: allocation.subgraphDeployment.id.ipfsHash, }) - const [allocationPOI] = await this.network.networkMonitor.resolvePOI( + const { poi: allocationPOI } = await this.network.networkMonitor.resolvePOI( allocation, poi, undefined, + undefined, force, ) logger.debug('POI resolved', { @@ -1073,39 +1211,27 @@ export class AllocationManager { const logger = this.logger.child({ function: 'validateActionBatch' }) logger.debug(`Validating action batch`, { size: batch.length }) - // Validate stake feasibility - let indexerFreeStake = 0n - if (await this.network.isHorizon.value()) { - const verifier = this.network.contracts.SubgraphService.target.toString() - const delegationRatio = - await this.network.contracts.SubgraphService.getDelegationRatio() - const tokensAvailable = - await this.network.contracts.HorizonStaking.getTokensAvailable( - this.network.specification.indexerOptions.address, - verifier, - delegationRatio, - ) - const lockedStake = - await this.network.contracts.SubgraphService.allocationProvisionTracker( - this.network.specification.indexerOptions.address, - ) - indexerFreeStake = - tokensAvailable > lockedStake ? tokensAvailable - lockedStake : 0n - } else { - indexerFreeStake = await this.network.contracts.LegacyStaking.getIndexerCapacity( - this.network.specification.indexerOptions.address, - ) - } + // Validate stake feasibility - we need to analyse stake depending on the action type + const indexerFreeStake = await this.network.networkMonitor.freeStake() + const actionsBatchStakeUsageSummaries = await pMap(batch, async (action: Action) => this.stakeUsageSummary(action), ) + const batchDeltaLegacy = actionsBatchStakeUsageSummaries + .filter((summary: ActionStakeUsageSummary) => summary.action.isLegacy) + .map((summary: ActionStakeUsageSummary) => summary.balance) + .reduce((a: bigint, b: bigint) => a + b, 0n) const batchDelta = actionsBatchStakeUsageSummaries + .filter((summary: ActionStakeUsageSummary) => !summary.action.isLegacy) .map((summary: ActionStakeUsageSummary) => summary.balance) - .reduce((a: bigint, b: bigint) => a + b) - const indexerNewBalance = indexerFreeStake - batchDelta + .reduce((a: bigint, b: bigint) => a + b, 0n) + + const indexerNewBalance = indexerFreeStake.horizon - batchDelta + const indexerNewBalanceLegacy = indexerFreeStake.legacy - batchDeltaLegacy logger.trace('Action batch stake usage summary', { indexerFreeStake: indexerFreeStake.toString(), + indexerFreeStakeLegacy: indexerFreeStake.legacy.toString(), actionsBatchStakeUsageSummaries: actionsBatchStakeUsageSummaries.map((summary) => { return { action: summary.action, @@ -1116,16 +1242,20 @@ export class AllocationManager { } }), batchDelta: batchDelta.toString(), + batchDeltaLegacy: batchDeltaLegacy.toString(), indexerNewBalance: indexerNewBalance.toString(), + indexerNewBalanceLegacy: indexerNewBalanceLegacy.toString(), }) - if (indexerNewBalance < 0n) { + if (indexerNewBalance < 0n || indexerNewBalanceLegacy < 0n) { { throw indexerError( IndexerErrorCode.IE013, `Unfeasible action batch: Approved action batch GRT balance is ` + - `${formatGRT(batchDelta)} ` + - `but available stake equals ${formatGRT(indexerFreeStake)}.`, + `${formatGRT(batchDelta)} for horizon actions and ` + + `${formatGRT(batchDeltaLegacy)} for legacy actions ` + + `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + + `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, ) } } diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index 420d10413..dc9d8c2ed 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-case-declarations */ import { Allocation, AllocationStatus, @@ -21,7 +22,7 @@ import { HorizonTransitionValue, Provision, parseGraphQLProvision, - POIMetadata, + POIData, IndexingStatusCode, } from '@graphprotocol/indexer-common' import { @@ -37,7 +38,7 @@ import { toAddress, formatGRT, } from '@graphprotocol/common-ts' -import { ethers, HDNodeWallet, hexlify, Provider } from 'ethers' +import { HDNodeWallet, hexlify, Provider, ZeroAddress } from 'ethers' import gql from 'graphql-tag' import pRetry, { Options } from 'p-retry' import { IndexerOptions } from '../network-specification' @@ -105,12 +106,16 @@ export class NetworkMonitor { * Returns the amount of free stake for the indexer. * * The free stake is the amount of tokens that the indexer can use to stake in - * new allocations. It's calculated as the difference between the tokens + * new allocations. + * + * Horizon: It's calculated as the difference between the tokens * available in the provision and the tokens already locked allocations. * + * Legacy: It's given by the indexer's stake capacity. + * * @returns The amount of free stake for the indexer. */ - async freeStake(): Promise { + async freeStake(): Promise> { const isHorizon = await this.isHorizon() if (isHorizon) { @@ -124,9 +129,19 @@ export class NetworkMonitor { ) const lockedStake = await this.contracts.SubgraphService.allocationProvisionTracker(address) - return tokensAvailable > lockedStake ? tokensAvailable - lockedStake : 0n + const freeStake = tokensAvailable > lockedStake ? tokensAvailable - lockedStake : 0n + + return { + legacy: 0n, // In horizon new legacy allocations cannot be created so we return 0 + horizon: freeStake, + } } else { - return 0n + return { + legacy: await this.contracts.LegacyStaking.getIndexerCapacity( + this.indexerOptions.address, + ), + horizon: 0n, + } } } @@ -1038,57 +1053,45 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n async resolvePOI( allocation: Allocation, poi: string | undefined, - blockNumber: number | undefined, - force: boolean, - ): Promise<[string, number]> { - return this._resolvePOI( - allocation, - poi, - blockNumber, - force, - allocation.indexer.toString(), - ) - } - - async resolvePOIMetadata( - allocation: Allocation, publicPOI: string | undefined, blockNumber: number | undefined, force: boolean, - ): Promise { - ;[publicPOI, blockNumber] = await this._resolvePOI( + ): Promise { + const [resolvedPOI, resolvedPOIBlockNumber] = await this._resolvePOI( allocation, - publicPOI, - blockNumber, + poi, force, - ethers.ZeroAddress, ) - const indexingStatus = await this.graphNode.indexingStatus([ - allocation.subgraphDeployment.id, - ]) - let indexingStatusCode = IndexingStatusCode.Unknown - if (indexingStatus.length === 1) { - switch (indexingStatus[0].health) { - case 'healthy': - indexingStatusCode = IndexingStatusCode.Healthy - break - case 'unhealthy': - indexingStatusCode = IndexingStatusCode.Unhealthy - break - case 'failed': - indexingStatusCode = IndexingStatusCode.Failed - break - default: - indexingStatusCode = IndexingStatusCode.Unknown - break + if (allocation.isLegacy) { + return { + poi: resolvedPOI, + publicPOI: hexlify(new Uint8Array(32).fill(0)), + blockNumber: 0, + indexingStatus: IndexingStatusCode.Unknown, } - } + } else { + const resolvedBlockNumber = await this._resolvePOIBlockNumber( + blockNumber, + resolvedPOIBlockNumber, + force, + ) + const resolvedPublicPOI = await this._resolvePublicPOI( + allocation, + publicPOI, + resolvedBlockNumber, + force, + ) + const resolvedIndexingStatus = await this._resolveIndexingStatus( + allocation.subgraphDeployment.id, + ) - return { - publicPOI, - blockNumber, - indexingStatus: indexingStatusCode, + return { + poi: resolvedPOI, + publicPOI: resolvedPublicPOI, + blockNumber: resolvedBlockNumber, + indexingStatus: resolvedIndexingStatus, + } } } @@ -1481,12 +1484,13 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n } } + // Returns a tuple of [POI, blockNumber] + // - POI is the POI to submit, which could be user provider or generated + // - blockNumber is the block number of the POI. If it's 0 then the block number is not known at this point. private async _resolvePOI( allocation: Allocation, poi: string | undefined, - blockNumber: number | undefined, force: boolean, - address: string, ): Promise<[string, number]> { // If the network is not supported, we can't resolve POI, as there will be no active epoch const supportedNetworkAlias = await this.allocationNetworkAlias(allocation) @@ -1503,22 +1507,32 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n case true: switch (!!poi) { case true: + this.logger.trace('Resolve POI: Force true, poi defined', { + poi, + blockNumber: 0, + }) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return [poi!, blockNumber!] + return [poi!, 0] case false: - // eslint-disable-next-line no-case-declarations const poiBlockNumber = await this.fetchPOIBlockPointer( supportedNetworkAlias, allocation, ) - return [ - (await this.graphNode.proofOfIndexing( - allocation.subgraphDeployment.id, - poiBlockNumber, - address, - )) || hexlify(new Uint8Array(32).fill(0)), - poiBlockNumber.number, - ] + const generatedPOI = await this.graphNode.proofOfIndexing( + allocation.subgraphDeployment.id, + poiBlockNumber, + allocation.indexer, + ) + const returnValue: [string, number] = + generatedPOI !== undefined + ? [generatedPOI, poiBlockNumber.number] + : [hexlify(new Uint8Array(32).fill(0)), 0] + + this.logger.trace('Resolve POI: Force true, poi undefined', { + poi: returnValue[0], + blockNumber: returnValue[1], + }) + return returnValue } break case false: { @@ -1530,11 +1544,15 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n const generatedPOI = await this.graphNode.proofOfIndexing( allocation.subgraphDeployment.id, epochStartBlock, - address, + allocation.indexer, ) - switch (poi == generatedPOI && blockNumber == epochStartBlock.number) { + switch (poi == generatedPOI) { case true: - if (poi == undefined || blockNumber == undefined) { + this.logger.trace('Resolve POI: Force false, poi matches generated', { + poi, + blockNumber: epochStartBlock.number, + }) + if (poi == undefined) { const deploymentStatus = await this.graphNode.indexingStatus([ allocation.subgraphDeployment.id, ]) @@ -1549,17 +1567,18 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n }`, ) } else { - return [poi, blockNumber] + return [poi, epochStartBlock.number] } case false: + this.logger.trace('Resolve POI: Force false, poi does not match generated', { + poi, + generatedPOI, + blockNumber: epochStartBlock.number, + }) if (poi == undefined && generatedPOI !== undefined) { return [generatedPOI, epochStartBlock.number] - } else if ( - poi !== undefined && - blockNumber !== undefined && - generatedPOI == undefined - ) { - return [poi, blockNumber] + } else if (poi !== undefined && generatedPOI == undefined) { + return [poi, 0] } throw indexerError( IndexerErrorCode.IE068, @@ -1571,4 +1590,98 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n } } } + + private async _resolvePOIBlockNumber( + blockNumber: number | undefined, + generatedPOIBlockNumber: number, + force: boolean, + ): Promise { + let returnBlockNumber = 0 + if (generatedPOIBlockNumber === 0) { + if (blockNumber === undefined) { + throw indexerError(IndexerErrorCode.IE067, 'Could not resolve POI block number') + } + returnBlockNumber = blockNumber + } else if (blockNumber === undefined || generatedPOIBlockNumber === blockNumber) { + returnBlockNumber = generatedPOIBlockNumber + } else { + returnBlockNumber = force ? blockNumber : generatedPOIBlockNumber + } + + this.logger.trace('Resolve POI block number:', { + blockNumber, + generatedPOIBlockNumber, + returnBlockNumber, + force, + }) + + return returnBlockNumber + } + + private async _resolvePublicPOI( + allocation: Allocation, + publicPOI: string | undefined, + blockNumber: number, + force: boolean, + ): Promise { + const blockHash = await this.graphNode.blockHashFromNumber( + resolveChainAlias(this.networkCAIPID), + blockNumber, + ) + const generatedPublicPOI = await this.graphNode.proofOfIndexing( + allocation.subgraphDeployment.id, + { + number: blockNumber, + hash: blockHash, + }, + ZeroAddress, + ) + + let returnPublicPOI: string + if (generatedPublicPOI === undefined) { + if (publicPOI === undefined) { + throw indexerError(IndexerErrorCode.IE067, 'Could not resolve public POI') + } + returnPublicPOI = publicPOI + } else if (publicPOI === undefined || generatedPublicPOI === publicPOI) { + returnPublicPOI = generatedPublicPOI + } else { + returnPublicPOI = force ? publicPOI : generatedPublicPOI + } + + this.logger.trace('Resolve public POI:', { + blockNumber, + publicPOI, + generatedPublicPOI, + returnPublicPOI, + force, + }) + + return returnPublicPOI + } + + private async _resolveIndexingStatus( + deployment: SubgraphDeploymentID, + ): Promise { + const indexingStatus = await this.graphNode.indexingStatus([deployment]) + + let indexingStatusCode = IndexingStatusCode.Unknown + if (indexingStatus.length === 1) { + switch (indexingStatus[0].health) { + case 'healthy': + indexingStatusCode = IndexingStatusCode.Healthy + break + case 'unhealthy': + indexingStatusCode = IndexingStatusCode.Unhealthy + break + case 'failed': + indexingStatusCode = IndexingStatusCode.Failed + break + default: + indexingStatusCode = IndexingStatusCode.Unknown + break + } + } + return indexingStatusCode + } } diff --git a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts index 6f998860b..6c6956ccc 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts @@ -3,7 +3,7 @@ import pMap from 'p-map' import gql from 'graphql-tag' -import { ethers, hexlify } from 'ethers' +import { ethers, hexlify, ZeroAddress } from 'ethers' import { Address, @@ -28,7 +28,7 @@ import { IndexingRuleAttributes, legacyAllocationIdProof, Network, - POIMetadata, + POIData, ReallocateAllocationResult, SubgraphClient, SubgraphIdentifierType, @@ -489,7 +489,7 @@ async function createHorizonAllocation( const dataService = contracts.SubgraphService.target.toString() // Identify how many GRT the indexer has staked - const freeStake = await network.networkMonitor.freeStake() + const freeStake = (await network.networkMonitor.freeStake()).horizon // If there isn't enough left for allocating, abort if (freeStake < allocationAmount) { @@ -535,10 +535,16 @@ async function createHorizonAllocation( // Double-check whether the allocationID already exists on chain, to // avoid unnecessary transactions. const allocation = await contracts.SubgraphService.getAllocation(allocationId) - if (allocation.createdAt !== 0n) { + const legacyAllocation = + await contracts.SubgraphService.getLegacyAllocation(allocationId) + const existsSubgraphService = allocation.createdAt !== 0n + const existsLegacyAllocation = legacyAllocation.indexer !== ZeroAddress + if (existsSubgraphService || existsLegacyAllocation) { logger.debug(`Skipping allocation as it already exists onchain`, { indexer: address, allocation: allocationId, + existsSubgraphService, + existsLegacyAllocation, }) throw indexerError( IndexerErrorCode.IE066, @@ -712,8 +718,7 @@ async function closeLegacyAllocation( async function closeHorizonAllocation( allocation: Allocation, - poi: string, - poiMetadata: POIMetadata, + poiData: POIData, network: Network, logger: Logger, ): Promise<{ txHash: string; rewardsAssigned: bigint }> { @@ -730,15 +735,15 @@ async function closeHorizonAllocation( } const encodedPOIMetadata = encodePOIMetadata( - poiMetadata.blockNumber, - poiMetadata.publicPOI, - poiMetadata.indexingStatus, + poiData.blockNumber, + poiData.publicPOI, + poiData.indexingStatus, 0, 0, ) const collectIndexingRewardsData = encodeCollectIndexingRewardsData( allocation.id, - poi, + poiData.poi, encodedPOIMetadata, ) @@ -820,7 +825,9 @@ async function closeHorizonAllocation( allocation: allocation.id, indexer: allocationStateAfter.indexer, amountGRT: formatGRT(allocationStateAfter.tokens), - poi: poi, + poi: poiData.poi, + blockNumber: poiData.blockNumber, + publicPOI: poiData.publicPOI, epoch: currentEpoch.toString(), transaction: receipt.hash, indexingRewards: rewardsAssigned, @@ -879,7 +886,7 @@ async function reallocateLegacyAllocation( }) // Identify how many GRT the indexer has staked - const freeStake = await contracts.LegacyStaking.getIndexerCapacity(address) + const freeStake = (await network.networkMonitor.freeStake()).legacy // When reallocating, we will first close the old allocation and free up the GRT in that allocation // This GRT will be available in addition to freeStake for the new allocation @@ -1053,8 +1060,7 @@ async function reallocateHorizonAllocation( allocation: Allocation, allocationAmount: bigint, activeAllocations: Allocation[], - poi: string, - poiMetadata: POIMetadata, + poiData: POIData, network: Network, logger: Logger, ): Promise<{ txHash: string; rewardsAssigned: bigint; newAllocationId: Address }> { @@ -1067,6 +1073,21 @@ async function reallocateHorizonAllocation( // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. const allocationData = await contracts.SubgraphService.getAllocation(allocation.id) + const legacyAllocation = await contracts.SubgraphService.getLegacyAllocation( + allocation.id, + ) + const existsSubgraphService = allocationData.createdAt !== 0n + const existsLegacyAllocation = legacyAllocation.indexer !== ZeroAddress + if (existsSubgraphService || existsLegacyAllocation) { + logger.warn(`Skipping allocation as it already exists onchain`, { + indexer: address, + allocation: allocation.id, + existsSubgraphService, + existsLegacyAllocation, + }) + throw indexerError(IndexerErrorCode.IE066, 'AllocationID already exists') + } + if (allocationData.closedAt !== 0n) { logger.warn(`Allocation has already been closed`) throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) @@ -1089,7 +1110,7 @@ async function reallocateHorizonAllocation( }) // Identify how many GRT the indexer has staked - const freeStake = await network.networkMonitor.freeStake() + const freeStake = (await network.networkMonitor.freeStake()).horizon // When reallocating, we will first close the old allocation and free up the GRT in that allocation // This GRT will be available in addition to freeStake for the new allocation @@ -1164,21 +1185,21 @@ async function reallocateHorizonAllocation( newAllocation: newAllocationId, newAllocationAmount: formatGRT(allocationAmount), deployment: allocation.subgraphDeployment.id.toString(), - poi: poi, + poi: poiData.poi, proof, epoch: currentEpoch.toString(), }) const encodedPOIMetadata = encodePOIMetadata( - poiMetadata.blockNumber, - poiMetadata.publicPOI, - poiMetadata.indexingStatus, + poiData.blockNumber, + poiData.publicPOI, + poiData.indexingStatus, 0, 0, ) const collectIndexingRewardsData = encodeCollectIndexingRewardsData( allocation.id, - poi, + poiData.poi, encodedPOIMetadata, ) const closeAllocationData = ethers.AbiCoder.defaultAbiCoder().encode( @@ -1288,7 +1309,7 @@ async function reallocateHorizonAllocation( deployment: createAllocationEventLogs.subgraphDeploymentID, closedAllocation: allocation.id, closedAllocationStakeGRT: formatGRT(allocation.allocatedTokens), - closedAllocationPOI: poi, + closedAllocationPOI: poiData.poi, closedAllocationEpoch: currentEpoch.toString(), indexingRewardsCollected: rewardsAssigned, createdAllocation: newAllocationId, @@ -1549,7 +1570,7 @@ export default { }: { allocation: string poi: string | undefined - blockNumber: number | string | undefined + blockNumber: string | undefined publicPOI: string | undefined force: boolean protocolNetwork: string @@ -1572,34 +1593,38 @@ export default { const allocationData = await networkMonitor.allocation(allocation) try { - ;[poi, blockNumber] = await networkMonitor.resolvePOI( + logger.debug('Resolving POI') + const poiData = await networkMonitor.resolvePOI( allocationData, poi, - Number(blockNumber), + allocationData.isLegacy ? undefined : publicPOI, + allocationData.isLegacy || blockNumber === null ? undefined : Number(blockNumber), force, ) logger.debug('POI resolved', { - poi: poi, - blockNumber: blockNumber, + userProvidedPOI: poi, + userProvidedBlockNumber: blockNumber, + poi: poiData.poi, + publicPOI: poiData.publicPOI, + blockNumber: poiData.blockNumber, + force, }) let txHash: string let rewardsAssigned: bigint if (allocationData.isLegacy) { - const result = await closeLegacyAllocation(allocationData, poi, network, logger) + const result = await closeLegacyAllocation( + allocationData, + poiData.poi, + network, + logger, + ) txHash = result.txHash rewardsAssigned = result.rewardsAssigned } else { - const poiMetadata = await networkMonitor.resolvePOIMetadata( - allocationData, - publicPOI, - blockNumber, - force, - ) const result = await closeHorizonAllocation( allocationData, - poi, - poiMetadata, + poiData, network, logger, ) @@ -1655,7 +1680,7 @@ export default { }: { allocation: string poi: string | undefined - blockNumber: number | string | undefined + blockNumber: string | undefined publicPOI: string | undefined amount: string force: boolean @@ -1702,15 +1727,20 @@ export default { try { logger.debug('Resolving POI') - const [allocationPOI] = await networkMonitor.resolvePOI( + const poiData = await networkMonitor.resolvePOI( allocationData, poi, - Number(blockNumber), + allocationData.isLegacy ? undefined : publicPOI, + allocationData.isLegacy || blockNumber === null ? undefined : Number(blockNumber), force, ) logger.debug('POI resolved', { userProvidedPOI: poi, - poi: allocationPOI, + userProvidedBlockNumber: blockNumber, + poi: poiData.poi, + publicPOI: poiData.publicPOI, + blockNumber: poiData.blockNumber, + force, }) const isHorizon = await network.isHorizon.value() @@ -1723,7 +1753,7 @@ export default { allocationData, allocationAmount, activeAllocations, - allocationPOI, + poiData.poi, network, logger, ) @@ -1735,7 +1765,7 @@ export default { allocationData, allocationAmount, activeAllocations, - allocationPOI, + poiData.poi, network, graphNode, logger, @@ -1744,18 +1774,11 @@ export default { rewardsAssigned = result.rewardsAssigned newAllocationId = result.newAllocationId } else { - const poiMetadata = await networkMonitor.resolvePOIMetadata( - allocationData, - publicPOI, - Number(blockNumber), - force, - ) const result = await reallocateHorizonAllocation( allocationData, allocationAmount, activeAllocations, - allocationPOI, - poiMetadata, + poiData, network, logger, ) diff --git a/packages/indexer-common/src/indexer-management/types.ts b/packages/indexer-common/src/indexer-management/types.ts index 3b023cf61..b76b19899 100644 --- a/packages/indexer-common/src/indexer-management/types.ts +++ b/packages/indexer-common/src/indexer-management/types.ts @@ -58,6 +58,11 @@ export interface ActionFailure { export const isActionFailure = (variableToCheck: any): variableToCheck is ActionFailure => 'failureReason' in variableToCheck +export const isActionFailureArray = ( + variableToCheck: any, +): variableToCheck is ActionFailure[] => + Array.isArray(variableToCheck) && variableToCheck.every(isActionFailure) + export type AllocationResult = | CreateAllocationResult | CloseAllocationResult @@ -374,7 +379,8 @@ export enum IndexingStatusCode { Failed = 3, } -export interface POIMetadata { +export interface POIData { + poi: string publicPOI: string blockNumber: number indexingStatus: IndexingStatusCode diff --git a/packages/indexer-common/src/operator.ts b/packages/indexer-common/src/operator.ts index 8f6c49323..b83c2ba1e 100644 --- a/packages/indexer-common/src/operator.ts +++ b/packages/indexer-common/src/operator.ts @@ -244,6 +244,8 @@ export class Operator { transaction status failureReason + protocolNetwork + isLegacy } } `, @@ -278,6 +280,7 @@ export class Operator { reason: action.reason, priority: 0, protocolNetwork: action.protocolNetwork, + isLegacy: action.isLegacy, } this.logger.trace(`Queueing action input`, { actionInput, @@ -295,6 +298,7 @@ export class Operator { priority status protocolNetwork + isLegacy } } `, @@ -314,6 +318,11 @@ export class Operator { `Action not queued: A recently executed action was found targeting ${actionInput.deploymentID}`, { action }, ) + } else { + this.logger.warn('Action not queued', { + action, + error: actionResult.error, + }) } return [] } @@ -336,6 +345,7 @@ export class Operator { logger: Logger, deploymentAllocationDecision: AllocationDecision, mostRecentlyClosedAllocation: Allocation | undefined, + isHorizon: boolean, ): Promise { const desiredAllocationAmount = deploymentAllocationDecision.ruleMatch.rule ?.allocationAmount @@ -344,6 +354,7 @@ export class Operator { logger.info(`No active allocation for deployment, creating one now`, { allocationAmount: formatGRT(desiredAllocationAmount), + isHorizon, }) // Skip allocating if the previous allocation for this deployment was closed with 0x00 POI but rules set to un-safe @@ -363,7 +374,7 @@ export class Operator { return } - // Send AllocateAction to the queue + // Send AllocateAction to the queue - isLegacy value depends on the horizon upgrade await this.queueAction({ params: { deploymentID: deploymentAllocationDecision.deployment.ipfsHash, @@ -372,6 +383,7 @@ export class Operator { type: ActionType.ALLOCATE, reason: deploymentAllocationDecision.reasonString(), protocolNetwork: deploymentAllocationDecision.protocolNetwork, + isLegacy: !isHorizon, }) return @@ -382,27 +394,24 @@ export class Operator { deploymentAllocationDecision: AllocationDecision, activeDeploymentAllocations: Allocation[], ): Promise { - const activeDeploymentAllocationsEligibleForClose = activeDeploymentAllocations.map( - (allocation) => allocation.id, - ) // Make sure to close all active allocations on the way out - if (activeDeploymentAllocationsEligibleForClose.length > 0) { + if (activeDeploymentAllocations.length > 0) { logger.info( `Deployment is not (or no longer) worth allocating towards, close allocations`, { - eligibleForClose: activeDeploymentAllocationsEligibleForClose, + eligibleForClose: activeDeploymentAllocations, reason: deploymentAllocationDecision.reasonString(), }, ) await pMap( // We can only close allocations from a previous epoch; // try the others again later - activeDeploymentAllocationsEligibleForClose, + activeDeploymentAllocations, async (allocation) => { - // Send unallocate action to the queue + // Send unallocate action to the queue - isLegacy value depends on the allocation being closed await this.queueAction({ params: { - allocationID: allocation, + allocationID: allocation.id, deploymentID: deploymentAllocationDecision.deployment.ipfsHash, poi: undefined, force: false, @@ -410,6 +419,7 @@ export class Operator { type: ActionType.UNALLOCATE, reason: deploymentAllocationDecision.reasonString(), protocolNetwork: deploymentAllocationDecision.protocolNetwork, + isLegacy: allocation.isLegacy, } as ActionItem) }, { concurrency: 1 }, @@ -434,6 +444,7 @@ export class Operator { : this.specification.indexerOptions.defaultAllocationAmount // Queue reallocate actions to be picked up by the worker + // isLegacy value depends on the allocation being reallocated, the switch to horizon is done by changing the allocation type elsewhere await pMap( expiredAllocations, async (allocation) => { @@ -446,6 +457,7 @@ export class Operator { type: ActionType.REALLOCATE, reason: `${deploymentAllocationDecision.reasonString()}:allocationExpiring`, // Need to update to include 'ExpiringSoon' protocolNetwork: deploymentAllocationDecision.protocolNetwork, + isLegacy: allocation.isLegacy, }) }, { From 606a8e7b2eed3b6bb6977c263e5b394c429e8a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 9 Jun 2025 10:14:48 -0300 Subject: [PATCH 10/28] fix: allocation cli bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../indexer/allocations/reallocate.ts | 1 + packages/indexer-common/src/errors.ts | 4 ++ .../src/indexer-management/monitor.ts | 14 ++--- .../resolvers/allocations.ts | 55 +++++++++++-------- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts index 4432b2d81..c7cac4b98 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts @@ -23,6 +23,7 @@ ${chalk.dim('Options:')} ${chalk.dim('Arguments:')} The allocation id to close + The amount of GRT to reallocate (optional) The POI to close the allocation with (optional, horizon only) The block number the POI was computed at. Must be set if POI is provided. (optional, horizon only) The public POI to close the allocation with. Must be same block height as POI. diff --git a/packages/indexer-common/src/errors.ts b/packages/indexer-common/src/errors.ts index 5c69e714d..dd4c518d7 100644 --- a/packages/indexer-common/src/errors.ts +++ b/packages/indexer-common/src/errors.ts @@ -94,6 +94,8 @@ export enum IndexerErrorCode { IE081 = 'IE081', IE082 = 'IE082', IE083 = 'IE083', + IE084 = 'IE084', + IE085 = 'IE085', } export const INDEXER_ERROR_MESSAGES: Record = { @@ -181,6 +183,8 @@ export const INDEXER_ERROR_MESSAGES: Record = { IE081: 'Multiple provisions found', IE082: 'Graph Horizon protocol not detected', IE083: 'Failed to thaw stake from provision', + IE084: 'Could not resolve POI block number', + IE085: 'Could not resolve public POI', } export type IndexerErrorCause = unknown diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index dc9d8c2ed..89e2d689b 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -56,7 +56,7 @@ export class NetworkMonitor { private networkSubgraph: SubgraphClient, private ethereum: Provider, private epochSubgraph: SubgraphClient, - ) {} + ) { } poiDisputeMonitoringEnabled(): boolean { return this.indexerOptions.poiDisputeMonitoring @@ -285,8 +285,7 @@ export class NetworkMonitor { if (allocations.length === 0) { this.logger.warn( - `No ${ - AllocationStatus[status.toUpperCase() as keyof typeof AllocationStatus] + `No ${AllocationStatus[status.toUpperCase() as keyof typeof AllocationStatus] } allocations found for indexer '${this.indexerOptions.address}'`, ) } @@ -1560,11 +1559,10 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n IndexerErrorCode.IE067, `POI not available for deployment at current epoch start block. currentEpochStartBlock: ${epochStartBlock.number} - deploymentStatus: ${ - deploymentStatus.length > 0 + deploymentStatus: ${deploymentStatus.length > 0 ? JSON.stringify(deploymentStatus) : 'not deployed' - }`, + }`, ) } else { return [poi, epochStartBlock.number] @@ -1599,7 +1597,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n let returnBlockNumber = 0 if (generatedPOIBlockNumber === 0) { if (blockNumber === undefined) { - throw indexerError(IndexerErrorCode.IE067, 'Could not resolve POI block number') + throw indexerError(IndexerErrorCode.IE084, 'No block number generated and none provided') } returnBlockNumber = blockNumber } else if (blockNumber === undefined || generatedPOIBlockNumber === blockNumber) { @@ -1640,7 +1638,7 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n let returnPublicPOI: string if (generatedPublicPOI === undefined) { if (publicPOI === undefined) { - throw indexerError(IndexerErrorCode.IE067, 'Could not resolve public POI') + throw indexerError(IndexerErrorCode.IE085, 'No public POI generated and none provided') } returnPublicPOI = publicPOI } else if (publicPOI === undefined || generatedPublicPOI === publicPOI) { diff --git a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts index 6c6956ccc..9f8ee48ea 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts @@ -803,8 +803,8 @@ async function closeHorizonAllocation( const closeAllocationEventLogs = transactionManager.findEvent( 'ServiceStopped', contracts.SubgraphService.interface, - 'data', - closeAllocationData, + 'serviceProvider', + address, receipt, logger, ) @@ -840,6 +840,7 @@ async function closeHorizonAllocation( return { txHash: receipt.hash, rewardsAssigned } } +// isHorizon: false async function reallocateLegacyAllocation( allocation: Allocation, allocationAmount: bigint, @@ -1056,6 +1057,7 @@ async function reallocateLegacyAllocation( return { txHash: receipt.hash, rewardsAssigned, newAllocationId } } +// isHorizon: true and allocation: not legacy async function reallocateHorizonAllocation( allocation: Allocation, allocationAmount: bigint, @@ -1073,20 +1075,6 @@ async function reallocateHorizonAllocation( // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. const allocationData = await contracts.SubgraphService.getAllocation(allocation.id) - const legacyAllocation = await contracts.SubgraphService.getLegacyAllocation( - allocation.id, - ) - const existsSubgraphService = allocationData.createdAt !== 0n - const existsLegacyAllocation = legacyAllocation.indexer !== ZeroAddress - if (existsSubgraphService || existsLegacyAllocation) { - logger.warn(`Skipping allocation as it already exists onchain`, { - indexer: address, - allocation: allocation.id, - existsSubgraphService, - existsLegacyAllocation, - }) - throw indexerError(IndexerErrorCode.IE066, 'AllocationID already exists') - } if (allocationData.closedAt !== 0n) { logger.warn(`Allocation has already been closed`) @@ -1254,8 +1242,8 @@ async function reallocateHorizonAllocation( const createAllocationEventLogs = network.transactionManager.findEvent( 'ServiceStarted', network.contracts.SubgraphService.interface, - 'data', - createAllocationData, + 'serviceProvider', + address, receipt, logger, ) @@ -1292,8 +1280,8 @@ async function reallocateHorizonAllocation( const closeAllocationEventLogs = transactionManager.findEvent( 'ServiceStopped', contracts.SubgraphService.interface, - 'data', - closeAllocationData, + 'serviceProvider', + address, receipt, logger, ) @@ -1322,6 +1310,7 @@ async function reallocateHorizonAllocation( return { txHash: receipt.hash, rewardsAssigned, newAllocationId } } +// isHorizon: true and allocation: legacy async function migrateLegacyAllocationToHorizon( allocation: Allocation, allocationAmount: bigint, @@ -1487,11 +1476,16 @@ export default { try { const currentEpoch = await network.contracts.EpochManager.currentEpoch() + const isHorizon = await network.isHorizon.value() + + logger.debug('createAllocation: Checking allocation resolution path', { + isHorizon, + }) let txHash: string let allocationId: Address - if (await network.isHorizon.value()) { - logger.info('Creating horizon allocation') + if (isHorizon) { + logger.debug('Creating horizon allocation') const result = await createHorizonAllocation( network, graphNode, @@ -1505,6 +1499,7 @@ export default { txHash = result.txHash allocationId = result.allocationId } else { + logger.debug('Creating legacy allocation') const result = await createLegacyAllocation( network, graphNode, @@ -1603,6 +1598,7 @@ export default { ) logger.debug('POI resolved', { userProvidedPOI: poi, + userProvidedPublicPOI: publicPOI, userProvidedBlockNumber: blockNumber, poi: poiData.poi, publicPOI: poiData.publicPOI, @@ -1610,9 +1606,14 @@ export default { force, }) + logger.debug('closeAllocation: Checking allocation resolution path', { + allocationIsLegacy: allocationData.isLegacy, + }) + let txHash: string let rewardsAssigned: bigint if (allocationData.isLegacy) { + logger.debug('Closing legacy allocation') const result = await closeLegacyAllocation( allocationData, poiData.poi, @@ -1622,6 +1623,7 @@ export default { txHash = result.txHash rewardsAssigned = result.rewardsAssigned } else { + logger.debug('Closing horizon allocation') const result = await closeHorizonAllocation( allocationData, poiData, @@ -1736,6 +1738,7 @@ export default { ) logger.debug('POI resolved', { userProvidedPOI: poi, + userProvidedPublicPOI: publicPOI, userProvidedBlockNumber: blockNumber, poi: poiData.poi, publicPOI: poiData.publicPOI, @@ -1745,10 +1748,16 @@ export default { const isHorizon = await network.isHorizon.value() + logger.debug('reallocateAllocation: Checking allocation resolution path', { + isHorizon, + allocationIsLegacy: allocationData.isLegacy, + }) + let txHash: string let rewardsAssigned: bigint let newAllocationId: Address if (!isHorizon) { + logger.debug('Reallocating legacy allocation') const result = await reallocateLegacyAllocation( allocationData, allocationAmount, @@ -1761,6 +1770,7 @@ export default { rewardsAssigned = result.rewardsAssigned newAllocationId = result.newAllocationId } else if (allocationData.isLegacy) { + logger.debug('Migrating legacy allocation to horizon') const result = await migrateLegacyAllocationToHorizon( allocationData, allocationAmount, @@ -1774,6 +1784,7 @@ export default { rewardsAssigned = result.rewardsAssigned newAllocationId = result.newAllocationId } else { + logger.debug('Reallocating horizon allocation') const result = await reallocateHorizonAllocation( allocationData, allocationAmount, From 325d6fa269e5ed40e4062fa1cb97284e75c7c635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 9 Jun 2025 14:33:06 -0300 Subject: [PATCH 11/28] feat: add column wrapping to table format in cli MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-cli/package.json | 3 +- packages/indexer-cli/src/command-helpers.ts | 64 ++++++++++++++------- yarn.lock | 32 ++++++++++- 3 files changed, 76 insertions(+), 23 deletions(-) diff --git a/packages/indexer-cli/package.json b/packages/indexer-cli/package.json index feed72fdd..ea23edc96 100644 --- a/packages/indexer-cli/package.json +++ b/packages/indexer-cli/package.json @@ -38,7 +38,8 @@ "graphql-tag": "2.12.6", "isomorphic-fetch": "3.0.0", "table": "6.7.5", - "yaml": "1.10.2" + "yaml": "1.10.2", + "wrap-ansi": "9.0.0" }, "devDependencies": { "@types/isomorphic-fetch": "0.0.36", diff --git a/packages/indexer-cli/src/command-helpers.ts b/packages/indexer-cli/src/command-helpers.ts index 99d74a649..b386501c2 100644 --- a/packages/indexer-cli/src/command-helpers.ts +++ b/packages/indexer-cli/src/command-helpers.ts @@ -27,6 +27,7 @@ // parameters array and returns the result of that. import { table, getBorderCharacters } from 'table' +import wrapAnsi from 'wrap-ansi' export enum OutputFormat { Table = 'table', @@ -99,34 +100,49 @@ export function pickFields( } } for (const key of drop) { - delete obj[key] + delete obj[key] } return obj } -export function displayObjectData(outputFormat: OutputFormat, data: object): string { - return outputFormat === OutputFormat.Json - ? JSON.stringify(data, null, 2) - : outputFormat === OutputFormat.Yaml - ? yaml.stringify(data).trim() - : table([Object.keys(data), Object.values(data)], { - border: getBorderCharacters('norc'), - }).trim() +export function displayObjectData(outputFormat: OutputFormat, data: object, wrapWidth: number): string { + if (outputFormat === OutputFormat.Json) { + return JSON.stringify(data, null, 2) + } else if (outputFormat === OutputFormat.Yaml) { + return yaml.stringify(data).trim() + } else { + const keys = Object.keys(data) + const values = Object.values(data).map(value => wrapCell(value, wrapWidth)) + + return table([keys, values], { + border: getBorderCharacters('norc'), + }).trim() + } } export function displayObjectArrayData( outputFormat: OutputFormat, data: object[], + wrapWidth: number, ): string { - return outputFormat === OutputFormat.Json - ? JSON.stringify(data, null, 2) - : outputFormat === OutputFormat.Yaml - ? yaml.stringify(data).trim() - : data.length === 0 - ? 'No items found' - : table([Object.keys(data[0]), ...data.map(item => Object.values(item))], { - border: getBorderCharacters('norc'), - }).trim() + if (outputFormat === OutputFormat.Json) { + return JSON.stringify(data, null, 2) + } else if (outputFormat === OutputFormat.Yaml) { + return yaml.stringify(data).trim() + } else if (data.length === 0) { + return 'No items found' + } else { + const keys = Object.keys(data[0]) + + const tableData = [ + keys, + ...data.map(item => keys.map(key => wrapCell((item as any)[key], wrapWidth))), + ] + + return table(tableData, { + border: getBorderCharacters('norc'), + }).trim() + } } export function printObjectOrArray( @@ -134,12 +150,13 @@ export function printObjectOrArray( outputFormat: OutputFormat, data: object | object[], keys: string[], + wrapWidth: number = 0, ): void { if (Array.isArray(data)) { const formatted = data.map(item => pickFields(item, keys)) - print.info(displayObjectArrayData(outputFormat, formatted)) + print.info(displayObjectArrayData(outputFormat, formatted, wrapWidth)) } else if (data) { - print.info(displayObjectData(outputFormat, pickFields(data, keys))) + print.info(displayObjectData(outputFormat, pickFields(data, keys), wrapWidth)) } else { print.error(`No items returned`) } @@ -251,3 +268,10 @@ export function requireProtocolNetworkOption(options: { [key: string]: any }): s } return protocolNetwork } + + +export function wrapCell(value: unknown, wrapWidth: number): string { + return wrapWidth > 0 + ? wrapAnsi(String(value), wrapWidth, { hard: true }) + : String(value) +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index f2c1a9b2e..3c7c35793 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3289,7 +3289,7 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.1.0: +ansi-styles@^6.1.0, ansi-styles@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== @@ -4951,6 +4951,11 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== +emoji-regex@^10.3.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -5894,6 +5899,11 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-east-asian-width@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz#21b4071ee58ed04ee0db653371b55b4299875389" + integrity sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ== + get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" @@ -10371,6 +10381,15 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" +string-width@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -10413,7 +10432,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -11228,6 +11247,15 @@ workerpool@^6.5.1: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e" + integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + wrap-ansi@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" From 3d4562b1a56ddb97410a36cda8ed8d158fd52ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 9 Jun 2025 14:40:33 -0300 Subject: [PATCH 12/28] feat: add wrap to allocation commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../indexer-cli/src/commands/indexer/allocations/close.ts | 6 ++++-- .../indexer-cli/src/commands/indexer/allocations/create.ts | 6 ++++-- .../indexer-cli/src/commands/indexer/allocations/get.ts | 6 ++++-- .../src/commands/indexer/allocations/reallocate.ts | 5 ++++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/indexer-cli/src/commands/indexer/allocations/close.ts b/packages/indexer-cli/src/commands/indexer/allocations/close.ts index 52b286d91..af3c0dac9 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/close.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/close.ts @@ -21,6 +21,7 @@ ${chalk.dim('Options:')} -n, --network The network to close the allocation on: mainnet, arbitrum-one, sepolia or arbitrum sepolia -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 + -w, --wrap [N] Wrap the output to a specific width (default: 0, no wrapping) ${chalk.dim('Arguments:')} The allocation id to close @@ -38,11 +39,12 @@ module.exports = { const spinner = toolbox.print.spin('Processing inputs') - const { h, help, f, force, o, output } = parameters.options + const { h, help, f, force, o, output, w, wrap } = parameters.options const outputFormat = o || output || 'table' const toHelp = help || h || undefined const toForce = force || f || false + const wrapWidth = w || wrap || 0 if (toHelp) { spinner.stopAndPersist({ symbol: '💁', text: HELP }) @@ -106,7 +108,7 @@ module.exports = { 'allocation', 'allocatedTokens', 'indexingRewards', - ]) + ], wrapWidth) } catch (error) { spinner.fail(error.toString()) process.exitCode = 1 diff --git a/packages/indexer-cli/src/commands/indexer/allocations/create.ts b/packages/indexer-cli/src/commands/indexer/allocations/create.ts index d0d84b5d3..addccc7a3 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/create.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/create.ts @@ -20,6 +20,7 @@ ${chalk.dim('Options:')} -h, --help Show usage information -n, --network The protocol network for this action (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML + -w, --wrap [N] Wrap the output to a specific width (default: 0, no wrapping) ` module.exports = { @@ -31,10 +32,11 @@ module.exports = { const spinner = toolbox.print.spin('Processing inputs') - const { h, help, o, output } = parameters.options + const { h, help, o, output, w, wrap } = parameters.options const outputFormat = o || output || 'table' const toHelp = help || h || undefined + const wrapWidth = w || wrap || 0 if (toHelp) { spinner.stopAndPersist({ symbol: '💁', text: HELP }) @@ -88,7 +90,7 @@ module.exports = { 'deployment', 'allocatedTokens', 'protocolNetwork', - ]) + ], wrapWidth) } catch (error) { spinner.fail(error.toString()) process.exitCode = 1 diff --git a/packages/indexer-cli/src/commands/indexer/allocations/get.ts b/packages/indexer-cli/src/commands/indexer/allocations/get.ts index fe3b804be..6e62b93e6 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/get.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/get.ts @@ -22,6 +22,7 @@ ${chalk.dim('Options:')} --status active|closed|claimable Filter by status --deployment Fetch only allocations for a specific subgraph deployment -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML + -w, --wrap [N] Wrap the output to a specific width (default: 0, no wrapping) ` module.exports = { @@ -33,10 +34,11 @@ module.exports = { const spinner = toolbox.print.spin('Processing inputs') - const { status, deployment, h, help, o, output } = parameters.options + const { status, deployment, h, help, o, output, w, wrap } = parameters.options const [allocation] = fixParameters(parameters, { h, help }) || [] const outputFormat = o || output || 'table' + const wrapWidth = w || wrap || 0 if (help || h) { spinner.stopAndPersist({ symbol: '💁', text: HELP }) @@ -169,7 +171,7 @@ module.exports = { ) } spinner.succeed('Allocations') - printIndexerAllocations(print, outputFormat, allocations, displayProperties) + printIndexerAllocations(print, outputFormat, allocations, displayProperties, wrapWidth) } catch (error) { spinner.fail(error.toString()) process.exitCode = 1 diff --git a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts index c7cac4b98..95923c4ac 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/reallocate.ts @@ -20,6 +20,7 @@ ${chalk.dim('Options:')} -h, --help Show usage information -n, --network The protocol network for this action (mainnet, arbitrum-one, sepolia, arbitrum-sepolia) -f, --force Bypass POI accuracy checks and submit transaction with provided data + -w, --wrap [N] Wrap the output to a specific width (default: 0, no wrapping) ${chalk.dim('Arguments:')} The allocation id to close @@ -38,11 +39,12 @@ module.exports = { const spinner = toolbox.print.spin('Processing inputs') - const { h, help, f, force, o, output } = parameters.options + const { h, help, f, force, o, output, w, wrap } = parameters.options const outputFormat = o || output || 'table' const toHelp = help || h || undefined const toForce = force || f || false + const wrapWidth = w || wrap || 0 if (toHelp) { spinner.stopAndPersist({ symbol: '💁', text: HELP }) @@ -110,6 +112,7 @@ module.exports = { 'createdAllocation', 'createdAllocationStake', ], + wrapWidth, ) } catch (error) { spinner.fail(error.toString()) From 09898ce7a4a9891278b809d0e9c8434848b2d2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 9 Jun 2025 15:16:13 -0300 Subject: [PATCH 13/28] feat: allocate and unallocate in action queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-agent/src/agent.ts | 1 + .../migrations/20-actions-add-poi-metadata.ts | 59 +++++ packages/indexer-cli/src/actions.ts | 25 +- packages/indexer-cli/src/allocations.ts | 13 +- .../src/commands/indexer/actions/approve.ts | 3 + .../src/commands/indexer/actions/cancel.ts | 3 + .../src/commands/indexer/actions/execute.ts | 3 + .../src/commands/indexer/actions/get.ts | 8 +- .../src/commands/indexer/actions/queue.ts | 9 +- .../src/commands/indexer/actions/update.ts | 3 + packages/indexer-common/src/actions.ts | 27 ++- .../src/indexer-management/allocations.ts | 218 +++++++++++------- .../src/indexer-management/client.ts | 14 +- .../src/indexer-management/models/action.ts | 11 + 14 files changed, 293 insertions(+), 104 deletions(-) create mode 100644 packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index 2e8f37e03..5df4e66ac 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -252,6 +252,7 @@ export class Agent { }, ) + // TODO HORIZON: Uncomment this // this.reconciliationLoop() return this } diff --git a/packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts b/packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts new file mode 100644 index 000000000..3351013b9 --- /dev/null +++ b/packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts @@ -0,0 +1,59 @@ +import { Logger } from '@graphprotocol/common-ts' +import { DataTypes, QueryInterface } from 'sequelize' + +interface MigrationContext { + queryInterface: QueryInterface + logger: Logger +} + +interface Context { + context: MigrationContext +} + +export async function up({ context }: Context): Promise { + const { queryInterface, logger } = context + + logger.debug(`Checking if 'Actions' table exists`) + const tables = await queryInterface.showAllTables() + if (!tables.includes('Actions')) { + logger.info(`Actions table does not exist, migration not necessary`) + return + } + + logger.debug(`Checking if 'Actions' table needs to be migrated`) + const table = await queryInterface.describeTable('Actions') + const publicPOI = table.publicPOI + const poiBlockNumber = table.poiBlockNumber + if (publicPOI && poiBlockNumber) { + logger.info(`'publicPOI' and 'poiBlockNumber' columns already exist, migration not necessary`) + return + } + + logger.info(`Add 'publicPOI' and 'poiBlockNumber' columns to 'Actions' table`) + await queryInterface.addColumn('Actions', 'publicPOI', { + type: DataTypes.STRING, + allowNull: true, + }) + await queryInterface.addColumn('Actions', 'poiBlockNumber', { + type: DataTypes.INTEGER, + allowNull: true, + }) +} + +export async function down({ context }: Context): Promise { + const { queryInterface, logger } = context + + return await queryInterface.sequelize.transaction({}, async transaction => { + const tables = await queryInterface.showAllTables() + + if (tables.includes('Actions')) { + logger.info(`Remove 'publicPOI' and 'poiBlockNumber' columns`) + await context.queryInterface.removeColumn('Actions', 'publicPOI', { + transaction, + }) + await context.queryInterface.removeColumn('Actions', 'poiBlockNumber', { + transaction, + }) + } + }) +} diff --git a/packages/indexer-cli/src/actions.ts b/packages/indexer-cli/src/actions.ts index 76f47215e..1c1fb8160 100644 --- a/packages/indexer-cli/src/actions.ts +++ b/packages/indexer-cli/src/actions.ts @@ -37,7 +37,6 @@ export async function buildActionInput( priority: number, protocolNetwork: string, ): Promise { - // TODO HORIZON: validate publicPOI and blockNumber for unallocate and reallocate only for horizon allocations await validateActionInput(type, actionParams) // TODO HORIZON: we could check isHorizon status here to set the proper value for isLegacy, but it requires multiNetworks @@ -67,7 +66,7 @@ export async function buildActionInput( allocationID: actionParams.param1, poi: poi, publicPOI: actionParams.param5, - blockNumber: actionParams.param6, + poiBlockNumber: actionParams.param4 ? Number(actionParams.param4) : undefined, force: actionParams.param3 === 'true', type, source, @@ -88,8 +87,8 @@ export async function buildActionInput( allocationID: actionParams.param1, amount: actionParams.param2?.toString(), poi: poi, - publicPOI: actionParams.param5, - blockNumber: actionParams.param6, + publicPOI: actionParams.param6, + poiBlockNumber: actionParams.param5 ? Number(actionParams.param5) : undefined, force: actionParams.param4 === 'true', type, source, @@ -198,7 +197,7 @@ export async function queueActions( amount poi publicPOI - blockNumber + poiBlockNumber force source reason @@ -227,7 +226,7 @@ const ACTION_PARAMS_PARSERS: Record any> amount: nullPassThrough(parseGRT), poi: nullPassThrough((x: string) => validatePOI(x)), publicPOI: nullPassThrough((x: string) => validatePOI(x)), - blockNumber: nullPassThrough((x: string) => Number(x)), + poiBlockNumber: nullPassThrough((x: string) => Number(x)), force: x => parseBoolean(x), type: x => validateActionType(x), status: x => validateActionStatus(x), @@ -270,7 +269,7 @@ export async function executeApprovedActions( amount poi publicPOI - blockNumber + poiBlockNumber force source reason @@ -307,7 +306,7 @@ export async function approveActions( amount poi publicPOI - blockNumber + poiBlockNumber force source reason @@ -347,7 +346,7 @@ export async function cancelActions( amount poi publicPOI - blockNumber + poiBlockNumber force source reason @@ -386,7 +385,7 @@ export async function fetchAction( amount poi publicPOI - blockNumber + poiBlockNumber force source reason @@ -438,7 +437,7 @@ export async function fetchActions( amount poi publicPOI - blockNumber + poiBlockNumber force source reason @@ -478,7 +477,7 @@ export async function deleteActions( amount poi publicPOI - blockNumber + poiBlockNumber force source reason @@ -518,7 +517,7 @@ export async function updateActions( amount poi publicPOI - blockNumber + poiBlockNumber force source reason diff --git a/packages/indexer-cli/src/allocations.ts b/packages/indexer-cli/src/allocations.ts index 8996b8cc5..1abbf291d 100644 --- a/packages/indexer-cli/src/allocations.ts +++ b/packages/indexer-cli/src/allocations.ts @@ -2,7 +2,7 @@ import { SubgraphDeploymentID, formatGRT, commify } from '@graphprotocol/common- import yaml from 'yaml' import { GluegunPrint } from 'gluegun' import { table, getBorderCharacters } from 'table' -import { OutputFormat, parseOutputFormat, pickFields } from './command-helpers' +import { OutputFormat, parseOutputFormat, pickFields, wrapCell } from './command-helpers' import { IndexerManagementClient } from '@graphprotocol/indexer-common' import gql from 'graphql-tag' import { @@ -121,16 +121,17 @@ export const printIndexerAllocations = ( | Partial[] | null, keys: (keyof IndexerAllocation)[], + wrapWidth: number = 0, ): void => { parseOutputFormat(print, outputFormat) if (Array.isArray(allocationOrAllocations)) { const allocations = allocationOrAllocations.map(allocation => formatIndexerAllocation(pickFields(allocation, keys)), ) - print.info(displayIndexerAllocations(outputFormat, allocations)) + print.info(displayIndexerAllocations(outputFormat, allocations, wrapWidth)) } else if (allocationOrAllocations) { const allocation = formatIndexerAllocation(pickFields(allocationOrAllocations, keys)) - print.info(displayIndexerAllocation(outputFormat, allocation)) + print.info(displayIndexerAllocation(outputFormat, allocation, wrapWidth)) } else { print.error(`No allocations found`) } @@ -139,6 +140,7 @@ export const printIndexerAllocations = ( export const displayIndexerAllocations = ( outputFormat: OutputFormat, allocations: Partial[], + wrapWidth: number, ): string => outputFormat === OutputFormat.Json ? JSON.stringify(allocations, null, 2) @@ -149,7 +151,7 @@ export const displayIndexerAllocations = ( : table( [ Object.keys(allocations[0]), - ...allocations.map(allocation => Object.values(allocation)), + ...allocations.map(allocation => Object.values(allocation).map(value => wrapCell(value, wrapWidth))), ], { border: getBorderCharacters('norc'), @@ -159,12 +161,13 @@ export const displayIndexerAllocations = ( export const displayIndexerAllocation = ( outputFormat: OutputFormat, allocation: Partial, + wrapWidth: number, ): string => outputFormat === OutputFormat.Json ? JSON.stringify(allocation, null, 2) : outputFormat === OutputFormat.Yaml ? yaml.stringify(allocation).trim() - : table([Object.keys(allocation), Object.values(allocation)], { + : table([Object.keys(allocation), Object.values(allocation).map(value => wrapCell(value, wrapWidth))], { border: getBorderCharacters('norc'), }).trim() diff --git a/packages/indexer-cli/src/commands/indexer/actions/approve.ts b/packages/indexer-cli/src/commands/indexer/actions/approve.ts index 52e32f55c..f6ce87520 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/approve.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/approve.ts @@ -114,11 +114,14 @@ module.exports = { 'allocationID', 'amount', 'poi', + 'publicPOI', + 'poiBlockNumber', 'force', 'priority', 'status', 'source', 'reason', + 'isLegacy', ]) } catch (error) { actionSpinner.fail(error.toString()) diff --git a/packages/indexer-cli/src/commands/indexer/actions/cancel.ts b/packages/indexer-cli/src/commands/indexer/actions/cancel.ts index d5b74701c..3fc105951 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/cancel.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/cancel.ts @@ -80,11 +80,14 @@ module.exports = { 'allocationID', 'amount', 'poi', + 'publicPOI', + 'poiBlockNumber', 'force', 'priority', 'status', 'source', 'reason', + 'isLegacy', ]) } catch (error) { actionSpinner.fail(error.toString()) diff --git a/packages/indexer-cli/src/commands/indexer/actions/execute.ts b/packages/indexer-cli/src/commands/indexer/actions/execute.ts index a742f21cd..422879651 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/execute.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/execute.ts @@ -74,12 +74,15 @@ module.exports = { 'allocationID', 'amount', 'poi', + 'publicPOI', + 'poiBlockNumber', 'force', 'priority', 'transaction', 'failureReason', 'source', 'reason', + 'isLegacy', ]) } catch (error) { spinner.fail(error.toString()) diff --git a/packages/indexer-cli/src/commands/indexer/actions/get.ts b/packages/indexer-cli/src/commands/indexer/actions/get.ts index 0e106ebeb..38b6c3a53 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/get.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/get.ts @@ -32,6 +32,7 @@ ${chalk.dim('Options:')} --first [N] Fetch only the N first records (default: all records) --fields [field1,field2,...] Comma-separated names of the fields to display (no spaces allowed between fields) -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML + -w, --wrap [N] Wrap the output to a specific width (default: 0, no wrapping) ` const actionFields: (keyof Action)[] = [ @@ -42,6 +43,8 @@ const actionFields: (keyof Action)[] = [ 'allocationID', 'amount', 'poi', + 'publicPOI', + 'poiBlockNumber', 'force', 'priority', 'status', @@ -90,12 +93,15 @@ module.exports = { output, first, fields, + w, + wrap, } = parameters.options const [action] = fixParameters(parameters, { h, help }) || [] let orderByParam = ActionParams.ID let orderDirectionValue = OrderDirection.DESC const outputFormat = o || output || 'table' + const wrapWidth = w || wrap || 0 const protocolNetwork: string | undefined = extractProtocolNetworkOption( parameters.options, @@ -224,7 +230,7 @@ module.exports = { action => (action.protocolNetwork = resolveChainAlias(action.protocolNetwork)), ) - printObjectOrArray(print, outputFormat, actions, displayProperties) + printObjectOrArray(print, outputFormat, actions, displayProperties, wrapWidth) } catch (error) { actionSpinner.fail(error.toString()) process.exitCode = 1 diff --git a/packages/indexer-cli/src/commands/indexer/actions/queue.ts b/packages/indexer-cli/src/commands/indexer/actions/queue.ts index 583486a6f..0e13d33f0 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/queue.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/queue.ts @@ -17,14 +17,14 @@ import { const HELP = ` ${chalk.bold( 'graph indexer actions queue', -)} [options] +)} [options] ${chalk.bold('graph indexer actions queue')} [options] allocate ${chalk.bold( 'graph indexer actions queue', -)} [options] unallocate +)} [options] unallocate ${chalk.bold( 'graph indexer actions queue', -)} [options] reallocate +)} [options] reallocate ${chalk.dim('Options:')} @@ -119,11 +119,14 @@ module.exports = { 'allocationID', 'amount', 'poi', + 'publicPOI', + 'poiBlockNumber', 'force', 'priority', 'status', 'source', 'reason', + 'isLegacy', ]) } catch (error) { actionSpinner.fail(error.toString()) diff --git a/packages/indexer-cli/src/commands/indexer/actions/update.ts b/packages/indexer-cli/src/commands/indexer/actions/update.ts index 0d27d8f31..cfadabdc8 100644 --- a/packages/indexer-cli/src/commands/indexer/actions/update.ts +++ b/packages/indexer-cli/src/commands/indexer/actions/update.ts @@ -108,6 +108,8 @@ module.exports = { 'allocationID', 'amount', 'poi', + 'publicPOI', + 'poiBlockNumber', 'force', 'priority', 'status', @@ -115,6 +117,7 @@ module.exports = { 'failureReason', 'transaction', 'reason', + 'isLegacy', ] // Format Actions 'protocolNetwork' field to display human-friendly chain aliases instead of CAIP2-IDs diff --git a/packages/indexer-common/src/actions.ts b/packages/indexer-common/src/actions.ts index ba42e3c0d..b639d1ebe 100644 --- a/packages/indexer-common/src/actions.ts +++ b/packages/indexer-common/src/actions.ts @@ -11,6 +11,8 @@ export interface ActionParamsInput { allocationID?: string amount?: string poi?: string + publicPOI?: string + poiBlockNumber?: number force?: boolean } @@ -29,7 +31,7 @@ export interface ActionUpdateInput { amount?: string poi?: string publicPOI?: string - blockNumber?: string + poiBlockNumber?: number force?: boolean type?: ActionType status?: ActionStatus @@ -45,7 +47,7 @@ export interface ActionInput { amount?: string poi?: string publicPOI?: string - blockNumber?: string + poiBlockNumber?: number force?: boolean source: string reason: string @@ -70,12 +72,28 @@ export const isValidActionInput = ( case ActionType.UNALLOCATE: hasActionParams = 'deploymentID' in variableToCheck && 'allocationID' in variableToCheck + + if (!variableToCheck.isLegacy && variableToCheck.poi !== undefined) { + hasActionParams = + hasActionParams && + 'poi' in variableToCheck && + 'publicPOI' in variableToCheck && + 'poiBlockNumber' in variableToCheck + } break case ActionType.REALLOCATE: hasActionParams = 'deploymentID' in variableToCheck && 'allocationID' in variableToCheck && 'amount' in variableToCheck + + if (!variableToCheck.isLegacy && variableToCheck.poi !== undefined) { + hasActionParams = + hasActionParams && + 'poi' in variableToCheck && + 'publicPOI' in variableToCheck && + 'poiBlockNumber' in variableToCheck + } } return ( hasActionParams && @@ -192,6 +210,8 @@ export interface ActionResult { allocationID: string | null amount: string | null poi: string | null + publicPOI: string | null + poiBlockNumber: number | null force: boolean | null source: string reason: string @@ -228,6 +248,8 @@ export enum ActionParams { TRANSACTION = 'transaction', AMOUNT = 'amount', POI = 'poi', + PUBLIC_POI = 'publicPOI', + POI_BLOCK_NUMBER = 'poiBlockNumber', FORCE = 'force', SOURCE = 'source', REASON = 'reason', @@ -235,4 +257,5 @@ export enum ActionParams { CREATED_AT = 'createdAt', UPDATED_AT = 'updatedAt', PROTOCOL_NETWORK = 'protocolNetwork', + IS_LEGACY = 'isLegacy', } diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index ac9ad6fe5..1e549c301 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -34,8 +34,13 @@ import { upsertIndexingRule, horizonAllocationIdProof, isActionFailureArray, + POIData, } from '@graphprotocol/indexer-common' -import { encodeStartServiceData } from '@graphprotocol/toolshed' +import { encodeStartServiceData, encodeStopServiceData, PaymentTypes } from '@graphprotocol/toolshed' +import { + encodeCollectIndexingRewardsData, + encodePOIMetadata, +} from '@graphprotocol/toolshed' import { BigNumberish, @@ -67,7 +72,9 @@ export interface AllocateTransactionParams { export interface UnallocateTransactionParams { allocationID: string - poi: BytesLike + poi: POIData + isLegacy: boolean + indexer: string } export interface ReallocateTransactionParams { @@ -105,7 +112,7 @@ export class AllocationManager { private models: IndexerManagementModels, private graphNode: GraphNode, private network: Network, - ) {} + ) { } async executeBatch( actions: Action[], @@ -374,6 +381,8 @@ export class AllocationManager { action.allocationID!, action.poi === null ? undefined : action.poi, action.force === null ? false : action.force, + action.poiBlockNumber === null ? undefined : action.poiBlockNumber, + action.publicPOI === null ? undefined : action.publicPOI, ) case ActionType.REALLOCATE: return await this.prepareReallocate( @@ -489,11 +498,6 @@ export class AllocationManager { // Double-check whether the allocationID already exists on chain, to // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized, Claimed } - // - // in the contracts. let allocationExistsSubgraphService = false let allocationExistsStaking = false const isHorizon = await this.network.isHorizon.value() @@ -532,21 +536,21 @@ export class AllocationManager { const proof = isHorizon ? await horizonAllocationIdProof( - allocationSigner, - Number(this.network.specification.networkIdentifier.split(':')[1]), - this.network.specification.indexerOptions.address, - allocationId, - this.network.contracts.SubgraphService.target.toString(), - ) + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + allocationId, + this.network.contracts.SubgraphService.target.toString(), + ) : await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - allocationId, - ) + allocationSigner, + this.network.specification.indexerOptions.address, + allocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, - isLegacy: isHorizon, + isLegacy: !isHorizon, }) return { @@ -576,29 +580,28 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE062, - `Allocation not created. ${ - receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + `Allocation not created. ${receipt === 'paused' ? 'Network paused' : 'Operator not authorized' }`, ) } const createAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - subgraphDeployment.bytes32, - receipt, - this.logger, - ) + 'AllocationCreated', + this.network.contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + subgraphDeployment.bytes32, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'ServiceStarted', - this.network.contracts.SubgraphService.interface, - 'serviceProvider', - this.network.specification.indexerOptions.address, - receipt, - logger, - ) + 'AllocationCreated', + this.network.contracts.SubgraphService.interface, + 'indexer', + this.network.specification.indexerOptions.address, + receipt, + logger, + ) if (!createAllocationEventLogs) { throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) @@ -606,9 +609,9 @@ export class AllocationManager { logger.info(`Successfully allocated to subgraph deployment`, { amountGRT: formatGRT(createAllocationEventLogs.tokens), - allocation: createAllocationEventLogs.allocationID, + allocation: isLegacy ? createAllocationEventLogs.allocationID : createAllocationEventLogs.allocationId, deployment: createAllocationEventLogs.subgraphDeploymentID, - epoch: createAllocationEventLogs.epoch.toString(), + epoch: isLegacy ? createAllocationEventLogs.epoch.toString() : createAllocationEventLogs.currentEpoch.toString(), isLegacy, }) @@ -634,7 +637,7 @@ export class AllocationManager { type: 'allocate', transactionID: receipt.hash, deployment: deployment, - allocation: createAllocationEventLogs.allocationID, + allocation: isLegacy ? createAllocationEventLogs.allocationID : createAllocationEventLogs.allocationId, allocatedTokens: amount, protocolNetwork: this.network.specification.networkIdentifier, } @@ -654,7 +657,7 @@ export class AllocationManager { amount: formatGRT(params.tokens), allocation: params.allocationID, proof: params.proof, - isLegacy: isHorizon, + isLegacy: !isHorizon, }) let populatedTransaction: ContractTransaction @@ -690,8 +693,10 @@ export class AllocationManager { allocationID: string, poi: string | undefined, force: boolean, + poiBlockNumber: number | undefined, + publicPOI: string | undefined, ): Promise { - logger.info('Preparing to close allocation (unallocate)', { + logger.info('Preparing to unallocate', { allocationID: allocationID, poi: poi || 'none provided', }) @@ -700,30 +705,32 @@ export class AllocationManager { const poiData = await this.network.networkMonitor.resolvePOI( allocation, poi, - undefined, - undefined, + publicPOI, + poiBlockNumber, force, ) - poi = poiData.poi // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized, Claimed } - // - // in the contracts. - const state = await this.network.contracts.HorizonStaking.getAllocationState( - allocation.id, - ) - if (state !== 1n) { - throw indexerError(IndexerErrorCode.IE065) + if (allocation.isLegacy) { + const state = await this.network.contracts.HorizonStaking.getAllocationState( + allocation.id, + ) + if (state !== 1n) { + throw indexerError(IndexerErrorCode.IE065) + } + } else { + const allocation = await this.network.contracts.SubgraphService.getAllocation(allocationID) + if (allocation.closedAt !== 0n) { + throw indexerError(IndexerErrorCode.IE065) + } } return { allocationID: allocation.id, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - poi: poi!, + poi: poiData, + isLegacy: allocation.isLegacy, + indexer: allocation.indexer, } } @@ -733,7 +740,12 @@ export class AllocationManager { receipt: TransactionReceipt | 'paused' | 'unauthorized', ): Promise { const logger = this.logger.child({ action: actionID }) - logger.info(`Confirming 'closeAllocation' transaction`) + const isLegacy = + (receipt as TransactionReceipt).to === this.network.contracts.HorizonStaking.target + + logger.info(`Confirming unallocate transaction`, { + isLegacy, + }) if (receipt === 'paused' || receipt === 'unauthorized') { throw indexerError( @@ -742,13 +754,20 @@ export class AllocationManager { ) } - const closeAllocationEventLogs = this.network.transactionManager.findEvent( + const closeAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( 'AllocationClosed', this.network.contracts.LegacyStaking.interface, 'allocationID', allocationID, receipt, this.logger, + ) : this.network.transactionManager.findEvent( + 'AllocationClosed', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, ) if (!closeAllocationEventLogs) { @@ -758,37 +777,45 @@ export class AllocationManager { ) } - const rewardsEventLogs = this.network.transactionManager.findEvent( + const rewardsEventLogs = isLegacy ? this.network.transactionManager.findEvent( 'RewardsAssigned', this.network.contracts.RewardsManager.interface, 'allocationID', allocationID, receipt, this.logger, + ) : this.network.transactionManager.findEvent( + 'IndexingRewardsCollected', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, ) - const rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.amount : 0 + const rewardsAssigned = rewardsEventLogs ? + (isLegacy ? rewardsEventLogs.amount : rewardsEventLogs.tokensIndexerRewards) : + 0 if (rewardsAssigned == 0) { logger.warn('No rewards were distributed upon closing the allocation') } const subgraphDeploymentID = new SubgraphDeploymentID( - closeAllocationEventLogs.subgraphDeploymentID, + isLegacy ? closeAllocationEventLogs.subgraphDeploymentID : closeAllocationEventLogs.subgraphDeploymentId, ) logger.info(`Successfully closed allocation`, { deployment: subgraphDeploymentID.display, - allocation: closeAllocationEventLogs.allocationID, + allocation: allocationID, indexer: closeAllocationEventLogs.indexer, amountGRT: formatGRT(closeAllocationEventLogs.tokens), - poi: closeAllocationEventLogs.poi, transaction: receipt.hash, indexingRewards: rewardsAssigned, }) logger.info('Identifying receipts worth collecting', { - allocation: closeAllocationEventLogs.allocationID, + allocation: allocationID, }) const allocation = await this.network.networkMonitor.allocation(allocationID) @@ -809,7 +836,7 @@ export class AllocationManager { actionID, type: 'unallocate', transactionID: receipt.hash, - allocation: closeAllocationEventLogs.allocationID, + allocation: allocationID, allocatedTokens: formatGRT(closeAllocationEventLogs.tokens), indexingRewards: formatGRT(rewardsAssigned), protocolNetwork: this.network.specification.networkIdentifier, @@ -820,15 +847,46 @@ export class AllocationManager { logger: Logger, params: UnallocateTransactionParams, ): Promise { - logger.debug(`Populating closeAllocation transaction`, { + logger.debug(`Populating unallocate transaction`, { allocationID: params.allocationID, - POI: params.poi, + poiData: params.poi, }) - // TODO HORIZON: split into pre-post horizon - return await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( - params.allocationID, - params.poi, - ) + + if (params.isLegacy) { + return await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( + params.allocationID, + params.poi.poi, + ) + } else { + // Horizon: Need to multicall collect and stopService + + // collect + const collectIndexingRewardsData = encodeCollectIndexingRewardsData( + params.allocationID, + params.poi.poi, + encodePOIMetadata( + params.poi.blockNumber, + params.poi.publicPOI, + params.poi.indexingStatus, + 0, + 0, + ), + ) + const collectCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( + 'collect', + [params.indexer, PaymentTypes.IndexingRewards, collectIndexingRewardsData], + ) + + // stopService + const stopServiceCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( + 'stopService', + [params.indexer, encodeStopServiceData(params.allocationID)], + ) + + return await this.network.contracts.SubgraphService.multicall.populateTransaction( + [collectCallData, stopServiceCallData], + ) + } } async prepareUnallocate( @@ -837,6 +895,8 @@ export class AllocationManager { allocationID: string, poi: string | undefined, force: boolean, + poiBlockNumber: number | undefined, + publicPOI: string | undefined, ): Promise { const params = await this.prepareUnallocateParams( logger, @@ -844,6 +904,8 @@ export class AllocationManager { allocationID, poi, force, + poiBlockNumber, + publicPOI, ) return await this.populateUnallocateTransaction(logger, params) } @@ -1190,9 +1252,9 @@ export class AllocationManager { action.poi === zeroHexString ? 0n : await this.network.contracts.RewardsManager.getRewards( - this.network.contracts.HorizonStaking.target, - action.allocationID, - ) + this.network.contracts.HorizonStaking.target, + action.allocationID, + ) unallocates = unallocates + allocation.allocatedTokens } @@ -1252,10 +1314,10 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE013, `Unfeasible action batch: Approved action batch GRT balance is ` + - `${formatGRT(batchDelta)} for horizon actions and ` + - `${formatGRT(batchDeltaLegacy)} for legacy actions ` + - `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + - `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, + `${formatGRT(batchDelta)} for horizon actions and ` + + `${formatGRT(batchDeltaLegacy)} for legacy actions ` + + `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + + `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, ) } } diff --git a/packages/indexer-common/src/indexer-management/client.ts b/packages/indexer-common/src/indexer-management/client.ts index a0212201d..b2edc8fa1 100644 --- a/packages/indexer-common/src/indexer-management/client.ts +++ b/packages/indexer-common/src/indexer-management/client.ts @@ -130,6 +130,8 @@ const SCHEMA_SDL = gql` allocationID: String amount: String poi: String + publicPOI: String + poiBlockNumber: Int force: Boolean priority: Int! source: String! @@ -149,6 +151,8 @@ const SCHEMA_SDL = gql` allocationID: String amount: String poi: String + publicPOI: String + poiBlockNumber: Int force: Boolean source: String! reason: String! @@ -163,6 +167,8 @@ const SCHEMA_SDL = gql` allocationID: String amount: Int poi: String + publicPOI: String + poiBlockNumber: Int force: Boolean type: ActionType status: ActionStatus @@ -178,6 +184,8 @@ const SCHEMA_SDL = gql` transaction amount poi + publicPOI + poiBlockNumber force source reason @@ -194,6 +202,8 @@ const SCHEMA_SDL = gql` allocationID: String amount: String poi: String + publicPOI: String + poiBlockNumber: Int force: Boolean source: String! reason: String! @@ -485,7 +495,7 @@ const SCHEMA_SDL = gql` closeAllocation( allocation: String! poi: String - blockNumber: String + poiBlockNumber: Int publicPOI: String force: Boolean protocolNetwork: String! @@ -493,7 +503,7 @@ const SCHEMA_SDL = gql` reallocateAllocation( allocation: String! poi: String - blockNumber: String + poiBlockNumber: Int publicPOI: String amount: String! force: Boolean diff --git a/packages/indexer-common/src/indexer-management/models/action.ts b/packages/indexer-common/src/indexer-management/models/action.ts index daf35d67a..e40f37b99 100644 --- a/packages/indexer-common/src/indexer-management/models/action.ts +++ b/packages/indexer-common/src/indexer-management/models/action.ts @@ -39,6 +39,9 @@ export class Action extends Model< declare isLegacy: boolean + declare publicPOI: string | null + declare poiBlockNumber: number | null + // eslint-disable-next-line @typescript-eslint/ban-types public toGraphQL(): object { return { ...this.toJSON(), __typename: 'Action' } @@ -159,6 +162,14 @@ export const defineActionModels = (sequelize: Sequelize): ActionModels => { allowNull: false, defaultValue: true, }, + publicPOI: { + type: DataTypes.STRING, + allowNull: true, + }, + poiBlockNumber: { + type: DataTypes.INTEGER, + allowNull: true, + }, }, { modelName: 'Action', From 65f6fd2e524dc57ba6e33ea7ee75c0ddc42086c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 10 Jun 2025 11:15:25 -0300 Subject: [PATCH 14/28] fix: action update serialization bug for bigints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-cli/src/actions.ts | 39 ++++++++++++++++++- .../src/indexer-management/client.ts | 2 +- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/indexer-cli/src/actions.ts b/packages/indexer-cli/src/actions.ts index 1c1fb8160..7545d80ba 100644 --- a/packages/indexer-cli/src/actions.ts +++ b/packages/indexer-cli/src/actions.ts @@ -15,7 +15,7 @@ import { import { validatePOI, validateRequiredParams } from './command-helpers' import gql from 'graphql-tag' import { hexlify } from 'ethers' -import { parseGRT } from '@graphprotocol/common-ts' +import { formatGRT, parseGRT } from '@graphprotocol/common-ts' export interface GenericActionInputParams { targetDeployment: string @@ -235,6 +235,25 @@ const ACTION_PARAMS_PARSERS: Record any> isLegacy: x => parseBoolean(x), } +const ACTION_CONVERTERS_TO_GRAPHQL: Record< + keyof ActionUpdateInput, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (x: never) => any +> = { + deploymentID: x => x, + allocationID: x => x, + amount: nullPassThrough((x: bigint) => formatGRT(x)), + poi: x => x, + publicPOI: x => x, + poiBlockNumber: nullPassThrough((x: number) => x), + force: x => x, + type: x => x, + status: x => x, + reason: x => x, + protocolNetwork: x => x, + isLegacy: x => x, +} + /** * Parses a user-provided action update input into a normalized form. */ @@ -252,6 +271,22 @@ export const parseActionUpdateInput = (input: object): ActionUpdateInput => { return obj as ActionUpdateInput } +/** + * Converts a normalized action to a representation + * compatible with the indexer management GraphQL API. + */ +export const actionToGraphQL = ( + action: Partial, +): Partial => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const obj = {} as any + for (const [key, value] of Object.entries(action)) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + obj[key] = (ACTION_CONVERTERS_TO_GRAPHQL as any)[key](value) + } + return obj as Partial +} + export async function executeApprovedActions( client: IndexerManagementClient, ): Promise { @@ -530,7 +565,7 @@ export async function updateActions( } } `, - { filter, action }, + { filter, action: actionToGraphQL(action) }, ) .toPromise() diff --git a/packages/indexer-common/src/indexer-management/client.ts b/packages/indexer-common/src/indexer-management/client.ts index b2edc8fa1..88a2ff93d 100644 --- a/packages/indexer-common/src/indexer-management/client.ts +++ b/packages/indexer-common/src/indexer-management/client.ts @@ -165,7 +165,7 @@ const SCHEMA_SDL = gql` id: Int deploymentID: String allocationID: String - amount: Int + amount: String poi: String publicPOI: String poiBlockNumber: Int From dc590ce05193a809ba770334c34fcd8b49c9d6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 10 Jun 2025 15:40:47 -0300 Subject: [PATCH 15/28] feat: unallocate action queue management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../src/indexer-management/allocations.ts | 373 +++++++++++++----- .../resolvers/allocations.ts | 4 +- 2 files changed, 283 insertions(+), 94 deletions(-) diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index 1e549c301..5cd1401c2 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -79,13 +79,14 @@ export interface UnallocateTransactionParams { export interface ReallocateTransactionParams { closingAllocationID: string - poi: BytesLike + poi: POIData indexer: string subgraphDeploymentID: BytesLike tokens: BigNumberish newAllocationID: string metadata: BytesLike proof: BytesLike + closingAllocationIsLegacy: boolean } // An Action with resolved Allocation and Unallocation values @@ -394,6 +395,8 @@ export class AllocationManager { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion parseGRT(action.amount!), action.force === null ? false : action.force, + action.poiBlockNumber === null ? undefined : action.poiBlockNumber, + action.publicPOI === null ? undefined : action.publicPOI, ) } } catch (error) { @@ -496,6 +499,11 @@ export class AllocationManager { activeAndRecentlyClosedAllocations.map((allocation) => allocation.id), ) + logger.debug('New unique Allocation ID generated', { + newAllocationID: allocationId, + newAllocationSigner: allocationSigner, + }) + // Double-check whether the allocationID already exists on chain, to // avoid unnecessary transactions. let allocationExistsSubgraphService = false @@ -699,6 +707,8 @@ export class AllocationManager { logger.info('Preparing to unallocate', { allocationID: allocationID, poi: poi || 'none provided', + publicPOI: publicPOI || 'none provided', + poiBlockNumber: poiBlockNumber || 'none provided', }) const allocation = await this.network.networkMonitor.allocation(allocationID) @@ -917,10 +927,14 @@ export class AllocationManager { poi: string | undefined, amount: bigint, force: boolean, + poiBlockNumber: number | undefined, + publicPOI: string | undefined, ): Promise { logger.info('Preparing to reallocate', { allocation: allocationID, poi: poi || 'none provided', + publicPOI: publicPOI || 'none provided', + poiBlockNumber: poiBlockNumber || 'none provided', amount: amount.toString(), force, }) @@ -942,32 +956,40 @@ export class AllocationManager { allocation: allocationID, deployment: allocation.subgraphDeployment.id.ipfsHash, }) - const { poi: allocationPOI } = await this.network.networkMonitor.resolvePOI( + const poiData = await this.network.networkMonitor.resolvePOI( allocation, poi, - undefined, - undefined, + publicPOI, + poiBlockNumber, force, ) logger.debug('POI resolved', { deployment: allocation.subgraphDeployment.id.ipfsHash, userProvidedPOI: poi, - poi: allocationPOI, + userProvidedPublicPOI: publicPOI, + userProvidedBlockNumber: poiBlockNumber, + poi: poiData.poi, + publicPOI: poiData.publicPOI, + blockNumber: poiData.blockNumber, + force, }) // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized, Claimed } - // - // in the this.contracts. - const state = await this.network.contracts.HorizonStaking.getAllocationState( - allocation.id, - ) - if (state !== 1n) { - logger.warn(`Allocation has already been closed`) - throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) + if (allocation.isLegacy) { + const state = await this.network.contracts.HorizonStaking.getAllocationState( + allocation.id, + ) + if (state !== 1n) { + logger.warn(`Allocation has already been closed`) + throw indexerError(IndexerErrorCode.IE065, `Legacy allocation has already been closed`) + } + } else { + const allocationData = await this.network.contracts.SubgraphService.getAllocation(allocationID) + if (allocationData.closedAt !== 0n) { + logger.warn(`Allocation has already been closed`) + throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) + } } if (amount < 0n) { @@ -981,11 +1003,15 @@ export class AllocationManager { } logger.debug('Generating a new unique Allocation ID') + const activeAndRecentlyClosedAllocations: Allocation[] = [ + ...context.recentlyClosedAllocations, + ...context.activeAllocations, + ] const { allocationSigner, allocationId: newAllocationId } = uniqueAllocationID( this.network.transactionManager.wallet.mnemonic!.phrase, Number(context.currentEpoch), allocation.subgraphDeployment.id, - context.activeAllocations.map((allocation) => allocation.id), + activeAndRecentlyClosedAllocations.map((allo) => allo.id), ) logger.debug('New unique Allocation ID generated', { @@ -995,34 +1021,56 @@ export class AllocationManager { // Double-check whether the allocationID already exists on chain, to // avoid unnecessary transactions. - // Note: We're checking the allocation state here, which is defined as - // - // enum AllocationState { Null, Active, Closed, Finalized, Claimed } - // - // in the this.contracts. - const newAllocationState = - await this.network.contracts.HorizonStaking.getAllocationState(newAllocationId) - if (newAllocationState !== 0n) { - logger.warn(`Skipping Allocation as it already exists onchain`, { - indexer: this.network.specification.indexerOptions.address, - allocation: newAllocationId, - newAllocationState, - }) - throw indexerError(IndexerErrorCode.IE066, 'AllocationID already exists') + const isHorizon = await this.network.isHorizon.value() + if (isHorizon) { + const allocationData = await this.network.contracts.SubgraphService.getAllocation(newAllocationId) + if (allocationData.createdAt !== 0n) { + logger.warn(`Skipping allocation as it already exists onchain`, { + indexer: this.network.specification.indexerOptions.address, + allocation: newAllocationId, + allocationData, + isHorizon, + }) + throw indexerError(IndexerErrorCode.IE066, 'AllocationID already exists') + } + } else { + const newAllocationState = + await this.network.contracts.HorizonStaking.getAllocationState(newAllocationId) + if (newAllocationState !== 0n) { + logger.warn(`Skipping allocation as it already exists onchain (legacy)`, { + indexer: this.network.specification.indexerOptions.address, + allocation: newAllocationId, + newAllocationState, + isHorizon, + }) + throw indexerError(IndexerErrorCode.IE066, 'Legacy AllocationID already exists') + } } + logger.debug('Generating new allocation ID proof', { newAllocationSigner: allocationSigner, newAllocationID: newAllocationId, indexerAddress: this.network.specification.indexerOptions.address, + isHorizon, }) - const proof = await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - newAllocationId, - ) + const proof = isHorizon + ? await horizonAllocationIdProof( + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + newAllocationId, + this.network.contracts.SubgraphService.target.toString(), + ) + : await legacyAllocationIdProof( + allocationSigner, + this.network.specification.indexerOptions.address, + newAllocationId, + ) + logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, + isHorizon, }) logger.info(`Prepared close and allocate multicall transaction`, { @@ -1032,14 +1080,15 @@ export class AllocationManager { newAllocation: newAllocationId, newAllocationAmount: formatGRT(amount), deployment: allocation.subgraphDeployment.id.toString(), - poi: allocationPOI, + poi: poiData, proof, epoch: context.currentEpoch.toString(), }) return { closingAllocationID: allocation.id, - poi: allocationPOI, + closingAllocationIsLegacy: allocation.isLegacy, + poi: poiData, indexer: this.network.specification.indexerOptions.address, subgraphDeploymentID: allocation.subgraphDeployment.id.bytes32, tokens: amount, @@ -1055,9 +1104,18 @@ export class AllocationManager { receipt: TransactionReceipt | 'paused' | 'unauthorized', ): Promise { const logger = this.logger.child({ action: actionID }) - logger.info(`Confirming close and allocate 'multicall' transaction`, { + const isHorizon = await this.network.isHorizon.value() + + // This could be a tx to the staking contract or the subgraph service contract + const isStakingContract = + (receipt as TransactionReceipt).to === this.network.contracts.HorizonStaking.target + + logger.info(`Confirming reallocate transaction`, { allocationID, + isHorizon, + isStakingContract, }) + if (receipt === 'paused' || receipt === 'unauthorized') { throw indexerError( IndexerErrorCode.IE062, @@ -1065,68 +1123,128 @@ export class AllocationManager { ) } - const closeAllocationEventLogs = this.network.transactionManager.findEvent( - 'AllocationClosed', - this.network.contracts.LegacyStaking.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) + let closeAllocationEventLogs + let createAllocationEventLogs + let subgraphDeploymentID + let rewardsAssigned - if (!closeAllocationEventLogs) { - throw indexerError( - IndexerErrorCode.IE015, - `Allocation close transaction was never successfully mined`, + if (isStakingContract) { + // tx to the staking contract can be one of the following: + // - closeAllocation for a legacy allocation + // - allocateFrom for a legacy allocation before horizon + + closeAllocationEventLogs = this.network.transactionManager.findEvent( + 'AllocationClosed', + this.network.contracts.LegacyStaking.interface, + 'allocationID', + allocationID, + receipt, + this.logger, ) - } - const createAllocationEventLogs = this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - closeAllocationEventLogs.subgraphDeploymentID, - receipt, - this.logger, - ) + if (!closeAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Legacy allocation close transaction was never successfully mined`, + ) + } - if (!createAllocationEventLogs) { - throw indexerError( - IndexerErrorCode.IE014, - `Allocation create transaction was never mined`, + if (!isHorizon) { + createAllocationEventLogs = this.network.transactionManager.findEvent( + 'AllocationCreated', + this.network.contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + closeAllocationEventLogs.subgraphDeploymentID, + receipt, + this.logger, + ) + + if (!createAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE014, + `Legacy allocation create transaction was never mined`, + ) + } + } + + const rewardsEventLogs = this.network.transactionManager.findEvent( + 'RewardsAssigned', + this.network.contracts.RewardsManager.interface, + 'allocationID', + allocationID, + receipt, + this.logger, ) - } - const rewardsEventLogs = this.network.transactionManager.findEvent( - 'RewardsAssigned', - this.network.contracts.RewardsManager.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) + rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.amount : 0 - const rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.amount : 0 + if (rewardsAssigned == 0) { + logger.warn('No rewards were distributed upon closing the legacy allocation') + } - if (rewardsAssigned == 0) { - logger.warn('No rewards were distributed upon closing the allocation') - } + subgraphDeploymentID = new SubgraphDeploymentID( + closeAllocationEventLogs.subgraphDeploymentID, + ) + } else { + // tx to the subgraph service contract can be one of the following: + // - collect + stopService for a new allocation + // - startService for a new allocation - const subgraphDeploymentID = new SubgraphDeploymentID( - closeAllocationEventLogs.subgraphDeploymentID, - ) + closeAllocationEventLogs = this.network.transactionManager.findEvent( + 'AllocationClosed', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) + + if (!closeAllocationEventLogs) { + throw indexerError( + IndexerErrorCode.IE015, + `Allocation close transaction was never successfully mined`, + ) + } + + const rewardsEventLogs = this.network.transactionManager.findEvent( + 'IndexingRewardsCollected', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) + + rewardsAssigned = rewardsEventLogs ? rewardsEventLogs.tokensIndexerRewards : 0 + + if (rewardsAssigned == 0) { + logger.warn('No rewards were distributed upon closing the allocation') + } + + createAllocationEventLogs = this.network.transactionManager.findEvent( + 'AllocationCreated', + this.network.contracts.SubgraphService.interface, + 'indexer', + this.network.specification.indexerOptions.address, + receipt, + logger, + ) + + if (!createAllocationEventLogs) { + throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) + } + + subgraphDeploymentID = new SubgraphDeploymentID(closeAllocationEventLogs.subgraphDeploymentId) + } logger.info(`Successfully reallocated to deployment`, { deployment: subgraphDeploymentID.display, - closedAllocation: closeAllocationEventLogs.allocationID, + closedAllocation: allocationID, closedAllocationStakeGRT: formatGRT(closeAllocationEventLogs.tokens), - closedAllocationPOI: closeAllocationEventLogs.poi, - closedAllocationEpoch: closeAllocationEventLogs.epoch.toString(), indexingRewardsCollected: formatGRT(rewardsAssigned), createdAllocation: createAllocationEventLogs.allocationID, createdAllocationStakeGRT: formatGRT(createAllocationEventLogs.tokens), indexer: createAllocationEventLogs.indexer, - epoch: createAllocationEventLogs.epoch.toString(), transaction: receipt.hash, }) @@ -1170,6 +1288,8 @@ export class AllocationManager { poi: string | undefined, amount: bigint, force: boolean, + poiBlockNumber: number | undefined, + publicPOI: string | undefined, ): Promise { const params = await this.prepareReallocateParams( logger, @@ -1178,23 +1298,92 @@ export class AllocationManager { poi, amount, force, + poiBlockNumber, + publicPOI, ) - // TODO HORIZON: split into pre-post horizon - return [ - await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( + return this.populateReallocateTransaction(logger, params) + } + + async populateReallocateTransaction( + logger: Logger, + params: ReallocateTransactionParams, + ): Promise { + logger.debug('Populating reallocate transaction', { + closingAllocationID: params.closingAllocationID, + poi: params.poi, + indexer: params.indexer, + subgraphDeploymentID: params.subgraphDeploymentID, + tokens: params.tokens, + newAllocationID: params.newAllocationID, + metadata: params.metadata, + proof: params.proof, + }) + + const txs: TransactionRequest[] = [] + + // -- close allocation + if (params.closingAllocationIsLegacy) { + txs.push(await this.network.contracts.LegacyStaking.closeAllocation.populateTransaction( params.closingAllocationID, - params.poi, - ), - await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( + params.poi.poi, + )) + } else { + // Horizon: Need to multicall collect and stopService + + // collect + const collectIndexingRewardsData = encodeCollectIndexingRewardsData( + params.closingAllocationID, + params.poi.poi, + encodePOIMetadata( + params.poi.blockNumber, + params.poi.publicPOI, + params.poi.indexingStatus, + 0, + 0, + ), + ) + const collectCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( + 'collect', + [params.indexer, PaymentTypes.IndexingRewards, collectIndexingRewardsData], + ) + + // stopService + const stopServiceCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( + 'stopService', + [params.indexer, encodeStopServiceData(params.closingAllocationID)], + ) + + txs.push(await this.network.contracts.SubgraphService.multicall.populateTransaction( + [collectCallData, stopServiceCallData], + )) + } + + // -- create new allocation + const isHorizon = await this.network.isHorizon.value() + if (isHorizon) { + const encodedData = encodeStartServiceData( + params.subgraphDeploymentID.toString(), + BigInt(params.tokens), + params.newAllocationID, + params.proof.toString(), + ) + txs.push(await this.network.contracts.SubgraphService.startService.populateTransaction( + params.indexer, + encodedData, + )) + } else { + txs.push(await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( params.indexer, params.subgraphDeploymentID, params.tokens, params.newAllocationID, params.metadata, params.proof, - ), - ] + )) + } + + return txs } async matchingRuleExists( diff --git a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts index 9f8ee48ea..82142374f 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts @@ -1732,8 +1732,8 @@ export default { const poiData = await networkMonitor.resolvePOI( allocationData, poi, - allocationData.isLegacy ? undefined : publicPOI, - allocationData.isLegacy || blockNumber === null ? undefined : Number(blockNumber), + publicPOI, + blockNumber === null ? undefined : Number(blockNumber), force, ) logger.debug('POI resolved', { From 557f0021a77401f94550b90a510292fe229e5b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 10 Jun 2025 15:45:59 -0300 Subject: [PATCH 16/28] chore: clean up todos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-agent/src/agent.ts | 3 +-- packages/indexer-cli/src/provisions.ts | 2 +- packages/indexer-common/src/indexer-management/monitor.ts | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/indexer-agent/src/agent.ts b/packages/indexer-agent/src/agent.ts index 5df4e66ac..cd3e25737 100644 --- a/packages/indexer-agent/src/agent.ts +++ b/packages/indexer-agent/src/agent.ts @@ -252,8 +252,7 @@ export class Agent { }, ) - // TODO HORIZON: Uncomment this - // this.reconciliationLoop() + this.reconciliationLoop() return this } diff --git a/packages/indexer-cli/src/provisions.ts b/packages/indexer-cli/src/provisions.ts index 7540a7cff..175024e4c 100644 --- a/packages/indexer-cli/src/provisions.ts +++ b/packages/indexer-cli/src/provisions.ts @@ -22,7 +22,7 @@ export interface IndexerProvision { protocolNetwork: string - // TODO: This is not really a provision property, but useful to avoid creating new types + // This is not really a provision property, but useful to avoid creating new types thawingUntil: string } diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index 89e2d689b..b5e2b36f0 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -75,7 +75,7 @@ export class NetworkMonitor { const isHorizon = await this.isHorizon() if (isHorizon) { - // TODO: this assumes a block time of 12 seconds which is true for current protocol chain but not always + // TODO HORIZON: this assumes a block time of 12 seconds which is true for current protocol chain but not always const BLOCK_IN_SECONDS = 12n const epochLengthInBlocks = await this.contracts.EpochManager.epochLength() const epochLengthInSeconds = Number(epochLengthInBlocks * BLOCK_IN_SECONDS) From 0e448beee3f71c7e61cc58c0eeb27f76d17e5642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 10 Jun 2025 16:27:29 -0300 Subject: [PATCH 17/28] wip: graph tally support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../indexer-common/src/query-fees/models.ts | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/packages/indexer-common/src/query-fees/models.ts b/packages/indexer-common/src/query-fees/models.ts index 095d60fe0..71464f679 100644 --- a/packages/indexer-common/src/query-fees/models.ts +++ b/packages/indexer-common/src/query-fees/models.ts @@ -2,6 +2,8 @@ import { DataTypes, Sequelize, Model, Association, CreationOptional } from 'sequ import { Address, toAddress } from '@graphprotocol/common-ts' import { caip2IdRegex } from '../parsers' import { TAPVerifier } from '@semiotic-labs/tap-contracts-bindings' +import { RAV as RAVv2 } from '@graphprotocol/toolshed' +import { BytesLike } from 'ethers' export interface ScalarTapReceiptsAttributes { id: number @@ -100,6 +102,21 @@ export interface ReceiptAggregateVoucherAttributes { redeemedAt: Date | null final: boolean } + +export interface ReceiptAggregateVoucherV2Attributes { + collectionId: string + payer: string + serviceProvider: string + dataService: string + metadata: string + signature: Uint8Array + timestampNs: bigint + valueAggregate: bigint + last: boolean + redeemedAt: Date | null + final: boolean +} + export interface FailedReceiptAggregateVoucherAttributes { allocationId: string senderAddress: string @@ -142,6 +159,53 @@ export class ReceiptAggregateVoucher } } +// TODO HORIZON: move this to the toolshed package +export type SignedRAVv2 = { + rav: RAVv2 + signature: BytesLike +} + +export class ReceiptAggregateVoucherV2 + extends Model + implements ReceiptAggregateVoucherV2Attributes +{ + public collectionId!: Address + public payer!: Address + public serviceProvider!: Address + public dataService!: Address + public metadata!: string + public signature!: Uint8Array + public timestampNs!: bigint + public valueAggregate!: bigint + public final!: boolean + public last!: boolean + public redeemedAt!: Date | null + + declare createdAt: CreationOptional + declare updatedAt: CreationOptional + + public readonly allocationSummary?: AllocationSummary + + public static associations: { + allocationSummary: Association + } + + getSignedRAV(): SignedRAVv2 { + return { + rav: { + collectionId: this.collectionId, + payer: this.payer, + serviceProvider: this.serviceProvider, + dataService: this.dataService, + timestampNs: Number(this.timestampNs), + valueAggregate: this.valueAggregate, + metadata: this.metadata, + }, + signature: this.signature, + } + } +} + export type SignedRAV = TAPVerifier.SignedRAVStruct export class FailedReceiptAggregateVoucher @@ -265,6 +329,7 @@ export interface QueryFeeModels { allocationReceipts: typeof AllocationReceipt vouchers: typeof Voucher receiptAggregateVouchers: typeof ReceiptAggregateVoucher + receiptAggregateVouchersV2: typeof ReceiptAggregateVoucherV2 transferReceipts: typeof TransferReceipt transfers: typeof Transfer allocationSummaries: typeof AllocationSummary @@ -416,6 +481,110 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { }, ) + + ReceiptAggregateVoucherV2.init( + { + collectionId: { + type: DataTypes.CHAR(64), // 64 because prefix '0x' gets removed by GraphTally agent + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('collectionId') + return toAddress(rawValue) + }, + set(value: Address) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('collectionId', addressWithoutPrefix) + }, + }, + payer: { + type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('payer') + return toAddress(rawValue) + }, + set(value: string) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('payer', addressWithoutPrefix) + }, + }, + serviceProvider: { + type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('serviceProvider') + return toAddress(rawValue) + }, + set(value: string) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('serviceProvider', addressWithoutPrefix) + }, + }, + dataService: { + type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('dataService') + return toAddress(rawValue) + }, + set(value: string) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('dataService', addressWithoutPrefix) + }, + }, + metadata: { + type: DataTypes.STRING, + allowNull: false, + }, + signature: { + type: DataTypes.BLOB, + allowNull: false, + }, + // ternary operator added to timestampNs and valueAggregate + // due to sequelize UPDATE + // calls the getters with undefined data + // 0 is returned since no real data is being requested + timestampNs: { + type: DataTypes.DECIMAL, + allowNull: false, + get() { + return BigInt(this.getDataValue('timestampNs')) + }, + }, + valueAggregate: { + type: DataTypes.DECIMAL, + allowNull: false, + get() { + return BigInt(this.getDataValue('valueAggregate')) + }, + }, + last: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + final: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + redeemedAt: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null, + }, + }, + { + underscored: true, + sequelize, + tableName: 'scalar_tap_ravs', + }, + ) + TransferReceipt.init( { id: { @@ -718,6 +887,7 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { allocationReceipts: AllocationReceipt, vouchers: Voucher, receiptAggregateVouchers: ReceiptAggregateVoucher, + receiptAggregateVouchersV2: ReceiptAggregateVoucherV2, transferReceipts: TransferReceipt, transfers: Transfer, allocationSummaries: AllocationSummary, From bff35ba9115f2697d15df0bf3ae851f679eb4342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 18 Jun 2025 11:15:06 -0300 Subject: [PATCH 18/28] chore: update toolshed to 0.6.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../migrations/20-actions-add-poi-metadata.ts | 4 +- packages/indexer-cli/src/allocations.ts | 16 +- packages/indexer-cli/src/command-helpers.ts | 11 +- .../src/commands/indexer/allocations/close.ts | 12 +- .../commands/indexer/allocations/create.ts | 13 +- .../src/commands/indexer/allocations/get.ts | 8 +- packages/indexer-common/package.json | 2 +- packages/indexer-common/src/actions.ts | 2 +- .../src/indexer-management/allocations.ts | 292 ++++++++++-------- .../src/indexer-management/monitor.ts | 20 +- .../resolvers/indexer-status.ts | 2 +- packages/indexer-common/src/network.ts | 2 +- .../indexer-common/src/query-fees/models.ts | 1 - yarn.lock | 30 +- 14 files changed, 237 insertions(+), 178 deletions(-) diff --git a/packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts b/packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts index 3351013b9..ba1b86abd 100644 --- a/packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts +++ b/packages/indexer-agent/src/db/migrations/20-actions-add-poi-metadata.ts @@ -25,7 +25,9 @@ export async function up({ context }: Context): Promise { const publicPOI = table.publicPOI const poiBlockNumber = table.poiBlockNumber if (publicPOI && poiBlockNumber) { - logger.info(`'publicPOI' and 'poiBlockNumber' columns already exist, migration not necessary`) + logger.info( + `'publicPOI' and 'poiBlockNumber' columns already exist, migration not necessary`, + ) return } diff --git a/packages/indexer-cli/src/allocations.ts b/packages/indexer-cli/src/allocations.ts index 1abbf291d..445582059 100644 --- a/packages/indexer-cli/src/allocations.ts +++ b/packages/indexer-cli/src/allocations.ts @@ -151,7 +151,9 @@ export const displayIndexerAllocations = ( : table( [ Object.keys(allocations[0]), - ...allocations.map(allocation => Object.values(allocation).map(value => wrapCell(value, wrapWidth))), + ...allocations.map(allocation => + Object.values(allocation).map(value => wrapCell(value, wrapWidth)), + ), ], { border: getBorderCharacters('norc'), @@ -167,9 +169,15 @@ export const displayIndexerAllocation = ( ? JSON.stringify(allocation, null, 2) : outputFormat === OutputFormat.Yaml ? yaml.stringify(allocation).trim() - : table([Object.keys(allocation), Object.values(allocation).map(value => wrapCell(value, wrapWidth))], { - border: getBorderCharacters('norc'), - }).trim() + : table( + [ + Object.keys(allocation), + Object.values(allocation).map(value => wrapCell(value, wrapWidth)), + ], + { + border: getBorderCharacters('norc'), + }, + ).trim() function nullPassThrough(fn: (x: T) => U): (x: T | null) => U | null { return (x: T | null) => (x === null ? null : fn(x)) diff --git a/packages/indexer-cli/src/command-helpers.ts b/packages/indexer-cli/src/command-helpers.ts index b386501c2..212a9b7c8 100644 --- a/packages/indexer-cli/src/command-helpers.ts +++ b/packages/indexer-cli/src/command-helpers.ts @@ -100,12 +100,16 @@ export function pickFields( } } for (const key of drop) { - delete obj[key] + delete obj[key] } return obj } -export function displayObjectData(outputFormat: OutputFormat, data: object, wrapWidth: number): string { +export function displayObjectData( + outputFormat: OutputFormat, + data: object, + wrapWidth: number, +): string { if (outputFormat === OutputFormat.Json) { return JSON.stringify(data, null, 2) } else if (outputFormat === OutputFormat.Yaml) { @@ -269,9 +273,8 @@ export function requireProtocolNetworkOption(options: { [key: string]: any }): s return protocolNetwork } - export function wrapCell(value: unknown, wrapWidth: number): string { return wrapWidth > 0 ? wrapAnsi(String(value), wrapWidth, { hard: true }) : String(value) -} \ No newline at end of file +} diff --git a/packages/indexer-cli/src/commands/indexer/allocations/close.ts b/packages/indexer-cli/src/commands/indexer/allocations/close.ts index af3c0dac9..3e4c033c4 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/close.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/close.ts @@ -104,11 +104,13 @@ module.exports = { ) spinner.succeed('Allocation closed') - printObjectOrArray(print, outputFormat, closeResult, [ - 'allocation', - 'allocatedTokens', - 'indexingRewards', - ], wrapWidth) + printObjectOrArray( + print, + outputFormat, + closeResult, + ['allocation', 'allocatedTokens', 'indexingRewards'], + wrapWidth, + ) } catch (error) { spinner.fail(error.toString()) process.exitCode = 1 diff --git a/packages/indexer-cli/src/commands/indexer/allocations/create.ts b/packages/indexer-cli/src/commands/indexer/allocations/create.ts index addccc7a3..f635e4d34 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/create.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/create.ts @@ -85,12 +85,13 @@ module.exports = { ) spinner.succeed('Allocation created') - printObjectOrArray(print, outputFormat, allocateResult, [ - 'allocation', - 'deployment', - 'allocatedTokens', - 'protocolNetwork', - ], wrapWidth) + printObjectOrArray( + print, + outputFormat, + allocateResult, + ['allocation', 'deployment', 'allocatedTokens', 'protocolNetwork'], + wrapWidth, + ) } catch (error) { spinner.fail(error.toString()) process.exitCode = 1 diff --git a/packages/indexer-cli/src/commands/indexer/allocations/get.ts b/packages/indexer-cli/src/commands/indexer/allocations/get.ts index 6e62b93e6..5be6a6f70 100644 --- a/packages/indexer-cli/src/commands/indexer/allocations/get.ts +++ b/packages/indexer-cli/src/commands/indexer/allocations/get.ts @@ -171,7 +171,13 @@ module.exports = { ) } spinner.succeed('Allocations') - printIndexerAllocations(print, outputFormat, allocations, displayProperties, wrapWidth) + printIndexerAllocations( + print, + outputFormat, + allocations, + displayProperties, + wrapWidth, + ) } catch (error) { spinner.fail(error.toString()) process.exitCode = 1 diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index af1dd37de..ce7cc9edf 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -24,7 +24,7 @@ "dependencies": { "@pinax/graph-networks-registry": "0.6.7", "@graphprotocol/common-ts": "3.0.1", - "@graphprotocol/toolshed": "0.5.5", + "@graphprotocol/toolshed": "0.6.4", "@semiotic-labs/tap-contracts-bindings": "2.0.0", "@thi.ng/heaps": "1.2.38", "@types/lodash.clonedeep": "^4.5.7", diff --git a/packages/indexer-common/src/actions.ts b/packages/indexer-common/src/actions.ts index b639d1ebe..68769dc9b 100644 --- a/packages/indexer-common/src/actions.ts +++ b/packages/indexer-common/src/actions.ts @@ -86,7 +86,7 @@ export const isValidActionInput = ( 'deploymentID' in variableToCheck && 'allocationID' in variableToCheck && 'amount' in variableToCheck - + if (!variableToCheck.isLegacy && variableToCheck.poi !== undefined) { hasActionParams = hasActionParams && diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index 5cd1401c2..7f279d091 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -36,7 +36,11 @@ import { isActionFailureArray, POIData, } from '@graphprotocol/indexer-common' -import { encodeStartServiceData, encodeStopServiceData, PaymentTypes } from '@graphprotocol/toolshed' +import { + encodeStartServiceData, + encodeStopServiceData, + PaymentTypes, +} from '@graphprotocol/toolshed' import { encodeCollectIndexingRewardsData, encodePOIMetadata, @@ -113,7 +117,7 @@ export class AllocationManager { private models: IndexerManagementModels, private graphNode: GraphNode, private network: Network, - ) { } + ) {} async executeBatch( actions: Action[], @@ -544,17 +548,17 @@ export class AllocationManager { const proof = isHorizon ? await horizonAllocationIdProof( - allocationSigner, - Number(this.network.specification.networkIdentifier.split(':')[1]), - this.network.specification.indexerOptions.address, - allocationId, - this.network.contracts.SubgraphService.target.toString(), - ) + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + allocationId, + this.network.contracts.SubgraphService.target.toString(), + ) : await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - allocationId, - ) + allocationSigner, + this.network.specification.indexerOptions.address, + allocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, @@ -588,28 +592,29 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE062, - `Allocation not created. ${receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + `Allocation not created. ${ + receipt === 'paused' ? 'Network paused' : 'Operator not authorized' }`, ) } const createAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - subgraphDeployment.bytes32, - receipt, - this.logger, - ) + 'AllocationCreated', + this.network.contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + subgraphDeployment.bytes32, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.SubgraphService.interface, - 'indexer', - this.network.specification.indexerOptions.address, - receipt, - logger, - ) + 'AllocationCreated', + this.network.contracts.SubgraphService.interface, + 'indexer', + this.network.specification.indexerOptions.address, + receipt, + logger, + ) if (!createAllocationEventLogs) { throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) @@ -617,9 +622,13 @@ export class AllocationManager { logger.info(`Successfully allocated to subgraph deployment`, { amountGRT: formatGRT(createAllocationEventLogs.tokens), - allocation: isLegacy ? createAllocationEventLogs.allocationID : createAllocationEventLogs.allocationId, + allocation: isLegacy + ? createAllocationEventLogs.allocationID + : createAllocationEventLogs.allocationId, deployment: createAllocationEventLogs.subgraphDeploymentID, - epoch: isLegacy ? createAllocationEventLogs.epoch.toString() : createAllocationEventLogs.currentEpoch.toString(), + epoch: isLegacy + ? createAllocationEventLogs.epoch.toString() + : createAllocationEventLogs.currentEpoch.toString(), isLegacy, }) @@ -645,7 +654,9 @@ export class AllocationManager { type: 'allocate', transactionID: receipt.hash, deployment: deployment, - allocation: isLegacy ? createAllocationEventLogs.allocationID : createAllocationEventLogs.allocationId, + allocation: isLegacy + ? createAllocationEventLogs.allocationID + : createAllocationEventLogs.allocationId, allocatedTokens: amount, protocolNetwork: this.network.specification.networkIdentifier, } @@ -730,7 +741,8 @@ export class AllocationManager { throw indexerError(IndexerErrorCode.IE065) } } else { - const allocation = await this.network.contracts.SubgraphService.getAllocation(allocationID) + const allocation = + await this.network.contracts.SubgraphService.getAllocation(allocationID) if (allocation.closedAt !== 0n) { throw indexerError(IndexerErrorCode.IE065) } @@ -764,21 +776,23 @@ export class AllocationManager { ) } - const closeAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'AllocationClosed', - this.network.contracts.LegacyStaking.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) : this.network.transactionManager.findEvent( - 'AllocationClosed', - this.network.contracts.SubgraphService.interface, - 'allocationId', - allocationID, - receipt, - this.logger, - ) + const closeAllocationEventLogs = isLegacy + ? this.network.transactionManager.findEvent( + 'AllocationClosed', + this.network.contracts.LegacyStaking.interface, + 'allocationID', + allocationID, + receipt, + this.logger, + ) + : this.network.transactionManager.findEvent( + 'AllocationClosed', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) if (!closeAllocationEventLogs) { throw indexerError( @@ -787,32 +801,38 @@ export class AllocationManager { ) } - const rewardsEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'RewardsAssigned', - this.network.contracts.RewardsManager.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) : this.network.transactionManager.findEvent( - 'IndexingRewardsCollected', - this.network.contracts.SubgraphService.interface, - 'allocationId', - allocationID, - receipt, - this.logger, - ) + const rewardsEventLogs = isLegacy + ? this.network.transactionManager.findEvent( + 'RewardsAssigned', + this.network.contracts.RewardsManager.interface, + 'allocationID', + allocationID, + receipt, + this.logger, + ) + : this.network.transactionManager.findEvent( + 'IndexingRewardsCollected', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) - const rewardsAssigned = rewardsEventLogs ? - (isLegacy ? rewardsEventLogs.amount : rewardsEventLogs.tokensIndexerRewards) : - 0 + const rewardsAssigned = rewardsEventLogs + ? isLegacy + ? rewardsEventLogs.amount + : rewardsEventLogs.tokensIndexerRewards + : 0 if (rewardsAssigned == 0) { logger.warn('No rewards were distributed upon closing the allocation') } const subgraphDeploymentID = new SubgraphDeploymentID( - isLegacy ? closeAllocationEventLogs.subgraphDeploymentID : closeAllocationEventLogs.subgraphDeploymentId, + isLegacy + ? closeAllocationEventLogs.subgraphDeploymentID + : closeAllocationEventLogs.subgraphDeploymentId, ) logger.info(`Successfully closed allocation`, { @@ -882,20 +902,24 @@ export class AllocationManager { 0, ), ) - const collectCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( - 'collect', - [params.indexer, PaymentTypes.IndexingRewards, collectIndexingRewardsData], - ) + const collectCallData = + this.network.contracts.SubgraphService.interface.encodeFunctionData('collect', [ + params.indexer, + PaymentTypes.IndexingRewards, + collectIndexingRewardsData, + ]) // stopService - const stopServiceCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( - 'stopService', - [params.indexer, encodeStopServiceData(params.allocationID)], - ) + const stopServiceCallData = + this.network.contracts.SubgraphService.interface.encodeFunctionData( + 'stopService', + [params.indexer, encodeStopServiceData(params.allocationID)], + ) - return await this.network.contracts.SubgraphService.multicall.populateTransaction( - [collectCallData, stopServiceCallData], - ) + return await this.network.contracts.SubgraphService.multicall.populateTransaction([ + collectCallData, + stopServiceCallData, + ]) } } @@ -982,10 +1006,14 @@ export class AllocationManager { ) if (state !== 1n) { logger.warn(`Allocation has already been closed`) - throw indexerError(IndexerErrorCode.IE065, `Legacy allocation has already been closed`) + throw indexerError( + IndexerErrorCode.IE065, + `Legacy allocation has already been closed`, + ) } } else { - const allocationData = await this.network.contracts.SubgraphService.getAllocation(allocationID) + const allocationData = + await this.network.contracts.SubgraphService.getAllocation(allocationID) if (allocationData.closedAt !== 0n) { logger.warn(`Allocation has already been closed`) throw indexerError(IndexerErrorCode.IE065, `Allocation has already been closed`) @@ -1023,7 +1051,8 @@ export class AllocationManager { // avoid unnecessary transactions. const isHorizon = await this.network.isHorizon.value() if (isHorizon) { - const allocationData = await this.network.contracts.SubgraphService.getAllocation(newAllocationId) + const allocationData = + await this.network.contracts.SubgraphService.getAllocation(newAllocationId) if (allocationData.createdAt !== 0n) { logger.warn(`Skipping allocation as it already exists onchain`, { indexer: this.network.specification.indexerOptions.address, @@ -1047,7 +1076,6 @@ export class AllocationManager { } } - logger.debug('Generating new allocation ID proof', { newAllocationSigner: allocationSigner, newAllocationID: newAllocationId, @@ -1056,17 +1084,17 @@ export class AllocationManager { }) const proof = isHorizon ? await horizonAllocationIdProof( - allocationSigner, - Number(this.network.specification.networkIdentifier.split(':')[1]), - this.network.specification.indexerOptions.address, - newAllocationId, - this.network.contracts.SubgraphService.target.toString(), - ) + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + newAllocationId, + this.network.contracts.SubgraphService.target.toString(), + ) : await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - newAllocationId, - ) + allocationSigner, + this.network.specification.indexerOptions.address, + newAllocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, @@ -1234,7 +1262,9 @@ export class AllocationManager { throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) } - subgraphDeploymentID = new SubgraphDeploymentID(closeAllocationEventLogs.subgraphDeploymentId) + subgraphDeploymentID = new SubgraphDeploymentID( + closeAllocationEventLogs.subgraphDeploymentId, + ) } logger.info(`Successfully reallocated to deployment`, { @@ -1324,10 +1354,12 @@ export class AllocationManager { // -- close allocation if (params.closingAllocationIsLegacy) { - txs.push(await this.network.contracts.LegacyStaking.closeAllocation.populateTransaction( - params.closingAllocationID, - params.poi.poi, - )) + txs.push( + await this.network.contracts.LegacyStaking.closeAllocation.populateTransaction( + params.closingAllocationID, + params.poi.poi, + ), + ) } else { // Horizon: Need to multicall collect and stopService @@ -1343,20 +1375,26 @@ export class AllocationManager { 0, ), ) - const collectCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( - 'collect', - [params.indexer, PaymentTypes.IndexingRewards, collectIndexingRewardsData], - ) + const collectCallData = + this.network.contracts.SubgraphService.interface.encodeFunctionData('collect', [ + params.indexer, + PaymentTypes.IndexingRewards, + collectIndexingRewardsData, + ]) // stopService - const stopServiceCallData = this.network.contracts.SubgraphService.interface.encodeFunctionData( - 'stopService', - [params.indexer, encodeStopServiceData(params.closingAllocationID)], - ) + const stopServiceCallData = + this.network.contracts.SubgraphService.interface.encodeFunctionData( + 'stopService', + [params.indexer, encodeStopServiceData(params.closingAllocationID)], + ) - txs.push(await this.network.contracts.SubgraphService.multicall.populateTransaction( - [collectCallData, stopServiceCallData], - )) + txs.push( + await this.network.contracts.SubgraphService.multicall.populateTransaction([ + collectCallData, + stopServiceCallData, + ]), + ) } // -- create new allocation @@ -1368,19 +1406,23 @@ export class AllocationManager { params.newAllocationID, params.proof.toString(), ) - txs.push(await this.network.contracts.SubgraphService.startService.populateTransaction( - params.indexer, - encodedData, - )) + txs.push( + await this.network.contracts.SubgraphService.startService.populateTransaction( + params.indexer, + encodedData, + ), + ) } else { - txs.push(await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( - params.indexer, - params.subgraphDeploymentID, - params.tokens, - params.newAllocationID, - params.metadata, - params.proof, - )) + txs.push( + await this.network.contracts.LegacyStaking.allocateFrom.populateTransaction( + params.indexer, + params.subgraphDeploymentID, + params.tokens, + params.newAllocationID, + params.metadata, + params.proof, + ), + ) } return txs @@ -1441,9 +1483,9 @@ export class AllocationManager { action.poi === zeroHexString ? 0n : await this.network.contracts.RewardsManager.getRewards( - this.network.contracts.HorizonStaking.target, - action.allocationID, - ) + this.network.contracts.HorizonStaking.target, + action.allocationID, + ) unallocates = unallocates + allocation.allocatedTokens } @@ -1503,10 +1545,10 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE013, `Unfeasible action batch: Approved action batch GRT balance is ` + - `${formatGRT(batchDelta)} for horizon actions and ` + - `${formatGRT(batchDeltaLegacy)} for legacy actions ` + - `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + - `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, + `${formatGRT(batchDelta)} for horizon actions and ` + + `${formatGRT(batchDeltaLegacy)} for legacy actions ` + + `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + + `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, ) } } diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index b5e2b36f0..845a973f7 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -56,7 +56,7 @@ export class NetworkMonitor { private networkSubgraph: SubgraphClient, private ethereum: Provider, private epochSubgraph: SubgraphClient, - ) { } + ) {} poiDisputeMonitoringEnabled(): boolean { return this.indexerOptions.poiDisputeMonitoring @@ -285,7 +285,8 @@ export class NetworkMonitor { if (allocations.length === 0) { this.logger.warn( - `No ${AllocationStatus[status.toUpperCase() as keyof typeof AllocationStatus] + `No ${ + AllocationStatus[status.toUpperCase() as keyof typeof AllocationStatus] } allocations found for indexer '${this.indexerOptions.address}'`, ) } @@ -1559,10 +1560,11 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n IndexerErrorCode.IE067, `POI not available for deployment at current epoch start block. currentEpochStartBlock: ${epochStartBlock.number} - deploymentStatus: ${deploymentStatus.length > 0 + deploymentStatus: ${ + deploymentStatus.length > 0 ? JSON.stringify(deploymentStatus) : 'not deployed' - }`, + }`, ) } else { return [poi, epochStartBlock.number] @@ -1597,7 +1599,10 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n let returnBlockNumber = 0 if (generatedPOIBlockNumber === 0) { if (blockNumber === undefined) { - throw indexerError(IndexerErrorCode.IE084, 'No block number generated and none provided') + throw indexerError( + IndexerErrorCode.IE084, + 'No block number generated and none provided', + ) } returnBlockNumber = blockNumber } else if (blockNumber === undefined || generatedPOIBlockNumber === blockNumber) { @@ -1638,7 +1643,10 @@ Please submit an issue at https://github.com/graphprotocol/block-oracle/issues/n let returnPublicPOI: string if (generatedPublicPOI === undefined) { if (publicPOI === undefined) { - throw indexerError(IndexerErrorCode.IE085, 'No public POI generated and none provided') + throw indexerError( + IndexerErrorCode.IE085, + 'No public POI generated and none provided', + ) } returnPublicPOI = publicPOI } else if (publicPOI === undefined || generatedPublicPOI === publicPOI) { diff --git a/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts b/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts index 5941f37b1..e8744997b 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/indexer-status.ts @@ -87,7 +87,7 @@ export default { address, protocolNetwork, url: service.url, - location: geohash.decode(service.geohash), + location: geohash.decode(service.geoHash), registered, isLegacy: true, __typename: 'IndexerRegistration', diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index 38ecf4cec..719392bc8 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -661,7 +661,7 @@ export class Network { const service = await this.contracts.LegacyServiceRegistry.services( this.specification.indexerOptions.address, ) - if (service.url === url && service.geohash === geoHash) { + if (service.url === url && service.geoHash === geoHash) { if (await this.transactionManager.isOperator.value()) { logger.info(`Indexer already registered, operator status already granted`) } else { diff --git a/packages/indexer-common/src/query-fees/models.ts b/packages/indexer-common/src/query-fees/models.ts index 71464f679..0193f3a2c 100644 --- a/packages/indexer-common/src/query-fees/models.ts +++ b/packages/indexer-common/src/query-fees/models.ts @@ -481,7 +481,6 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { }, ) - ReceiptAggregateVoucherV2.init( { collectionId: { diff --git a/yarn.lock b/yarn.lock index 3c7c35793..eda196cec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -568,15 +568,10 @@ prom-client "14.2.0" sequelize "6.33.0" -"@graphprotocol/contracts@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@graphprotocol/contracts/-/contracts-7.1.2.tgz#919cf6747d25cb52855d01be6582c06695ae3b83" - integrity sha512-t8o0nA+cs5HEKLxjaV0zELBtDLAPm6hoXi0o5tnpw7vigyMPoP92QQkVfbjAt9eMnkC7/AyGRWOMBfAZV9l8Og== - -"@graphprotocol/horizon@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@graphprotocol/horizon/-/horizon-0.3.3.tgz#2fe0a9ebf27532b5deea94443d47342e159d43c8" - integrity sha512-aAQ7zOaqGE/nMuu+h2CGwO8Tkho/m1CcezfOz54voBpFSqfxk2WggYe1lUWd+nvHpuynfgaqM4gW+kYTLliWYw== +"@graphprotocol/interfaces@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@graphprotocol/interfaces/-/interfaces-0.2.4.tgz#57e4d391db2f2add181667808d25c99f196e2897" + integrity sha512-a4IiWnKHenL5pli8YXNz/l3idkdWQX1CBT2wqiesqUXt1HKGLMreWySEtrcQHOsCl0jdCMzIMdnAd7KlCZQsCQ== "@graphprotocol/pino-sentry-simple@0.7.1": version "0.7.1" @@ -588,19 +583,12 @@ split2 "^3.1.1" through2 "^3.0.1" -"@graphprotocol/subgraph-service@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.3.5.tgz#38af1602b73602c57617e915ccf77c89a386a356" - integrity sha512-QmcQ4eOoUkmA+yStnRwIPAjCDyqIyQ0hLTL9IRZPDXs5a0ye7Kd9XIZDikuPlm1Bdqwu+tr2/yYdc3x3t0Sx2Q== - -"@graphprotocol/toolshed@0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.5.5.tgz#7fccd11499a5938fb51a1eb822ea8faaed05fdc1" - integrity sha512-fS/FmGAukWq2MjW4uOOJ/y+fXY6vB5kiZORLmKTN36hJnBXJsCOs6u8JNWER2E5MN4iTMSOLd6fj9JgncDNhsg== +"@graphprotocol/toolshed@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.6.4.tgz#f9be510403b808864fe81a969c04020c5e92b240" + integrity sha512-uFgR6LNxp+3IM4z0+Hb/968PzCGkpECwcdhb3l1jtsMV/PMmYfnsOJqphC84DbHUBG8WNT62D2WQEY9c8ZSucQ== dependencies: - "@graphprotocol/contracts" "^7.1.2" - "@graphprotocol/horizon" "^0.3.3" - "@graphprotocol/subgraph-service" "^0.3.5" + "@graphprotocol/interfaces" "^0.2.4" "@nomicfoundation/hardhat-ethers" "3.0.8" debug "^4.4.0" ethers "6.13.7" From 7697a938085e76c50761c06f5ff26ba857d83a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 18 Jun 2025 12:48:20 -0300 Subject: [PATCH 19/28] fix: rewardsmanager events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-common/package.json | 2 +- .../src/indexer-management/allocations.ts | 5 +++-- .../resolvers/allocations.ts | 6 ++++-- yarn.lock | 18 +++++++++--------- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index ce7cc9edf..866db698b 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -24,7 +24,7 @@ "dependencies": { "@pinax/graph-networks-registry": "0.6.7", "@graphprotocol/common-ts": "3.0.1", - "@graphprotocol/toolshed": "0.6.4", + "@graphprotocol/toolshed": "0.6.5", "@semiotic-labs/tap-contracts-bindings": "2.0.0", "@thi.ng/heaps": "1.2.38", "@types/lodash.clonedeep": "^4.5.7", diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index 7f279d091..920a75ab0 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -764,6 +764,7 @@ export class AllocationManager { const logger = this.logger.child({ action: actionID }) const isLegacy = (receipt as TransactionReceipt).to === this.network.contracts.HorizonStaking.target + const isHorizon = await this.network.isHorizon.value() logger.info(`Confirming unallocate transaction`, { isLegacy, @@ -803,7 +804,7 @@ export class AllocationManager { const rewardsEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'RewardsAssigned', + isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', this.network.contracts.RewardsManager.interface, 'allocationID', allocationID, @@ -1196,7 +1197,7 @@ export class AllocationManager { } const rewardsEventLogs = this.network.transactionManager.findEvent( - 'RewardsAssigned', + isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', this.network.contracts.RewardsManager.interface, 'allocationID', allocationID, diff --git a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts index 82142374f..dda8f24d0 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts @@ -636,6 +636,7 @@ async function closeLegacyAllocation( ): Promise<{ txHash: string; rewardsAssigned: bigint }> { const contracts = network.contracts const transactionManager = network.transactionManager + const isHorizon = await network.isHorizon.value() // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. @@ -688,7 +689,7 @@ async function closeLegacyAllocation( } const rewardsEventLogs = transactionManager.findEvent( - 'RewardsAssigned', + isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', contracts.RewardsManager.interface, 'allocationID', allocation.id, @@ -853,6 +854,7 @@ async function reallocateLegacyAllocation( const transactionManager = network.transactionManager const address = network.specification.indexerOptions.address const currentEpoch = await contracts.EpochManager.currentEpoch() + const isHorizon = await network.isHorizon.value() // Double-check whether the allocation is still active on chain, to // avoid unnecessary transactions. @@ -1023,7 +1025,7 @@ async function reallocateLegacyAllocation( } const rewardsEventLogs = transactionManager.findEvent( - 'RewardsAssigned', + isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', contracts.RewardsManager.interface, 'allocationID', allocation.id, diff --git a/yarn.lock b/yarn.lock index eda196cec..439fb1dab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -568,10 +568,10 @@ prom-client "14.2.0" sequelize "6.33.0" -"@graphprotocol/interfaces@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@graphprotocol/interfaces/-/interfaces-0.2.4.tgz#57e4d391db2f2add181667808d25c99f196e2897" - integrity sha512-a4IiWnKHenL5pli8YXNz/l3idkdWQX1CBT2wqiesqUXt1HKGLMreWySEtrcQHOsCl0jdCMzIMdnAd7KlCZQsCQ== +"@graphprotocol/interfaces@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@graphprotocol/interfaces/-/interfaces-0.2.5.tgz#b628b198f4f2c6118d6acbf29f70c2de3ba61211" + integrity sha512-z2Worw4OzMs9aDup8MkkoNk/QmJFKhPIfQrYnbu0FKImyi72z1JVQXfaH8ypH3QO4/Lpc3PrK81cJFxqdWNExQ== "@graphprotocol/pino-sentry-simple@0.7.1": version "0.7.1" @@ -583,12 +583,12 @@ split2 "^3.1.1" through2 "^3.0.1" -"@graphprotocol/toolshed@0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.6.4.tgz#f9be510403b808864fe81a969c04020c5e92b240" - integrity sha512-uFgR6LNxp+3IM4z0+Hb/968PzCGkpECwcdhb3l1jtsMV/PMmYfnsOJqphC84DbHUBG8WNT62D2WQEY9c8ZSucQ== +"@graphprotocol/toolshed@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.6.5.tgz#42fd39d1a5b9a41002c81feaecfa574f9e2dbe46" + integrity sha512-yVyFX2rVYzgUUUcuyLCctItNXEQFeNYi739/kZupf3I/FHevaFpIvB4ZFn/Kg9SAi7556Vv3JfAPO6jkJ/xypg== dependencies: - "@graphprotocol/interfaces" "^0.2.4" + "@graphprotocol/interfaces" "^0.2.5" "@nomicfoundation/hardhat-ethers" "3.0.8" debug "^4.4.0" ethers "6.13.7" From 112e1e814d7cdde4fe677dc676593477ed300838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Wed, 18 Jun 2025 17:46:27 -0300 Subject: [PATCH 20/28] fix: wip refactor of batch execution to account for non atomic batches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../src/indexer-management/actions.ts | 4 +- .../src/indexer-management/allocations.ts | 437 ++++++++++++------ .../src/indexer-management/types.ts | 13 + 3 files changed, 308 insertions(+), 146 deletions(-) diff --git a/packages/indexer-common/src/indexer-management/actions.ts b/packages/indexer-common/src/indexer-management/actions.ts index f37a76fef..47f8c832f 100644 --- a/packages/indexer-common/src/indexer-management/actions.ts +++ b/packages/indexer-common/src/indexer-management/actions.ts @@ -334,7 +334,7 @@ export class ActionManager { }) if (pendingActions.length > 0) { logger.warn( - `${pendingActions} Actions found in PENDING state when execution began. Was there a crash?` + + `${pendingActions.length} Actions found in PENDING state when execution began. Was there a crash? ` + `These indicate that execution was interrupted while calling contracts, and will need to be cleared manually.`, ) } @@ -370,7 +370,7 @@ export class ActionManager { const allocationManager = this.allocationManagers[network.specification.networkIdentifier] - let results + let results: AllocationResult[] try { // TODO: we should lift the batch execution (graph-node, then contracts) up to here so we can // mark the actions appropriately diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index 920a75ab0..bedbf5851 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -33,8 +33,8 @@ import { uniqueAllocationID, upsertIndexingRule, horizonAllocationIdProof, - isActionFailureArray, POIData, + ExecuteTransactionResult, } from '@graphprotocol/indexer-common' import { encodeStartServiceData, @@ -79,6 +79,8 @@ export interface UnallocateTransactionParams { poi: POIData isLegacy: boolean indexer: string + actionID: number + protocolNetwork: string } export interface ReallocateTransactionParams { @@ -91,6 +93,8 @@ export interface ReallocateTransactionParams { metadata: BytesLike proof: BytesLike closingAllocationIsLegacy: boolean + actionID: number + protocolNetwork: string } // An Action with resolved Allocation and Unallocation values @@ -103,10 +107,15 @@ export interface ActionStakeUsageSummary { } export type PopulateTransactionResult = - | TransactionRequest - | TransactionRequest[] + | ActionTransactionRequest + | ActionTransactionRequest[] | ActionFailure +export type ActionTransactionRequest = TransactionRequest & { + actionID: number + protocolNetwork: string +} + export type TransactionResult = | (TransactionReceipt | 'paused' | 'unauthorized')[] | ActionFailure[] @@ -117,7 +126,7 @@ export class AllocationManager { private models: IndexerManagementModels, private graphNode: GraphNode, private network: Network, - ) {} + ) { } async executeBatch( actions: Action[], @@ -126,19 +135,14 @@ export class AllocationManager { const logger = this.logger.child({ function: 'executeBatch' }) logger.trace('Executing action batch', { actions }) const result = await this.executeTransactions(actions, onFinishedDeploying) - - if (isActionFailureArray(result)) { - logger.trace('Execute batch transaction failed', { actionBatchResult: result }) - return result as ActionFailure[] - } - return await this.confirmTransactions(result, actions) } private async executeTransactions( actions: Action[], onFinishedDeploying: (actions: Action[]) => Promise, - ): Promise { + ): Promise { + const actionResults: ExecuteTransactionResult[] = [] const logger = this.logger.child({ function: 'executeTransactions' }) logger.trace('Begin executing transactions', { actions }) if (actions.length < 1) { @@ -151,30 +155,47 @@ export class AllocationManager { await this.deployBeforeAllocating(logger, validatedActions) await onFinishedDeploying(validatedActions) - const populateTransactionsResults = await this.prepareTransactions(validatedActions) + // Populated transaction result for each action + const populatedActionTransactionsResults = await this.prepareTransactions(validatedActions) + logger.trace('populatedActionTransactionsResults', { populatedActionTransactionsResults }) - const failedTransactionPreparations = populateTransactionsResults - .filter((result) => isActionFailure(result)) - .map((result) => result as ActionFailure) + // Flat list of valid prepared transactions + const preparedTransactions: ActionTransactionRequest[] = [] - if (failedTransactionPreparations.length > 0) { - logger.trace('Failed to prepare transactions', { failedTransactionPreparations }) - return failedTransactionPreparations + for (const populatedActionTransactionResult of populatedActionTransactionsResults) { + if (isActionFailure(populatedActionTransactionResult)) { + logger.debug('Failed to prepare action', { populatedActionTransactionResult }) + actionResults.push({ + actionID: populatedActionTransactionResult.actionID, + success: false, + result: populatedActionTransactionResult, + }) + } else { + if (Array.isArray(populatedActionTransactionResult)) { + preparedTransactions.push(...populatedActionTransactionResult) + } else { + preparedTransactions.push(populatedActionTransactionResult) + } + } } logger.trace('Prepared transactions ', { - preparedTransactions: populateTransactionsResults, + preparedTransactions: preparedTransactions, }) - const callDataStakingContract = populateTransactionsResults - .flat() - .map((tx) => tx as TransactionRequest) + // We need to process both staking contract and subgraph service transactions separately + // as they cannot be multicalled + // Realistically, the only scenario where a batch would have both is shortly after the horizon upgrade + + // -- STAKING CONTRACT -- + const callDataStakingContract = preparedTransactions .filter( (tx: TransactionRequest) => tx.to === this.network.contracts.HorizonStaking.target, ) .filter((tx: TransactionRequest) => !!tx.data) .map((tx) => tx.data as string) + logger.debug('Found staking contract transactions', { count: callDataStakingContract.length, }) @@ -182,13 +203,67 @@ export class AllocationManager { callDataStakingContract, }) - const callDataSubgraphService = populateTransactionsResults - .flat() - .map((tx) => tx as TransactionRequest) + if (callDataStakingContract.length > 0) { + try { + const stakingTransactionResult = await this.network.transactionManager.executeTransaction( + async () => + this.network.contracts.HorizonStaking.multicall.estimateGas( + callDataStakingContract, + ), + async (gasLimit) => + this.network.contracts.HorizonStaking.multicall(callDataStakingContract, { + gasLimit, + }), + this.logger.child({ + actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, + function: 'staking.multicall', + }), + ) + + // Mark all actions with staking contract transactions as successful + for (const preparedTransaction of preparedTransactions) { + if (preparedTransaction.to === this.network.contracts.HorizonStaking.target) { + actionResults.push({ + actionID: preparedTransaction.actionID, + success: true, + result: stakingTransactionResult, + }) + } + } + } catch (error) { + logger.error('Failed to execute staking contract transaction', { error }) + + // Mark all actions with staking contract transactions as failed + for (const preparedTransaction of preparedTransactions) { + if (preparedTransaction.to === this.network.contracts.HorizonStaking.target) { + actionResults.push({ + actionID: preparedTransaction.actionID, + success: false, + result: { + actionID: preparedTransaction.actionID, + failureReason: `Failed to execute staking contract transaction: ${error.message}`, + protocolNetwork: preparedTransaction.protocolNetwork, + }, + }) + } + } + } + } + + // -- SUBGRAPH SERVICE -- + const callDataSubgraphService = preparedTransactions .filter( (tx: TransactionRequest) => tx.to === this.network.contracts.SubgraphService.target, ) + // Reallocate of a legacy allocation during the transition period can result in + // a staking and subgraph service transaction in the same batch. If the staking tx failed we + // should not execute the subgraph service tx. + .filter((tx: ActionTransactionRequest) => { + const actionStakingTransaction = actionResults + .find((result) => result.actionID === tx.actionID) + return actionStakingTransaction === undefined || actionStakingTransaction.success === true + }) .filter((tx: TransactionRequest) => !!tx.data) .map((tx) => tx.data as string) logger.debug('Found subgraph service transactions', { @@ -198,29 +273,9 @@ export class AllocationManager { callDataSubgraphService, }) - const transactionResults: Promise[] = - [] - if (callDataStakingContract.length > 0) { - const stakingTransaction = this.network.transactionManager.executeTransaction( - async () => - this.network.contracts.HorizonStaking.multicall.estimateGas( - callDataStakingContract, - ), - async (gasLimit) => - this.network.contracts.HorizonStaking.multicall(callDataStakingContract, { - gasLimit, - }), - this.logger.child({ - actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, - function: 'staking.multicall', - }), - ) - transactionResults.push(stakingTransaction) - } - if (callDataSubgraphService.length > 0) { - const subgraphServiceTransaction = - this.network.transactionManager.executeTransaction( + try { + const subgraphServiceTransactionResult = await this.network.transactionManager.executeTransaction( async () => this.network.contracts.SubgraphService.multicall.estimateGas( callDataSubgraphService, @@ -234,42 +289,95 @@ export class AllocationManager { function: 'subgraphService.multicall', }), ) - transactionResults.push(subgraphServiceTransaction) + + // Mark all actions with subgraph service transactions as successful + for (const preparedTransaction of preparedTransactions) { + if (preparedTransaction.to === this.network.contracts.SubgraphService.target) { + actionResults.push({ + actionID: preparedTransaction.actionID, + success: true, + result: subgraphServiceTransactionResult, + }) + } + } + } catch (error) { + logger.error('Failed to execute subgraph service transaction', { error }) + + // Mark all actions with subgraph service transactions as failed + for (const preparedTransaction of preparedTransactions) { + if (preparedTransaction.to === this.network.contracts.SubgraphService.target) { + actionResults.push({ + actionID: preparedTransaction.actionID, + success: false, + result: { + actionID: preparedTransaction.actionID, + failureReason: `Failed to execute subgraph service transaction: ${error.message}`, + protocolNetwork: preparedTransaction.protocolNetwork, + }, + }) + } + } + } } - return await Promise.all(transactionResults) + // sanity check that all actions have a result + if (actionResults.length !== actions.length) { + logger.error('Inconsistent number of action results', { + actionResults: actionResults.length, + actions: actions.length, + }) + } + + return actionResults } async confirmTransactions( - receipts: (TransactionReceipt | 'paused' | 'unauthorized')[], + transactionResults: ExecuteTransactionResult[], actions: Action[], ): Promise { const logger = this.logger.child({ function: 'confirmTransactions', - receipts, - actions, + transactionResults, }) - logger.trace('Confirming transaction') + logger.trace('Confirming transactions') return pMap( - actions, - async (action: Action) => { - const receipt = receipts.find( - (receipt) => - (receipt as TransactionReceipt).to === - (action.isLegacy - ? this.network.contracts.HorizonStaking.target - : this.network.contracts.SubgraphService.target), - ) + transactionResults, + async (transactionResult: ExecuteTransactionResult) => { + + const action = actions.find((action) => action.id === transactionResult.actionID) + if (action === undefined) { + this.logger.error('No action found for transaction result', { + transactionResult, + }) + throw new Error('No action found for transaction result') + } + + if (isActionFailure(transactionResult.result)) { + logger.debug('Execute batch transaction failed', { actionBatchResult: transactionResult, reason: transactionResult.result.failureReason }) + return transactionResult.result + } + + if (transactionResult.result === "paused" || transactionResult.result === "unauthorized") { + logger.debug('Execute batch transaction failed', { actionBatchResult: transactionResult, reason: transactionResult.result }) + return { + actionID: transactionResult.actionID, + transactionID: undefined, + failureReason: transactionResult.result, + protocolNetwork: action.protocolNetwork, + } + } + + const receipt = transactionResult.result try { if (receipt === undefined) { this.logger.error('No receipt found for action', { - action, - receipts, + action: transactionResult.actionID, }) throw new Error('No receipt found for action') } + return await this.confirmActionExecution(receipt, action) } catch (error) { let transaction: string | undefined = undefined @@ -377,6 +485,8 @@ export class AllocationManager { new SubgraphDeploymentID(action.deploymentID!), // eslint-disable-next-line @typescript-eslint/no-non-null-assertion parseGRT(action.amount!), + action.id, + action.protocolNetwork, ) case ActionType.UNALLOCATE: return await this.prepareUnallocate( @@ -388,6 +498,8 @@ export class AllocationManager { action.force === null ? false : action.force, action.poiBlockNumber === null ? undefined : action.poiBlockNumber, action.publicPOI === null ? undefined : action.publicPOI, + action.id, + action.protocolNetwork, ) case ActionType.REALLOCATE: return await this.prepareReallocate( @@ -401,6 +513,8 @@ export class AllocationManager { action.force === null ? false : action.force, action.poiBlockNumber === null ? undefined : action.poiBlockNumber, action.publicPOI === null ? undefined : action.publicPOI, + action.id, + action.protocolNetwork, ) } } catch (error) { @@ -548,17 +662,17 @@ export class AllocationManager { const proof = isHorizon ? await horizonAllocationIdProof( - allocationSigner, - Number(this.network.specification.networkIdentifier.split(':')[1]), - this.network.specification.indexerOptions.address, - allocationId, - this.network.contracts.SubgraphService.target.toString(), - ) + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + allocationId, + this.network.contracts.SubgraphService.target.toString(), + ) : await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - allocationId, - ) + allocationSigner, + this.network.specification.indexerOptions.address, + allocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, @@ -592,29 +706,28 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE062, - `Allocation not created. ${ - receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + `Allocation not created. ${receipt === 'paused' ? 'Network paused' : 'Operator not authorized' }`, ) } const createAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - subgraphDeployment.bytes32, - receipt, - this.logger, - ) + 'AllocationCreated', + this.network.contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + subgraphDeployment.bytes32, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.SubgraphService.interface, - 'indexer', - this.network.specification.indexerOptions.address, - receipt, - logger, - ) + 'AllocationCreated', + this.network.contracts.SubgraphService.interface, + 'indexer', + this.network.specification.indexerOptions.address, + receipt, + logger, + ) if (!createAllocationEventLogs) { throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) @@ -667,7 +780,9 @@ export class AllocationManager { context: TransactionPreparationContext, deployment: SubgraphDeploymentID, amount: bigint, - ): Promise { + actionID: number, + protocolNetwork: string, + ): Promise { const isHorizon = await this.network.isHorizon.value() const params = await this.prepareAllocateParams(logger, context, deployment, amount) logger.debug(`Populating allocation creation transaction`, { @@ -703,7 +818,11 @@ export class AllocationManager { params.proof, ) } - return populatedTransaction + return { + protocolNetwork, + actionID, + ...populatedTransaction, + } } async prepareUnallocateParams( @@ -714,6 +833,8 @@ export class AllocationManager { force: boolean, poiBlockNumber: number | undefined, publicPOI: string | undefined, + actionID: number, + protocolNetwork: string, ): Promise { logger.info('Preparing to unallocate', { allocationID: allocationID, @@ -749,6 +870,8 @@ export class AllocationManager { } return { + protocolNetwork, + actionID, allocationID: allocation.id, poi: poiData, isLegacy: allocation.isLegacy, @@ -779,21 +902,21 @@ export class AllocationManager { const closeAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'AllocationClosed', - this.network.contracts.LegacyStaking.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) + 'AllocationClosed', + this.network.contracts.LegacyStaking.interface, + 'allocationID', + allocationID, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'AllocationClosed', - this.network.contracts.SubgraphService.interface, - 'allocationId', - allocationID, - receipt, - this.logger, - ) + 'AllocationClosed', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) if (!closeAllocationEventLogs) { throw indexerError( @@ -804,21 +927,21 @@ export class AllocationManager { const rewardsEventLogs = isLegacy ? this.network.transactionManager.findEvent( - isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', - this.network.contracts.RewardsManager.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) + isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', + this.network.contracts.RewardsManager.interface, + 'allocationID', + allocationID, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'IndexingRewardsCollected', - this.network.contracts.SubgraphService.interface, - 'allocationId', - allocationID, - receipt, - this.logger, - ) + 'IndexingRewardsCollected', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) const rewardsAssigned = rewardsEventLogs ? isLegacy @@ -877,17 +1000,22 @@ export class AllocationManager { async populateUnallocateTransaction( logger: Logger, params: UnallocateTransactionParams, - ): Promise { + ): Promise { logger.debug(`Populating unallocate transaction`, { allocationID: params.allocationID, poiData: params.poi, }) if (params.isLegacy) { - return await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( + const tx = await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( params.allocationID, params.poi.poi, ) + return { + protocolNetwork: params.protocolNetwork, + actionID: params.actionID, + ...tx, + } } else { // Horizon: Need to multicall collect and stopService @@ -917,10 +1045,15 @@ export class AllocationManager { [params.indexer, encodeStopServiceData(params.allocationID)], ) - return await this.network.contracts.SubgraphService.multicall.populateTransaction([ + const tx = await this.network.contracts.SubgraphService.multicall.populateTransaction([ collectCallData, stopServiceCallData, ]) + return { + protocolNetwork: params.protocolNetwork, + actionID: params.actionID, + ...tx, + } } } @@ -932,7 +1065,9 @@ export class AllocationManager { force: boolean, poiBlockNumber: number | undefined, publicPOI: string | undefined, - ): Promise { + actionID: number, + protocolNetwork: string, + ): Promise { const params = await this.prepareUnallocateParams( logger, context, @@ -941,6 +1076,8 @@ export class AllocationManager { force, poiBlockNumber, publicPOI, + actionID, + protocolNetwork, ) return await this.populateUnallocateTransaction(logger, params) } @@ -954,6 +1091,8 @@ export class AllocationManager { force: boolean, poiBlockNumber: number | undefined, publicPOI: string | undefined, + actionID: number, + protocolNetwork: string, ): Promise { logger.info('Preparing to reallocate', { allocation: allocationID, @@ -1085,17 +1224,17 @@ export class AllocationManager { }) const proof = isHorizon ? await horizonAllocationIdProof( - allocationSigner, - Number(this.network.specification.networkIdentifier.split(':')[1]), - this.network.specification.indexerOptions.address, - newAllocationId, - this.network.contracts.SubgraphService.target.toString(), - ) + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + newAllocationId, + this.network.contracts.SubgraphService.target.toString(), + ) : await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - newAllocationId, - ) + allocationSigner, + this.network.specification.indexerOptions.address, + newAllocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, @@ -1124,6 +1263,8 @@ export class AllocationManager { newAllocationID: newAllocationId, metadata: hexlify(new Uint8Array(32).fill(0)), proof, + actionID, + protocolNetwork, } } @@ -1321,7 +1462,9 @@ export class AllocationManager { force: boolean, poiBlockNumber: number | undefined, publicPOI: string | undefined, - ): Promise { + actionID: number, + protocolNetwork: string, + ): Promise { const params = await this.prepareReallocateParams( logger, context, @@ -1331,6 +1474,8 @@ export class AllocationManager { force, poiBlockNumber, publicPOI, + actionID, + protocolNetwork, ) return this.populateReallocateTransaction(logger, params) @@ -1339,7 +1484,7 @@ export class AllocationManager { async populateReallocateTransaction( logger: Logger, params: ReallocateTransactionParams, - ): Promise { + ): Promise { logger.debug('Populating reallocate transaction', { closingAllocationID: params.closingAllocationID, poi: params.poi, @@ -1426,7 +1571,11 @@ export class AllocationManager { ) } - return txs + return txs.map((tx) => ({ + actionID: params.actionID, + protocolNetwork: params.protocolNetwork, + ...tx, + })) } async matchingRuleExists( @@ -1484,9 +1633,9 @@ export class AllocationManager { action.poi === zeroHexString ? 0n : await this.network.contracts.RewardsManager.getRewards( - this.network.contracts.HorizonStaking.target, - action.allocationID, - ) + this.network.contracts.HorizonStaking.target, + action.allocationID, + ) unallocates = unallocates + allocation.allocatedTokens } @@ -1546,10 +1695,10 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE013, `Unfeasible action batch: Approved action batch GRT balance is ` + - `${formatGRT(batchDelta)} for horizon actions and ` + - `${formatGRT(batchDeltaLegacy)} for legacy actions ` + - `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + - `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, + `${formatGRT(batchDelta)} for horizon actions and ` + + `${formatGRT(batchDeltaLegacy)} for legacy actions ` + + `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + + `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, ) } } diff --git a/packages/indexer-common/src/indexer-management/types.ts b/packages/indexer-common/src/indexer-management/types.ts index b76b19899..677c7ec81 100644 --- a/packages/indexer-common/src/indexer-management/types.ts +++ b/packages/indexer-common/src/indexer-management/types.ts @@ -7,6 +7,7 @@ import { import { Allocation, Provision } from '../allocations' import { GraphNode } from '../graph-node' import { SubgraphDeployment } from '../types' +import { TransactionReceipt } from 'ethers' /* eslint-disable @typescript-eslint/no-explicit-any */ let registry: any @@ -47,6 +48,18 @@ export interface ReallocateAllocationResult { protocolNetwork: string } +export interface ActionExecutionResult { + actionID: number + success: boolean + result: AllocationResult +} + +export interface ExecuteTransactionResult { + actionID: number + success: boolean + result: ActionFailure | TransactionReceipt | "paused" | "unauthorized" +} + export interface ActionFailure { actionID: number transactionID?: string From 3579e8e7526b1d6937e72a92bfa9725d84987619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 19 Jun 2025 11:12:03 -0300 Subject: [PATCH 21/28] chore: better tx filtering on executeTransaction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../src/indexer-management/allocations.ts | 92 +++++++++---------- 1 file changed, 42 insertions(+), 50 deletions(-) diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index bedbf5851..e85c04bfd 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -186,13 +186,17 @@ export class AllocationManager { // We need to process both staking contract and subgraph service transactions separately // as they cannot be multicalled // Realistically, the only scenario where a batch would have both is shortly after the horizon upgrade + const stakingTransactions = preparedTransactions.filter( + (tx: TransactionRequest) => + tx.to === this.network.contracts.HorizonStaking.target, + ) + const subgraphServiceTransactions = preparedTransactions.filter( + (tx: TransactionRequest) => + tx.to === this.network.contracts.SubgraphService.target, + ) // -- STAKING CONTRACT -- - const callDataStakingContract = preparedTransactions - .filter( - (tx: TransactionRequest) => - tx.to === this.network.contracts.HorizonStaking.target, - ) + const callDataStakingContract = stakingTransactions .filter((tx: TransactionRequest) => !!tx.data) .map((tx) => tx.data as string) @@ -221,41 +225,33 @@ export class AllocationManager { ) // Mark all actions with staking contract transactions as successful - for (const preparedTransaction of preparedTransactions) { - if (preparedTransaction.to === this.network.contracts.HorizonStaking.target) { - actionResults.push({ - actionID: preparedTransaction.actionID, - success: true, - result: stakingTransactionResult, - }) - } + for (const transaction of stakingTransactions) { + actionResults.push({ + actionID: transaction.actionID, + success: true, + result: stakingTransactionResult, + }) } } catch (error) { logger.error('Failed to execute staking contract transaction', { error }) // Mark all actions with staking contract transactions as failed - for (const preparedTransaction of preparedTransactions) { - if (preparedTransaction.to === this.network.contracts.HorizonStaking.target) { - actionResults.push({ - actionID: preparedTransaction.actionID, - success: false, - result: { - actionID: preparedTransaction.actionID, - failureReason: `Failed to execute staking contract transaction: ${error.message}`, - protocolNetwork: preparedTransaction.protocolNetwork, - }, - }) - } + for (const transaction of stakingTransactions) { + actionResults.push({ + actionID: transaction.actionID, + success: false, + result: { + actionID: transaction.actionID, + failureReason: `Failed to execute staking contract transaction: ${error.message}`, + protocolNetwork: transaction.protocolNetwork, + }, + }) } } } // -- SUBGRAPH SERVICE -- - const callDataSubgraphService = preparedTransactions - .filter( - (tx: TransactionRequest) => - tx.to === this.network.contracts.SubgraphService.target, - ) + const callDataSubgraphService = subgraphServiceTransactions // Reallocate of a legacy allocation during the transition period can result in // a staking and subgraph service transaction in the same batch. If the staking tx failed we // should not execute the subgraph service tx. @@ -291,31 +287,27 @@ export class AllocationManager { ) // Mark all actions with subgraph service transactions as successful - for (const preparedTransaction of preparedTransactions) { - if (preparedTransaction.to === this.network.contracts.SubgraphService.target) { - actionResults.push({ - actionID: preparedTransaction.actionID, - success: true, - result: subgraphServiceTransactionResult, - }) - } + for (const transaction of subgraphServiceTransactions) { + actionResults.push({ + actionID: transaction.actionID, + success: true, + result: subgraphServiceTransactionResult, + }) } } catch (error) { logger.error('Failed to execute subgraph service transaction', { error }) // Mark all actions with subgraph service transactions as failed - for (const preparedTransaction of preparedTransactions) { - if (preparedTransaction.to === this.network.contracts.SubgraphService.target) { - actionResults.push({ - actionID: preparedTransaction.actionID, - success: false, - result: { - actionID: preparedTransaction.actionID, - failureReason: `Failed to execute subgraph service transaction: ${error.message}`, - protocolNetwork: preparedTransaction.protocolNetwork, - }, - }) - } + for (const transaction of subgraphServiceTransactions) { + actionResults.push({ + actionID: transaction.actionID, + success: false, + result: { + actionID: transaction.actionID, + failureReason: `Failed to execute subgraph service transaction: ${error.message}`, + protocolNetwork: transaction.protocolNetwork, + }, + }) } } } From 660ce64b5ab61084f16f63ff84254451caa49b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 19 Jun 2025 17:50:16 -0300 Subject: [PATCH 22/28] feat: fix graphtally database model and add migrations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../db/migrations/21-add-tap-horizon-table.ts | 249 +++++++++++++++ .../22-add-tap-horizon-deny-list.ts | 77 +++++ .../indexer-common/src/query-fees/models.ts | 302 +++++++++++++++--- 3 files changed, 590 insertions(+), 38 deletions(-) create mode 100644 packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts create mode 100644 packages/indexer-agent/src/db/migrations/22-add-tap-horizon-deny-list.ts diff --git a/packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts b/packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts new file mode 100644 index 000000000..c3a0dc015 --- /dev/null +++ b/packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts @@ -0,0 +1,249 @@ +import { Logger } from '@graphprotocol/common-ts' +import { QueryInterface, DataTypes } from 'sequelize' + +interface MigrationContext { + queryInterface: QueryInterface + logger: Logger +} + +interface Context { + context: MigrationContext +} + +export async function up({ context }: Context): Promise { + const { queryInterface, logger } = context + + const tables = await queryInterface.showAllTables() + logger.debug(`Checking if tap_horizon_receipts table exists`, { tables }) + + if (tables.includes('tap_horizon_receipts')) { + logger.debug(`tap_horizon_receipts already exist, migration not necessary`) + } else { + logger.info(`Create tap_horizon_receipts`) + await queryInterface.createTable('tap_horizon_receipts', { + id: { + type: DataTypes.BIGINT, + primaryKey: true, + autoIncrement: true, + }, + allocation_id: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signer_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signature: { + type: DataTypes.BLOB, + allowNull: false, + }, + timestamp_ns: { + type: DataTypes.DECIMAL(20), + allowNull: false, + }, + nonce: { + type: DataTypes.DECIMAL, + allowNull: false, + }, + value: { + type: DataTypes.DECIMAL(39), + allowNull: false, + }, + }) + } + + logger.debug('Create function and trigger using raw SQL') + const functionSQL = ` + CREATE FUNCTION tap_horizon_receipt_notify() + RETURNS trigger AS + $$ + BEGIN + PERFORM pg_notify('tap_horizon_receipt_notification', format('{"id": %s, "allocation_id": "%s", "signer_address": "%s", "timestamp_ns": %s, "value": %s}', NEW.id, NEW.allocation_id, NEW.signer_address, NEW.timestamp_ns, NEW.value)); + RETURN NEW; + END; + $$ LANGUAGE 'plpgsql'; + ` + const triggerSQL = ` + CREATE TRIGGER receipt_update AFTER INSERT OR UPDATE + ON tap_horizon_receipts + FOR EACH ROW EXECUTE PROCEDURE tap_horizon_receipt_notify(); + ` + await queryInterface.sequelize.query(functionSQL) + await queryInterface.sequelize.query(triggerSQL) + + queryInterface.addIndex('tap_horizon_receipts', ['allocation_id'], { + name: 'tap_horizon_receipts_allocation_id_idx', + }) + queryInterface.addIndex('tap_horizon_receipts', ['timestamp_ns'], { + name: 'tap_horizon_receipts_timestamp_ns_idx', + }) + + if (tables.includes('tap_horizon_receipts_invalid')) { + logger.info( + `tap_horizon_receipts_invalid already exist, migration not necessary`, + ) + } else { + // Create the tap_horizon_ravs table if it doesn't exist + await queryInterface.createTable('tap_horizon_receipts_invalid', { + id: { + type: DataTypes.BIGINT, + primaryKey: true, + autoIncrement: true, + }, + allocation_id: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signer_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signature: { + type: DataTypes.BLOB, + allowNull: false, + }, + timestamp_ns: { + type: DataTypes.DECIMAL(20), + allowNull: false, + }, + nonce: { + type: DataTypes.DECIMAL, + allowNull: false, + }, + value: { + type: DataTypes.DECIMAL(20), + allowNull: false, + }, + }) + } + + if (tables.includes('tap_horizon_ravs')) { + logger.info(`tap_horizon_ravs already exist, migration not necessary`) + } else { + // Create the tap_horizon_ravs table if it doesn't exist + await queryInterface.createTable('tap_horizon_ravs', { + collection_id: { + type: DataTypes.CHAR(64), + allowNull: false, + }, + sender_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + service_provider_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + data_service_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signature: { + type: DataTypes.BLOB, + allowNull: false, + }, + timestamp_ns: { + type: DataTypes.DECIMAL, + allowNull: false, + }, + value_aggregate: { + type: DataTypes.DECIMAL(39), + allowNull: false, + }, + metadata: { + type: DataTypes.BLOB, + allowNull: false, + }, + final: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + last: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + }, + redeemed_at: { + type: DataTypes.DATE, + allowNull: true, + }, + created_at: { + type: DataTypes.DATE, + allowNull: false, + }, + updated_at: { + type: DataTypes.DATE, + allowNull: false, + }, + }) + } + + logger.info(`Add primary key`) + await queryInterface.addConstraint('tap_horizon_ravs', { + fields: ['collection_id', 'sender_address', 'service_provider_address', 'data_service_address'], + type: 'primary key', + name: 'pk_tap_horizon_ravs', + }) + + await queryInterface.createTable('tap_horizon_rav_requests_failed', { + id: { + type: DataTypes.BIGINT, + primaryKey: true, + autoIncrement: true, + }, + collection_id: { + type: DataTypes.CHAR(64), + allowNull: false, + }, + sender_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + service_provider_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + data_service_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + expected_rav: { + type: DataTypes.JSON, + allowNull: false, + }, + rav_response: { + type: DataTypes.JSON, + allowNull: false, + }, + reason: { + allowNull: false, + type: DataTypes.TEXT, + }, + }) +} + +export async function down({ context }: Context): Promise { + const { queryInterface, logger } = context + // Drop the tap_horizon_ravs table + logger.info(`Drop table`) + await queryInterface.dropTable('tap_horizon_ravs') + + logger.info(`Drop function, trigger, indices, and table`) + await queryInterface.sequelize.query( + 'DROP TRIGGER IF EXISTS receipt_update ON tap_horizon_receipts', + ) + await queryInterface.sequelize.query( + 'DROP FUNCTION IF EXISTS tap_horizon_receipt_notify', + ) + await queryInterface.removeIndex( + 'tap_horizon_receipts', + 'tap_horizon_receipts_allocation_id_idx', + ) + await queryInterface.removeIndex( + 'tap_horizon_receipts', + 'tap_horizon_receipts_timestamp_ns_idx', + ) + await queryInterface.dropTable('tap_horizon_receipts') +} diff --git a/packages/indexer-agent/src/db/migrations/22-add-tap-horizon-deny-list.ts b/packages/indexer-agent/src/db/migrations/22-add-tap-horizon-deny-list.ts new file mode 100644 index 000000000..413e3b457 --- /dev/null +++ b/packages/indexer-agent/src/db/migrations/22-add-tap-horizon-deny-list.ts @@ -0,0 +1,77 @@ +import { Logger } from '@graphprotocol/common-ts' + +import { QueryInterface, DataTypes } from 'sequelize' + +interface MigrationContext { + queryInterface: QueryInterface + logger: Logger +} + +interface Context { + context: MigrationContext +} + +export async function up({ context }: Context): Promise { + const { queryInterface, logger } = context + + const tables = await queryInterface.showAllTables() + logger.debug(`Checking if tap_horizon_denylist table exists`, { tables }) + + if (tables.includes('tap_horizon_denylist')) { + logger.debug(`tap_horizon_denylist already exist, migration not necessary`) + } else { + logger.info(`Create tap_horizon_denylist`) + await queryInterface.createTable('tap_horizon_denylist', { + id: { + type: DataTypes.BIGINT, + primaryKey: true, + autoIncrement: true, + }, + sender_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + }) + } + const functionSQL = ` + CREATE FUNCTION tap_horizon_deny_notify() + RETURNS trigger AS + $$ + BEGIN + IF TG_OP = 'DELETE' THEN + PERFORM pg_notify('tap_horizon_deny_notification', format('{"tg_op": "DELETE", "sender_address": "%s"}', OLD.sender_address)); + RETURN OLD; + ELSIF TG_OP = 'INSERT' THEN + PERFORM pg_notify('tap_horizon_deny_notification', format('{"tg_op": "INSERT", "sender_address": "%s"}', NEW.sender_address)); + RETURN NEW; + ELSE -- UPDATE OR TRUNCATE, should never happen + PERFORM pg_notify('tap_horizon_deny_notification', format('{"tg_op": "%s", "sender_address": null}', TG_OP, NEW.sender_address)); + RETURN NEW; + END IF; + END; + $$ LANGUAGE 'plpgsql'; + ` + const triggerSQL = ` + CREATE TRIGGER deny_update AFTER INSERT OR UPDATE OR DELETE + ON tap_horizon_denylist + FOR EACH ROW EXECUTE PROCEDURE tap_horizon_deny_notify(); + ` + + await queryInterface.sequelize.query(functionSQL) + await queryInterface.sequelize.query(triggerSQL) +} + +export async function down({ context }: Context): Promise { + const { queryInterface, logger } = context + + logger.info(`Drop tap_horizon_denylist`) + await queryInterface.sequelize.query( + 'DROP TRIGGER IF EXISTS deny_update ON tap_horizon_denylist', + ) + logger.info(`Drop function tap_horizon_deny_notify`) + await queryInterface.sequelize.query( + 'DROP FUNCTION IF EXISTS tap_horizon_deny_notify', + ) + logger.info(`Drop table tap_horizon_denylist`) + await queryInterface.dropTable('tap_horizon_denylist') +} diff --git a/packages/indexer-common/src/query-fees/models.ts b/packages/indexer-common/src/query-fees/models.ts index 0193f3a2c..7ed997e2d 100644 --- a/packages/indexer-common/src/query-fees/models.ts +++ b/packages/indexer-common/src/query-fees/models.ts @@ -17,8 +17,32 @@ export interface ScalarTapReceiptsAttributes { } export class ScalarTapReceipts extends Model - implements ScalarTapReceiptsAttributes -{ + implements ScalarTapReceiptsAttributes { + public id!: number + public allocation_id!: Address + public signer_address!: Address + public signature!: Uint8Array + public timestamp_ns!: bigint + public nonce!: bigint + public value!: bigint + + declare createdAt: CreationOptional + declare updatedAt: CreationOptional +} + +export interface TapHorizonReceiptsAttributes { + id: number + allocation_id: Address + signer_address: Address + signature: Uint8Array + timestamp_ns: bigint + nonce: bigint + value: bigint + error_log?: string +} +export class TapHorizonReceipts + extends Model + implements TapHorizonReceiptsAttributes { public id!: number public allocation_id!: Address public signer_address!: Address @@ -33,8 +57,23 @@ export class ScalarTapReceipts export class ScalarTapReceiptsInvalid extends Model - implements ScalarTapReceiptsAttributes -{ + implements ScalarTapReceiptsAttributes { + public id!: number + public allocation_id!: Address + public signer_address!: Address + public timestamp_ns!: bigint + public nonce!: bigint + public value!: bigint + public signature!: Uint8Array + public error_log!: string + + declare createdAt: CreationOptional + declare updatedAt: CreationOptional +} + +export class TapHorizonReceiptsInvalid + extends Model + implements TapHorizonReceiptsAttributes { public id!: number public allocation_id!: Address public signer_address!: Address @@ -47,6 +86,7 @@ export class ScalarTapReceiptsInvalid declare createdAt: CreationOptional declare updatedAt: CreationOptional } + export interface AllocationReceiptAttributes { id: string allocation: Address @@ -57,8 +97,7 @@ export interface AllocationReceiptAttributes { export class AllocationReceipt extends Model - implements AllocationReceiptAttributes -{ + implements AllocationReceiptAttributes { public id!: string public allocation!: Address public fees!: string @@ -105,9 +144,9 @@ export interface ReceiptAggregateVoucherAttributes { export interface ReceiptAggregateVoucherV2Attributes { collectionId: string - payer: string - serviceProvider: string - dataService: string + senderAddress: string + serviceProviderAddress: string + dataServiceAddress: string metadata: string signature: Uint8Array timestampNs: bigint @@ -125,10 +164,20 @@ export interface FailedReceiptAggregateVoucherAttributes { reason: string } + +export interface FailedReceiptAggregateVoucherV2Attributes { + collectionId: string + senderAddress: string + serviceProviderAddress: string + dataServiceAddress: string + expectedRav: JSON + rav_response: JSON + reason: string +} + export class ReceiptAggregateVoucher extends Model - implements ReceiptAggregateVoucherAttributes -{ + implements ReceiptAggregateVoucherAttributes { public allocationId!: Address public senderAddress!: Address public signature!: Uint8Array @@ -161,18 +210,21 @@ export class ReceiptAggregateVoucher // TODO HORIZON: move this to the toolshed package export type SignedRAVv2 = { - rav: RAVv2 + rav: Omit & { + senderAddress: string + serviceProviderAddress: string + dataServiceAddress: string + } signature: BytesLike } export class ReceiptAggregateVoucherV2 extends Model - implements ReceiptAggregateVoucherV2Attributes -{ + implements ReceiptAggregateVoucherV2Attributes { public collectionId!: Address - public payer!: Address - public serviceProvider!: Address - public dataService!: Address + public senderAddress!: Address + public serviceProviderAddress!: Address + public dataServiceAddress!: Address public metadata!: string public signature!: Uint8Array public timestampNs!: bigint @@ -194,9 +246,9 @@ export class ReceiptAggregateVoucherV2 return { rav: { collectionId: this.collectionId, - payer: this.payer, - serviceProvider: this.serviceProvider, - dataService: this.dataService, + senderAddress: this.senderAddress, + serviceProviderAddress: this.serviceProviderAddress, + dataServiceAddress: this.dataServiceAddress, timestampNs: Number(this.timestampNs), valueAggregate: this.valueAggregate, metadata: this.metadata, @@ -210,8 +262,7 @@ export type SignedRAV = TAPVerifier.SignedRAVStruct export class FailedReceiptAggregateVoucher extends Model - implements FailedReceiptAggregateVoucherAttributes -{ + implements FailedReceiptAggregateVoucherAttributes { public allocationId!: Address public senderAddress!: Address public expectedRav!: JSON @@ -219,6 +270,19 @@ export class FailedReceiptAggregateVoucher public reason!: string } + +export class FailedReceiptAggregateVoucherV2 + extends Model + implements FailedReceiptAggregateVoucherV2Attributes { + public collectionId!: Address + public senderAddress!: Address + public serviceProviderAddress!: Address + public dataServiceAddress!: Address + public expectedRav!: JSON + public rav_response!: JSON + public reason!: string +} + export interface TransferReceiptAttributes { id: number signer: Address @@ -229,8 +293,7 @@ export interface TransferReceiptAttributes { export class TransferReceipt extends Model - implements TransferReceiptAttributes -{ + implements TransferReceiptAttributes { public id!: number public signer!: Address public fees!: string @@ -295,8 +358,7 @@ export interface AllocationSummaryAttributes { export class AllocationSummary extends Model - implements AllocationSummaryAttributes -{ + implements AllocationSummaryAttributes { public allocation!: Address public closedAt!: Date public createdTransfers!: number @@ -314,8 +376,9 @@ export class AllocationSummary public readonly allocationReceipts?: AllocationReceipt[] public readonly voucher?: Voucher public readonly receiptAggregateVoucher?: ReceiptAggregateVoucher + public readonly receiptAggregateVoucherV2?: ReceiptAggregateVoucherV2 - public voucherType?: 'Voucher' | 'ReceiptAggregateVoucher' + public voucherType?: 'Voucher' | 'ReceiptAggregateVoucher' | 'ReceiptAggregateVoucherV2' public static associations: { transfers: Association @@ -336,6 +399,7 @@ export interface QueryFeeModels { scalarTapReceipts: typeof ScalarTapReceipts scalarTapReceiptsInvalid: typeof ScalarTapReceiptsInvalid failedReceiptAggregateVouchers: typeof FailedReceiptAggregateVoucher + failedReceiptAggregateVouchersV2: typeof FailedReceiptAggregateVoucherV2 } export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { @@ -496,47 +560,47 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { this.setDataValue('collectionId', addressWithoutPrefix) }, }, - payer: { + senderAddress: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('payer') + const rawValue = this.getDataValue('senderAddress') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('payer', addressWithoutPrefix) + this.setDataValue('senderAddress', addressWithoutPrefix) }, }, - serviceProvider: { + serviceProviderAddress: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('serviceProvider') + const rawValue = this.getDataValue('serviceProviderAddress') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('serviceProvider', addressWithoutPrefix) + this.setDataValue('serviceProviderAddress', addressWithoutPrefix) }, }, - dataService: { + dataServiceAddress: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('dataService') + const rawValue = this.getDataValue('dataServiceAddress') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('dataService', addressWithoutPrefix) + this.setDataValue('dataServiceAddress', addressWithoutPrefix) }, }, metadata: { - type: DataTypes.STRING, + type: DataTypes.BLOB, allowNull: false, }, signature: { @@ -580,7 +644,7 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { { underscored: true, sequelize, - tableName: 'scalar_tap_ravs', + tableName: 'tap_horizon_ravs', }, ) @@ -755,6 +819,81 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { }, ) + + FailedReceiptAggregateVoucherV2.init( + { + collectionId: { + type: DataTypes.CHAR(64), + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('collectionId') + return toAddress(rawValue) + }, + set(value: Address) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('collectionId', addressWithoutPrefix) + }, + }, + senderAddress: { + type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('senderAddress') + return toAddress(rawValue) + }, + set(value: string) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('senderAddress', addressWithoutPrefix) + }, + }, + serviceProviderAddress: { + type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('serviceProviderAddress') + return toAddress(rawValue) + }, + set(value: string) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('serviceProviderAddress', addressWithoutPrefix) + }, + }, + dataServiceAddress: { + type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent + allowNull: false, + primaryKey: true, + get() { + const rawValue = this.getDataValue('dataServiceAddress') + return toAddress(rawValue) + }, + set(value: string) { + const addressWithoutPrefix = value.toLowerCase().replace('0x', '') + this.setDataValue('dataServiceAddress', addressWithoutPrefix) + }, + }, + expectedRav: { + type: DataTypes.JSON, + allowNull: false, + }, + rav_response: { + type: DataTypes.JSON, + allowNull: false, + }, + reason: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + underscored: true, + sequelize, + tableName: 'failed_receipt_aggregate_vouchers_v2', + }, + ) + ScalarTapReceipts.init( { id: { @@ -795,6 +934,46 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { }, ) + TapHorizonReceipts.init( + { + id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true, + }, + allocation_id: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signer_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signature: { + type: DataTypes.BLOB, + allowNull: false, + }, + timestamp_ns: { + type: DataTypes.BIGINT, + allowNull: false, + }, + nonce: { + type: DataTypes.BIGINT, + allowNull: false, + }, + value: { + type: DataTypes.BIGINT, + allowNull: false, + }, + }, + { + underscored: true, + sequelize, + tableName: 'tap_horizon_receipts', + }, + ) + ScalarTapReceiptsInvalid.init( { id: { @@ -840,6 +1019,52 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { }, ) + + TapHorizonReceiptsInvalid.init( + { + id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true, + }, + allocation_id: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + signer_address: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + timestamp_ns: { + type: DataTypes.BIGINT, + allowNull: false, + }, + nonce: { + type: DataTypes.BIGINT, + allowNull: false, + }, + value: { + type: DataTypes.BIGINT, + allowNull: false, + }, + signature: { + type: DataTypes.BLOB, + allowNull: false, + }, + error_log: { + type: DataTypes.TEXT, + allowNull: false, + defaultValue: '', + }, + }, + { + underscored: true, + sequelize, + tableName: 'tap_horizon_receipts_invalid', + }, + ) + Transfer.hasMany(TransferReceipt, { sourceKey: 'signer', foreignKey: 'signer', @@ -893,5 +1118,6 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { scalarTapReceipts: ScalarTapReceipts, scalarTapReceiptsInvalid: ScalarTapReceiptsInvalid, failedReceiptAggregateVouchers: FailedReceiptAggregateVoucher, + failedReceiptAggregateVouchersV2: FailedReceiptAggregateVoucherV2, } } From 55d2284544990eaef05df88ec9d1c2173808665b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 20 Jun 2025 12:13:15 -0300 Subject: [PATCH 23/28] fix: database migrations for horizon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../db/migrations/21-add-tap-horizon-table.ts | 87 +++++++---- .../indexer-common/src/query-fees/models.ts | 143 +++++++++++------- 2 files changed, 151 insertions(+), 79 deletions(-) diff --git a/packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts b/packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts index c3a0dc015..85ca3e1da 100644 --- a/packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts +++ b/packages/indexer-agent/src/db/migrations/21-add-tap-horizon-table.ts @@ -26,18 +26,32 @@ export async function up({ context }: Context): Promise { primaryKey: true, autoIncrement: true, }, - allocation_id: { - type: DataTypes.CHAR(40), - allowNull: false, - }, signer_address: { type: DataTypes.CHAR(40), allowNull: false, }, + + // Values below are the individual fields of the EIP-712 receipt signature: { type: DataTypes.BLOB, allowNull: false, }, + collection_id: { + type: DataTypes.CHAR(64), + allowNull: false, + }, + payer: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + data_service: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + service_provider: { + type: DataTypes.CHAR(40), + allowNull: false, + }, timestamp_ns: { type: DataTypes.DECIMAL(20), allowNull: false, @@ -59,7 +73,7 @@ export async function up({ context }: Context): Promise { RETURNS trigger AS $$ BEGIN - PERFORM pg_notify('tap_horizon_receipt_notification', format('{"id": %s, "allocation_id": "%s", "signer_address": "%s", "timestamp_ns": %s, "value": %s}', NEW.id, NEW.allocation_id, NEW.signer_address, NEW.timestamp_ns, NEW.value)); + PERFORM pg_notify('tap_horizon_receipt_notification', format('{"id": %s, "collection_id": "%s", "signer_address": "%s", "timestamp_ns": %s, "value": %s}', NEW.id, NEW.collection_id, NEW.signer_address, NEW.timestamp_ns, NEW.value)); RETURN NEW; END; $$ LANGUAGE 'plpgsql'; @@ -72,8 +86,8 @@ export async function up({ context }: Context): Promise { await queryInterface.sequelize.query(functionSQL) await queryInterface.sequelize.query(triggerSQL) - queryInterface.addIndex('tap_horizon_receipts', ['allocation_id'], { - name: 'tap_horizon_receipts_allocation_id_idx', + queryInterface.addIndex('tap_horizon_receipts', ['collection_id'], { + name: 'tap_horizon_receipts_collection_id_idx', }) queryInterface.addIndex('tap_horizon_receipts', ['timestamp_ns'], { name: 'tap_horizon_receipts_timestamp_ns_idx', @@ -91,18 +105,32 @@ export async function up({ context }: Context): Promise { primaryKey: true, autoIncrement: true, }, - allocation_id: { - type: DataTypes.CHAR(40), - allowNull: false, - }, signer_address: { type: DataTypes.CHAR(40), allowNull: false, }, + + // Values below are the individual fields of the EIP-712 receipt signature: { type: DataTypes.BLOB, allowNull: false, }, + collection_id: { + type: DataTypes.CHAR(64), + allowNull: false, + }, + payer: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + data_service: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + service_provider: { + type: DataTypes.CHAR(40), + allowNull: false, + }, timestamp_ns: { type: DataTypes.DECIMAL(20), allowNull: false, @@ -115,6 +143,10 @@ export async function up({ context }: Context): Promise { type: DataTypes.DECIMAL(20), allowNull: false, }, + error_log: { + type: DataTypes.TEXT, + allowNull: true, + }, }) } @@ -123,28 +155,29 @@ export async function up({ context }: Context): Promise { } else { // Create the tap_horizon_ravs table if it doesn't exist await queryInterface.createTable('tap_horizon_ravs', { + // Values below are the individual fields of the EIP-712 receipt + signature: { + type: DataTypes.BLOB, + allowNull: false, + }, collection_id: { type: DataTypes.CHAR(64), allowNull: false, }, - sender_address: { + payer: { type: DataTypes.CHAR(40), allowNull: false, }, - service_provider_address: { + data_service: { type: DataTypes.CHAR(40), allowNull: false, }, - data_service_address: { + service_provider: { type: DataTypes.CHAR(40), allowNull: false, }, - signature: { - type: DataTypes.BLOB, - allowNull: false, - }, timestamp_ns: { - type: DataTypes.DECIMAL, + type: DataTypes.DECIMAL(20), allowNull: false, }, value_aggregate: { @@ -155,16 +188,18 @@ export async function up({ context }: Context): Promise { type: DataTypes.BLOB, allowNull: false, }, - final: { + + last: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false, }, - last: { + final: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false, }, + redeemed_at: { type: DataTypes.DATE, allowNull: true, @@ -182,7 +217,7 @@ export async function up({ context }: Context): Promise { logger.info(`Add primary key`) await queryInterface.addConstraint('tap_horizon_ravs', { - fields: ['collection_id', 'sender_address', 'service_provider_address', 'data_service_address'], + fields: ['payer', 'data_service', 'service_provider', 'collection_id'], type: 'primary key', name: 'pk_tap_horizon_ravs', }) @@ -197,15 +232,15 @@ export async function up({ context }: Context): Promise { type: DataTypes.CHAR(64), allowNull: false, }, - sender_address: { + payer: { type: DataTypes.CHAR(40), allowNull: false, }, - service_provider_address: { + data_service: { type: DataTypes.CHAR(40), allowNull: false, }, - data_service_address: { + service_provider: { type: DataTypes.CHAR(40), allowNull: false, }, @@ -239,7 +274,7 @@ export async function down({ context }: Context): Promise { ) await queryInterface.removeIndex( 'tap_horizon_receipts', - 'tap_horizon_receipts_allocation_id_idx', + 'tap_horizon_receipts_collection_id_idx', ) await queryInterface.removeIndex( 'tap_horizon_receipts', diff --git a/packages/indexer-common/src/query-fees/models.ts b/packages/indexer-common/src/query-fees/models.ts index 7ed997e2d..5de5a0d4f 100644 --- a/packages/indexer-common/src/query-fees/models.ts +++ b/packages/indexer-common/src/query-fees/models.ts @@ -32,21 +32,30 @@ export class ScalarTapReceipts export interface TapHorizonReceiptsAttributes { id: number - allocation_id: Address signer_address: Address + signature: Uint8Array + collection_id: string + payer: Address + data_service: Address + service_provider: Address timestamp_ns: bigint nonce: bigint value: bigint + error_log?: string } export class TapHorizonReceipts extends Model implements TapHorizonReceiptsAttributes { public id!: number - public allocation_id!: Address public signer_address!: Address + public signature!: Uint8Array + public collection_id!: string + public payer!: Address + public data_service!: Address + public service_provider!: Address public timestamp_ns!: bigint public nonce!: bigint public value!: bigint @@ -75,12 +84,17 @@ export class TapHorizonReceiptsInvalid extends Model implements TapHorizonReceiptsAttributes { public id!: number - public allocation_id!: Address public signer_address!: Address + + public signature!: Uint8Array + public collection_id!: string + public payer!: Address + public data_service!: Address + public service_provider!: Address public timestamp_ns!: bigint public nonce!: bigint public value!: bigint - public signature!: Uint8Array + public error_log!: string declare createdAt: CreationOptional @@ -143,17 +157,18 @@ export interface ReceiptAggregateVoucherAttributes { } export interface ReceiptAggregateVoucherV2Attributes { - collectionId: string - senderAddress: string - serviceProviderAddress: string - dataServiceAddress: string - metadata: string signature: Uint8Array + collectionId: string + payer: string + dataService: string + serviceProvider: string timestampNs: bigint valueAggregate: bigint + metadata: string + last: boolean - redeemedAt: Date | null final: boolean + redeemedAt: Date | null } export interface FailedReceiptAggregateVoucherAttributes { @@ -167,9 +182,9 @@ export interface FailedReceiptAggregateVoucherAttributes { export interface FailedReceiptAggregateVoucherV2Attributes { collectionId: string - senderAddress: string - serviceProviderAddress: string - dataServiceAddress: string + payer: string + dataService: string + serviceProvider: string expectedRav: JSON rav_response: JSON reason: string @@ -210,29 +225,26 @@ export class ReceiptAggregateVoucher // TODO HORIZON: move this to the toolshed package export type SignedRAVv2 = { - rav: Omit & { - senderAddress: string - serviceProviderAddress: string - dataServiceAddress: string - } + rav: RAVv2 signature: BytesLike } export class ReceiptAggregateVoucherV2 extends Model implements ReceiptAggregateVoucherV2Attributes { - public collectionId!: Address - public senderAddress!: Address - public serviceProviderAddress!: Address - public dataServiceAddress!: Address - public metadata!: string public signature!: Uint8Array + public collectionId!: string + public payer!: Address + public dataService!: Address + public serviceProvider!: Address public timestampNs!: bigint public valueAggregate!: bigint + public metadata!: string + public final!: boolean public last!: boolean - public redeemedAt!: Date | null + public redeemedAt!: Date | null declare createdAt: CreationOptional declare updatedAt: CreationOptional @@ -246,9 +258,9 @@ export class ReceiptAggregateVoucherV2 return { rav: { collectionId: this.collectionId, - senderAddress: this.senderAddress, - serviceProviderAddress: this.serviceProviderAddress, - dataServiceAddress: this.dataServiceAddress, + payer: this.payer, + dataService: this.dataService, + serviceProvider: this.serviceProvider, timestampNs: Number(this.timestampNs), valueAggregate: this.valueAggregate, metadata: this.metadata, @@ -274,10 +286,10 @@ export class FailedReceiptAggregateVoucher export class FailedReceiptAggregateVoucherV2 extends Model implements FailedReceiptAggregateVoucherV2Attributes { - public collectionId!: Address - public senderAddress!: Address - public serviceProviderAddress!: Address - public dataServiceAddress!: Address + public collectionId!: string + public payer!: Address + public dataService!: Address + public serviceProvider!: Address public expectedRav!: JSON public rav_response!: JSON public reason!: string @@ -385,6 +397,7 @@ export class AllocationSummary allocationReceipts: Association voucher: Association receiptAggregateVoucher: Association + receiptAggregateVoucherV2: Association } } @@ -555,48 +568,48 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { const rawValue = this.getDataValue('collectionId') return toAddress(rawValue) }, - set(value: Address) { + set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') this.setDataValue('collectionId', addressWithoutPrefix) }, }, - senderAddress: { + payer: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('senderAddress') + const rawValue = this.getDataValue('payer') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('senderAddress', addressWithoutPrefix) + this.setDataValue('payer', addressWithoutPrefix) }, }, - serviceProviderAddress: { + serviceProvider: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('serviceProviderAddress') + const rawValue = this.getDataValue('serviceProvider') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('serviceProviderAddress', addressWithoutPrefix) + this.setDataValue('serviceProvider', addressWithoutPrefix) }, }, - dataServiceAddress: { + dataService: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('dataServiceAddress') + const rawValue = this.getDataValue('dataService') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('dataServiceAddress', addressWithoutPrefix) + this.setDataValue('dataService', addressWithoutPrefix) }, }, metadata: { @@ -830,48 +843,48 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { const rawValue = this.getDataValue('collectionId') return toAddress(rawValue) }, - set(value: Address) { + set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') this.setDataValue('collectionId', addressWithoutPrefix) }, }, - senderAddress: { + payer: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('senderAddress') + const rawValue = this.getDataValue('payer') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('senderAddress', addressWithoutPrefix) + this.setDataValue('payer', addressWithoutPrefix) }, }, - serviceProviderAddress: { + serviceProvider: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('serviceProviderAddress') + const rawValue = this.getDataValue('serviceProvider') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('serviceProviderAddress', addressWithoutPrefix) + this.setDataValue('serviceProvider', addressWithoutPrefix) }, }, - dataServiceAddress: { + dataService: { type: DataTypes.CHAR(40), // 40 because prefix '0x' gets removed by TAP agent allowNull: false, primaryKey: true, get() { - const rawValue = this.getDataValue('dataServiceAddress') + const rawValue = this.getDataValue('dataService') return toAddress(rawValue) }, set(value: string) { const addressWithoutPrefix = value.toLowerCase().replace('0x', '') - this.setDataValue('dataServiceAddress', addressWithoutPrefix) + this.setDataValue('dataService', addressWithoutPrefix) }, }, expectedRav: { @@ -942,7 +955,7 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { primaryKey: true, autoIncrement: true, }, - allocation_id: { + collection_id: { type: DataTypes.CHAR(40), allowNull: false, }, @@ -950,6 +963,18 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { type: DataTypes.CHAR(40), allowNull: false, }, + payer: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + data_service: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + service_provider: { + type: DataTypes.CHAR(40), + allowNull: false, + }, signature: { type: DataTypes.BLOB, allowNull: false, @@ -1028,7 +1053,19 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { primaryKey: true, autoIncrement: true, }, - allocation_id: { + collection_id: { + type: DataTypes.CHAR(64), + allowNull: false, + }, + payer: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + data_service: { + type: DataTypes.CHAR(40), + allowNull: false, + }, + service_provider: { type: DataTypes.CHAR(40), allowNull: false, }, From 19a4df1f4cf5c8807ee6a03c2911a9fbcae2ba46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 24 Jun 2025 17:57:30 -0300 Subject: [PATCH 24/28] feat: add graph-tally collector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .../src/allocations/graph-tally-collector.ts | 761 ++++++++++++++++++ .../allocations/horizon-escrow-accounts.ts | 106 +++ packages/indexer-common/src/network.ts | 27 + 3 files changed, 894 insertions(+) create mode 100644 packages/indexer-common/src/allocations/graph-tally-collector.ts create mode 100644 packages/indexer-common/src/allocations/horizon-escrow-accounts.ts diff --git a/packages/indexer-common/src/allocations/graph-tally-collector.ts b/packages/indexer-common/src/allocations/graph-tally-collector.ts new file mode 100644 index 000000000..e502dfea6 --- /dev/null +++ b/packages/indexer-common/src/allocations/graph-tally-collector.ts @@ -0,0 +1,761 @@ +import { Counter, Gauge, Histogram } from 'prom-client' +import { + Logger, + toAddress, + formatGRT, + Address, + Metrics, + Eventual, +} from '@graphprotocol/common-ts' +import { + Allocation, + indexerError, + IndexerErrorCode, + QueryFeeModels, + ensureAllocationSummary, + TransactionManager, + specification as spec, + SignedRAVv2, + parseGraphQLAllocation, + sequentialTimerMap, + ReceiptAggregateVoucherV2, +} from '..' +import pReduce from 'p-reduce' +import { SubgraphClient, QueryResult } from '../subgraph-client' +import gql from 'graphql-tag' +import { getEscrowAccounts } from './horizon-escrow-accounts' +import { + GraphHorizonContracts, + SubgraphServiceContracts, +} from '@graphprotocol/toolshed/deployments' +import { encodeCollectQueryFeesData, PaymentTypes } from '@graphprotocol/toolshed' +import { zeroPadValue, dataSlice } from 'ethers' + +// every 15 minutes +const RAV_CHECK_INTERVAL_MS = 900_000 + +// 1000 here was leading to http 413 request entity too large +const PAGE_SIZE = 200 + +interface RavMetrics { + ravRedeemsSuccess: Counter + ravRedeemsInvalid: Counter + ravRedeemsFailed: Counter + ravsRedeemDuration: Histogram + ravCollectedFees: Gauge +} + +interface TapCollectorOptions { + logger: Logger + metrics: Metrics + transactionManager: TransactionManager + contracts: GraphHorizonContracts & SubgraphServiceContracts + allocations: Eventual + models: QueryFeeModels + networkSpecification: spec.NetworkSpecification + networkSubgraph: SubgraphClient +} + +interface ValidRavs { + belowThreshold: RavWithAllocation[] + eligible: RavWithAllocation[] +} + +export interface RavWithAllocation { + rav: SignedRAVv2 + allocation: Allocation + payer: string +} + +export interface SubgraphResponse { + transactions: GraphTallyTransaction[] + _meta: GraphTallyMeta +} + +interface GraphTallyMeta { + block: { + timestamp: number + hash: string + } +} + +export interface GraphTallyTransaction { + id: string + allocationId: string + timestamp: number + payer: { + id: string + } +} + +export interface AllocationsResponse { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + allocations: any[] + meta: { + block: { + hash: string + } + } +} + +export class GraphTallyCollector { + declare logger: Logger + declare metrics: RavMetrics + declare models: QueryFeeModels + declare transactionManager: TransactionManager + declare contracts: GraphHorizonContracts & SubgraphServiceContracts + declare allocations: Eventual + declare ravRedemptionThreshold: bigint + declare protocolNetwork: string + declare networkSubgraph: SubgraphClient + declare finalityTime: number + declare indexerAddress: Address + + // eslint-disable-next-line @typescript-eslint/no-empty-function -- Private constructor to prevent direct instantiation + private constructor() { } + + public static create({ + logger, + metrics, + transactionManager, + models, + contracts, + allocations, + networkSpecification, + networkSubgraph, + }: TapCollectorOptions): GraphTallyCollector { + const collector = new GraphTallyCollector() + collector.logger = logger.child({ component: 'GraphTallyCollector' }) + collector.metrics = registerReceiptMetrics( + metrics, + networkSpecification.networkIdentifier, + ) + collector.transactionManager = transactionManager + collector.models = models + collector.contracts = contracts + collector.allocations = allocations + collector.protocolNetwork = networkSpecification.networkIdentifier + collector.networkSubgraph = networkSubgraph + + const { voucherRedemptionThreshold, finalityTime, address } = + networkSpecification.indexerOptions + collector.ravRedemptionThreshold = voucherRedemptionThreshold + collector.finalityTime = finalityTime + collector.indexerAddress = address + + collector.logger.info(`RAV v2 processing is initiated`) + collector.startRAVProcessing() + return collector + } + + startRAVProcessing() { + const notifyAndMapEligible = (signedRavs: ValidRavs) => { + if (signedRavs.belowThreshold.length > 0) { + const logger = this.logger.child({ function: 'startRAVProcessingV2()' }) + const totalValueGRT = formatGRT( + signedRavs.belowThreshold.reduce( + (total, signedRav) => total + BigInt(signedRav.rav.rav.valueAggregate), + 0n, + ), + ) + logger.info(`Query RAVs v2 below the redemption threshold`, { + hint: 'If you would like to redeem RAVs v2 like this, reduce the voucher redemption threshold', + ravRedemptionThreshold: formatGRT(this.ravRedemptionThreshold), + belowThresholdCount: signedRavs.belowThreshold.length, + totalValueGRT, + allocations: signedRavs.belowThreshold.map( + (signedRav) => dataSlice(signedRav.rav.rav.collectionId, 12).toString(), + ), + }) + } + return signedRavs.eligible + } + + const pendingRAVs = this.getPendingRAVs() + const signedRAVs = this.getSignedRAVsEventual(pendingRAVs) + const eligibleRAVs = signedRAVs + .map(notifyAndMapEligible) + .filter((signedRavs) => signedRavs.length > 0) + eligibleRAVs.pipe(async (ravs) => await this.submitRAVs(ravs)) + } + + private getPendingRAVs(): Eventual { + return sequentialTimerMap( + { + logger: this.logger, + milliseconds: RAV_CHECK_INTERVAL_MS, + }, + async () => { + let ravs = await this.pendingRAVs() + if (ravs.length === 0) { + this.logger.info(`No pending RAVs v2 to process`) + return [] + } + if (ravs.length > 0) { + ravs = await this.filterAndUpdateRavs(ravs) + } + const allocations: Allocation[] = await this.getAllocationsfromAllocationIds(ravs) + this.logger.info(`Retrieved allocations for pending RAVs v2`, { + ravs: ravs.length, + allocations: allocations.length, + }) + return ravs + .map((rav) => { + const signedRav = rav.getSignedRAV() + return { + rav: signedRav, + allocation: allocations.find( + (a) => a.id === toAddress(dataSlice(signedRav.rav.collectionId, 12).toString()), + ), + payer: rav.payer, + } + }) + .filter((rav) => rav.allocation !== undefined) as RavWithAllocation[] // this is safe because we filter out undefined allocations + }, + { onError: (err) => this.logger.error(`Failed to query pending RAVs v2`, { err }) }, + ) + } + + private async getAllocationsfromAllocationIds( + ravs: ReceiptAggregateVoucherV2[], + ): Promise { + const allocationIds: string[] = ravs.map((rav) => + dataSlice(rav.collectionId, 12).toString().toLowerCase(), + ) + + let block: { hash: string } | undefined = undefined + let lastId = '' + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const returnedAllocations: any[] = [] + + for (; ;) { + const result = await this.networkSubgraph.query( + gql` + query allocations( + $lastId: String! + $pageSize: Int! + $block: Block_height + $allocationIds: [String!]! + ) { + meta: _meta(block: $block) { + block { + number + hash + timestamp + } + } + allocations( + first: $pageSize + block: $block + orderBy: id + orderDirection: asc + where: { id_gt: $lastId, id_in: $allocationIds } + ) { + id + status + subgraphDeployment { + id + stakedTokens + signalledTokens + queryFeesAmount + deniedAt + } + indexer { + id + } + allocatedTokens + createdAtEpoch + createdAtBlockHash + closedAtEpoch + closedAtEpoch + closedAtBlockHash + poi + queryFeeRebates + queryFeesCollected + } + } + `, + { allocationIds, lastId, pageSize: PAGE_SIZE, block }, + ) + if (!result.data) { + throw `There was an error while querying Network Subgraph. Errors: ${result.error}` + } + + returnedAllocations.push(...result.data.allocations) + block = { hash: result.data.meta.block.hash } + if (result.data.allocations.length < PAGE_SIZE) { + break + } + lastId = result.data.allocations.slice(-1)[0].id + } + + if (returnedAllocations.length == 0) { + this.logger.error( + `No allocations returned for ${allocationIds} in network subgraph`, + ) + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return returnedAllocations.map((x) => parseGraphQLAllocation(x, this.protocolNetwork)) + } + + private getSignedRAVsEventual( + pendingRAVs: Eventual, + ): Eventual { + + return pendingRAVs.tryMap( + async (pendingRAVs) => { + const escrowAccounts = await getEscrowAccounts(this.networkSubgraph, this.indexerAddress, this.contracts.GraphTallyCollector.target.toString()) + return await pReduce( + pendingRAVs, + async (results, rav) => { + const tokensCollected = escrowAccounts.getTokensCollectedForReceiver(rav.payer, rav.rav.rav.collectionId) + if ((BigInt(rav.rav.rav.valueAggregate) - tokensCollected) < this.ravRedemptionThreshold) { + results.belowThreshold.push(rav) + } else { + results.eligible.push(rav) + } + return results + }, + { belowThreshold: [], eligible: [] }, + ) + }, + { onError: (err) => this.logger.error(`Failed to reduce to signed RAVs`, { err }) }, + ) + } + + // redeem only if last is true + // Later can add order and limit + private async pendingRAVs(): Promise { + return await this.models.receiptAggregateVouchersV2.findAll({ + where: { last: true, final: false }, + limit: 100, + }) + } + + private async filterAndUpdateRavs( + ravsLastNotFinal: ReceiptAggregateVoucherV2[], + ): Promise { + // look for all transactions for that includes senderaddress[] and allocations[] + const subgraphResponse = await this.findTransactionsForRavs(ravsLastNotFinal) + + // check for redeemed ravs in tx list but not marked as redeemed in our database + this.markRavsInTransactionsAsRedeemed(subgraphResponse, ravsLastNotFinal) + + // Filter unfinalized RAVS fetched from DB, keeping RAVs that have not yet been redeemed on-chain + const nonRedeemedRavs = ravsLastNotFinal + // get all ravs that were marked as redeemed in our database + .filter((rav) => !!rav.redeemedAt) + // get all ravs that wasn't possible to find the transaction + .filter( + (rav) => + !subgraphResponse.transactions.find( + (tx) => + toAddress(rav.payer) === toAddress(tx.payer.id) && + dataSlice(rav.collectionId, 12) === tx.allocationId, + ), + ) + + // we use the subgraph timestamp to make decisions + // block timestamp minus 1 minute (because of blockchain timestamp uncertainty) + const ONE_MINUTE = 60 + const blockTimestampSecs = subgraphResponse._meta.block.timestamp - ONE_MINUTE + + // Mark RAVs as unredeemed in DB if the TAP subgraph couldn't find the redeem Tx. + // To handle a chain reorg that "unredeemed" the RAVs. + if (nonRedeemedRavs.length > 0) { + await this.revertRavsRedeemed(nonRedeemedRavs, blockTimestampSecs) + } + + // For all RAVs that passed finality time, we mark it as final + await this.markRavsAsFinal(blockTimestampSecs) + + return await this.models.receiptAggregateVouchersV2.findAll({ + where: { redeemedAt: null, final: false, last: true }, + }) + } + + public async markRavsInTransactionsAsRedeemed( + subgraphResponse: SubgraphResponse, + ravsLastNotFinal: ReceiptAggregateVoucherV2[], + ) { + // get a list of transactions for ravs marked as not redeemed in our database + const redeemedRavsNotOnOurDatabase = subgraphResponse.transactions + // get only the transactions that exists, this prevents errors marking as redeemed + // transactions for different senders with the same allocation id + .filter((tx) => { + // check if exists in the ravsLastNotFinal list + return !!ravsLastNotFinal.find( + (rav) => + // rav has the same sender address as tx + toAddress(rav.payer) === toAddress(tx.payer.id) && + // rav has the same allocation id as tx + dataSlice(rav.collectionId, 12) === tx.allocationId && + // rav was marked as not redeemed in the db + !rav.redeemedAt, + ) + }) + + // for each transaction that is not redeemed on our database + // but was redeemed on the blockchain, update it to redeemed + if (redeemedRavsNotOnOurDatabase.length > 0) { + for (const rav of redeemedRavsNotOnOurDatabase) { + await this.markRavAsRedeemed( + zeroPadValue(rav.allocationId, 32), + rav.payer.id, + rav.timestamp, + ) + } + } + } + + public async findTransactionsForRavs( + ravs: ReceiptAggregateVoucherV2[], + ): Promise { + let meta: GraphTallyMeta | undefined = undefined + let lastId = '' + const transactions: GraphTallyTransaction[] = [] + + const unfinalizedRavsAllocationIds = [ + ...new Set(ravs.map((value) => toAddress(value.collectionId.slice(12)).toLowerCase())), + ] + + const payerAddresses = [ + ...new Set(ravs.map((value) => toAddress(value.payer).toLowerCase())), + ] + + for (; ;) { + let block: { hash: string } | undefined = undefined + if (meta?.block?.hash) { + block = { + hash: meta?.block?.hash, + } + } + + const result: QueryResult = + await this.networkSubgraph.query( + gql` + query transactions( + $lastId: String! + $pageSize: Int! + $block: Block_height + $unfinalizedRavsAllocationIds: [String!]! + $payerAddresses: [String!]! + ) { + transactions( + first: $pageSize + block: $block + orderBy: id + orderDirection: asc + where: { + id_gt: $lastId + type: "redeem" + allocationId_in: $unfinalizedRavsAllocationIds + payer_: { id_in: $payerAddresses } + } + ) { + id + allocationId + timestamp + payer { + id + } + } + _meta { + block { + hash + timestamp + } + } + } + `, + { + lastId, + pageSize: PAGE_SIZE, + block, + unfinalizedRavsAllocationIds, + payerAddresses, + }, + ) + + if (!result.data) { + throw `There was an error while querying Network Subgraph. Errors: ${result.error}` + } + meta = result.data._meta + transactions.push(...result.data.transactions) + if (result.data.transactions.length < PAGE_SIZE) { + break + } + lastId = result.data.transactions.slice(-1)[0].id + } + + return { + transactions, + _meta: meta!, + } + } + + // for every allocation_id of this list that contains the redeemedAt less than the current + // subgraph timestamp + private async revertRavsRedeemed( + ravsNotRedeemed: { collectionId: string; payer: string }[], + blockTimestampSecs: number, + ) { + if (ravsNotRedeemed.length == 0) { + return + } + + // WE use sql directly due to a bug in sequelize update: + // https://github.com/sequelize/sequelize/issues/7664 (bug been open for 7 years no fix yet or ever) + const query = ` + UPDATE tap_horizon_ravs + SET redeemed_at = NULL + WHERE (collection_id::char(64), payer::char(40)) IN (VALUES ${ravsNotRedeemed + .map( + (rav) => + `('${rav.collectionId + .toString() + .toLowerCase() + .replace('0x', '')}'::char(64), '${rav.payer + .toString() + .toLowerCase() + .replace('0x', '')}'::char(40))`, + ) + .join(', ')}) + AND redeemed_at < to_timestamp(${blockTimestampSecs}) + ` + + await this.models.receiptAggregateVouchersV2.sequelize?.query(query) + + this.logger.warn( + `Reverted Redeemed RAVs v2: ${ravsNotRedeemed + .map((rav) => `(${rav.payer},${rav.collectionId})`) + .join(', ')}`, + ) + } + + // we use blockTimestamp instead of NOW() because we must be older than + // the subgraph timestamp + private async markRavsAsFinal(blockTimestampSecs: number) { + const query = ` + UPDATE tap_horizon_ravs + SET final = TRUE + WHERE last = TRUE + AND final = FALSE + AND redeemed_at IS NOT NULL + AND redeemed_at < to_timestamp(${blockTimestampSecs - this.finalityTime}) + ` + + await this.models.receiptAggregateVouchersV2.sequelize?.query(query) + } + + private async submitRAVs(signedRavs: RavWithAllocation[]): Promise { + const logger = this.logger.child({ + function: 'submitRAVsV2', + ravsToSubmit: signedRavs.length, + }) + + logger.info(`Submit last RAVs v2 on chain individually`, { + signedRavs, + }) + + const escrowAccounts = await getEscrowAccounts(this.networkSubgraph, this.indexerAddress, this.contracts.GraphTallyCollector.target.toString()) + + // Redeem RAV one-by-one as no plual version available + const tokensCollectedPerAllocation: { allocationId: string, tokensCollected: bigint }[] = []; + + for (const { rav: signedRav, allocation, payer } of signedRavs) { + const { rav } = signedRav + + // verify escrow balances + const ravValue = BigInt(rav.valueAggregate.toString()) + const tokensAlreadyCollected = escrowAccounts.getTokensCollectedForReceiver(payer, rav.collectionId) + const payerBalance = escrowAccounts.getBalanceForPayer(payer) + + // In horizon the RAV value is monotonically increasing. To calculate the actual outstanding amount we need to subtract the tokens already collected. + const tokensToCollect = ravValue - tokensAlreadyCollected + if (payerBalance < tokensToCollect) { + this.logger.warn( + 'RAV v2 was not sent to the blockchain \ + because its value aggregate is lower than escrow balance.', + { + rav, + payer, + payerBalance, + }, + ) + continue + } + + const stopTimer = this.metrics.ravsRedeemDuration.startTimer({ + collection: rav.collectionId, + }) + + try { + // subtract from the escrow account + // THIS IS A MUT OPERATION + const actualTokensCollected = await this.redeemRav(logger, signedRav) + if (!actualTokensCollected) { + throw new Error(`Failed to redeem RAV v2: no tokens collected`) + } + tokensCollectedPerAllocation.push({ allocationId: allocation.id, tokensCollected: actualTokensCollected }) + escrowAccounts.updateBalances(payer, rav.collectionId, actualTokensCollected) + } catch (err) { + this.metrics.ravRedeemsFailed.inc({ collection: rav.collectionId }) + logger.error(`Failed to redeem RAV v2`, { + err: indexerError(IndexerErrorCode.IE055, err), + }) + continue + } + stopTimer() + } + + try { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await this.models.allocationSummaries.sequelize!.transaction( + async (transaction) => { + for (const { allocationId, tokensCollected } of tokensCollectedPerAllocation) { + const [summary] = await ensureAllocationSummary( + this.models, + toAddress(allocationId.toString()), + transaction, + this.protocolNetwork, + ) + summary.withdrawnFees = ( + BigInt(summary.withdrawnFees) + BigInt(tokensCollected) + ).toString() + await summary.save({ transaction }) + } + }, + ) + + logger.info(`Updated allocation summaries table with withdrawn fees for RAV v2`) + } catch (err) { + logger.warn(`Failed to update allocation summaries for RAV v2`, { + err, + }) + } + + signedRavs.map((signedRav) => + this.metrics.ravRedeemsSuccess.inc({ collection: signedRav.rav.rav.collectionId }), + ) + } + + public async redeemRav( + logger: Logger, + signedRav: SignedRAVv2, + ): Promise { + const { rav, signature } = signedRav + + const encodedData = encodeCollectQueryFeesData(rav, signature.toString(), 0n) + + // Submit the signed RAV on chain + const txReceipt = await this.transactionManager.executeTransaction( + () => this.contracts.SubgraphService.collect.estimateGas(rav.serviceProvider, PaymentTypes.QueryFee, encodedData), + (gasLimit) => + this.contracts.SubgraphService.collect(rav.serviceProvider, 0, encodedData, { + gasLimit, + }), + logger.child({ function: 'collect' }), + ) + + // get tx receipt and post process + if (txReceipt === 'paused' || txReceipt === 'unauthorized') { + this.metrics.ravRedeemsInvalid.inc({ collection: rav.collectionId }) + return + } + + // Get the actual value collected + const contractInterface = this.contracts.GraphTallyCollector.interface + const event = contractInterface.getEvent('PaymentCollected') + + const log = txReceipt.logs.find(log => log.topics[0] === event.topicHash); + if (!log) throw new Error('PaymentCollected event not found!'); + + const decoded = contractInterface.decodeEventLog(event, log.data, log.topics); + if (!decoded.tokens) { + throw new Error(`Actual value collected not found for collection ${rav.collectionId}`) + } + const actualTokensCollected = BigInt(decoded.tokens); + + this.metrics.ravCollectedFees.set( + { collection: rav.collectionId }, + parseFloat(actualTokensCollected.toString()), + ) + + try { + await this.markRavAsRedeemed(rav.collectionId, rav.payer) + logger.info( + `Updated receipt aggregate vouchers v2 table with redeemed_at for collection ${rav.collectionId} and payer ${rav.payer}`, + ) + } catch (err) { + logger.warn( + `Failed to update receipt aggregate voucher v2 table with redeemed_at for collection ${rav.collectionId} and payer ${rav.payer}`, + { + err, + }, + ) + } + + return actualTokensCollected; + } + + private async markRavAsRedeemed( + collectionId: string, + payer: string, + timestamp?: number, + ) { + // WE use sql directly due to a bug in sequelize update: + // https://github.com/sequelize/sequelize/issues/7664 (bug been open for 7 years no fix yet or ever) + const query = ` + UPDATE tap_horizon_ravs + SET redeemed_at = ${timestamp ? `to_timestamp(${timestamp})` : 'NOW()'} + WHERE collection_id = '${collectionId + .toString() + .toLowerCase() + .replace('0x', '')}' + AND payer = '${payer + .toString() + .toLowerCase() + .replace('0x', '')}' + ` + + await this.models.receiptAggregateVouchersV2.sequelize?.query(query) + } +} + +const registerReceiptMetrics = (metrics: Metrics, networkIdentifier: string) => ({ + ravRedeemsSuccess: new metrics.client.Counter({ + name: `indexer_agent_rav_v2_exchanges_ok_${networkIdentifier}`, + help: 'Successfully redeemed ravs v2', + registers: [metrics.registry], + labelNames: ['collection'], + }), + + ravRedeemsInvalid: new metrics.client.Counter({ + name: `indexer_agent_rav_v2_exchanges_invalid_${networkIdentifier}`, + help: 'Invalid ravs v2 redeems - tx paused or unauthorized', + registers: [metrics.registry], + labelNames: ['collection'], + }), + + ravRedeemsFailed: new metrics.client.Counter({ + name: `indexer_agent_rav_v2_redeems_failed_${networkIdentifier}`, + help: 'Failed redeems for ravs v2', + registers: [metrics.registry], + labelNames: ['collection'], + }), + + ravsRedeemDuration: new metrics.client.Histogram({ + name: `indexer_agent_rav_v2_redeem_duration_${networkIdentifier}`, + help: 'Duration of redeeming ravs v2', + registers: [metrics.registry], + labelNames: ['collection'], + }), + + ravCollectedFees: new metrics.client.Gauge({ + name: `indexer_agent_rav_v2_collected_fees_${networkIdentifier}`, + help: 'Amount of query fees collected for a rav v2', + registers: [metrics.registry], + labelNames: ['collection'], + }), +}) diff --git a/packages/indexer-common/src/allocations/horizon-escrow-accounts.ts b/packages/indexer-common/src/allocations/horizon-escrow-accounts.ts new file mode 100644 index 000000000..6607364a9 --- /dev/null +++ b/packages/indexer-common/src/allocations/horizon-escrow-accounts.ts @@ -0,0 +1,106 @@ +import { SubgraphClient } from '../subgraph-client' +import gql from 'graphql-tag' + +export type PaymentsEscrowAccountResponse = { + paymentsEscrowAccounts: { + balance: string + payer: { + id: string + } + }[], + // Not a typo just how graph-client pluralizes the field name + graphTallyTokensCollecteds: { + tokens: string + collectionId: string + payer: { + id: string + }, + }[] +} + +export class PaymentsEscrowAccounts { + private payersBalances: Map + private receiversTokensCollected: Map + + constructor(payersBalances: Map, receiversTokensCollected: Map) { + this.payersBalances = payersBalances + this.receiversTokensCollected = receiversTokensCollected + } + + getBalanceForPayer(payer: string): bigint { + const balance = this.payersBalances.get(payer) + if (balance === undefined) { + throw new Error(`No balance found for payer: ${payer}`) + } + return balance + } + + getTokensCollectedForReceiver(payer: string, collectionId: string): bigint { + const balance = this.receiversTokensCollected.get(`${payer}-${collectionId}`) + if (balance === undefined) { + throw new Error(`No tokens collected found for payer: ${payer} and collectionId: ${collectionId}`) + } + return balance + } + + updateBalances(payer: string, collectionId: string, value: bigint) { + // payer balance + const balance = this.getBalanceForPayer(payer) + if (balance < value) { + throw new Error(`Negative balances are not allowed`) + } + const newBalance = balance - value + this.payersBalances.set(payer, newBalance) + + // receiver tokens collected + const tokensCollected = this.getTokensCollectedForReceiver(payer, collectionId) + this.receiversTokensCollected.set(`${payer}-${collectionId}`, tokensCollected + value) + } + + static fromResponse(response: PaymentsEscrowAccountResponse): PaymentsEscrowAccounts { + const payersBalances = new Map() + const tokensCollected = new Map() + + response.paymentsEscrowAccounts.forEach((account) => { + payersBalances.set(account.payer.id, BigInt(account.balance)) + }) + + response.graphTallyTokensCollecteds.forEach((token) => { + tokensCollected.set(`${token.payer.id}-${token.collectionId}`, BigInt(token.tokens)) + }) + + return new PaymentsEscrowAccounts(payersBalances, tokensCollected) + } +} + +export const getEscrowAccounts = async ( + subgraph: SubgraphClient, + indexer: string, + collectorAddress: string, +): Promise => { + const result = await subgraph.query( + gql` + query PaymentsEscrowAccountQuery($indexer: ID!, $collector: String!) { + paymentsEscrowAccounts(where: { receiver_: { id: $indexer }, collector: $collector }) { + balance + payer { + id + } + } + graphTallyTokensCollecteds(where: { receiver_: { id: $indexer } }) { + tokens + collectionId + payer { + id + } + } + } + `, + { indexer, collector: collectorAddress }, + ) + if (!result.data) { + throw `There was an error while querying Network Subgraph. Errors: ${result.error}` + } + + return PaymentsEscrowAccounts.fromResponse(result.data) +} diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index 719392bc8..d8a94e97e 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -37,6 +37,7 @@ import { resolveChainId } from './indexer-management' import { monitorEthBalance } from './utils' import { QueryFeeModels } from './query-fees' import { TapCollector } from './allocations/tap-collector' +import { GraphTallyCollector } from './allocations/graph-tally-collector' import { encodeRegistrationData } from '@graphprotocol/toolshed' export class Network { @@ -49,6 +50,7 @@ export class Network { networkMonitor: NetworkMonitor tapCollector: TapCollector | undefined + graphTallyCollector: GraphTallyCollector | undefined specification: spec.NetworkSpecification paused: Eventual isOperator: Eventual @@ -63,6 +65,7 @@ export class Network { transactionManager: TransactionManager, networkMonitor: NetworkMonitor, tapCollector: TapCollector | undefined, + graphTallyCollector: GraphTallyCollector | undefined, specification: spec.NetworkSpecification, paused: Eventual, isOperator: Eventual, @@ -76,6 +79,7 @@ export class Network { this.transactionManager = transactionManager this.networkMonitor = networkMonitor this.tapCollector = tapCollector + this.graphTallyCollector = graphTallyCollector this.specification = specification this.paused = paused this.isOperator = isOperator @@ -312,6 +316,28 @@ export class Network { Tap Subgraph: ${!!tapSubgraph}.`) } + + // -------------------------------------------------------------------------------- + // * Graph Tally Collector + // -------------------------------------------------------------------------------- + let graphTallyCollector: GraphTallyCollector | undefined = undefined + if (contracts && networkSubgraph) { + graphTallyCollector = GraphTallyCollector.create({ + logger, + metrics, + transactionManager: transactionManager, + models: queryFeeModels, + contracts, + allocations, + networkSpecification: specification, + networkSubgraph, + }) + } else { + logger.info(`RAV v2 process not initiated. + Contracts: ${!!contracts}. + Subgraph: ${!!networkSubgraph}.`) + } + // -------------------------------------------------------------------------------- // * Network // -------------------------------------------------------------------------------- @@ -324,6 +350,7 @@ export class Network { transactionManager, networkMonitor, tapCollector, + graphTallyCollector, specification, paused, isOperator, From 30e368220259c7dfd015436c6868b8ffcac453ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Carranza=20V=C3=A9lez?= Date: Mon, 28 Jul 2025 13:34:26 -0300 Subject: [PATCH 25/28] fix: tests in the horizon branch (#1135) Co-authored-by: Claude --- packages/indexer-cli/jest.config.js | 1 - .../indexer-actions-get-first.stdout | 10 +- .../references/indexer-actions-get.stdout | 14 +- .../indexer-rules-invalid-set-arg.stdout | 5 +- packages/indexer-cli/src/__tests__/util.ts | 19 +- packages/indexer-common/package.json | 2 + .../src/allocations/graph-tally-collector.ts | 104 ++++--- .../allocations/horizon-escrow-accounts.ts | 17 +- .../src/indexer-management/allocations.ts | 260 ++++++++++-------- .../src/indexer-management/types.ts | 2 +- packages/indexer-common/src/network.ts | 1 - .../indexer-common/src/query-fees/models.ts | 39 +-- yarn.lock | 10 + 13 files changed, 285 insertions(+), 199 deletions(-) diff --git a/packages/indexer-cli/jest.config.js b/packages/indexer-cli/jest.config.js index d20b4b76f..0eeafcaef 100644 --- a/packages/indexer-cli/jest.config.js +++ b/packages/indexer-cli/jest.config.js @@ -13,7 +13,6 @@ module.exports = { // The glob patterns Jest uses to detect test files testMatch: ['**/?(*.)+(spec|test).ts?(x)'], testPathIgnorePatterns: ['/node_modules/', '/dist/', '.yalc'], - transformIgnorePatterns: ['!node_modules/'], testTimeout: 60000, globals: { __DATABASE__: { diff --git a/packages/indexer-cli/src/__tests__/references/indexer-actions-get-first.stdout b/packages/indexer-cli/src/__tests__/references/indexer-actions-get-first.stdout index 8a9613df1..dd32934db 100644 --- a/packages/indexer-cli/src/__tests__/references/indexer-actions-get-first.stdout +++ b/packages/indexer-cli/src/__tests__/references/indexer-actions-get-first.stdout @@ -1,5 +1,5 @@ -┌────┬──────────────────┬────────────┬────────────────────────────────────────────────┬──────────────┬────────┬──────┬───────┬──────────┬────────┬────────┬───────────────┬─────────────┬────────┐ -│ id │ protocolNetwork │ type │ deploymentID │ allocationID │ amount │ poi │ force │ priority │ status │ source │ failureReason │ transaction │ reason │ -├────┼──────────────────┼────────────┼────────────────────────────────────────────────┼──────────────┼────────┼──────┼───────┼──────────┼────────┼────────┼───────────────┼─────────────┼────────┤ -│ 2 │ arbitrum-sepolia │ unallocate │ QmSrf6VVPyg9NGdS1xhLmoosk3qZQaWhfoSTHE2H7sht6Q │ null │ null │ null │ null │ 0 │ failed │ test │ null │ null │ test │ -└────┴──────────────────┴────────────┴────────────────────────────────────────────────┴──────────────┴────────┴──────┴───────┴──────────┴────────┴────────┴───────────────┴─────────────┴────────┘ +┌────┬──────────────────┬────────────┬────────────────────────────────────────────────┬──────────────┬────────┬──────┬───────────┬────────────────┬───────┬──────────┬────────┬────────┬───────────────┬─────────────┬────────┬──────────┐ +│ id │ protocolNetwork │ type │ deploymentID │ allocationID │ amount │ poi │ publicPOI │ poiBlockNumber │ force │ priority │ status │ source │ failureReason │ transaction │ reason │ isLegacy │ +├────┼──────────────────┼────────────┼────────────────────────────────────────────────┼──────────────┼────────┼──────┼───────────┼────────────────┼───────┼──────────┼────────┼────────┼───────────────┼─────────────┼────────┼──────────┤ +│ 2 │ arbitrum-sepolia │ unallocate │ QmSrf6VVPyg9NGdS1xhLmoosk3qZQaWhfoSTHE2H7sht6Q │ null │ null │ null │ null │ null │ null │ 0 │ failed │ test │ null │ null │ test │ false │ +└────┴──────────────────┴────────────┴────────────────────────────────────────────────┴──────────────┴────────┴──────┴───────────┴────────────────┴───────┴──────────┴────────┴────────┴───────────────┴─────────────┴────────┴──────────┘ diff --git a/packages/indexer-cli/src/__tests__/references/indexer-actions-get.stdout b/packages/indexer-cli/src/__tests__/references/indexer-actions-get.stdout index 1d0ac63da..1055b1e43 100644 --- a/packages/indexer-cli/src/__tests__/references/indexer-actions-get.stdout +++ b/packages/indexer-cli/src/__tests__/references/indexer-actions-get.stdout @@ -1,7 +1,7 @@ -┌────┬──────────────────┬────────────┬────────────────────────────────────────────────┬──────────────┬────────┬──────┬───────┬──────────┬─────────┬────────┬───────────────┬─────────────┬────────┐ -│ id │ protocolNetwork │ type │ deploymentID │ allocationID │ amount │ poi │ force │ priority │ status │ source │ failureReason │ transaction │ reason │ -├────┼──────────────────┼────────────┼────────────────────────────────────────────────┼──────────────┼────────┼──────┼───────┼──────────┼─────────┼────────┼───────────────┼─────────────┼────────┤ -│ 2 │ arbitrum-sepolia │ unallocate │ QmSrf6VVPyg9NGdS1xhLmoosk3qZQaWhfoSTHE2H7sht6Q │ null │ null │ null │ null │ 0 │ failed │ test │ null │ null │ test │ -├────┼──────────────────┼────────────┼────────────────────────────────────────────────┼──────────────┼────────┼──────┼───────┼──────────┼─────────┼────────┼───────────────┼─────────────┼────────┤ -│ 1 │ arbitrum-sepolia │ allocate │ QmSrf6VVPyg9NGdS1xhLmoosk3qZQaWhfoSTHE2H7sht6Q │ null │ null │ null │ null │ 0 │ success │ test │ null │ null │ test │ -└────┴──────────────────┴────────────┴────────────────────────────────────────────────┴──────────────┴────────┴──────┴───────┴──────────┴─────────┴────────┴───────────────┴─────────────┴────────┘ +┌────┬──────────────────┬────────────┬────────────────────────────────────────────────┬──────────────┬────────┬──────┬───────────┬────────────────┬───────┬──────────┬─────────┬────────┬───────────────┬─────────────┬────────┬──────────┐ +│ id │ protocolNetwork │ type │ deploymentID │ allocationID │ amount │ poi │ publicPOI │ poiBlockNumber │ force │ priority │ status │ source │ failureReason │ transaction │ reason │ isLegacy │ +├────┼──────────────────┼────────────┼────────────────────────────────────────────────┼──────────────┼────────┼──────┼───────────┼────────────────┼───────┼──────────┼─────────┼────────┼───────────────┼─────────────┼────────┼──────────┤ +│ 2 │ arbitrum-sepolia │ unallocate │ QmSrf6VVPyg9NGdS1xhLmoosk3qZQaWhfoSTHE2H7sht6Q │ null │ null │ null │ null │ null │ null │ 0 │ failed │ test │ null │ null │ test │ false │ +├────┼──────────────────┼────────────┼────────────────────────────────────────────────┼──────────────┼────────┼──────┼───────────┼────────────────┼───────┼──────────┼─────────┼────────┼───────────────┼─────────────┼────────┼──────────┤ +│ 1 │ arbitrum-sepolia │ allocate │ QmSrf6VVPyg9NGdS1xhLmoosk3qZQaWhfoSTHE2H7sht6Q │ null │ null │ null │ null │ null │ null │ 0 │ success │ test │ null │ null │ test │ false │ +└────┴──────────────────┴────────────┴────────────────────────────────────────────────┴──────────────┴────────┴──────┴───────────┴────────────────┴───────┴──────────┴─────────┴────────┴───────────────┴─────────────┴────────┴──────────┘ diff --git a/packages/indexer-cli/src/__tests__/references/indexer-rules-invalid-set-arg.stdout b/packages/indexer-cli/src/__tests__/references/indexer-rules-invalid-set-arg.stdout index 332674874..50ffde39a 100644 --- a/packages/indexer-cli/src/__tests__/references/indexer-rules-invalid-set-arg.stdout +++ b/packages/indexer-cli/src/__tests__/references/indexer-rules-invalid-set-arg.stdout @@ -1,4 +1 @@ -Error: Indexing rule attribute 'allocationAmoewt' not supported, did you mean? -- allocationAmount -- allocationLifetime -- maxAllocationPercentage +Error: allocationAmoewt diff --git a/packages/indexer-cli/src/__tests__/util.ts b/packages/indexer-cli/src/__tests__/util.ts index bf702416a..41df97e13 100644 --- a/packages/indexer-cli/src/__tests__/util.ts +++ b/packages/indexer-cli/src/__tests__/util.ts @@ -5,7 +5,6 @@ import { Socket } from 'net' import { URL } from 'url' import path from 'path' import { Sequelize } from 'sequelize' -import stripAnsi from 'strip-ansi' import { ActionStatus, ActionType, @@ -56,6 +55,22 @@ let metrics: Metrics const yamlObj = loadTestYamlConfig() const testNetworkSpecification = specification.NetworkSpecification.parse(yamlObj) +// Replace strip-ansi with a simple function using the same regex pattern +// Based on ansi-regex v6.1.0 pattern +function stripAnsi(str: string): string { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string, got ${typeof str}`) + } + + // Regex pattern from ansi-regex + const pattern = [ + '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))', + '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))', + ].join('|') + + return str.replace(new RegExp(pattern, 'g'), '') +} + export const setupMultiNetworks = async () => { return await setup(true) } @@ -279,6 +294,7 @@ export const seedActions = async () => { source: 'test', reason: 'test', protocolNetwork: 'eip155:421614', + isLegacy: false, }) await models.Action.create({ id: 2, @@ -288,6 +304,7 @@ export const seedActions = async () => { source: 'test', reason: 'test', protocolNetwork: 'eip155:421614', + isLegacy: false, }) } catch (e) { logger.error('Failed to seed ', { error: e }) diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index 866db698b..5b50ff9e5 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -24,6 +24,8 @@ "dependencies": { "@pinax/graph-networks-registry": "0.6.7", "@graphprotocol/common-ts": "3.0.1", + "@graphprotocol/horizon": "0.4.1", + "@graphprotocol/subgraph-service": "0.4.1", "@graphprotocol/toolshed": "0.6.5", "@semiotic-labs/tap-contracts-bindings": "2.0.0", "@thi.ng/heaps": "1.2.38", diff --git a/packages/indexer-common/src/allocations/graph-tally-collector.ts b/packages/indexer-common/src/allocations/graph-tally-collector.ts index e502dfea6..1108b10a3 100644 --- a/packages/indexer-common/src/allocations/graph-tally-collector.ts +++ b/packages/indexer-common/src/allocations/graph-tally-collector.ts @@ -112,7 +112,7 @@ export class GraphTallyCollector { declare indexerAddress: Address // eslint-disable-next-line @typescript-eslint/no-empty-function -- Private constructor to prevent direct instantiation - private constructor() { } + private constructor() {} public static create({ logger, @@ -163,8 +163,8 @@ export class GraphTallyCollector { ravRedemptionThreshold: formatGRT(this.ravRedemptionThreshold), belowThresholdCount: signedRavs.belowThreshold.length, totalValueGRT, - allocations: signedRavs.belowThreshold.map( - (signedRav) => dataSlice(signedRav.rav.rav.collectionId, 12).toString(), + allocations: signedRavs.belowThreshold.map((signedRav) => + dataSlice(signedRav.rav.rav.collectionId, 12).toString(), ), }) } @@ -205,7 +205,9 @@ export class GraphTallyCollector { return { rav: signedRav, allocation: allocations.find( - (a) => a.id === toAddress(dataSlice(signedRav.rav.collectionId, 12).toString()), + (a) => + a.id === + toAddress(dataSlice(signedRav.rav.collectionId, 12).toString()), ), payer: rav.payer, } @@ -228,7 +230,7 @@ export class GraphTallyCollector { // eslint-disable-next-line @typescript-eslint/no-explicit-any const returnedAllocations: any[] = [] - for (; ;) { + for (;;) { const result = await this.networkSubgraph.query( gql` query allocations( @@ -301,15 +303,24 @@ export class GraphTallyCollector { private getSignedRAVsEventual( pendingRAVs: Eventual, ): Eventual { - return pendingRAVs.tryMap( async (pendingRAVs) => { - const escrowAccounts = await getEscrowAccounts(this.networkSubgraph, this.indexerAddress, this.contracts.GraphTallyCollector.target.toString()) + const escrowAccounts = await getEscrowAccounts( + this.networkSubgraph, + this.indexerAddress, + this.contracts.GraphTallyCollector.target.toString(), + ) return await pReduce( pendingRAVs, async (results, rav) => { - const tokensCollected = escrowAccounts.getTokensCollectedForReceiver(rav.payer, rav.rav.rav.collectionId) - if ((BigInt(rav.rav.rav.valueAggregate) - tokensCollected) < this.ravRedemptionThreshold) { + const tokensCollected = escrowAccounts.getTokensCollectedForReceiver( + rav.payer, + rav.rav.rav.collectionId, + ) + if ( + BigInt(rav.rav.rav.valueAggregate) - tokensCollected < + this.ravRedemptionThreshold + ) { results.belowThreshold.push(rav) } else { results.eligible.push(rav) @@ -416,14 +427,16 @@ export class GraphTallyCollector { const transactions: GraphTallyTransaction[] = [] const unfinalizedRavsAllocationIds = [ - ...new Set(ravs.map((value) => toAddress(value.collectionId.slice(12)).toLowerCase())), + ...new Set( + ravs.map((value) => toAddress(value.collectionId.slice(12)).toLowerCase()), + ), ] const payerAddresses = [ ...new Set(ravs.map((value) => toAddress(value.payer).toLowerCase())), ] - for (; ;) { + for (;;) { let block: { hash: string } | undefined = undefined if (meta?.block?.hash) { block = { @@ -510,17 +523,17 @@ export class GraphTallyCollector { UPDATE tap_horizon_ravs SET redeemed_at = NULL WHERE (collection_id::char(64), payer::char(40)) IN (VALUES ${ravsNotRedeemed - .map( - (rav) => - `('${rav.collectionId - .toString() - .toLowerCase() - .replace('0x', '')}'::char(64), '${rav.payer + .map( + (rav) => + `('${rav.collectionId + .toString() + .toLowerCase() + .replace('0x', '')}'::char(64), '${rav.payer .toString() .toLowerCase() .replace('0x', '')}'::char(40))`, - ) - .join(', ')}) + ) + .join(', ')}) AND redeemed_at < to_timestamp(${blockTimestampSecs}) ` @@ -558,17 +571,27 @@ export class GraphTallyCollector { signedRavs, }) - const escrowAccounts = await getEscrowAccounts(this.networkSubgraph, this.indexerAddress, this.contracts.GraphTallyCollector.target.toString()) + const escrowAccounts = await getEscrowAccounts( + this.networkSubgraph, + this.indexerAddress, + this.contracts.GraphTallyCollector.target.toString(), + ) // Redeem RAV one-by-one as no plual version available - const tokensCollectedPerAllocation: { allocationId: string, tokensCollected: bigint }[] = []; + const tokensCollectedPerAllocation: { + allocationId: string + tokensCollected: bigint + }[] = [] for (const { rav: signedRav, allocation, payer } of signedRavs) { const { rav } = signedRav // verify escrow balances const ravValue = BigInt(rav.valueAggregate.toString()) - const tokensAlreadyCollected = escrowAccounts.getTokensCollectedForReceiver(payer, rav.collectionId) + const tokensAlreadyCollected = escrowAccounts.getTokensCollectedForReceiver( + payer, + rav.collectionId, + ) const payerBalance = escrowAccounts.getBalanceForPayer(payer) // In horizon the RAV value is monotonically increasing. To calculate the actual outstanding amount we need to subtract the tokens already collected. @@ -597,7 +620,10 @@ export class GraphTallyCollector { if (!actualTokensCollected) { throw new Error(`Failed to redeem RAV v2: no tokens collected`) } - tokensCollectedPerAllocation.push({ allocationId: allocation.id, tokensCollected: actualTokensCollected }) + tokensCollectedPerAllocation.push({ + allocationId: allocation.id, + tokensCollected: actualTokensCollected, + }) escrowAccounts.updateBalances(payer, rav.collectionId, actualTokensCollected) } catch (err) { this.metrics.ravRedeemsFailed.inc({ collection: rav.collectionId }) @@ -650,7 +676,12 @@ export class GraphTallyCollector { // Submit the signed RAV on chain const txReceipt = await this.transactionManager.executeTransaction( - () => this.contracts.SubgraphService.collect.estimateGas(rav.serviceProvider, PaymentTypes.QueryFee, encodedData), + () => + this.contracts.SubgraphService.collect.estimateGas( + rav.serviceProvider, + PaymentTypes.QueryFee, + encodedData, + ), (gasLimit) => this.contracts.SubgraphService.collect(rav.serviceProvider, 0, encodedData, { gasLimit, @@ -668,14 +699,16 @@ export class GraphTallyCollector { const contractInterface = this.contracts.GraphTallyCollector.interface const event = contractInterface.getEvent('PaymentCollected') - const log = txReceipt.logs.find(log => log.topics[0] === event.topicHash); - if (!log) throw new Error('PaymentCollected event not found!'); + const log = txReceipt.logs.find((log) => log.topics[0] === event.topicHash) + if (!log) throw new Error('PaymentCollected event not found!') - const decoded = contractInterface.decodeEventLog(event, log.data, log.topics); + const decoded = contractInterface.decodeEventLog(event, log.data, log.topics) if (!decoded.tokens) { - throw new Error(`Actual value collected not found for collection ${rav.collectionId}`) + throw new Error( + `Actual value collected not found for collection ${rav.collectionId}`, + ) } - const actualTokensCollected = BigInt(decoded.tokens); + const actualTokensCollected = BigInt(decoded.tokens) this.metrics.ravCollectedFees.set( { collection: rav.collectionId }, @@ -696,7 +729,7 @@ export class GraphTallyCollector { ) } - return actualTokensCollected; + return actualTokensCollected } private async markRavAsRedeemed( @@ -710,13 +743,10 @@ export class GraphTallyCollector { UPDATE tap_horizon_ravs SET redeemed_at = ${timestamp ? `to_timestamp(${timestamp})` : 'NOW()'} WHERE collection_id = '${collectionId - .toString() - .toLowerCase() - .replace('0x', '')}' - AND payer = '${payer - .toString() - .toLowerCase() - .replace('0x', '')}' + .toString() + .toLowerCase() + .replace('0x', '')}' + AND payer = '${payer.toString().toLowerCase().replace('0x', '')}' ` await this.models.receiptAggregateVouchersV2.sequelize?.query(query) diff --git a/packages/indexer-common/src/allocations/horizon-escrow-accounts.ts b/packages/indexer-common/src/allocations/horizon-escrow-accounts.ts index 6607364a9..4a7216612 100644 --- a/packages/indexer-common/src/allocations/horizon-escrow-accounts.ts +++ b/packages/indexer-common/src/allocations/horizon-escrow-accounts.ts @@ -7,14 +7,14 @@ export type PaymentsEscrowAccountResponse = { payer: { id: string } - }[], + }[] // Not a typo just how graph-client pluralizes the field name graphTallyTokensCollecteds: { tokens: string collectionId: string payer: { id: string - }, + } }[] } @@ -22,7 +22,10 @@ export class PaymentsEscrowAccounts { private payersBalances: Map private receiversTokensCollected: Map - constructor(payersBalances: Map, receiversTokensCollected: Map) { + constructor( + payersBalances: Map, + receiversTokensCollected: Map, + ) { this.payersBalances = payersBalances this.receiversTokensCollected = receiversTokensCollected } @@ -38,7 +41,9 @@ export class PaymentsEscrowAccounts { getTokensCollectedForReceiver(payer: string, collectionId: string): bigint { const balance = this.receiversTokensCollected.get(`${payer}-${collectionId}`) if (balance === undefined) { - throw new Error(`No tokens collected found for payer: ${payer} and collectionId: ${collectionId}`) + throw new Error( + `No tokens collected found for payer: ${payer} and collectionId: ${collectionId}`, + ) } return balance } @@ -81,7 +86,9 @@ export const getEscrowAccounts = async ( const result = await subgraph.query( gql` query PaymentsEscrowAccountQuery($indexer: ID!, $collector: String!) { - paymentsEscrowAccounts(where: { receiver_: { id: $indexer }, collector: $collector }) { + paymentsEscrowAccounts( + where: { receiver_: { id: $indexer }, collector: $collector } + ) { balance payer { id diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index e85c04bfd..144f63b45 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -126,7 +126,7 @@ export class AllocationManager { private models: IndexerManagementModels, private graphNode: GraphNode, private network: Network, - ) { } + ) {} async executeBatch( actions: Action[], @@ -156,8 +156,11 @@ export class AllocationManager { await onFinishedDeploying(validatedActions) // Populated transaction result for each action - const populatedActionTransactionsResults = await this.prepareTransactions(validatedActions) - logger.trace('populatedActionTransactionsResults', { populatedActionTransactionsResults }) + const populatedActionTransactionsResults = + await this.prepareTransactions(validatedActions) + logger.trace('populatedActionTransactionsResults', { + populatedActionTransactionsResults, + }) // Flat list of valid prepared transactions const preparedTransactions: ActionTransactionRequest[] = [] @@ -183,16 +186,14 @@ export class AllocationManager { preparedTransactions: preparedTransactions, }) - // We need to process both staking contract and subgraph service transactions separately + // We need to process both staking contract and subgraph service transactions separately // as they cannot be multicalled // Realistically, the only scenario where a batch would have both is shortly after the horizon upgrade const stakingTransactions = preparedTransactions.filter( - (tx: TransactionRequest) => - tx.to === this.network.contracts.HorizonStaking.target, + (tx: TransactionRequest) => tx.to === this.network.contracts.HorizonStaking.target, ) const subgraphServiceTransactions = preparedTransactions.filter( - (tx: TransactionRequest) => - tx.to === this.network.contracts.SubgraphService.target, + (tx: TransactionRequest) => tx.to === this.network.contracts.SubgraphService.target, ) // -- STAKING CONTRACT -- @@ -209,20 +210,21 @@ export class AllocationManager { if (callDataStakingContract.length > 0) { try { - const stakingTransactionResult = await this.network.transactionManager.executeTransaction( - async () => - this.network.contracts.HorizonStaking.multicall.estimateGas( - callDataStakingContract, - ), - async (gasLimit) => - this.network.contracts.HorizonStaking.multicall(callDataStakingContract, { - gasLimit, + const stakingTransactionResult = + await this.network.transactionManager.executeTransaction( + async () => + this.network.contracts.HorizonStaking.multicall.estimateGas( + callDataStakingContract, + ), + async (gasLimit) => + this.network.contracts.HorizonStaking.multicall(callDataStakingContract, { + gasLimit, + }), + this.logger.child({ + actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, + function: 'staking.multicall', }), - this.logger.child({ - actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, - function: 'staking.multicall', - }), - ) + ) // Mark all actions with staking contract transactions as successful for (const transaction of stakingTransactions) { @@ -252,13 +254,17 @@ export class AllocationManager { // -- SUBGRAPH SERVICE -- const callDataSubgraphService = subgraphServiceTransactions - // Reallocate of a legacy allocation during the transition period can result in - // a staking and subgraph service transaction in the same batch. If the staking tx failed we + // Reallocate of a legacy allocation during the transition period can result in + // a staking and subgraph service transaction in the same batch. If the staking tx failed we // should not execute the subgraph service tx. .filter((tx: ActionTransactionRequest) => { - const actionStakingTransaction = actionResults - .find((result) => result.actionID === tx.actionID) - return actionStakingTransaction === undefined || actionStakingTransaction.success === true + const actionStakingTransaction = actionResults.find( + (result) => result.actionID === tx.actionID, + ) + return ( + actionStakingTransaction === undefined || + actionStakingTransaction.success === true + ) }) .filter((tx: TransactionRequest) => !!tx.data) .map((tx) => tx.data as string) @@ -271,20 +277,21 @@ export class AllocationManager { if (callDataSubgraphService.length > 0) { try { - const subgraphServiceTransactionResult = await this.network.transactionManager.executeTransaction( - async () => - this.network.contracts.SubgraphService.multicall.estimateGas( - callDataSubgraphService, - ), - async (gasLimit) => - this.network.contracts.SubgraphService.multicall(callDataSubgraphService, { - gasLimit, + const subgraphServiceTransactionResult = + await this.network.transactionManager.executeTransaction( + async () => + this.network.contracts.SubgraphService.multicall.estimateGas( + callDataSubgraphService, + ), + async (gasLimit) => + this.network.contracts.SubgraphService.multicall(callDataSubgraphService, { + gasLimit, + }), + this.logger.child({ + actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, + function: 'subgraphService.multicall', }), - this.logger.child({ - actions: `${JSON.stringify(validatedActions.map((action) => action.id))}`, - function: 'subgraphService.multicall', - }), - ) + ) // Mark all actions with subgraph service transactions as successful for (const transaction of subgraphServiceTransactions) { @@ -336,7 +343,6 @@ export class AllocationManager { return pMap( transactionResults, async (transactionResult: ExecuteTransactionResult) => { - const action = actions.find((action) => action.id === transactionResult.actionID) if (action === undefined) { this.logger.error('No action found for transaction result', { @@ -346,12 +352,21 @@ export class AllocationManager { } if (isActionFailure(transactionResult.result)) { - logger.debug('Execute batch transaction failed', { actionBatchResult: transactionResult, reason: transactionResult.result.failureReason }) + logger.debug('Execute batch transaction failed', { + actionBatchResult: transactionResult, + reason: transactionResult.result.failureReason, + }) return transactionResult.result } - if (transactionResult.result === "paused" || transactionResult.result === "unauthorized") { - logger.debug('Execute batch transaction failed', { actionBatchResult: transactionResult, reason: transactionResult.result }) + if ( + transactionResult.result === 'paused' || + transactionResult.result === 'unauthorized' + ) { + logger.debug('Execute batch transaction failed', { + actionBatchResult: transactionResult, + reason: transactionResult.result, + }) return { actionID: transactionResult.actionID, transactionID: undefined, @@ -654,17 +669,17 @@ export class AllocationManager { const proof = isHorizon ? await horizonAllocationIdProof( - allocationSigner, - Number(this.network.specification.networkIdentifier.split(':')[1]), - this.network.specification.indexerOptions.address, - allocationId, - this.network.contracts.SubgraphService.target.toString(), - ) + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + allocationId, + this.network.contracts.SubgraphService.target.toString(), + ) : await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - allocationId, - ) + allocationSigner, + this.network.specification.indexerOptions.address, + allocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, @@ -698,28 +713,29 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE062, - `Allocation not created. ${receipt === 'paused' ? 'Network paused' : 'Operator not authorized' + `Allocation not created. ${ + receipt === 'paused' ? 'Network paused' : 'Operator not authorized' }`, ) } const createAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.LegacyStaking.interface, - 'subgraphDeploymentID', - subgraphDeployment.bytes32, - receipt, - this.logger, - ) + 'AllocationCreated', + this.network.contracts.LegacyStaking.interface, + 'subgraphDeploymentID', + subgraphDeployment.bytes32, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'AllocationCreated', - this.network.contracts.SubgraphService.interface, - 'indexer', - this.network.specification.indexerOptions.address, - receipt, - logger, - ) + 'AllocationCreated', + this.network.contracts.SubgraphService.interface, + 'indexer', + this.network.specification.indexerOptions.address, + receipt, + logger, + ) if (!createAllocationEventLogs) { throw indexerError(IndexerErrorCode.IE014, `Allocation was never mined`) @@ -894,21 +910,21 @@ export class AllocationManager { const closeAllocationEventLogs = isLegacy ? this.network.transactionManager.findEvent( - 'AllocationClosed', - this.network.contracts.LegacyStaking.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) + 'AllocationClosed', + this.network.contracts.LegacyStaking.interface, + 'allocationID', + allocationID, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'AllocationClosed', - this.network.contracts.SubgraphService.interface, - 'allocationId', - allocationID, - receipt, - this.logger, - ) + 'AllocationClosed', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) if (!closeAllocationEventLogs) { throw indexerError( @@ -919,21 +935,21 @@ export class AllocationManager { const rewardsEventLogs = isLegacy ? this.network.transactionManager.findEvent( - isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', - this.network.contracts.RewardsManager.interface, - 'allocationID', - allocationID, - receipt, - this.logger, - ) + isHorizon ? 'HorizonRewardsAssigned' : 'RewardsAssigned', + this.network.contracts.RewardsManager.interface, + 'allocationID', + allocationID, + receipt, + this.logger, + ) : this.network.transactionManager.findEvent( - 'IndexingRewardsCollected', - this.network.contracts.SubgraphService.interface, - 'allocationId', - allocationID, - receipt, - this.logger, - ) + 'IndexingRewardsCollected', + this.network.contracts.SubgraphService.interface, + 'allocationId', + allocationID, + receipt, + this.logger, + ) const rewardsAssigned = rewardsEventLogs ? isLegacy @@ -999,10 +1015,11 @@ export class AllocationManager { }) if (params.isLegacy) { - const tx = await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( - params.allocationID, - params.poi.poi, - ) + const tx = + await this.network.contracts.HorizonStaking.closeAllocation.populateTransaction( + params.allocationID, + params.poi.poi, + ) return { protocolNetwork: params.protocolNetwork, actionID: params.actionID, @@ -1037,10 +1054,11 @@ export class AllocationManager { [params.indexer, encodeStopServiceData(params.allocationID)], ) - const tx = await this.network.contracts.SubgraphService.multicall.populateTransaction([ - collectCallData, - stopServiceCallData, - ]) + const tx = + await this.network.contracts.SubgraphService.multicall.populateTransaction([ + collectCallData, + stopServiceCallData, + ]) return { protocolNetwork: params.protocolNetwork, actionID: params.actionID, @@ -1216,17 +1234,17 @@ export class AllocationManager { }) const proof = isHorizon ? await horizonAllocationIdProof( - allocationSigner, - Number(this.network.specification.networkIdentifier.split(':')[1]), - this.network.specification.indexerOptions.address, - newAllocationId, - this.network.contracts.SubgraphService.target.toString(), - ) + allocationSigner, + Number(this.network.specification.networkIdentifier.split(':')[1]), + this.network.specification.indexerOptions.address, + newAllocationId, + this.network.contracts.SubgraphService.target.toString(), + ) : await legacyAllocationIdProof( - allocationSigner, - this.network.specification.indexerOptions.address, - newAllocationId, - ) + allocationSigner, + this.network.specification.indexerOptions.address, + newAllocationId, + ) logger.debug('Successfully generated allocation ID proof', { allocationIDProof: proof, @@ -1625,9 +1643,9 @@ export class AllocationManager { action.poi === zeroHexString ? 0n : await this.network.contracts.RewardsManager.getRewards( - this.network.contracts.HorizonStaking.target, - action.allocationID, - ) + this.network.contracts.HorizonStaking.target, + action.allocationID, + ) unallocates = unallocates + allocation.allocatedTokens } @@ -1687,10 +1705,10 @@ export class AllocationManager { throw indexerError( IndexerErrorCode.IE013, `Unfeasible action batch: Approved action batch GRT balance is ` + - `${formatGRT(batchDelta)} for horizon actions and ` + - `${formatGRT(batchDeltaLegacy)} for legacy actions ` + - `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + - `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, + `${formatGRT(batchDelta)} for horizon actions and ` + + `${formatGRT(batchDeltaLegacy)} for legacy actions ` + + `but available horizon stake equals ${formatGRT(indexerFreeStake.horizon)} ` + + `and legacy stake equals ${formatGRT(indexerFreeStake.legacy)}.`, ) } } diff --git a/packages/indexer-common/src/indexer-management/types.ts b/packages/indexer-common/src/indexer-management/types.ts index 677c7ec81..05a9d3f6e 100644 --- a/packages/indexer-common/src/indexer-management/types.ts +++ b/packages/indexer-common/src/indexer-management/types.ts @@ -57,7 +57,7 @@ export interface ActionExecutionResult { export interface ExecuteTransactionResult { actionID: number success: boolean - result: ActionFailure | TransactionReceipt | "paused" | "unauthorized" + result: ActionFailure | TransactionReceipt | 'paused' | 'unauthorized' } export interface ActionFailure { diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index d8a94e97e..84689e513 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -316,7 +316,6 @@ export class Network { Tap Subgraph: ${!!tapSubgraph}.`) } - // -------------------------------------------------------------------------------- // * Graph Tally Collector // -------------------------------------------------------------------------------- diff --git a/packages/indexer-common/src/query-fees/models.ts b/packages/indexer-common/src/query-fees/models.ts index 5de5a0d4f..78570cb95 100644 --- a/packages/indexer-common/src/query-fees/models.ts +++ b/packages/indexer-common/src/query-fees/models.ts @@ -17,7 +17,8 @@ export interface ScalarTapReceiptsAttributes { } export class ScalarTapReceipts extends Model - implements ScalarTapReceiptsAttributes { + implements ScalarTapReceiptsAttributes +{ public id!: number public allocation_id!: Address public signer_address!: Address @@ -47,7 +48,8 @@ export interface TapHorizonReceiptsAttributes { } export class TapHorizonReceipts extends Model - implements TapHorizonReceiptsAttributes { + implements TapHorizonReceiptsAttributes +{ public id!: number public signer_address!: Address @@ -66,7 +68,8 @@ export class TapHorizonReceipts export class ScalarTapReceiptsInvalid extends Model - implements ScalarTapReceiptsAttributes { + implements ScalarTapReceiptsAttributes +{ public id!: number public allocation_id!: Address public signer_address!: Address @@ -82,7 +85,8 @@ export class ScalarTapReceiptsInvalid export class TapHorizonReceiptsInvalid extends Model - implements TapHorizonReceiptsAttributes { + implements TapHorizonReceiptsAttributes +{ public id!: number public signer_address!: Address @@ -111,7 +115,8 @@ export interface AllocationReceiptAttributes { export class AllocationReceipt extends Model - implements AllocationReceiptAttributes { + implements AllocationReceiptAttributes +{ public id!: string public allocation!: Address public fees!: string @@ -165,7 +170,7 @@ export interface ReceiptAggregateVoucherV2Attributes { timestampNs: bigint valueAggregate: bigint metadata: string - + last: boolean final: boolean redeemedAt: Date | null @@ -179,7 +184,6 @@ export interface FailedReceiptAggregateVoucherAttributes { reason: string } - export interface FailedReceiptAggregateVoucherV2Attributes { collectionId: string payer: string @@ -192,7 +196,8 @@ export interface FailedReceiptAggregateVoucherV2Attributes { export class ReceiptAggregateVoucher extends Model - implements ReceiptAggregateVoucherAttributes { + implements ReceiptAggregateVoucherAttributes +{ public allocationId!: Address public senderAddress!: Address public signature!: Uint8Array @@ -231,7 +236,8 @@ export type SignedRAVv2 = { export class ReceiptAggregateVoucherV2 extends Model - implements ReceiptAggregateVoucherV2Attributes { + implements ReceiptAggregateVoucherV2Attributes +{ public signature!: Uint8Array public collectionId!: string public payer!: Address @@ -274,7 +280,8 @@ export type SignedRAV = TAPVerifier.SignedRAVStruct export class FailedReceiptAggregateVoucher extends Model - implements FailedReceiptAggregateVoucherAttributes { + implements FailedReceiptAggregateVoucherAttributes +{ public allocationId!: Address public senderAddress!: Address public expectedRav!: JSON @@ -282,10 +289,10 @@ export class FailedReceiptAggregateVoucher public reason!: string } - export class FailedReceiptAggregateVoucherV2 extends Model - implements FailedReceiptAggregateVoucherV2Attributes { + implements FailedReceiptAggregateVoucherV2Attributes +{ public collectionId!: string public payer!: Address public dataService!: Address @@ -305,7 +312,8 @@ export interface TransferReceiptAttributes { export class TransferReceipt extends Model - implements TransferReceiptAttributes { + implements TransferReceiptAttributes +{ public id!: number public signer!: Address public fees!: string @@ -370,7 +378,8 @@ export interface AllocationSummaryAttributes { export class AllocationSummary extends Model - implements AllocationSummaryAttributes { + implements AllocationSummaryAttributes +{ public allocation!: Address public closedAt!: Date public createdTransfers!: number @@ -832,7 +841,6 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { }, ) - FailedReceiptAggregateVoucherV2.init( { collectionId: { @@ -1044,7 +1052,6 @@ export function defineQueryFeeModels(sequelize: Sequelize): QueryFeeModels { }, ) - TapHorizonReceiptsInvalid.init( { id: { diff --git a/yarn.lock b/yarn.lock index 439fb1dab..d5d4f7c57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -568,6 +568,11 @@ prom-client "14.2.0" sequelize "6.33.0" +"@graphprotocol/horizon@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@graphprotocol/horizon/-/horizon-0.4.1.tgz#b29f0944eeb9d4b50fc586e533904b9e51f18ade" + integrity sha512-YC/HVmWuCkfembwVQbPEY9NEDNsPsuHxnBMCThB1nAyai9I0Ad/nKnHZ+9baFmq5Sg1YwXxDG7Nc4SQJlgZD2g== + "@graphprotocol/interfaces@^0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@graphprotocol/interfaces/-/interfaces-0.2.5.tgz#b628b198f4f2c6118d6acbf29f70c2de3ba61211" @@ -583,6 +588,11 @@ split2 "^3.1.1" through2 "^3.0.1" +"@graphprotocol/subgraph-service@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.4.1.tgz#31a76c10031aa118960a1fa0d7ba955cac123f32" + integrity sha512-vJA9lzlNQr4IRDPAbUiXM1ybizB4GzI0B1bndvB2X00ecTOWQQCiDl0W/qlApQ86+YXMjU2g90Db23ldqVOvyQ== + "@graphprotocol/toolshed@0.6.5": version "0.6.5" resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.6.5.tgz#42fd39d1a5b9a41002c81feaecfa574f9e2dbe46" From 5a5188869c39845048d53b71937026bd66a5606d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 5 Aug 2025 13:57:36 -0300 Subject: [PATCH 26/28] core: replace horizon and subgraph dependency with address book MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-common/package.json | 3 ++- packages/indexer-common/src/network.ts | 8 +++++++- yarn.lock | 24 +++++++++++++++--------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index 5b50ff9e5..e0ff32aaf 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -23,10 +23,11 @@ }, "dependencies": { "@pinax/graph-networks-registry": "0.6.7", + "@graphprotocol/address-book": "0.1.0", "@graphprotocol/common-ts": "3.0.1", "@graphprotocol/horizon": "0.4.1", "@graphprotocol/subgraph-service": "0.4.1", - "@graphprotocol/toolshed": "0.6.5", + "@graphprotocol/toolshed": "0.6.11", "@semiotic-labs/tap-contracts-bindings": "2.0.0", "@thi.ng/heaps": "1.2.38", "@types/lodash.clonedeep": "^4.5.7", diff --git a/packages/indexer-common/src/network.ts b/packages/indexer-common/src/network.ts index 84689e513..7a27eeba1 100644 --- a/packages/indexer-common/src/network.ts +++ b/packages/indexer-common/src/network.ts @@ -785,7 +785,13 @@ async function connectToProtocolContracts( } catch (error) { const errorMessage = 'Failed to connect to contracts, please ensure you are using the intended protocol network.' - logger.error(errorMessage, { error, networkIdentifier, numericNetworkId }) + logger.error(errorMessage, { + error, + networkIdentifier, + numericNetworkId, + horizonAddressBook, + subgraphServiceAddressBook, + }) throw new Error(`${errorMessage} Error: ${error}`) } diff --git a/yarn.lock b/yarn.lock index d5d4f7c57..444a456fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -542,6 +542,11 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@graphprotocol/address-book@0.1.0", "@graphprotocol/address-book@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@graphprotocol/address-book/-/address-book-0.1.0.tgz#96cf1e8fc506797adc85d582e5246320b83a8232" + integrity sha512-QHtpxitV7YCjq8mXx6ruvbSKcwDNiWBFFRJKgAlTCJgebFdfxmovr1GzV8biFB1587gfYmfL8OEU9pafZq3n+g== + "@graphprotocol/common-ts@3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@graphprotocol/common-ts/-/common-ts-3.0.1.tgz#c20428a5c2c7cf8f6631fea9fc304e203b0e7483" @@ -573,10 +578,10 @@ resolved "https://registry.yarnpkg.com/@graphprotocol/horizon/-/horizon-0.4.1.tgz#b29f0944eeb9d4b50fc586e533904b9e51f18ade" integrity sha512-YC/HVmWuCkfembwVQbPEY9NEDNsPsuHxnBMCThB1nAyai9I0Ad/nKnHZ+9baFmq5Sg1YwXxDG7Nc4SQJlgZD2g== -"@graphprotocol/interfaces@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@graphprotocol/interfaces/-/interfaces-0.2.5.tgz#b628b198f4f2c6118d6acbf29f70c2de3ba61211" - integrity sha512-z2Worw4OzMs9aDup8MkkoNk/QmJFKhPIfQrYnbu0FKImyi72z1JVQXfaH8ypH3QO4/Lpc3PrK81cJFxqdWNExQ== +"@graphprotocol/interfaces@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@graphprotocol/interfaces/-/interfaces-0.5.2.tgz#61532bb7bda90aca92a944cd9d1c9aaffbfb53b9" + integrity sha512-dW7odjioGFEO4gFE/vpFVSbwxz+HOtA4OrmnRgAiu7f1uQvjv8FAKuDZNeWR4MkIYHqbEPa4QGj9NtIm4TzLaw== "@graphprotocol/pino-sentry-simple@0.7.1": version "0.7.1" @@ -593,12 +598,13 @@ resolved "https://registry.yarnpkg.com/@graphprotocol/subgraph-service/-/subgraph-service-0.4.1.tgz#31a76c10031aa118960a1fa0d7ba955cac123f32" integrity sha512-vJA9lzlNQr4IRDPAbUiXM1ybizB4GzI0B1bndvB2X00ecTOWQQCiDl0W/qlApQ86+YXMjU2g90Db23ldqVOvyQ== -"@graphprotocol/toolshed@0.6.5": - version "0.6.5" - resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.6.5.tgz#42fd39d1a5b9a41002c81feaecfa574f9e2dbe46" - integrity sha512-yVyFX2rVYzgUUUcuyLCctItNXEQFeNYi739/kZupf3I/FHevaFpIvB4ZFn/Kg9SAi7556Vv3JfAPO6jkJ/xypg== +"@graphprotocol/toolshed@0.6.11": + version "0.6.11" + resolved "https://registry.yarnpkg.com/@graphprotocol/toolshed/-/toolshed-0.6.11.tgz#7f0d2986fd6a7ca59145d18fa6d1f228cd231a16" + integrity sha512-J9fuR9k3Bh63mGqyfI314rlrOE5YL+LcuqMpx0UoRPWDEymGMipZ4jzzRuThWe2gGWJ4o1jk5JCnIv/eKDNUMw== dependencies: - "@graphprotocol/interfaces" "^0.2.5" + "@graphprotocol/address-book" "^0.1.0" + "@graphprotocol/interfaces" "^0.5.2" "@nomicfoundation/hardhat-ethers" "3.0.8" debug "^4.4.0" ethers "6.13.7" From ce2184585eb36687f6facbb1a84cec5142080db5 Mon Sep 17 00:00:00 2001 From: Maikol <86025070+Maikol@users.noreply.github.com> Date: Fri, 15 Aug 2025 09:50:50 -0300 Subject: [PATCH 27/28] fix: ensure allocation keys derive from root wallet (#1136) --- packages/indexer-common/src/allocations/keys.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/indexer-common/src/allocations/keys.ts b/packages/indexer-common/src/allocations/keys.ts index da11921c8..e3dcc7d1b 100644 --- a/packages/indexer-common/src/allocations/keys.ts +++ b/packages/indexer-common/src/allocations/keys.ts @@ -1,4 +1,11 @@ -import { Wallet, Signer, HDNodeWallet, solidityPackedKeccak256, getBytes } from 'ethers' +import { + Wallet, + Signer, + HDNodeWallet, + solidityPackedKeccak256, + getBytes, + Mnemonic, +} from 'ethers' import { Address, SubgraphDeploymentID, toAddress } from '@graphprotocol/common-ts' import { Allocation } from './types' @@ -8,7 +15,7 @@ const deriveKeyPair = ( deployment: SubgraphDeploymentID, index: number, ): { publicKey: string; privateKey: string; address: Address } => { - const path = [epoch, ...Buffer.from(deployment.ipfsHash), index].join('/') + const path = 'm/' + [epoch, ...Buffer.from(deployment.ipfsHash), index].join('/') const derivedKey = hdNode.derivePath(path) return { publicKey: derivedKey.publicKey, @@ -22,7 +29,7 @@ export const allocationSignerPrivateKey = ( wallet: HDNodeWallet, allocation: Allocation, ): string => { - const hdNode = HDNodeWallet.fromPhrase(wallet.mnemonic!.phrase) + const hdNode = HDNodeWallet.fromMnemonic(wallet.mnemonic!, 'm') // The allocation was either created at the epoch it intended to or one // epoch later. So try both both. @@ -69,7 +76,8 @@ export const uniqueAllocationID = ( existingIDs: Address[], ): { allocationSigner: Signer; allocationId: Address } => { for (let i = 0; i < 100; i++) { - const hdNode = HDNodeWallet.fromPhrase(indexerMnemonic) + const mnemonicObj = Mnemonic.fromPhrase(indexerMnemonic) + const hdNode = HDNodeWallet.fromMnemonic(mnemonicObj, 'm') const keyPair = deriveKeyPair(hdNode, epoch, deployment, i) if (!existingIDs.includes(keyPair.address)) { return { From dd9cd0678cda3b195a1dffed092e34421c793567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 19 Aug 2025 17:54:14 -0300 Subject: [PATCH 28/28] chore: lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- packages/indexer-common/src/indexer-management/allocations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/indexer-common/src/indexer-management/allocations.ts b/packages/indexer-common/src/indexer-management/allocations.ts index 1e0259977..144f63b45 100644 --- a/packages/indexer-common/src/indexer-management/allocations.ts +++ b/packages/indexer-common/src/indexer-management/allocations.ts @@ -1722,4 +1722,4 @@ export class AllocationManager { ) .map((a: ActionStakeUsageSummary) => a.action) } -} \ No newline at end of file +}