gemachain_client/
client_error.rs

1use {
2    crate::{rpc_request, rpc_response},
3    gemachain_faucet::faucet::FaucetError,
4    gemachain_sdk::{
5        signature::SignerError, transaction::TransactionError, transport::TransportError,
6    },
7    std::io,
8    thiserror::Error,
9};
10
11pub use reqwest; // export `reqwest` for clients
12
13#[derive(Error, Debug)]
14pub enum ClientErrorKind {
15    #[error(transparent)]
16    Io(#[from] io::Error),
17    #[error(transparent)]
18    Reqwest(#[from] reqwest::Error),
19    #[error(transparent)]
20    RpcError(#[from] rpc_request::RpcError),
21    #[error(transparent)]
22    SerdeJson(#[from] serde_json::error::Error),
23    #[error(transparent)]
24    SigningError(#[from] SignerError),
25    #[error(transparent)]
26    TransactionError(#[from] TransactionError),
27    #[error(transparent)]
28    FaucetError(#[from] FaucetError),
29    #[error("Custom: {0}")]
30    Custom(String),
31}
32
33impl ClientErrorKind {
34    pub fn get_transaction_error(&self) -> Option<TransactionError> {
35        match self {
36            Self::RpcError(rpc_request::RpcError::RpcResponseError {
37                data:
38                    rpc_request::RpcResponseErrorData::SendTransactionPreflightFailure(
39                        rpc_response::RpcSimulateTransactionResult {
40                            err: Some(tx_err), ..
41                        },
42                    ),
43                ..
44            }) => Some(tx_err.clone()),
45            Self::TransactionError(tx_err) => Some(tx_err.clone()),
46            _ => None,
47        }
48    }
49}
50
51impl From<TransportError> for ClientErrorKind {
52    fn from(err: TransportError) -> Self {
53        match err {
54            TransportError::IoError(err) => Self::Io(err),
55            TransportError::TransactionError(err) => Self::TransactionError(err),
56            TransportError::Custom(err) => Self::Custom(err),
57        }
58    }
59}
60
61impl From<ClientErrorKind> for TransportError {
62    fn from(client_error_kind: ClientErrorKind) -> Self {
63        match client_error_kind {
64            ClientErrorKind::Io(err) => Self::IoError(err),
65            ClientErrorKind::TransactionError(err) => Self::TransactionError(err),
66            ClientErrorKind::Reqwest(err) => Self::Custom(format!("{:?}", err)),
67            ClientErrorKind::RpcError(err) => Self::Custom(format!("{:?}", err)),
68            ClientErrorKind::SerdeJson(err) => Self::Custom(format!("{:?}", err)),
69            ClientErrorKind::SigningError(err) => Self::Custom(format!("{:?}", err)),
70            ClientErrorKind::FaucetError(err) => Self::Custom(format!("{:?}", err)),
71            ClientErrorKind::Custom(err) => Self::Custom(format!("{:?}", err)),
72        }
73    }
74}
75
76#[derive(Error, Debug)]
77#[error("{kind}")]
78pub struct ClientError {
79    pub request: Option<rpc_request::RpcRequest>,
80
81    #[source]
82    pub kind: ClientErrorKind,
83}
84
85impl ClientError {
86    pub fn new_with_request(kind: ClientErrorKind, request: rpc_request::RpcRequest) -> Self {
87        Self {
88            request: Some(request),
89            kind,
90        }
91    }
92
93    pub fn into_with_request(self, request: rpc_request::RpcRequest) -> Self {
94        Self {
95            request: Some(request),
96            ..self
97        }
98    }
99
100    pub fn request(&self) -> Option<&rpc_request::RpcRequest> {
101        self.request.as_ref()
102    }
103
104    pub fn kind(&self) -> &ClientErrorKind {
105        &self.kind
106    }
107
108    pub fn get_transaction_error(&self) -> Option<TransactionError> {
109        self.kind.get_transaction_error()
110    }
111}
112
113impl From<ClientErrorKind> for ClientError {
114    fn from(kind: ClientErrorKind) -> Self {
115        Self {
116            request: None,
117            kind,
118        }
119    }
120}
121
122impl From<TransportError> for ClientError {
123    fn from(err: TransportError) -> Self {
124        Self {
125            request: None,
126            kind: err.into(),
127        }
128    }
129}
130
131impl From<ClientError> for TransportError {
132    fn from(client_error: ClientError) -> Self {
133        client_error.kind.into()
134    }
135}
136
137impl From<std::io::Error> for ClientError {
138    fn from(err: std::io::Error) -> Self {
139        Self {
140            request: None,
141            kind: err.into(),
142        }
143    }
144}
145
146impl From<reqwest::Error> for ClientError {
147    fn from(err: reqwest::Error) -> Self {
148        Self {
149            request: None,
150            kind: err.into(),
151        }
152    }
153}
154
155impl From<rpc_request::RpcError> for ClientError {
156    fn from(err: rpc_request::RpcError) -> Self {
157        Self {
158            request: None,
159            kind: err.into(),
160        }
161    }
162}
163
164impl From<serde_json::error::Error> for ClientError {
165    fn from(err: serde_json::error::Error) -> Self {
166        Self {
167            request: None,
168            kind: err.into(),
169        }
170    }
171}
172
173impl From<SignerError> for ClientError {
174    fn from(err: SignerError) -> Self {
175        Self {
176            request: None,
177            kind: err.into(),
178        }
179    }
180}
181
182impl From<TransactionError> for ClientError {
183    fn from(err: TransactionError) -> Self {
184        Self {
185            request: None,
186            kind: err.into(),
187        }
188    }
189}
190
191impl From<FaucetError> for ClientError {
192    fn from(err: FaucetError) -> Self {
193        Self {
194            request: None,
195            kind: err.into(),
196        }
197    }
198}
199
200pub type Result<T> = std::result::Result<T, ClientError>;