1use thiserror::Error;
2
3#[derive(Debug, Error)]
5pub enum Error {
6 #[error("transport error: {0}")]
8 Transport(String),
9
10 #[error("json error: {0}")]
12 Json(String),
13
14 #[error("abi error: {0}")]
16 Abi(String),
17
18 #[error("invalid data: {0}")]
20 InvalidData(String),
21
22 #[error("rpc error {code}: {message}")]
24 Rpc {
25 code: i64,
27 message: String,
29 },
30
31 #[error("reverted: {0}")]
33 Reverted(String),
34
35 #[error("timeout: {0}")]
37 Timeout(String),
38}
39
40impl From<reqwest::Error> for Error {
41 fn from(e: reqwest::Error) -> Self {
42 Self::Transport(e.to_string())
43 }
44}
45
46impl From<serde_json::Error> for Error {
47 fn from(e: serde_json::Error) -> Self {
48 Self::Json(e.to_string())
49 }
50}
51
52impl From<url::ParseError> for Error {
53 fn from(e: url::ParseError) -> Self {
54 Self::Transport(e.to_string())
55 }
56}
57
58#[cfg(test)]
59#[allow(clippy::unwrap_used)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn transport_error_display() {
65 let err = Error::Transport("connection refused".into());
66 assert_eq!(err.to_string(), "transport error: connection refused");
67 }
68
69 #[test]
70 fn json_error_display() {
71 let err = Error::Json("unexpected token".into());
72 assert_eq!(err.to_string(), "json error: unexpected token");
73 }
74
75 #[test]
76 fn abi_error_display() {
77 let err = Error::Abi("unknown type".into());
78 assert_eq!(err.to_string(), "abi error: unknown type");
79 }
80
81 #[test]
82 fn invalid_data_error_display() {
83 let err = Error::InvalidData("field out of range".into());
84 assert_eq!(err.to_string(), "invalid data: field out of range");
85 }
86
87 #[test]
88 fn rpc_error_display() {
89 let err = Error::Rpc {
90 code: -32600,
91 message: "invalid request".into(),
92 };
93 assert_eq!(err.to_string(), "rpc error -32600: invalid request");
94 }
95
96 #[test]
97 fn reverted_error_display() {
98 let err = Error::Reverted("assertion failed".into());
99 assert_eq!(err.to_string(), "reverted: assertion failed");
100 }
101
102 #[test]
103 fn timeout_error_display() {
104 let err = Error::Timeout("waited 30s".into());
105 assert_eq!(err.to_string(), "timeout: waited 30s");
106 }
107
108 #[test]
109 fn from_serde_json_error() {
110 let raw = serde_json::from_str::<serde_json::Value>("not json");
111 let serde_err = raw.unwrap_err();
112 let err: Error = serde_err.into();
113 assert!(matches!(err, Error::Json(_)));
114 }
115
116 #[test]
117 fn from_url_parse_error() {
118 let url_err = url::Url::parse("not a url :://").unwrap_err();
119 let err: Error = url_err.into();
120 assert!(matches!(err, Error::Transport(_)));
121 }
122
123 #[test]
124 fn error_is_send_sync() {
125 fn assert_send_sync<T: Send + Sync>() {}
126 assert_send_sync::<Error>();
127 }
128}