@@ -11,33 +11,33 @@ export const fetchContractFromEtherscan = async (plugin, endpoint: string | Netw
1111 if ( ! etherscanKey ) etherscanKey = '2HKUX5ZVASZIKWJM8MIQVCRUVZ6JAWT531'
1212
1313 if ( etherscanKey ) {
14- // Extract chain ID from Network object before converting to string
14+ // Extract chain ID and build endpoint string once
1515 let chainId = 1 // Default to Ethereum mainnet
16+ let endpointStr : string
1617 if ( typeof endpoint === 'object' && endpoint !== null && 'id' in endpoint && 'name' in endpoint ) {
1718 chainId = endpoint . id
18- endpoint = endpoint . id == 1 ? 'api.etherscan.io' : 'api-' + endpoint . name + '.etherscan.io'
19+ const normalized = String ( ( endpoint as any ) . name || '' ) . toLowerCase ( )
20+ endpointStr = endpoint . id == 1 ? 'api.etherscan.io' : 'api-' + normalized + '.etherscan.io'
21+ } else {
22+ endpointStr = endpoint as string
1923 }
2024 try {
21- // Try V2 API first with chainid parameter
22- let apiUrl = 'https://' + endpoint + '/v2/api?chainid=' + chainId + '&module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
23- data = await fetch ( apiUrl )
24-
25- // If V2 API fails (404 or other error), fallback to V1 API
26- if ( ! data . ok ) {
27- apiUrl = 'https://' + endpoint + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
28- data = await fetch ( apiUrl )
29- }
30-
31- data = await data . json ( )
32-
33- // Handle deprecated V1 endpoint response
34- if ( data . message === 'NOTOK' && data . result && data . result . includes ( 'deprecated V1 endpoint' ) ) {
35- // Force V2 API usage even if it initially failed
36- apiUrl = 'https://' + endpoint + '/v2/api?chainid=' + chainId + '&module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
37- data = await fetch ( apiUrl )
38- data = await data . json ( )
25+ // Prefer central V2 API host with chainid param (works across Etherscan-supported networks)
26+ const v2CentralUrl = 'https://api.etherscan.io/v2/api?chainid=' + chainId + '&module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
27+ let response = await fetch ( v2CentralUrl )
28+
29+ // If central V2 not OK, try per-network V2, then per-network V1
30+ if ( ! response . ok ) {
31+ const v2PerNetworkUrl = 'https://' + endpointStr + '/v2/api?chainid=' + chainId + '&module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
32+ response = await fetch ( v2PerNetworkUrl )
33+ if ( ! response . ok ) {
34+ const v1Url = 'https://' + endpointStr + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
35+ response = await fetch ( v1Url )
36+ }
3937 }
40-
38+
39+ data = await response . json ( )
40+
4141 // etherscan api doc https://docs.etherscan.io/api-endpoints/contracts
4242 if ( data . message === 'OK' && data . status === "1" ) {
4343 if ( data . result . length ) {
0 commit comments