Skip to main content

ethrex_rpc/types/
transaction.rs

1use crate::utils::RpcErr;
2use ethrex_common::{
3    Address, H256, serde_utils,
4    types::{
5        BlockHash, BlockNumber, EIP1559Transaction, EIP2930Transaction, EIP7702Transaction,
6        FeeTokenTransaction, LegacyTransaction, PrivilegedL2Transaction, Transaction,
7        WrappedEIP4844Transaction,
8    },
9};
10use ethrex_crypto::NativeCrypto;
11use ethrex_rlp::{decode::RLPDecode, error::RLPDecodeError};
12use serde::{Deserialize, Serialize};
13
14#[allow(unused)]
15#[derive(Debug, Serialize, Deserialize)]
16#[serde(rename_all = "camelCase")]
17pub struct RpcTransaction {
18    #[serde(flatten)]
19    pub tx: Transaction,
20    #[serde(with = "serde_utils::u64::hex_str_opt")]
21    block_number: Option<BlockNumber>,
22    block_hash: Option<BlockHash>,
23    from: Address,
24    pub hash: H256,
25    #[serde(with = "serde_utils::u64::hex_str_opt")]
26    transaction_index: Option<u64>,
27}
28
29impl RpcTransaction {
30    pub fn build(
31        tx: Transaction,
32        block_number: Option<BlockNumber>,
33        block_hash: Option<BlockHash>,
34        transaction_index: Option<usize>,
35    ) -> Result<Self, RpcErr> {
36        let from = tx.sender(&NativeCrypto)?;
37        let hash = tx.hash();
38        let transaction_index = transaction_index.map(|n| n as u64);
39        Ok(RpcTransaction {
40            tx,
41            block_number,
42            block_hash,
43            from,
44            hash,
45            transaction_index,
46        })
47    }
48}
49
50#[derive(Debug)]
51pub enum SendRawTransactionRequest {
52    Legacy(LegacyTransaction),
53    EIP2930(EIP2930Transaction),
54    EIP1559(EIP1559Transaction),
55    EIP4844(WrappedEIP4844Transaction),
56    EIP7702(EIP7702Transaction),
57    PrivilegedL2(PrivilegedL2Transaction),
58    FeeToken(FeeTokenTransaction),
59}
60
61impl SendRawTransactionRequest {
62    pub fn to_transaction(&self) -> Transaction {
63        match self {
64            SendRawTransactionRequest::Legacy(t) => Transaction::LegacyTransaction(t.clone()),
65            SendRawTransactionRequest::EIP1559(t) => Transaction::EIP1559Transaction(t.clone()),
66            SendRawTransactionRequest::EIP2930(t) => Transaction::EIP2930Transaction(t.clone()),
67            SendRawTransactionRequest::EIP4844(t) => Transaction::EIP4844Transaction(t.tx.clone()),
68            SendRawTransactionRequest::EIP7702(t) => Transaction::EIP7702Transaction(t.clone()),
69            SendRawTransactionRequest::PrivilegedL2(t) => {
70                Transaction::PrivilegedL2Transaction(t.clone())
71            }
72            SendRawTransactionRequest::FeeToken(t) => Transaction::FeeTokenTransaction(t.clone()),
73        }
74    }
75
76    pub fn decode_canonical(bytes: &[u8]) -> Result<Self, RLPDecodeError> {
77        // Look at the first byte to check if it corresponds to a TransactionType
78        match bytes.first() {
79            // First byte is a valid TransactionType https://eips.ethereum.org/EIPS/eip-2718#transactiontype-only-goes-up-to-0x7f
80            Some(tx_type) if *tx_type <= 0x7f => {
81                // Decode tx based on type
82                let tx_bytes = &bytes[1..];
83
84                match *tx_type {
85                    // Legacy
86                    0x0 => {
87                        LegacyTransaction::decode(tx_bytes).map(SendRawTransactionRequest::Legacy)
88                    }
89                    // EIP2930
90                    0x1 => {
91                        EIP2930Transaction::decode(tx_bytes).map(SendRawTransactionRequest::EIP2930)
92                    }
93                    // EIP1559
94                    0x2 => {
95                        EIP1559Transaction::decode(tx_bytes).map(SendRawTransactionRequest::EIP1559)
96                    }
97                    // EIP4844
98                    0x3 => WrappedEIP4844Transaction::decode(tx_bytes)
99                        .map(SendRawTransactionRequest::EIP4844),
100                    // EIP7702
101                    0x4 => {
102                        EIP7702Transaction::decode(tx_bytes).map(SendRawTransactionRequest::EIP7702)
103                    }
104                    // FeeTokenTransaction
105                    0x7d => FeeTokenTransaction::decode(tx_bytes)
106                        .map(SendRawTransactionRequest::FeeToken),
107                    // PrivilegedL2Transaction
108                    0x7e => PrivilegedL2Transaction::decode(tx_bytes)
109                        .map(SendRawTransactionRequest::PrivilegedL2),
110                    ty => Err(RLPDecodeError::Custom(format!(
111                        "Invalid transaction type: {ty}"
112                    ))),
113                }
114            }
115            // LegacyTransaction
116            _ => LegacyTransaction::decode(bytes).map(SendRawTransactionRequest::Legacy),
117        }
118    }
119}