Sitelet https://github.com/SharkHand3/examples/commit/670469d153ddc9b326b93676317243e17eb8fb1e
Skip to content

Commit 670469d

Browse files
authored
Add send_private_transaction using Flashbots Protect (alloy-rs#93)
* clean up and add send_private_transaction with explainer * document * note on invalid state of request
1 parent b7463d7 commit 670469d

11 files changed

Lines changed: 91 additions & 11 deletions

File tree

‎Cargo.toml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ type_repetition_in_bounds = "allow"
8080
unnecessary_struct_initialization = "allow"
8181

8282
[workspace.dependencies]
83-
alloy = { git = "https://github.com/alloy-rs/alloy", rev = "3edca45", features = [
83+
alloy = { git = "https://github.com/alloy-rs/alloy", rev = "dc56a76", features = [
8484
"consensus",
8585
"contract",
8686
"eips",
@@ -94,6 +94,7 @@ alloy = { git = "https://github.com/alloy-rs/alloy", rev = "3edca45", features =
9494
"rpc-client-ipc",
9595
"rpc-client-ws",
9696
"rpc-client",
97+
"rpc-types",
9798
"rpc-types-eth",
9899
"rpc-types-trace",
99100
"signer-aws",

‎README.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ This repository contains the following examples:
6969
- [x] [Transfer ERC20 token](./examples/transactions/examples/transfer_erc20.rs)
7070
- [x] [Transfer ETH](./examples/transactions/examples/transfer_eth.rs)
7171
- [x] [Sign and send a raw transaction](./examples/transactions/examples/sign_transaction.rs)
72-
- [x] [Send EIP-1559 transaction](./examples/transactions/examples/send_eip1559_tx.rs)
73-
- [x] [Send legacy transaction](./examples/transactions/examples/send_legacy_tx.rs)
74-
- [x] [Send EIP-4844 transaction](./examples/transactions/examples/send_eip4844_tx.rs)
72+
- [x] [Send EIP-1559 transaction](./examples/transactions/examples/send_eip1559_transaction.rs)
73+
- [x] [Send legacy transaction](./examples/transactions/examples/send_legacy_transaction.rs)
74+
- [x] [Send EIP-4844 transaction](./examples/transactions/examples/send_eip4844_transaction.rs)
75+
- [x] [Send private transaction using Flashbots Protect](./examples/transactions/examples/send_private_transaction.rs)
7576
- [x] [Send transaction with access list](./examples/transactions/examples/with_access_list.rs)
7677
- [x] Wallets
7778
- [x] [AWS signer](./examples/wallets/examples/aws_signer.rs)

‎examples/providers/examples/builder.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ async fn main() -> Result<()> {
1717
let anvil = Anvil::new().block_time(1).try_spawn()?;
1818

1919
// Set up signer from the first default Anvil account (Alice).
20-
let wallet: LocalWallet = anvil.keys()[0].clone().into();
20+
let signer: LocalWallet = anvil.keys()[0].clone().into();
2121

2222
// Create two users, Alice and Bob.
23-
let alice = wallet.address();
23+
let alice = signer.address();
2424
let bob = anvil.addresses()[1];
2525

2626
// Set up the HTTP provider with the `reqwest` crate.
2727
let rpc_url = anvil.endpoint().parse()?;
2828
let provider = ProviderBuilder::new()
2929
.with_recommended_fillers()
30-
.signer(EthereumSigner::from(wallet))
30+
.signer(EthereumSigner::from(signer))
3131
.on_http(rpc_url);
3232

3333
// Create a transaction.

examples/transactions/examples/send_eip1559_tx.rs renamed to examples/transactions/examples/send_eip1559_transaction.rs

File renamed without changes.

examples/transactions/examples/send_eip4844_tx.rs renamed to examples/transactions/examples/send_eip4844_transaction.rs

File renamed without changes.
File renamed without changes.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//! Example of sending a private transaction using Flashbots Protect.
2+
3+
use alloy::{
4+
network::{eip2718::Encodable2718, EthereumSigner, TransactionBuilder},
5+
primitives::U256,
6+
providers::{Provider, ProviderBuilder},
7+
rpc::types::eth::TransactionRequest,
8+
signers::wallet::LocalWallet,
9+
};
10+
use eyre::Result;
11+
12+
#[tokio::main]
13+
async fn main() -> Result<()> {
14+
// Set up the HTTP transport which is consumed by the RPC client.
15+
//
16+
// By default, Flashbots Protect transactions are only shared with the Flashbots Builder, which
17+
// builds only a subset of all Ethereum blocks. In `fast` mode, transactions are shared with
18+
// all registered builders no less than one block after they are received to increase the
19+
// number of blocks the user's transaction can be included in.
20+
//
21+
// Fast mode has 2 key differences from the default Protect experience:
22+
// - Shared with all builders: By default, Flashbots Protect transactions are only shared with
23+
// the Flashbots Builder, which builds only a subset of all Ethereum blocks. In fast mode,
24+
// transactions are shared with all registered builders no less than one block after they are
25+
// received to increase the number of blocks the user's transaction can be included in.
26+
// - Larger refund paid to validator: By default, only 10% of MEV-Share refunds are paid to
27+
// validators. In fast mode, validators receive 50% of refunds which makes it more likely that
28+
// the user’s transactions will be chosen in a given block.
29+
//
30+
// For more information, see the [Flashbots documentation](https://docs.flashbots.net/flashbots-protect/overview).
31+
//
32+
// To use `fast` mode change the URL to `https://rpc.flashbots.net/fast`.
33+
let flashbots_url = "https://rpc.flashbots.net".parse()?;
34+
35+
// Create a provider.
36+
let provider = ProviderBuilder::new().on_http(flashbots_url);
37+
38+
// Create a signer from a random wallet.
39+
let signer = LocalWallet::random();
40+
41+
// Create two users, Alice and Bob.
42+
let alice = signer.address();
43+
let bob = LocalWallet::random().address();
44+
45+
// Build a transaction to send 100 wei from Alice to Bob.
46+
let tx = TransactionRequest::default()
47+
.with_from(alice)
48+
.with_to(bob)
49+
.with_nonce(0)
50+
.with_chain_id(1)
51+
.with_value(U256::from(100))
52+
.with_gas_limit(21_000)
53+
.with_max_priority_fee_per_gas(1_000_000_000)
54+
.with_max_fee_per_gas(20_000_000_000);
55+
56+
// Build the transaction using the `EthereumSigner` with the provided signer.
57+
// Flashbots Protect requires the transaction to be signed locally and send using
58+
// `eth_sendRawTransaction`.
59+
let tx_envelope = tx.build(&EthereumSigner::from(signer)).await?;
60+
61+
// Encode the transaction using EIP-2718 encoding.
62+
let tx_encoded = tx_envelope.encoded_2718();
63+
64+
// Send the raw transaction. The transaction is sent to the Flashbots relay and, if valid, will
65+
// be included in a block by a Flashbots builder. Note that the transaction request, as defined,
66+
// is invalid and will not be included in the blockchain.
67+
let pending = provider.send_raw_transaction(&tx_encoded).await?.register().await?;
68+
69+
println!("Send transaction: {}", pending.tx_hash());
70+
71+
Ok(())
72+
}

‎examples/transactions/examples/sign_transaction.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ async fn main() -> Result<()> {
3939
.with_max_priority_fee_per_gas(1_000_000_000)
4040
.with_max_fee_per_gas(20_000_000_000);
4141

42-
// Build the transaction using the EthereumSigner with the provided signer.
42+
// Build the transaction using the `EthereumSigner` with the provided signer.
4343
let tx_envelope = tx.build(&signer).await?;
4444

4545
// Encode the transaction using EIP-2718 encoding.

‎examples/wallets/examples/ledger_signer.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ use eyre::Result;
1414

1515
#[tokio::main]
1616
async fn main() -> Result<()> {
17+
// Set up the HTTP transport which is consumed by the RPC client.
18+
let rpc_url = "https://eth.merkle.io".parse()?;
19+
1720
// Instantiate the application by acquiring a lock on the Ledger device.
1821
let signer = LedgerSigner::new(HDPath::LedgerLive(0), Some(1)).await?;
1922
let from = signer.address();
2023

2124
// Create a provider with the signer.
22-
let rpc_url = "http://localhost:8545".parse()?;
2325
let provider = ProviderBuilder::new()
2426
.with_recommended_fillers()
2527
.signer(EthereumSigner::from(signer))

‎examples/wallets/examples/trezor_signer.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ use eyre::Result;
1414

1515
#[tokio::main]
1616
async fn main() -> Result<()> {
17+
// Set up the HTTP transport which is consumed by the RPC client.
18+
let rpc_url = "https://eth.merkle.io".parse()?;
19+
1720
// Instantiate the application by acquiring a lock on the Trezor device.
1821
let signer = TrezorSigner::new(HDPath::TrezorLive(0), Some(1)).await?;
1922
let from = signer.address();
2023

2124
// Create a provider with the signer.
22-
let rpc_url = "http://localhost:8545".parse()?;
2325
let provider = ProviderBuilder::new()
2426
.with_recommended_fillers()
2527
.signer(EthereumSigner::from(signer))

0 commit comments

Comments
 (0)