safecoin_client/
client_error.rs

1pub use reqwest;
2use {
3    crate::{nonblocking::quic_client::QuicError, rpc_request, rpc_response},
4    quinn::ConnectError,
5    safecoin_faucet::faucet::FaucetError,
6    solana_sdk::{
7        signature::SignerError, transaction::TransactionError, transport::TransportError,
8    },
9    std::io,
10    thiserror::Error,
11}; // 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
76impl From<QuicError> for ClientErrorKind {
77    fn from(quic_error: QuicError) -> Self {
78        Self::Custom(format!("{:?}", quic_error))
79    }
80}
81
82impl From<ConnectError> for ClientErrorKind {
83    fn from(connect_error: ConnectError) -> Self {
84        Self::Custom(format!("{:?}", connect_error))
85    }
86}
87
88#[derive(Error, Debug)]
89#[error("{kind}")]
90pub struct ClientError {
91    pub request: Option<rpc_request::RpcRequest>,
92
93    #[source]
94    pub kind: ClientErrorKind,
95}
96
97impl ClientError {
98    pub fn new_with_request(kind: ClientErrorKind, request: rpc_request::RpcRequest) -> Self {
99        Self {
100            request: Some(request),
101            kind,
102        }
103    }
104
105    pub fn into_with_request(self, request: rpc_request::RpcRequest) -> Self {
106        Self {
107            request: Some(request),
108            ..self
109        }
110    }
111
112    pub fn request(&self) -> Option<&rpc_request::RpcRequest> {
113        self.request.as_ref()
114    }
115
116    pub fn kind(&self) -> &ClientErrorKind {
117        &self.kind
118    }
119
120    pub fn get_transaction_error(&self) -> Option<TransactionError> {
121        self.kind.get_transaction_error()
122    }
123}
124
125impl From<ClientErrorKind> for ClientError {
126    fn from(kind: ClientErrorKind) -> Self {
127        Self {
128            request: None,
129            kind,
130        }
131    }
132}
133
134impl From<TransportError> for ClientError {
135    fn from(err: TransportError) -> Self {
136        Self {
137            request: None,
138            kind: err.into(),
139        }
140    }
141}
142
143impl From<ClientError> for TransportError {
144    fn from(client_error: ClientError) -> Self {
145        client_error.kind.into()
146    }
147}
148
149impl From<std::io::Error> for ClientError {
150    fn from(err: std::io::Error) -> Self {
151        Self {
152            request: None,
153            kind: err.into(),
154        }
155    }
156}
157
158impl From<reqwest::Error> for ClientError {
159    fn from(err: reqwest::Error) -> Self {
160        Self {
161            request: None,
162            kind: err.into(),
163        }
164    }
165}
166
167impl From<rpc_request::RpcError> for ClientError {
168    fn from(err: rpc_request::RpcError) -> Self {
169        Self {
170            request: None,
171            kind: err.into(),
172        }
173    }
174}
175
176impl From<serde_json::error::Error> for ClientError {
177    fn from(err: serde_json::error::Error) -> Self {
178        Self {
179            request: None,
180            kind: err.into(),
181        }
182    }
183}
184
185impl From<SignerError> for ClientError {
186    fn from(err: SignerError) -> Self {
187        Self {
188            request: None,
189            kind: err.into(),
190        }
191    }
192}
193
194impl From<TransactionError> for ClientError {
195    fn from(err: TransactionError) -> Self {
196        Self {
197            request: None,
198            kind: err.into(),
199        }
200    }
201}
202
203impl From<FaucetError> for ClientError {
204    fn from(err: FaucetError) -> Self {
205        Self {
206            request: None,
207            kind: err.into(),
208        }
209    }
210}
211
212pub type Result<T> = std::result::Result<T, ClientError>;