@@ -7,6 +7,31 @@ import { withSpinner } from './spinner';
7
7
8
8
const logger = debugFactory ( 'graph-cli:abi-helpers' ) ;
9
9
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
+
10
35
export const loadAbiFromEtherscan = async (
11
36
ABICtor : typeof ABI ,
12
37
network : string ,
@@ -18,16 +43,14 @@ export const loadAbiFromEtherscan = async (
18
43
`Warnings while fetching ABI from Etherscan` ,
19
44
async ( ) => {
20
45
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
+ ) ;
23
49
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 )
28
51
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' ) ;
31
54
} ,
32
55
) ;
33
56
@@ -62,11 +85,11 @@ export const fetchDeployContractTransactionFromEtherscan = async (
62
85
address : string ,
63
86
) : Promise < string > => {
64
87
const scanApiUrl = getEtherscanLikeAPIUrl ( network ) ;
65
- const json = await fetchContractCreationHashWithRetry (
88
+ const json = await fetchFromEtherscan (
66
89
`${ scanApiUrl } ?module=contract&action=getcontractcreation&contractaddresses=${ address } ` ,
67
- 5 ,
68
90
) ;
69
- if ( json . status === '1' ) {
91
+
92
+ if ( json ) {
70
93
const hash = json . result [ 0 ] . txHash ;
71
94
logger ( 'Successfully fetchDeployContractTransactionFromEtherscan. txHash: %s' , hash ) ;
72
95
return hash ;
@@ -75,26 +98,6 @@ export const fetchDeployContractTransactionFromEtherscan = async (
75
98
throw new Error ( `Failed to fetch deploy contract transaction` ) ;
76
99
} ;
77
100
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
-
98
101
export const fetchTransactionByHashFromRPC = async (
99
102
network : string ,
100
103
transactionHash : string ,
@@ -131,14 +134,15 @@ export const fetchSourceCodeFromEtherscan = async (
131
134
address : string ,
132
135
) : Promise < any > => {
133
136
const scanApiUrl = getEtherscanLikeAPIUrl ( network ) ;
134
- const result = await fetch (
137
+ const json = await fetchFromEtherscan (
135
138
`${ scanApiUrl } ?module=contract&action=getsourcecode&address=${ address } ` ,
136
139
) ;
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 } ` ) ;
142
146
} ;
143
147
144
148
export const getContractNameForAddress = async (
0 commit comments