unc_jsonrpc_primitives/
errors.rs

1use serde_json::{to_value, Value};
2use std::fmt;
3use unc_primitives::errors::TxExecutionError;
4
5#[derive(Debug, serde::Serialize)]
6pub struct RpcParseError(pub String);
7
8/// This struct may be returned from JSON RPC server in case of error
9/// It is expected that that this struct has impls From<_> all other RPC errors
10/// like [RpcBlockError](crate::types::blocks::RpcBlockError)
11#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
12#[serde(deny_unknown_fields)]
13pub struct RpcError {
14    #[serde(flatten)]
15    pub error_struct: Option<RpcErrorKind>,
16    /// Deprecated please use the `error_struct` instead
17    pub code: i64,
18    /// Deprecated please use the `error_struct` instead
19    pub message: String,
20    /// Deprecated please use the `error_struct` instead
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub data: Option<Value>,
23}
24
25#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
26#[serde(tag = "name", content = "cause", rename_all = "SCREAMING_SNAKE_CASE")]
27pub enum RpcErrorKind {
28    RequestValidationError(RpcRequestValidationErrorKind),
29    HandlerError(Value),
30    InternalError(Value),
31}
32
33#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
34#[serde(tag = "name", content = "info", rename_all = "SCREAMING_SNAKE_CASE")]
35pub enum RpcRequestValidationErrorKind {
36    MethodNotFound { method_name: String },
37    ParseError { error_message: String },
38}
39
40/// A general Server Error
41#[derive(
42    serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone, unc_rpc_error_macro::RpcError,
43)]
44pub enum ServerError {
45    TxExecutionError(TxExecutionError),
46    Timeout,
47    Closed,
48}
49
50impl RpcError {
51    /// A generic constructor.
52    ///
53    /// Mostly for completeness, doesn't do anything but filling in the corresponding fields.
54    pub fn new(code: i64, message: String, data: Option<Value>) -> Self {
55        RpcError { code, message, data, error_struct: None }
56    }
57
58    /// Create an Invalid Param error.
59    #[cfg(feature = "test_features")]
60    pub fn invalid_params(data: impl serde::Serialize) -> Self {
61        let value = match to_value(data) {
62            Ok(value) => value,
63            Err(err) => {
64                return Self::server_error(Some(format!(
65                    "Failed to serialize invalid parameters error: {:?}",
66                    err.to_string()
67                )))
68            }
69        };
70        RpcError::new(-32_602, "Invalid params".to_owned(), Some(value))
71    }
72
73    /// Create a server error.
74    #[cfg(feature = "test_features")]
75    pub fn server_error<E: serde::Serialize>(e: Option<E>) -> Self {
76        RpcError::new(
77            -32_000,
78            "Server error".to_owned(),
79            e.map(|v| to_value(v).expect("Must be representable in JSON")),
80        )
81    }
82
83    /// Create a parse error.
84    pub fn parse_error(e: String) -> Self {
85        RpcError {
86            code: -32_700,
87            message: "Parse error".to_owned(),
88            data: Some(Value::String(e.clone())),
89            error_struct: Some(RpcErrorKind::RequestValidationError(
90                RpcRequestValidationErrorKind::ParseError { error_message: e },
91            )),
92        }
93    }
94
95    pub fn serialization_error(e: String) -> Self {
96        RpcError::new_internal_error(Some(Value::String(e.clone())), e)
97    }
98
99    /// Helper method to define extract INTERNAL_ERROR in separate RpcErrorKind
100    /// Returns HANDLER_ERROR if the error is not internal one
101    pub fn new_internal_or_handler_error(error_data: Option<Value>, error_struct: Value) -> Self {
102        if error_struct["name"] == "INTERNAL_ERROR" {
103            let error_message = match error_struct["info"].get("error_message") {
104                Some(Value::String(error_message)) => error_message.as_str(),
105                _ => "InternalError happened during serializing InternalError",
106            };
107            Self::new_internal_error(error_data, error_message.to_string())
108        } else {
109            Self::new_handler_error(error_data, error_struct)
110        }
111    }
112
113    pub fn new_internal_error(error_data: Option<Value>, info: String) -> Self {
114        RpcError {
115            code: -32_000,
116            message: "Server error".to_owned(),
117            data: error_data,
118            error_struct: Some(RpcErrorKind::InternalError(serde_json::json!({
119                "name": "INTERNAL_ERROR",
120                "info": serde_json::json!({"error_message": info})
121            }))),
122        }
123    }
124
125    fn new_handler_error(error_data: Option<Value>, error_struct: Value) -> Self {
126        RpcError {
127            code: -32_000,
128            message: "Server error".to_owned(),
129            data: error_data,
130            error_struct: Some(RpcErrorKind::HandlerError(error_struct)),
131        }
132    }
133
134    /// Create a method not found error.
135    pub fn method_not_found(method: String) -> Self {
136        RpcError {
137            code: -32_601,
138            message: "Method not found".to_owned(),
139            data: Some(Value::String(method.clone())),
140            error_struct: Some(RpcErrorKind::RequestValidationError(
141                RpcRequestValidationErrorKind::MethodNotFound { method_name: method },
142            )),
143        }
144    }
145}
146
147impl fmt::Display for RpcError {
148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149        write!(f, "{:?}", self)
150    }
151}
152
153impl From<RpcParseError> for RpcError {
154    fn from(parse_error: RpcParseError) -> Self {
155        Self::parse_error(parse_error.0)
156    }
157}
158
159impl From<std::convert::Infallible> for RpcError {
160    fn from(_: std::convert::Infallible) -> Self {
161        unsafe { core::hint::unreachable_unchecked() }
162    }
163}
164
165impl fmt::Display for ServerError {
166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167        match self {
168            ServerError::TxExecutionError(e) => write!(f, "ServerError: {}", e),
169            ServerError::Timeout => write!(f, "ServerError: Timeout"),
170            ServerError::Closed => write!(f, "ServerError: Closed"),
171        }
172    }
173}
174
175impl From<ServerError> for RpcError {
176    fn from(e: ServerError) -> RpcError {
177        let error_data = match to_value(&e) {
178            Ok(value) => value,
179            Err(_err) => {
180                return RpcError::new_internal_error(
181                    None,
182                    "Failed to serialize ServerError".to_string(),
183                )
184            }
185        };
186        match e {
187            ServerError::TxExecutionError(_) => {
188                RpcError::new_handler_error(Some(error_data.clone()), error_data)
189            }
190            _ => RpcError::new_internal_error(Some(error_data), e.to_string()),
191        }
192    }
193}