token
Documentation for eth_defi.token Python module.
ERC-20 token deployment and manipulation.
Deploy ERC-20 tokens to be used within your test suite.
Read also unit test suite for tokens to see how ERC-20 can be manipulated in pytest.
Module Attributes
Addresses of wrapped native token (WETH9) of different chains |
|
Addresses of USDC of different chains |
|
Bridged USDC of different chains |
|
Used in fork testing |
|
Used in fork testing |
|
Addresses USDT Tether of different chains |
|
Sky (MakerDAO) new tokens |
|
Berachain 0xFCBD14DC51f0A4d49d5E53C2E0950e0bC26d0Dce https://docs.berachain.com/learn/pol/tokens/honey |
|
Token symbols that are stablecoin like. |
|
Stablecoins which can be used as collateral, but which also have built-in yield bearing function with rebasing. |
|
Stablecoins plus their interest wrapped counterparts on Compound and Aave. |
|
All stablecoin likes - both interested bearing and non interest bearing. |
|
Some test accounts with funded USDC for Anvil mainnet forking |
Functions
|
Deploys a new ERC-20 token on local dev, testnet or mainnet. |
|
Read token details from on-chain data. |
|
Get all good quote tokens on chain. |
|
Get all good known stablecoins on a chain. |
|
Wrap address as ERC-20 standard interface. |
|
Get WETH9 contract for the chain |
|
|
|
Check if specific token symbol is likely a stablecoin. |
|
Normalise token symbol for stablecoin detection. |
Purge the cached token data. |
Classes
Contract placeholder making contract references pickable |
|
ERC-20 token Python presentation. |
|
Token cache that stores tokens in disk. |
Exceptions
Cannot extract token details for an ERC-20 token for some reason. |
- DEFAULT_TOKEN_CACHE = LRUCache({}, maxsize=1024, currsize=0)
By default we cache 1024 token details using LRU in the process memory.
- TokenAddress
ERC-20 address, 0x prefixed string
- WRAPPED_NATIVE_TOKEN: dict[int, Union[eth_typing.evm.HexAddress, str]] = {1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 56: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', 957: '0x4200000000000000000000000000000000000006', 8453: '0x4200000000000000000000000000000000000006', 42161: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', 43114: '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7', 421614: '0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9'}
Addresses of wrapped native token (WETH9) of different chains
- USDC_NATIVE_TOKEN: dict[int, Union[eth_typing.evm.HexAddress, str]] = {1: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 56: '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', 957: '0x6879287835A86F50f784313dBEd5E5cCC5bb8481', 8453: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', 42161: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', 43114: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', 421614: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d'}
Addresses of USDC of different chains
- BRIDGED_USDC_TOKEN: dict[int, Union[eth_typing.evm.HexAddress, str]] = {42161: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8'}
Bridged USDC of different chains
- USDC_WHALE: dict[int, Union[eth_typing.evm.HexAddress, str]] = {8453: '0x40EbC1Ac8d4Fedd2E144b75fe9C0420BE82750c6', 42161: '0x3DD1D15b3c78d6aCFD75a254e857Cbe5b9fF0aF2'}
Used in fork testing
- USDT_WHALE: dict[int, Union[eth_typing.evm.HexAddress, str]] = {56: '0x128463A60784c4D3f46c23Af3f65Ed859Ba87974', 42161: '0x9E36CB86a159d479cEd94Fa05036f235Ac40E1d5'}
Used in fork testing
- USDT_NATIVE_TOKEN: dict[int, eth_typing.evm.HexAddress] = {1: '0xdAC17F958D2ee523a2206206994597C13D831ec7', 56: '0x55d398326f99059fF775485246999027B3197955', 42161: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', 43114: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7'}
Addresses USDT Tether of different chains
- SUSDS_NATIVE_TOKEN: dict[int, eth_typing.evm.HexAddress] = {8453: '0x5875eEE11Cf8398102FdAd704C9E96607675467a'}
Sky (MakerDAO) new tokens
- HONEY_NATIVE_TOKEN: dict[int, eth_typing.evm.HexAddress] = {80094: '0xFCBD14DC51f0A4d49d5E53C2E0950e0bC26d0Dce'}
Berachain 0xFCBD14DC51f0A4d49d5E53C2E0950e0bC26d0Dce https://docs.berachain.com/learn/pol/tokens/honey
- STABLECOIN_LIKE = {'ALUSD', 'AUDT', 'AUSD', 'BAC', 'BDO', 'BEAN', 'BOB', 'BOLD', 'BUSD', 'BYUSD', 'CADC', 'CEUR', 'CJPY', 'CNHT', 'CRVUSD', 'CUSD', 'DAI', 'DJED', 'DOLADUSD', 'EOSDT', 'EURA', 'EURCV', 'EUROC', 'EUROe', 'EURS', 'EURT', 'EURe', 'EUSD', 'FDUSD', 'FEI', 'FLEXUSD', 'FUSD', 'FXD', 'FXUSD', 'GBPT', 'GHO', 'GHST', 'GUSD', 'GYD', 'GYEN', 'HAI', 'HUSD', 'IRON', 'JCHF', 'JPYC', 'KDAI', 'LISUSD', 'LUSD', 'MIM', 'MIMATIC', 'MKUSD', 'MTUSD', 'MUSD', 'ONC', 'OUSD', 'PAR', 'PAXG', 'PYUSD', 'RAI', 'RLUSD', 'RUSD', 'SAI', 'SDAI', 'SEUR', 'SFRAX', 'SILK', 'STUSD', 'SUSD', 'TCNH', 'TOR', 'TRYB', 'TUSD', 'USC', 'USD+', 'USD0', 'USD1', 'USD8', 'USDA', 'USDB', 'USDC', 'USDC.e', 'USDCV', 'USDD', 'USDE', 'USDF', 'USDH', 'USDHLUSDG', 'USDM', 'USDN', 'USDO', 'USDP', 'USDR', 'USDS', 'USDT', 'USDT.e', 'USDT0', 'USDV', 'USDX', 'USDXL', 'USDai', 'USDbC', 'USDe', 'USDf', 'USDs', 'USDt', 'USDtb', 'USD₮', 'USD₮0', 'USH', 'USK', 'USR', 'UST', 'USTC', 'USX', 'USXAU', 'UTY', 'UUSD', 'VAI', 'VEUR', 'VST', 'VUSD', 'WXDAI', 'XAUT', 'XDAI', 'XIDR', 'XSGD', 'XSTUSD', 'XUSD', 'YUSD', 'ZCHF', 'ZSD', 'ZUSD', 'avUSD', 'bvUSD', 'crvUSD', 'csUSD', 'dUSD', 'deUSD', 'feUSD', 'frxUSD', 'ftUSD', 'gmUSD', 'iUSD', 'jEUR', 'kUSD', 'lvlUSD', 'mUSD', 'meUSDT', 'msUSD', 'mtUSDC', 'mtUSDT', 'plUSD', 'reUSD', 'sUSDC', 'satUSD', 'scUSD', 'sosUSDT', 'vbUSDC', 'vbUSDT', 'wM', 'xUSD', 'ysUSDC'}
Token symbols that are stablecoin like. Note that it is not safe to to check the token symbol to know if a token is a specific stablecoin, but you always need to check the contract address. Checking against this list only works USDf and USDF
- YIELD_BEARING_STABLES = {'sAUSD', 'sBOLD', 'sUSDai', 'sUSDe', 'sfrxUSD', 'ynUSDx'}
Stablecoins which can be used as collateral, but which also have built-in yield bearing function with rebasing.
- WRAPPED_STABLECOIN_LIKE = {'aDAI', 'agEUR', 'alUSD', 'blUSD', 'cDAI', 'cUSDC', 'cUSDT', 'gDAI', 'gmdUSDC', 'sUSD', 'tfUSDC'}
Stablecoins plus their interest wrapped counterparts on Compound and Aave. Also contains other derivates.
- ALL_STABLECOIN_LIKE = {'ALUSD', 'AUDT', 'AUSD', 'BAC', 'BDO', 'BEAN', 'BOB', 'BOLD', 'BUSD', 'BYUSD', 'CADC', 'CEUR', 'CJPY', 'CNHT', 'CRVUSD', 'CUSD', 'DAI', 'DJED', 'DOLADUSD', 'EOSDT', 'EURA', 'EURCV', 'EUROC', 'EUROe', 'EURS', 'EURT', 'EURe', 'EUSD', 'FDUSD', 'FEI', 'FLEXUSD', 'FUSD', 'FXD', 'FXUSD', 'GBPT', 'GHO', 'GHST', 'GUSD', 'GYD', 'GYEN', 'HAI', 'HUSD', 'IRON', 'JCHF', 'JPYC', 'KDAI', 'LISUSD', 'LUSD', 'MIM', 'MIMATIC', 'MKUSD', 'MTUSD', 'MUSD', 'ONC', 'OUSD', 'PAR', 'PAXG', 'PYUSD', 'RAI', 'RLUSD', 'RUSD', 'SAI', 'SDAI', 'SEUR', 'SFRAX', 'SILK', 'STUSD', 'SUSD', 'TCNH', 'TOR', 'TRYB', 'TUSD', 'USC', 'USD+', 'USD0', 'USD1', 'USD8', 'USDA', 'USDB', 'USDC', 'USDC.e', 'USDCV', 'USDD', 'USDE', 'USDF', 'USDH', 'USDHLUSDG', 'USDM', 'USDN', 'USDO', 'USDP', 'USDR', 'USDS', 'USDT', 'USDT.e', 'USDT0', 'USDV', 'USDX', 'USDXL', 'USDai', 'USDbC', 'USDe', 'USDf', 'USDs', 'USDt', 'USDtb', 'USD₮', 'USD₮0', 'USH', 'USK', 'USR', 'UST', 'USTC', 'USX', 'USXAU', 'UTY', 'UUSD', 'VAI', 'VEUR', 'VST', 'VUSD', 'WXDAI', 'XAUT', 'XDAI', 'XIDR', 'XSGD', 'XSTUSD', 'XUSD', 'YUSD', 'ZCHF', 'ZSD', 'ZUSD', 'aDAI', 'agEUR', 'alUSD', 'avUSD', 'blUSD', 'bvUSD', 'cDAI', 'cUSDC', 'cUSDT', 'crvUSD', 'csUSD', 'dUSD', 'deUSD', 'feUSD', 'frxUSD', 'ftUSD', 'gDAI', 'gmUSD', 'gmdUSDC', 'iUSD', 'jEUR', 'kUSD', 'lvlUSD', 'mUSD', 'meUSDT', 'msUSD', 'mtUSDC', 'mtUSDT', 'plUSD', 'reUSD', 'sAUSD', 'sBOLD', 'sUSD', 'sUSDC', 'sUSDai', 'sUSDe', 'satUSD', 'scUSD', 'sfrxUSD', 'sosUSDT', 'tfUSDC', 'vbUSDC', 'vbUSDT', 'wM', 'xUSD', 'ynUSDx', 'ysUSDC'}
All stablecoin likes - both interested bearing and non interest bearing.
- LARGE_USDC_HOLDERS = {8453: '0xBaeD383EDE0e5d9d72430661f3285DAa77E9439F', 42161: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', 43114: '0x9f8c163cBA728e99993ABe7495F06c0A3c8Ac8b9'}
Some test accounts with funded USDC for Anvil mainnet forking
TBD: In theory we can find ERC-20 balance slots and write value there with Anvil, but it is difficult to do reliably.
- class TokenDetails
Bases:
objectERC-20 token Python presentation.
A helper class to work with ERC-20 tokens.
Read on-chain data, deal with token value decimal conversions.
Any field can be
Nonefor non-well-formed tokens.Supports one-way pickling
Example how to get USDC details on Polygon:
usdc = fetch_erc20_details(web3, "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174") # USDC on Polygon formatted = f"Token {usdc.name} ({usdc.symbol}) at {usdc.address} on chain {usdc.chain_id}" assert formatted == "Token USD Coin (PoS) (USDC) at 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 on chain 137"
- contract: web3.contract.contract.Contract
The underlying ERC-20 contract proxy class instance
- property address: eth_typing.evm.HexAddress
The address of this token.
See also
address_lower().
- property address_lower: eth_typing.evm.HexAddress
The address of this token.
Always lowercase.
- property functions: web3.contract.contract.ContractFunctions
Alias for underlying Web3 contract method
- convert_to_decimals(raw_amount)
Convert raw token units to decimals.
Example:
details = fetch_erc20_details(web3, token_address) # Convert 1 wei units to edcimals assert details.convert_to_decimals(1) == Decimal("0.0000000000000001")
- Parameters
raw_amount (int) –
- Return type
- convert_to_raw(decimal_amount)
Convert decimalised token amount to raw uint256.
Example:
details = fetch_erc20_details(web3, token_address) # Convert 1.0 USDC to raw unit with 6 decimals assert details.convert_to_raw(1) == 1_000_000
- Parameters
decimal_amount (decimal.Decimal) –
- Return type
- fetch_balance_of(address, block_identifier='latest')
Get an address token balance.
- Parameters
block_identifier – A specific block to query if doing archive node historical queries
address (Union[eth_typing.evm.HexAddress, str]) –
- Returns
Converted to decimal using
convert_to_decimal()- Return type
- transfer(to, amount)
Prepare a ERC20.transfer() transaction with human-readable amount.
Example:
another_new_depositor = web3.eth.accounts[6] tx_hash = base_usdc.transfer(another_new_depositor, Decimal(500)).transact({"from": usdc_holder, "gas": 100_000}) assert_transaction_success_with_explanation(web3, tx_hash)
- Returns
Bound contract function you need to turn to a tx
- Parameters
to (Union[eth_typing.evm.HexAddress, str]) –
amount (decimal.Decimal) –
- Return type
web3.contract.contract.ContractFunction
- approve(to, amount)
Prepare a ERC20.approve() transaction with human-readable amount.
Example:
usdc_amount = Decimal(9.00) tx_hash = usdc.approve(vault.address, usdc_amount).transact({"from": depositor}) assert_transaction_success_with_explanation(web3, tx_hash)
- Returns
Bound contract function you need to turn to a tx
- Parameters
to (Union[eth_typing.evm.HexAddress, str]) –
amount (decimal.Decimal) –
- Return type
web3.contract.contract.ContractFunction
- fetch_raw_balance_of(address, block_identifier='latest')
Get an address token balance.
- Parameters
block_identifier – A specific block to query if doing archive node historical queries
address (Union[eth_typing.evm.HexAddress, str]) –
- Returns
Raw token amount.
- Return type
- static generate_cache_key(chain_id, address)
Generate a cache key for this token.
Cached by (chain, address) as a string
Validate the inputs before generating the key
Address is always lowercase
- export()
Create a serialisable entry of this class.
Removes web3 connection and such unserialisable data.
- Returns
Python dict of exported data.
- Return type
- is_stablecoin_like()
Smell test for stablecoins.
Symbol check for common stablecoins
Not immune to scams
For the list see
is_stablecoin_like()
- Returns
True if we think this could be a stablecoin.
- Return type
- __init__(contract, name=None, symbol=None, total_supply=None, decimals=None, extra_data=<factory>)
- exception TokenDetailError
Bases:
ExceptionCannot extract token details for an ERC-20 token for some reason.
- __init__(*args, **kwargs)
- __new__(**kwargs)
- add_note()
Exception.add_note(note) – add a note to the exception
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- create_token(web3, deployer, name, symbol, supply, decimals=18)
Deploys a new ERC-20 token on local dev, testnet or mainnet.
Uses ERC20Mock contract for the deployment.
Waits until the transaction has completed
Example:
# Deploys an ERC-20 token where 100,000 tokens are allocated ato the deployer address token = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18) print(f"Deployed token contract address is {token.address}") print(f"Deployer account {deployer} has {token.functions.balanceOf(user_1).call() / 10**18} tokens")Find more examples in Tutorials and unit testing source code.
- Parameters
web3 (web3.main.Web3) – Web3 instance
deployer (str) –
Deployer account as 0x address.
Make sure this account has enough ETH or native token to cover the gas cost.
name (str) – Token name
symbol (str) – Token symbol
supply (int) –
Token starting supply as raw units.
E.g.
500 * 10**18to have 500 tokens minted to the deployer at the start.decimals (int) – How many decimals ERC-20 token values have
- Returns
Instance to a deployed Web3 contract.
- Return type
web3.contract.contract.Contract
- get_erc20_contract(web3, address, contract_name='ERC20MockDecimals.json')
Wrap address as ERC-20 standard interface.
- Parameters
web3 (web3.main.Web3) –
address (eth_typing.evm.HexAddress) –
- Return type
web3.contract.contract.Contract
- fetch_erc20_details(web3, token_address, max_str_length=256, raise_on_error=True, contract_name='ERC20MockDecimals.json', cache=LRUCache({}, maxsize=1024, currsize=0), chain_id=None, cause_diagnostics_message=None)
Read token details from on-chain data.
Connect to Web3 node and do RPC calls to extract the token info. We apply some sanitazation for incoming data, like length checks and removal of null bytes.
The function should not raise an exception as long as the underlying node connection does not fail.
Note
Always give
chain_idwhen possible. Otherwise the caching of data is inefficient.Example:
details = fetch_erc20_details(web3, token_address) assert details.name == "Hentai books token" assert details.decimals == 6
- Parameters
web3 (web3.main.Web3) – Web3 instance
token_address (Union[eth_typing.evm.HexAddress, str]) – ERC-20 contract address:
max_str_length (int) – For input sanitisation
raise_on_error – If set, raise TokenDetailError on any error instead of silently ignoring in and setting details to None.
contract_name –
Contract ABI file to use.
The default is
ERC20MockDecimals.json. For USDC usecentre/FiatToken.json.cache (dict | None) –
Use this cache for cache token detail calls.
The main purpose is to easily reduce JSON-RPC API call count.
By default, we use LRU cache of 1024 entries.
Set to
Noneto disable the cache.Instance of
cachetools.Cache. See cachetools documentation for details.chain_id (int) –
Chain id hint for the cache.
If not given do
eth_chainIdRPC call to figure out.cause_diagnostics_message (str | None) – Log in Python logging subsystem why this fetch was done to debug RPC overuse.
- Returns
Sanitised token info
- Return type
- reset_default_token_cache()
Purge the cached token data.
- get_chain_stablecoins(chain_id)
Get all good known stablecoins on a chain.
- Raises
AssertionError – Chain has zero stablecoins configured
- Parameters
chain_id (int) –
- Return type
- get_chain_known_quote_tokens(chain_id)
Get all good quote tokens on chain.
- Parameters
chain_id (int) –
- Return type
- is_stablecoin_like(token_symbol, symbol_list={'ALUSD', 'AUDT', 'AUSD', 'BAC', 'BDO', 'BEAN', 'BOB', 'BOLD', 'BUSD', 'BYUSD', 'CADC', 'CEUR', 'CJPY', 'CNHT', 'CRVUSD', 'CUSD', 'DAI', 'DJED', 'DOLADUSD', 'EOSDT', 'EURA', 'EURCV', 'EUROC', 'EUROe', 'EURS', 'EURT', 'EURe', 'EUSD', 'FDUSD', 'FEI', 'FLEXUSD', 'FUSD', 'FXD', 'FXUSD', 'GBPT', 'GHO', 'GHST', 'GUSD', 'GYD', 'GYEN', 'HAI', 'HUSD', 'IRON', 'JCHF', 'JPYC', 'KDAI', 'LISUSD', 'LUSD', 'MIM', 'MIMATIC', 'MKUSD', 'MTUSD', 'MUSD', 'ONC', 'OUSD', 'PAR', 'PAXG', 'PYUSD', 'RAI', 'RLUSD', 'RUSD', 'SAI', 'SDAI', 'SEUR', 'SFRAX', 'SILK', 'STUSD', 'SUSD', 'TCNH', 'TOR', 'TRYB', 'TUSD', 'USC', 'USD+', 'USD0', 'USD1', 'USD8', 'USDA', 'USDB', 'USDC', 'USDC.e', 'USDCV', 'USDD', 'USDE', 'USDF', 'USDH', 'USDHLUSDG', 'USDM', 'USDN', 'USDO', 'USDP', 'USDR', 'USDS', 'USDT', 'USDT.e', 'USDT0', 'USDV', 'USDX', 'USDXL', 'USDai', 'USDbC', 'USDe', 'USDf', 'USDs', 'USDt', 'USDtb', 'USD₮', 'USD₮0', 'USH', 'USK', 'USR', 'UST', 'USTC', 'USX', 'USXAU', 'UTY', 'UUSD', 'VAI', 'VEUR', 'VST', 'VUSD', 'WXDAI', 'XAUT', 'XDAI', 'XIDR', 'XSGD', 'XSTUSD', 'XUSD', 'YUSD', 'ZCHF', 'ZSD', 'ZUSD', 'aDAI', 'agEUR', 'alUSD', 'avUSD', 'blUSD', 'bvUSD', 'cDAI', 'cUSDC', 'cUSDT', 'crvUSD', 'csUSD', 'dUSD', 'deUSD', 'feUSD', 'frxUSD', 'ftUSD', 'gDAI', 'gmUSD', 'gmdUSDC', 'iUSD', 'jEUR', 'kUSD', 'lvlUSD', 'mUSD', 'meUSDT', 'msUSD', 'mtUSDC', 'mtUSDT', 'plUSD', 'reUSD', 'sAUSD', 'sBOLD', 'sUSD', 'sUSDC', 'sUSDai', 'sUSDe', 'satUSD', 'scUSD', 'sfrxUSD', 'sosUSDT', 'tfUSDC', 'vbUSDC', 'vbUSDT', 'wM', 'xUSD', 'ynUSDx', 'ysUSDC'})
Check if specific token symbol is likely a stablecoin.
Useful for quickly filtering stable/stable pairs in the pools. However, you should never rely on this check alone.
Note that new stablecoins might be introduced, so this check is never going to be future proof.
Example:
assert is_stablecoin_like("USDC") == True assert is_stablecoin_like("USDT") == True assert is_stablecoin_like("GHO") == True assert is_stablecoin_like("crvUSD") == True assert is_stablecoin_like("WBTC") == False
- normalise_token_symbol(token_symbol)
Normalise token symbol for stablecoin detection.
Uppercase
Remove bridge suffixes
Fix USDT variations
- get_weth_contract(web3, name='1delta/IWETH9.json')
Get WETH9 contract for the chain
WETH9 is different contract with different functions on different chain
- Parameters
web3 (web3.main.Web3) – Web3 instance
name (str) – Alternative implementation.
- Returns
WETH token details
- Return type
web3.contract.contract.Contract
- class TokenCacheWarmupResult
Bases:
TypedDict- __init__(*args, **kwargs)
- __new__(**kwargs)
- clear() None. Remove all items from D.
- copy() a shallow copy of D
- fromkeys(value=None, /)
Create a new dictionary with keys from iterable and values set to value.
- get(key, default=None, /)
Return the value for key if key is in the dictionary, else default.
- items() a set-like object providing a view on D's items
- keys() a set-like object providing a view on D's keys
- pop(k[, d]) v, remove specified key and return the corresponding value.
If the key is not found, return the default if given; otherwise, raise a KeyError.
- popitem()
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
- setdefault(key, default=None, /)
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- update([E, ]**F) None. Update D from mapping/iterable E and F.
If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
- values() an object providing a view on D's values
- class TokenDiskCache
Bases:
eth_defi.sqlite_cache.PersistentKeyValueStoreToken cache that stores tokens in disk.
Use with
fetch_erc20_details()For loading hundreds of tokens once
Shared across chains
Enable fast cache warmup with
load_token_details_with_multicall()Persistent: Make sure subsequent batch jobs do not refetch token data over RPC as it is expensive
Store as a SQLite database
Example:
addresses = [ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", # USDC "0x4200000000000000000000000000000000000006", # WETH "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", # DAI "0x554a1283cecca5a46bc31c2b82d6702785fc72d9", # UNI ] cache = TokenDiskCache(tmp_path / "disk_cache.sqlite") web3factory = MultiProviderWeb3Factory(JSON_RPC_BASE) web3 = web3factory() # # Do single token lookups against cache # token = fetch_erc20_details( web3, token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", chain_id=web3.eth.chain_id, cache=cache, ) assert token.extra_data["cached"] == False assert len(cache) == 1 # After one look up, we should have it cached token = fetch_erc20_details( web3, token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", chain_id=web3.eth.chain_id, cache=cache, ) assert token.extra_data["cached"] == True cache.purge() # # Warm up multiple on dry cache # result = cache.load_token_details_with_multicall( chain_id=web3.eth.chain_id, web3factory=web3factory, addresses=addresses, max_workers=max_workers, display_progress=False, ) assert result["tokens_read"] == 4 assert "8453-0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913".lower() in cache assert "8453-0x4200000000000000000000000000000000000006".lower() in cache cache_data = cache["8453-0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913".lower()] assert cache_data["name"] == "USD Coin" assert cache_data["symbol"] == "USDC" assert cache_data["decimals"] == 6 assert cache_data["supply"] > 1_000_000 token = fetch_erc20_details( web3, token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", chain_id=web3.eth.chain_id, cache=cache, ) assert token.extra_data["cached"] == True
- Parameters
filename – Path to the sqlite database
autocommit – Whether to autocommit every time new entry is added to the database
- __init__(filename=PosixPath('~/.cache/eth-defi-tokens.sqlite'), max_str_length=256)
- Parameters
filename – Path to the sqlite database
autocommit – Whether to autocommit every time new entry is added to the database
max_str_length (int) –
- encode_value(value)
Hook to convert Python objects to cache format
- decode_value(value)
Hook to convert SQLite values to Python objects
- encode_multicalls(address)
Generate multicalls for each token address
- Parameters
address (eth_typing.evm.HexAddress) –
- Return type
- create_cache_entry(call_results)
Map multicall results to token details data for one address
- Parameters
call_results (dict[str, eth_defi.event_reader.multicall_batcher.EncodedCallResult]) –
- Return type
- load_token_details_with_multicall(chain_id, web3factory, addresses, display_progress=False, max_workers=8, block_identifier='latest', checkpoint=32)
Warm up cache and load token details for multiple
- Parameters
chain_id (int) –
web3factory (eth_defi.event_reader.web3factory.Web3Factory) –
addresses (list[eth_typing.evm.HexAddress]) –
checkpoint (int) –
- Return type
- __new__(**kwargs)
- clear() None. Remove all items from D.
- property conn: sqlite3.Connection
One connection per thread
- copy() a shallow copy of D
- fromkeys(value=None, /)
Create a new dictionary with keys from iterable and values set to value.
- get(key, default=None)
Return the value for key if key is in the dictionary, else default.
- items() a set-like object providing a view on D's items
- keys() a set-like object providing a view on D's keys
- pop(k[, d]) v, remove specified key and return the corresponding value.
If the key is not found, return the default if given; otherwise, raise a KeyError.
- popitem()
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
- purge()
Delete all keys and save.
- setdefault(key, default=None, /)
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- update([E, ]**F) None. Update D from mapping/iterable E and F.
If E is present and has a .keys() method, then does: for k in E.keys(): D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
- values() an object providing a view on D's values