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