chain
Documentation for eth_defi.chain Python module.
Chain specific configuration.
Many chains like Polygon and BNB Chain may need their own Web3 connection tuning. In this module, we have helpers.
Module Attributes
List of chain ids that need to have proof-of-authority middleweare installed |
|
Known testnet chain IDs — used to guard operations that should never be retried or relaxed on mainnets (e.g. |
|
L2 sequencer and official public RPC endpoints. |
|
Manually maintained shorthand names for different EVM chains |
|
For linking on reports |
|
Chain shortest block times in seconds. |
Functions
|
Get the block mined at timestamp. |
|
Get average block time for a chain. |
|
Translate Ethereum chain id to a link to its homepage. |
|
Get chain id by its name. |
|
Translate Ethereum chain id to its name. |
|
Get the eth_call reasonable gas limit. |
|
Resolve potential GraphQL endpoint API for a JSON-RPC provider. |
|
Check if a node has GoEthereum GraphQL API turned on. |
Install API call counter middleware. |
|
Install API call counter middleware on a specific API provider. |
|
|
Install any chain-specific middleware to Web3 instance. |
|
Install gracefully HTTP request retry middleware. |
|
- POA_MIDDLEWARE_NEEDED_CHAIN_IDS = {56, 137, 43114}
List of chain ids that need to have proof-of-authority middleweare installed
- TESTNET_CHAIN_IDS: set[int] = {998, 84532, 421614, 11155111}
Known testnet chain IDs — used to guard operations that should never be retried or relaxed on mainnets (e.g. forge deploy retries).
- SEQUENCERS: dict[int, dict[str, str]] = {10: {'public_rpc': 'https://mainnet.optimism.io', 'sequencer': 'https://mainnet-sequencer.optimism.io'}, 8453: {'public_rpc': 'https://mainnet.base.org', 'sequencer': 'https://mainnet-sequencer.base.org'}, 42161: {'public_rpc': 'https://arb1.arbitrum.io/rpc', 'sequencer': 'https://arb1-sequencer.arbitrum.io/rpc'}, 84532: {'public_rpc': 'https://sepolia.base.org', 'sequencer': 'https://sepolia-sequencer.base.org'}, 421614: {'public_rpc': 'https://sepolia-rollup.arbitrum.io/rpc', 'sequencer': 'https://sepolia-rollup-sequencer.arbitrum.io/rpc'}, 11155420: {'public_rpc': 'https://sepolia.optimism.io', 'sequencer': 'https://sepolia-sequencer.optimism.io'}}
L2 sequencer and official public RPC endpoints.
Many L2 chains have a centralised sequencer that processes transactions. Broadcasting directly to the sequencer (or the chain’s official single-endpoint public RPC) avoids issues with load-balanced RPCs like drpc.live where different backend nodes may return inconsistent state.
Each entry maps a chain ID to a dict with:
sequencer: write-only endpoint foreth_sendRawTransaction. Arbitrum sequencers only supporteth_sendRawTransaction(no reads: noeth_chainId,eth_getTransactionReceipt, etc.). OP Stack sequencers (Base, Optimism) run a fullop-gethbut may return 403 on read calls under load. Use with themev+prefix increate_multi_provider_web3().public_rpc: official single-endpoint RPC that supports both reads and writes. Suitable forforge createwhich needseth_chainId,eth_gasPrice,eth_getTransactionReceiptetc. These avoid the receipt-polling issue on load-balanced providers (seeforge.pydocstring on foundry#1362).
Sources:
- CHAIN_NAMES = {1: 'Ethereum', 10: 'Optimism', 56: 'Binance', 100: 'Gnosis', 130: 'Unichain', 137: 'Polygon', 143: 'Monad', 146: 'Sonic', 239: 'TAC', 324: 'ZKsync', 325: 'Grvt', 957: 'Derive', 998: 'Hyperliquid_Testnet', 999: 'Hyperliquid', 1868: 'Soneium', 2741: 'Abstract', 5000: 'Mantle', 8453: 'Base', 9745: 'Plasma', 9998: 'Lighter', 9999: 'Hypercore', 34443: 'Mode', 42161: 'Arbitrum', 42220: 'Celo', 43111: 'Hemi', 43114: 'Avalanche', 57073: 'Ink', 59144: 'Linea', 80094: 'Berachain', 81457: 'Blast', 84532: 'Base_Sepolia', 421614: 'Arbitrum_Sepolia', 645749: 'Hyperliquid_Legacy', 747474: 'Katana', 7777777: 'Zora', 11155111: 'Ethereum_Sepolia'}
Manually maintained shorthand names for different EVM chains
- CHAIN_HOMEPAGES = {1: {'homepage': 'https://ethereum.org', 'name': 'Ethereum'}, 10: {'homepage': 'https://www.optimism.io', 'name': 'Optimism'}, 56: {'homepage': 'https://www.bnbchain.org', 'name': 'Binance'}, 100: {'homepage': 'https://www.gnosis.io', 'name': 'Gnosis'}, 130: {'homepage': 'https://www.uniswap.org/unichain', 'name': 'Unichain'}, 137: {'homepage': 'https://polygon.technology', 'name': 'Polygon'}, 143: {'homepage': 'https://monad.xyz', 'name': 'Monad'}, 146: {'homepage': 'https://www.soniclabs.com/', 'name': 'Sonic'}, 239: {'homepage': 'https://tac.build/', 'name': 'TAC'}, 324: {'homepage': 'https://zksync.io', 'name': 'ZKsync'}, 325: {'homepage': 'https://grvt.io', 'name': 'GRVT'}, 957: {'homepage': 'https://derive.xyz', 'name': 'Derive'}, 998: {'homepage': 'https://hyperliquid.xyz', 'name': 'Hyperliquid Testnet'}, 999: {'homepage': 'https://hyperliquid.xyz', 'name': 'Hyperliquid'}, 1868: {'homepage': 'https://www.soneium.org', 'name': 'Soneium'}, 2741: {'homepage': 'https://www.abstract.foundation', 'name': 'Abstract'}, 5000: {'homepage': 'https://www.mantle.xyz', 'name': 'Mantle'}, 8453: {'homepage': 'https://www.base.org', 'name': 'Base'}, 9745: {'homepage': 'https://www.plasma.to/', 'name': 'Plasma'}, 9998: {'homepage': 'https://lighter.xyz', 'name': 'Lighter'}, 9999: {'homepage': 'https://hyperliquid.xyz', 'name': 'Hyperliquid'}, 34443: {'homepage': 'https://www.mode.network', 'name': 'Mode'}, 42161: {'homepage': 'https://arbitrum.io', 'name': 'Arbitrum'}, 42220: {'homepage': 'https://celo.org', 'name': 'Celo'}, 43111: {'homepage': 'https://hemi.xyz/', 'name': 'Hemi'}, 43114: {'homepage': 'https://www.avax.network', 'name': 'Avalanche'}, 57073: {'homepage': 'https://inkonchain.com/', 'name': 'Ink'}, 59144: {'homepage': 'https://linea.build/', 'name': 'Linea'}, 80094: {'homepage': 'https://www.berachain.com', 'name': 'Berachain'}, 81457: {'homepage': 'https://blast.io', 'name': 'Blast'}, 84532: {'homepage': 'https://www.base.org', 'name': 'Base Sepolia'}, 421614: {'homepage': 'https://arbitrum.io', 'name': 'Arbitrum Sepolia'}, 645749: {'homepage': 'https://hyperliquid.xyz', 'name': 'Hyperliquid'}, 747474: {'homepage': 'https://katana.network/', 'name': 'Katana'}, 7777777: {'homepage': 'https://zora.co', 'name': 'Zora'}, 11155111: {'homepage': 'https://ethereum.org', 'name': 'Ethereum Sepolia'}}
For linking on reports
- EVM_BLOCK_TIMES = {1: 12, 10: 2, 56: 3, 100: 5, 130: 1, 137: 2, 143: 0.4, 146: 1, 239: 1.5, 324: 1, 957: 2, 998: 1, 999: 1, 1868: 2, 2741: 2, 5000: 2, 8453: 2, 9745: 1, 34443: 2, 42161: 0.25, 42220: 5, 43111: 12, 43114: 2, 57073: 2, 59144: 2, 80094: 1, 81457: 2, 84532: 2, 421614: 0.25, 645749: 1, 747474: 1, 7777777: 2, 11155111: 12}
Chain shortest block times in seconds.
Used to convert between block ranges and wall-clock durations. For chains with multiple block types (e.g. HyperEVM dual-block architecture), we use the shortest block time so that block-range → time estimates are accurate.
Note that for many chains these are approximate and can vary based on network conditions and upgrades.
- get_chain_homepage(chain_id)
Translate Ethereum chain id to a link to its homepage.
- get_chain_name(chain_id)
Translate Ethereum chain id to its name.
- get_chain_id_by_name(name)
Get chain id by its name.
- get_block_time(chain_id)
Get average block time for a chain.
- get_default_call_gas_limit(chain_id)
Get the eth_call reasonable gas limit.
15M except for Mantle 99M
Mantle has weird policy and all transactions and calls cost much more than other chains
- install_chain_middleware(web3, poa_middleware=None, hint='')
Install any chain-specific middleware to Web3 instance.
Mainly this is POA middleware for BNB Chain, Polygon, Avalanche C-chain.
Example:
web3 = Web3(HTTPProvider(json_rpc_url)) print(f"Connected to blockchain, chain id is {web3.eth.chain_id}. the latest block is {web3.eth.block_number:,}") # Read and setup a local private key private_key = os.environ.get("PRIVATE_KEY") assert private_key is not None, "You must set PRIVATE_KEY environment variable" assert private_key.startswith("0x"), "Private key must start with 0x hex prefix" account: LocalAccount = Account.from_key(private_key) web3.middleware_onion.add(construct_sign_and_send_raw_middleware(account)) # Support Polygon, BNG chain install_chain_middleware(web3) # ... code goes here...z tx_hash = erc_20.functions.transfer(to_address, raw_amount).transact({"from": account.address})
- Parameters
poa_middleware –
If set, force the installation of proof-of-authority GoEthereum middleware.
Needed e.g. when using forked Polygon with Anvil.
hint (str) – Optional hint for error logs when something goes wrong. Useful for debugging and logging.
web3 (web3.main.Web3) –
- install_retry_middleware(web3)
Install gracefully HTTP request retry middleware.
In the case your Internet connection or JSON-RPC node has issues, gracefully do exponential backoff retries.
- Parameters
web3 (web3.main.Web3) –
- install_api_call_counter_middleware(web3)
Install API call counter middleware.
Measure total and per-API EVM call counts for your application.
Every time a Web3 API is called increase its count.
Attach web3.api_counter object to the connection
Compatible with both web3.py v6 and v7.
Example:
from eth_defi.chain import install_api_call_counter_middleware web3 = Web3(tester) counter = install_api_call_counter_middleware(web3) # Make an API call chain_id = web3.eth.chain_id assert counter["total"] == 1 assert counter["eth_chainId"] == 1 # Make another API call block_number = web3.eth.block_number assert counter["total"] == 2 assert counter["eth_blockNumber"] == 1
- Returns
Counter object with columns per RPC endpoint and “total”
- Parameters
web3 (web3.main.Web3) –
- Return type
- install_api_call_counter_middleware_on_provider(provider)
Install API call counter middleware on a specific API provider.
Allows per-provider API call counting when using complex provider setups.
Compatible with both web3.py v6 and v7.
See also
eth_defi.fallback_provider.FallbackProvider
- Returns
Counter object with columns per RPC endpoint and “total”
- Parameters
provider (web3.providers.base.JSONBaseProvider) –
- Return type
- get_graphql_url(provider)
Resolve potential GraphQL endpoint API for a JSON-RPC provider.
- Parameters
provider (web3.providers.base.BaseProvider) –
- Return type
- has_graphql_support(provider)
Check if a node has GoEthereum GraphQL API turned on.
You can check if GraphQL has been turned on for your node with:
curl -X POST https://mynode.example.com/graphql -H "Content-Type: application/json" --data '{ "query": "query { block { number } }" }'
A valid response looks like:
{"data":{"block":{"number":16328259}}}- Parameters
provider (web3.providers.base.BaseProvider) –
- Return type
- fetch_block_timestamp(web3, block_number)
Get the block mined at timestamp.
Warning
Uses eth_getBlock. Very slow for large number of blocks. Use alternative methods for managing timestamps for large block ranges.
Example:
# Get when the first block was mined timestamp = fetch_block_timestamp(web3, 1) print(timestamp)
- Parameters
web3 (web3.main.Web3) – Web3 connection
block_number (int) – Block number of which timestamp we are going to get
- Returns
UTC naive datetime of the block timestamp
- Return type