Ethereum client

Ethereum client

class xchainpy2_ethereum.eth_client.EthereumClient(network=NetworkType.MAINNET, phrase: str | None = None, private_key: str | bytes | callable | None = None, root_derivation_paths: Dict[NetworkType, str] | None = None, explorer_providers=None, wallet_index=0, provider: str | BaseProvider | None = None, extra_data_provider: EVMDataProvider | None = None, **kwargs)

Bases: XChainClient

async approve_erc20_token(spender: str, amount: CryptoAmount, gas: Gas) str

Approve ERC20 token for a spender.

Parameters:
  • spender – Spender address

  • amount – Amount to approve

  • gas – Gas options. Default is Gas.auto(FeeOption.FAST)

Returns:

Transaction hash

async broadcast_tx(tx_hex: str) str

Broadcast a signed transaction to the network.

Parameters:

tx_hex – Signed transaction in hex format

Returns:

Transaction ID that is broadcast to the network

property chain_id: int

Get the chain ID for the current network. 1 for Ethereum mainnet and so on.

Returns:

int chain ID

enable_web3_caching()

Enable Web3 caching middlewares

erc20_asset_from_contract(contract: Contract | str, symbol: str)

Create an Asset object from a contract address.

Parameters:
  • contract – Contract address or Contract object

  • symbol – Symbol of the token

Returns:

Asset object

async estimate_gas_limit(tx_with_data: dict) int
async estimate_gas_of_transfer(what: CryptoAmount, recipient: str, memo: str | None = None, gas: Gas | None = None, nonce: int | None = None) CryptoAmount

Estimate gas for a transfer transaction.

Parameters:
  • what – Amount to transfer

  • recipient – Recipient address or contract address to call

  • memo – Optional memo (not supported for ERC20 token transfer)

  • gas – Optional Gas object. If not provided, it will use Gas.auto(FeeOption.FAST).

  • nonce – Optional nonce. If not provided, it will fetch the nonce from the blockchain.

Returns:

gas_limit_estimation

If True, it will estimate the gas limit for the transaction before sending it. It is useful for complex transactions where the gas limit is not known in advance. This action requires an extra RPC call to the node. Otherwise, it will use the default gas limit for the transaction.

gas_transfer_margin

Gas transfer margin is a percentage of the gas limit that is added to the gas limit to prevent gas underestimation.

get_account() Account

Get the account object (web3) for the current wallet.

get_address() str

Get the address for the given wallet index. The address returned is check-summed.

Returns:

string address

async get_balance(address: str = '', with_erc20=False) List[CryptoAmount]

Get the balance of a given address.

Parameters:
  • address – By default, it will return the balance of the current wallet. (optional)

  • with_erc20 – If True, it will return the balance of all ERC20 tokens as well. (optional). Experimental!

Returns:

async get_block_timestamp(block_number: int) int

Get the timestamp of a given block number.

Parameters:

block_number – int

Returns:

Timestamp

async get_erc20_allowance(contract_address: str | Asset | Contract, spender: str, address: str = '') CryptoAmount

Get the allowance of a given address.

Parameters:
  • contract_address – ERC20 Contract address. Can be an Asset object or a string.

  • spender – Spender address

  • address – By default, it will return the allowance of the current wallet. (optional)

Returns:

CryptoAmount

get_erc20_as_contract(contract_address: str | Asset | Contract)

Get the ERC20 contract object for a given contract address.

Parameters:

contract_address – Contract address, or Asset object, or Contract object

Returns:

Contract object

async get_erc20_token_balance(contract_address: str | Asset | Contract, address: str = '') CryptoAmount

Get the balance of a given address.

async get_erc20_token_info(contract: str | Asset | Contract) TokenInfo

Returns zero balance and token symbol for a given contract address. The balance is zero because we are only interested in the token symbol and decimals.

Parameters:

contract – Contract object or contract address or Asset object

get_explorer_tx_url(tx_id: str) str

Get the explorer url for the given transaction id.

Parameters:

tx_id – str The transaction id

Returns:

str The explorer url for the given transaction id based on the network.

async get_fees(fee_multiplier=1.0) EVMFees

Get EVM gas rates for the current network. Fees are estimated based on the last 20 blocks. All FeeRate are in Gwei!

Parameters:

fee_multiplier – Fee multiplier. Default is 1.0

