From d53fbcf7318b98662f0929289fcfa9a1d6cdeb27 Mon Sep 17 00:00:00 2001 From: prathamesh0 <42446521+prathamesh0@users.noreply.github.com> Date: Thu, 1 Aug 2024 19:01:54 +0530 Subject: [PATCH] Add support for args on nested GQL query selections in subgraph watchers (#530) * Add support for arguments on nested GQL query selections * Update package versions --- lerna.json | 2 +- packages/cache/package.json | 2 +- packages/cli/package.json | 12 ++-- packages/codegen/package.json | 4 +- .../src/templates/package-template.handlebars | 10 ++-- packages/graph-node/package.json | 10 ++-- packages/ipld-eth-client/package.json | 6 +- packages/peer/package.json | 2 +- packages/rpc-eth-client/package.json | 8 +-- packages/solidity-mapper/package.json | 2 +- packages/test/package.json | 2 +- packages/tracing-client/package.json | 2 +- packages/util/package.json | 8 +-- packages/util/src/graph/database.ts | 56 +++++++++++++++++-- 14 files changed, 87 insertions(+), 39 deletions(-) diff --git a/lerna.json b/lerna.json index 0ebfe1b7..bfc5de4e 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.2.104", + "version": "0.2.105", "npmClient": "yarn", "useWorkspaces": true, "command": { diff --git a/packages/cache/package.json b/packages/cache/package.json index 09beec21..7f8fb3c6 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cache", - "version": "0.2.104", + "version": "0.2.105", "description": "Generic object cache", "main": "dist/index.js", "scripts": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 6fdc2f9f..1bf12be3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cli", - "version": "0.2.104", + "version": "0.2.105", "main": "dist/index.js", "license": "AGPL-3.0", "scripts": { @@ -15,13 +15,13 @@ }, "dependencies": { "@apollo/client": "^3.7.1", - "@cerc-io/cache": "^0.2.104", - "@cerc-io/ipld-eth-client": "^0.2.104", + "@cerc-io/cache": "^0.2.105", + "@cerc-io/ipld-eth-client": "^0.2.105", "@cerc-io/libp2p": "^0.42.2-laconic-0.1.4", "@cerc-io/nitro-node": "^0.1.15", - "@cerc-io/peer": "^0.2.104", - "@cerc-io/rpc-eth-client": "^0.2.104", - "@cerc-io/util": "^0.2.104", + "@cerc-io/peer": "^0.2.105", + "@cerc-io/rpc-eth-client": "^0.2.105", + "@cerc-io/util": "^0.2.105", "@ethersproject/providers": "^5.4.4", "@graphql-tools/utils": "^9.1.1", "@ipld/dag-cbor": "^8.0.0", diff --git a/packages/codegen/package.json b/packages/codegen/package.json index f53544de..7f75f6dc 100644 --- a/packages/codegen/package.json +++ b/packages/codegen/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/codegen", - "version": "0.2.104", + "version": "0.2.105", "description": "Code generator", "private": true, "main": "index.js", @@ -20,7 +20,7 @@ }, "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { - "@cerc-io/util": "^0.2.104", + "@cerc-io/util": "^0.2.105", "@graphql-tools/load-files": "^6.5.2", "@npmcli/package-json": "^5.0.0", "@poanet/solidity-flattener": "https://github.com/vulcanize/solidity-flattener.git", diff --git a/packages/codegen/src/templates/package-template.handlebars b/packages/codegen/src/templates/package-template.handlebars index ecd6bf7f..044d6b2e 100644 --- a/packages/codegen/src/templates/package-template.handlebars +++ b/packages/codegen/src/templates/package-template.handlebars @@ -41,12 +41,12 @@ "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { "@apollo/client": "^3.3.19", - "@cerc-io/cli": "^0.2.104", - "@cerc-io/ipld-eth-client": "^0.2.104", - "@cerc-io/solidity-mapper": "^0.2.104", - "@cerc-io/util": "^0.2.104", + "@cerc-io/cli": "^0.2.105", + "@cerc-io/ipld-eth-client": "^0.2.105", + "@cerc-io/solidity-mapper": "^0.2.105", + "@cerc-io/util": "^0.2.105", {{#if (subgraphPath)}} - "@cerc-io/graph-node": "^0.2.104", + "@cerc-io/graph-node": "^0.2.105", {{/if}} "@ethersproject/providers": "^5.4.4", "debug": "^4.3.1", diff --git a/packages/graph-node/package.json b/packages/graph-node/package.json index c70b533e..79362cc0 100644 --- a/packages/graph-node/package.json +++ b/packages/graph-node/package.json @@ -1,10 +1,10 @@ { "name": "@cerc-io/graph-node", - "version": "0.2.104", + "version": "0.2.105", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { - "@cerc-io/solidity-mapper": "^0.2.104", + "@cerc-io/solidity-mapper": "^0.2.105", "@ethersproject/providers": "^5.4.4", "@graphprotocol/graph-ts": "^0.22.0", "@nomiclabs/hardhat-ethers": "^2.0.2", @@ -51,9 +51,9 @@ "dependencies": { "@apollo/client": "^3.3.19", "@cerc-io/assemblyscript": "0.19.10-watcher-ts-0.1.2", - "@cerc-io/cache": "^0.2.104", - "@cerc-io/ipld-eth-client": "^0.2.104", - "@cerc-io/util": "^0.2.104", + "@cerc-io/cache": "^0.2.105", + "@cerc-io/ipld-eth-client": "^0.2.105", + "@cerc-io/util": "^0.2.105", "@types/json-diff": "^0.5.2", "@types/yargs": "^17.0.0", "bn.js": "^4.11.9", diff --git a/packages/ipld-eth-client/package.json b/packages/ipld-eth-client/package.json index 2c579b58..2d5bfe04 100644 --- a/packages/ipld-eth-client/package.json +++ b/packages/ipld-eth-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/ipld-eth-client", - "version": "0.2.104", + "version": "0.2.105", "description": "IPLD ETH Client", "main": "dist/index.js", "scripts": { @@ -20,8 +20,8 @@ "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { "@apollo/client": "^3.7.1", - "@cerc-io/cache": "^0.2.104", - "@cerc-io/util": "^0.2.104", + "@cerc-io/cache": "^0.2.105", + "@cerc-io/util": "^0.2.105", "cross-fetch": "^3.1.4", "debug": "^4.3.1", "ethers": "^5.4.4", diff --git a/packages/peer/package.json b/packages/peer/package.json index 60a7b74d..0b944728 100644 --- a/packages/peer/package.json +++ b/packages/peer/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/peer", - "version": "0.2.104", + "version": "0.2.105", "description": "libp2p module", "main": "dist/index.js", "exports": "./dist/index.js", diff --git a/packages/rpc-eth-client/package.json b/packages/rpc-eth-client/package.json index 53a7f4f7..e97b52cf 100644 --- a/packages/rpc-eth-client/package.json +++ b/packages/rpc-eth-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/rpc-eth-client", - "version": "0.2.104", + "version": "0.2.105", "description": "RPC ETH Client", "main": "dist/index.js", "scripts": { @@ -19,9 +19,9 @@ }, "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { - "@cerc-io/cache": "^0.2.104", - "@cerc-io/ipld-eth-client": "^0.2.104", - "@cerc-io/util": "^0.2.104", + "@cerc-io/cache": "^0.2.105", + "@cerc-io/ipld-eth-client": "^0.2.105", + "@cerc-io/util": "^0.2.105", "chai": "^4.3.4", "ethers": "^5.4.4", "left-pad": "^1.3.0", diff --git a/packages/solidity-mapper/package.json b/packages/solidity-mapper/package.json index c498e03c..c66102cc 100644 --- a/packages/solidity-mapper/package.json +++ b/packages/solidity-mapper/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/solidity-mapper", - "version": "0.2.104", + "version": "0.2.105", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { diff --git a/packages/test/package.json b/packages/test/package.json index e2901b95..de3217d5 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/test", - "version": "0.2.104", + "version": "0.2.105", "main": "dist/index.js", "license": "AGPL-3.0", "private": true, diff --git a/packages/tracing-client/package.json b/packages/tracing-client/package.json index 2529ebcb..69bd802b 100644 --- a/packages/tracing-client/package.json +++ b/packages/tracing-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/tracing-client", - "version": "0.2.104", + "version": "0.2.105", "description": "ETH VM tracing client", "main": "dist/index.js", "scripts": { diff --git a/packages/util/package.json b/packages/util/package.json index ff349355..a0928792 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,13 +1,13 @@ { "name": "@cerc-io/util", - "version": "0.2.104", + "version": "0.2.105", "main": "dist/index.js", "license": "AGPL-3.0", "dependencies": { "@apollo/utils.keyvaluecache": "^1.0.1", "@cerc-io/nitro-node": "^0.1.15", - "@cerc-io/peer": "^0.2.104", - "@cerc-io/solidity-mapper": "^0.2.104", + "@cerc-io/peer": "^0.2.105", + "@cerc-io/solidity-mapper": "^0.2.105", "@cerc-io/ts-channel": "1.0.3-ts-nitro-0.1.1", "@ethersproject/properties": "^5.7.0", "@ethersproject/providers": "^5.4.4", @@ -54,7 +54,7 @@ "yargs": "^17.0.1" }, "devDependencies": { - "@cerc-io/cache": "^0.2.104", + "@cerc-io/cache": "^0.2.105", "@nomiclabs/hardhat-waffle": "^2.0.1", "@types/bunyan": "^1.8.8", "@types/express": "^4.17.14", diff --git a/packages/util/src/graph/database.ts b/packages/util/src/graph/database.ts index cbd86e74..401fceef 100644 --- a/packages/util/src/graph/database.ts +++ b/packages/util/src/graph/database.ts @@ -17,11 +17,11 @@ import { } from 'typeorm'; import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata'; import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer'; -import { GraphQLResolveInfo, SelectionNode } from 'graphql'; +import { ArgumentNode, FieldNode, GraphQLResolveInfo, SelectionNode, IntValueNode, EnumValueNode } from 'graphql'; import _ from 'lodash'; import debug from 'debug'; -import { Database as BaseDatabase, QueryOptions, Where, CanonicalBlockHeight } from '../database'; +import { Database as BaseDatabase, QueryOptions, Where, CanonicalBlockHeight, OrderDirection } from '../database'; import { BlockProgressInterface } from '../types'; import { cachePrunedEntitiesCount, eventProcessingLoadEntityCacheHitCount, eventProcessingLoadEntityCount, eventProcessingLoadEntityDBQueryDuration } from '../metrics'; import { ServerConfig } from '../config'; @@ -272,6 +272,7 @@ export class GraphDatabase { const relationPromises = selections.filter((selection) => selection.kind === 'Field' && Boolean(relations[selection.name.value])) .map(async (selection) => { assert(selection.kind === 'Field'); + const field = selection.name.value; const { entity: relationEntity, isArray, isDerived, field: foreignKey } = relations[field]; let childSelections = selection.selectionSet?.selections || []; @@ -279,7 +280,16 @@ export class GraphDatabase { // Filter out __typename field in GQL for loading relations. childSelections = childSelections.filter(selection => !(selection.kind === 'Field' && selection.name.value === '__typename')); + // Parse arguments on a plural selection field + let relationWhere: Where = {}; + let relationQueryOptions: QueryOptions = {}; + if (isDerived || isArray) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + ({ where: relationWhere, queryOptions: relationQueryOptions } = this._getSelectionFieldArguments(selection)); + } + if (isDerived) { + // TODO: Merge with relationWhere const where: Where = { [foreignKey]: [{ value: entityData.id, @@ -294,7 +304,7 @@ export class GraphDatabase { relationsMap, block, where, - { limit: DEFAULT_LIMIT }, + relationQueryOptions, childSelections, queryInfo ); @@ -305,6 +315,7 @@ export class GraphDatabase { } if (isArray) { + // TODO: Merge with relationWhere const where: Where = { id: [{ value: entityData[field], @@ -319,7 +330,7 @@ export class GraphDatabase { relationsMap, block, where, - { limit: DEFAULT_LIMIT }, + relationQueryOptions, childSelections, queryInfo ); @@ -1347,4 +1358,41 @@ export class GraphDatabase { return [...acc, selection]; }, []); } + + _getSelectionFieldArguments (fieldNode: FieldNode): { where: Where, queryOptions: QueryOptions } { + const where: Where = {}; + const queryOptions: QueryOptions = {}; + + fieldNode.arguments?.forEach((arg: ArgumentNode) => { + switch (arg.name.value) { + case 'where': + // TODO: Parse ArgumentNode to build where filter + // where = this.buildFilter(arg.value); + break; + + case 'first': + queryOptions.limit = Number((arg.value as IntValueNode).value); + break; + + case 'skip': + queryOptions.skip = Number((arg.value as IntValueNode).value); + break; + + case 'orderBy': + queryOptions.orderBy = (arg.value as EnumValueNode).value; + break; + + case 'orderDirection': + queryOptions.orderDirection = (arg.value as EnumValueNode).value as OrderDirection; + break; + + default: + throw new Error('Unrecognized query argument'); + } + }); + + queryOptions.limit = queryOptions.limit || DEFAULT_LIMIT; + + return { where, queryOptions }; + } }