Skip to main content

cardano_connector/
error.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error)]
2pub enum APIErrorCode {
3    #[error("Invalid inputs.")]
4    InvalidRequest,
5    #[error("An error occured during the execution of this API call.")]
6    InternalError,
7    #[error("The request was denied. The wallet may be disconnected.")]
8    Refused,
9    /// If this error happens we might need to re-authenticate.
10    #[error("The account has changed.")]
11    AccountChange,
12    #[error("Unknown error code `{0}'")]
13    Unknown(i64),
14}
15
16#[derive(
17    Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error, serde::Deserialize,
18)]
19#[error("{code}. {info}.")]
20pub struct APIError {
21    pub code: APIErrorCode,
22    pub info: String,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error)]
26pub enum DataSignErrorCode {
27    #[error(
28        "Wallet could not sign the data (e.g. does not have the secret key associated with the address)"
29    )]
30    ProofGeneration,
31    #[error("Address was not a P2PK address and thus had no SK associated with it")]
32    AddressNotPK,
33    #[error("User declined to sign the data")]
34    UserDeclined,
35    #[error("Unknown error code `{0}'")]
36    Unknown(u64),
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error)]
40#[error("{code}. {info}.")]
41pub struct DataSignError {
42    pub code: DataSignErrorCode,
43    pub info: String,
44}
45
46#[derive(
47    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error, serde::Deserialize,
48)]
49#[serde(rename_all = "camelCase")]
50#[error("Pagination error")]
51pub struct PaginateError {
52    pub max_size: usize,
53}
54
55impl<'de> serde::Deserialize<'de> for APIErrorCode {
56    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57    where
58        D: serde::Deserializer<'de>,
59    {
60        struct Visitor;
61        impl serde::de::Visitor<'_> for Visitor {
62            type Value = APIErrorCode;
63
64            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
65                write!(formatter, "Expecting an integer APIErrorCode")
66            }
67
68            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
69            where
70                E: serde::de::Error,
71            {
72                match v {
73                    -1 => Ok(APIErrorCode::InvalidRequest),
74                    -2 => Ok(APIErrorCode::InternalError),
75                    -3 => Ok(APIErrorCode::Refused),
76                    -4 => Ok(APIErrorCode::AccountChange),
77                    unknown => Ok(APIErrorCode::Unknown(unknown)),
78                }
79            }
80        }
81
82        deserializer.deserialize_i64(Visitor)
83    }
84}
85
86impl<'de> serde::Deserialize<'de> for DataSignErrorCode {
87    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
88    where
89        D: serde::Deserializer<'de>,
90    {
91        struct Visitor;
92        impl serde::de::Visitor<'_> for Visitor {
93            type Value = DataSignErrorCode;
94
95            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
96                write!(formatter, "Expecting an integer DataSignErrorCode")
97            }
98
99            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
100            where
101                E: serde::de::Error,
102            {
103                match v {
104                    1 => Ok(DataSignErrorCode::ProofGeneration),
105                    2 => Ok(DataSignErrorCode::AddressNotPK),
106                    3 => Ok(DataSignErrorCode::UserDeclined),
107                    unknown => Ok(DataSignErrorCode::Unknown(unknown)),
108                }
109            }
110        }
111
112        deserializer.deserialize_u64(Visitor)
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use serde_json::json;
119
120    use super::*;
121
122    #[test]
123    fn api_error_code_json() {
124        assert_eq!(
125            serde_json::from_value::<APIErrorCode>(json! { -1 }).unwrap(),
126            APIErrorCode::InvalidRequest
127        );
128        assert_eq!(
129            serde_json::from_value::<APIErrorCode>(json! { -2 }).unwrap(),
130            APIErrorCode::InternalError
131        );
132        assert_eq!(
133            serde_json::from_value::<APIErrorCode>(json! { -3 }).unwrap(),
134            APIErrorCode::Refused
135        );
136        assert_eq!(
137            serde_json::from_value::<APIErrorCode>(json! { -4 }).unwrap(),
138            APIErrorCode::AccountChange
139        );
140        assert_eq!(
141            serde_json::from_value::<APIErrorCode>(json! { -42 }).unwrap(),
142            APIErrorCode::Unknown(-42)
143        );
144    }
145
146    #[test]
147    fn api_error_json() {
148        assert_eq!(
149            serde_json::from_value::<APIError>(json! { {
150                "code": -1,
151                "info": "Parameter malformed.",
152            }})
153            .unwrap(),
154            APIError {
155                code: APIErrorCode::InvalidRequest,
156                info: "Parameter malformed.".to_owned()
157            }
158        );
159
160        assert_eq!(
161            serde_json::from_value::<APIError>(json! { {
162                "code": -2,
163                "info": "Internal Error.",
164            }})
165            .unwrap(),
166            APIError {
167                code: APIErrorCode::InternalError,
168                info: "Internal Error.".to_owned()
169            }
170        );
171
172        assert_eq!(
173            serde_json::from_value::<APIError>(json! { {
174                "code": -3,
175                "info": "Access Denied.",
176            }})
177            .unwrap(),
178            APIError {
179                code: APIErrorCode::Refused,
180                info: "Access Denied.".to_owned()
181            }
182        );
183
184        assert_eq!(
185            serde_json::from_value::<APIError>(json! { {
186                "code": -4,
187                "info": "Account has changed.",
188            }})
189            .unwrap(),
190            APIError {
191                code: APIErrorCode::AccountChange,
192                info: "Account has changed.".to_owned()
193            }
194        );
195    }
196
197    #[test]
198    fn sign_data_error_code_json() {
199        assert_eq!(
200            serde_json::from_value::<DataSignErrorCode>(json! { 1 }).unwrap(),
201            DataSignErrorCode::ProofGeneration
202        );
203        assert_eq!(
204            serde_json::from_value::<DataSignErrorCode>(json! { 2 }).unwrap(),
205            DataSignErrorCode::AddressNotPK
206        );
207        assert_eq!(
208            serde_json::from_value::<DataSignErrorCode>(json! { 3 }).unwrap(),
209            DataSignErrorCode::UserDeclined
210        );
211        assert_eq!(
212            serde_json::from_value::<DataSignErrorCode>(json! { 42 }).unwrap(),
213            DataSignErrorCode::Unknown(42)
214        );
215    }
216}