crypto_pay_api/error/
mod.rs

1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum CryptoBotError {
5    #[error("Invalid header name: {0}")]
6    InvalidHeaderName(#[from] reqwest::header::InvalidHeaderName),
7
8    #[error("Invalid header value: {0}")]
9    InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue),
10
11    #[error("HTTP client error: {0}")]
12    HttpError(#[from] reqwest::Error),
13
14    #[error("API error: {code} - {message}")]
15    ApiError {
16        code: i32,
17        message: String,
18        details: Option<serde_json::Value>,
19    },
20
21    #[error("Validation error: {kind} - {message}")]
22    ValidationError {
23        kind: ValidationErrorKind,
24        message: String,
25        field: Option<String>,
26    },
27
28    #[error("Webhook error: {kind} - {message}")]
29    WebhookError { kind: WebhookErrorKind, message: String },
30
31    #[error("No result returned from API")]
32    NoResult,
33}
34
35#[derive(Debug, PartialEq)]
36pub enum ValidationErrorKind {
37    Format,
38    Range,
39    Currency,
40    Missing,
41    Invalid,
42}
43
44#[derive(Debug)]
45pub enum WebhookErrorKind {
46    InvalidSignature,
47    InvalidPayload,
48    DeserializationError,
49    Expired,
50}
51
52impl std::fmt::Display for ValidationErrorKind {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        write!(f, "{self:?}")
55    }
56}
57
58impl std::fmt::Display for WebhookErrorKind {
59    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60        write!(f, "{self:?}")
61    }
62}
63
64pub type CryptoBotResult<T> = std::result::Result<T, CryptoBotError>;
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_validation_error_kind_display() {
72        let test_cases = vec![
73            (ValidationErrorKind::Range, "Range"),
74            (ValidationErrorKind::Format, "Format"),
75            (ValidationErrorKind::Missing, "Missing"),
76            (ValidationErrorKind::Invalid, "Invalid"),
77            (ValidationErrorKind::Currency, "Currency"),
78        ];
79
80        for (kind, expected) in test_cases {
81            assert_eq!(kind.to_string(), expected);
82        }
83    }
84
85    #[test]
86    fn test_webhook_error_kind_display() {
87        let test_cases = vec![
88            (WebhookErrorKind::InvalidSignature, "InvalidSignature"),
89            (WebhookErrorKind::InvalidPayload, "InvalidPayload"),
90            (WebhookErrorKind::DeserializationError, "DeserializationError"),
91            (WebhookErrorKind::Expired, "Expired"),
92        ];
93
94        for (kind, expected) in test_cases {
95            assert_eq!(kind.to_string(), expected);
96        }
97    }
98
99    #[test]
100    fn test_validation_error_formatting() {
101        let error = CryptoBotError::ValidationError {
102            kind: ValidationErrorKind::Range,
103            message: "Value out of range".to_string(),
104            field: Some("amount".to_string()),
105        };
106
107        assert_eq!(error.to_string(), "Validation error: Range - Value out of range");
108    }
109
110    #[test]
111    fn test_webhook_error_formatting() {
112        let error = CryptoBotError::WebhookError {
113            kind: WebhookErrorKind::InvalidSignature,
114            message: "Invalid signature".to_string(),
115        };
116
117        assert_eq!(error.to_string(), "Webhook error: InvalidSignature - Invalid signature");
118    }
119}