1use std::{future::Future, pin::Pin};
2
3use crossbeam_channel::TrySendError;
4use serde::Serialize;
5use serde_json::json;
6
7use jsonrpc_core::{Error, Result};
8use solana_pubkey::Pubkey;
9
10pub type SurfpoolResult<T> = std::result::Result<T, SurfpoolError>;
11
12#[derive(Debug, Clone)]
13pub struct SurfpoolError(Error);
14
15impl From<SurfpoolError> for String {
16 fn from(e: SurfpoolError) -> Self {
17 e.0.to_string()
18 }
19}
20
21impl From<SurfpoolError> for Error {
22 fn from(e: SurfpoolError) -> Self {
23 e.0
24 }
25}
26
27impl std::error::Error for SurfpoolError {}
28
29impl std::fmt::Display for SurfpoolError {
30 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
31 let Error {
32 code,
33 message,
34 data,
35 } = &self.0;
36
37 let core = if code.description().eq(message) {
38 format!("{}", code.description())
39 } else {
40 format!("{}: {}", code.description(), message)
41 };
42
43 if let Some(data_value) = data {
44 write!(f, "{}: {}", core, data_value.to_string().as_str())
45 } else {
46 write!(f, "{}", core)
47 }
48 }
49}
50
51impl<T> From<SurfpoolError> for Pin<Box<dyn Future<Output = Result<T>> + Send>> {
52 fn from(e: SurfpoolError) -> Self {
53 Box::pin(async move { Err(e.into()) })
54 }
55}
56
57impl<T> Into<SurfpoolError> for TrySendError<T> {
58 fn into(self) -> SurfpoolError {
59 SurfpoolError::from_try_send_error(self)
60 }
61}
62
63impl SurfpoolError {
64 pub fn from_try_send_error<T>(e: TrySendError<T>) -> Self {
65 let mut error = Error::internal_error();
66 error.data = Some(json!(format!(
67 "Failed to send command on channel: {}",
68 e.to_string()
69 )));
70 Self(error)
71 }
72
73 pub fn no_locker() -> Self {
74 let mut error = Error::internal_error();
75 error.data = Some(json!("Failed to access internal SVM state"));
76 Self(error)
77 }
78
79 pub fn set_account<T>(pubkey: Pubkey, e: T) -> Self
80 where
81 T: ToString,
82 {
83 let mut error = Error::internal_error();
84 error.data = Some(json!(format!(
85 "Failed to set account {} in remote: {}",
86 pubkey,
87 e.to_string()
88 )));
89 Self(error)
90 }
91 pub fn get_account<T>(pubkey: Pubkey, e: T) -> Self
92 where
93 T: ToString,
94 {
95 let mut error = Error::internal_error();
96 error.data = Some(json!(format!(
97 "Failed to fetch account {} from remote: {}",
98 pubkey,
99 e.to_string()
100 )));
101 Self(error)
102 }
103
104 pub fn get_multiple_accounts<T>(e: T) -> Self
105 where
106 T: ToString,
107 {
108 let mut error = Error::internal_error();
109 error.data = Some(json!(format!(
110 "Failed to fetch accounts from remote: {}",
111 e.to_string()
112 )));
113 Self(error)
114 }
115
116 pub fn invalid_pubkey<D>(pubkey: &str, data: D) -> Self
117 where
118 D: Serialize,
119 {
120 let mut error = Error::invalid_params(format!("Invalid pubkey {pubkey}"));
121 error.data = Some(json!(data));
122 Self(error)
123 }
124
125 pub fn invalid_signature<D>(signature: &str, data: D) -> Self
126 where
127 D: Serialize,
128 {
129 let mut error = Error::invalid_params(format!("Invalid signature {signature}"));
130 error.data = Some(json!(data));
131 Self(error)
132 }
133}