Skip to content

Commit c09d6d6

Browse files
authored
Merge branch 'master' into joe-patch-014
2 parents 94c6c8a + 9e55ef0 commit c09d6d6

File tree

1 file changed

+43
-3
lines changed

1 file changed

+43
-3
lines changed

libs/remix-core-plugin/src/lib/helpers/fetch-etherscan.ts

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,52 @@ export const fetchContractFromEtherscan = async (plugin, endpoint: string | Netw
1111
if (!etherscanKey) etherscanKey = '2HKUX5ZVASZIKWJM8MIQVCRUVZ6JAWT531'
1212

1313
if (etherscanKey) {
14+
// Extract chain ID and build endpoint string once
15+
let chainId = 1 // Default to Ethereum mainnet
16+
let endpointStr: string
1417
if (typeof endpoint === 'object' && endpoint !== null && 'id' in endpoint && 'name' in endpoint) {
15-
endpoint = endpoint.id == 1 ? 'api.etherscan.io' : 'api-' + endpoint.name + '.etherscan.io'
18+
chainId = endpoint.id
19+
const normalized = String(endpoint.name || '').toLowerCase()
20+
endpointStr = endpoint.id == 1 ? 'api.etherscan.io' : 'api-' + normalized + '.etherscan.io'
21+
} else {
22+
endpointStr = endpoint as string
1623
}
1724
try {
18-
data = await fetch('https://' + endpoint + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey)
19-
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+
const centralV2Status = response.status;
29+
const centralV2StatusText = response.statusText;
30+
31+
// If central V2 not OK, try per-network V2, then per-network V1
32+
if (!response.ok) {
33+
const v2PerNetworkUrl = 'https://' + endpointStr + '/v2/api?chainid=' + chainId + '&module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
34+
const v2PerNetworkResponse = await fetch(v2PerNetworkUrl)
35+
const v2PerNetworkStatus = v2PerNetworkResponse.status;
36+
const v2PerNetworkStatusText = v2PerNetworkResponse.statusText;
37+
if (v2PerNetworkResponse.ok) {
38+
response = v2PerNetworkResponse;
39+
} else {
40+
const v1Url = 'https://' + endpointStr + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey
41+
const v1Response = await fetch(v1Url)
42+
const v1Status = v1Response.status;
43+
const v1StatusText = v1Response.statusText;
44+
if (v1Response.ok) {
45+
response = v1Response;
46+
} else {
47+
// All three endpoints failed, throw a descriptive error
48+
throw new Error(
49+
`All Etherscan API endpoints failed:\n` +
50+
`Central V2: ${v2CentralUrl} [${centralV2Status} ${centralV2StatusText}]\n` +
51+
`Per-network V2: ${v2PerNetworkUrl} [${v2PerNetworkStatus} ${v2PerNetworkStatusText}]\n` +
52+
`Per-network V1: ${v1Url} [${v1Status} ${v1StatusText}]`
53+
);
54+
}
55+
}
56+
}
57+
58+
data = await response.json()
59+
2060
// etherscan api doc https://docs.etherscan.io/api-endpoints/contracts
2161
if (data.message === 'OK' && data.status === "1") {
2262
if (data.result.length) {

0 commit comments

Comments
 (0)