hopr_chain_rpc/
errors.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/// Errors produced by this crate and other error-related types.
use ethers::prelude::nonce_manager::NonceManagerError;
use ethers::prelude::signer::SignerMiddlewareError;
use ethers::providers::{JsonRpcError, ProviderError};
use thiserror::Error;

/// Enumerates different errors produced by this crate.
#[derive(Error, Debug)]
pub enum RpcError {
    #[error("error on backend interface: {0}")]
    InterfaceError(String),

    #[error("error in smart contract '{0}' while executing '{1}': {2}")]
    ContractError(String, String, String),

    #[error("middleware error: {0}")]
    MiddlewareError(String),

    #[error("block with such id does not (yet) exist")]
    NoSuchBlock,

    #[error("filter does not contain any criteria")]
    FilterIsEmpty,

    #[error("transaction {0} has not been included on-chain")]
    TransactionDropped(String),

    #[error("transaction submission to the RPC provider timed out")]
    Timeout,

    #[error("non-specific RPC error occurred: {0}")]
    GeneralError(String),

    #[error(transparent)]
    KeypairError(#[from] ethers::signers::WalletError),

    #[error(transparent)]
    ProviderError(#[from] ProviderError),

    #[error("multicall Error: {0}")]
    MulticallError(String),

    /// Error occurred during data conversion
    #[error("conversion error: {0}")]
    ConversionError(String),
}

pub type Result<T> = std::result::Result<T, RpcError>;

impl<M> From<NonceManagerError<M>> for RpcError
where
    M: ethers::middleware::Middleware,
{
    fn from(value: NonceManagerError<M>) -> Self {
        Self::MiddlewareError(value.to_string())
    }
}

impl<M, S> From<SignerMiddlewareError<M, S>> for RpcError
where
    M: ethers::middleware::Middleware,
    S: ethers::signers::Signer,
{
    fn from(value: SignerMiddlewareError<M, S>) -> Self {
        Self::MiddlewareError(value.to_string())
    }
}

/// Error abstraction for `HttpRequestor`.
#[derive(Error, Clone, Debug, PartialEq)]
pub enum HttpRequestError {
    #[error("connection timed out")]
    Timeout,

    #[error("http error - status {0}")]
    HttpError(http_types::StatusCode),

    #[error("io error when performing http request: {0}")]
    TransportError(String),

    #[error("unrecognized error: {0}")]
    UnknownError(String),
}

/// Errors for `JsonRpcProviderClient`
#[derive(Error, Debug)]
pub enum JsonRpcProviderClientError {
    #[error("Deserialization Error: {err}. Response: {text}")]
    /// Serde JSON Error
    SerdeJson {
        /// Underlying error
        err: serde_json::Error,
        /// The contents of the HTTP response that could not be deserialized
        text: String,
    },

    #[error(transparent)]
    JsonRpcError(#[from] JsonRpcError),

    #[error(transparent)]
    BackendError(#[from] HttpRequestError),
}

impl From<JsonRpcProviderClientError> for ProviderError {
    fn from(src: JsonRpcProviderClientError) -> Self {
        match src {
            // Because we cannot use `ProviderError::HTTPError`, due to `request::Error` having private constructor
            // we must resolve connectivity error within our `RetryPolicy<JsonRpcProviderClientError>`
            JsonRpcProviderClientError::BackendError(err) => ProviderError::CustomError(err.to_string()),
            _ => ProviderError::JsonRpcClientError(Box::new(src)),
        }
    }
}

impl ethers::providers::RpcError for JsonRpcProviderClientError {
    fn as_error_response(&self) -> Option<&JsonRpcError> {
        if let JsonRpcProviderClientError::JsonRpcError(err) = self {
            Some(err)
        } else {
            None
        }
    }

    fn as_serde_error(&self) -> Option<&serde_json::Error> {
        match self {
            JsonRpcProviderClientError::SerdeJson { err, .. } => Some(err),
            _ => None,
        }
    }
}