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