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