provider.broken_provider

Documentation for eth_defi.provider.broken_provider Python module.

Fixes and workaronds for various JSON-RPC service providers.

  • Mainly to deal with unstable blockchain chain tip

See also

Functions

get_almost_latest_block_number(web3)

Get the latest block number with workarounds for low quality JSON-RPC service providers.

get_block_tip_latency(web3)

What block tip latency we should use for this JSON-RPC provider

get_default_block_tip_latency(web3)

Workaround for Ankr and other node providers that do not handle the chain tip properly.

get_fork_safe_latest_block(web3)

Get the latest block identifier that is safe for Anvil mainnet forks.

get_safe_cached_latest_block_number(web3, ...)

Get almost "latest" block to work around broken JSON-RPC providers.

set_block_tip_latency(web3, block_count)

Override the default block tip latency settings.

verify_archive_node(rpc_url, chain_name)

Verify RPC providers and filter out broken ones.

Exceptions

BlockNumberOutOfRange

Raised when the RPC returns a block number that is impossibly far from the last known block.

exception BlockNumberOutOfRange

Bases: Exception

Raised when the RPC returns a block number that is impossibly far from the last known block.

This typically happens when a fallback provider switches to a misconfigured endpoint or the RPC backend routes the request to the wrong chain after a transient error.

__init__(*args, **kwargs)
__new__(**kwargs)
add_note(note, /)

Add a note to the exception

with_traceback(tb, /)

Set self.__traceback__ to tb and return self.

get_almost_latest_block_number(web3)

Get the latest block number with workarounds for low quality JSON-RPC service providers.

Use this method instead of web3.eth.block_number.

Because low quality providers may lose the block of this block number on the subsequent API calls, we add some number of delay or confirmations to the chain tip, specified by get_block_tip_latency().

Includes a monotonicity safety check: if the block number drops by more than MAX_BLOCK_REGRESSION blocks compared to the last observed value, raises BlockNumberOutOfRange. This catches scenarios where the RPC provider silently starts returning data for the wrong chain after a failover.

Providers with known issues

  • LlamaNodes

  • Ankr

Example:

from eth_defi.provider.broken_provider import get_almost_latest_block_number

# We cannot query the chain head on Ankr or LlamaNodes,
# so get the almost head
if not block_number:
    block_number = get_almost_latest_block_number(web3)

timestamp = fetch_block_timestamp(web3, block_number)

token = fetch_erc20_details(web3, asset.address)
amount = token.fetch_balance_of(address, block_identifier=block_number)
Raises

BlockNumberOutOfRange – If the block number regresses by more than MAX_BLOCK_REGRESSION.

Parameters

web3 (web3.main.Web3) –

Return type

int

get_block_tip_latency(web3)

What block tip latency we should use for this JSON-RPC provider

  • Defaults to zero

  • If using eth_defi.provider.fallback.FallbackProvider we use 4 blocks latency as multiple providers are unlikely to agree on a chain tip (blocks have not propagated yet).

  • We have some built-in rules to work out specific providers

  • You can override this by setting the latency sa web3.block_tip_latency attribute

See the source code of get_default_block_tip_latency() for other rules.

Parameters

web3 (web3.main.Web3) –

Return type

int

get_default_block_tip_latency(web3)

Workaround for Ankr and other node providers that do not handle the chain tip properly.

Likely due to how requests are broken a block number available in one call disappears in the following. Thus, with broken JSON-RPC service providers we cannot trust web3.eth.block_number to work and we need to subtract this number from it.

See get_block_tip_latency()

Returns

Number of blocks we need to subtract from the latest block

Parameters

web3 (web3.main.Web3) –

Return type

int

get_fork_safe_latest_block(web3)

Get the latest block identifier that is safe for Anvil mainnet forks.

  • For Anvil mainnet forks, returns web3.eth.block_number (an integer) instead of "latest" to prevent the upstream RPC from resolving "latest" to the actual chain tip (which may be beyond the fork block or the upstream’s available window).

  • For non-fork Anvil (test backend), returns "latest" as there is no upstream RPC.

  • For non-Anvil providers, returns "latest".

This is needed because web3.py v7 forwards "latest" to the upstream RPC when Anvil needs to fetch state not cached at fork time. The upstream then resolves "latest" to its own chain tip, causing BlockOutOfRangeError if the upstream has a limited block window.

See get_safe_cached_latest_block_number() which uses this function.

Parameters

web3 (web3.main.Web3) –

Return type

Union[Literal[‘latest’, ‘earliest’, ‘pending’, ‘safe’, ‘finalized’], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]

get_safe_cached_latest_block_number(web3, chain_id, blocks=1000, cache_duration=3600)

Get almost “latest” block to work around broken JSON-RPC providers.

  • Not for high frequency usage, as it caches the block for delay seconds

  • No RPC call are made to

  • Disabled in Anvil configs

Work around the error on Monad/Arbitrum/dRPC/shitty RPCs:

{'message': 'upstream does not have the requested block yet', 'code': -32603}

Their internal routing is likely broken and when calling eth_call with latest the request fails for no reason.

Parameters
  • chain_id (int) – Chain id to use as part of the cache key

  • blocks – Number of blocks to subtract from the latest block

  • cache_duration (int) – Number of seconds to cache the result

  • web3 (web3.main.Web3) –

Returns

Latest block number minus blocks.

May return “latest” for special configs like unit tests.

Return type

Union[Literal[‘latest’, ‘earliest’, ‘pending’, ‘safe’, ‘finalized’], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]

set_block_tip_latency(web3, block_count)

Override the default block tip latency settings.

Useful for unit testing, because unit testing assumes stuff has happened in the latest block you want to read.

See get_block_tip_latency().

Parameters
  • web3 (web3.main.Web3) –

  • block_count (int) –

verify_archive_node(rpc_url, chain_name)

Verify RPC providers and filter out broken ones.

Parses the space-separated multi-RPC configuration line and tests each endpoint individually. Checks that each provider can serve both block 1 and the latest block. Broken providers are logged at ERROR level and filtered out; the scan continues with working providers only.

Parameters
  • rpc_url (str) – RPC URL configuration line (may contain space-separated fallbacks, mev+ prefixed endpoints are skipped)

  • chain_name (str) – Chain name for logging

Returns

Tuple of (filtered RPC URL with only working providers, latest block number)

Raises

RuntimeError – If all providers fail verification

Return type

tuple[str, int]