Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(provider): provider examples #3

Merged
merged 13 commits into from
Mar 25, 2024
Binary file added .DS_Store
Binary file not shown.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ license = "MIT OR Apache-2.0"
homepage = "https://github.com/alloy-rs/examples"
repository = "https://github.com/alloy-rs/examples"
publish = false
exclude = ["examples/"]

[workspace.dependencies]
alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4f", default-features = false }
Expand All @@ -35,7 +36,9 @@ alloy-signer-trezor = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4
alloy-signer-wallet = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4f", default-features = false }
alloy-transport = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4f", default-features = false }
alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4f", default-features = false }
alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4f", default-features = false }
alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4f", default-features = false, features = [
"mock",
] }
alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "e7dfb4f", default-features = false }

alloy-core = { version = "0.6.4", default-features = false, features = ["std"] }
Expand Down
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,11 @@ cargo run --example mnemonic_signer
- [ ] Signer
- [ ] Time lag
- [ ] Transformer
- [ ] Providers
- [ ] Http
- [ ] IPC
- [ ] Mock
- [ ] Quorum
- [ ] Retry
- [ ] RW
- [ ] WS
- [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
Expand Down
Binary file added examples/.DS_Store
Binary file not shown.
33 changes: 33 additions & 0 deletions examples/providers/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "examples-providers"

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-contract.workspace = true
alloy-primitives.workspace = true
alloy-provider = { workspace = true, features = ["pubsub", "ws"] }
alloy-pubsub.workspace = true
alloy-sol-types = { workspace = true, features = ["json"] }
alloy-rpc-types.workspace = true
alloy-rpc-client.workspace = true
alloy-rpc-trace-types.workspace = true
alloy-signer-wallet.workspace = true
alloy-transport.workspace = true
alloy-transport-http.workspace = true
alloy-transport-ws.workspace = true
alloy-transport-ipc.workspace = true
zerosnacks marked this conversation as resolved.
Show resolved Hide resolved

eyre.workspace = true
futures-util = "0.3"
reqwest.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
48 changes: 48 additions & 0 deletions examples/providers/examples/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Example of using the `ProviderBuilder` to create a provider with a signer and network.

use alloy_network::{Ethereum, EthereumSigner, TransactionBuilder};
use alloy_node_bindings::Anvil;
use alloy_primitives::{U256, U64};
use alloy_provider::{Provider, ProviderBuilder, RootProvider};
use alloy_rpc_client::RpcClient;
use alloy_rpc_types::TransactionRequest;
use alloy_signer_wallet::Wallet;
use alloy_transport_http::Http;
use eyre::Result;
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<()> {
// Setup the HTTP transport which is consumed by the RPC client
let anvil = Anvil::new().spawn();

let pk = &anvil.keys()[0];
let from = anvil.addresses()[0];
let signer = Wallet::from(pk.to_owned());

let rpc_client = RpcClient::new(Http::<Client>::new(anvil.endpoint().parse().unwrap()), false);
let provider_with_signer = ProviderBuilder::<_, Ethereum>::new()
.signer(EthereumSigner::from(signer))
.network::<Ethereum>()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shouldn't be necessary anymore

.provider(RootProvider::new(rpc_client));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideal UX here is alloy_network::Ethereum::builder().signer(signer).connect(anvil.endpoint()). We should strive to get to that, incl the gas / nonce filling layer being on by default with the option to turn it off with .manual() or something. cc @onbjerg @DaniPopes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now ::<_, Ethereum> and .network are not necessary anymore: alloy-rs/alloy#304


let to = anvil.addresses()[1];

let mut tx_req = TransactionRequest::default()
.to(Some(to))
.value(U256::from(100))
.nonce(U64::from(0))
mattsse marked this conversation as resolved.
Show resolved Hide resolved
.gas_limit(U256::from(21000));

tx_req.set_gas_price(U256::from(20e9));

let pending_tx = provider_with_signer.send_transaction(tx_req).await?;

println!("Pending transaction...{:?}", pending_tx.tx_hash());

let receipt = pending_tx.get_receipt().await?;

assert_eq!(receipt.from, from);

Ok(())
}
29 changes: 29 additions & 0 deletions examples/providers/examples/http.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! Example of using the HTTP provider to get the latest block number.

use alloy_network::Ethereum;
use alloy_provider::{HttpProvider, Provider};
use alloy_rpc_client::RpcClient;
use alloy_transport_http::Http;
use eyre::Result;
use reqwest::Client;

#[tokio::main]
async fn main() -> Result<()> {
// Setup the HTTP transport which is consumed by the RPC client
let rpc_url = "https://eth.llamarpc.com".parse().unwrap();
let http = Http::<Client>::new(rpc_url);

// Create the RPC client
let rpc_client = RpcClient::new(http, false);

// Provider can then be instantiated using the RPC client, HttpProvider is an alias
// RootProvider. RootProvider requires two generics N: Network and T: Transport
let provider = HttpProvider::<Ethereum>::new(rpc_client);

// Get latest block number
let latest_block = provider.get_block_number().await?;

println!("Latest block number: {}", latest_block);

Ok(())
}
27 changes: 27 additions & 0 deletions examples/providers/examples/ipc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//! Example of using the IPC provider to get the latest block number.

use alloy_network::Ethereum;
use alloy_provider::{Provider, RootProvider};
use alloy_rpc_client::RpcClient;
use alloy_transport_ipc::IpcConnect;
use eyre::Result;

#[tokio::main]
async fn main() -> Result<()> {
// Setup the IPC transport which is consumed by the RPC client
let ipc_path = "/tmp/reth.ipc";

// IPC transport
let ipc = IpcConnect::from(ipc_path.to_string());

// RPC client using IPC transport
let ipc_client = RpcClient::connect_pubsub(ipc).await?;

let provider = RootProvider::<Ethereum, _>::new(ipc_client);

let latest_block = provider.get_block_number().await?;

println!("Latest block: {}", latest_block);

Ok(())
}
29 changes: 29 additions & 0 deletions examples/providers/examples/ws.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! Example of using the WS provider to subscribe to new blocks.

use alloy_network::Ethereum;
use alloy_provider::{Provider, RootProvider};
use alloy_rpc_client::{RpcClient, WsConnect};
use eyre::Result;
use futures_util::StreamExt;

#[tokio::main]
async fn main() -> Result<()> {
let rpc_url = "wss://eth-mainnet.g.alchemy.com/v2/your-api-key";

let ws_transport = WsConnect::new(rpc_url);

let rpc_client = RpcClient::connect_pubsub(ws_transport).await?;

let provider = RootProvider::<Ethereum, _>::new(rpc_client);

let sub = provider.subscribe_blocks().await?;

let mut stream = sub.into_stream().take(4);
println!("Awaiting blocks...");

while let Some(block) = stream.next().await {
println!("{:?}", block.header.number);
}

Ok(())
}
46 changes: 46 additions & 0 deletions examples/providers/examples/ws_with_auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Example of using the WS provider with auth to subscribe to new blocks.

use alloy_network::Ethereum;
use alloy_provider::{Provider, RootProvider};
use alloy_rpc_client::{RpcClient, WsConnect};
use alloy_transport::Authorization;
use eyre::Result;
use futures_util::StreamExt;

#[tokio::main]
async fn main() -> Result<()> {
let rpc_url = "wss://your-ws-endpoint.com/";

let auth = Authorization::basic("username", "password");
let auth_bearer = Authorization::bearer("bearer-token");

let ws_transport_basic = WsConnect::with_auth(rpc_url, Some(auth));

let ws_transport_bearer = WsConnect::with_auth(rpc_url, Some(auth_bearer));

let rpc_client_basic = RpcClient::connect_pubsub(ws_transport_basic).await?;

let rpc_client_bearer = RpcClient::connect_pubsub(ws_transport_bearer).await?;

let provider_basic = RootProvider::<Ethereum, _>::new(rpc_client_basic);

let provider_bearer = RootProvider::<Ethereum, _>::new(rpc_client_bearer);

let sub_basic = provider_basic.subscribe_blocks();
let sub_bearer = provider_bearer.subscribe_blocks();

let mut stream_basic = sub_basic.await?.into_stream().take(4);
let mut stream_bearer = sub_bearer.await?.into_stream().take(4);

println!("Awaiting blocks...");

while let Some(block) = stream_basic.next().await {
println!("From basic {:?}", block.header.number);
}
yash-atreya marked this conversation as resolved.
Show resolved Hide resolved

while let Some(block) = stream_bearer.next().await {
println!("From bearer {:?}", block.header.number);
}

Ok(())
}
Loading