1use async_trait::async_trait;
2use auto_impl::auto_impl;
3use serde::Serialize;
4use starknet_core::types::{
5 requests::*, BlockHashAndNumber, BlockId, BroadcastedDeclareTransaction,
6 BroadcastedDeployAccountTransaction, BroadcastedInvokeTransaction, BroadcastedTransaction,
7 ConfirmedBlockId, ContractClass, ContractStorageKeys, DeclareTransactionResult,
8 DeployAccountTransactionResult, EventFilter, EventsPage, FeeEstimate, Felt, FunctionCall,
9 Hash256, InvokeTransactionResult, MaybePendingBlockWithReceipts, MaybePendingBlockWithTxHashes,
10 MaybePendingBlockWithTxs, MaybePendingStateUpdate, MessageWithStatus, MsgFromL1,
11 SimulatedTransaction, SimulationFlag, SimulationFlagForEstimateFee, StarknetError,
12 StorageProof, SyncStatusType, Transaction, TransactionReceiptWithBlockInfo, TransactionStatus,
13 TransactionTrace, TransactionTraceWithHash,
14};
15use std::{any::Any, error::Error, fmt::Debug};
16
17#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
28#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
29#[auto_impl(&, Box, Arc)]
30pub trait Provider {
31 async fn spec_version(&self) -> Result<String, ProviderError>;
33
34 async fn get_block_with_tx_hashes<B>(
36 &self,
37 block_id: B,
38 ) -> Result<MaybePendingBlockWithTxHashes, ProviderError>
39 where
40 B: AsRef<BlockId> + Send + Sync;
41
42 async fn get_block_with_txs<B>(
44 &self,
45 block_id: B,
46 ) -> Result<MaybePendingBlockWithTxs, ProviderError>
47 where
48 B: AsRef<BlockId> + Send + Sync;
49
50 async fn get_block_with_receipts<B>(
52 &self,
53 block_id: B,
54 ) -> Result<MaybePendingBlockWithReceipts, ProviderError>
55 where
56 B: AsRef<BlockId> + Send + Sync;
57
58 async fn get_state_update<B>(
60 &self,
61 block_id: B,
62 ) -> Result<MaybePendingStateUpdate, ProviderError>
63 where
64 B: AsRef<BlockId> + Send + Sync;
65
66 async fn get_storage_at<A, K, B>(
68 &self,
69 contract_address: A,
70 key: K,
71 block_id: B,
72 ) -> Result<Felt, ProviderError>
73 where
74 A: AsRef<Felt> + Send + Sync,
75 K: AsRef<Felt> + Send + Sync,
76 B: AsRef<BlockId> + Send + Sync;
77
78 async fn get_messages_status(
81 &self,
82 transaction_hash: Hash256,
83 ) -> Result<Vec<MessageWithStatus>, ProviderError>;
84
85 async fn get_transaction_status<H>(
88 &self,
89 transaction_hash: H,
90 ) -> Result<TransactionStatus, ProviderError>
91 where
92 H: AsRef<Felt> + Send + Sync;
93
94 async fn get_transaction_by_hash<H>(
96 &self,
97 transaction_hash: H,
98 ) -> Result<Transaction, ProviderError>
99 where
100 H: AsRef<Felt> + Send + Sync;
101
102 async fn get_transaction_by_block_id_and_index<B>(
104 &self,
105 block_id: B,
106 index: u64,
107 ) -> Result<Transaction, ProviderError>
108 where
109 B: AsRef<BlockId> + Send + Sync;
110
111 async fn get_transaction_receipt<H>(
113 &self,
114 transaction_hash: H,
115 ) -> Result<TransactionReceiptWithBlockInfo, ProviderError>
116 where
117 H: AsRef<Felt> + Send + Sync;
118
119 async fn get_class<B, H>(
121 &self,
122 block_id: B,
123 class_hash: H,
124 ) -> Result<ContractClass, ProviderError>
125 where
126 B: AsRef<BlockId> + Send + Sync,
127 H: AsRef<Felt> + Send + Sync;
128
129 async fn get_class_hash_at<B, A>(
132 &self,
133 block_id: B,
134 contract_address: A,
135 ) -> Result<Felt, ProviderError>
136 where
137 B: AsRef<BlockId> + Send + Sync,
138 A: AsRef<Felt> + Send + Sync;
139
140 async fn get_class_at<B, A>(
142 &self,
143 block_id: B,
144 contract_address: A,
145 ) -> Result<ContractClass, ProviderError>
146 where
147 B: AsRef<BlockId> + Send + Sync,
148 A: AsRef<Felt> + Send + Sync;
149
150 async fn get_block_transaction_count<B>(&self, block_id: B) -> Result<u64, ProviderError>
152 where
153 B: AsRef<BlockId> + Send + Sync;
154
155 async fn call<R, B>(&self, request: R, block_id: B) -> Result<Vec<Felt>, ProviderError>
157 where
158 R: AsRef<FunctionCall> + Send + Sync,
159 B: AsRef<BlockId> + Send + Sync;
160
161 async fn estimate_fee<R, S, B>(
163 &self,
164 request: R,
165 simulation_flags: S,
166 block_id: B,
167 ) -> Result<Vec<FeeEstimate>, ProviderError>
168 where
169 R: AsRef<[BroadcastedTransaction]> + Send + Sync,
170 S: AsRef<[SimulationFlagForEstimateFee]> + Send + Sync,
171 B: AsRef<BlockId> + Send + Sync;
172
173 async fn estimate_message_fee<M, B>(
175 &self,
176 message: M,
177 block_id: B,
178 ) -> Result<FeeEstimate, ProviderError>
179 where
180 M: AsRef<MsgFromL1> + Send + Sync,
181 B: AsRef<BlockId> + Send + Sync;
182
183 async fn block_number(&self) -> Result<u64, ProviderError>;
185
186 async fn block_hash_and_number(&self) -> Result<BlockHashAndNumber, ProviderError>;
188
189 async fn chain_id(&self) -> Result<Felt, ProviderError>;
191
192 async fn syncing(&self) -> Result<SyncStatusType, ProviderError>;
194
195 async fn get_events(
197 &self,
198 filter: EventFilter,
199 continuation_token: Option<String>,
200 chunk_size: u64,
201 ) -> Result<EventsPage, ProviderError>;
202
203 async fn get_nonce<B, A>(
205 &self,
206 block_id: B,
207 contract_address: A,
208 ) -> Result<Felt, ProviderError>
209 where
210 B: AsRef<BlockId> + Send + Sync,
211 A: AsRef<Felt> + Send + Sync;
212
213 async fn get_storage_proof<B, H, A, K>(
217 &self,
218 block_id: B,
219 class_hashes: H,
220 contract_addresses: A,
221 contracts_storage_keys: K,
222 ) -> Result<StorageProof, ProviderError>
223 where
224 B: AsRef<ConfirmedBlockId> + Send + Sync,
225 H: AsRef<[Felt]> + Send + Sync,
226 A: AsRef<[Felt]> + Send + Sync,
227 K: AsRef<[ContractStorageKeys]> + Send + Sync;
228
229 async fn add_invoke_transaction<I>(
231 &self,
232 invoke_transaction: I,
233 ) -> Result<InvokeTransactionResult, ProviderError>
234 where
235 I: AsRef<BroadcastedInvokeTransaction> + Send + Sync;
236
237 async fn add_declare_transaction<D>(
239 &self,
240 declare_transaction: D,
241 ) -> Result<DeclareTransactionResult, ProviderError>
242 where
243 D: AsRef<BroadcastedDeclareTransaction> + Send + Sync;
244
245 async fn add_deploy_account_transaction<D>(
247 &self,
248 deploy_account_transaction: D,
249 ) -> Result<DeployAccountTransactionResult, ProviderError>
250 where
251 D: AsRef<BroadcastedDeployAccountTransaction> + Send + Sync;
252
253 async fn trace_transaction<H>(
256 &self,
257 transaction_hash: H,
258 ) -> Result<TransactionTrace, ProviderError>
259 where
260 H: AsRef<Felt> + Send + Sync;
261
262 async fn simulate_transactions<B, T, S>(
270 &self,
271 block_id: B,
272 transactions: T,
273 simulation_flags: S,
274 ) -> Result<Vec<SimulatedTransaction>, ProviderError>
275 where
276 B: AsRef<BlockId> + Send + Sync,
277 T: AsRef<[BroadcastedTransaction]> + Send + Sync,
278 S: AsRef<[SimulationFlag]> + Send + Sync;
279
280 async fn trace_block_transactions<B>(
282 &self,
283 block_id: B,
284 ) -> Result<Vec<TransactionTraceWithHash>, ProviderError>
285 where
286 B: AsRef<BlockId> + Send + Sync;
287
288 async fn batch_requests<R>(
291 &self,
292 requests: R,
293 ) -> Result<Vec<ProviderResponseData>, ProviderError>
294 where
295 R: AsRef<[ProviderRequestData]> + Send + Sync;
296
297 async fn estimate_fee_single<R, S, B>(
299 &self,
300 request: R,
301 simulation_flags: S,
302 block_id: B,
303 ) -> Result<FeeEstimate, ProviderError>
304 where
305 R: AsRef<BroadcastedTransaction> + Send + Sync,
306 S: AsRef<[SimulationFlagForEstimateFee]> + Send + Sync,
307 B: AsRef<BlockId> + Send + Sync,
308 {
309 let mut result = self
310 .estimate_fee([request.as_ref().to_owned()], simulation_flags, block_id)
311 .await?;
312
313 if result.len() == 1 {
314 Ok(result.pop().unwrap())
316 } else {
317 Err(ProviderError::ArrayLengthMismatch)
318 }
319 }
320
321 async fn simulate_transaction<B, T, S>(
323 &self,
324 block_id: B,
325 transaction: T,
326 simulation_flags: S,
327 ) -> Result<SimulatedTransaction, ProviderError>
328 where
329 B: AsRef<BlockId> + Send + Sync,
330 T: AsRef<BroadcastedTransaction> + Send + Sync,
331 S: AsRef<[SimulationFlag]> + Send + Sync,
332 {
333 let mut result = self
334 .simulate_transactions(
335 block_id,
336 [transaction.as_ref().to_owned()],
337 simulation_flags,
338 )
339 .await?;
340
341 if result.len() == 1 {
342 Ok(result.pop().unwrap())
344 } else {
345 Err(ProviderError::ArrayLengthMismatch)
346 }
347 }
348}
349
350pub trait ProviderImplError: Error + Debug + Send + Sync {
358 fn as_any(&self) -> &dyn Any;
359}
360
361#[derive(Debug, thiserror::Error)]
372pub enum ProviderError {
373 #[error(transparent)]
375 StarknetError(StarknetError),
376 #[error("Request rate limited")]
378 RateLimited,
379 #[error("Array length mismatch")]
382 ArrayLengthMismatch,
383 #[error("{0}")]
385 Other(Box<dyn ProviderImplError>),
386}
387
388#[derive(Debug, Clone, Serialize)]
390#[serde(untagged)]
391pub enum ProviderRequestData {
392 SpecVersion(SpecVersionRequest),
394 GetBlockWithTxHashes(GetBlockWithTxHashesRequest),
396 GetBlockWithTxs(GetBlockWithTxsRequest),
398 GetBlockWithReceipts(GetBlockWithReceiptsRequest),
400 GetStateUpdate(GetStateUpdateRequest),
402 GetStorageAt(GetStorageAtRequest),
404 GetMessagesStatus(GetMessagesStatusRequest),
406 GetTransactionStatus(GetTransactionStatusRequest),
408 GetTransactionByHash(GetTransactionByHashRequest),
410 GetTransactionByBlockIdAndIndex(GetTransactionByBlockIdAndIndexRequest),
412 GetTransactionReceipt(GetTransactionReceiptRequest),
414 GetClass(GetClassRequest),
416 GetClassHashAt(GetClassHashAtRequest),
418 GetClassAt(GetClassAtRequest),
420 GetBlockTransactionCount(GetBlockTransactionCountRequest),
422 Call(CallRequest),
424 EstimateFee(EstimateFeeRequest),
426 EstimateMessageFee(EstimateMessageFeeRequest),
428 BlockNumber(BlockNumberRequest),
430 BlockHashAndNumber(BlockHashAndNumberRequest),
432 ChainId(ChainIdRequest),
434 Syncing(SyncingRequest),
436 GetEvents(GetEventsRequest),
438 GetNonce(GetNonceRequest),
440 GetStorageProof(GetStorageProofRequest),
442 AddInvokeTransaction(AddInvokeTransactionRequest),
444 AddDeclareTransaction(AddDeclareTransactionRequest),
446 AddDeployAccountTransaction(AddDeployAccountTransactionRequest),
448 TraceTransaction(TraceTransactionRequest),
450 SimulateTransactions(SimulateTransactionsRequest),
452 TraceBlockTransactions(TraceBlockTransactionsRequest),
454}
455
456#[allow(clippy::large_enum_variant)]
458#[derive(Debug, Clone)]
459pub enum ProviderResponseData {
460 SpecVersion(String),
462 GetBlockWithTxHashes(MaybePendingBlockWithTxHashes),
464 GetBlockWithTxs(MaybePendingBlockWithTxs),
466 GetBlockWithReceipts(MaybePendingBlockWithReceipts),
468 GetStateUpdate(MaybePendingStateUpdate),
470 GetStorageAt(Felt),
472 GetMessagesStatus(Vec<MessageWithStatus>),
474 GetTransactionStatus(TransactionStatus),
476 GetTransactionByHash(Transaction),
478 GetTransactionByBlockIdAndIndex(Transaction),
480 GetTransactionReceipt(TransactionReceiptWithBlockInfo),
482 GetClass(ContractClass),
484 GetClassHashAt(Felt),
486 GetClassAt(ContractClass),
488 GetBlockTransactionCount(u64),
490 Call(Vec<Felt>),
492 EstimateFee(Vec<FeeEstimate>),
494 EstimateMessageFee(FeeEstimate),
496 BlockNumber(u64),
498 BlockHashAndNumber(BlockHashAndNumber),
500 ChainId(Felt),
502 Syncing(SyncStatusType),
504 GetEvents(EventsPage),
506 GetNonce(Felt),
508 GetStorageProof(StorageProof),
510 AddInvokeTransaction(InvokeTransactionResult),
512 AddDeclareTransaction(DeclareTransactionResult),
514 AddDeployAccountTransaction(DeployAccountTransactionResult),
516 TraceTransaction(TransactionTrace),
518 SimulateTransactions(Vec<SimulatedTransaction>),
520 TraceBlockTransactions(Vec<TransactionTraceWithHash>),
522}