1use core::time::Duration;
4
5use flex_error::{define_error, DefaultTracer, DisplayError, DisplayOnly, ErrorMessageTracer};
6
7use crate::{prelude::*, response_error::ResponseError, rpc_url::Url};
8
9#[cfg(feature = "reqwest")]
10type ReqwestError = flex_error::DisplayOnly<reqwest::Error>;
11
12#[cfg(not(feature = "reqwest"))]
13type ReqwestError = flex_error::NoSource;
14
15#[cfg(feature = "reqwest")]
16type HttpStatusCode = reqwest::StatusCode;
17
18#[cfg(not(feature = "reqwest"))]
19type HttpStatusCode = core::num::NonZeroU16;
20
21#[cfg(feature = "tokio")]
22type JoinError = flex_error::DisplayOnly<tokio::task::JoinError>;
23
24#[cfg(not(feature = "tokio"))]
25type JoinError = flex_error::NoSource;
26
27#[cfg(feature = "async-tungstenite")]
28type TungsteniteError = flex_error::DisplayOnly<async_tungstenite::tungstenite::Error>;
29
30#[cfg(not(feature = "async-tungstenite"))]
31type TungsteniteError = flex_error::NoSource;
32
33define_error! {
34 #[derive(Debug, Clone, PartialEq, Eq)]
35 Error {
36 Response
37 [ DisplayError<ResponseError> ]
38 | _ | { "response error" },
39
40 Io
41 [ DisplayOnly<std::io::Error> ]
42 | _ | { "I/O error" },
43
44 Http
45 [ ReqwestError ]
46 | _ | { "HTTP error" },
47
48 InvalidProxy
49 [ ReqwestError ]
50 | _ | { "Invalid proxy configuration" },
51
52 InvalidParams
53 {
54 message: String
55 }
56 | e | {
57 format_args!("invalid params error: {}", e.message)
58 },
59
60 WebSocket
61 {
62 message: String
63 }
64 [ TungsteniteError ]
65 | e | {
66 format_args!("web socket error: {}", e.message)
67 },
68
69 WebSocketTimeout
70 {
71 timeout: Duration
72 }
73 | e | {
74 format_args!("reading from WebSocket connection timed out after {} seconds",
75 e.timeout.as_secs())
76 },
77
78 MethodNotFound
79 {
80 method: String
81 }
82 | e | {
83 format_args!("method not found: {}", e.method)
84 },
85
86 HttpRequestFailed
87 {
88 status: HttpStatusCode,
89 }
90 | e | {
91 format_args!("HTTP request failed with non-200 status code: {}", e.status)
92 },
93
94 Parse
95 {
96 reason: String
97 }
98 | e | {
99 format_args!("parse error: {}", e.reason)
100 },
101
102 Server
103 {
104 reason: String
105 }
106 | e | {
107 format_args!("server error: {}", e.reason)
108 },
109
110 ClientInternal
111 {
112 reason: String
113 }
114 | e | {
115 format_args!("client internal error: {}", e.reason)
116 },
117
118 Timeout
119 {
120 duration: Duration
121 }
122 | e | {
123 format_args!(
124 "timed out waiting for healthy response after {}ms",
125 e.duration.as_millis()
126 )
127 },
128
129 ChannelSend
130 | _ | { "failed to send message to internal channel" },
131
132 InvalidUrl
133 { url: Url }
134 | e | {
135 format_args!(
136 "cannot use URL {} with HTTP clients",
137 e.url
138 )
139 },
140
141 Tendermint
142 [ tendermint::Error ]
143 | _ | { "tendermint error" },
144
145 ParseInt
146 [ DisplayOnly<core::num::ParseIntError> ]
147 | _ | { "error parsing integer" },
148
149 OutOfRange
150 [ DisplayOnly<core::num::TryFromIntError> ]
151 | _ | { "number out of range" },
152
153 InvalidNetworkAddress
154 | _ | { "only TCP-based node addresses are supported" },
155
156 MismatchResponse
157 | _ | { "no matching response for incoming request" },
158
159 UnrecognizedEventType
160 {
161 event_type: String
162 }
163 | e | {
164 format_args!("unrecognized event type: {}", e.event_type)
165 },
166
167 Serde
168 [ DisplayOnly<serde_json::Error> ]
169 | _ | { "serde parse error" },
170
171 ParseUrl
172 [ DisplayOnly<url::ParseError> ]
173 | _ | { "parse error" },
174
175 Tungstenite
176 [ TungsteniteError ]
177 | _ | { "tungstenite error" },
178
179 Join
180 [ JoinError ]
181 | _ | { "join error" },
182
183 MalformedJson
184 | _ | { "server returned malformatted JSON (no 'result' or 'error')" },
185
186 UnsupportedScheme
187 {
188 scheme: String
189 }
190 | e | {
191 format_args!("unsupported scheme: {}", e.scheme)
192 },
193
194 UnsupportedRpcVersion
195 {
196 version: String,
197 supported: String
198 }
199 | e | {
200 format_args!("server RPC version unsupported: '{}' (only '{}' supported)",
201 e.version, e.supported)
202 },
203
204 InvalidTendermintVersion
205 {
206 version: String,
207 }
208 | e | {
209 format_args!("invalid Tendermint version reported by the node: {}", e.version)
210 },
211
212 UnsupportedTendermintVersion
213 {
214 version: String,
215 }
216 | e | {
217 format_args!("unsupported Tendermint version reported by the node: {}", e.version)
218 },
219
220 InvalidCompatMode
221 {
222 mode: String,
223 supported: &'static str,
224 }
225 | e | {
226 format_args!("invalid compatibility mode: '{}' (supported: {})",
227 e.mode, e.supported)
228 },
229 }
230}
231
232impl Clone for Error {
233 fn clone(&self) -> Self {
234 Error(
235 self.detail().clone(),
236 DefaultTracer::new_message(self.trace()),
237 )
238 }
239}
240
241#[cfg(feature = "tokio")]
242impl Error {
243 pub fn send<T>(_: tokio::sync::mpsc::error::SendError<T>) -> Error {
244 Error::channel_send()
245 }
246}