@@ -7,6 +7,31 @@ import { withSpinner } from './spinner';
77
88const logger = debugFactory ( 'graph-cli:abi-helpers' ) ;
99
10+ const fetchFromEtherscan = async ( url : string ) : Promise < any | null > => {
11+ const result = await fetch ( url ) ;
12+ let json : any = { } ;
13+
14+ if ( result . ok ) {
15+ json = await result . json ( ) . catch ( error => {
16+ throw new Error ( `Failed to read JSON response from Etherscan: ${ error } ` ) ;
17+ } ) ;
18+
19+ // Etherscan returns a JSON object that has a `status`, a `message` and
20+ // a `result` field. The `status` is '0' in case of errors and '1' in
21+ // case of success
22+ if ( json . status === '1' ) return json ;
23+ }
24+
25+ logger (
26+ 'Failed to fetchFromEtherscan: [%s] %s (%s)\n%O' ,
27+ result . status ,
28+ result . statusText ,
29+ result . url ,
30+ json ,
31+ ) ;
32+ return null ;
33+ } ;
34+
1035export const loadAbiFromEtherscan = async (
1136 ABICtor : typeof ABI ,
1237 network : string ,
@@ -18,16 +43,14 @@ export const loadAbiFromEtherscan = async (
1843 `Warnings while fetching ABI from Etherscan` ,
1944 async ( ) => {
2045 const scanApiUrl = getEtherscanLikeAPIUrl ( network ) ;
21- const result = await fetch ( `${ scanApiUrl } ?module=contract&action=getabi&address=${ address } ` ) ;
22- const json = await result . json ( ) ;
46+ const json = await fetchFromEtherscan (
47+ `${ scanApiUrl } ?module=contract&action=getabi&address=${ address } ` ,
48+ ) ;
2349
24- // Etherscan returns a JSON object that has a `status`, a `message` and
25- // a `result` field. The `status` is '0' in case of errors and '1' in
26- // case of success
27- if ( json . status === '1' ) {
50+ if ( json )
2851 return new ABICtor ( 'Contract' , undefined , immutable . fromJS ( JSON . parse ( json . result ) ) ) ;
29- }
30- throw new Error ( 'ABI not found, try loading it from a local file' ) ;
52+
53+ throw new Error ( 'Try loading it from a local file' ) ;
3154 } ,
3255 ) ;
3356
@@ -62,11 +85,11 @@ export const fetchDeployContractTransactionFromEtherscan = async (
6285 address : string ,
6386) : Promise < string > => {
6487 const scanApiUrl = getEtherscanLikeAPIUrl ( network ) ;
65- const json = await fetchContractCreationHashWithRetry (
88+ const json = await fetchFromEtherscan (
6689 `${ scanApiUrl } ?module=contract&action=getcontractcreation&contractaddresses=${ address } ` ,
67- 5 ,
6890 ) ;
69- if ( json . status === '1' ) {
91+
92+ if ( json ) {
7093 const hash = json . result [ 0 ] . txHash ;
7194 logger ( 'Successfully fetchDeployContractTransactionFromEtherscan. txHash: %s' , hash ) ;
7295 return hash ;
@@ -75,26 +98,6 @@ export const fetchDeployContractTransactionFromEtherscan = async (
7598 throw new Error ( `Failed to fetch deploy contract transaction` ) ;
7699} ;
77100
78- export const fetchContractCreationHashWithRetry = async (
79- url : string ,
80- retryCount : number ,
81- ) : Promise < any > => {
82- let json ;
83- for ( let i = 0 ; i < retryCount ; i ++ ) {
84- try {
85- const result = await fetch ( url ) ;
86- json = await result . json ( ) ;
87- if ( json . status !== '0' ) {
88- return json ;
89- }
90- } catch ( error ) {
91- logger ( 'Failed to fetchContractCreationHashWithRetry: %O' , error ) ;
92- /* empty */
93- }
94- }
95- throw new Error ( `Failed to fetch contract creation transaction hash` ) ;
96- } ;
97-
98101export const fetchTransactionByHashFromRPC = async (
99102 network : string ,
100103 transactionHash : string ,
@@ -131,14 +134,15 @@ export const fetchSourceCodeFromEtherscan = async (
131134 address : string ,
132135) : Promise < any > => {
133136 const scanApiUrl = getEtherscanLikeAPIUrl ( network ) ;
134- const result = await fetch (
137+ const json = await fetchFromEtherscan (
135138 `${ scanApiUrl } ?module=contract&action=getsourcecode&address=${ address } ` ,
136139 ) ;
137- const json = await result . json ( ) ;
138- if ( json . status === '1' ) {
139- return json ;
140- }
141- throw new Error ( 'Failed to fetch contract source code' ) ;
140+
141+ // Have to check that the SourceCode response is not empty due to Etherscan API bug responding with
142+ // 1 - OK on non-valid contracts.
143+ if ( json . result [ 0 ] . SourceCode ) return json ;
144+
145+ throw new Error ( `Failed to fetch contract source code: ${ json . result [ 0 ] . ABI } ` ) ;
142146} ;
143147
144148export const getContractNameForAddress = async (
0 commit comments