Skip to main content

light_client/interface/
initialize_config.rs

1//! Helper for initializing config with sensible defaults.
2
3#[cfg(feature = "anchor")]
4use anchor_lang::{AnchorDeserialize, AnchorSerialize};
5#[cfg(not(feature = "anchor"))]
6use borsh::{BorshDeserialize as AnchorDeserialize, BorshSerialize as AnchorSerialize};
7use solana_instruction::{AccountMeta, Instruction};
8use solana_pubkey::Pubkey;
9
10/// Default address tree v2 pubkey.
11pub const ADDRESS_TREE_V2: Pubkey =
12    solana_pubkey::pubkey!("amt2kaJA14v3urZbZvnc5v2np8jqvc4Z8zDep5wbtzx");
13
14/// Default write top-up value (5000 lamports).
15pub const DEFAULT_INIT_WRITE_TOP_UP: u32 = 5_000;
16
17/// Instruction data format matching anchor-generated `initialize_compression_config`.
18#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug)]
19pub struct InitializeCompressionConfigAnchorData {
20    pub write_top_up: u32,
21    pub rent_sponsor: Pubkey,
22    pub compression_authority: Pubkey,
23    pub rent_config: light_compressible::rent::RentConfig,
24    pub address_space: Vec<Pubkey>,
25}
26
27/// Builder for `initialize_compression_config` instruction with sensible defaults.
28pub struct InitializeRentFreeConfig {
29    program_id: Pubkey,
30    fee_payer: Pubkey,
31    program_data_pda: Pubkey,
32    authority: Option<Pubkey>,
33    rent_sponsor: Pubkey,
34    compression_authority: Pubkey,
35    rent_config: light_compressible::rent::RentConfig,
36    write_top_up: u32,
37    address_space: Vec<Pubkey>,
38    config_bump: u8,
39}
40
41impl InitializeRentFreeConfig {
42    pub fn new(
43        program_id: &Pubkey,
44        fee_payer: &Pubkey,
45        program_data_pda: &Pubkey,
46        rent_sponsor: Pubkey,
47        compression_authority: Pubkey,
48    ) -> Self {
49        Self {
50            program_id: *program_id,
51            fee_payer: *fee_payer,
52            program_data_pda: *program_data_pda,
53            authority: None,
54            rent_sponsor,
55            compression_authority,
56            rent_config: light_compressible::rent::RentConfig::default(),
57            write_top_up: DEFAULT_INIT_WRITE_TOP_UP,
58            address_space: vec![ADDRESS_TREE_V2],
59            config_bump: 0,
60        }
61    }
62
63    pub fn authority(mut self, authority: Pubkey) -> Self {
64        self.authority = Some(authority);
65        self
66    }
67
68    pub fn rent_config(mut self, rent_config: light_compressible::rent::RentConfig) -> Self {
69        self.rent_config = rent_config;
70        self
71    }
72
73    pub fn write_top_up(mut self, write_top_up: u32) -> Self {
74        self.write_top_up = write_top_up;
75        self
76    }
77
78    pub fn address_space(mut self, address_space: Vec<Pubkey>) -> Self {
79        self.address_space = address_space;
80        self
81    }
82
83    pub fn config_bump(mut self, config_bump: u8) -> Self {
84        self.config_bump = config_bump;
85        self
86    }
87
88    pub fn build(self) -> (Instruction, Pubkey) {
89        let authority = self.authority.unwrap_or(self.fee_payer);
90        let config_bump_u16 = self.config_bump as u16;
91        let (config_pda, _) = Pubkey::find_program_address(
92            &[
93                light_account::LIGHT_CONFIG_SEED,
94                &config_bump_u16.to_le_bytes(),
95            ],
96            &self.program_id,
97        );
98
99        let accounts = vec![
100            AccountMeta::new(self.fee_payer, true), // payer
101            AccountMeta::new(config_pda, false),    // config
102            AccountMeta::new_readonly(self.program_data_pda, false), // program_data
103            AccountMeta::new_readonly(authority, true), // authority
104            AccountMeta::new_readonly(
105                solana_pubkey::pubkey!("11111111111111111111111111111111"),
106                false,
107            ), // system_program
108        ];
109
110        let instruction_data = InitializeCompressionConfigAnchorData {
111            write_top_up: self.write_top_up,
112            rent_sponsor: self.rent_sponsor,
113            compression_authority: self.compression_authority,
114            rent_config: self.rent_config,
115            address_space: self.address_space,
116        };
117
118        // Anchor discriminator for "initialize_compression_config"
119        // SHA256("global:initialize_compression_config")[..8]
120        const DISCRIMINATOR: [u8; 8] = [133, 228, 12, 169, 56, 76, 222, 61];
121
122        let serialized_data = instruction_data
123            .try_to_vec()
124            .expect("Failed to serialize instruction data");
125
126        let mut data = Vec::with_capacity(DISCRIMINATOR.len() + serialized_data.len());
127        data.extend_from_slice(&DISCRIMINATOR);
128        data.extend_from_slice(&serialized_data);
129
130        let instruction = Instruction {
131            program_id: self.program_id,
132            accounts,
133            data,
134        };
135
136        (instruction, config_pda)
137    }
138}