11import { type Address } from 'viem' ;
2+ import { resolveChainId , getSupportedNetworks } from '../chains.js' ;
23
34/**
4- * Fetch contract ABI from Etherscan API
5+ * Fetch contract ABI from Etherscan v2 API (unified endpoint for all EVM chains)
56 * Requires ETHERSCAN_API_KEY environment variable to be set
67 *
78 * @param contractAddress The contract address to fetch ABI for
8- * @param network The network to use (etherscan, polygonscan, etc.)
9+ * @param network The network name or chain ID
910 * @returns The contract ABI as a JSON string
1011 */
1112export async function fetchContractABI (
@@ -14,35 +15,25 @@ export async function fetchContractABI(
1415) : Promise < string > {
1516 const apiKey = process . env . ETHERSCAN_API_KEY ;
1617 if ( ! apiKey ) {
17- throw new Error ( 'ETHERSCAN_API_KEY environment variable is not set. Set it to fetch contract ABIs.' ) ;
18+ throw new Error ( 'ETHERSCAN_API_KEY environment variable is not set. Set it to fetch contract ABIs from block explorers .' ) ;
1819 }
1920
20- // Map network names to Etherscan-compatible API domains
21- const networkMap : { [ key : string ] : string } = {
22- 'ethereum' : 'https://api.etherscan.io' ,
23- 'sepolia' : 'https://api-sepolia.etherscan.io' ,
24- 'polygon' : 'https://api.polygonscan.com' ,
25- 'mumbai' : 'https://api-testnet.polygonscan.com' ,
26- 'arbitrum' : 'https://api.arbiscan.io' ,
27- 'arbitrum-sepolia' : 'https://api-sepolia.arbiscan.io' ,
28- 'optimism' : 'https://api-optimistic.etherscan.io' ,
29- 'optimism-sepolia' : 'https://api-sepolia-optimistic.etherscan.io' ,
30- 'base' : 'https://api.basescan.org' ,
31- 'base-sepolia' : 'https://api-sepolia.basescan.org' ,
32- 'avalanche' : 'https://api.snowtrace.io' ,
33- 'avalanche-fuji' : 'https://api-testnet.snowtrace.io' ,
34- } ;
35-
36- const apiUrl = networkMap [ network . toLowerCase ( ) ] ;
37- if ( ! apiUrl ) {
38- throw new Error ( `Network "${ network } " is not supported for ABI fetching. Supported: ${ Object . keys ( networkMap ) . join ( ', ' ) } ` ) ;
21+ // Resolve chain ID using the chains.ts utilities
22+ let chainId : number ;
23+ try {
24+ chainId = resolveChainId ( network ) ;
25+ } catch ( error ) {
26+ const supported = getSupportedNetworks ( ) ;
27+ throw new Error ( `Network "${ network } " is not supported. Supported: ${ supported . join ( ', ' ) } ` ) ;
3928 }
4029
4130 try {
42- const url = new URL ( `${ apiUrl } /api` ) ;
31+ // Use unified Etherscan v2 API endpoint
32+ const url = new URL ( 'https://api.etherscan.io/v2/api' ) ;
4333 url . searchParams . set ( 'module' , 'contract' ) ;
4434 url . searchParams . set ( 'action' , 'getabi' ) ;
4535 url . searchParams . set ( 'address' , contractAddress ) ;
36+ url . searchParams . set ( 'chainid' , chainId . toString ( ) ) ;
4637 url . searchParams . set ( 'apikey' , apiKey ) ;
4738
4839 const response = await fetch ( url . toString ( ) ) ;
0 commit comments