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        /// Timestamp of the block.
29        block_timestamp: u64,
30        /// base fee of the block.
31        base_fee: Option<u64>,
32    },
33}
34
35// === impl TransactionSource ===
36
37impl<T: SignedTransaction> TransactionSource<T> {
38    /// Consumes the type and returns the wrapped transaction.
39    pub fn into_recovered(self) -> Recovered<T> {
40        self.into()
41    }
42
43    /// Conversion into network specific transaction type.
44    pub fn into_transaction<Builder>(
45        self,
46        resp_builder: &Builder,
47    ) -> Result<RpcTransaction<Builder::Network>, Builder::Error>
48    where
49        Builder: RpcConvert<Primitives: NodePrimitives<SignedTx = T>>,
50    {
51        match self {
52            Self::Pool(tx) => resp_builder.fill_pending(tx),
53            Self::Block {
54                transaction,
55                index,
56                block_hash,
57                block_number,
58                block_timestamp,
59                base_fee,
60            } => {
61                let tx_info = TransactionInfo {
62                    hash: Some(transaction.trie_hash()),
63                    index: Some(index),
64                    block_hash: Some(block_hash),
65                    block_number: Some(block_number),
66                    block_timestamp: Some(block_timestamp),
67                    base_fee,
68                };
69
70                resp_builder.fill(transaction, tx_info)
71            }
72        }
73    }
74
75    /// Returns the transaction and block related info, if not pending
76    pub fn split(self) -> (Recovered<T>, TransactionInfo) {
77        match self {
78            Self::Pool(tx) => {
79                let hash = tx.trie_hash();
80                (tx, TransactionInfo { hash: Some(hash), ..Default::default() })
81            }
82            Self::Block {
83                transaction,
84                index,
85                block_hash,
86                block_number,
87                block_timestamp,
88                base_fee,
89            } => {
90                let hash = transaction.trie_hash();
91                (
92                    transaction,
93                    TransactionInfo {
94                        hash: Some(hash),
95                        index: Some(index),
96                        block_hash: Some(block_hash),
97                        block_number: Some(block_number),
98                        block_timestamp: Some(block_timestamp),
99                        base_fee,
100                    },
101                )
102            }
103        }
104    }
105}
106
107impl<T> From<TransactionSource<T>> for Recovered<T> {
108    fn from(value: TransactionSource<T>) -> Self {
109        match value {
110            TransactionSource::Pool(tx) => tx,
111            TransactionSource::Block { transaction, .. } => transaction,
112        }
113    }
114}