anya_core/api/
error.rs

1use axum::{
2    http::StatusCode,
3    response::{IntoResponse, Response},
4    Json,
5};
6use serde_json::json;
7use thiserror::Error;
8
9#[cfg(feature = "rust-bitcoin")]
10use crate::bitcoin::error::BitcoinError;
11
12#[derive(Error, Debug)]
13pub enum ApiError {
14    #[error("Authentication required: {0}")]
15    AuthenticationRequired(String),
16
17    #[error("Authorization failed: {0}")]
18    AuthorizationFailed(String),
19
20    #[error("Resource not found: {0}")]
21    NotFound(String),
22
23    #[error("Invalid request: {0}")]
24    BadRequest(String),
25
26    #[cfg(feature = "rust-bitcoin")]
27    #[error("Bitcoin operation failed: {0}")]
28    BitcoinError(#[from] BitcoinError),
29
30    #[error("Internal server error: {0}")]
31    InternalError(String),
32}
33
34impl IntoResponse for ApiError {
35    fn into_response(self) -> Response {
36        let (status, error_message) = match self {
37            ApiError::AuthenticationRequired(msg) => (StatusCode::UNAUTHORIZED, msg),
38            ApiError::AuthorizationFailed(msg) => (StatusCode::FORBIDDEN, msg),
39            ApiError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
40            ApiError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
41            #[cfg(feature = "rust-bitcoin")]
42            ApiError::BitcoinError(e) => match e {
43                BitcoinError::WalletNotFound(_) => (StatusCode::NOT_FOUND, e.to_string()),
44                BitcoinError::InvalidAddress(_) => (StatusCode::BAD_REQUEST, e.to_string()),
45                BitcoinError::InsufficientFunds => (StatusCode::BAD_REQUEST, e.to_string()),
46                _ => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
47            },
48            ApiError::InternalError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg),
49        };
50
51        let body = Json(json!({
52            "success": false,
53            "message": error_message
54        }));
55
56        (status, body).into_response()
57    }
58}