data_anchor_client/client/
indexer_client.rs

1use anchor_lang::{prelude::Pubkey, solana_program::clock::Slot};
2use data_anchor_api::{CompoundInclusionProof, IndexerRpcClient, PubkeyFromStr, TimeRange};
3use data_anchor_utils::{
4    compression::DataAnchorCompressionAsync,
5    encoding::{DataAnchorEncoding, Decodable},
6};
7use solana_signer::Signer;
8
9use super::BloberIdentifier;
10use crate::{DataAnchorClient, DataAnchorClientResult};
11
12#[derive(thiserror::Error, Debug)]
13pub enum IndexerError {
14    /// Failed to read blobs for slot {0} via indexer client: {1}
15    #[error("Failed to read blobs for slot {0} via indexer client: {1}")]
16    Blobs(Slot, String),
17    /// Failed to read proof for slot {0} via indexer client: {1}
18    #[error("Failed to read proof for slot {0} via indexer client: {1}")]
19    Proof(Slot, String),
20    /// Failed to read blobs for blober {0} via indexer client: {1}
21    #[error("Failed to read blobs for blober {0} via indexer client: {1}")]
22    BlobsForBlober(String, String),
23    /// Failed to read blobs for payer {0} via indexer client: {1}
24    #[error("Failed to read blobs for payer {0} via indexer client: {1}")]
25    BlobsForPayer(String, String),
26    /// Failed to read blobs for network {0} via indexer client: {1}
27    #[error("Failed to read blobs for network {0} via indexer client: {1}")]
28    BlobsForNetwork(String, String),
29    /// Failed to read blobs for namespace {0} via indexer client: {1}
30    #[error("Failed to read blobs for namespace {0} via indexer client: {1}")]
31    BlobsForNamespace(String, String),
32    /// Failed to read proof for blob {0} via indexer client: {1}
33    #[error("Failed to read proof for blob {0} via indexer client: {1}")]
34    ProofForBlob(String, String),
35    /// Failed to read compound proof for slot {0} via indexer client: {1}
36    #[error("Failed to read checkpoint proof for blober {0} and slot {1} via indexer client: {2}")]
37    ZKProof(String, u64, String),
38    /// Failed to read payers for network {0} via indexer client: {1}
39    #[error("Failed to read payers for network {0} via indexer client: {1}")]
40    PayersForNamespace(String, String),
41}
42
43impl<Encoding, Compression> DataAnchorClient<Encoding, Compression>
44where
45    Encoding: DataAnchorEncoding + Default,
46    Compression: DataAnchorCompressionAsync,
47{
48    /// Fetches all blobs for a given slot from the [`IndexerRpcClient`].
49    pub async fn get_blobs<T>(
50        &self,
51        slot: u64,
52        identifier: BloberIdentifier,
53    ) -> DataAnchorClientResult<Option<Vec<T>>>
54    where
55        T: Decodable,
56    {
57        let blober = identifier.to_blober_address(self.program_id, self.payer.pubkey());
58
59        let Some(blobs) = self
60            .indexer()
61            .get_blobs(blober.into(), slot)
62            .await
63            .map_err(|e| IndexerError::Blobs(slot, e.to_string()))?
64        else {
65            return Ok(None);
66        };
67
68        self.decompress_and_decode_vec(blobs.iter().map(|b| b.as_slice()))
69            .await
70            .map(Some)
71    }
72
73    /// Fetches blobs for a given blober and time range from the [`IndexerRpcClient`].
74    pub async fn get_blobs_by_blober<T>(
75        &self,
76        identifier: BloberIdentifier,
77        time_range: Option<TimeRange>,
78    ) -> DataAnchorClientResult<Vec<T>>
79    where
80        T: Decodable,
81    {
82        let blober = identifier.to_blober_address(self.program_id, self.payer.pubkey());
83
84        let blobs = self
85            .indexer()
86            .get_blobs_by_blober(blober.into(), time_range)
87            .await
88            .map_err(|e| IndexerError::BlobsForBlober(blober.to_string(), e.to_string()))?;
89
90        self.decompress_and_decode_vec(blobs.iter().map(|b| b.as_slice()))
91            .await
92    }
93
94    /// Fetches blobs for a given payer, network name and time range from the [`IndexerRpcClient`].
95    pub async fn get_blobs_by_payer<T>(
96        &self,
97        payer: Pubkey,
98        network_name: String,
99        time_range: Option<TimeRange>,
100    ) -> DataAnchorClientResult<Vec<T>>
101    where
102        T: Decodable,
103    {
104        let blobs = self
105            .indexer()
106            .get_blobs_by_payer(payer.into(), network_name, time_range)
107            .await
108            .map_err(|e| IndexerError::BlobsForPayer(payer.to_string(), e.to_string()))?;
109
110        self.decompress_and_decode_vec(blobs.iter().map(|b| b.as_slice()))
111            .await
112    }
113
114    /// Fetches blobs for a given network and time range from the [`IndexerRpcClient`].
115    pub async fn get_blobs_by_network<T>(
116        &self,
117        network_name: String,
118        time_range: Option<TimeRange>,
119    ) -> DataAnchorClientResult<Vec<T>>
120    where
121        T: Decodable,
122    {
123        let blobs = self
124            .indexer()
125            .get_blobs_by_network(network_name.clone(), time_range)
126            .await
127            .map_err(|e| IndexerError::BlobsForNetwork(network_name, e.to_string()))?;
128
129        self.decompress_and_decode_vec(blobs.iter().map(|b| b.as_slice()))
130            .await
131    }
132
133    /// Fetches blobs for a given namespace and time range from the [`IndexerRpcClient`].
134    pub async fn get_blobs_by_namespace_for_payer<T>(
135        &self,
136        namespace: String,
137        payer_pubkey: Option<Pubkey>,
138        time_range: Option<TimeRange>,
139    ) -> DataAnchorClientResult<Vec<T>>
140    where
141        T: Decodable,
142    {
143        let blobs = self
144            .indexer()
145            .get_blobs_by_namespace_for_payer(
146                namespace.clone(),
147                payer_pubkey.map(|p| p.into()),
148                time_range,
149            )
150            .await
151            .map_err(|e| IndexerError::BlobsForNamespace(namespace, e.to_string()))?;
152
153        self.decompress_and_decode_vec(blobs.iter().map(|b| b.as_slice()))
154            .await
155    }
156
157    /// Fetches payers for a given network from the [`IndexerRpcClient`].
158    pub async fn get_payers_by_network(
159        &self,
160        network: String,
161    ) -> DataAnchorClientResult<Vec<PubkeyFromStr>> {
162        self.indexer()
163            .get_payers_by_network(network.clone())
164            .await
165            .map_err(|e| IndexerError::PayersForNamespace(network, e.to_string()).into())
166    }
167
168    /// Fetches compound proof for a given slot from the [`IndexerRpcClient`].
169    pub async fn get_proof(
170        &self,
171        slot: u64,
172        identifier: BloberIdentifier,
173    ) -> DataAnchorClientResult<Option<CompoundInclusionProof>> {
174        let blober = identifier.to_blober_address(self.program_id, self.payer.pubkey());
175
176        self.indexer()
177            .get_proof(blober.into(), slot)
178            .await
179            .map_err(|e| IndexerError::Proof(slot, e.to_string()).into())
180    }
181
182    /// Fetches compound proof for a given blob PDA [`Pubkey`] from the [`IndexerRpcClient`].
183    pub async fn get_proof_for_blob(
184        &self,
185        blob: Pubkey,
186    ) -> DataAnchorClientResult<Option<CompoundInclusionProof>> {
187        self.indexer()
188            .get_proof_for_blob(blob.into())
189            .await
190            .map_err(|e| IndexerError::ProofForBlob(blob.to_string(), e.to_string()).into())
191    }
192}