bankai_sdk/fetch/clients/
execution_client.rs1use crate::errors::{SdkError, SdkResult};
2use alloy_primitives::{Address, FixedBytes, U256};
3use alloy_provider::{Provider, ProviderBuilder};
4use alloy_rpc_types_eth::{EIP1186AccountProofResponse, Header as ExecutionHeader};
5use bankai_types::fetch::evm::execution::TxProof;
6use eth_trie_proofs::tx_trie::TxsMptHandler;
7use url::Url;
8
9pub struct ExecutionFetcher {
10 pub rpc_url: String,
11 pub network_id: u64,
12}
13
14impl ExecutionFetcher {
15 pub fn new(rpc_url: String, network_id: u64) -> Self {
16 Self {
17 rpc_url,
18 network_id,
19 }
20 }
21
22 pub async fn fetch_header(&self, block_number: u64) -> SdkResult<ExecutionHeader> {
23 let rpc_url: Url = self
24 .rpc_url
25 .parse()
26 .map_err(|e| SdkError::Provider(format!("invalid rpc url: {e}")))?;
27 let provider = ProviderBuilder::new().connect_http(rpc_url);
28
29 let block = provider
30 .get_block_by_number(block_number.into())
31 .await
32 .map_err(|e| SdkError::Provider(format!("rpc error: {e}")))?;
33
34 let block =
35 block.ok_or_else(|| SdkError::NotFound(format!("block {block_number} not found")))?;
36
37 Ok(block.header)
38 }
39
40 pub async fn fetch_account_proof(
41 &self,
42 address: Address,
43 block_number: u64,
44 ) -> SdkResult<EIP1186AccountProofResponse> {
45 let rpc_url: Url = self
46 .rpc_url
47 .parse()
48 .map_err(|e| SdkError::Provider(format!("invalid rpc url: {e}")))?;
49 let provider = ProviderBuilder::new().connect_http(rpc_url);
50
51 let proof = provider
52 .get_proof(address, vec![])
53 .block_id(block_number.into())
54 .await
55 .map_err(|e| SdkError::Provider(format!("rpc error: {e}")))?;
56
57 Ok(proof)
58 }
59
60 pub async fn fetch_storage_slot_proof(
62 &self,
63 address: Address,
64 block_number: u64,
65 slot_keys: &[U256],
66 ) -> SdkResult<EIP1186AccountProofResponse> {
67 let rpc_url: Url = self
68 .rpc_url
69 .parse()
70 .map_err(|e| SdkError::Provider(format!("invalid rpc url: {e}")))?;
71 let provider = ProviderBuilder::new().connect_http(rpc_url);
72
73 let keys: Vec<FixedBytes<32>> = slot_keys
74 .iter()
75 .map(|k| FixedBytes::from(k.to_be_bytes::<32>()))
76 .collect();
77
78 let proof = provider
79 .get_proof(address, keys)
80 .block_id(block_number.into())
81 .await
82 .map_err(|e| SdkError::Provider(format!("rpc error: {e}")))?;
83
84 Ok(proof)
85 }
86
87 pub async fn fetch_tx_proof(&self, tx_hash: FixedBytes<32>) -> SdkResult<TxProof> {
88 let rpc_url: Url = self
89 .rpc_url
90 .parse()
91 .map_err(|e| SdkError::Provider(format!("invalid rpc url: {e}")))?;
92
93 let mut txs_mpt_handler = TxsMptHandler::new(rpc_url).unwrap();
94 txs_mpt_handler
95 .build_tx_tree_from_tx_hash(tx_hash)
96 .await
97 .unwrap();
98
99 let tx_index = txs_mpt_handler.tx_hash_to_tx_index(tx_hash).unwrap();
100 let proof = txs_mpt_handler.get_proof(tx_index).unwrap();
101 let encoded_tx = txs_mpt_handler
102 .verify_proof(tx_index, proof.clone())
103 .unwrap();
104
105 let block_number = self.fetch_tx_block_number(tx_hash).await?;
106
107 Ok(TxProof {
108 network_id: self.network_id,
109 block_number,
110 tx_hash,
111 tx_index,
112 proof: proof.into_iter().map(|p| p.into()).collect(),
113 encoded_tx,
114 })
115 }
116
117 pub async fn fetch_tx_block_number(&self, tx_hash: FixedBytes<32>) -> SdkResult<u64> {
118 let rpc_url: Url = self
119 .rpc_url
120 .parse()
121 .map_err(|e| SdkError::Provider(format!("invalid rpc url: {e}")))?;
122 let provider = ProviderBuilder::new().connect_http(rpc_url);
123
124 let receipt = provider
125 .get_transaction_receipt(tx_hash)
126 .await
127 .map_err(|_| SdkError::NotFound("block not found".to_string()))?
128 .ok_or(SdkError::NotFound("block not found".to_string()))?;
129
130 Ok(receipt.block_number.unwrap())
131 }
132}