From 3c64e0e990adadae40528da69ff21aca0160b18f Mon Sep 17 00:00:00 2001 From: Dhruv Srivastava Date: Mon, 3 Apr 2023 14:31:21 +0530 Subject: [PATCH 1/4] Add --continue-on-error flag to codegen for skipping unhandled data types --- packages/codegen/src/generate-code.ts | 10 +++++++++- packages/codegen/src/visitor.ts | 28 +++++++++++++++++---------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/packages/codegen/src/generate-code.ts b/packages/codegen/src/generate-code.ts index 7866d1d7a..c3e7248e3 100644 --- a/packages/codegen/src/generate-code.ts +++ b/packages/codegen/src/generate-code.ts @@ -47,6 +47,13 @@ const main = async (): Promise => { describe: 'Watcher generation config file path (yaml)', type: 'string' }) + .option('continue-on-error', { + alias: 'C', + demandOption: false, + default: false, + describe: 'Continue generating watcher if unhandled types encountered', + type: 'boolean' + }) .argv; const config = getConfig(path.resolve(argv['config-file'])); @@ -96,7 +103,8 @@ const main = async (): Promise => { contracts.push(contractData); } - const visitor = new Visitor(); + const continueOnError = argv['continue-on-error']; + const visitor = new Visitor(continueOnError); parseAndVisit(visitor, contracts, config.mode); diff --git a/packages/codegen/src/visitor.ts b/packages/codegen/src/visitor.ts index 07d2a7830..4db3f740f 100644 --- a/packages/codegen/src/visitor.ts +++ b/packages/codegen/src/visitor.ts @@ -25,10 +25,11 @@ export class Visitor { _database: Database; _client: Client; _types: Types; + _continueOnError: boolean; _contract?: { name: string, kind: string }; - constructor () { + constructor (continueOnErrorFlag = false) { this._schema = new Schema(); this._resolvers = new Resolvers(); this._indexer = new Indexer(); @@ -36,6 +37,7 @@ export class Visitor { this._database = new Database(); this._client = new Client(); this._types = new Types(); + this._continueOnError = continueOnErrorFlag; } setContract (name: string, kind: string): void { @@ -66,15 +68,21 @@ export class Visitor { // TODO Handle multiple return parameters and array return type. const returnType = typeName.name; - - this._schema.addQuery(name, params, returnType); - this._resolvers.addQuery(name, params, returnType); - this._entity.addQuery(name, params, returnType); - this._database.addQuery(name, params, returnType); - this._client.addQuery(name, params, returnType); - - assert(this._contract); - this._indexer.addQuery(this._contract.name, MODE_ETH_CALL, name, params, returnType); + try { + this._schema.addQuery(name, params, returnType); + this._resolvers.addQuery(name, params, returnType); + this._entity.addQuery(name, params, returnType); + this._database.addQuery(name, params, returnType); + this._client.addQuery(name, params, returnType); + + assert(this._contract); + this._indexer.addQuery(this._contract.name, MODE_ETH_CALL, name, params, returnType); + } catch (error: any) { + if (!this._continueOnError) { + throw error; + } + console.log(error.message); + } } } From aa3c984c3b20d3a8b2663bdd4a159347e8379894 Mon Sep 17 00:00:00 2001 From: Dhruv Srivastava Date: Tue, 4 Apr 2023 11:45:46 +0530 Subject: [PATCH 2/4] Use solc version defined in config --- packages/codegen/src/artifacts.ts | 22 ++++++++++++++++++++-- packages/codegen/src/generate-code.ts | 6 ++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/codegen/src/artifacts.ts b/packages/codegen/src/artifacts.ts index 178e84ff9..d23b989f1 100644 --- a/packages/codegen/src/artifacts.ts +++ b/packages/codegen/src/artifacts.ts @@ -4,13 +4,17 @@ import solc from 'solc'; +interface Solc { + compile(input: string): any; +} + /** * Compiles the given contract using solc and returns resultant artifacts. * @param contractContent Contents of the contract file to be compiled. * @param contractFileName Input contract file name. * @param contractName Name of the main contract in the contract file. */ -export function generateArtifacts (contractContent: string, contractFileName: string, contractName: string): { abi: any[], storageLayout: any } { +export async function generateArtifacts (contractContent: string, contractFileName: string, contractName: string, solcVersion: string): Promise<{ abi: any[], storageLayout: any }> { const input: any = { language: 'Solidity', sources: {}, @@ -27,6 +31,20 @@ export function generateArtifacts (contractContent: string, contractFileName: st content: contractContent }; + const solcInstance = (solcVersion === undefined) ? solc : await getSolcByVersion(solcVersion); + // Get artifacts for the required contract. - return JSON.parse(solc.compile(JSON.stringify(input))).contracts[contractFileName][contractName]; + return JSON.parse(solcInstance.compile(JSON.stringify(input))).contracts[contractFileName][contractName]; +} + +async function getSolcByVersion (solcVersion: string): Promise { + return new Promise((resolve, reject) => { + solc.loadRemoteVersion(solcVersion, (err: any, solcInstance: Solc | Promise) => { + if (err) { + reject(err); + } else { + resolve(solcInstance); + } + }); + }); } diff --git a/packages/codegen/src/generate-code.ts b/packages/codegen/src/generate-code.ts index c3e7248e3..cadc3f3d8 100644 --- a/packages/codegen/src/generate-code.ts +++ b/packages/codegen/src/generate-code.ts @@ -90,10 +90,11 @@ const main = async (): Promise => { // Generate artifacts from contract. const inputFileName = path.basename(inputFile, '.sol'); - const { abi, storageLayout } = generateArtifacts( + const { abi, storageLayout } = await generateArtifacts( contractData.contractString, `${inputFileName}.sol`, - contractData.contractName + contractData.contractName, + config.solc ); contractData.contractAbi = abi; @@ -387,6 +388,7 @@ function getConfig (configFile: string): any { mode: inputConfig.mode || MODE_ALL, kind: inputConfig.kind || KIND_ACTIVE, port: inputConfig.port || DEFAULT_PORT, + solc: inputConfig.solc, flatten, subgraphPath, subgraphConfig From adf505d29b1504a649d0c11df17bf1cb9c0cb59f Mon Sep 17 00:00:00 2001 From: Dhruv Srivastava Date: Tue, 4 Apr 2023 12:30:22 +0530 Subject: [PATCH 3/4] Fix codegen log for unhandled array types --- packages/codegen/src/visitor.ts | 51 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/packages/codegen/src/visitor.ts b/packages/codegen/src/visitor.ts index 4db3f740f..ec9e3b0b3 100644 --- a/packages/codegen/src/visitor.ts +++ b/packages/codegen/src/visitor.ts @@ -58,30 +58,43 @@ export class Visitor { return { name: item.name, type: item.typeName.name }; }); + let errorMessage = ''; + const typeName = node.returnParameters[0].typeName; + switch (typeName.type) { + case 'ElementaryTypeName': { + const returnType = typeName.name; + + this._schema.addQuery(name, params, returnType); + this._resolvers.addQuery(name, params, returnType); + this._entity.addQuery(name, params, returnType); + this._database.addQuery(name, params, returnType); + this._client.addQuery(name, params, returnType); - // TODO Handle user defined type return. - if (typeName.type === 'UserDefinedTypeName') { - // Skip in case of UserDefinedTypeName. - return; + assert(this._contract); + this._indexer.addQuery(this._contract.name, MODE_ETH_CALL, name, params, returnType); + + break; + } + case 'UserDefinedTypeName': + errorMessage = `No support in codegen for user defined return type from method "${node.name}"`; + break; + + case 'ArrayTypeName': + errorMessage = `No support in codegen for return type "${typeName.baseTypeName.name}[]" from method "${node.name}"`; + break; + + default: + errorMessage = `No support in codegen for return type "${typeName.type}" from method "${node.name}"`; } - // TODO Handle multiple return parameters and array return type. - const returnType = typeName.name; - try { - this._schema.addQuery(name, params, returnType); - this._resolvers.addQuery(name, params, returnType); - this._entity.addQuery(name, params, returnType); - this._database.addQuery(name, params, returnType); - this._client.addQuery(name, params, returnType); - - assert(this._contract); - this._indexer.addQuery(this._contract.name, MODE_ETH_CALL, name, params, returnType); - } catch (error: any) { - if (!this._continueOnError) { - throw error; + if (errorMessage !== '') { + if (this._continueOnError) { + console.log(errorMessage); + return; } - console.log(error.message); + + throw new Error(errorMessage); } } } From 6a52bcace3602cb99bc7b2f874be8bad585461ee Mon Sep 17 00:00:00 2001 From: Dhruv Srivastava Date: Tue, 4 Apr 2023 15:08:53 +0530 Subject: [PATCH 4/4] Log solc compilation errors --- packages/codegen/src/artifacts.ts | 13 ++++++++++++- packages/codegen/src/generate-code.ts | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/codegen/src/artifacts.ts b/packages/codegen/src/artifacts.ts index d23b989f1..dda36e438 100644 --- a/packages/codegen/src/artifacts.ts +++ b/packages/codegen/src/artifacts.ts @@ -32,9 +32,20 @@ export async function generateArtifacts (contractContent: string, contractFileNa }; const solcInstance = (solcVersion === undefined) ? solc : await getSolcByVersion(solcVersion); + const compiledContract = JSON.parse(solcInstance.compile(JSON.stringify(input))); + + if (compiledContract.errors?.length) { + compiledContract.errors.forEach((error: any) => { + if (error.severity === 'error') { + throw new Error(error.formattedMessage); + } + + console.log(`${error.severity}: ${error.formattedMessage}`); + }); + } // Get artifacts for the required contract. - return JSON.parse(solcInstance.compile(JSON.stringify(input))).contracts[contractFileName][contractName]; + return compiledContract.contracts[contractFileName][contractName]; } async function getSolcByVersion (solcVersion: string): Promise { diff --git a/packages/codegen/src/generate-code.ts b/packages/codegen/src/generate-code.ts index cadc3f3d8..74ac5f4fb 100644 --- a/packages/codegen/src/generate-code.ts +++ b/packages/codegen/src/generate-code.ts @@ -48,7 +48,7 @@ const main = async (): Promise => { type: 'string' }) .option('continue-on-error', { - alias: 'C', + alias: 'e', demandOption: false, default: false, describe: 'Continue generating watcher if unhandled types encountered',