light_program_test/program_test/
indexer.rs

1use async_trait::async_trait;
2use light_client::indexer::{
3    Address, AddressWithTree, BatchAddressUpdateIndexerResponse, CompressedAccount,
4    CompressedTokenAccount, GetCompressedAccountsByOwnerConfig,
5    GetCompressedTokenAccountsByOwnerOrDelegateOptions, Hash, Indexer, IndexerError,
6    IndexerRpcConfig, Items, ItemsWithCursor, MerkleProof, NewAddressProofWithContext,
7    OwnerBalance, PaginatedOptions, QueueElementsResult, Response, RetryConfig,
8    SignatureWithMetadata, TokenBalance, ValidityProofWithContext,
9};
10use light_compressed_account::QueueType;
11use solana_sdk::pubkey::Pubkey;
12
13use crate::program_test::LightProgramTest;
14
15#[async_trait]
16impl Indexer for LightProgramTest {
17    async fn get_validity_proof(
18        &self,
19        hashes: Vec<Hash>,
20        new_addresses_with_trees: Vec<AddressWithTree>,
21        config: Option<IndexerRpcConfig>,
22    ) -> Result<Response<ValidityProofWithContext>, IndexerError> {
23        Ok(self
24            .indexer
25            .as_ref()
26            .ok_or(IndexerError::NotInitialized)?
27            .get_validity_proof(hashes, new_addresses_with_trees, config)
28            .await?)
29    }
30
31    async fn get_indexer_slot(&self, config: Option<RetryConfig>) -> Result<u64, IndexerError> {
32        Ok(self
33            .indexer
34            .as_ref()
35            .ok_or(IndexerError::NotInitialized)?
36            .get_indexer_slot(config)
37            .await?)
38    }
39
40    async fn get_multiple_compressed_account_proofs(
41        &self,
42        hashes: Vec<[u8; 32]>,
43        config: Option<IndexerRpcConfig>,
44    ) -> Result<Response<Items<MerkleProof>>, IndexerError> {
45        Ok(self
46            .indexer
47            .as_ref()
48            .ok_or(IndexerError::NotInitialized)?
49            .get_multiple_compressed_account_proofs(hashes, config)
50            .await?)
51    }
52
53    async fn get_compressed_accounts_by_owner(
54        &self,
55        owner: &Pubkey,
56        options: Option<GetCompressedAccountsByOwnerConfig>,
57        config: Option<IndexerRpcConfig>,
58    ) -> Result<Response<ItemsWithCursor<CompressedAccount>>, IndexerError> {
59        Ok(self
60            .indexer
61            .as_ref()
62            .ok_or(IndexerError::NotInitialized)?
63            .get_compressed_accounts_by_owner(owner, options, config)
64            .await?)
65    }
66
67    async fn get_compressed_account(
68        &self,
69        address: Address,
70        config: Option<IndexerRpcConfig>,
71    ) -> Result<Response<Option<CompressedAccount>>, IndexerError> {
72        Ok(self
73            .indexer
74            .as_ref()
75            .ok_or(IndexerError::NotInitialized)?
76            .get_compressed_account(address, config)
77            .await?)
78    }
79
80    async fn get_compressed_account_by_hash(
81        &self,
82        hash: Hash,
83        config: Option<IndexerRpcConfig>,
84    ) -> Result<Response<Option<CompressedAccount>>, IndexerError> {
85        Ok(self
86            .indexer
87            .as_ref()
88            .ok_or(IndexerError::NotInitialized)?
89            .get_compressed_account_by_hash(hash, config)
90            .await?)
91    }
92
93    async fn get_compressed_token_accounts_by_owner(
94        &self,
95        owner: &Pubkey,
96        options: Option<GetCompressedTokenAccountsByOwnerOrDelegateOptions>,
97        config: Option<IndexerRpcConfig>,
98    ) -> Result<Response<ItemsWithCursor<CompressedTokenAccount>>, IndexerError> {
99        Ok(self
100            .indexer
101            .as_ref()
102            .ok_or(IndexerError::NotInitialized)?
103            .get_compressed_token_accounts_by_owner(owner, options, config)
104            .await?)
105    }
106
107    async fn get_compressed_balance(
108        &self,
109        address: Option<Address>,
110        hash: Option<Hash>,
111        config: Option<IndexerRpcConfig>,
112    ) -> Result<Response<u64>, IndexerError> {
113        let indexer = self.indexer.as_ref().ok_or(IndexerError::NotInitialized)?;
114        Ok(Indexer::get_compressed_balance(indexer, address, hash, config).await?)
115    }
116
117    async fn get_compressed_token_account_balance(
118        &self,
119        address: Option<Address>,
120        hash: Option<Hash>,
121        config: Option<IndexerRpcConfig>,
122    ) -> Result<Response<u64>, IndexerError> {
123        Ok(self
124            .indexer
125            .as_ref()
126            .ok_or(IndexerError::NotInitialized)?
127            .get_compressed_token_account_balance(address, hash, config)
128            .await?)
129    }
130
131    async fn get_multiple_compressed_accounts(
132        &self,
133        addresses: Option<Vec<Address>>,
134        hashes: Option<Vec<Hash>>,
135        config: Option<IndexerRpcConfig>,
136    ) -> Result<Response<Items<Option<CompressedAccount>>>, IndexerError> {
137        Ok(self
138            .indexer
139            .as_ref()
140            .ok_or(IndexerError::NotInitialized)?
141            .get_multiple_compressed_accounts(addresses, hashes, config)
142            .await?)
143    }
144
145    async fn get_compressed_token_balances_by_owner_v2(
146        &self,
147        owner: &Pubkey,
148        options: Option<GetCompressedTokenAccountsByOwnerOrDelegateOptions>,
149        config: Option<IndexerRpcConfig>,
150    ) -> Result<Response<ItemsWithCursor<TokenBalance>>, IndexerError> {
151        Ok(self
152            .indexer
153            .as_ref()
154            .ok_or(IndexerError::NotInitialized)?
155            .get_compressed_token_balances_by_owner_v2(owner, options, config)
156            .await?)
157    }
158
159    async fn get_compression_signatures_for_account(
160        &self,
161        hash: Hash,
162        config: Option<IndexerRpcConfig>,
163    ) -> Result<Response<Items<SignatureWithMetadata>>, IndexerError> {
164        Ok(self
165            .indexer
166            .as_ref()
167            .ok_or(IndexerError::NotInitialized)?
168            .get_compression_signatures_for_account(hash, config)
169            .await?)
170    }
171
172    async fn get_multiple_new_address_proofs(
173        &self,
174        merkle_tree_pubkey: [u8; 32],
175        addresses: Vec<[u8; 32]>,
176        config: Option<IndexerRpcConfig>,
177    ) -> Result<Response<Items<NewAddressProofWithContext>>, IndexerError> {
178        Ok(self
179            .indexer
180            .as_ref()
181            .ok_or(IndexerError::NotInitialized)?
182            .get_multiple_new_address_proofs(merkle_tree_pubkey, addresses, config)
183            .await?)
184    }
185
186    async fn get_address_queue_with_proofs(
187        &mut self,
188        merkle_tree_pubkey: &Pubkey,
189        zkp_batch_size: u16,
190        start_offset: Option<u64>,
191        config: Option<IndexerRpcConfig>,
192    ) -> Result<Response<BatchAddressUpdateIndexerResponse>, IndexerError> {
193        Ok(self
194            .indexer
195            .as_mut()
196            .ok_or(IndexerError::NotInitialized)?
197            .get_address_queue_with_proofs(merkle_tree_pubkey, zkp_batch_size, start_offset, config)
198            .await?)
199    }
200
201    async fn get_queue_elements(
202        &mut self,
203        merkle_tree_pubkey: [u8; 32],
204        queue_type: QueueType,
205        num_elements: u16,
206        start_queue_index: Option<u64>,
207        config: Option<IndexerRpcConfig>,
208    ) -> Result<Response<QueueElementsResult>, IndexerError> {
209        Ok(self
210            .indexer
211            .as_mut()
212            .ok_or(IndexerError::NotInitialized)?
213            .get_queue_elements(
214                merkle_tree_pubkey,
215                queue_type,
216                num_elements,
217                start_queue_index,
218                config,
219            )
220            .await?)
221    }
222
223    async fn get_subtrees(
224        &self,
225        merkle_tree_pubkey: [u8; 32],
226        config: Option<IndexerRpcConfig>,
227    ) -> Result<Response<Items<[u8; 32]>>, IndexerError> {
228        Ok(self
229            .indexer
230            .as_ref()
231            .ok_or(IndexerError::NotInitialized)?
232            .get_subtrees(merkle_tree_pubkey, config)
233            .await?)
234    }
235
236    // New required trait methods
237    async fn get_compressed_balance_by_owner(
238        &self,
239        owner: &Pubkey,
240        config: Option<IndexerRpcConfig>,
241    ) -> Result<Response<u64>, IndexerError> {
242        Ok(self
243            .indexer
244            .as_ref()
245            .ok_or(IndexerError::NotInitialized)?
246            .get_compressed_balance_by_owner(owner, config)
247            .await?)
248    }
249
250    async fn get_compressed_mint_token_holders(
251        &self,
252        mint: &Pubkey,
253        options: Option<PaginatedOptions>,
254        config: Option<IndexerRpcConfig>,
255    ) -> Result<Response<ItemsWithCursor<OwnerBalance>>, IndexerError> {
256        Ok(self
257            .indexer
258            .as_ref()
259            .ok_or(IndexerError::NotInitialized)?
260            .get_compressed_mint_token_holders(mint, options, config)
261            .await?)
262    }
263
264    async fn get_compressed_token_accounts_by_delegate(
265        &self,
266        delegate: &Pubkey,
267        options: Option<GetCompressedTokenAccountsByOwnerOrDelegateOptions>,
268        config: Option<IndexerRpcConfig>,
269    ) -> Result<Response<ItemsWithCursor<CompressedTokenAccount>>, IndexerError> {
270        Ok(self
271            .indexer
272            .as_ref()
273            .ok_or(IndexerError::NotInitialized)?
274            .get_compressed_token_accounts_by_delegate(delegate, options, config)
275            .await?)
276    }
277
278    async fn get_compression_signatures_for_address(
279        &self,
280        address: &[u8; 32],
281        options: Option<PaginatedOptions>,
282        config: Option<IndexerRpcConfig>,
283    ) -> Result<Response<ItemsWithCursor<SignatureWithMetadata>>, IndexerError> {
284        Ok(self
285            .indexer
286            .as_ref()
287            .ok_or(IndexerError::NotInitialized)?
288            .get_compression_signatures_for_address(address, options, config)
289            .await?)
290    }
291
292    async fn get_compression_signatures_for_owner(
293        &self,
294        owner: &Pubkey,
295        options: Option<PaginatedOptions>,
296        config: Option<IndexerRpcConfig>,
297    ) -> Result<Response<ItemsWithCursor<SignatureWithMetadata>>, IndexerError> {
298        Ok(self
299            .indexer
300            .as_ref()
301            .ok_or(IndexerError::NotInitialized)?
302            .get_compression_signatures_for_owner(owner, options, config)
303            .await?)
304    }
305
306    async fn get_compression_signatures_for_token_owner(
307        &self,
308        owner: &Pubkey,
309        options: Option<PaginatedOptions>,
310        config: Option<IndexerRpcConfig>,
311    ) -> Result<Response<ItemsWithCursor<SignatureWithMetadata>>, IndexerError> {
312        Ok(self
313            .indexer
314            .as_ref()
315            .ok_or(IndexerError::NotInitialized)?
316            .get_compression_signatures_for_token_owner(owner, options, config)
317            .await?)
318    }
319
320    async fn get_indexer_health(&self, config: Option<RetryConfig>) -> Result<bool, IndexerError> {
321        Ok(self
322            .indexer
323            .as_ref()
324            .ok_or(IndexerError::NotInitialized)?
325            .get_indexer_health(config)
326            .await?)
327    }
328}