--- title: Examples --- # Examples Practical, copy-pasteable snippets for the most common tasks. Every call returns a promise resolving to an {@link EtherscanResponse} whose `result` is typed per endpoint. ## Creating a client ```ts import { init } from 'etherscan-api'; // Ethereum mainnet (default) const api = init('YourApiKey'); // A testnet or L2, by name… const sepolia = init('YourApiKey', 'sepolia'); const arbitrum = init('YourApiKey', 'arbitrum'); // …or by numeric chainid (works for any of Etherscan's 60+ chains) const linea = init('YourApiKey', 59144); // With a custom timeout (ms) const slow = init('YourApiKey', 'mainnet', 30_000); // …or everything as one options object, including the transport limits const custom = init({ apiKey: 'YourApiKey', chain: 'base', timeout: 30_000, maxResponseBytes: 200 * 1024 * 1024 }); ``` Retired testnets throw immediately rather than silently hitting mainnet: ```ts init('YourApiKey', 'goerli'); // Error: Chain "goerli" is no longer supported: Goerli was deprecated; // use Sepolia or Hoodi. ... ``` ## Accounts ```ts // Single balance — result is a string (wei) const { result: wei } = await api.account.balance( '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae', ); // Multiple balances — pass an array → result is { account, balance }[] const multi = await api.account.balance([ '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae', '0x63a9975ba31b0b9626b34300f7f627147df1f526', ]); // Normal transactions — result is NormalTransaction[]. List endpoints take an // options object (block range, page, offset, sort, filter); all fields optional. const txs = await api.account.txlist('0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae', { page: 1, offset: 100, sort: 'desc', }); for (const tx of txs.result ?? []) { console.log(tx.hash, tx.from, '→', tx.to, tx.value); } // ERC-20 transfers for an address (optionally filtered by token) const transfers = await api.account.tokentx('0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae', { contractaddress: '0x6b175474e89094c44da98b954eedeac495271d0f', // DAI }); ``` ## Stats, gas & prices ```ts // Typed result: EthPrice const price = await api.stats.ethprice(); console.log(price.result?.ethusd); // Typed result: GasOracle const gas = await api.gastracker.gasoracle(); console.log('propose gas (gwei):', gas.result?.ProposeGasPrice); // Estimated confirmation time (seconds) for a given gas price (wei) const eta = await api.gastracker.gasestimate(2_000_000_000); ``` ## Proxy (JSON-RPC) ```ts const block = await api.proxy.eth_blockNumber(); // result: hex string const gasPrice = await api.proxy.eth_gasPrice(); // result: hex string const receipt = await api.proxy.eth_getTransactionReceipt( '0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1', ); ``` ## Event logs ```ts const logs = await api.log.getLogs({ address: '0x33990122638b9132ca29c723bdf037f1c891a925', fromBlock: 379224, toBlock: 400000, topic0: '0xf63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a8545', }); ``` ## Contracts ```ts // ABI (JSON encoded as a string) and source for a verified contract const abi = await api.contract.getabi('0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413'); const src = await api.contract.getsourcecode('0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413'); console.log(src.result?.[0]?.ContractName); // Who created a contract, and in which tx const creation = await api.contract.getcontractcreation( '0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413', ); ``` ### Verifying a contract (POST + poll) ```ts import { EtherscanError } from 'etherscan-api'; const submit = await api.contract.verifysourcecode({ contractaddress: '0xabc...', sourceCode: '// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24; contract C {}', codeformat: 'solidity-single-file', contractname: 'C', compilerversion: 'v0.8.24+commit.e11b9ed9', optimizationUsed: 1, runs: 200, }); const guid = submit.result; // string GUID if (!guid) throw new Error('Etherscan returned no verification GUID'); // Etherscan reports every state except "Pass - Verified" with status "0", so // "Pending in queue" and "Fail - …" reject with an EtherscanError whose // `result` holds the status text. Read it from there. async function verificationStatus(guid: string): Promise { try { return (await api.contract.checkverifystatus(guid)).result ?? ''; } catch (err) { if (err instanceof EtherscanError && typeof err.result === 'string') { return err.result; } throw err; } } // Poll until done let status = await verificationStatus(guid); while (status === 'Pending in queue') { await new Promise((r) => setTimeout(r, 5000)); status = await verificationStatus(guid); } console.log(status); // 'Pass - Verified' | 'Fail - Unable to verify' | … ``` ## Error handling Logical API failures reject with an {@link EtherscanError} (a subclass of `Error`): ```ts import { EtherscanError } from 'etherscan-api'; try { await api.contract.getabi('0xNotVerified...'); } catch (err) { if (err instanceof EtherscanError) { console.error(err.message); // e.g. "Contract source code not verified" console.error(err.status); // raw API status, when present } } ``` When Etherscan answers with a non-2xx HTTP status (a 429 rate limit, a 5xx), the default transport rejects with an {@link EtherscanHttpError}. It is a subclass of `EtherscanError`, so the check above catches it too, and it adds the `statusCode` and response `headers` needed for backoff. A rate limit can arrive either way, as a 200 with `status: "0"` or as a 429: ```ts import { EtherscanError, EtherscanHttpError } from 'etherscan-api'; try { await api.stats.ethsupply(); } catch (err) { if (err instanceof EtherscanHttpError && err.statusCode === 429) { const retryAfter = Number(err.headers['retry-after'] ?? 1); // seconds console.error(`rate limited, retry in ${retryAfter}s`); } else if (err instanceof EtherscanError) { console.error(err.message); } } ``` An **empty** result (e.g. an address with no transactions) is **not** an error — Etherscan reports it as `status: "0"`, but the client resolves it with an empty array: ```ts const res = await api.account.txlist('0xAddressWithNoHistory...'); res.result; // [] — resolved, not thrown ``` ## Custom HTTP transport The library has no runtime dependencies — requests use Node's built-in `https`. To use your own networking (a proxy, retries, `fetch`), pass a transport as the 4th argument. `method`/`body` are only set for the POST verification endpoints. ```ts import { init, type Transport } from 'etherscan-api'; const request: Transport = async (url, { timeout, method = 'GET', body } = {}) => { const res = await fetch(url, { method, body, headers: body ? { 'Content-Type': 'application/x-www-form-urlencoded' } : undefined, signal: AbortSignal.timeout(timeout ?? 10_000), }); // fetch resolves on any HTTP status; surface non-2xx as an error. if (!res.ok) throw new Error(`Request failed with status code ${res.status}`); return res.json(); }; const api = init('YourApiKey', 'mainnet', 10_000, request); ``` ## Utilities ```ts // Live list of supported chains and their chainids (the request carries no // API key, though init() still needs one to create the client) const chains = await api.usage.chainlist(); // Your API key's usage and daily limit const limit = await api.usage.getapilimit(); // Resolve a chain name to its id without creating a client import { resolveChainId } from 'etherscan-api'; resolveChainId('base'); // 8453 ```