Skip to content

Commit 4107312

Browse files
authored
feat: revamp provider error handling (#511)
Greatly simplify provider error code matching. Previously, the error code returned from the RPC is an enum with 2 variants for known and unknown codes to accommodate the fact that JSON-RPC nodes sometimes return codes that are part of the JSON-RPC standard, but are not from the Starknet specifications. This commit changes to move the unknown codes to be handled by the implementation-specific error type instead, making it much easier to match against specification error codes, at the cost of being harder to match the unknown codes.
1 parent e685b5e commit 4107312

File tree

8 files changed

+62
-79
lines changed

8 files changed

+62
-79
lines changed

starknet-accounts/src/factory/mod.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ use starknet_core::{
99
SimulationFlag, StarknetError,
1010
},
1111
};
12-
use starknet_providers::{
13-
MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage,
14-
};
12+
use starknet_providers::{Provider, ProviderError};
1513
use std::error::Error;
1614

1715
pub mod argent;
@@ -178,10 +176,9 @@ where
178176
.await
179177
{
180178
Ok(nonce) => Ok(nonce),
181-
Err(ProviderError::StarknetError(StarknetErrorWithMessage {
182-
code: MaybeUnknownErrorCode::Known(StarknetError::ContractNotFound),
183-
..
184-
})) => Ok(FieldElement::ZERO),
179+
Err(ProviderError::StarknetError(StarknetError::ContractNotFound)) => {
180+
Ok(FieldElement::ZERO)
181+
}
185182
Err(err) => Err(err),
186183
}
187184
}

starknet-core/src/types/codegen.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// https://github.com/xJonathanLEI/starknet-jsonrpc-codegen
44

55
// Code generated with version:
6-
// https://github.com/xJonathanLEI/starknet-jsonrpc-codegen#3215ab04aee89aafa48973cdcf027219f662f49d
6+
// https://github.com/xJonathanLEI/starknet-jsonrpc-codegen#51260963a0723fdbc715598efb7198ce5a1d49b9
77

88
// Code generation requested but not implemented for these types:
99
// - `BLOCK_ID`
@@ -1397,6 +1397,39 @@ impl core::fmt::Display for StarknetError {
13971397
}
13981398
}
13991399

1400+
impl StarknetError {
1401+
pub fn message(&self) -> &'static str {
1402+
match self {
1403+
Self::FailedToReceiveTransaction => "Failed to write transaction",
1404+
Self::ContractNotFound => "Contract not found",
1405+
Self::BlockNotFound => "Block not found",
1406+
Self::InvalidTransactionIndex => "Invalid transaction index in a block",
1407+
Self::ClassHashNotFound => "Class hash not found",
1408+
Self::TransactionHashNotFound => "Transaction hash not found",
1409+
Self::PageSizeTooBig => "Requested page size is too big",
1410+
Self::NoBlocks => "There are no blocks",
1411+
Self::InvalidContinuationToken => "The supplied continuation token is invalid or unknown",
1412+
Self::TooManyKeysInFilter => "Too many keys provided in a filter",
1413+
Self::ContractError => "Contract error",
1414+
Self::ClassAlreadyDeclared => "Class already declared",
1415+
Self::InvalidTransactionNonce => "Invalid transaction nonce",
1416+
Self::InsufficientMaxFee => "Max fee is smaller than the minimal transaction cost (validation plus fee transfer)",
1417+
Self::InsufficientAccountBalance => "Account balance is smaller than the transaction's max_fee",
1418+
Self::ValidationFailure => "Account validation failed",
1419+
Self::CompilationFailed => "Compilation failed",
1420+
Self::ContractClassSizeIsTooLarge => "Contract class size it too large",
1421+
Self::NonAccount => "Sender address in not an account contract",
1422+
Self::DuplicateTx => "A transaction with the same hash already exists in the mempool",
1423+
Self::CompiledClassHashMismatch => "the compiled class hash did not match the one supplied in the transaction",
1424+
Self::UnsupportedTxVersion => "the transaction version is not supported",
1425+
Self::UnsupportedContractClassVersion => "the contract class version is not supported",
1426+
Self::UnexpectedError => "An unexpected error occurred",
1427+
Self::NoTraceAvailable => "No trace available for transaction",
1428+
Self::InvalidTransactionHash => "Invalid transaction hash",
1429+
}
1430+
}
1431+
}
1432+
14001433
/// The change in state applied in this block, given as a mapping of addresses to the new values
14011434
/// and/or new contracts.
14021435
#[serde_as]

