From 22417784dfe70d920006e445a1788ffd7d28c027 Mon Sep 17 00:00:00 2001 From: Saihajpreet Singh Date: Tue, 13 Feb 2024 12:34:08 -0500 Subject: [PATCH 1/4] common: introduce protocolNetwork field on CostModel --- packages/indexer-cli/src/cost.ts | 5 ++++ .../indexer-management/models/cost-model.ts | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/packages/indexer-cli/src/cost.ts b/packages/indexer-cli/src/cost.ts index af2fc51d8..d3cc8487d 100644 --- a/packages/indexer-cli/src/cost.ts +++ b/packages/indexer-cli/src/cost.ts @@ -3,6 +3,7 @@ import { CostModelAttributes, GraphQLCostModel, IndexerManagementClient, + validateNetworkIdentifier, } from '@graphprotocol/indexer-common' import gql from 'graphql-tag' import yaml from 'yaml' @@ -30,6 +31,7 @@ const COST_MODEL_PARSERS: Record any> = deployment: parseDeploymentID, model: x => x, variables: nullPassThrough(JSON.parse), + protocolNetwork: x => validateNetworkIdentifier(x), } const COST_MODEL_FORMATTERS: Record< @@ -40,6 +42,7 @@ const COST_MODEL_FORMATTERS: Record< deployment: (d: SubgraphDeploymentIDIsh) => (typeof d === 'string' ? d : d.ipfsHash), model: x => x, variables: nullPassThrough(s => JSON.stringify(s, null, 2)), + protocolNetwork: x => validateNetworkIdentifier(x), } const COST_MODEL_CONVERTERS_FROM_GRAPHQL: Record< @@ -51,6 +54,7 @@ const COST_MODEL_CONVERTERS_FROM_GRAPHQL: Record< deployment: parseDeploymentID, model: x => x, variables: nullPassThrough(JSON.parse), + protocolNetwork: x => validateNetworkIdentifier(x), } const COST_MODEL_CONVERTERS_TO_GRAPHQL: Record< @@ -62,6 +66,7 @@ const COST_MODEL_CONVERTERS_TO_GRAPHQL: Record< deployment: (x: SubgraphDeploymentIDIsh) => x.toString(), model: x => x, variables: nullPassThrough(JSON.stringify), + protocolNetwork: x => validateNetworkIdentifier(x), } /** 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 65cb27bb4..98b73b485 100644 --- a/packages/indexer-common/src/indexer-management/models/cost-model.ts +++ b/packages/indexer-common/src/indexer-management/models/cost-model.ts @@ -2,11 +2,13 @@ import { Optional, Model, DataTypes, Sequelize } from 'sequelize' import { utils } from 'ethers' +import { validateNetworkIdentifier } from '../../parsers/validators' export interface GraphQLCostModel { deployment: string model: string | null | undefined variables: string | null | undefined + protocolNetwork: string } export const parseGraphQLCostModel = ( @@ -21,6 +23,7 @@ export const parseGraphQLCostModel = ( deployment: costModel.deployment, model: costModel.model || null, variables: variables, + protocolNetwork: costModel.protocolNetwork, } } catch (error) { throw new Error(`Failed to parse GraphQL cost model: ${error}`) @@ -37,6 +40,7 @@ export interface CostModelAttributes { deployment: string model: string | null variables: CostModelVariables | null + protocolNetwork: string } export interface CostModelCreationAttributes @@ -50,6 +54,7 @@ export class CostModel public deployment!: string public model!: string | null public variables!: CostModelVariables | null + public protocolNetwork!: string public createdAt!: Date public updatedAt!: Date @@ -99,6 +104,24 @@ export const defineCostModelModels = (sequelize: Sequelize): CostModelModels => }, }, }, + protocolNetwork: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isProtocolNetwork: (value: string) => { + if (typeof value !== 'string') { + throw new Error('Protocol network must be a string') + } + + // must be `eip155:` + if (validateNetworkIdentifier(value)) { + return + } + + throw new Error(`Protocol network must be a valid 'eip155' network`) + }, + }, + }, model: { type: DataTypes.TEXT, allowNull: true, From e7f1b1bab674cb5248597ff753e0e81bd7c665f5 Mon Sep 17 00:00:00 2001 From: Saihajpreet Singh Date: Tue, 13 Feb 2024 13:01:02 -0500 Subject: [PATCH 2/4] *: add format script to workspace --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 331625e6a..ed4b44517 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "scripts": { "bootstrap": "lerna bootstrap", "prepare": "lerna run prepare", + "format": "lerna run format", "release": "./scripts/release.sh", "test": "lerna --concurrency 1 run test --stream --ignore @graphprotocol/indexer-service", "test:ci": "lerna --concurrency 1 run test:ci --stream --ignore @graphprotocol/indexer-service", From 78c47e8f571933e8589705818228dee0c281b6f6 Mon Sep 17 00:00:00 2001 From: Saihajpreet Singh Date: Tue, 13 Feb 2024 14:35:38 -0500 Subject: [PATCH 3/4] cli, common, service: include protocol network for cost model creation --- .../src/commands/indexer/cost/set/model.ts | 12 ++++++++++-- packages/indexer-cli/src/cost.ts | 4 ++++ .../src/indexer-management/client.ts | 2 ++ .../src/indexer-management/models/cost-model.ts | 15 ++------------- packages/indexer-service/src/server/cost.ts | 3 +++ 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/indexer-cli/src/commands/indexer/cost/set/model.ts b/packages/indexer-cli/src/commands/indexer/cost/set/model.ts index e8ac4e506..f07c7a490 100644 --- a/packages/indexer-cli/src/commands/indexer/cost/set/model.ts +++ b/packages/indexer-cli/src/commands/indexer/cost/set/model.ts @@ -4,7 +4,7 @@ import fs from 'fs' import { loadValidatedConfig } from '../../../../config' import { createIndexerManagementClient } from '../../../../client' -import { fixParameters } from '../../../../command-helpers' +import { extractProtocolNetworkOption, fixParameters } from '../../../../command-helpers' import { parseCostModel, parseDeploymentID, @@ -18,7 +18,7 @@ ${chalk.bold('graph indexer cost set model')} [options] ${chalk.bold('graph indexer cost set model')} [options] global ${chalk.dim('Options:')} - + -n, --network Protocol network -h, --help Show usage information -o, --output table|json|yaml Choose the output format: table (default), JSON, or YAML ` @@ -31,6 +31,13 @@ module.exports = { const { print, parameters } = toolbox const { h, help, merged, o, output } = parameters.options + + const protocolNetwork = extractProtocolNetworkOption(parameters.options, true) + + if (!protocolNetwork) { + throw new Error('Protocol network is required') + } + const [deployment, filename] = fixParameters(parameters, { h, help, merged }) || [] const outputFormat = o || output || 'table' @@ -69,6 +76,7 @@ module.exports = { deployment, model, variables: null, + protocolNetwork, }) try { diff --git a/packages/indexer-cli/src/cost.ts b/packages/indexer-cli/src/cost.ts index d3cc8487d..9ae890f82 100644 --- a/packages/indexer-cli/src/cost.ts +++ b/packages/indexer-cli/src/cost.ts @@ -204,6 +204,7 @@ export const costModels = async ( deployment model variables + protocolNetwork } } `) @@ -228,6 +229,7 @@ export const costModel = async ( deployment model variables + protocolNetwork } } `, @@ -258,6 +260,7 @@ export const setCostModel = async ( deployment model variables + protocolNetwork } } `, @@ -284,6 +287,7 @@ export const deleteCostModels = async ( deployment model variables + protocolNetwork } } `, diff --git a/packages/indexer-common/src/indexer-management/client.ts b/packages/indexer-common/src/indexer-management/client.ts index 648dea8cc..3f33f4009 100644 --- a/packages/indexer-common/src/indexer-management/client.ts +++ b/packages/indexer-common/src/indexer-management/client.ts @@ -360,12 +360,14 @@ const SCHEMA_SDL = gql` deployment: String! model: String variables: String + protocolNetwork: String! } input CostModelInput { deployment: String! model: String variables: String + protocolNetwork: String! } type Query { 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 98b73b485..0a374891f 100644 --- a/packages/indexer-common/src/indexer-management/models/cost-model.ts +++ b/packages/indexer-common/src/indexer-management/models/cost-model.ts @@ -2,7 +2,7 @@ import { Optional, Model, DataTypes, Sequelize } from 'sequelize' import { utils } from 'ethers' -import { validateNetworkIdentifier } from '../../parsers/validators' +import { caip2IdRegex } from '../../parsers/validators' export interface GraphQLCostModel { deployment: string @@ -108,18 +108,7 @@ export const defineCostModelModels = (sequelize: Sequelize): CostModelModels => type: DataTypes.STRING, allowNull: false, validate: { - isProtocolNetwork: (value: string) => { - if (typeof value !== 'string') { - throw new Error('Protocol network must be a string') - } - - // must be `eip155:` - if (validateNetworkIdentifier(value)) { - return - } - - throw new Error(`Protocol network must be a valid 'eip155' network`) - }, + is: caip2IdRegex, }, }, model: { diff --git a/packages/indexer-service/src/server/cost.ts b/packages/indexer-service/src/server/cost.ts index 1b288733c..0b8602a8e 100644 --- a/packages/indexer-service/src/server/cost.ts +++ b/packages/indexer-service/src/server/cost.ts @@ -94,6 +94,7 @@ export const createCostServer = async ({ deployment: String! model: String variables: String + protocolNetwork: String! } type Query { @@ -126,6 +127,7 @@ export const createCostServer = async ({ deployment model variables + protocolNetwork } } `, @@ -172,6 +174,7 @@ export const createCostServer = async ({ deployment model variables + protocolNetwork } } `, From 313906dd123925b50af4ebce699f42eeeee78387 Mon Sep 17 00:00:00 2001 From: Saihajpreet Singh Date: Mon, 19 Feb 2024 10:19:06 -0500 Subject: [PATCH 4/4] agent: protocol network migration for cost model --- ...2-add-protocol-network-field-cost-model.ts | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 packages/indexer-agent/src/db/migrations/12-add-protocol-network-field-cost-model.ts diff --git a/packages/indexer-agent/src/db/migrations/12-add-protocol-network-field-cost-model.ts b/packages/indexer-agent/src/db/migrations/12-add-protocol-network-field-cost-model.ts new file mode 100644 index 000000000..ec0ff924d --- /dev/null +++ b/packages/indexer-agent/src/db/migrations/12-add-protocol-network-field-cost-model.ts @@ -0,0 +1,61 @@ +import { Logger } from '@graphprotocol/common-ts' +import { caip2IdRegex } from '@graphprotocol/indexer-common' +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 'CostModel' table exists`) + const tables = await queryInterface.showAllTables() + if (!tables.includes('CostModel')) { + logger.info(`Indexing rules table does not exist, migration not necessary`) + return + } + + logger.debug(`Checking if 'CostModel' table needs to be migrated`) + const table = await queryInterface.describeTable('CostModel') + const protocolNetwork = table.protocolNetwork + if (protocolNetwork) { + logger.info( + `'protocolNetwork' column already exist, migration not necessary`, + ) + return + } + + logger.info(`Add 'protocolNetwork' column to 'CostModel' table`) + await queryInterface.addColumn('CostModel', 'protocolNetwork', { + type: DataTypes.STRING, + allowNull: false, + validate: { + is: caip2IdRegex, + }, + }) +} + +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('CostModel')) { + logger.info(`Remove 'protocolNetwork' column`) + await context.queryInterface.removeColumn( + 'CostModel', + 'protocolNetwork', + { + transaction, + }, + ) + } + }) +}