From 9f0bdd9a7f113e8edfd550fec5163f3c343dd86c Mon Sep 17 00:00:00 2001 From: Etienne Donneger Date: Fri, 7 Feb 2025 11:00:23 -0500 Subject: [PATCH] Use Sourcify v2 endpoint for contract lookups --- .changeset/giant-owls-accept.md | 5 +++ .../cli/src/command-helpers/contracts.test.ts | 7 ++++ packages/cli/src/command-helpers/contracts.ts | 32 +++++++++---------- 3 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 .changeset/giant-owls-accept.md diff --git a/.changeset/giant-owls-accept.md b/.changeset/giant-owls-accept.md new file mode 100644 index 000000000..cbd0815e1 --- /dev/null +++ b/.changeset/giant-owls-accept.md @@ -0,0 +1,5 @@ +--- +'@graphprotocol/graph-cli': patch +--- + +Use Sourcify v2 endpoint for contract lookups diff --git a/packages/cli/src/command-helpers/contracts.test.ts b/packages/cli/src/command-helpers/contracts.test.ts index 10705ce93..888307be9 100644 --- a/packages/cli/src/command-helpers/contracts.test.ts +++ b/packages/cli/src/command-helpers/contracts.test.ts @@ -111,6 +111,13 @@ const TEST_SOURCIFY_CONTRACT_INFO = { startBlock: null, }, }, + // Invalid address (missing 0x) + matic: { + '0000000000000000000000000000000000000000': { + name: null, + startBlock: null, + }, + } }; // Retry helper with configurable number of retries diff --git a/packages/cli/src/command-helpers/contracts.ts b/packages/cli/src/command-helpers/contracts.ts index 608e92448..fcfec9dd5 100644 --- a/packages/cli/src/command-helpers/contracts.ts +++ b/packages/cli/src/command-helpers/contracts.ts @@ -163,37 +163,35 @@ export class ContractService { if (!network.caip2Id.startsWith('eip155')) throw new Error(`Invalid chainId, Sourcify API only supports EVM chains`); + if (!address.startsWith('0x') || address.length != 42) + throw new Error(`Invalid address, must start with 0x prefix and be 20 bytes long`); + const chainId = network.caip2Id.split(':')[1]; - const url = `https://sourcify.dev/server/files/any/${chainId}/${address}`; + const url = `https://sourcify.dev/server/v2/contract/${chainId}/${address}?fields=abi,compilation,deployment`; const json: | { - status: string; - files: { name: string; path: string; content: string }[]; + abi: any[]; + compilation: { name: string }; + deployment: { blockNumber: string }; } - | { error: string } = await ( + | { customCode: string; message: string; errorId: string; } = await ( await fetch(url).catch(error => { throw new Error(`Sourcify API is unreachable: ${error}`); }) ).json(); if (json) { - if ('error' in json) throw new Error(`Sourcify API error: ${json.error}`); - - let metadata: any = json.files.find(e => e.name === 'metadata.json')?.content; - if (!metadata) throw new Error('Contract is missing metadata'); + if ('errorId' in json) throw new Error(`Sourcify API error: [${json.customCode}] ${json.message}`); - const tx_hash = json.files.find(e => e.name === 'creator-tx-hash.txt')?.content; - if (!tx_hash) throw new Error('Contract is missing tx creation hash'); + const abi = json.abi; + const contractName = json.compilation.name; + const blockNumber = json.deployment.blockNumber; - const tx = await this.fetchTransactionByHash(networkId, tx_hash); - if (!tx?.blockNumber) - throw new Error(`Can't fetch blockNumber from tx: ${JSON.stringify(tx)}`); + if (!abi || !contractName || !blockNumber) throw new Error('Contract is missing metadata'); - metadata = JSON.parse(metadata); - const contractName = Object.values(metadata.settings.compilationTarget)[0] as string; return { - abi: new ABICtor(contractName, undefined, immutable.fromJS(metadata.output.abi)) as ABI, - startBlock: Number(tx.blockNumber).toString(), + abi: new ABICtor(contractName, undefined, immutable.fromJS(abi)) as ABI, + startBlock: Number(blockNumber).toString(), name: contractName, }; }