light_client/rpc/
get_light_state_tree_infos.rs1use light_compressed_account::TreeType;
2use solana_address_lookup_table_interface::state::AddressLookupTable;
3use solana_pubkey::Pubkey;
4
5use crate::{
6 constants::{
7 NULLIFIED_STATE_TREE_LOOKUP_TABLE_DEVNET, NULLIFIED_STATE_TREE_LOOKUP_TABLE_MAINNET,
8 STATE_TREE_LOOKUP_TABLE_DEVNET, STATE_TREE_LOOKUP_TABLE_MAINNET,
9 },
10 indexer::TreeInfo,
11 rpc::{errors::RpcError, LightClient, Rpc},
12};
13
14pub struct StateTreeLUTPair {
16 pub state_tree_lookup_table: Pubkey,
17 pub nullify_table: Pubkey,
18}
19
20pub fn default_state_tree_lookup_tables() -> (Vec<StateTreeLUTPair>, Vec<StateTreeLUTPair>) {
22 let mainnet = vec![StateTreeLUTPair {
23 state_tree_lookup_table: STATE_TREE_LOOKUP_TABLE_MAINNET,
24 nullify_table: NULLIFIED_STATE_TREE_LOOKUP_TABLE_MAINNET,
25 }];
26
27 let devnet = vec![StateTreeLUTPair {
28 state_tree_lookup_table: STATE_TREE_LOOKUP_TABLE_DEVNET,
29 nullify_table: NULLIFIED_STATE_TREE_LOOKUP_TABLE_DEVNET,
30 }];
31
32 (mainnet, devnet)
33}
34
35pub fn pick_random_tree_and_queue(info: &[TreeInfo]) -> Result<(Pubkey, Pubkey), RpcError> {
45 let length = info.len();
46 if length == 0 {
47 return Err(RpcError::StateTreeLookupTableNotFound);
48 }
49
50 let index = rand::random::<usize>() % length;
51
52 let tree = info[index].tree;
53 let queue = info[index].queue;
54
55 Ok((tree, queue))
56}
57
58pub async fn get_light_state_tree_infos(
59 rpc_client: &LightClient,
60 state_tree_lookup_table_address: &Pubkey,
61 nullify_table_address: &Pubkey,
62) -> Result<Vec<TreeInfo>, RpcError> {
63 let account = rpc_client
64 .get_account(*state_tree_lookup_table_address)
65 .await
66 .map_err(|_| RpcError::StateTreeLookupTableNotFound)?
67 .ok_or(RpcError::StateTreeLookupTableNotFound)?;
68
69 let state_tree_lookup_table = AddressLookupTable::deserialize(&account.data)
70 .map_err(|_| RpcError::StateTreeLookupTableNotFound)?;
71 let state_tree_pubkeys = state_tree_lookup_table.addresses.to_vec();
72
73 if state_tree_pubkeys.len() % 3 != 0 {
74 return Err(RpcError::InvalidStateTreeLookupTable);
75 }
76
77 let account = rpc_client
78 .get_account(*nullify_table_address)
79 .await
80 .map_err(|_| RpcError::StateTreeLookupTableNotFound)?
81 .ok_or(RpcError::StateTreeLookupTableNotFound)?;
82
83 let nullify_table = AddressLookupTable::deserialize(&account.data)
84 .map_err(|_| RpcError::StateTreeLookupTableNotFound)?;
85
86 let nullify_table_pubkeys = nullify_table.addresses.to_vec();
87
88 let mut bundles = Vec::new();
89
90 for chunk in state_tree_pubkeys.chunks(3) {
91 if let [tree, queue, cpi_context] = chunk {
92 if !nullify_table_pubkeys.contains(tree) {
93 bundles.push(TreeInfo {
94 tree: *tree,
95 queue: *queue,
96 cpi_context: Some(*cpi_context),
97 next_tree_info: None,
98 tree_type: TreeType::StateV1,
99 });
100 }
101 }
102 }
103
104 Ok(bundles)
105}