ethrex_rpc/types/
transaction.rs1use 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 match bytes.first() {
79 Some(tx_type) if *tx_type <= 0x7f => {
81 let tx_bytes = &bytes[1..];
83
84 match *tx_type {
85 0x0 => {
87 LegacyTransaction::decode(tx_bytes).map(SendRawTransactionRequest::Legacy)
88 }
89 0x1 => {
91 EIP2930Transaction::decode(tx_bytes).map(SendRawTransactionRequest::EIP2930)
92 }
93 0x2 => {
95 EIP1559Transaction::decode(tx_bytes).map(SendRawTransactionRequest::EIP1559)
96 }
97 0x3 => WrappedEIP4844Transaction::decode(tx_bytes)
99 .map(SendRawTransactionRequest::EIP4844),
100 0x4 => {
102 EIP7702Transaction::decode(tx_bytes).map(SendRawTransactionRequest::EIP7702)
103 }
104 0x7d => FeeTokenTransaction::decode(tx_bytes)
106 .map(SendRawTransactionRequest::FeeToken),
107 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::decode(bytes).map(SendRawTransactionRequest::Legacy),
117 }
118 }
119}