From d77aff61d01f64f12e9cf3052347535ef160c1f0 Mon Sep 17 00:00:00 2001 From: Jonathan LEI Date: Sun, 29 Oct 2023 05:58:12 +0000 Subject: [PATCH] feat: erase implementation-specific provider error Changes the `Other` variant of `ProviderError` to use a trait object instead of a generic parameter. This makes the `ProviderError` type much easier to work with, as errors from different `Provider` types are now compatible, and any type that wraps `ProviderError` will have one fewer generic parameter to deal with. At the same time, it's still possible, though harder, to access the erased error type by downcasting, which requires the caller to know the concrete type at compile time, as showcased in the new example. This is a breaking change, but it shouldn't affect downstream applications which already erase the whole `ProviderError` type with something like `anyhow`. --- README.md | 2 + examples/downcast_provider_error.rs | 26 ++ starknet-accounts/src/account/declaration.rs | 74 +--- starknet-accounts/src/account/execution.rs | 29 +- starknet-accounts/src/account/mod.rs | 8 +- starknet-accounts/src/factory/mod.rs | 41 +- starknet-contract/src/factory.rs | 13 +- starknet-providers/src/any.rs | 405 +++++++++---------- starknet-providers/src/jsonrpc/mod.rs | 99 ++--- starknet-providers/src/lib.rs | 2 +- starknet-providers/src/provider.rs | 87 ++-- starknet-providers/src/sequencer/mod.rs | 102 ++--- starknet-providers/src/sequencer/provider.rs | 113 +++--- 13 files changed, 443 insertions(+), 558 deletions(-) create mode 100644 examples/downcast_provider_error.rs diff --git a/README.md b/README.md index 68d1f876..4e803253 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,8 @@ Examples can be found in the [examples folder](./examples): 9. [Parsing a JSON-RPC request on the server side](./examples/parse_jsonrpc_request.rs) +10. [Inspecting a erased provider-specific error type](./examples/downcast_provider_error.rs) + ## License Licensed under either of diff --git a/examples/downcast_provider_error.rs b/examples/downcast_provider_error.rs new file mode 100644 index 00000000..8d3a0eba --- /dev/null +++ b/examples/downcast_provider_error.rs @@ -0,0 +1,26 @@ +use starknet_providers::{ + jsonrpc::{HttpTransport, HttpTransportError, JsonRpcClient, JsonRpcClientError}, + Provider, ProviderError, +}; +use url::Url; + +#[tokio::main] +async fn main() { + let rpc_client = + JsonRpcClient::new(HttpTransport::new(Url::parse("https://fake.url/").unwrap())); + + let error = match rpc_client.block_number().await.unwrap_err() { + ProviderError::Other(inner) => inner, + _ => panic!("unexpected error variant"), + }; + + // The implementation-specific error type is erased to make the `ProviderError` type easier to + // work with. Here, we showcase how to recover the inner type. + let impl_specific_error: &JsonRpcClientError = + match error.as_any().downcast_ref() { + Some(inner) => inner, + None => panic!("unexpected downcast failure"), + }; + + dbg!(impl_specific_error); +} diff --git a/starknet-accounts/src/account/declaration.rs b/starknet-accounts/src/account/declaration.rs index 2af89a48..283cf3fa 100644 --- a/starknet-accounts/src/account/declaration.rs +++ b/starknet-accounts/src/account/declaration.rs @@ -99,9 +99,7 @@ impl<'a, A> Declaration<'a, A> where A: ConnectedAccount + Sync, { - pub async fn estimate_fee( - &self, - ) -> Result::Error>> { + pub async fn estimate_fee(&self) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -119,8 +117,7 @@ where &self, skip_validate: bool, skip_fee_charge: bool, - ) -> Result::Error>> - { + ) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -135,21 +132,11 @@ where .await } - pub async fn send( - &self, - ) -> Result< - DeclareTransactionResult, - AccountError::Error>, - > { + pub async fn send(&self) -> Result> { self.prepare().await?.send().await } - async fn prepare( - &self, - ) -> Result< - PreparedDeclaration<'a, A>, - AccountError::Error>, - > { + async fn prepare(&self) -> Result, AccountError> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -183,7 +170,7 @@ where async fn estimate_fee_with_nonce( &self, nonce: FieldElement, - ) -> Result::Error>> { + ) -> Result> { let prepared = PreparedDeclaration { account: self.account, inner: RawDeclaration { @@ -210,8 +197,7 @@ where nonce: FieldElement, skip_validate: bool, skip_fee_charge: bool, - ) -> Result::Error>> - { + ) -> Result> { let prepared = PreparedDeclaration { account: self.account, inner: RawDeclaration { @@ -298,9 +284,7 @@ impl<'a, A> LegacyDeclaration<'a, A> where A: ConnectedAccount + Sync, { - pub async fn estimate_fee( - &self, - ) -> Result::Error>> { + pub async fn estimate_fee(&self) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -318,8 +302,7 @@ where &self, skip_validate: bool, skip_fee_charge: bool, - ) -> Result::Error>> - { + ) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -334,21 +317,13 @@ where .await } - pub async fn send( - &self, - ) -> Result< - DeclareTransactionResult, - AccountError::Error>, - > { + pub async fn send(&self) -> Result> { self.prepare().await?.send().await } async fn prepare( &self, - ) -> Result< - PreparedLegacyDeclaration<'a, A>, - AccountError::Error>, - > { + ) -> Result, AccountError> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -381,7 +356,7 @@ where async fn estimate_fee_with_nonce( &self, nonce: FieldElement, - ) -> Result::Error>> { + ) -> Result> { let prepared = PreparedLegacyDeclaration { account: self.account, inner: RawLegacyDeclaration { @@ -407,8 +382,7 @@ where nonce: FieldElement, skip_validate: bool, skip_fee_charge: bool, - ) -> Result::Error>> - { + ) -> Result> { let prepared = PreparedLegacyDeclaration { account: self.account, inner: RawLegacyDeclaration { @@ -505,12 +479,7 @@ impl<'a, A> PreparedDeclaration<'a, A> where A: ConnectedAccount, { - pub async fn send( - &self, - ) -> Result< - DeclareTransactionResult, - AccountError::Error>, - > { + pub async fn send(&self) -> Result> { let tx_request = self.get_declare_request(false).await?; self.account .provider() @@ -522,10 +491,7 @@ where pub async fn get_declare_request( &self, query_only: bool, - ) -> Result< - BroadcastedDeclareTransactionV2, - AccountError::Error>, - > { + ) -> Result> { let signature = self .account .sign_declaration(&self.inner, query_only) @@ -563,12 +529,7 @@ impl<'a, A> PreparedLegacyDeclaration<'a, A> where A: ConnectedAccount, { - pub async fn send( - &self, - ) -> Result< - DeclareTransactionResult, - AccountError::Error>, - > { + pub async fn send(&self) -> Result> { let tx_request = self.get_declare_request(false).await?; self.account .provider() @@ -580,10 +541,7 @@ where pub async fn get_declare_request( &self, query_only: bool, - ) -> Result< - BroadcastedDeclareTransactionV1, - AccountError::Error>, - > { + ) -> Result> { let signature = self .account .sign_legacy_declaration(&self.inner, query_only) diff --git a/starknet-accounts/src/account/execution.rs b/starknet-accounts/src/account/execution.rs index 5a6abbda..8f9f958a 100644 --- a/starknet-accounts/src/account/execution.rs +++ b/starknet-accounts/src/account/execution.rs @@ -82,9 +82,7 @@ impl<'a, A> Execution<'a, A> where A: ConnectedAccount + Sync, { - pub async fn estimate_fee( - &self, - ) -> Result::Error>> { + pub async fn estimate_fee(&self) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -102,8 +100,7 @@ where &self, skip_validate: bool, skip_fee_charge: bool, - ) -> Result::Error>> - { + ) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -118,19 +115,11 @@ where .await } - pub async fn send( - &self, - ) -> Result::Error>> - { + pub async fn send(&self) -> Result> { self.prepare().await?.send().await } - async fn prepare( - &self, - ) -> Result< - PreparedExecution<'a, A>, - AccountError::Error>, - > { + async fn prepare(&self) -> Result, AccountError> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -163,7 +152,7 @@ where async fn estimate_fee_with_nonce( &self, nonce: FieldElement, - ) -> Result::Error>> { + ) -> Result> { let prepared = PreparedExecution { account: self.account, inner: RawExecution { @@ -192,8 +181,7 @@ where nonce: FieldElement, skip_validate: bool, skip_fee_charge: bool, - ) -> Result::Error>> - { + ) -> Result> { let prepared = PreparedExecution { account: self.account, inner: RawExecution { @@ -276,10 +264,7 @@ impl<'a, A> PreparedExecution<'a, A> where A: ConnectedAccount, { - pub async fn send( - &self, - ) -> Result::Error>> - { + pub async fn send(&self) -> Result> { let tx_request = self .get_invoke_request(false) .await diff --git a/starknet-accounts/src/account/mod.rs b/starknet-accounts/src/account/mod.rs index 37d5ee6c..fb257687 100644 --- a/starknet-accounts/src/account/mod.rs +++ b/starknet-accounts/src/account/mod.rs @@ -80,9 +80,7 @@ pub trait ConnectedAccount: Account { BlockId::Tag(BlockTag::Latest) } - async fn get_nonce( - &self, - ) -> Result::Error>> { + async fn get_nonce(&self) -> Result { self.provider() .get_nonce(self.block_id(), self.address()) .await @@ -170,11 +168,11 @@ pub struct PreparedLegacyDeclaration<'a, A> { } #[derive(Debug, thiserror::Error)] -pub enum AccountError { +pub enum AccountError { #[error(transparent)] Signing(S), #[error(transparent)] - Provider(ProviderError

), + Provider(ProviderError), #[error(transparent)] ClassHashCalculation(ComputeClassHashError), #[error(transparent)] diff --git a/starknet-accounts/src/factory/mod.rs b/starknet-accounts/src/factory/mod.rs index 5561c655..0bb68cbd 100644 --- a/starknet-accounts/src/factory/mod.rs +++ b/starknet-accounts/src/factory/mod.rs @@ -100,11 +100,11 @@ pub struct PreparedAccountDeployment<'f, F> { } #[derive(Debug, thiserror::Error)] -pub enum AccountFactoryError { +pub enum AccountFactoryError { #[error(transparent)] Signing(S), #[error(transparent)] - Provider(ProviderError

), + Provider(ProviderError), } impl<'f, F> AccountDeployment<'f, F> { @@ -170,9 +170,7 @@ where ) } - pub async fn fetch_nonce( - &self, - ) -> Result::Error>> { + pub async fn fetch_nonce(&self) -> Result { match self .factory .provider() @@ -188,10 +186,7 @@ where } } - pub async fn estimate_fee( - &self, - ) -> Result::Error>> - { + pub async fn estimate_fee(&self) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -208,10 +203,7 @@ where &self, skip_validate: bool, skip_fee_charge: bool, - ) -> Result< - SimulatedTransaction, - AccountFactoryError::Error>, - > { + ) -> Result> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -227,19 +219,13 @@ where pub async fn send( &self, - ) -> Result< - DeployAccountTransactionResult, - AccountFactoryError::Error>, - > { + ) -> Result> { self.prepare().await?.send().await } async fn prepare( &self, - ) -> Result< - PreparedAccountDeployment<'f, F>, - AccountFactoryError::Error>, - > { + ) -> Result, AccountFactoryError> { // Resolves nonce let nonce = match self.nonce { Some(value) => value, @@ -271,8 +257,7 @@ where async fn estimate_fee_with_nonce( &self, nonce: FieldElement, - ) -> Result::Error>> - { + ) -> Result> { let prepared = PreparedAccountDeployment { factory: self.factory, inner: RawAccountDeployment { @@ -301,10 +286,7 @@ where nonce: FieldElement, skip_validate: bool, skip_fee_charge: bool, - ) -> Result< - SimulatedTransaction, - AccountFactoryError::Error>, - > { + ) -> Result> { let prepared = PreparedAccountDeployment { factory: self.factory, inner: RawAccountDeployment { @@ -379,10 +361,7 @@ where pub async fn send( &self, - ) -> Result< - DeployAccountTransactionResult, - AccountFactoryError::Error>, - > { + ) -> Result> { let tx_request = self .get_deploy_request() .await diff --git a/starknet-contract/src/factory.rs b/starknet-contract/src/factory.rs index d57b1381..3fb1b1b4 100644 --- a/starknet-contract/src/factory.rs +++ b/starknet-contract/src/factory.rs @@ -3,7 +3,6 @@ use starknet_core::{ types::{FeeEstimate, FieldElement, InvokeTransactionResult, SimulatedTransaction}, utils::{get_udc_deployed_address, UdcUniqueSettings, UdcUniqueness}, }; -use starknet_providers::Provider; /// The default UDC address: 0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf. const UDC_ADDRESS: FieldElement = FieldElement::from_mont([ @@ -123,9 +122,7 @@ impl<'f, A> Deployment<'f, A> where A: ConnectedAccount + Sync, { - pub async fn estimate_fee( - &self, - ) -> Result::Error>> { + pub async fn estimate_fee(&self) -> Result> { let execution: Execution = self.into(); execution.estimate_fee().await } @@ -134,16 +131,12 @@ where &self, skip_validate: bool, skip_fee_charge: bool, - ) -> Result::Error>> - { + ) -> Result> { let execution: Execution = self.into(); execution.simulate(skip_validate, skip_fee_charge).await } - pub async fn send( - &self, - ) -> Result::Error>> - { + pub async fn send(&self) -> Result> { let execution: Execution = self.into(); execution.send().await } diff --git a/starknet-providers/src/any.rs b/starknet-providers/src/any.rs index d2c3382b..a4dc95b8 100644 --- a/starknet-providers/src/any.rs +++ b/starknet-providers/src/any.rs @@ -20,78 +20,71 @@ use crate::{ /// /// A recommended pattern is to make your business logic code (e.g. functions) generic over the /// [Provider] trait, while using this [AnyProvider] type for bootstrapping your application. +/// +/// NOTE: This type was introduced when [Provider] was not Box-able. It should be reviewed whether +/// it's still needed anymore. #[derive(Debug)] pub enum AnyProvider { JsonRpcHttp(JsonRpcClient), SequencerGateway(SequencerGatewayProvider), } -#[derive(Debug, thiserror::Error)] -#[error(transparent)] -pub enum AnyProviderError { - JsonRpcHttp( as Provider>::Error), - SequencerGateway(::Error), -} - #[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] impl Provider for AnyProvider { - type Error = AnyProviderError; - async fn get_block_with_tx_hashes( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::get_block_with_tx_hashes( inner, block_id, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::get_block_with_tx_hashes(inner, block_id) - .await?, - ), + .await + } } } async fn get_block_with_txs( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::get_block_with_txs(inner, block_id) - .await?, - ), - Self::SequencerGateway(inner) => Ok( - ::get_block_with_txs(inner, block_id).await?, - ), + .await + } + Self::SequencerGateway(inner) => { + ::get_block_with_txs(inner, block_id).await + } } } async fn get_state_update( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( - as Provider>::get_state_update(inner, block_id) - .await?, - ), - Self::SequencerGateway(inner) => Ok( - ::get_state_update(inner, block_id).await?, - ), + Self::JsonRpcHttp(inner) => { + as Provider>::get_state_update(inner, block_id).await + } + Self::SequencerGateway(inner) => { + ::get_state_update(inner, block_id).await + } } } @@ -100,7 +93,7 @@ impl Provider for AnyProvider { contract_address: A, key: K, block_id: B, - ) -> Result> + ) -> Result where A: AsRef + Send + Sync, K: AsRef + Send + Sync, @@ -108,22 +101,22 @@ impl Provider for AnyProvider { { match self { Self::JsonRpcHttp(inner) => { - Ok( as Provider>::get_storage_at( + as Provider>::get_storage_at( inner, contract_address, key, block_id, ) - .await?) + .await } Self::SequencerGateway(inner) => { - Ok(::get_storage_at( + ::get_storage_at( inner, contract_address, key, block_id, ) - .await?) + .await } } } @@ -131,25 +124,25 @@ impl Provider for AnyProvider { async fn get_transaction_by_hash( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::get_transaction_by_hash( inner, transaction_hash, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::get_transaction_by_hash( inner, transaction_hash, ) - .await?, - ), + .await + } } } @@ -157,48 +150,48 @@ impl Provider for AnyProvider { &self, block_id: B, index: u64, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::get_transaction_by_block_id_and_index( inner, block_id, index, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::get_transaction_by_block_id_and_index( inner, block_id, index, ) - .await?, - ), + .await + } } } async fn get_transaction_receipt( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::get_transaction_receipt( inner, transaction_hash, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::get_transaction_receipt( inner, transaction_hash, ) - .await?, - ), + .await + } } } @@ -206,20 +199,19 @@ impl Provider for AnyProvider { &self, block_id: B, class_hash: H, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, H: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( as Provider>::get_class( - inner, block_id, class_hash, - ) - .await?), - Self::SequencerGateway(inner) => Ok(::get_class( - inner, block_id, class_hash, - ) - .await?), + Self::JsonRpcHttp(inner) => { + as Provider>::get_class(inner, block_id, class_hash) + .await + } + Self::SequencerGateway(inner) => { + ::get_class(inner, block_id, class_hash).await + } } } @@ -227,27 +219,27 @@ impl Provider for AnyProvider { &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::get_class_hash_at( inner, block_id, contract_address, ) - .await?, - ), + .await + } Self::SequencerGateway(inner) => { - Ok(::get_class_hash_at( + ::get_class_hash_at( inner, block_id, contract_address, ) - .await?) + .await } } } @@ -256,70 +248,60 @@ impl Provider for AnyProvider { &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, { match self { Self::JsonRpcHttp(inner) => { - Ok( as Provider>::get_class_at( + as Provider>::get_class_at( inner, block_id, contract_address, ) - .await?) + .await } Self::SequencerGateway(inner) => { - Ok(::get_class_at( + ::get_class_at( inner, block_id, contract_address, ) - .await?) + .await } } } - async fn get_block_transaction_count( - &self, - block_id: B, - ) -> Result> + async fn get_block_transaction_count(&self, block_id: B) -> Result where B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::get_block_transaction_count( inner, block_id, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( - ::get_block_transaction_count( - inner, block_id, - ) - .await?, - ), + .await + } + Self::SequencerGateway(inner) => { + ::get_block_transaction_count(inner, block_id) + .await + } } } - async fn call( - &self, - request: R, - block_id: B, - ) -> Result, ProviderError> + async fn call(&self, request: R, block_id: B) -> Result, ProviderError> where R: AsRef + Send + Sync, B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( as Provider>::call( - inner, request, block_id, - ) - .await?), + Self::JsonRpcHttp(inner) => { + as Provider>::call(inner, request, block_id).await + } Self::SequencerGateway(inner) => { - Ok(::call(inner, request, block_id).await?) + ::call(inner, request, block_id).await } } } @@ -328,20 +310,19 @@ impl Provider for AnyProvider { &self, request: R, block_id: B, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where R: AsRef<[BroadcastedTransaction]> + Send + Sync, B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::estimate_fee(inner, request, block_id) - .await?, - ), - Self::SequencerGateway(inner) => Ok( - ::estimate_fee(inner, request, block_id) - .await?, - ), + .await + } + Self::SequencerGateway(inner) => { + ::estimate_fee(inner, request, block_id).await + } } } @@ -349,80 +330,78 @@ impl Provider for AnyProvider { &self, message: M, block_id: B, - ) -> Result> + ) -> Result where M: AsRef + Send + Sync, B: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::estimate_message_fee( inner, message, block_id, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::estimate_message_fee( inner, message, block_id, ) - .await?, - ), + .await + } } } - async fn block_number(&self) -> Result> { + async fn block_number(&self) -> Result { match self { Self::JsonRpcHttp(inner) => { - Ok( as Provider>::block_number(inner).await?) + as Provider>::block_number(inner).await } Self::SequencerGateway(inner) => { - Ok(::block_number(inner).await?) + ::block_number(inner).await } } } - async fn block_hash_and_number( - &self, - ) -> Result> { + async fn block_hash_and_number(&self) -> Result { match self { - Self::JsonRpcHttp(inner) => Ok( - as Provider>::block_hash_and_number(inner).await?, - ), + Self::JsonRpcHttp(inner) => { + as Provider>::block_hash_and_number(inner).await + } Self::SequencerGateway(inner) => { - Ok(::block_hash_and_number(inner).await?) + ::block_hash_and_number(inner).await } } } - async fn chain_id(&self) -> Result> { + async fn chain_id(&self) -> Result { match self { Self::JsonRpcHttp(inner) => { - Ok( as Provider>::chain_id(inner).await?) + as Provider>::chain_id(inner).await } Self::SequencerGateway(inner) => { - Ok(::chain_id(inner).await?) + ::chain_id(inner).await } } } - async fn pending_transactions(&self) -> Result, ProviderError> { + async fn pending_transactions(&self) -> Result, ProviderError> { match self { Self::JsonRpcHttp(inner) => { - Ok( as Provider>::pending_transactions(inner).await?) + as Provider>::pending_transactions(inner).await } Self::SequencerGateway(inner) => { - Ok(::pending_transactions(inner).await?) + ::pending_transactions(inner).await } } } - async fn syncing(&self) -> Result> { + async fn syncing(&self) -> Result { match self { Self::JsonRpcHttp(inner) => { - Ok( as Provider>::syncing(inner).await?) + as Provider>::syncing(inner).await } Self::SequencerGateway(inner) => { - Ok(::syncing(inner).await?) + ::syncing(inner).await } } } @@ -432,23 +411,25 @@ impl Provider for AnyProvider { filter: EventFilter, continuation_token: Option, chunk_size: u64, - ) -> Result> { + ) -> Result { match self { - Self::JsonRpcHttp(inner) => Ok( as Provider>::get_events( - inner, - filter, - continuation_token, - chunk_size, - ) - .await?), + Self::JsonRpcHttp(inner) => { + as Provider>::get_events( + inner, + filter, + continuation_token, + chunk_size, + ) + .await + } Self::SequencerGateway(inner) => { - Ok(::get_events( + ::get_events( inner, filter, continuation_token, chunk_size, ) - .await?) + .await } } } @@ -457,121 +438,121 @@ impl Provider for AnyProvider { &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( as Provider>::get_nonce( - inner, - block_id, - contract_address, - ) - .await?), - Self::SequencerGateway(inner) => Ok(::get_nonce( - inner, - block_id, - contract_address, - ) - .await?), + Self::JsonRpcHttp(inner) => { + as Provider>::get_nonce( + inner, + block_id, + contract_address, + ) + .await + } + Self::SequencerGateway(inner) => { + ::get_nonce(inner, block_id, contract_address) + .await + } } } async fn add_invoke_transaction( &self, invoke_transaction: I, - ) -> Result> + ) -> Result where I: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::add_invoke_transaction( inner, invoke_transaction, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::add_invoke_transaction( inner, invoke_transaction, ) - .await?, - ), + .await + } } } async fn add_declare_transaction( &self, declare_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::add_declare_transaction( inner, declare_transaction, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::add_declare_transaction( inner, declare_transaction, ) - .await?, - ), + .await + } } } async fn add_deploy_account_transaction( &self, deploy_account_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::add_deploy_account_transaction( inner, deploy_account_transaction, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::add_deploy_account_transaction( inner, deploy_account_transaction, ) - .await?, - ), + .await + } } } async fn trace_transaction( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::trace_transaction( inner, transaction_hash, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::trace_transaction(inner, transaction_hash) - .await?, - ), + .await + } } } @@ -580,78 +561,52 @@ impl Provider for AnyProvider { block_id: B, transactions: T, simulation_flags: S, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where B: AsRef + Send + Sync, T: AsRef<[BroadcastedTransaction]> + Send + Sync, S: AsRef<[SimulationFlag]> + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::simulate_transactions( inner, block_id, transactions, simulation_flags, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::simulate_transactions( inner, block_id, transactions, simulation_flags, ) - .await?, - ), + .await + } } } async fn trace_block_transactions( &self, block_hash: H, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where H: AsRef + Send + Sync, { match self { - Self::JsonRpcHttp(inner) => Ok( + Self::JsonRpcHttp(inner) => { as Provider>::trace_block_transactions( inner, block_hash, ) - .await?, - ), - Self::SequencerGateway(inner) => Ok( + .await + } + Self::SequencerGateway(inner) => { ::trace_block_transactions(inner, block_hash) - .await?, - ), - } - } -} - -impl From as Provider>::Error>> - for ProviderError -{ - fn from(value: ProviderError< as Provider>::Error>) -> Self { - match value { - ProviderError::StarknetError(inner) => Self::StarknetError(inner), - ProviderError::RateLimited => Self::RateLimited, - ProviderError::ArrayLengthMismatch => Self::ArrayLengthMismatch, - ProviderError::Other(inner) => Self::Other(AnyProviderError::JsonRpcHttp(inner)), - } - } -} - -impl From::Error>> - for ProviderError -{ - fn from(value: ProviderError<::Error>) -> Self { - match value { - ProviderError::StarknetError(inner) => Self::StarknetError(inner), - ProviderError::RateLimited => Self::RateLimited, - ProviderError::ArrayLengthMismatch => Self::ArrayLengthMismatch, - ProviderError::Other(inner) => Self::Other(AnyProviderError::SequencerGateway(inner)), + .await + } } } } diff --git a/starknet-providers/src/jsonrpc/mod.rs b/starknet-providers/src/jsonrpc/mod.rs index 0daedb1a..4817e3af 100644 --- a/starknet-providers/src/jsonrpc/mod.rs +++ b/starknet-providers/src/jsonrpc/mod.rs @@ -1,3 +1,5 @@ +use std::{any::Any, error::Error}; + use async_trait::async_trait; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_with::serde_as; @@ -16,7 +18,7 @@ use starknet_core::{ }; use crate::{ - provider::{MaybeUnknownErrorCode, StarknetErrorWithMessage}, + provider::{MaybeUnknownErrorCode, ProviderImplError, StarknetErrorWithMessage}, Provider, ProviderError, }; @@ -171,13 +173,9 @@ impl JsonRpcClient { impl JsonRpcClient where - T: JsonRpcTransport, + T: 'static + JsonRpcTransport + Send + Sync, { - async fn send_request( - &self, - method: JsonRpcMethod, - params: P, - ) -> Result>> + async fn send_request(&self, method: JsonRpcMethod, params: P) -> Result where P: Serialize + Send, R: DeserializeOwned, @@ -186,7 +184,7 @@ where .transport .send_request(method, params) .await - .map_err(|err| ProviderError::Other(JsonRpcClientError::TransportError(err)))? + .map_err(JsonRpcClientError::TransportError)? { JsonRpcResponse::Success { result, .. } => Ok(result), JsonRpcResponse::Error { error, .. } => { @@ -206,15 +204,13 @@ where #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] impl Provider for JsonRpcClient where - T: JsonRpcTransport + Sync + Send, + T: 'static + JsonRpcTransport + Sync + Send, { - type Error = JsonRpcClientError; - /// Get block information with transaction hashes given the block id async fn get_block_with_tx_hashes( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -231,7 +227,7 @@ where async fn get_block_with_txs( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -248,7 +244,7 @@ where async fn get_state_update( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -267,7 +263,7 @@ where contract_address: A, key: K, block_id: B, - ) -> Result> + ) -> Result where A: AsRef + Send + Sync, K: AsRef + Send + Sync, @@ -290,7 +286,7 @@ where async fn get_transaction_by_hash( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { @@ -308,7 +304,7 @@ where &self, block_id: B, index: u64, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -326,7 +322,7 @@ where async fn get_transaction_receipt( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { @@ -344,7 +340,7 @@ where &self, block_id: B, class_hash: H, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, H: AsRef + Send + Sync, @@ -364,7 +360,7 @@ where &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, @@ -386,7 +382,7 @@ where &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, @@ -402,10 +398,7 @@ where } /// Get the number of transactions in a block given a block id - async fn get_block_transaction_count( - &self, - block_id: B, - ) -> Result> + async fn get_block_transaction_count(&self, block_id: B) -> Result where B: AsRef + Send + Sync, { @@ -419,11 +412,7 @@ where } /// Call a starknet function without creating a Starknet transaction - async fn call( - &self, - request: R, - block_id: B, - ) -> Result, ProviderError> + async fn call(&self, request: R, block_id: B) -> Result, ProviderError> where R: AsRef + Send + Sync, B: AsRef + Send + Sync, @@ -445,7 +434,7 @@ where &self, request: R, block_id: B, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where R: AsRef<[BroadcastedTransaction]> + Send + Sync, B: AsRef + Send + Sync, @@ -465,7 +454,7 @@ where &self, message: M, block_id: B, - ) -> Result> + ) -> Result where M: AsRef + Send + Sync, B: AsRef + Send + Sync, @@ -481,21 +470,19 @@ where } /// Get the most recent accepted block number - async fn block_number(&self) -> Result> { + async fn block_number(&self) -> Result { self.send_request(JsonRpcMethod::BlockNumber, BlockNumberRequest) .await } /// Get the most recent accepted block hash and number - async fn block_hash_and_number( - &self, - ) -> Result> { + async fn block_hash_and_number(&self) -> Result { self.send_request(JsonRpcMethod::BlockHashAndNumber, BlockHashAndNumberRequest) .await } /// Return the currently configured Starknet chain id - async fn chain_id(&self) -> Result> { + async fn chain_id(&self) -> Result { Ok(self .send_request::<_, Felt>(JsonRpcMethod::ChainId, ChainIdRequest) .await? @@ -503,7 +490,7 @@ where } /// Returns the transactions in the transaction pool, recognized by this sequencer - async fn pending_transactions(&self) -> Result, ProviderError> { + async fn pending_transactions(&self) -> Result, ProviderError> { self.send_request( JsonRpcMethod::PendingTransactions, PendingTransactionsRequest, @@ -512,7 +499,7 @@ where } /// Returns an object about the sync status, or false if the node is not synching - async fn syncing(&self) -> Result> { + async fn syncing(&self) -> Result { self.send_request(JsonRpcMethod::Syncing, SyncingRequest) .await } @@ -523,7 +510,7 @@ where filter: EventFilter, continuation_token: Option, chunk_size: u64, - ) -> Result> { + ) -> Result { self.send_request( JsonRpcMethod::GetEvents, GetEventsRequestRef { @@ -544,7 +531,7 @@ where &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, @@ -565,7 +552,7 @@ where async fn add_invoke_transaction( &self, invoke_transaction: I, - ) -> Result> + ) -> Result where I: AsRef + Send + Sync, { @@ -582,7 +569,7 @@ where async fn add_declare_transaction( &self, declare_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync, { @@ -599,7 +586,7 @@ where async fn add_deploy_account_transaction( &self, deploy_account_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync, { @@ -617,7 +604,7 @@ where async fn trace_transaction( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { @@ -637,7 +624,7 @@ where block_id: B, transactions: TX, simulation_flags: S, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where B: AsRef + Send + Sync, TX: AsRef<[BroadcastedTransaction]> + Send + Sync, @@ -658,7 +645,7 @@ where async fn trace_block_transactions( &self, block_hash: H, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where H: AsRef + Send + Sync, { @@ -815,6 +802,24 @@ impl<'de> Deserialize<'de> for JsonRpcRequest { } } +impl ProviderImplError for JsonRpcClientError +where + T: 'static + Error + Send + Sync, +{ + fn as_any(&self) -> &dyn Any { + self + } +} + +impl From> for ProviderError +where + T: 'static + Error + Send + Sync, +{ + fn from(value: JsonRpcClientError) -> Self { + Self::Other(Box::new(value)) + } +} + impl From for JsonRpcClientError { fn from(value: serde_json::Error) -> Self { Self::JsonError(value) diff --git a/starknet-providers/src/lib.rs b/starknet-providers/src/lib.rs index 070019d4..491a3278 100644 --- a/starknet-providers/src/lib.rs +++ b/starknet-providers/src/lib.rs @@ -12,4 +12,4 @@ pub mod jsonrpc; pub use jsonrpc::JsonRpcClient; mod any; -pub use any::{AnyProvider, AnyProviderError}; +pub use any::AnyProvider; diff --git a/starknet-providers/src/provider.rs b/starknet-providers/src/provider.rs index 75d4d875..4d08886f 100644 --- a/starknet-providers/src/provider.rs +++ b/starknet-providers/src/provider.rs @@ -9,19 +9,17 @@ use starknet_core::types::{ MaybePendingTransactionReceipt, MsgFromL1, SimulatedTransaction, SimulationFlag, StarknetError, SyncStatusType, Transaction, TransactionTrace, TransactionTraceWithHash, }; -use std::error::Error; +use std::{any::Any, error::Error, fmt::Debug}; #[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[auto_impl(&, Box, Arc)] pub trait Provider { - type Error: Error + Send + Sync; - /// Get block information with transaction hashes given the block id async fn get_block_with_tx_hashes( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync; @@ -29,7 +27,7 @@ pub trait Provider { async fn get_block_with_txs( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync; @@ -37,7 +35,7 @@ pub trait Provider { async fn get_state_update( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync; @@ -47,7 +45,7 @@ pub trait Provider { contract_address: A, key: K, block_id: B, - ) -> Result> + ) -> Result where A: AsRef + Send + Sync, K: AsRef + Send + Sync, @@ -57,7 +55,7 @@ pub trait Provider { async fn get_transaction_by_hash( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync; @@ -66,7 +64,7 @@ pub trait Provider { &self, block_id: B, index: u64, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync; @@ -74,7 +72,7 @@ pub trait Provider { async fn get_transaction_receipt( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync; @@ -83,7 +81,7 @@ pub trait Provider { &self, block_id: B, class_hash: H, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, H: AsRef + Send + Sync; @@ -93,7 +91,7 @@ pub trait Provider { &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync; @@ -103,25 +101,18 @@ pub trait Provider { &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync; /// Get the number of transactions in a block given a block id - async fn get_block_transaction_count( - &self, - block_id: B, - ) -> Result> + async fn get_block_transaction_count(&self, block_id: B) -> Result where B: AsRef + Send + Sync; /// Call a starknet function without creating a Starknet transaction - async fn call( - &self, - request: R, - block_id: B, - ) -> Result, ProviderError> + async fn call(&self, request: R, block_id: B) -> Result, ProviderError> where R: AsRef + Send + Sync, B: AsRef + Send + Sync; @@ -131,7 +122,7 @@ pub trait Provider { &self, request: R, block_id: B, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where R: AsRef<[BroadcastedTransaction]> + Send + Sync, B: AsRef + Send + Sync; @@ -140,26 +131,25 @@ pub trait Provider { &self, message: M, block_id: B, - ) -> Result> + ) -> Result where M: AsRef + Send + Sync, B: AsRef + Send + Sync; /// Get the most recent accepted block number - async fn block_number(&self) -> Result>; + async fn block_number(&self) -> Result; /// Get the most recent accepted block hash and number - async fn block_hash_and_number(&self) - -> Result>; + async fn block_hash_and_number(&self) -> Result; /// Return the currently configured Starknet chain id - async fn chain_id(&self) -> Result>; + async fn chain_id(&self) -> Result; /// Returns the transactions in the transaction pool, recognized by this sequencer - async fn pending_transactions(&self) -> Result, ProviderError>; + async fn pending_transactions(&self) -> Result, ProviderError>; /// Returns an object about the sync status, or false if the node is not synching - async fn syncing(&self) -> Result>; + async fn syncing(&self) -> Result; /// Returns all events matching the given filter async fn get_events( @@ -167,14 +157,14 @@ pub trait Provider { filter: EventFilter, continuation_token: Option, chunk_size: u64, - ) -> Result>; + ) -> Result; /// Get the nonce associated with the given address in the given block async fn get_nonce( &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync; @@ -183,7 +173,7 @@ pub trait Provider { async fn add_invoke_transaction( &self, invoke_transaction: I, - ) -> Result> + ) -> Result where I: AsRef + Send + Sync; @@ -191,7 +181,7 @@ pub trait Provider { async fn add_declare_transaction( &self, declare_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync; @@ -199,7 +189,7 @@ pub trait Provider { async fn add_deploy_account_transaction( &self, deploy_account_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync; @@ -208,7 +198,7 @@ pub trait Provider { async fn trace_transaction( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync; @@ -219,7 +209,7 @@ pub trait Provider { block_id: B, transactions: T, simulation_flags: S, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where B: AsRef + Send + Sync, T: AsRef<[BroadcastedTransaction]> + Send + Sync, @@ -229,7 +219,7 @@ pub trait Provider { async fn trace_block_transactions( &self, block_hash: H, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where H: AsRef + Send + Sync; @@ -238,7 +228,7 @@ pub trait Provider { &self, request: R, block_id: B, - ) -> Result> + ) -> Result where R: AsRef + Send + Sync, B: AsRef + Send + Sync, @@ -261,7 +251,7 @@ pub trait Provider { block_id: B, transaction: T, simulation_flags: S, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, T: AsRef + Send + Sync, @@ -284,16 +274,27 @@ pub trait Provider { } } +/// Trait for implementation-specific error type. These errors are irrelevant in most cases, +/// assuming that users typically care more about the specifics of RPC errors instead of the +/// underlying transport. Therefore, it makes little sense to bloat [ProviderError] with a generic +/// parameter just for these errors. Instead, they're erased to this trait object. +/// +/// This trait is used instead of a plain [std::error::Error] to allow downcasting, in case access +/// to the specific error type is indeed desired. This is achieved with the `as_any()` method. +pub trait ProviderImplError: Error + Debug + Send + Sync { + fn as_any(&self) -> &dyn Any; +} + #[derive(Debug, thiserror::Error)] -pub enum ProviderError { +pub enum ProviderError { #[error(transparent)] StarknetError(StarknetErrorWithMessage), #[error("Request rate limited")] RateLimited, #[error("Array length mismatch")] ArrayLengthMismatch, - #[error(transparent)] - Other(E), + #[error("{0}")] + Other(Box), } #[derive(Debug, thiserror::Error)] diff --git a/starknet-providers/src/sequencer/mod.rs b/starknet-providers/src/sequencer/mod.rs index abe0cbdf..429b98a3 100644 --- a/starknet-providers/src/sequencer/mod.rs +++ b/starknet-providers/src/sequencer/mod.rs @@ -192,7 +192,7 @@ impl SequencerGatewayProvider { url } - async fn send_get_request(&self, url: Url) -> Result> + async fn send_get_request(&self, url: Url) -> Result where T: DeserializeOwned, { @@ -203,33 +203,24 @@ impl SequencerGatewayProvider { .get(url) .send() .await - .map_err(|err| ProviderError::Other(GatewayClientError::Network(err)))?; + .map_err(GatewayClientError::Network)?; if res.status() == StatusCode::TOO_MANY_REQUESTS { Err(ProviderError::RateLimited) } else { - let body = res - .text() - .await - .map_err(|err| ProviderError::Other(GatewayClientError::Network(err)))?; + let body = res.text().await.map_err(GatewayClientError::Network)?; trace!("Response from sequencer API: {}", body); - serde_json::from_str(&body) - .map_err(|err| ProviderError::Other(GatewayClientError::Serde(err))) + Ok(serde_json::from_str(&body).map_err(GatewayClientError::Serde)?) } } - async fn send_post_request( - &self, - url: Url, - body: &Q, - ) -> Result> + async fn send_post_request(&self, url: Url, body: &Q) -> Result where Q: Serialize, S: DeserializeOwned, { - let request_body = serde_json::to_string(body) - .map_err(|err| ProviderError::Other(GatewayClientError::Serde(err)))?; + let request_body = serde_json::to_string(body).map_err(GatewayClientError::Serde)?; trace!( "Sending POST request to sequencer API ({}): {}", @@ -244,19 +235,15 @@ impl SequencerGatewayProvider { .body(request_body) .send() .await - .map_err(|err| ProviderError::Other(GatewayClientError::Network(err)))?; + .map_err(GatewayClientError::Network)?; if res.status() == StatusCode::TOO_MANY_REQUESTS { Err(ProviderError::RateLimited) } else { - let body = res - .text() - .await - .map_err(|err| ProviderError::Other(GatewayClientError::Network(err)))?; + let body = res.text().await.map_err(GatewayClientError::Network)?; trace!("Response from sequencer API: {}", body); - serde_json::from_str(&body) - .map_err(|err| ProviderError::Other(GatewayClientError::Serde(err))) + Ok(serde_json::from_str(&body).map_err(GatewayClientError::Serde)?) } } } @@ -268,7 +255,7 @@ impl SequencerGatewayProvider { pub async fn add_transaction( &self, tx: TransactionRequest, - ) -> Result> { + ) -> Result { let request_url = self.extend_gateway_url("add_transaction"); self.send_post_request::<_, GatewayResponse<_>>(request_url, &tx) @@ -279,9 +266,7 @@ impl SequencerGatewayProvider { #[deprecated( note = "Sequencer-specific functions are deprecated. Use it via the Provider trait instead." )] - pub async fn get_contract_addresses( - &self, - ) -> Result> { + pub async fn get_contract_addresses(&self) -> Result { let request_url = self.extend_feeder_gateway_url("get_contract_addresses"); self.send_get_request::>(request_url) @@ -296,7 +281,7 @@ impl SequencerGatewayProvider { &self, call_function: CallFunction, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("call_contract"); append_block_id(&mut request_url, block_identifier); @@ -313,7 +298,7 @@ impl SequencerGatewayProvider { tx: AccountTransaction, block_identifier: BlockId, skip_validate: bool, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("estimate_fee"); request_url .query_pairs_mut() @@ -333,7 +318,7 @@ impl SequencerGatewayProvider { txs: &[AccountTransaction], block_identifier: BlockId, skip_validate: bool, - ) -> Result, ProviderError> { + ) -> Result, ProviderError> { let mut request_url = self.extend_feeder_gateway_url("estimate_fee_bulk"); request_url .query_pairs_mut() @@ -352,7 +337,7 @@ impl SequencerGatewayProvider { &self, call_l1_handler: CallL1Handler, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("estimate_message_fee"); append_block_id(&mut request_url, block_identifier); @@ -369,7 +354,7 @@ impl SequencerGatewayProvider { tx: AccountTransaction, block_identifier: BlockId, skip_validate: bool, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("simulate_transaction"); request_url .query_pairs_mut() @@ -384,10 +369,7 @@ impl SequencerGatewayProvider { #[deprecated( note = "Sequencer-specific functions are deprecated. Use it via the Provider trait instead." )] - pub async fn get_block( - &self, - block_identifier: BlockId, - ) -> Result> { + pub async fn get_block(&self, block_identifier: BlockId) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_block"); append_block_id(&mut request_url, block_identifier); @@ -402,7 +384,7 @@ impl SequencerGatewayProvider { pub async fn get_block_traces( &self, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_block_traces"); append_block_id(&mut request_url, block_identifier); @@ -417,7 +399,7 @@ impl SequencerGatewayProvider { pub async fn get_state_update( &self, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_state_update"); append_block_id(&mut request_url, block_identifier); @@ -433,7 +415,7 @@ impl SequencerGatewayProvider { &self, contract_address: FieldElement, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_code"); request_url .query_pairs_mut() @@ -460,7 +442,7 @@ impl SequencerGatewayProvider { &self, contract_address: FieldElement, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_full_contract"); request_url .query_pairs_mut() @@ -479,7 +461,7 @@ impl SequencerGatewayProvider { &self, class_hash: FieldElement, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_compiled_class_by_class_hash"); request_url .query_pairs_mut() @@ -498,7 +480,7 @@ impl SequencerGatewayProvider { &self, contract_address: FieldElement, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_class_hash_at"); request_url .query_pairs_mut() @@ -517,7 +499,7 @@ impl SequencerGatewayProvider { &self, class_hash: FieldElement, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_class_by_hash"); request_url .query_pairs_mut() @@ -537,7 +519,7 @@ impl SequencerGatewayProvider { contract_address: FieldElement, key: FieldElement, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_storage_at"); request_url .query_pairs_mut() @@ -557,7 +539,7 @@ impl SequencerGatewayProvider { &self, contract_address: FieldElement, block_identifier: BlockId, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_nonce"); request_url .query_pairs_mut() @@ -575,7 +557,7 @@ impl SequencerGatewayProvider { pub async fn get_transaction_status( &self, transaction_hash: FieldElement, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_transaction_status"); request_url .query_pairs_mut() @@ -592,7 +574,7 @@ impl SequencerGatewayProvider { pub async fn get_transaction( &self, transaction_hash: FieldElement, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_transaction"); request_url .query_pairs_mut() @@ -609,7 +591,7 @@ impl SequencerGatewayProvider { pub async fn get_transaction_receipt( &self, transaction_hash: FieldElement, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_transaction_receipt"); request_url .query_pairs_mut() @@ -626,7 +608,7 @@ impl SequencerGatewayProvider { pub async fn get_transaction_trace( &self, transaction_hash: FieldElement, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_transaction_trace"); request_url .query_pairs_mut() @@ -643,7 +625,7 @@ impl SequencerGatewayProvider { pub async fn get_block_hash_by_id( &self, block_number: u64, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_block_hash_by_id"); request_url .query_pairs_mut() @@ -660,7 +642,7 @@ impl SequencerGatewayProvider { pub async fn get_block_id_by_hash( &self, block_hash: FieldElement, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_block_id_by_hash"); request_url .query_pairs_mut() @@ -677,7 +659,7 @@ impl SequencerGatewayProvider { pub async fn get_transaction_hash_by_id( &self, transaction_number: u64, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_transaction_hash_by_id"); request_url .query_pairs_mut() @@ -694,7 +676,7 @@ impl SequencerGatewayProvider { pub async fn get_transaction_id_by_hash( &self, transaction_hash: FieldElement, - ) -> Result> { + ) -> Result { let mut request_url = self.extend_feeder_gateway_url("get_transaction_id_by_hash"); request_url .query_pairs_mut() @@ -708,7 +690,7 @@ impl SequencerGatewayProvider { #[deprecated( note = "Sequencer-specific functions are deprecated. Use it via the Provider trait instead." )] - pub async fn get_last_batch_id(&self) -> Result> { + pub async fn get_last_batch_id(&self) -> Result { let request_url = self.extend_feeder_gateway_url("get_last_batch_id"); self.send_get_request::>(request_url) @@ -719,7 +701,7 @@ impl SequencerGatewayProvider { #[deprecated( note = "Sequencer-specific functions are deprecated. Use it via the Provider trait instead." )] - pub async fn get_l1_blockchain_id(&self) -> Result> { + pub async fn get_l1_blockchain_id(&self) -> Result { let request_url = self.extend_feeder_gateway_url("get_l1_blockchain_id"); self.send_get_request::>(request_url) @@ -728,7 +710,7 @@ impl SequencerGatewayProvider { } } -impl From for ProviderError { +impl From for ProviderError { fn from(value: SequencerError) -> Self { let matching_code = match value.code { ErrorCode::BlockNotFound => Some(StarknetError::BlockNotFound), @@ -752,18 +734,18 @@ impl From for ProviderError { code: MaybeUnknownErrorCode::Known(code), message: value.message, }), - None => ProviderError::Other(GatewayClientError::SequencerError(value)), + None => GatewayClientError::SequencerError(value).into(), } } } -impl From for ProviderError { +impl From for ProviderError { fn from(_value: ConversionError) -> Self { - Self::Other(GatewayClientError::ModelConversionError) + Self::Other(Box::new(GatewayClientError::ModelConversionError)) } } -impl From> for Result> { +impl From> for Result { fn from(value: GatewayResponse) -> Self { match value { GatewayResponse::Data(data) => Ok(data), @@ -772,7 +754,7 @@ impl From> for Result } } -impl From for Result> { +impl From for Result { fn from(value: RawFieldElementResponse) -> Self { match value { RawFieldElementResponse::Data(data) => Ok(data), diff --git a/starknet-providers/src/sequencer/provider.rs b/starknet-providers/src/sequencer/provider.rs index 5901c23b..92478ca3 100644 --- a/starknet-providers/src/sequencer/provider.rs +++ b/starknet-providers/src/sequencer/provider.rs @@ -1,5 +1,7 @@ #![allow(deprecated)] +use std::any::Any; + use async_trait::async_trait; use starknet_core::types::{ BlockHashAndNumber, BlockId, BroadcastedDeclareTransaction, @@ -12,7 +14,7 @@ use starknet_core::types::{ }; use crate::{ - provider::{MaybeUnknownErrorCode, StarknetErrorWithMessage}, + provider::{MaybeUnknownErrorCode, ProviderImplError, StarknetErrorWithMessage}, sequencer::{ models::conversions::{ConversionError, TransactionWithReceipt}, GatewayClientError, @@ -24,12 +26,10 @@ use crate::{ #[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] impl Provider for SequencerGatewayProvider { - type Error = GatewayClientError; - async fn get_block_with_tx_hashes( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -42,7 +42,7 @@ impl Provider for SequencerGatewayProvider { async fn get_block_with_txs( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -55,7 +55,7 @@ impl Provider for SequencerGatewayProvider { async fn get_state_update( &self, block_id: B, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -70,7 +70,7 @@ impl Provider for SequencerGatewayProvider { contract_address: A, key: K, block_id: B, - ) -> Result> + ) -> Result where A: AsRef + Send + Sync, K: AsRef + Send + Sync, @@ -88,7 +88,7 @@ impl Provider for SequencerGatewayProvider { async fn get_transaction_by_hash( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { @@ -102,7 +102,7 @@ impl Provider for SequencerGatewayProvider { &self, block_id: B, index: u64, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, { @@ -112,19 +112,17 @@ impl Provider for SequencerGatewayProvider { if index < block.transactions.len() { Ok(block.transactions.remove(index).try_into()?) } else { - Err(ProviderError::::StarknetError( - StarknetErrorWithMessage { - code: MaybeUnknownErrorCode::Known(StarknetError::InvalidTransactionIndex), - message: "Invalid transaction index in a block".into(), - }, - )) + Err(ProviderError::StarknetError(StarknetErrorWithMessage { + code: MaybeUnknownErrorCode::Known(StarknetError::InvalidTransactionIndex), + message: "Invalid transaction index in a block".into(), + })) } } async fn get_transaction_receipt( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { @@ -136,12 +134,10 @@ impl Provider for SequencerGatewayProvider { if receipt.status == super::models::TransactionStatus::NotReceived || receipt.status == super::models::TransactionStatus::Received { - Err(ProviderError::::StarknetError( - StarknetErrorWithMessage { - code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound), - message: "Transaction hash not found".into(), - }, - )) + Err(ProviderError::StarknetError(StarknetErrorWithMessage { + code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound), + message: "Transaction hash not found".into(), + })) } else { // JSON-RPC also sends tx type, which is not available in our receipt type let tx = self.get_transaction(*transaction_hash.as_ref()).await?; @@ -158,7 +154,7 @@ impl Provider for SequencerGatewayProvider { &self, block_id: B, class_hash: H, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, H: AsRef + Send + Sync, @@ -173,7 +169,7 @@ impl Provider for SequencerGatewayProvider { &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, @@ -190,7 +186,7 @@ impl Provider for SequencerGatewayProvider { &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, @@ -204,10 +200,7 @@ impl Provider for SequencerGatewayProvider { .try_into()?) } - async fn get_block_transaction_count( - &self, - block_id: B, - ) -> Result> + async fn get_block_transaction_count(&self, block_id: B) -> Result where B: AsRef + Send + Sync, { @@ -215,11 +208,7 @@ impl Provider for SequencerGatewayProvider { Ok(block.transactions.len() as u64) } - async fn call( - &self, - request: R, - block_id: B, - ) -> Result, ProviderError> + async fn call(&self, request: R, block_id: B) -> Result, ProviderError> where R: AsRef + Send + Sync, B: AsRef + Send + Sync, @@ -237,7 +226,7 @@ impl Provider for SequencerGatewayProvider { &self, request: R, block_id: B, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where R: AsRef<[BroadcastedTransaction]> + Send + Sync, B: AsRef + Send + Sync, @@ -262,7 +251,7 @@ impl Provider for SequencerGatewayProvider { &self, message: M, block_id: B, - ) -> Result> + ) -> Result where M: AsRef + Send + Sync, B: AsRef + Send + Sync, @@ -276,14 +265,12 @@ impl Provider for SequencerGatewayProvider { .into()) } - async fn block_number(&self) -> Result> { + async fn block_number(&self) -> Result { let block = self.get_block(super::models::BlockId::Latest).await?; Ok(block.block_number.ok_or(ConversionError)?) } - async fn block_hash_and_number( - &self, - ) -> Result> { + async fn block_hash_and_number(&self) -> Result { let block = self.get_block(super::models::BlockId::Latest).await?; Ok(BlockHashAndNumber { block_hash: block.block_hash.ok_or(ConversionError)?, @@ -291,11 +278,11 @@ impl Provider for SequencerGatewayProvider { }) } - async fn chain_id(&self) -> Result> { + async fn chain_id(&self) -> Result { Ok(self.chain_id) } - async fn pending_transactions(&self) -> Result, ProviderError> { + async fn pending_transactions(&self) -> Result, ProviderError> { let block = self.get_block(super::models::BlockId::Pending).await?; if block.status == super::models::BlockStatus::Pending { Ok(block @@ -308,7 +295,7 @@ impl Provider for SequencerGatewayProvider { } } - async fn syncing(&self) -> Result> { + async fn syncing(&self) -> Result { Ok(SyncStatusType::NotSyncing) } @@ -317,15 +304,17 @@ impl Provider for SequencerGatewayProvider { filter: EventFilter, continuation_token: Option, chunk_size: u64, - ) -> Result> { - Err(ProviderError::Other(Self::Error::MethodNotSupported)) + ) -> Result { + Err(ProviderError::Other(Box::new( + GatewayClientError::MethodNotSupported, + ))) } async fn get_nonce( &self, block_id: B, contract_address: A, - ) -> Result> + ) -> Result where B: AsRef + Send + Sync, A: AsRef + Send + Sync, @@ -341,7 +330,7 @@ impl Provider for SequencerGatewayProvider { async fn add_invoke_transaction( &self, invoke_transaction: I, - ) -> Result> + ) -> Result where I: AsRef + Send + Sync, { @@ -359,7 +348,7 @@ impl Provider for SequencerGatewayProvider { async fn add_declare_transaction( &self, declare_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync, { @@ -378,7 +367,7 @@ impl Provider for SequencerGatewayProvider { async fn add_deploy_account_transaction( &self, deploy_account_transaction: D, - ) -> Result> + ) -> Result where D: AsRef + Send + Sync, { @@ -397,7 +386,7 @@ impl Provider for SequencerGatewayProvider { async fn trace_transaction( &self, transaction_hash: H, - ) -> Result> + ) -> Result where H: AsRef + Send + Sync, { @@ -412,7 +401,7 @@ impl Provider for SequencerGatewayProvider { block_id: B, transactions: T, simulation_flags: S, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where B: AsRef + Send + Sync, T: AsRef<[BroadcastedTransaction]> + Send + Sync, @@ -420,9 +409,9 @@ impl Provider for SequencerGatewayProvider { { let transactions = transactions.as_ref(); if transactions.len() != 1 { - return Err(ProviderError::Other( + return Err(ProviderError::Other(Box::new( GatewayClientError::BulkSimulationNotSupported, - )); + ))); } let transaction = transactions[0].to_owned(); @@ -434,9 +423,9 @@ impl Provider for SequencerGatewayProvider { skip_validate = true; } SimulationFlag::SkipFeeCharge => { - return Err(ProviderError::Other( + return Err(ProviderError::Other(Box::new( GatewayClientError::UnsupportedSimulationFlag, - )); + ))); } } } @@ -455,7 +444,7 @@ impl Provider for SequencerGatewayProvider { async fn trace_block_transactions( &self, block_hash: H, - ) -> Result, ProviderError> + ) -> Result, ProviderError> where H: AsRef + Send + Sync, { @@ -468,3 +457,15 @@ impl Provider for SequencerGatewayProvider { .collect::, _>>()?) } } + +impl ProviderImplError for GatewayClientError { + fn as_any(&self) -> &dyn Any { + self + } +} + +impl From for ProviderError { + fn from(value: GatewayClientError) -> Self { + Self::Other(Box::new(value)) + } +}