reth_rpc/eth/helpers/
types.rs1use alloy_consensus::{Signed, Transaction as _, TxEip4844Variant, TxEnvelope};
4use alloy_network::{Ethereum, Network};
5use alloy_primitives::PrimitiveSignature as Signature;
6use alloy_rpc_types::TransactionRequest;
7use alloy_rpc_types_eth::{Transaction, TransactionInfo};
8use reth_primitives::{RecoveredTx, TransactionSigned};
9use reth_rpc_eth_api::EthApiTypes;
10use reth_rpc_eth_types::EthApiError;
11use reth_rpc_types_compat::TransactionCompat;
12
13#[derive(Debug, Clone, Copy, Default)]
15pub struct EthereumEthApiTypes(EthTxBuilder);
16
17impl EthApiTypes for EthereumEthApiTypes {
18 type Error = EthApiError;
19 type NetworkTypes = Ethereum;
20 type TransactionCompat = EthTxBuilder;
21
22 fn tx_resp_builder(&self) -> &Self::TransactionCompat {
23 &self.0
24 }
25}
26
27#[derive(Debug, Clone, Copy, Default)]
29#[non_exhaustive]
30pub struct EthTxBuilder;
31
32impl TransactionCompat for EthTxBuilder
33where
34 Self: Send + Sync,
35{
36 type Transaction = <Ethereum as Network>::TransactionResponse;
37
38 type Error = EthApiError;
39
40 fn fill(
41 &self,
42 tx: RecoveredTx,
43 tx_info: TransactionInfo,
44 ) -> Result<Self::Transaction, Self::Error> {
45 let from = tx.signer();
46 let hash = tx.hash();
47 let TransactionSigned { transaction, signature, .. } = tx.into_signed();
48
49 let inner: TxEnvelope = match transaction {
50 reth_primitives::Transaction::Legacy(tx) => {
51 Signed::new_unchecked(tx, signature, hash).into()
52 }
53 reth_primitives::Transaction::Eip2930(tx) => {
54 Signed::new_unchecked(tx, signature, hash).into()
55 }
56 reth_primitives::Transaction::Eip1559(tx) => {
57 Signed::new_unchecked(tx, signature, hash).into()
58 }
59 reth_primitives::Transaction::Eip4844(tx) => {
60 Signed::new_unchecked(tx, signature, hash).into()
61 }
62 reth_primitives::Transaction::Eip7702(tx) => {
63 Signed::new_unchecked(tx, signature, hash).into()
64 }
65 reth_primitives::Transaction::Seismic(tx) => {
66 Signed::new_unchecked(tx, signature, hash).into()
67 }
68 #[allow(unreachable_patterns)]
69 _ => unreachable!(),
70 };
71
72 let TransactionInfo {
73 block_hash, block_number, index: transaction_index, base_fee, ..
74 } = tx_info;
75
76 let effective_gas_price = base_fee
77 .map(|base_fee| {
78 inner.effective_tip_per_gas(base_fee as u64).unwrap_or_default() + base_fee
79 })
80 .unwrap_or_else(|| inner.max_fee_per_gas());
81
82 Ok(Transaction {
83 inner,
84 block_hash,
85 block_number,
86 transaction_index,
87 from,
88 effective_gas_price: Some(effective_gas_price),
89 })
90 }
91
92 fn build_simulate_v1_transaction(
93 &self,
94 request: TransactionRequest,
95 ) -> Result<TransactionSigned, Self::Error> {
96 let Ok(tx) = request.build_typed_tx() else {
97 return Err(EthApiError::TransactionConversionError)
98 };
99
100 let signature = Signature::new(Default::default(), Default::default(), false);
102 Ok(TransactionSigned::new_unhashed(tx.into(), signature))
103 }
104
105 fn otterscan_api_truncate_input(tx: &mut Self::Transaction) {
106 let input = match &mut tx.inner {
107 TxEnvelope::Eip1559(tx) => &mut tx.tx_mut().input,
108 TxEnvelope::Eip2930(tx) => &mut tx.tx_mut().input,
109 TxEnvelope::Legacy(tx) => &mut tx.tx_mut().input,
110 TxEnvelope::Eip4844(tx) => match tx.tx_mut() {
111 TxEip4844Variant::TxEip4844(tx) => &mut tx.input,
112 TxEip4844Variant::TxEip4844WithSidecar(tx) => &mut tx.tx.input,
113 },
114 TxEnvelope::Eip7702(tx) => &mut tx.tx_mut().input,
115 _ => return,
116 };
117 *input = input.slice(..4);
118 }
119}