Skip to main content

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_ethereum_primitives::TransactionSigned;
8use reth_primitives_traits::{NodePrimitives, Recovered, SignedTransaction};
9use reth_rpc_convert::{RpcConvert, RpcTransaction};
10
11/// Represents from where a transaction was fetched.
12#[derive(Debug, Clone, Eq, PartialEq)]
13pub enum TransactionSource<T = TransactionSigned> {
14    /// Transaction exists in the pool (Pending)
15    Pool(Recovered<T>),
16    /// Transaction already included in a block
17    ///
18    /// This can be a historical block or a pending block (received from the CL)
19    Block {
20        /// Transaction fetched via provider
21        transaction: Recovered<T>,
22        /// Index of the transaction in the block
23        index: u64,
24        /// Hash of the block.
25        block_hash: B256,
26        /// Number of the block.
27        block_number: u64,
28        /// base fee of the block.
29        base_fee: Option<u64>,
30    },
31}
32
33// === impl TransactionSource ===
34
35impl<T: SignedTransaction> TransactionSource<T> {
36    /// Consumes the type and returns the wrapped transaction.
37    pub fn into_recovered(self) -> Recovered<T> {
38        self.into()
39    }
40
41    /// Conversion into network specific transaction type.
42    pub fn into_transaction<Builder>(
43        self,
44        resp_builder: &Builder,
45    ) -> Result<RpcTransaction<Builder::Network>, Builder::Error>
46    where
47        Builder: RpcConvert<Primitives: NodePrimitives<SignedTx = T>>,
48    {
49        match self {
50            Self::Pool(tx) => resp_builder.fill_pending(tx),
51            Self::Block { transaction, index, block_hash, block_number, base_fee } => {
52                #[allow(clippy::needless_update)]
53                let tx_info = TransactionInfo {
54                    hash: Some(transaction.trie_hash()),
55                    index: Some(index),
56                    block_hash: Some(block_hash),
57                    block_number: Some(block_number),
58                    base_fee,
59                    ..Default::default()
60                };
61
62                resp_builder.fill(transaction, tx_info)
63            }
64        }
65    }
66
67    /// Returns the transaction and block related info, if not pending
68    pub fn split(self) -> (Recovered<T>, TransactionInfo) {
69        match self {
70            Self::Pool(tx) => {
71                let hash = tx.trie_hash();
72                (tx, TransactionInfo { hash: Some(hash), ..Default::default() })
73            }
74            #[allow(clippy::needless_update)]
75            Self::Block { transaction, index, block_hash, block_number, base_fee } => {
76                let hash = transaction.trie_hash();
77                (
78                    transaction,
79                    TransactionInfo {
80                        hash: Some(hash),
81                        index: Some(index),
82                        block_hash: Some(block_hash),
83                        block_number: Some(block_number),
84                        base_fee,
85                        ..Default::default()
86                    },
87                )
88            }
89        }
90    }
91}
92
93impl<T> From<TransactionSource<T>> for Recovered<T> {
94    fn from(value: TransactionSource<T>) -> Self {
95        match value {
96            TransactionSource::Pool(tx) => tx,
97            TransactionSource::Block { transaction, .. } => transaction,
98        }
99    }
100}