starknet-providers/src/jsonrpc/mod.rs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@ use starknet_core::{
1212
EventFilterWithPage, EventsPage, FeeEstimate, FieldElement, FunctionCall,
1313
InvokeTransactionResult, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs,
1414
MaybePendingStateUpdate, MaybePendingTransactionReceipt, MsgFromL1, ResultPageRequest,
15-
SimulatedTransaction, SimulationFlag, StarknetError, SyncStatusType, Transaction,
16-
TransactionStatus, TransactionTrace, TransactionTraceWithHash,
15+
SimulatedTransaction, SimulationFlag, SyncStatusType, Transaction, TransactionStatus,
16+
TransactionTrace, TransactionTraceWithHash,
1717
},
1818
};
1919

20-
use crate::{
21-
provider::{MaybeUnknownErrorCode, ProviderImplError, StarknetErrorWithMessage},
22-
Provider, ProviderError,
23-
};
20+
use crate::{provider::ProviderImplError, Provider, ProviderError};
2421

2522
mod transports;
2623
pub use transports::{HttpTransport, HttpTransportError, JsonRpcTransport};
@@ -135,15 +132,7 @@ pub enum JsonRpcClientError<T> {
135132
#[error(transparent)]
136133
TransportError(T),
137134
#[error(transparent)]
138-
RpcError(RpcError),
139-
}
140-
141-
#[derive(Debug, thiserror::Error)]
142-
pub enum RpcError {
143-
#[error(transparent)]
144-
Code(StarknetError),
145-
#[error(transparent)]
146-
Unknown(JsonRpcError),
135+
JsonRpcError(JsonRpcError),
147136
}
148137

149138
#[derive(Debug, thiserror::Error, Deserialize)]
@@ -190,15 +179,10 @@ where
190179
.map_err(JsonRpcClientError::TransportError)?
191180
{
192181
JsonRpcResponse::Success { result, .. } => Ok(result),
193-
JsonRpcResponse::Error { error, .. } => {
194-
Err(ProviderError::StarknetError(StarknetErrorWithMessage {
195-
code: match error.code.try_into() {
196-
Ok(code) => MaybeUnknownErrorCode::Known(code),
197-
Err(_) => MaybeUnknownErrorCode::Unknown(error.code),
198-
},
199-
message: error.message,
200-
}))
201-
}
182+
JsonRpcResponse::Error { error, .. } => Err(match error.code.try_into() {
183+
Ok(code) => ProviderError::StarknetError(code),
184+
Err(_) => JsonRpcClientError::<T::Error>::JsonRpcError(error).into(),
185+
}),
202186
}
203187
}
204188
}

starknet-providers/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![doc = include_str!("../README.md")]
22

33
mod provider;
4-
pub use provider::{MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage};
4+
pub use provider::{Provider, ProviderError};
55

66
pub mod sequencer;
77
pub use sequencer::{

starknet-providers/src/provider.rs

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -297,33 +297,11 @@ pub trait ProviderImplError: Error + Debug + Send + Sync {
297297
#[derive(Debug, thiserror::Error)]
298298
pub enum ProviderError {
299299
#[error(transparent)]
300-
StarknetError(StarknetErrorWithMessage),
300+
StarknetError(StarknetError),
301301
#[error("Request rate limited")]
302302
RateLimited,
303303
#[error("Array length mismatch")]
304304
ArrayLengthMismatch,
305305
#[error("{0}")]
306306
Other(Box<dyn ProviderImplError>),
307307
}
308-
309-
#[derive(Debug, thiserror::Error)]
310-
#[error("code={code}, message=\"{message}\"")]
311-
pub struct StarknetErrorWithMessage {
312-
pub code: MaybeUnknownErrorCode,
313-
pub message: String,
314-
}
315-
316-
#[derive(Debug)]
317-
pub enum MaybeUnknownErrorCode {
318-
Known(StarknetError),
319-
Unknown(i64),
320-
}
321-
322-
impl core::fmt::Display for MaybeUnknownErrorCode {
323-
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
324-
match self {
325-
MaybeUnknownErrorCode::Known(code) => write!(f, "{}", code),
326-
MaybeUnknownErrorCode::Unknown(code) => write!(f, "{}", code),
327-
}
328-
}
329-
}

starknet-providers/src/sequencer/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::provider::{MaybeUnknownErrorCode, ProviderError, StarknetErrorWithMessage};
1+
use crate::provider::ProviderError;
22

33
use log::trace;
44
use reqwest::{Client, Error as ReqwestError, StatusCode};
@@ -730,10 +730,7 @@ impl From<SequencerError> for ProviderError {
730730
};
731731

732732
match matching_code {
733-
Some(code) => ProviderError::StarknetError(StarknetErrorWithMessage {
734-
code: MaybeUnknownErrorCode::Known(code),
735-
message: value.message,
736-
}),
733+
Some(code) => ProviderError::StarknetError(code),
737734
None => GatewayClientError::SequencerError(value).into(),
738735
}
739736
}

