light_client/indexer/
error.rs

1use 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}