reth_rpc_eth_types/
transaction.rs

1//! Helper types for `reth_rpc_eth_api::EthApiServer` implementation.
2//!
3//! Transaction wrapper that labels transaction with its origin.
4
5use alloy_primitives::B256;
6use alloy_rpc_types_eth::TransactionInfo;
7use reth_primitives::{RecoveredTx, TransactionSigned};
8use reth_primitives_traits::SignedTransaction;
9use reth_rpc_types_compat::{
10    transaction::{from_recovered, from_recovered_with_block_context},
11    TransactionCompat,
12};
13
14/// Represents from where a transaction was fetched.
15#[derive(Debug, Clone, Eq, PartialEq)]
16pub enum TransactionSource<T = TransactionSigned> {
17    /// Transaction exists in the pool (Pending)
18    Pool(RecoveredTx<T>),
19    /// Transaction already included in a block
20    ///
21    /// This can be a historical block or a pending block (received from the CL)
22    Block {
23        /// Transaction fetched via provider
24        transaction: RecoveredTx<T>,
25        /// Index of the transaction in the block
26        index: u64,
27        /// Hash of the block.
28        block_hash: B256,
29        /// Number of the block.
30        block_number: u64,
31        /// base fee of the block.
32        base_fee: Option<u64>,
33    },
34}
35
36// === impl TransactionSource ===
37
38impl<T: SignedTransaction> TransactionSource<T> {
39    /// Consumes the type and returns the wrapped transaction.
40    pub fn into_recovered(self) -> RecoveredTx<T> {
41        self.into()
42    }
43
44    /// Conversion into network specific transaction type.
45    pub fn into_transaction<Builder: TransactionCompat<T>>(
46        self,
47        resp_builder: &Builder,
48    ) -> Result<Builder::Transaction, Builder::Error> {
49        match self {
50            Self::Pool(tx) => from_recovered(tx, resp_builder),
51            Self::Block { transaction, index, block_hash, block_number, base_fee } => {
52                let tx_info = TransactionInfo {
53                    hash: Some(transaction.trie_hash()),
54                    index: Some(index),
55                    block_hash: Some(block_hash),
56                    block_number: Some(block_number),
57                    base_fee: base_fee.map(u128::from),
58                    tx_type: Some(transaction.ty() as isize),
59                };
60
61                from_recovered_with_block_context(transaction, tx_info, resp_builder)
62            }
63        }
64    }
65
66    /// Returns the transaction and block related info, if not pending
67    pub fn split(self) -> (RecoveredTx<T>, TransactionInfo) {
68        match self {
69            Self::Pool(tx) => {
70                let hash = tx.trie_hash();
71                (tx, TransactionInfo { hash: Some(hash), ..Default::default() })
72            }
73            Self::Block { transaction, index, block_hash, block_number, base_fee } => {
74                let tx_type = Some(transaction.ty() as isize);
75                let hash = transaction.trie_hash();
76                (
77                    transaction,
78                    TransactionInfo {
79                        hash: Some(hash),
80                        index: Some(index),
81                        block_hash: Some(block_hash),
82                        block_number: Some(block_number),
83                        base_fee: base_fee.map(u128::from),
84                        tx_type,
85                    },
86                )
87            }
88        }
89    }
90}
91
92impl<T> From<TransactionSource<T>> for RecoveredTx<T> {
93    fn from(value: TransactionSource<T>) -> Self {
94        match value {
95            TransactionSource::Pool(tx) => tx,
96            TransactionSource::Block { transaction, .. } => transaction,
97        }
98    }
99}