starknet-providers/src/sequencer/provider.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use starknet_core::types::{
1414
};
1515

1616
use crate::{
17-
provider::{MaybeUnknownErrorCode, ProviderImplError, StarknetErrorWithMessage},
17+
provider::ProviderImplError,
1818
sequencer::{
1919
models::conversions::{ConversionError, TransactionWithReceipt},
2020
GatewayClientError,
@@ -106,10 +106,9 @@ impl Provider for SequencerGatewayProvider {
106106

107107
// `NotReceived` is not a valid status for JSON-RPC. It's an error.
108108
if let Some(TransactionFinalityStatus::NotReceived) = &status.finality_status {
109-
return Err(ProviderError::StarknetError(StarknetErrorWithMessage {
110-
code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound),
111-
message: "Transaction hash not found".into(),
112-
}));
109+
return Err(ProviderError::StarknetError(
110+
StarknetError::TransactionHashNotFound,
111+
));
113112
}
114113

115114
Ok(status.try_into()?)
@@ -142,10 +141,9 @@ impl Provider for SequencerGatewayProvider {
142141
if index < block.transactions.len() {
143142
Ok(block.transactions.remove(index).try_into()?)
144143
} else {
145-
Err(ProviderError::StarknetError(StarknetErrorWithMessage {
146-
code: MaybeUnknownErrorCode::Known(StarknetError::InvalidTransactionIndex),
147-
message: "Invalid transaction index in a block".into(),
148-
}))
144+
Err(ProviderError::StarknetError(
145+
StarknetError::InvalidTransactionIndex,
146+
))
149147
}
150148
}
151149

@@ -164,10 +162,9 @@ impl Provider for SequencerGatewayProvider {
164162
if receipt.status == super::models::TransactionStatus::NotReceived
165163
|| receipt.status == super::models::TransactionStatus::Received
166164
{
167-
Err(ProviderError::StarknetError(StarknetErrorWithMessage {
168-
code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound),
169-
message: "Transaction hash not found".into(),
170-
}))
165+
Err(ProviderError::StarknetError(
166+
StarknetError::TransactionHashNotFound,
167+
))
171168
} else {
172169
// JSON-RPC also sends tx type, which is not available in our receipt type
173170
let tx = self.get_transaction(*transaction_hash.as_ref()).await?;

starknet-providers/tests/jsonrpc.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use starknet_core::{
1111
};
1212
use starknet_providers::{
1313
jsonrpc::{HttpTransport, JsonRpcClient},
14-
MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage,
14+
Provider, ProviderError,
1515
};
1616
use url::Url;
1717

@@ -371,10 +371,7 @@ async fn jsonrpc_get_transaction_by_hash_non_existent_tx() {
371371
.unwrap_err();
372372

373373
match err {
374-
ProviderError::StarknetError(StarknetErrorWithMessage {
375-
code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound),
376-
..
377-
}) => {
374+
ProviderError::StarknetError(StarknetError::TransactionHashNotFound) => {
378375
// TXN_HASH_NOT_FOUND
379376
}
380377
_ => panic!("Unexpected error"),

0 commit comments

Comments
 (0)