Skip to main content

aztec_core/
error.rs

1use thiserror::Error;
2
3/// Crate-level error type for aztec-rs.
4#[derive(Debug, Error)]
5pub enum Error {
6    /// HTTP or transport-layer failure.
7    #[error("transport error: {0}")]
8    Transport(String),
9
10    /// JSON serialization/deserialization failure.
11    #[error("json error: {0}")]
12    Json(String),
13
14    /// ABI or data validation failure.
15    #[error("abi error: {0}")]
16    Abi(String),
17
18    /// Invalid or unexpected data.
19    #[error("invalid data: {0}")]
20    InvalidData(String),
21
22    /// JSON-RPC error returned by the server.
23    #[error("rpc error {code}: {message}")]
24    Rpc {
25        /// JSON-RPC error code.
26        code: i64,
27        /// Error message from the server.
28        message: String,
29    },
30
31    /// Transaction execution reverted.
32    #[error("reverted: {0}")]
33    Reverted(String),
34
35    /// Operation timed out.
36    #[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}