HotWallet

Documentation for eth_defi.hotwallet.HotWallet Python class.

class HotWallet[source]

Hot wallet for signing transactions effectively.

To use this class with the existing web3.py Contract.functions.myFunc().transact() you can add the private key as the local signing middleware. However you should try to use sign_bound_call_with_new_nonce() instead when possible. See also eth_defi.middleware.construct_sign_and_send_raw_middleware_anvil() when working with Anvil.

Example:

from eth_account import Account
from web3.middleware import construct_sign_and_send_raw_middleware

from eth_defi.trace import assert_transaction_success_with_explanation
from eth_defi.hotwallet import HotWallet

account = Account.create()

# Move 1/2 of ETH from the first test account to ours
test_account_1 = web3.eth.accounts[0]
stash = web3.eth.get_balance(test_account_1)
tx_hash = web3.eth.send_transaction({"from": test_account_1, "to": account.address, "value": stash // 2})
assert_transaction_success_with_explanation(web3, tx_hash)

# Attach local private key to the web3.py middleware machinery
web3.middleware_onion.add(construct_sign_and_send_raw_middleware(account))

# Create a hot wallet instance
hot_wallet = HotWallet(account)
hot_wallet.sync_nonce(web3)

# Use web3.py signing (NOTE: does not correctly increment nonce)
# so you need to call hot_wallet.sync_nonce() after the tx has been confirmed
tx_hash = usdc.functions.transfer(
    some_address,
    500 * 10**6,
).transact({"from": hot_wallet.address})
assert_transaction_success_with_explanation(web3, tx_hash)
hot_wallet.sync_nonce(web3)  # Sync nonce again, as the manual management is off

Note

This class is not thread safe. If multiple threads try to sign transactions at the same time, nonce tracking may be lost.

See also how to create private keys from command line.

Attributes summary

address

Ethereum address of the wallet.

private_key

The private key as plain text.

Methods summary

__init__(account)

Create a hot wallet from a local account.

allocate_nonce()

Get the next free available nonce to be used with a transaction.

create_for_testing(web3[, test_account_n, ...])

Creates a new hot wallet and seeds it with ETH from one of well-known test accounts.

fill_in_gas_price(web3, tx)

Fills in the gas value fields for a transaction.

from_private_key(key)

Create a hot wallet from a private key that is passed in as a hex string.

get_native_currency_balance(web3)

Get the balance of the native currency (ETH, BNB, MATIC) of the wallet.

sign_bound_call_with_new_nonce(func[, tx_params])

Signs a bound Web3 Contract call.

sign_transaction_with_new_nonce(tx)

Signs a transaction and allocates a nonce for it.

sync_nonce(web3)

Initialise the current nonce from the on-chain data.

__init__(account)[source]

Create a hot wallet from a local account.

Parameters

account (eth_account.signers.local.LocalAccount) –

property address: eth_typing.evm.HexAddress

Ethereum address of the wallet.

property private_key: hexbytes.main.HexBytes

The private key as plain text.

sync_nonce(web3)[source]

Initialise the current nonce from the on-chain data.

Parameters

web3 (web3.main.Web3) –

allocate_nonce()[source]

Get the next free available nonce to be used with a transaction.

Ethereum tx nonces are a counter.

Increase the nonce counter

Return type

int

sign_transaction_with_new_nonce(tx)[source]

Signs a transaction and allocates a nonce for it.

Example:

web3 = Web3(mev_blocker_provider)
wallet = HotWallet.create_for_testing(web3)

# Send some ETH to zero address from
# the hot wallet
signed_tx = wallet.sign_transaction_with_new_nonce({
    "from": wallet.address,
    "to": ZERO_ADDRESS,
    "value": 1,
    "gas": 100_000,
    "gasPrice": web3.eth.gas_price,
})
tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction)
Parameters

tx (dict) – Ethereum transaction data as a dict. This is modified in-place to include nonce.

Returns

A transaction payload and nonce with used to generate this transaction.

Return type

eth_defi.hotwallet.SignedTransactionWithNonce

sign_bound_call_with_new_nonce(func, tx_params=None)[source]

Signs a bound Web3 Contract call.

Example:

bound_func = busd_token.functions.transfer(user_2, 50*10**18)  # Transfer 50 BUDF
signed_tx = hot_wallet.sign_bound_call_with_new_nonce(bound_func)
web3.eth.send_raw_transaction(signed_tx.rawTransaction)

With manual gas estimation:

approve_call = usdc.contract.functions.approve(quickswap.router.address, raw_amount)
gas_estimation = estimate_gas_fees(web3)
tx_gas_parameters = apply_gas({"gas": 100_000}, gas_estimation)  # approve should not take more than 100k gas
signed_tx = hot_wallet.sign_bound_call_with_new_nonce(approve_call, tx_gas_parameters)

See also

Parameters
  • func (web3.contract.contract.ContractFunction) – Web3 contract function that has its arguments bound

  • tx_params (Optional[dict]) – Transaction parameters like gas

Return type

eth_defi.hotwallet.SignedTransactionWithNonce

get_native_currency_balance(web3)[source]

Get the balance of the native currency (ETH, BNB, MATIC) of the wallet.

Useful to check if you have enough cryptocurrency for the gas fees.

Parameters

web3 (web3.main.Web3) –

Return type

decimal.Decimal

static fill_in_gas_price(web3, tx)[source]

Fills in the gas value fields for a transaction.

  • Estimates raw transaction gas usage

  • Uses web3 methods to get the gas value fields for the dict

  • web3 offers different backends for this

  • likely queries the values from the node

Returns

Transaction data (mutated) with gas values filled in.

Parameters
  • web3 (web3.main.Web3) –

  • tx (dict) –

Return type

dict

static from_private_key(key)[source]

Create a hot wallet from a private key that is passed in as a hex string.

Add the key to web3 signing chain.

Example:

# Generated with  openssl rand -hex 32
wallet = HotWallet.from_private_key("0x54c137e27d2930f7b3433249c5f07b37ddcfea70871c0a4ef9e0f65655faf957")
Parameters

key (str) – 0x prefixed hex string

Returns

Ready to go hot wallet account

Return type

eth_defi.hotwallet.HotWallet

static create_for_testing(web3, test_account_n=0, eth_amount=10)[source]

Creates a new hot wallet and seeds it with ETH from one of well-known test accounts.

Shortcut method for unit testing.

Example:

web3 = Web3(test_provider)
wallet = HotWallet.create_for_testing(web3)

signed_tx = wallet.sign_transaction_with_new_nonce(
    {
        "from": wallet.address,
        "to": ZERO_ADDRESS,
        "value": 1,
        "gas": 100_000,
        "gasPrice": web3.eth.gas_price,
    }
)

tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction)
assert_transaction_success_with_explanation(web3, tx_hash)
Parameters

web3 (web3.main.Web3) –

Return type

eth_defi.hotwallet.HotWallet