Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
## 4.64.0 (2025-11-14)

- changed: Upgrade @polkadot/api to latest to support Asset Hub migration
- removed: Removed 'api.bscscan.com' server due to deprecation

## 4.63.2 (2025-11-13)

Expand Down
95 changes: 82 additions & 13 deletions src/ethereum/ethereumTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,92 @@ export interface EthereumNetworkInfo {
decoyAddressConfig?: DecoyAddressConfig
}

const asNetworkAdaptorConfigType = asValue(
'amberdata-rpc',
'blockbook',
'blockbook-ws',
'blockchair',
'blockcypher',
'evmscan',
'filfox',
'pulsechain-scan',
'rpc'
)
const asNetworkAdaptorConfig = asObject({
type: asNetworkAdaptorConfigType,
const asAmberdataAdapterConfig: Cleaner<
import('./networkAdapters/AmberdataAdapter').AmberdataAdapterConfig
> = asObject({
type: asValue('amberdata-rpc'),
amberdataBlockchainId: asString,
servers: asArray(asString)
})

const asBlockbookAdapterConfig: Cleaner<
import('./networkAdapters/BlockbookAdapter').BlockbookAdapterConfig
> = asObject({
type: asValue('blockbook'),
servers: asArray(asString)
})

const asBlockbookWsAdapterConnection: Cleaner<
import('./networkAdapters/BlockbookWsAdapter').BlockbookWsAdapterConnection
> = asObject({
url: asString,
keyType: asOptional(asValue('nowNodesApiKey'))
})

const asBlockbookWsAdapterConfig: Cleaner<
import('./networkAdapters/BlockbookWsAdapter').BlockbookWsAdapterConfig
> = asObject({
type: asValue('blockbook-ws'),
connections: asArray(asBlockbookWsAdapterConnection)
})

const asBlockchairAdapterConfig: Cleaner<
import('./networkAdapters/BlockchairAdapter').BlockchairAdapterConfig
> = asObject({
type: asValue('blockchair'),
servers: asArray(asString)
})

const asBlockcypherAdapterConfig: Cleaner<
import('./networkAdapters/BlockcypherAdapter').BlockcypherAdapterConfig
> = asObject({
type: asValue('blockcypher'),
servers: asArray(asString)
})

const asEvmScanAdapterConfig: Cleaner<
import('./networkAdapters/EvmScanAdapter').EvmScanAdapterConfig
> = asObject({
type: asValue('evmscan'),
servers: asArray(asString),
version: asValue(1, 2),
gastrackerSupport: asOptional(asBoolean)
})

const asFilfoxAdapterConfig: Cleaner<
import('./networkAdapters/FilfoxAdapter').FilfoxAdapterConfig
> = asObject({
type: asValue('filfox'),
servers: asArray(asString)
})

const asPulsechainScanAdapterConfig: Cleaner<
import('./networkAdapters/PulsechainScanAdapter').PulsechainScanAdapterConfig
> = asObject({
type: asValue('pulsechain-scan'),
servers: asArray(asString)
})

const asRpcAdapterConfig: Cleaner<
import('./networkAdapters/RpcAdapter').RpcAdapterConfig
> = asObject({
type: asValue('rpc'),
servers: asArray(asString),
ethBalCheckerContract: asOptional(asString)
})

const asNetworkAdaptorConfig: Cleaner<NetworkAdapterConfig> = asEither(
asAmberdataAdapterConfig,
asBlockbookAdapterConfig,
asBlockbookWsAdapterConfig,
asBlockchairAdapterConfig,
asBlockcypherAdapterConfig,
asEvmScanAdapterConfig,
asFilfoxAdapterConfig,
asPulsechainScanAdapterConfig,
asRpcAdapterConfig
)

/**
* Other Methods from EthereumTools
*/
Expand Down
11 changes: 7 additions & 4 deletions src/ethereum/fees/feeProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,12 @@ export const fetchFeesFromEvmScan = async (
const apiKey = `&apikey=${
Array.isArray(scanApiKey) ? pickRandom(scanApiKey, 1)[0] : scanApiKey ?? ''
}`
// Use Etherscan v2 API when targeting etherscan.io, otherwise use the network-specific scan API format
// Use version from config to determine URL format (server URLs already include full paths)
const chainId = networkInfo.chainParams.chainId
const url = server.includes('etherscan.io')
? `${server}/v2/api?chainid=${chainId}&module=gastracker&action=gasoracle${apiKey}`
: `${server}/api?module=gastracker&action=gasoracle${apiKey}`
const url =
evmScanConfig.version === 2
? `${server}?chainid=${chainId}&module=gastracker&action=gasoracle${apiKey}`
: `${server}?module=gastracker&action=gasoracle${apiKey}`

const fetchResponse = await fetch(url)
if (!fetchResponse.ok)
Expand Down Expand Up @@ -346,6 +347,8 @@ export const getEvmScanApiKey = (
log: EdgeLog,
serverUrl: string
): string | string[] | undefined => {
// TODO: This is total BS. We should just have a key associated with a domain name.
// This is getting out of hand.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Improve EVM Scan API Key Network Handling

The getEvmScanApiKey function checks if serverUrl.includes('etherscan.io') and requires etherscanApiKey, but this breaks BSC after removing api.bscscan.com as a fallback server. Now BSC uses only https://api.etherscan.io/v2/api, which matches the etherscan.io check and throws an error or returns the wrong API key. The function should differentiate between Etherscan being used for ETH vs other networks, allowing bscscanApiKey or the unified evmScanApiKey to be used for BSC.

Fix in Cursor Fix in Web

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was always a problem. The solution is to add etherscanApiKey to bsc key list

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Legacy Etherscan Check Blocks Unified API

The getEvmScanApiKey function requires etherscanApiKey when the server URL contains 'etherscan.io', throwing an error before checking for the unified evmScanApiKey. After consolidating BSC to use https://api.etherscan.io/v2/api, calls for BSC will now always match the etherscan.io check and throw if etherscanApiKey is missing, even when evmScanApiKey is configured. This breaks BSC fee queries for deployments using only the recommended evmScanApiKey pattern.

Fix in Cursor Fix in Web

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was always a problem. The solution is to add etherscanApiKey to bsc key list

const { evmScanApiKey, etherscanApiKey, bscscanApiKey, polygonscanApiKey } =
initOptions

Expand Down
5 changes: 3 additions & 2 deletions src/ethereum/info/abstractInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ const networkInfo: EthereumNetworkInfo = {
networkAdapterConfigs: [
{
type: 'rpc',
servers: ['https://api.mainnet.abs.xyz ']
servers: ['https://api.mainnet.abs.xyz']
},
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.abscan.org/']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Abstract Chain API: Generic Endpoint Incompatibility

Abstract chain configuration is using Etherscan's v2 API with chainId 2741, but Etherscan v2 API doesn't support Abstract's chain ID. The chain-specific api.abscan.org server was replaced with a generic Etherscan endpoint that will fail queries for this network. Abstract requires its own dedicated API server configuration.

Fix in Cursor Fix in Web

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
],
uriNetworks: ['abstract'],
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/amoyInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api-amoy.polygonscan.com/']
servers: ['https://api-amoy.polygonscan.com/v2/api'],
version: 2
}
],
uriNetworks: ['amoy'],
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/arbitrumInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io', 'https://api.arbiscan.io']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
},
{
type: 'blockchair',
Expand Down
13 changes: 9 additions & 4 deletions src/ethereum/info/avalancheInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,19 @@ const networkInfo: EthereumNetworkInfo = {
],
ethBalCheckerContract: '0xd023d153a0dfa485130ecfde2faa7e612ef94818'
},
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io/v2/api'],
version: 2
},
{
type: 'evmscan',
gastrackerSupport: true,
servers: [
'https://api.etherscan.io',
'https://api.avascan.info/v2/network/mainnet/evm/43114/etherscan',
'https://api.snowscan.xyz'
]
'https://api.avascan.info/v2/network/mainnet/evm/43114/etherscan/api'
],
version: 1
}
],
uriNetworks: ['avalanche'],
Expand Down
4 changes: 2 additions & 2 deletions src/ethereum/info/baseInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ const networkInfo: EthereumNetworkInfo = {
type: 'rpc',
servers: [
'https://base-mainnet.public.blastapi.io',
'https://rpc.ankr.com/base',
'https://lb.drpc.org/ogrpc?network=base&dkey={{drpcApiKey}}'
],
ethBalCheckerContract: '0x3ba5A41eA17fd4950a641a057dC0bEb8E8ff1521'
},
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io', 'https://api.basescan.org']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
},
{
type: 'blockchair',
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/binancesmartchainInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io', 'https://api.bscscan.com']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
}
],
uriNetworks: ['smartchain'],
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/bobevmInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://explorer.gobob.xyz']
servers: ['https://explorer.gobob.xyz/api'],
version: 1
}
],
uriNetworks: [],
Expand Down
5 changes: 3 additions & 2 deletions src/ethereum/info/botanixInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ const networkInfo: EthereumNetworkInfo = {
type: 'evmscan',
gastrackerSupport: true,
servers: [
'https://api.routescan.io/v2/network/mainnet/evm/3637/etherscan'
]
'https://api.routescan.io/v2/network/mainnet/evm/3637/etherscan/api'
],
version: 1
}
],
uriNetworks: [],
Expand Down
10 changes: 8 additions & 2 deletions src/ethereum/info/celoInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,20 @@ const networkInfo: EthereumNetworkInfo = {
servers: [
'https://forno.celo.org',
'https://rpc.ankr.com/celo',
'https://celo-mainnet-rpc.allthatnode.com',
'https://lb.drpc.org/ogrpc?network=celo&dkey={{drpcApiKey}}'
]
},
{
type: 'evmscan',
gastrackerSupport: false,
servers: ['https://api.etherscan.io', 'https://explorer.celo.org/mainnet']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
},
{
type: 'evmscan',
gastrackerSupport: false,
servers: ['https://explorer.celo.org/mainnet/api'],
version: 1
}
],
uriNetworks: ['celo'],
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/ethereumInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1173,7 +1173,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
},
{
type: 'blockbook',
Expand Down
10 changes: 3 additions & 7 deletions src/ethereum/info/ethereumclassicInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,14 @@ const networkInfo: EthereumNetworkInfo = {
networkAdapterConfigs: [
{
type: 'rpc',
servers: [
'https://etc.rivet.link',
'https://geth-de.etc-network.info',
'https://geth-at.etc-network.info',
'https://etc.etcdesktop.com'
],
servers: ['https://etc.rivet.link', 'https://etc.etcdesktop.com'],
ethBalCheckerContract: '0xfC701A6b65e1BcF59fb3BDbbe5cb41f35FC7E009'
},
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://etc.blockscout.com']
servers: ['https://etc.blockscout.com/api'],
version: 1
},
{
type: 'blockbook',
Expand Down
7 changes: 0 additions & 7 deletions src/ethereum/info/ethereumpowInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,6 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'rpc',
servers: ['https://mainnet.ethereumpow.org']
},
{
type: 'evmscan',
gastrackerSupport: true,
servers: [
// TODO:
]
}
],

Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/fantomInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: false,
servers: ['https://ftmscout.com/']
servers: ['https://ftmscout.com/api'],
version: 1
}
],
uriNetworks: ['fantom'],
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/holeskyInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
}
],

