reth_rpc_types_compat/
transaction.rs1use core::error;
4use std::fmt;
5
6use alloy_consensus::Transaction as _;
7use alloy_rpc_types_eth::{
8 request::{TransactionInput, TransactionRequest},
9 TransactionInfo,
10};
11use reth_primitives::{RecoveredTx, TransactionSigned};
12use serde::{Deserialize, Serialize};
13
14pub fn from_recovered_with_block_context<Tx, T: TransactionCompat<Tx>>(
20 tx: RecoveredTx<Tx>,
21 tx_info: TransactionInfo,
22 resp_builder: &T,
23) -> Result<T::Transaction, T::Error> {
24 resp_builder.fill(tx, tx_info)
25}
26
27pub fn from_recovered<Tx, T: TransactionCompat<Tx>>(
30 tx: RecoveredTx<Tx>,
31 resp_builder: &T,
32) -> Result<T::Transaction, T::Error> {
33 resp_builder.fill(tx, TransactionInfo::default())
34}
35
36pub trait TransactionCompat<T = TransactionSigned>:
38 Send + Sync + Unpin + Clone + fmt::Debug
39{
40 type Transaction: Serialize
42 + for<'de> Deserialize<'de>
43 + Send
44 + Sync
45 + Unpin
46 + Clone
47 + fmt::Debug
48 + alloy_consensus::transaction::ShieldableTransaction;
49
50 type Error: error::Error + Into<jsonrpsee_types::ErrorObject<'static>>;
52
53 fn fill(
56 &self,
57 tx: RecoveredTx<T>,
58 tx_inf: TransactionInfo,
59 ) -> Result<Self::Transaction, Self::Error>;
60
61 fn build_simulate_v1_transaction(&self, request: TransactionRequest) -> Result<T, Self::Error>;
64
65 fn otterscan_api_truncate_input(tx: &mut Self::Transaction);
69}
70
71pub fn transaction_to_call_request(tx: RecoveredTx) -> TransactionRequest {
73 let from = tx.signer();
74 let to = Some(tx.transaction.to().into());
75 let gas = tx.transaction.gas_limit();
76 let value = tx.transaction.value();
77 let input = tx.transaction.input().clone();
78 let nonce = tx.transaction.nonce();
79 let chain_id = tx.transaction.chain_id();
80 let access_list = tx.transaction.access_list().cloned();
81 let max_fee_per_blob_gas = tx.transaction.max_fee_per_blob_gas();
82 let authorization_list = tx.transaction.authorization_list().map(|l| l.to_vec());
83 let blob_versioned_hashes = tx.transaction.blob_versioned_hashes().map(Vec::from);
84 let tx_type = tx.transaction.tx_type();
85
86 let (gas_price, max_fee_per_gas) = if tx.is_dynamic_fee() {
88 (None, Some(tx.max_fee_per_gas()))
89 } else {
90 (Some(tx.max_fee_per_gas()), None)
91 };
92 let max_priority_fee_per_gas = tx.transaction.max_priority_fee_per_gas();
93
94 TransactionRequest {
95 from: Some(from),
96 to,
97 gas_price,
98 max_fee_per_gas,
99 max_priority_fee_per_gas,
100 gas: Some(gas),
101 value: Some(value),
102 input: TransactionInput::new(input),
103 nonce: Some(nonce),
104 chain_id,
105 access_list,
106 max_fee_per_blob_gas,
107 blob_versioned_hashes,
108 transaction_type: Some(tx_type.into()),
109 sidecar: None,
110 authorization_list,
111 seismic_elements: None,
114 }
115}