reth_e2e_test_utils/
rpc.rs

1use alloy_consensus::TxEnvelope;
2use alloy_eips::{BlockId, BlockNumberOrTag};
3use alloy_network::eip2718::Decodable2718;
4use alloy_primitives::{Address, Bytes, B256};
5use alloy_rpc_types_eth::Account;
6use reth_chainspec::EthereumHardforks;
7use reth_node_api::{BlockTy, FullNodeComponents};
8use reth_node_builder::{rpc::RpcRegistry, NodeTypes};
9use reth_provider::BlockReader;
10use reth_rpc_api::DebugApiServer;
11use reth_rpc_eth_api::{
12    helpers::{EthApiSpec, EthState, FullEthApi, TraceExt},
13    EthApiTypes, RpcReceipt,
14};
15
16#[expect(missing_debug_implementations)]
17pub struct RpcTestContext<Node: FullNodeComponents, EthApi: EthApiTypes> {
18    pub inner: RpcRegistry<Node, EthApi>,
19}
20
21impl<Node, EthApi> RpcTestContext<Node, EthApi>
22where
23    Node: FullNodeComponents<Types: NodeTypes<ChainSpec: EthereumHardforks>>,
24    EthApi: EthApiSpec<Provider: BlockReader<Block = BlockTy<Node::Types>>> + FullEthApi + TraceExt,
25{
26    /// Injects a raw transaction into the node tx pool via RPC server
27    pub async fn inject_tx(&self, raw_tx: Bytes) -> Result<B256, EthApi::Error> {
28        let eth_api = self.inner.eth_api();
29        eth_api.send_raw_transaction(raw_tx).await
30    }
31
32    /// Retrieves a transaction envelope by its hash
33    pub async fn envelope_by_hash(&self, hash: B256) -> eyre::Result<TxEnvelope> {
34        let tx = self.inner.debug_api().raw_transaction(hash).await?.unwrap();
35        let tx = tx.to_vec();
36        Ok(TxEnvelope::decode_2718(&mut tx.as_ref()).unwrap())
37    }
38
39    /// get transaction receipt
40    pub async fn transaction_receipt(
41        &self,
42        tx_hash: B256,
43    ) -> Result<Option<RpcReceipt<EthApi::NetworkTypes>>, EthApi::Error> {
44        let eth_api = self.inner.eth_api();
45        eth_api.transaction_receipt(tx_hash).await
46    }
47
48    /// get code
49    pub async fn get_code(
50        &self,
51        address: Address,
52        block_number: u64,
53    ) -> Result<Bytes, EthApi::Error> {
54        let eth_api = self.inner.eth_api();
55        EthState::get_code(
56            eth_api,
57            address,
58            Some(BlockId::Number(BlockNumberOrTag::Number(block_number.into()))),
59        )
60        .await
61    }
62
63    pub async fn get_account(
64        &self,
65        address: Address,
66        block_number: u64,
67    ) -> Result<Option<Account>, EthApi::Error> {
68        let eth_api = self.inner.eth_api();
69        EthState::get_account(
70            eth_api,
71            address,
72            BlockId::Number(BlockNumberOrTag::Number(block_number.into())),
73        )
74        .await
75    }
76}