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}