data_anchor_client/client/
indexer_client.rs1use 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 #[error("Failed to read blobs for slot {0} via indexer client: {1}")]
13 Blobs(Slot, String),
14 #[error("Failed to read proof for slot {0} via indexer client: {1}")]
16 Proof(Slot, String),
17 #[error("Failed to read blobs for blober {0} via indexer client: {1}")]
19 BlobsForBlober(String, String),
20 #[error("Failed to read blobs for payer {0} via indexer client: {1}")]
22 BlobsForPayer(String, String),
23 #[error("Failed to read blobs for network {0} via indexer client: {1}")]
25 BlobsForNetwork(String, String),
26 #[error("Failed to read blobs for namespace {0} via indexer client: {1}")]
28 BlobsForNamespace(String, String),
29 #[error("Failed to read proof for blob {0} via indexer client: {1}")]
31 ProofForBlob(String, String),
32 #[error("Failed to read checkpoint proof for blober {0} and slot {1} via indexer client: {2}")]
34 ZKProof(String, u64, String),
35 #[error("Failed to read payers for network {0} via indexer client: {1}")]
37 PayersForNamespace(String, String),
38}
39
40impl DataAnchorClient {
41 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 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 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 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 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 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 #[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 #[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}