Skip to content

Commit

Permalink
add nonce_layer and signer_layer
Browse files Browse the repository at this point in the history
  • Loading branch information
zerosnacks committed Mar 15, 2024
1 parent ab8b5f6 commit db7d30c
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 10 deletions.
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,9 @@ cargo run --example mnemonic_signer
- [ ] Events
- [ ] Logs and filtering
- [ ] Solidity topics
- [ ] Middleware
- [ ] Builder
- [ ] Create custom middleware
- [ ] Gas escalator
- [ ] Gas oracle
- [ ] Nonce manager
- [ ] Policy
- [ ] Signer
- [ ] Time lag
- [ ] Transformer
- [x] Layers
- [x] [Nonce manager](./examples/layers/examples/nonce_layer.rs)
- [x] [Signature manager](./examples/layers/examples/signer_layer.rs)
- [ ] Providers
- [ ] Http
- [ ] IPC
Expand Down
24 changes: 24 additions & 0 deletions examples/layers/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "examples-layers"

publish.workspace = true
version.workspace = true
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true

[dev-dependencies]
alloy-network.workspace = true
alloy-node-bindings.workspace = true
alloy-primitives.workspace = true
alloy-provider.workspace = true
alloy-rpc-client.workspace = true
alloy-rpc-types.workspace = true
alloy-signer-wallet.workspace = true
alloy-transport-http.workspace = true

reqwest.workspace = true
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
63 changes: 63 additions & 0 deletions examples/layers/examples/nonce_layer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! Example of using the `ManagedNonceLayer` in the provider.

use alloy_network::EthereumSigner;
use alloy_node_bindings::Anvil;
use alloy_primitives::{address, U256, U64};
use alloy_provider::{layers::ManagedNonceLayer, Provider, ProviderBuilder, RootProvider};
use alloy_rpc_client::RpcClient;
use alloy_rpc_types::request::TransactionRequest;
use alloy_signer_wallet::LocalWallet;
use alloy_transport_http::Http;
use reqwest::Client;

/// In Ethereum, the nonce of a transaction is a number that represents the number of transactions
/// that have been sent from a particular account. The nonce is used to ensure that transactions are
/// processed in the order they are intended, and to prevent the same transaction from being
/// processed multiple times.
///
/// The nonce manager in Alloy is a layer that helps you manage the nonce
/// of transactions by keeping track of the current nonce for a given account and automatically
/// incrementing it as needed. This can be useful if you want to ensure that transactions are sent
/// in the correct order, or if you want to avoid having to manually manage the nonce yourself.
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Spin up a local Anvil node.
// Ensure `anvil` is available in $PATH
let anvil = Anvil::new().spawn();

// Set up the wallets.
let wallet: LocalWallet = anvil.keys()[0].clone().into();
let from = wallet.address();

// Create a provider with a signer and the network.
let http = Http::<Client>::new(anvil.endpoint().parse()?);
let provider = ProviderBuilder::new()
.layer(ManagedNonceLayer)
.signer(EthereumSigner::from(wallet))
.provider(RootProvider::new(RpcClient::new(http, true)));

let tx = TransactionRequest {
from: Some(from),
value: Some(U256::from(100)),
to: address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into(),
gas_price: Some(U256::from(20e9)),
gas: Some(U256::from(21000)),
..Default::default()
};

let pending = provider.send_transaction(tx.clone()).await?;
let tx_hash = pending.watch().await?;
let mined_tx = provider.get_transaction_by_hash(tx_hash).await?;
assert_eq!(mined_tx.nonce, U64::from(0));

println!("Transaction sent with nonce: {}", mined_tx.nonce);

let pending = provider.send_transaction(tx).await?;
let tx_hash = pending.watch().await?;
let mined_tx = provider.get_transaction_by_hash(tx_hash).await?;
assert_eq!(mined_tx.nonce, U64::from(1));

println!("Transaction sent with nonce: {}", mined_tx.nonce);

Ok(())
}
65 changes: 65 additions & 0 deletions examples/layers/examples/signer_layer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//! Example of using the `SignerLayer` in the provider.

use alloy_network::EthereumSigner;
use alloy_node_bindings::Anvil;
use alloy_primitives::{address, b256, U256, U64};
use alloy_provider::{Provider, ProviderBuilder, RootProvider};
use alloy_rpc_client::RpcClient;
use alloy_rpc_types::request::TransactionRequest;
use alloy_signer_wallet::LocalWallet;
use alloy_transport_http::Http;
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Spin up a local Anvil node.
// Ensure `anvil` is available in $PATH
let anvil = Anvil::new().spawn();

// Set up the wallets.
let wallet: LocalWallet = anvil.keys()[0].clone().into();

// Create a provider with a signer and the network.
let http = Http::<Client>::new(anvil.endpoint().parse()?);
let provider = ProviderBuilder::new()
.signer(EthereumSigner::from(wallet))
.provider(RootProvider::new(RpcClient::new(http, true)));

let tx = TransactionRequest {
nonce: Some(U64::from(0)),
value: Some(U256::from(100)),
to: address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into(),
gas_price: Some(U256::from(20e9)),
gas: Some(U256::from(21000)),
..Default::default()
};

let builder = provider.send_transaction(tx).await?;
let node_hash = *builder.tx_hash();

println!(
"Node hash matches expected hash: {}",
node_hash == b256!("eb56033eab0279c6e9b685a5ec55ea0ff8d06056b62b7f36974898d4fbb57e64")
);

let pending = builder.register().await?;
let pending_transaction_hash = *pending.tx_hash();

println!(
"Pending transaction hash matches node hash: {}",
pending_transaction_hash == node_hash
);

let transaction_hash = pending.await?;
assert_eq!(transaction_hash, node_hash);

println!("Transaction hash matches node hash: {}", transaction_hash == node_hash);

let receipt =
provider.get_transaction_receipt(transaction_hash).await.unwrap().expect("no receipt");
let receipt_hash = receipt.transaction_hash.expect("no receipt hash");

println!("Receipt hash matches node hash: {}", receipt_hash == node_hash);

Ok(())
}

0 comments on commit db7d30c

Please sign in to comment.