Returns:

Fees object

async get_last_fee() CryptoAmount

Get the last Ethereum fee from Web3 provider.

Returns:

CryptoAmount

async get_nonce(address: str = '') int

Get the nonce for a given address. Otherwise, it will return the nonce of the current wallet. Nonce is the number of transactions sent from an address.

Parameters:

address (str) – Address of a wallet (optional)

Returns:

Nonce

Return type:

int

get_public_key()

Get the public key for the current wallet.

async get_transaction_data(tx_id: str, with_timestamp=False) XcTx | None

Get transaction details by transaction ID (hash).

Parameters:
  • tx_id – Transaction ID (hash)

  • with_timestamp – If True, it will return the timestamp of the block. Extra API call!

Returns:

Optional[XcTx]

async get_transactions(address: str = '', offset: int = 0, limit: int = 0, start_time: datetime | None = None, end_time: datetime | None = None, asset: Asset | None = None) TxPage

Get transactions of a given address. Works only if you have provided an extra data provider. Etherscan Pro and Moralis are supported.

Parameters:
  • address – Address of wallet to inspect its history

  • offset – (not supported)

  • limit – Maximum number of transactions to return

  • start_time – (not supported)

  • end_time – (not supported)

  • asset – (not supported)

Returns:

async make_contract_call(method_pointer, value, gas: Gas, nonce: int | None = None) str

Make a contract call.

Parameters:
  • method_pointer – Contract method pointer

  • value – Value to send

  • gas – Gas options

  • nonce – Nonce (optional) if not provided, it will fetch the nonce from the blockchain

Returns:

Transaction hash

property provider

Get the current Web3 provider.

Returns:

BaseProvider

async revoke_erc20_token_allowance(spender: str, token: str | Asset, gas: Gas) str

Revoke ERC20 token allowance for a spender.

Parameters:
  • spender – Spender address

  • token – Token symbol or Asset object

  • gas – Gas options. Default is Gas.auto(FeeOption.FAST)

async transfer(what: CryptoAmount, recipient: str, memo: str | None = None, gas: Gas | None = None, **kwargs) str

Transfer Ethereum or ERC20 token. Do not use it for swap or something like this. Use AMM’s deposit method instead.

Parameters:
  • what – Amount to transfer

  • recipient – Recipient address or contract address to call

  • memo – Memo (optional, not supported for ERC20 token transfer)

  • gas – Gas object is optional. If not provided, it will use Gas.auto(FeeOption.FAST).

Returns:

Transaction hash

validate_address(address: str) bool

Validates an Ethereum address.

Parameters:

address – Address string

Returns:

True if valid, False otherwise.

validated_checksum_address(address: str) str

Validate and checksum an Ethereum address if it’s not checksummed.

Parameters:

address – str Address to validate

Returns:

bool True if valid, False otherwise.

async wait_for_transaction(tx_id: str, timeout: int = 120, with_timestamp=False, *args, **kwargs) XcTx | None

Wait for a transaction to be mined. This method does not perform polling explicitly. It uses the web3.wait_for_transaction_receipt method. If the transaction is not mined within the timeout, it will raise a TimeExhausted exception.

Parameters:
  • tx_id – Transaction ID

  • timeout – Timeout in seconds. Default is 120 seconds

  • with_timestamp – If True, it will return the timestamp of the block

Returns:

Transaction object XcTx

Ethereum constants

xchainpy2_ethereum.const.DEFAULT_ETH_EXPLORER_PROVIDERS = {NetworkType.MAINNET: ('https://etherscan.io', 'https://etherscan.io/address/{address}', 'https://etherscan.io/tx/{tx_id}'), NetworkType.STAGENET: ('https://etherscan.io', 'https://etherscan.io/address/{address}', 'https://etherscan.io/tx/{tx_id}'), NetworkType.TESTNET: ('https://sepolia.etherscan.io/', 'https://sepolia.etherscan.io/address/{address}', 'https://sepolia.etherscan.io/tx/{tx_id}')}

Ethereum Default Explorer URLS

xchainpy2_ethereum.const.ETH_CHAIN_ID = {NetworkType.MAINNET: 1, NetworkType.STAGENET: 1, NetworkType.TESTNET: 11155111}

