hopr_chain_rpc/
errors.rs

1/// Errors produced by this crate and other error-related types.
2use ethers::prelude::nonce_manager::NonceManagerError;
3use ethers::prelude::signer::SignerMiddlewareError;
4use ethers::providers::{JsonRpcError, ProviderError};
5use thiserror::Error;
6
7/// Enumerates different errors produced by this crate.
8#[derive(Error, Debug)]
9pub enum RpcError {
10    #[error("error on backend interface: {0}")]
11    InterfaceError(String),
12
13    #[error("error in smart contract '{0}' while executing '{1}': {2}")]
14    ContractError(String, String, String),
15
16    #[error("middleware error: {0}")]
17    MiddlewareError(String),
18
19    #[error("block with such id does not (yet) exist")]
20    NoSuchBlock,
21
22    #[error("filter does not contain any criteria")]
23    FilterIsEmpty,
24
25    #[error("transaction {0} has not been included on-chain")]
26    TransactionDropped(String),
27
28    #[error("transaction submission to the RPC provider timed out")]
29    Timeout,
30
31    #[error("non-specific RPC error occurred: {0}")]
32    GeneralError(String),
33
34    #[error(transparent)]
35    KeypairError(#[from] ethers::signers::WalletError),
36
37    #[error(transparent)]
38    ProviderError(#[from] ProviderError),
39
40    #[error("multicall Error: {0}")]
41    MulticallError(String),
42
43    /// Error occurred during data conversion
44    #[error("conversion error: {0}")]
45    ConversionError(String),
46}
47
48pub type Result<T> = std::result::Result<T, RpcError>;
49
50impl<M> From<NonceManagerError<M>> for RpcError
51where
52    M: ethers::middleware::Middleware,
53{
54    fn from(value: NonceManagerError<M>) -> Self {
55        Self::MiddlewareError(value.to_string())
56    }
57}
58
59impl<M, S> From<SignerMiddlewareError<M, S>> for RpcError
60where
61    M: ethers::middleware::Middleware,
62    S: ethers::signers::Signer,
63{
64    fn from(value: SignerMiddlewareError<M, S>) -> Self {
65        Self::MiddlewareError(value.to_string())
66    }
67}
68
69/// Error abstraction for `HttpRequestor`.
70#[derive(Error, Clone, Debug, PartialEq)]
71pub enum HttpRequestError {
72    #[error("connection timed out")]
73    Timeout,
74
75    #[error("http error - status {0}")]
76    HttpError(http_types::StatusCode),
77
78    #[error("io error when performing http request: {0}")]
79    TransportError(String),
80
81    #[error("unrecognized error: {0}")]
82    UnknownError(String),
83}
84
85/// Errors for `JsonRpcProviderClient`
86#[derive(Error, Debug)]
87pub enum JsonRpcProviderClientError {
88    #[error("Deserialization Error: {err}. Response: {text}")]
89    /// Serde JSON Error
90    SerdeJson {
91        /// Underlying error
92        err: serde_json::Error,
93        /// The contents of the HTTP response that could not be deserialized
94        text: String,
95    },
96
97    #[error(transparent)]
98    JsonRpcError(#[from] JsonRpcError),
99
100    #[error(transparent)]
101    BackendError(#[from] HttpRequestError),
102}
103
104impl From<JsonRpcProviderClientError> for ProviderError {
105    fn from(src: JsonRpcProviderClientError) -> Self {
106        match src {
107            // Because we cannot use `ProviderError::HTTPError`, due to `request::Error` having private constructor
108            // we must resolve connectivity error within our `RetryPolicy<JsonRpcProviderClientError>`
109            JsonRpcProviderClientError::BackendError(err) => ProviderError::CustomError(err.to_string()),
110            _ => ProviderError::JsonRpcClientError(Box::new(src)),
111        }
112    }
113}
114
115impl ethers::providers::RpcError for JsonRpcProviderClientError {
116    fn as_error_response(&self) -> Option<&JsonRpcError> {
117        if let JsonRpcProviderClientError::JsonRpcError(err) = self {
118            Some(err)
119        } else {
120            None
121        }
122    }
123
124    fn as_serde_error(&self) -> Option<&serde_json::Error> {
125        match self {
126            JsonRpcProviderClientError::SerdeJson { err, .. } => Some(err),
127            _ => None,
128        }
129    }
130}