solana_rpc_client_api/
client_error.rs

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