eth_trie_proofs/
rpc.rs

1use crate::error::EthTrieError;
2use alloy::network::Ethereum;
3use alloy::primitives::B256;
4use alloy::providers::{Provider, RootProvider};
5
6use alloy::rpc::types::{BlockTransactions, Transaction, TransactionReceipt};
7use alloy::transports::http::{Client, Http};
8use alloy::transports::{RpcError, TransportErrorKind};
9
10pub(crate) struct RpcProvider {
11    provider: RootProvider<Http<Client>, Ethereum>,
12}
13
14impl RpcProvider {
15    pub(crate) fn new(rpc_url: url::Url) -> Self {
16        let provider = RootProvider::new_http(rpc_url);
17        Self { provider }
18    }
19
20    pub(crate) async fn get_block_transactions(
21        &self,
22        block_number: u64,
23    ) -> Result<(Vec<Transaction>, B256), EthTrieError> {
24        let block = self
25            .provider
26            .get_block(
27                block_number.into(),
28                alloy::rpc::types::BlockTransactionsKind::Full,
29            )
30            .await?
31            .ok_or_else(|| EthTrieError::BlockNotFound)?;
32
33        let txs = match block.transactions {
34            BlockTransactions::Full(txs) => txs,
35            _ => return Err(EthTrieError::TxNotFound),
36        };
37
38        Ok((txs, block.header.transactions_root))
39    }
40
41    pub(crate) async fn get_block_transaction_receipts(
42        &self,
43        block_number: u64,
44    ) -> Result<(Vec<TransactionReceipt>, B256), EthTrieError> {
45        let block = self
46            .provider
47            .get_block(
48                block_number.into(),
49                alloy::rpc::types::BlockTransactionsKind::Full,
50            )
51            .await?
52            .ok_or_else(|| EthTrieError::BlockNotFound)?;
53
54        let tx_receipts = self
55            .provider
56            .get_block_receipts(block_number.into())
57            .await?
58            .ok_or_else(|| EthTrieError::BlockNotFound)?;
59
60        Ok((tx_receipts, block.header.receipts_root))
61    }
62
63    pub(crate) async fn get_tx_index_by_hash(&self, tx_hash: B256) -> Result<u64, EthTrieError> {
64        let tx = self
65            .provider
66            .get_transaction_by_hash(tx_hash)
67            .await?
68            .expect("tx not found");
69
70        let index: u64 = match tx.transaction_index {
71            Some(index) => index,
72            None => return Err(EthTrieError::TxNotFound),
73        };
74
75        Ok(index)
76    }
77
78    pub(crate) async fn get_tx_block_height(&self, tx_hash: B256) -> Result<u64, EthTrieError> {
79        let tx = self
80            .provider
81            .get_transaction_by_hash(tx_hash)
82            .await?
83            .expect("tx not found");
84
85        let height: u64 = match tx.block_number {
86            Some(height) => height,
87            None => return Err(EthTrieError::TxNotFound),
88        };
89
90        Ok(height)
91    }
92}
93
94impl From<RpcError<TransportErrorKind>> for EthTrieError {
95    fn from(err: RpcError<TransportErrorKind>) -> Self {
96        EthTrieError::RPC(err)
97    }
98}