1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use std::io;

use thiserror::Error;

use near_jsonrpc_primitives::errors::{RpcError, RpcErrorKind, RpcRequestValidationErrorKind};
use near_jsonrpc_primitives::message::{self, Message};

#[derive(Debug, Error)]
pub enum JsonRpcTransportSendError {
    #[error("error while serializing payload: [{0}]")]
    PayloadSerializeError(io::Error),
    #[error("error while sending payload: [{0}]")]
    PayloadSendError(reqwest::Error),
}

#[derive(Debug, Error)]
pub enum JsonRpcTransportHandlerResponseError {
    #[error("error while parsing method call result: [{0}]")]
    ResultParseError(serde_json::Error),
    #[error("error while parsing method call error message: [{0}]")]
    ErrorMessageParseError(serde_json::Error),
}

#[derive(Debug, Error)]
pub enum JsonRpcTransportRecvError {
    #[error("unexpected server response: [{0:?}]")]
    UnexpectedServerResponse(Message),
    #[error("error while reading response: [{0}]")]
    PayloadRecvError(reqwest::Error),
    #[error("error while parsing server response: [{0:?}]")]
    PayloadParseError(message::Broken),
    #[error(transparent)]
    ResponseParseError(JsonRpcTransportHandlerResponseError),
}

#[derive(Debug, Error)]
pub enum RpcTransportError {
    #[error(transparent)]
    SendError(JsonRpcTransportSendError),
    #[error(transparent)]
    RecvError(JsonRpcTransportRecvError),
}

#[derive(Debug, Error)]
pub enum JsonRpcServerResponseStatusError {
    #[error("this client is unauthorized")]
    Unauthorized,
    #[error("this client has exceeded the rate limit")]
    TooManyRequests,
    #[error("the server returned a non-OK (200) status code: [{status}]")]
    Unexpected { status: reqwest::StatusCode },
}

#[derive(Debug, Error)]
pub enum JsonRpcServerError<E> {
    #[error("request validation error: [{0:?}]")]
    RequestValidationError(RpcRequestValidationErrorKind),
    #[error("handler error: [{0}]")]
    HandlerError(E),
    #[error("internal error: [{info:?}]")]
    InternalError { info: Option<String> },
    #[error("error response lacks context: {0}")]
    NonContextualError(RpcError),
    #[error(transparent)]
    ResponseStatusError(JsonRpcServerResponseStatusError),
}

#[derive(Debug, Error)]
pub enum JsonRpcError<E> {
    #[error(transparent)]
    TransportError(RpcTransportError),
    #[error(transparent)]
    ServerError(JsonRpcServerError<E>),
}

impl<E> JsonRpcError<E> {
    pub fn handler_error(&self) -> Option<&E> {
        if let Self::ServerError(JsonRpcServerError::HandlerError(err)) = self {
            return Some(err);
        }
        None
    }
}

impl<E: super::methods::RpcHandlerError> From<RpcError> for JsonRpcError<E> {
    fn from(err: RpcError) -> Self {
        let mut handler_parse_error = None;
        match err.error_struct {
            Some(RpcErrorKind::HandlerError(ref handler_error)) => {
                match E::parse(handler_error.clone()) {
                    Ok(handler_error) => {
                        return JsonRpcError::ServerError(JsonRpcServerError::HandlerError(
                            handler_error,
                        ))
                    }
                    Err(err) => {
                        handler_parse_error.replace(err);
                    }
                }
            }
            Some(RpcErrorKind::RequestValidationError(err)) => {
                return JsonRpcError::ServerError(JsonRpcServerError::RequestValidationError(err));
            }
            Some(RpcErrorKind::InternalError(err)) => {
                return JsonRpcError::ServerError(JsonRpcServerError::InternalError {
                    info: err["info"]["error_message"]
                        .as_str()
                        .map(|info| info.to_string()),
                })
            }
            None => {}
        }
        if let Some(ref raw_err_data) = err.data {
            match E::parse_legacy_error(raw_err_data.clone()) {
                Some(Ok(handler_error)) => {
                    return JsonRpcError::ServerError(JsonRpcServerError::HandlerError(
                        handler_error,
                    ))
                }
                Some(Err(err)) => {
                    handler_parse_error.replace(err);
                }
                None => {}
            }
        }
        if let Some(err) = handler_parse_error {
            return JsonRpcError::TransportError(RpcTransportError::RecvError(
                JsonRpcTransportRecvError::ResponseParseError(
                    JsonRpcTransportHandlerResponseError::ErrorMessageParseError(err),
                ),
            ));
        }
        JsonRpcError::ServerError(JsonRpcServerError::NonContextualError(err))
    }
}