1use anyhow::Error as AnyhowError;
2use serde_json::Error as SerdeJsonError;
3use std::error::Error as StdError;
4use std::fmt::Debug;
5use std::fmt::{self, Display, Formatter};
6use std::sync::Arc;
7
8type ParentError = Arc<dyn StdError + Send + Sync + 'static>;
9
10#[derive(Debug)]
11pub struct AnyhowWrapper {
12 inner: AnyhowError,
13}
14
15impl StdError for AnyhowWrapper {
16 fn source(&self) -> Option<&(dyn StdError + 'static)> {
17 self.inner.source()
18 }
19}
20
21impl From<AnyhowError> for AnyhowWrapper {
22 fn from(error: AnyhowError) -> Self {
23 AnyhowWrapper { inner: error }
24 }
25}
26
27impl Display for AnyhowWrapper {
28 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
29 write!(f, "{}", self.inner)?;
30 Ok(())
31 }
32}
33
34#[derive(Clone, Debug)]
36pub enum SbError {
37 AnyhowError(Arc<AnyhowWrapper>), Generic,
41 Message(&'static str),
42 CustomMessage(String),
43 CustomError {
44 message: String,
45 source: ParentError,
46 },
47 Unexpected,
48 EnvVariableMissing(String),
50 InvalidKeypairFile,
51 KeyParseError,
52 CheckSizeError,
53
54 IoError(ParentError),
55
56 SgxError,
58 SgxWriteError,
59
60 AmdSevError,
62 AmdRandomnessError,
63
64 NetworkError,
66
67 QuoteParseError,
69 InvalidQuoteError,
70
71 QvnError(Arc<String>),
73
74 DockerError,
76 DockerFetchError,
77 FunctionImageTooBigError,
78 ContainerErrorMessage(String),
79 ContainerError(ParentError),
80 ContainerStartError(ParentError),
81 ContainerCreateError(ParentError),
82 ContainerNeedsUpdate,
83 ContainerResultParseError,
85 AttachError,
86 ContainerTimeout,
87 ContainerActive,
88 ContainerBackoff(u64),
89 FunctionErrorCountExceeded(u32),
90
91 FunctionResultParseError,
93 IllegalFunctionOutput,
94 FunctionVerifyFailure,
95 FunctionResultIllegalAccount,
96 FunctionResultAccountsMismatch,
97 FunctionResultInvalidData,
98 FunctionResultInvalidPid,
99 FunctionResultEmptyInstructions,
100
101 TxFailure,
103 TxCompileErr,
104 TxDeserializationError,
105 QvnTxSendFailure,
106 InvalidInstructionError,
107
108 InvalidChain,
110 AnchorParse,
111 AnchorParseError,
112 EvmError,
113
114 IpfsParseError,
116 IpfsNetworkError,
117 HeartbeatRoutineFailure,
118 EventListenerRoutineFailure,
119 DecryptError,
120 ParseError,
121 MrEnclaveMismatch,
122 FunctionResultIxIncorrectTargetChain,
123 InvalidSignature,
124
125 SolanaFetchError(String),
128 SolanaBlockhashError,
130 SolanaBlockhashFetchError(ParentError),
132 SolanaPayerMismatch(String, String),
135 SolanaPayerSignerMissing(String),
136 SolanaMissingSigner(String),
138 SolanaSignError(ParentError, String),
139 SolanaInstructionsEmpty,
140 SolanaInstructionOverflow,
141 FunctionResultIxMissingDiscriminator,
142 FunctionResultError(&'static str),
143 FunctionResultIxError(&'static str),
144 FunctionResultFailoverError(u8, ParentError),
146 FunctionResultNonRetryableError(ParentError),
148
149 AccountNotFound,
150 HttpError(String, u32, u32),
151}
152
153impl fmt::Display for SbError {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 match self {
156 SbError::AnyhowError(e) => write!(f, "Anyhow error: {}", e),
157 SbError::EnvVariableMissing(message) => {
158 write!(f, "Env variable missing: {}", message.as_str())
159 }
160 SbError::Message(message) => write!(f, "error: {}", message),
161 SbError::CustomMessage(message) => write!(f, "error: {}", message.as_str()),
162 SbError::CustomError {
163 message, source, ..
164 } => write!(f, "error: {} - {:?}", message.as_str(), source),
165 SbError::FunctionResultError(message) => {
166 write!(f, "error: FunctionResultError - {}", message)
167 }
168 SbError::FunctionResultIxError(message) => {
169 write!(f, "error: FunctionResultIxError - {}", message)
170 }
171 SbError::FunctionResultFailoverError(code, source) => {
172 write!(
173 f,
174 "error: FunctionResultFailoverError ({}) - {:?}",
175 code, source
176 )
177 }
178 SbError::FunctionResultNonRetryableError(source) => {
179 write!(f, "error: FunctionResultNonRetryableError - {:?}", source)
180 }
181 SbError::SolanaPayerMismatch(expected, actual) => {
182 write!(
183 f,
184 "error: SolanaPayerMismatch - expected: {}, actual: {}",
185 expected, actual
186 )
187 }
188 SbError::SolanaMissingSigner(missing_signer) => {
189 write!(f, "error: Missing required signer: {}", missing_signer)
190 }
191 SbError::SolanaInstructionsEmpty => write!(
192 f,
193 "error: The attempted action requires at least one instruction but none were provided"
194 ),
195 SbError::SolanaInstructionOverflow => write!(
196 f,
197 "error: The transaction exceeded the maximum number of instructions (10)"
198 ),
199 SbError::SolanaPayerSignerMissing(payer) => write!(
200 f,
201 "error: The payer keypair is missing from the provided signers: {}",
202 payer
203 ),
204 SbError::SolanaBlockhashFetchError(source) => write!(
205 f,
206 "error: Failed to fetch blockhash from the cluster. Please try again. - {:?}", source
207 ),
208 _ => write!(f, "{:#?}", self),
210 }
211 }
212}
213
214impl<T> From<SbError> for Result<T, Box<SbError>> {
215 fn from(err: SbError) -> Result<T, Box<SbError>> {
216 Err(Box::new(err))
217 }
218}
219
220impl From<&str> for SbError {
221 fn from(error: &str) -> Self {
222 SbError::CustomMessage(error.to_string())
223 }
224}
225impl From<String> for SbError {
226 fn from(error: String) -> Self {
227 SbError::CustomMessage(error)
228 }
229}
230
231impl From<hex::FromHexError> for SbError {
232 fn from(error: hex::FromHexError) -> Self {
233 SbError::CustomError {
234 message: "hex error".to_string(),
235 source: Arc::new(error),
236 }
237 }
238}
239
240impl std::error::Error for SbError {
241 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
242 match self {
243 SbError::AnyhowError(e) => Some(e.as_ref()),
244 SbError::CustomError { source, .. } => Some(source.as_ref()), SbError::ContainerError(source) => Some(source.as_ref()),
246 SbError::ContainerStartError(source) => Some(source.as_ref()),
247 SbError::SolanaSignError(source, ..) => Some(source.as_ref()),
248 SbError::FunctionResultFailoverError(_code, source, ..) => Some(source.as_ref()),
249 SbError::FunctionResultNonRetryableError(source, ..) => Some(source.as_ref()),
250 _ => None,
251 }
252 }
253}
254
255impl From<SerdeJsonError> for SbError {
256 fn from(error: SerdeJsonError) -> Self {
257 SbError::CustomError {
258 message: "serde_json error".to_string(),
259 source: Arc::new(error),
260 }
261 }
262}
263
264impl From<std::io::Error> for SbError {
265 fn from(val: std::io::Error) -> Self {
266 SbError::IoError(std::sync::Arc::new(val))
267 }
268}
269
270impl From<anyhow::Error> for SbError {
271 fn from(err: anyhow::Error) -> Self {
272 SbError::AnyhowError(Arc::new(AnyhowWrapper::from(err)))
273 }
274}
275
276impl<T> From<Result<T, anyhow::Error>> for SbError {
277 fn from(err: Result<T, anyhow::Error>) -> Self {
278 match err {
279 Ok(_) => SbError::Generic,
280 Err(e) => SbError::from(e),
281 }
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288 use anyhow::anyhow;
289
290 #[test]
291 fn display_generic() {
292 let error = SbError::Generic;
293 assert_eq!(format!("{}", error), "Generic");
294 }
295
296 #[test]
297 fn display_custom_message() {
298 let error = SbError::CustomMessage("my custom message".to_string());
299 assert_eq!(format!("{}", error), "error: my custom message");
300 }
301
302 #[test]
303 fn display_env_variable_missing() {
304 let error = SbError::EnvVariableMissing("MY_ENV_VAR".to_string());
305 assert_eq!(format!("{}", error), "Env variable missing: MY_ENV_VAR");
306 }
307
308 #[test]
309 fn from_str() {
310 let error: SbError = "my custom message".into();
311 assert_eq!(format!("{}", error), "error: my custom message");
312 }
313
314 #[test]
315 fn from_hex_error() {
316 let hex_error = hex::FromHexError::OddLength;
317 let error: SbError = hex_error.into();
318 assert_eq!(format!("{}", error), "error: hex error - OddLength");
319 }
320
321 #[test]
322 fn from_serde_json_error() {
323 let json = "\"";
324 let serde_json_error = serde_json::from_str::<serde_json::Value>(json).unwrap_err();
325 let error: SbError = serde_json_error.into();
326 assert!(format!("{}", error).starts_with("error: serde_json error - "));
327 }
328
329 }
379
380impl From<SbError> for Box<dyn StdError + Send> {
381 fn from(err: SbError) -> Self {
382 Box::new(err) }
384}