Ethereum Chain IDs. In the Ethereum Virtual Machine (EVM), the Chain ID is a unique identifier assigned to each blockchain to prevent replay attacks, where a transaction on one chain could be copied and reused on another. The Chain ID was introduced in EIP-155 to add an additional layer of security and to help distinguish between different Ethereum-compatible networks, like Ethereum mainnet, testnets, and sidechains.

xchainpy2_ethereum.const.ETH_DECIMALS = 18

Ethereum Decimals The resolution of eth is 18 decimals, which means that 1 eth = “1 followed by 18 zeros” wei eth.

xchainpy2_ethereum.const.ETH_NORMAL_PRIORITY_FEE_WEI = 1500000000

Ethereum Normal Fee in gwei This is a typical fee for a transaction but it can be increased or decreased based on your needs

xchainpy2_ethereum.const.ETH_ROOT_DERIVATION_PATHS = {NetworkType.MAINNET: "m/44'/60'/0'/0/", NetworkType.STAGENET: "m/44'/60'/0'/0/", NetworkType.TESTNET: "m/44'/60'/0'/0/"}

Ethereum Root Derivation Paths

xchainpy2_ethereum.const.ETH_TOKEN_LIST = '/home/docs/checkouts/readthedocs.org/user_builds/xchainpy2/checkouts/develop/packages/xchainpy_ethereum/xchainpy2_ethereum/data/eth_mainnet_latest.json'

Ethereum ERC20 Token List Source: 1inch

xchainpy2_ethereum.const.EVM_NULL_ADDRESS = '0x0000000000000000000000000000000000000000'

Ethereum Null Address

xchainpy2_ethereum.const.FREE_ETH_PROVIDERS = {NetworkType.MAINNET: ['https://rpc.ankr.com/eth', 'https://eth-mainnet.public.blastapi.io', 'https://eth.llamarpc.com', 'https://cloudflare-eth.com/', 'https://rpc.flashbots.net/'], NetworkType.STAGENET: ['https://rpc.ankr.com/eth', 'https://eth-mainnet.public.blastapi.io', 'https://eth.llamarpc.com', 'https://cloudflare-eth.com/', 'https://rpc.flashbots.net/'], NetworkType.TESTNET: ['https://rpc2.sepolia.org', 'https://sepolia.drpc.org', 'wss://sepolia.gateway.tenderly.co']}

Free public Ethereum WEB3 Providers. These providers are used by default, and they may have some limitations. You better use your own provider for production.

xchainpy2_ethereum.const.GAS_LIMITS = {NetworkType.MAINNET: (200000, 23000, 170000, 180000, 30000000000), NetworkType.STAGENET: (200000, 23000, 170000, 180000, 30000000000), NetworkType.TESTNET: (200000, 23000, 170000, 180000, 30000000000)}

Ethereum default gas limits

xchainpy2_ethereum.const.MAIN_NET_ETHERSCAN_PROVIDER = ('https://etherscan.io', 'https://etherscan.io/address/{address}', 'https://etherscan.io/tx/{tx_id}')

Ethereum Mainnet explorer URLS (Etherscan.io)

xchainpy2_ethereum.const.MAX_APPROVAL = 115792089237316195423570985008687907853269984665640564039457584007913129639935

Maximum approval value for ERC20 tokens

Ethereum Gas Management

class xchainpy2_ethereum.gas.EVMFees(fees: Dict[FeeOption, CryptoAmount], priority_fee: CryptoAmount, base_fee: CryptoAmount)

Bases: FeeProgressive

select(option: FeeOption, gas_limit: int = 0) EVMGas

Selects the fee amount based on the provided FeeOption.

Parameters:
  • option – The FeeOption to select.

  • gas_limit – Just to pass it through if needed, as EVMGas requires it.

Returns:

The corresponding CryptoAmount for the selected fee option.

class xchainpy2_ethereum.gas.EVMGas(gas_price: int | None = None, max_fee_per_gas: int | None = None, max_priority_fee_per_gas: int | None = None, gas_limit: int | None = None)

Bases: IGasExplicitSettings

Gas options for transaction invocation in Ethereum-like chains.

classmethod eip1559(max_fee_per_gas: int, max_priority_fee_per_gas: int, gas_limit: int)

max_priority_fee_per_gas is your “tip” (what goes to the miner). base_fee_per_gas is the protocol-burned minimum fee for that block. max_fee_per_gas is the total ceiling you’re willing to pay per gas; it must cover both the base fee and your tip.

