light_client/rpc/
errors.rs1use std::io;
2
3use light_sdk::error::LightSdkError;
4use solana_rpc_client_api::client_error::{Error as ClientError, ErrorKind};
5use solana_transaction_error::TransactionError;
6use thiserror::Error;
7
8use crate::indexer::IndexerError;
9
10#[derive(Error, Debug)]
11pub enum RpcError {
12 #[cfg(feature = "program-test")]
13 #[error("BanksError: {0}")]
14 BanksError(#[from] solana_banks_client::BanksClientError),
15
16 #[error("Rate limited")]
17 RateLimited,
18
19 #[error("State tree lookup table not found")]
20 StateTreeLookupTableNotFound,
21
22 #[error("State tree lookup table must have a multiple of 3 addresses")]
23 InvalidStateTreeLookupTable,
24
25 #[error("Nullify table not found")]
26 NullifyTableNotFound,
27
28 #[error("TransactionError: {0}")]
29 TransactionError(#[from] TransactionError),
30
31 #[error("ClientError: {0}")]
32 ClientError(ClientError),
33
34 #[error("IoError: {0}")]
35 IoError(#[from] io::Error),
36
37 #[error("Error: `{0}`")]
38 CustomError(String),
39
40 #[error("Signing error: {0}")]
41 SigningError(String),
42
43 #[error("Transaction build error: {0}")]
44 TransactionBuildError(String),
45
46 #[error("Assert Rpc Error: {0}")]
47 AssertRpcError(String),
48
49 #[error("Warp slot not in the future")]
51 InvalidWarpSlot,
52
53 #[cfg(feature = "program-test")]
54 #[error("LiteSVM Error: {0}")]
55 LiteSvmError(String),
56
57 #[error("Account {0} does not exist")]
58 AccountDoesNotExist(String),
59
60 #[error("Invalid response data.")]
61 InvalidResponseData,
62
63 #[error("Indexer not initialized.")]
64 IndexerNotInitialized,
65
66 #[error("Indexer error: {0}")]
67 IndexerError(#[from] IndexerError),
68
69 #[error(
70 "No state trees available, use rpc.get_latest_active_state_trees() to fetch state trees"
71 )]
72 NoStateTreesAvailable,
73
74 #[error("LightSdkError error: {0}")]
75 LightSdkError(#[from] LightSdkError),
76}
77
78impl From<light_event::error::ParseIndexerEventError> for RpcError {
79 fn from(e: light_event::error::ParseIndexerEventError) -> Self {
80 RpcError::CustomError(format!("ParseIndexerEventError: {}", e))
81 }
82}
83
84impl From<ClientError> for RpcError {
85 fn from(e: ClientError) -> Self {
86 if e.kind.get_transaction_error().is_some() {
88 return RpcError::ClientError(e);
89 }
90
91 if let ErrorKind::Reqwest(ref reqwest_err) = *e.kind {
93 if let Some(status) = reqwest_err.status() {
94 if status.as_u16() == 429 {
95 return RpcError::RateLimited;
96 }
97 }
98 }
99
100 RpcError::ClientError(e)
101 }
102}
103
104impl Clone for RpcError {
105 fn clone(&self) -> Self {
106 match self {
107 #[cfg(feature = "program-test")]
108 RpcError::BanksError(_) => RpcError::CustomError("BanksError".to_string()),
109 RpcError::RateLimited => RpcError::RateLimited,
110 RpcError::TransactionError(e) => RpcError::TransactionError(e.clone()),
111 RpcError::ClientError(_) => RpcError::CustomError("ClientError".to_string()),
112 RpcError::IoError(e) => RpcError::IoError(e.kind().into()),
113 RpcError::CustomError(e) => RpcError::CustomError(e.clone()),
114 RpcError::SigningError(e) => RpcError::SigningError(e.clone()),
115 RpcError::TransactionBuildError(e) => RpcError::TransactionBuildError(e.clone()),
116 RpcError::AssertRpcError(e) => RpcError::AssertRpcError(e.clone()),
117 RpcError::InvalidWarpSlot => RpcError::InvalidWarpSlot,
118 RpcError::AccountDoesNotExist(e) => RpcError::AccountDoesNotExist(e.clone()),
119 RpcError::InvalidResponseData => RpcError::InvalidResponseData,
120 RpcError::IndexerNotInitialized => RpcError::IndexerNotInitialized,
121 RpcError::IndexerError(e) => RpcError::IndexerError(e.clone()),
122 RpcError::LightSdkError(e) => RpcError::CustomError(e.to_string()),
123 RpcError::StateTreeLookupTableNotFound => RpcError::StateTreeLookupTableNotFound,
124 RpcError::InvalidStateTreeLookupTable => RpcError::InvalidStateTreeLookupTable,
125 RpcError::NullifyTableNotFound => RpcError::NullifyTableNotFound,
126 RpcError::NoStateTreesAvailable => RpcError::NoStateTreesAvailable,
127 #[cfg(feature = "program-test")]
128 RpcError::LiteSvmError(e) => RpcError::LiteSvmError(e.clone()),
129 }
130 }
131}
132
133#[cfg(feature = "program-test")]
134impl From<litesvm::error::LiteSVMError> for RpcError {
135 fn from(e: litesvm::error::LiteSVMError) -> Self {
136 RpcError::LiteSvmError(e.to_string())
137 }
138}