Expand Down
8 changes: 5 additions & 3 deletions src/ethereum/info/hyperEvmInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,16 @@ const networkInfo: EthereumNetworkInfo = {
servers: [
'https://rpc.hyperliquid.xyz/evm',
'https://rpc.hypurrscan.io',
'https://hyperliquid-json-rpc.stakely.io',
'https://hyperliquid-json-rpc.stakely.io'
'https://rpc.hyperlend.finance'
]
},
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.routescan.io/v2/network/mainnet/evm/999/etherscan']
servers: [
'https://api.routescan.io/v2/network/mainnet/evm/999/etherscan/api'
],
version: 1
}
],
uriNetworks: [],
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/optimismInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
}
],
uriNetworks: ['optimism'],
Expand Down
6 changes: 2 additions & 4 deletions src/ethereum/info/polygonInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,6 @@ const networkInfo: EthereumNetworkInfo = {
type: 'rpc',
servers: [
'https://polygon-rpc.com/',
'https://rpc.polycat.finance',
'https://rpc-mainnet.maticvigil.com',
'https://matic-mainnet.chainstacklabs.com',
'https://rpc.ankr.com/polygon',
'https://poly.api.pocket.network',
'https://rpc-mainnet.matic.quiknode.pro/{{quiknodeApiKey}}/',
Expand All @@ -198,7 +195,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: true,
servers: ['https://api.etherscan.io', 'https://api.polygonscan.com']
servers: ['https://api.etherscan.io/v2/api'],
version: 2
}
],
uriNetworks: ['polygon'],
Expand Down
3 changes: 2 additions & 1 deletion src/ethereum/info/pulsechainInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ const networkInfo: EthereumNetworkInfo = {
{
type: 'evmscan',
gastrackerSupport: false,
servers: ['https://api.scan.pulsechain.com']
servers: ['https://api.scan.pulsechain.com/api'],
version: 1
},
{
type: 'pulsechain-scan',
Expand Down
Loading
Loading