In other words: maxFeePerGas ≥ baseFeePerGas + maxPriorityFeePerGas

Parameters:
  • max_fee_per_gas – Maximum fee per gas you are willing to pay for the transaction in Wei.

  • max_priority_fee_per_gas – Maximum priority fee per gas you are willing to pay for the transaction in Wei.

  • gas_limit – Gas limit for the transaction in Wei.

Returns:

EVMGas instance with EIP-1559 parameters.

classmethod eip1559_in_gwei(max_fee_per_gas: float, max_priority_fee_per_gas: float, gas_limit: int)
property is_valid: bool

Validates the gas configuration: - Either legacy (gas_price) or EIP-1559 (max_fee_per_gas + max_priority_fee_per_gas), not both. - gas_limit must be set >= 0 or 0 for automatic estimation. - For legacy: gas_price must be set, EIP-1559 fields must be None. - For EIP-1559: both max_fee_per_gas and max_priority_fee_per_gas must be set, and gas_price must be None. - max_fee_per_gas >= max_priority_fee_per_gas.

classmethod legacy(gas_price: int, gas_limit: int)
classmethod legacy_in_gwei(gas_price: float, gas_limit: int)
class xchainpy2_ethereum.gas.EVMGasLimits(approve_gas_limit: int, transfer_gas_asset_gas_limit: int, transfer_token_gas_limit: int, deposit_gas_limit: int, gas_price: int)

Bases: NamedTuple

Sufficient gas limits for various transaction types in Ethereum-like chains.

approve_gas_limit: int

Alias for field number 0

classmethod default()
deposit_gas_limit: int

Alias for field number 3

gas_price: int

Alias for field number 4

transfer_gas_asset_gas_limit: int

Alias for field number 1

transfer_token_gas_limit: int

Alias for field number 2

class xchainpy2_ethereum.gas.EVMGasPriceEstimator(w3: Web3, chain: Chain, gas_asset: Asset, percentiles=(20, 50, 80), block_count=10, base_fee_multiplier=1.0)

Bases: object

async base_fee()
async static call_service(sync_method, *args)
async estimate() EVMFees

Estimate the gas fees based on the current network conditions. This method fetches the fee history, base fee, and max priority fee, and calculates the average, fast, and fastest fees based on the reward history.

Returns:

FeesEVM object containing the estimated fees

async fee_history()
async max_priority_fee_safe_low()

Get the priority fee needed to be included in a block. You can consider this value as “safe-low” priority fee This value is returned by the RPC node

xchainpy2_ethereum.gas.wei_to_gwei(wei)

Convert Wei to Gwei.

Parameters:

wei – Amount in Wei to be converted to Gwei.

Returns:

Other Ethereum Utils

exception xchainpy2_ethereum.utils.EVMCallError

Bases: Exception

This kind of exception is raised when there are issues with Web3 provider communication

xchainpy2_ethereum.utils.get_erc20_abi()

Loads and returns standard ERC20 token ABI as a Python dictionary See: https://eips.ethereum.org/EIPS/eip-20

Returns:

dict

xchainpy2_ethereum.utils.get_router_abi()

Loads and returns ABI of the THORChain router v4 as a Python dictionary See: https://dev.thorchain.org/protocol-development/chain-clients/evm-chains.html?highlight=router#router

Returns:

dict

xchainpy2_ethereum.utils.is_valid_eth_address(address)

Validates Ethereum address, including checksum validation

Parameters:

address – Ethereum address to be validated

Returns:

bool

xchainpy2_ethereum.utils.select_random_free_provider(network: NetworkType, source: dict) BaseProvider

Selects a random free RPC provider from the source list

Parameters:
  • network (NetworkType) – Type of network

  • source – Dictionary of free RPC providers grouped by network

Returns:

Web3 provider instance

:rtype web3.providers.BaseProvider

xchainpy2_ethereum.utils.validated_checksum_address(web3_pr: BaseWeb3, address: str) str

This function validates and returns a checksum address. In case the address is in uppercase, that means it probably came from THORChain or other similar AMM. it converts it to checksum address. Otherwise, it validates the address and returns it.

Parameters:
  • web3_pr (BaseWeb3) – Web3 instance

  • address – EVM Address to be validated

Returns:

Validated checksum address

Return type:

str