Skip to content

Example: ethereum_wallet

To run this example:

  • Clone the examples repository: git clone git@github.com:alloy-rs/examples.git
  • Run: cargo run --example ethereum_wallet
//! Demonstrates how `EthereumWallet` can use multiple different types of signers.
 
use alloy::{
    network::{EthereumWallet, TransactionBuilder, TxSigner},
    node_bindings::Anvil,
    primitives::{address, U256},
    providers::{Provider, ProviderBuilder},
    rpc::types::TransactionRequest,
    signers::{
        aws::AwsSigner,
        ledger::{HDPath, LedgerSigner},
        local::PrivateKeySigner,
    },
};
use aws_config::BehaviorVersion;
 
#[tokio::main]
async fn main() -> eyre::Result<()> {
    // Spin up a local Anvil node.
    // Ensure `anvil` is available in $PATH.
    let anvil = Anvil::new().try_spawn()?;
 
    // Initialize your signers.
 
    // Set up a local signer.
    let pk_signer: PrivateKeySigner =
        "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse()?;
    let pk_addr = pk_signer.address();
 
    // Set up a hardware wallet signer
    let ledger = LedgerSigner::new(HDPath::LedgerLive(0), Some(1)).await?;
    let ledger_addr = ledger.address();
 
    // AWS KMS signer
    let key_id = std::env::var("AWS_KEY_ID").expect("AWS_KEY_ID not set in .env file");
    let config = aws_config::load_defaults(BehaviorVersion::latest()).await;
    let client = aws_sdk_kms::Client::new(&config);
    let aws = AwsSigner::new(client, key_id, Some(1)).await?;
    let _aws_addr = aws.address();
 
    // Initialize `EthereumWallet`.
    // `pk_signer` is set as the default signer.
    // This signer is used to sign `TransactionRequest` and `TypedTransaction` objects that do
    // not specify a signer address in the `from` field.
    let mut wallet = EthereumWallet::new(pk_signer);
    // Add aws and ledger signers to the wallet
    wallet.register_signer(aws);
    wallet.register_signer(ledger);
 
    // Create a provider with the `WalletFiller`.
    let provider = ProviderBuilder::new().wallet(wallet).on_http(anvil.endpoint_url());
 
    // Note that the `from` field hasn't been specified.
    // The wallet filler in the provider will set to it the default signer's address, which is
    // `pk_signer`.
    let tx = TransactionRequest::default()
        .with_to(address!("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"))
        .with_value(U256::from(100));
 
    let receipt = provider.send_transaction(tx).await?.get_receipt().await?;
    assert_eq!(pk_addr, receipt.from);
 
    // One can hint the wallet filler about which signer to use by specifying the `from` field.
    // In this case, the `ledger` signer will be used to sign the transaction.
    let tx = TransactionRequest::default()
        .with_from(ledger_addr)
        .with_to(address!("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"))
        .with_value(U256::from(100));
 
    let receipt = provider.send_transaction(tx).await?.get_receipt().await?;
    assert_eq!(ledger_addr, receipt.from);
 
    Ok(())
}

Find the source code on Github here.