light_client/indexer/
error.rs1use thiserror::Error;
2
3#[derive(Error, Debug, PartialEq)]
4pub enum IndexerError {
5 #[error("Photon API error in {context}: {message}")]
6 PhotonError { context: String, message: String },
7
8 #[error("RPC error: {0}")]
9 RpcError(String),
10
11 #[error("Failed to deserialize account data: {0}")]
12 DeserializeError(#[from] solana_program_error::ProgramError),
13
14 #[error("API error: {0}")]
15 ApiError(String),
16
17 #[error("Missing result from {context}: {message}")]
18 MissingResult { context: String, message: String },
19
20 #[error("Account not found")]
21 AccountNotFound,
22
23 #[error("Base58 decode error: {field} - {message}")]
24 Base58DecodeError { field: String, message: String },
25
26 #[error("Invalid parameters: {0}")]
27 InvalidParameters(String),
28
29 #[error("Data decode error: {field} - {message}")]
30 DataDecodeError { field: String, message: String },
31
32 #[error("Method not implemented: {0}")]
33 NotImplemented(String),
34
35 #[error("Unknown error: {0}")]
36 Unknown(String),
37
38 #[error("Indexed Merkle tree reference v1 error: {0}")]
39 ReferenceIndexedMerkleTreeError(
40 #[from] light_indexed_merkle_tree::reference::IndexedReferenceMerkleTreeError,
41 ),
42 #[error("Indexed Merkle tree v1 error: {0}")]
43 IndexedMerkleTreeError(#[from] light_indexed_merkle_tree::errors::IndexedMerkleTreeError),
44 #[error("Invalid response data")]
45 InvalidResponseData,
46
47 #[error("Error: `{0}`")]
48 CustomError(String),
49 #[error(
50 "Indexer not initialized. Set photon_url in LightClientConfig to enable indexer API calls."
51 )]
52 NotInitialized,
53 #[error("Indexer slot has not reached the requested slot.")]
54 IndexerNotSyncedToSlot,
55 #[error("Address Merkle trees cannot be packed as output Merkle trees.")]
56 InvalidPackTreeType,
57 #[error("Cannot mix v1 and v2 trees in the same validity proof. State tree version: {state_version}, Address tree version: {address_version}")]
58 MixedTreeVersions {
59 state_version: String,
60 address_version: String,
61 },
62}
63
64impl IndexerError {
65 pub fn missing_result(context: impl Into<String>, message: impl Into<String>) -> Self {
66 Self::MissingResult {
67 context: context.into(),
68 message: message.into(),
69 }
70 }
71
72 pub fn api_error(error: impl std::fmt::Display) -> Self {
73 Self::ApiError(error.to_string())
74 }
75
76 pub fn decode_error(field: impl Into<String>, error: impl std::fmt::Display) -> Self {
77 Self::DataDecodeError {
78 field: field.into(),
79 message: error.to_string(),
80 }
81 }
82
83 pub fn base58_decode_error(field: impl Into<String>, error: impl std::fmt::Display) -> Self {
84 Self::Base58DecodeError {
85 field: field.into(),
86 message: error.to_string(),
87 }
88 }
89}
90
91impl<T> From<photon_api::apis::Error<T>> for IndexerError {
92 fn from(error: photon_api::apis::Error<T>) -> Self {
93 match error {
94 photon_api::apis::Error::Reqwest(e) => {
95 IndexerError::ApiError(format!("Request error: {}", e))
96 }
97 photon_api::apis::Error::Serde(e) => {
98 IndexerError::ApiError(format!("Serialization error: {}", e))
99 }
100 photon_api::apis::Error::Io(e) => IndexerError::ApiError(format!("IO error: {}", e)),
101 _ => IndexerError::ApiError(format!("Unknown API error {}", error)),
102 }
103 }
104}
105
106impl From<crate::rpc::RpcError> for IndexerError {
107 fn from(error: crate::rpc::RpcError) -> Self {
108 IndexerError::RpcError(error.to_string())
109 }
110}
111
112impl Clone for IndexerError {
113 fn clone(&self) -> Self {
114 match self {
115 IndexerError::PhotonError { context, message } => IndexerError::PhotonError {
116 context: context.clone(),
117 message: message.clone(),
118 },
119 IndexerError::RpcError(message) => IndexerError::RpcError(message.clone()),
120 IndexerError::DeserializeError(err) => IndexerError::DeserializeError(err.clone()),
121 IndexerError::ApiError(message) => IndexerError::ApiError(message.clone()),
122 IndexerError::MissingResult { context, message } => IndexerError::MissingResult {
123 context: context.clone(),
124 message: message.clone(),
125 },
126 IndexerError::AccountNotFound => IndexerError::AccountNotFound,
127 IndexerError::Base58DecodeError { field, message } => IndexerError::Base58DecodeError {
128 field: field.clone(),
129 message: message.clone(),
130 },
131 IndexerError::InvalidParameters(message) => {
132 IndexerError::InvalidParameters(message.clone())
133 }
134 IndexerError::DataDecodeError { field, message } => IndexerError::DataDecodeError {
135 field: field.clone(),
136 message: message.clone(),
137 },
138 IndexerError::NotImplemented(message) => IndexerError::NotImplemented(message.clone()),
139 IndexerError::Unknown(message) => IndexerError::Unknown(message.clone()),
140 IndexerError::ReferenceIndexedMerkleTreeError(_) => {
141 IndexerError::CustomError("ReferenceIndexedMerkleTreeError".to_string())
142 }
143 IndexerError::IndexedMerkleTreeError(_) => {
144 IndexerError::CustomError("IndexedMerkleTreeError".to_string())
145 }
146 IndexerError::InvalidResponseData => IndexerError::InvalidResponseData,
147 IndexerError::CustomError(_) => IndexerError::CustomError("IndexerError".to_string()),
148 IndexerError::NotInitialized => IndexerError::NotInitialized,
149 IndexerError::IndexerNotSyncedToSlot => IndexerError::IndexerNotSyncedToSlot,
150 IndexerError::InvalidPackTreeType => IndexerError::InvalidPackTreeType,
151 IndexerError::MixedTreeVersions {
152 state_version,
153 address_version,
154 } => IndexerError::MixedTreeVersions {
155 state_version: state_version.clone(),
156 address_version: address_version.clone(),
157 },
158 }
159 }
160}