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::{Bytes, 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};
10use serde::{Deserialize, Serialize};
11
12/// Response type for `eth_fillTransaction` RPC method.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct FillTransactionResult<T> {
15    /// RLP-encoded transaction bytes
16    pub raw: Bytes,
17    /// Filled transaction object
18    pub tx: T,
19}
20
21/// Represents from where a transaction was fetched.
22#[derive(Debug, Clone, Eq, PartialEq)]
23pub enum TransactionSource<T = TransactionSigned> {
24    /// Transaction exists in the pool (Pending)
25    Pool(Recovered<T>),
26    /// Transaction already included in a block
27    ///
28    /// This can be a historical block or a pending block (received from the CL)
29    Block {
30        /// Transaction fetched via provider
31        transaction: Recovered<T>,
32        /// Index of the transaction in the block
33        index: u64,
34        /// Hash of the block.
35        block_hash: B256,
36        /// Number of the block.
37        block_number: u64,
38        /// base fee of the block.
39        base_fee: Option<u64>,
40    },
41}
42
43// === impl TransactionSource ===
44
45impl<T: SignedTransaction> TransactionSource<T> {
46    /// Consumes the type and returns the wrapped transaction.
47    pub fn into_recovered(self) -> Recovered<T> {
48        self.into()
49    }
50
51    /// Conversion into network specific transaction type.
52    pub fn into_transaction<Builder>(
53        self,
54        resp_builder: &Builder,
55    ) -> Result<RpcTransaction<Builder::Network>, Builder::Error>
56    where
57        Builder: RpcConvert<Primitives: NodePrimitives<SignedTx = T>>,
58    {
59        match self {
60            Self::Pool(tx) => resp_builder.fill_pending(tx),
61            Self::Block { transaction, index, block_hash, block_number, base_fee } => {
62                let tx_info = TransactionInfo {
63                    hash: Some(transaction.trie_hash()),
64                    index: Some(index),
65                    block_hash: Some(block_hash),
66                    block_number: Some(block_number),
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 { transaction, index, block_hash, block_number, base_fee } => {
83                let hash = transaction.trie_hash();
84                (
85                    transaction,
86                    TransactionInfo {
87                        hash: Some(hash),
88                        index: Some(index),
89                        block_hash: Some(block_hash),
90                        block_number: Some(block_number),
91                        base_fee,
92                    },
93                )
94            }
95        }
96    }
97}
98
99impl<T> From<TransactionSource<T>> for Recovered<T> {
100    fn from(value: TransactionSource<T>) -> Self {
101        match value {
102            TransactionSource::Pool(tx) => tx,
103            TransactionSource::Block { transaction, .. } => transaction,
104        }
105    }
106}