near_jsonrpc_client/
errors.rs

1//! Error types.
2use std::io;
3
4use thiserror::Error;
5
6use near_jsonrpc_primitives::errors::{RpcError, RpcErrorKind, RpcRequestValidationErrorKind};
7use near_jsonrpc_primitives::message::{self, Message};
8
9/// Potential errors returned while sending a request to the RPC server.
10#[derive(Debug, Error)]
11pub enum JsonRpcTransportSendError {
12    /// Client is unable to serialize the request payload before sending it to the server.
13    #[error("error while serializing payload: [{0}]")]
14    PayloadSerializeError(io::Error),
15    /// Client is unable to send the request to the server.
16    #[error("error while sending payload: [{0}]")]
17    PayloadSendError(reqwest::Error),
18}
19
20/// Potential errors returned when the client has an issue parsing the response of a method call.
21#[derive(Debug, Error)]
22pub enum JsonRpcTransportHandlerResponseError {
23    /// Client fails to deserialize the result of a method call.
24    #[error("error while parsing method call result: [{0}]")]
25    ResultParseError(serde_json::Error),
26    /// Client fails to deserialize the error message returned from a method call.
27    #[error("error while parsing method call error message: [{0}]")]
28    ErrorMessageParseError(serde_json::Error),
29}
30
31/// Potential errors returned while receiving responses from an RPC server.
32#[derive(Debug, Error)]
33pub enum JsonRpcTransportRecvError {
34    /// Client receives a JSON RPC message body that isn't structured as a response.
35    #[error("unexpected server response: [{0:?}]")]
36    UnexpectedServerResponse(Message),
37    /// Client is unable to read the response from the RPC server.
38    #[error("error while reading response: [{0}]")]
39    PayloadRecvError(reqwest::Error),
40    /// The base response structure is malformed e.g. meta properties like RPC version are missing.
41    #[error("error while parsing server response: [{0:?}]")]
42    PayloadParseError(message::Broken),
43    /// Potential errors returned when the client has an issue parsing the response of a method call.
44    #[error(transparent)]
45    ResponseParseError(JsonRpcTransportHandlerResponseError),
46}
47
48/// Potential errors returned while sending requests to or receiving responses from the RPC server.
49#[derive(Debug, Error)]
50pub enum RpcTransportError {
51    /// Potential errors returned while sending a request to the RPC server.
52    #[error(transparent)]
53    SendError(JsonRpcTransportSendError),
54    /// Potential errors returned while receiving a response from an RPC server.
55    #[error(transparent)]
56    RecvError(JsonRpcTransportRecvError),
57}
58
59/// Unexpected status codes returned by the RPC server.
60#[derive(Debug, Error)]
61pub enum JsonRpcServerResponseStatusError {
62    /// The RPC client is unauthorized.
63    #[error("this client is unauthorized")]
64    Unauthorized,
65    /// The RPC client exceeds the rate limit by sending too many requests.
66    #[error("this client has exceeded the rate limit")]
67    TooManyRequests,
68    #[error("the server returned status code 400 - bad request")]
69    BadRequest,
70    #[error("the request failed with timeout error")]
71    TimeoutError,
72    #[error("the server is unavailable")]
73    ServiceUnavailable,
74    /// The RPC server returned a non-200 status code.
75    #[error("the server returned a non-OK (200) status code: [{status}]")]
76    Unexpected { status: reqwest::StatusCode },
77}
78
79/// Potential errors returned by the RPC server.
80#[derive(Debug, Error)]
81pub enum JsonRpcServerError<E> {
82    /// An invalid RPC method is called or the RPC methdo is unable to parse the provided arguments.
83    #[error("request validation error: [{0:?}]")]
84    RequestValidationError(RpcRequestValidationErrorKind),
85    /// RPC method call error.
86    #[error("handler error: [{0}]")]
87    HandlerError(E),
88    /// The RPC server returned an internal server error.
89    #[error("internal error: [{info:?}]")]
90    InternalError { info: Option<String> },
91    /// The RPC server returned a response without context i.e. a response the client doesn't expect.
92    #[error("error response lacks context: {0}")]
93    NonContextualError(RpcError),
94    /// Unexpected status codes returned by the RPC server.
95    #[error(transparent)]
96    ResponseStatusError(JsonRpcServerResponseStatusError),
97}
98
99/// Potential errors returned by the RPC client.
100#[derive(Debug, Error)]
101pub enum JsonRpcError<E> {
102    /// Potential errors returned while sending requests to or receiving responses from the RPC server.
103    #[error(transparent)]
104    TransportError(RpcTransportError),
105    /// Potential errors returned by the RPC server.
106    #[error(transparent)]
107    ServerError(JsonRpcServerError<E>),
108}
109
110impl<E> JsonRpcError<E> {
111    pub fn handler_error(&self) -> Option<&E> {
112        if let Self::ServerError(JsonRpcServerError::HandlerError(err)) = self {
113            return Some(err);
114        }
115        None
116    }
117}
118
119impl<E: super::methods::RpcHandlerError> From<RpcError> for JsonRpcError<E> {
120    fn from(err: RpcError) -> Self {
121        let mut handler_parse_error = None;
122        match err.error_struct {
123            Some(RpcErrorKind::HandlerError(ref handler_error)) => {
124                match E::parse(*handler_error.clone()) {
125                    Ok(handler_error) => {
126                        return JsonRpcError::ServerError(JsonRpcServerError::HandlerError(
127                            handler_error,
128                        ))
129                    }
130                    Err(err) => {
131                        handler_parse_error.replace(err);
132                    }
133                }
134            }
135            Some(RpcErrorKind::RequestValidationError(err)) => {
136                return JsonRpcError::ServerError(JsonRpcServerError::RequestValidationError(err));
137            }
138            Some(RpcErrorKind::InternalError(err)) => {
139                return JsonRpcError::ServerError(JsonRpcServerError::InternalError {
140                    info: err["info"]["error_message"]
141                        .as_str()
142                        .map(|info| info.to_string()),
143                })
144            }
145            None => {}
146        }
147        if let Some(ref raw_err_data) = err.data {
148            match E::parse_legacy_error(*raw_err_data.clone()) {
149                Some(Ok(handler_error)) => {
150                    return JsonRpcError::ServerError(JsonRpcServerError::HandlerError(
151                        handler_error,
152                    ))
153                }
154                Some(Err(err)) => {
155                    handler_parse_error.replace(err);
156                }
157                None => {}
158            }
159        }
160        if let Some(err) = handler_parse_error {
161            return JsonRpcError::TransportError(RpcTransportError::RecvError(
162                JsonRpcTransportRecvError::ResponseParseError(
163                    JsonRpcTransportHandlerResponseError::ErrorMessageParseError(err),
164                ),
165            ));
166        }
167        JsonRpcError::ServerError(JsonRpcServerError::NonContextualError(err))
168    }
169}