Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions examples/txpool-tracing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ edition.workspace = true
license.workspace = true

[dependencies]
reth-ethereum = { workspace = true, features = ["node", "pool", "cli"] }
reth-ethereum = { workspace = true, features = ["node", "pool", "cli", "rpc"] }

alloy-primitives.workspace = true
alloy-rpc-types-trace.workspace = true
alloy-network.workspace = true

clap = { workspace = true, features = ["derive"] }
futures-util.workspace = true
alloy-primitives.workspace = true
eyre.workspace = true
2 changes: 2 additions & 0 deletions examples/txpool-tracing/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use reth_ethereum::{
rpc::eth::primitives::TransactionRequest,
};

mod submit;

fn main() {
Cli::<EthereumChainSpecParser, RethCliTxpoolExt>::parse()
.run(|builder, args| async move {
Expand Down
133 changes: 133 additions & 0 deletions examples/txpool-tracing/src/submit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//! Transaction submission functionality for the txpool tracing example
#![allow(unused)]
#![allow(clippy::too_many_arguments)]

use alloy_network::{Ethereum, EthereumWallet, NetworkWallet, TransactionBuilder};
use alloy_primitives::{Address, TxHash, U256};
use futures_util::StreamExt;
use reth_ethereum::{
node::api::{FullNodeComponents, NodeTypes},
pool::{PoolTransaction, TransactionEvent, TransactionOrigin, TransactionPool},
primitives::SignerRecoverable,
rpc::eth::primitives::TransactionRequest,
EthPrimitives, TransactionSigned,
};

/// Submit a transaction to the transaction pool
///
/// This function demonstrates how to create, sign, and submit a transaction
/// to the reth transaction pool.
pub async fn submit_transaction<FC>(
node: &FC,
wallet: &EthereumWallet,
to: Address,
data: Vec<u8>,
nonce: u64,
chain_id: u64,
gas_limit: u64,
max_priority_fee_per_gas: u128,
max_fee_per_gas: u128,
) -> eyre::Result<TxHash>
where
// This enforces `EthPrimitives` types for this node, this unlocks the proper conversions when
FC: FullNodeComponents<Types: NodeTypes<Primitives = EthPrimitives>>,
{
// Create the transaction request
let request = TransactionRequest::default()
.with_to(to)
.with_input(data)
.with_nonce(nonce)
.with_chain_id(chain_id)
.with_gas_limit(gas_limit)
.with_max_priority_fee_per_gas(max_priority_fee_per_gas)
.with_max_fee_per_gas(max_fee_per_gas);

// Sign the transaction
let transaction: TransactionSigned =
NetworkWallet::<Ethereum>::sign_request(wallet, request).await?.into();
// Get the transaction hash before submitting
let tx_hash = *transaction.hash();

// Recover the transaction
let transaction = transaction.try_into_recovered()?;

// Convert to pool transaction type
let pool_transaction =
<FC::Pool as TransactionPool>::Transaction::try_from_consensus(transaction)
.map_err(|e| eyre::eyre!("Failed to convert to pool transaction: {e}"))?;

// Submit the transaction to the pool and get event stream
let mut tx_events = node
.pool()
.add_transaction_and_subscribe(TransactionOrigin::Local, pool_transaction)
.await?;

// Wait for the transaction to be added to the pool
while let Some(event) = tx_events.next().await {
match event {
TransactionEvent::Mined(_) => {
println!("Transaction was mined: {:?}", tx_events.hash());
break;
}
TransactionEvent::Pending => {
println!("Transaction added to pending pool: {:?}", tx_events.hash());
break;
}
TransactionEvent::Discarded => {
return Err(eyre::eyre!("Transaction discarded: {:?}", tx_events.hash(),));
}
_ => {
// Continue waiting for added or rejected event
}
}
}

Ok(tx_hash)
}

/// Helper function to submit a simple ETH transfer transaction
///
/// This will first populate a tx request, sign it then submit to the pool in the required format.
pub async fn submit_eth_transfer<FC>(
node: &FC,
wallet: &EthereumWallet,
to: Address,
value: U256,
nonce: u64,
chain_id: u64,
gas_limit: u64,
max_priority_fee_per_gas: u128,
max_fee_per_gas: u128,
) -> eyre::Result<TxHash>
where
FC: FullNodeComponents<Types: NodeTypes<Primitives = EthPrimitives>>,
{
// Create the transaction request for ETH transfer
let request = TransactionRequest::default()
.with_to(to)
.with_value(value)
.with_nonce(nonce)
.with_chain_id(chain_id)
.with_gas_limit(gas_limit)
.with_max_priority_fee_per_gas(max_priority_fee_per_gas)
.with_max_fee_per_gas(max_fee_per_gas);

// Sign the transaction
let transaction: TransactionSigned =
NetworkWallet::<Ethereum>::sign_request(wallet, request).await?.into();
// Recover the transaction
let transaction = transaction.try_into_recovered()?;

// Get the transaction hash
let tx_hash = *transaction.hash();

// Convert to pool transaction type
let pool_transaction =
<FC::Pool as TransactionPool>::Transaction::try_from_consensus(transaction)
.map_err(|e| eyre::eyre!("Failed to convert to pool transaction: {e}"))?;

// Submit the transaction to the pool
node.pool().add_transaction(TransactionOrigin::Local, pool_transaction).await?;

Ok(tx_hash)
}
Loading