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}