Skip to content

Commit

Permalink
Merge branch 'main' into provider_examples
Browse files Browse the repository at this point in the history
  • Loading branch information
yash-atreya authored Mar 25, 2024
2 parents 01372cf + e329e7d commit d443654
Show file tree
Hide file tree
Showing 23 changed files with 1,844 additions and 47 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ alloy = { git = "https://github.com/alloy-rs/alloy", rev = "fd8f065", features =
# "rpc-types",
"rpc-types-eth",
# "rpc-types-engine",
# "rpc-types-trace",
"rpc-types-trace",
"signers",
# "signer-aws",
# "signer-gcp",
"signer-ledger",
"signer-trezor",
"signer-wallet",
# "signer-keystore",
"signer-mnemonic",
"signer-yubihsm",
"transports",
Expand Down
54 changes: 14 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ cargo run --example mnemonic_signer

## Table of Contents

- [ ] Address book
- [x] Anvil
- [x] [Deploy contract](./examples/anvil/examples/deploy_contract_anvil.rs)
- [x] [Fork](./examples/anvil/examples/fork_anvil.rs)
Expand All @@ -28,54 +27,29 @@ cargo run --example mnemonic_signer
- [x] [Deploy from artifact](./examples/contracts/examples/deploy_from_artifact.rs)
- [x] [Deploy from contract](./examples/contracts/examples/deploy_from_contract.rs)
- [x] [Generate](./examples/contracts/examples/generate.rs)
- [ ] Events
- [ ] Logs and filtering
- [ ] Solidity topics
- [ ] Middleware
- [ ] Builder
- [ ] Create custom middleware
- [ ] Gas escalator
- [ ] Gas oracle
- [ ] Nonce manager
- [ ] Policy
- [ ] Signer
- [ ] Time lag
- [ ] Transformer
- [x] Providers
- [x] [Builder](./examples/providers/examples/builder.rs)
- [x] [HTTP](./examples/providers/examples/http.rs)
- [x] [IPC](./examples/providers/examples/ipc.rs)
- [x] [WS](./examples/providers/examples/ws.rs)
- [ ] Queries
- [ ] Blocks
- [ ] Contracts
- [ ] Events
- [ ] Paginated logs
- [ ] UniswapV2 pair
- [ ] Transactions
- [x] Layers
- [x] [Nonce manager](./examples/layers/examples/nonce_layer.rs)
- [x] [Signature manager](./examples/layers/examples/signer_layer.rs)
- [x] Queries
- [x] [Contract storage](./examples/queries/examples/query_contract_storage.rs)
- [x] [Contract deployed bytecode](./examples/queries/examples/query_deployed_bytecode.rs)
- [x] [Logs](./examples/queries/examples/query_logs.rs)
- [ ] Subscriptions
- [ ] Watch blocks
- [ ] Subscribe events by type
- [ ] Subscribe logs
- [ ] Transactions
- [ ] Call override
- [ ] Create raw transaction
- [ ] Create typed transaction
- [ ] Decode input
- [ ] EIP-1559
- [ ] ENS
- [ ] Estimate gas
- [ ] Get gas price
- [ ] Get gas price USD
- [ ] Remove liquidity
- [ ] Set gas for a transaction
- [ ] Send raw transaction
- [ ] Send typed transaction
- [ ] Trace
- [ ] Transaction receipt
- [ ] Transaction status
- [ ] Transfer ETH
- [ ] Transfer ERC20 token
- [x] Transactions
- [x] [Decode input](./examples/transactions/examples/decode_input.rs)
- [x] [Get gas price in USD](./examples/transactions/examples/gas_price_usd.rs)
- [x] [Trace call](./examples/transactions/examples/trace_call.rs)
- [x] [Trace transaction](./examples/transactions/examples/trace_transaction.rs)
- [x] [Transfer ERC20 token](./examples/transactions/examples/transfer_erc20.rs)
- [x] [Transfer ETH](./examples/transactions/examples/transfer_eth.rs)
- [ ] Wallets
- [ ] AWS signer
- [ ] GCP signer
Expand Down
18 changes: 18 additions & 0 deletions examples/layers/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[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.workspace = true

eyre.workspace = true
reqwest.workspace = true
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
67 changes: 67 additions & 0 deletions examples/layers/examples/nonce_layer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Example of using the `ManagedNonceLayer` in the provider.
use alloy::{
network::{EthereumSigner, TransactionBuilder},
node_bindings::Anvil,
primitives::{address, U256},
providers::{layers::ManagedNonceLayer, Provider, ProviderBuilder},
rpc::{client::RpcClient, types::eth::request::TransactionRequest},
signers::wallet::LocalWallet,
};
use eyre::Result;

/// 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<()> {
// Spin up a local Anvil node.
// Ensure `anvil` is available in $PATH
let anvil = Anvil::new().try_spawn()?;

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

// Create a provider with the signer.
let http = anvil.endpoint().parse()?;
let provider = ProviderBuilder::new()
// Add the `ManagedNonceLayer` to the provider
.layer(ManagedNonceLayer)
.signer(EthereumSigner::from(wallet))
.on_client(RpcClient::new_http(http));

// Create an EIP-1559 type transaction.
let tx = TransactionRequest::default()
.with_from(from)
.with_to(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into())
.with_value(U256::from(100))
.with_gas_limit(U256::from(21000))
.with_max_fee_per_gas(U256::from(20e9))
.with_max_priority_fee_per_gas(U256::from(1e9))
.with_chain_id(anvil.chain_id());

// Send the transaction, the nonce (0) is automatically managed by the provider.
let builder = provider.send_transaction(tx.clone()).await?;
let node_hash = *builder.tx_hash();
let pending_transaction = provider.get_transaction_by_hash(node_hash).await?;
assert_eq!(pending_transaction.nonce, 0);

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

// Send the transaction, the nonce (1) is automatically managed by the provider.
let builder = provider.send_transaction(tx).await?;
let node_hash = *builder.tx_hash();
let pending_transaction = provider.get_transaction_by_hash(node_hash).await?;
assert_eq!(pending_transaction.nonce, 1);

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

Ok(())
}
68 changes: 68 additions & 0 deletions examples/layers/examples/signer_layer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! Example of using the `SignerLayer` in the provider.
use alloy::{
network::{EthereumSigner, TransactionBuilder},
node_bindings::Anvil,
primitives::{address, b256, U256},
providers::{Provider, ProviderBuilder},
rpc::{client::RpcClient, types::eth::request::TransactionRequest},
signers::wallet::LocalWallet,
};
use eyre::Result;

#[tokio::main]
async fn main() -> Result<()> {
// Spin up a local Anvil node.
// Ensure `anvil` is available in $PATH
let anvil = Anvil::new().try_spawn()?;

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

// Create a provider with the signer.
let http = anvil.endpoint().parse()?;
let provider = ProviderBuilder::new()
// Add the `SignerLayer` to the provider
.signer(EthereumSigner::from(wallet))
.on_client(RpcClient::new_http(http));

// Create a legacy type transaction.
let tx = TransactionRequest::default()
.with_nonce(0)
.with_from(from)
.with_to(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into())
.with_value(U256::from(100))
.with_gas_price(U256::from(20e9))
.with_gas_limit(U256::from(21000));

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;
assert_eq!(receipt_hash, node_hash);

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

Ok(())
}
25 changes: 25 additions & 0 deletions examples/queries/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "examples-queries"

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.workspace = true
# alloy-network.workspace = true
# alloy-primitives.workspace = true
# alloy-provider = { workspace = true, features = ["pubsub", "ws"] }
# alloy-rpc-types.workspace = true
# alloy-rpc-client.workspace = true
# alloy-transport-http.workspace = true

eyre.workspace = true
futures-util = "0.3"
reqwest.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
25 changes: 25 additions & 0 deletions examples/queries/examples/query_contract_storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! Example of querying contract storage from the Ethereum network.
use alloy::{
network::Ethereum,
primitives::{address, U256},
providers::{Provider, RootProvider},
};
use eyre::Result;

#[tokio::main]
async fn main() -> Result<()> {
let url = "https://eth.merkle.io".parse().unwrap();
let provider = RootProvider::<Ethereum, _>::new_http(url);

// Get slot0 from USDC-ETH Uniswap V3 pool
let pool_address = address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640");

let storage_slot = U256::from(0);

let storage = provider.get_storage_at(pool_address, storage_slot, None).await?;

println!("Slot 0: {:?}", storage);

Ok(())
}
25 changes: 25 additions & 0 deletions examples/queries/examples/query_deployed_bytecode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! Example of querying deployed bytecode of a contract on Ethereum network.
use alloy::{
network::Ethereum,
primitives::address,
providers::{Provider, RootProvider},
rpc::types::eth::{BlockId, BlockNumberOrTag},
};
use eyre::Result;

#[tokio::main]
async fn main() -> Result<()> {
let url = "https://eth.merkle.io".parse().unwrap();
let provider = RootProvider::<Ethereum, _>::new_http(url);

// Get bytecode of USDC-ETH Uniswap V3 pool
let pool_address = address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640");

let bytecode =
provider.get_code_at(pool_address, BlockId::Number(BlockNumberOrTag::Latest)).await?;

println!("Bytecode: {:?}", bytecode);

Ok(())
}
51 changes: 51 additions & 0 deletions examples/queries/examples/query_logs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use alloy::{
network::Ethereum,
primitives::{address, fixed_bytes},
providers::{Provider, RootProvider},
rpc::types::eth::Filter,
};
use eyre::Result;
#[tokio::main]
async fn main() -> Result<()> {
let url = "https://eth.merkle.io".parse().unwrap();
let provider = RootProvider::<Ethereum, _>::new_http(url);

// Get logs from the latest block
let latest_block = provider.get_block_number().await?;

// Get all logs from the latest block
let filter = Filter::new().from_block(latest_block);

let logs = provider.get_logs(&filter).await?;

for log in logs {
println!("{:?}", log);
}

let tranfer_event_signature =
fixed_bytes!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef");

// Get all logs from the latest block that match the transfer event signature/topic
let filter = Filter::new().event_signature(tranfer_event_signature).from_block(latest_block);
// You could also use the event name instead of the event signature like so:
// .event("Transfer(address,address,uint256)")

let logs = provider.get_logs(&filter).await?;

for log in logs {
println!("Transfer event: {:?}", log);
}

let uni_address = address!("1f9840a85d5aF5bf1D1762F925BDADdC4201F984");

// Get all from the latest block emitted by the UNI token address
let filter = Filter::new().address(uni_address).from_block(latest_block);

let logs = provider.get_logs(&filter).await?;

for log in logs {
println!("UNI token logs: {:?}", log);
}

Ok(())
}
18 changes: 18 additions & 0 deletions examples/transactions/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "examples-transactions"

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.workspace = true

eyre.workspace = true
reqwest.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
Loading

0 comments on commit d443654

Please sign in to comment.