zksvm_api_types/
errors.rs

1use std::error::Error;
2
3use axum::{
4    http::StatusCode,
5    response::{IntoResponse, Response},
6    Json,
7};
8use serde::{Deserialize, Serialize};
9
10/// Define the error types for the DB module
11#[derive(Debug, thiserror::Error)]
12pub enum DBError {
13    /// Failed to read an environment variable: {0}
14    #[error("Failed to read environment variable: {0}")]
15    EnvVar(String),
16    /// Failed to read from DB: {0}
17    #[error("Failed to read from DB: {0}")]
18    Read(String),
19    /// Failed to write to DB: {0}
20    #[error("Failed to write to DB: {0}")]
21    Write(String),
22}
23
24/// Errors that can occur in the API
25#[derive(Debug, thiserror::Error)]
26pub enum ApiError {
27    /// Auth error: {0}
28    #[error("Auth error: {0}")]
29    Auth(String),
30    /// Environment variable not found: {0}
31    #[error("Environment variable not found: {0}")]
32    EnvVar(String),
33    /// Invalid UUID received: {0}
34    #[error("Invalid UUID received: {0}")]
35    Uuid(#[from] uuid::Error),
36    /// Exceeded transaction limit for session: {0}
37    #[error("Exceeded transaction limit for session: {0}")]
38    MaxTxLimit(u64),
39    /// Session already initiated
40    #[error("Session already initiated")]
41    SessionAlreadyInitiated,
42    /// DB error
43    #[error(transparent)]
44    DB(#[from] DBError),
45    /// Catch all error
46    #[error(transparent)]
47    CatchAll(#[from] Box<dyn Error>),
48}
49
50pub type ApiResult<T = ()> = Result<T, ApiError>;
51
52#[derive(Debug, Serialize, Deserialize)]
53#[serde(tag = "status", rename_all = "snake_case")]
54pub enum ApiResponse<T: Serialize = ()> {
55    Success {
56        #[serde(flatten)]
57        data: T,
58    },
59    Error {
60        code: u16,
61        message: String,
62    },
63}
64
65impl<T: Serialize> From<ApiError> for ApiResponse<T> {
66    fn from(err: ApiError) -> Self {
67        use ApiError::*;
68        let code = match err {
69            EnvVar(_) | DB(_) | CatchAll(_) => StatusCode::INTERNAL_SERVER_ERROR,
70            Uuid(_) | MaxTxLimit(_) | SessionAlreadyInitiated => StatusCode::BAD_REQUEST,
71            Auth(_) => StatusCode::UNAUTHORIZED,
72        }
73        .into();
74
75        ApiResponse::Error {
76            code,
77            message: format!("{err:?}"),
78        }
79    }
80}
81
82impl<T: Serialize> ApiResponse<T> {
83    pub fn success(data: T) -> ApiResult<Self> {
84        Ok(Self::Success { data })
85    }
86}
87
88impl<T: Serialize> IntoResponse for ApiResponse<T> {
89    fn into_response(self) -> Response {
90        Json(self).into_response()
91    }
92}
93
94impl IntoResponse for ApiError {
95    fn into_response(self) -> Response {
96        ApiResponse::<()>::from(self).into_response()
97    }
98}