iota_sdk/
json_rpc_error.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use iota_json_rpc_api::error_object_from_rpc;
6pub use iota_json_rpc_api::{TRANSACTION_EXECUTION_CLIENT_ERROR_CODE, TRANSIENT_ERROR_CODE};
7use jsonrpsee::types::error::UNKNOWN_ERROR_CODE;
8use thiserror::Error;
9
10#[derive(Error, Debug, Clone)]
11pub struct Error {
12    pub code: i32,
13    pub message: String,
14    // TODO: as this SDK is specialized for the IOTA JSON RPC implementation, we should define
15    // structured representation for the data field if applicable
16    pub data: Option<serde_json::Value>,
17}
18
19impl std::fmt::Display for Error {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        write!(f, "code: '{}', message: '{}'", self.code, self.message)
22    }
23}
24
25impl Error {
26    pub fn is_call_error(&self) -> bool {
27        self.code != UNKNOWN_ERROR_CODE
28    }
29
30    pub fn is_client_error(&self) -> bool {
31        use jsonrpsee::types::error::{
32            BATCHES_NOT_SUPPORTED_CODE, INVALID_PARAMS_CODE, INVALID_REQUEST_CODE,
33            METHOD_NOT_FOUND_CODE, OVERSIZED_REQUEST_CODE, PARSE_ERROR_CODE,
34        };
35        matches!(
36            self.code,
37            PARSE_ERROR_CODE
38                | OVERSIZED_REQUEST_CODE
39                | INVALID_PARAMS_CODE
40                | INVALID_REQUEST_CODE
41                | METHOD_NOT_FOUND_CODE
42                | BATCHES_NOT_SUPPORTED_CODE
43                | TRANSACTION_EXECUTION_CLIENT_ERROR_CODE
44        )
45    }
46
47    pub fn is_execution_error(&self) -> bool {
48        self.code == TRANSACTION_EXECUTION_CLIENT_ERROR_CODE
49    }
50
51    pub fn is_transient_error(&self) -> bool {
52        self.code == TRANSIENT_ERROR_CODE
53    }
54}
55
56impl From<jsonrpsee::core::ClientError> for Error {
57    fn from(err: jsonrpsee::core::ClientError) -> Self {
58        // The following code converts any variant that is not Error::Call into
59        // an ErrorObject with UNKNOWN_ERROR_CODE
60        let error_object_owned = error_object_from_rpc(err);
61        Error {
62            code: error_object_owned.code(),
63            message: error_object_owned.message().to_string(),
64            data: error_object_owned
65                .data()
66                .map(|v| serde_json::from_str(v.get()).expect("raw json is always valid")),
67        }
68    }
69}