ethers_providers/
errors.rs

1use std::{error::Error, fmt::Debug};
2use thiserror::Error;
3
4use crate::JsonRpcError;
5
6/// An `RpcError` is an abstraction over error types returned by a
7/// [`crate::JsonRpcClient`].
8///
9/// All clients can return [`JsonRpcError`] responses, as
10/// well as serde deserialization errors. However, because client errors are
11/// typically type-erased via the [`ProviderError`], the error info can be
12/// difficult to access. This trait provides convenient access to the
13/// underlying error types.
14///
15/// This trait deals only with behavior that is common to all clients.
16/// Client-specific errorvariants cannot be accessed via this trait.
17pub trait RpcError: Error + Debug + Send + Sync {
18    /// Access an underlying JSON-RPC error (if any)
19    ///
20    /// Attempts to access an underlying [`JsonRpcError`]. If the underlying
21    /// error is not a JSON-RPC error response, this function will return
22    /// `None`.
23    fn as_error_response(&self) -> Option<&JsonRpcError>;
24
25    /// Returns `true` if the underlying error is a JSON-RPC error response
26    fn is_error_response(&self) -> bool {
27        self.as_error_response().is_some()
28    }
29
30    /// Access an underlying `serde_json` error (if any)
31    ///
32    /// Attempts to access an underlying [`serde_json::Error`]. If the
33    /// underlying error is not a serde_json error, this function will return
34    /// `None`.
35    ///
36    /// ### Implementor's Note
37    ///
38    /// When writing a stacked [`crate::JsonRpcClient`] abstraction (e.g. a quorum
39    /// provider or retrying provider), be sure to account for `serde_json`
40    /// errors at your layer, as well as at lower layers.
41    fn as_serde_error(&self) -> Option<&serde_json::Error>;
42
43    /// Returns `true` if the underlying error is a serde_json (de)serialization
44    /// error. This method can be used to identify
45    fn is_serde_error(&self) -> bool {
46        self.as_serde_error().is_some()
47    }
48}
49
50/// [`MiddlewareError`] is a companion trait to [`crate::Middleware`]. It
51/// describes error behavior that is common to all Middleware errors.
52///
53/// Like [`crate::Middleware`], it allows moving down through layered errors.
54///
55/// Like [`RpcError`] it exposes convenient accessors to useful underlying
56/// error information.
57///
58///
59/// ## Not to Devs:
60/// While this trait includes the same methods as [`RpcError`], it is not a
61/// supertrait. This is so that 3rd party developers do not need to learn and
62/// implement both traits. We provide default methods that delegate to inner
63/// middleware errors on the assumption that it will eventually reach a
64/// [`ProviderError`], which has correct behavior. This allows Middleware devs
65/// to ignore the methods' presence if they want. Middleware are already plenty
66/// complicated and we don't need to make it worse :)
67pub trait MiddlewareError: Error + Sized + Send + Sync {
68    /// The `Inner` type is the next lower middleware layer's error type.
69    type Inner: MiddlewareError;
70
71    /// Convert the next lower middleware layer's error to this layer's error
72    fn from_err(e: Self::Inner) -> Self;
73
74    /// Attempt to convert this error to the next lower middleware's error.
75    /// Conversion fails if the error is not from an inner layer (i.e. the
76    /// error originates at this middleware layer)
77    fn as_inner(&self) -> Option<&Self::Inner>;
78
79    /// Returns `true` if the underlying error stems from a lower middleware
80    /// layer
81    fn is_inner(&self) -> bool {
82        self.as_inner().is_some()
83    }
84
85    /// Access an underlying `serde_json` error (if any)
86    ///
87    /// Attempts to access an underlying [`serde_json::Error`]. If the
88    /// underlying error is not a serde_json error, this function will return
89    /// `None`.
90    ///
91    /// ### Implementor's Note:
92    ///
93    /// When writing a custom middleware, if your middleware uses `serde_json`
94    /// we recommend a custom implementation of this method. It should first
95    /// check your Middleware's error for local `serde_json` errors, and then
96    /// delegate to inner if none is found. Failing to implement this method may
97    /// result in missed `serde_json` errors.
98    fn as_serde_error(&self) -> Option<&serde_json::Error> {
99        self.as_inner()?.as_serde_error()
100    }
101
102    /// Returns `true` if the underlying error is a serde_json (de)serialization
103    /// error. This method can be used to identify
104    fn is_serde_error(&self) -> bool {
105        self.as_serde_error().is_some()
106    }
107
108    /// Attempts to access an underlying [`ProviderError`], usually by
109    /// traversing the entire middleware stack. Access fails if the underlying
110    /// error is not a [`ProviderError`]
111    fn as_provider_error(&self) -> Option<&ProviderError> {
112        self.as_inner()?.as_provider_error()
113    }
114
115    /// Convert a [`ProviderError`] to this type, by successively wrapping it
116    /// in the error types of all lower middleware
117    fn from_provider_err(p: ProviderError) -> Self {
118        Self::from_err(Self::Inner::from_provider_err(p))
119    }
120
121    /// Access an underlying JSON-RPC error (if any)
122    ///
123    /// Attempts to access an underlying [`JsonRpcError`]. If the underlying
124    /// error is not a JSON-RPC error response, this function will return
125    /// `None`.
126    fn as_error_response(&self) -> Option<&JsonRpcError> {
127        self.as_inner()?.as_error_response()
128    }
129
130    /// Returns `true` if the underlying error is a JSON-RPC error response
131    fn is_error_response(&self) -> bool {
132        self.as_error_response().is_some()
133    }
134}
135
136#[derive(Debug, Error)]
137/// An error thrown when making a call to the provider
138pub enum ProviderError {
139    /// An internal error in the JSON RPC Client
140    #[error("{0}")]
141    JsonRpcClientError(Box<dyn crate::RpcError + Send + Sync>),
142
143    /// An error during ENS name resolution
144    #[error("ens name not found: {0}")]
145    EnsError(String),
146
147    /// Invalid reverse ENS name
148    #[error("reverse ens name not pointing to itself: {0}")]
149    EnsNotOwned(String),
150
151    /// Error in underlying lib `serde_json`
152    #[error(transparent)]
153    SerdeJson(#[from] serde_json::Error),
154
155    /// Error in underlying lib `hex`
156    #[error(transparent)]
157    HexError(#[from] hex::FromHexError),
158
159    /// Error in underlying lib `reqwest`
160    #[error(transparent)]
161    HTTPError(#[from] reqwest::Error),
162
163    /// Custom error from unknown source
164    #[error("custom error: {0}")]
165    CustomError(String),
166
167    /// RPC method is not supported by this provider
168    #[error("unsupported RPC")]
169    UnsupportedRPC,
170
171    /// Node is not supported by this provider
172    #[error("unsupported node client")]
173    UnsupportedNodeClient,
174
175    /// Signer is not available to this provider.
176    #[error("Attempted to sign a transaction with no available signer. Hint: did you mean to use a SignerMiddleware?")]
177    SignerUnavailable,
178}
179
180impl RpcError for ProviderError {
181    fn as_error_response(&self) -> Option<&super::JsonRpcError> {
182        if let ProviderError::JsonRpcClientError(err) = self {
183            err.as_error_response()
184        } else {
185            None
186        }
187    }
188
189    fn as_serde_error(&self) -> Option<&serde_json::Error> {
190        match self {
191            ProviderError::JsonRpcClientError(e) => e.as_serde_error(),
192            ProviderError::SerdeJson(e) => Some(e),
193            _ => None,
194        }
195    }
196}
197
198// Do not change these implementations, they are critical to proper middleware
199// error stack behavior.
200impl MiddlewareError for ProviderError {
201    type Inner = Self;
202
203    fn as_error_response(&self) -> Option<&super::JsonRpcError> {
204        RpcError::as_error_response(self)
205    }
206
207    fn as_serde_error(&self) -> Option<&serde_json::Error> {
208        RpcError::as_serde_error(self)
209    }
210
211    fn from_err(e: Self::Inner) -> Self {
212        e
213    }
214
215    fn as_inner(&self) -> Option<&Self::Inner> {
216        // prevents infinite loops
217        None
218    }
219}