light_program_test/utils/
setup_light_programs.rs

1use light_client::rpc::RpcError;
2use light_compressed_account::constants::REGISTERED_PROGRAM_PDA;
3#[cfg(feature = "devenv")]
4use light_registry::account_compression_cpi::sdk::get_registered_program_pda;
5use litesvm::LiteSVM;
6use solana_compute_budget::compute_budget::ComputeBudget;
7use solana_pubkey::Pubkey;
8use solana_sdk::pubkey;
9
10use crate::{
11    accounts::{
12        registered_program_accounts::{
13            registered_program_test_account_registry_program,
14            registered_program_test_account_system_program,
15        },
16        test_accounts::NOOP_PROGRAM_ID,
17    },
18    utils::find_light_bin::find_light_bin,
19};
20
21// Program IDs as Pubkeys
22const ACCOUNT_COMPRESSION_ID: Pubkey = pubkey!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq");
23const LIGHT_REGISTRY_ID: Pubkey = pubkey!("Lighton6oQpVkeewmo2mcPTQQp7kYHr4fWpAgJyEmDX");
24const LIGHT_COMPRESSED_TOKEN_ID: Pubkey = pubkey!("cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m");
25
26/// Creates ProgramTestContext with light protocol and additional programs.
27///
28/// Programs:
29/// 1. light_registry program
30/// 2. account_compression program
31/// 3. light_compressed_token program
32/// 4. light_system_program program
33pub fn setup_light_programs(
34    additional_programs: Option<Vec<(&'static str, Pubkey)>>,
35) -> Result<LiteSVM, RpcError> {
36    let program_test = LiteSVM::new().with_log_bytes_limit(Some(100_000));
37    let program_test = program_test.with_compute_budget(ComputeBudget {
38        compute_unit_limit: 1_400_000,
39        ..Default::default()
40    });
41    let mut program_test = program_test.with_transaction_history(0);
42    // find path to bin where light cli stores program binaries.
43    let light_bin_path = find_light_bin().ok_or(RpcError::CustomError(
44        "Failed to find light binary path. To use light-program-test zk compression cli needs to be installed and light system programs need to be downloaded. Light system programs are downloaded the first time light test-validator is run.".to_string(),
45    ))?;
46    let light_bin_path = light_bin_path
47        .to_str()
48        .ok_or(RpcError::CustomError(format!(
49            "Found invalid light binary path {:?}",
50            light_bin_path
51        )))?;
52    let path = format!("{}/light_registry.so", light_bin_path);
53    program_test
54        .add_program_from_file(LIGHT_REGISTRY_ID, path.clone())
55        .inspect_err(|_| {
56            println!("Program light_registry bin not found in {}", path);
57        })?;
58    let path = format!("{}/account_compression.so", light_bin_path);
59    program_test
60        .add_program_from_file(ACCOUNT_COMPRESSION_ID, path.clone())
61        .inspect_err(|_| {
62            println!("Program account_compression bin not found in {}", path);
63        })?;
64    let path = format!("{}/light_compressed_token.so", light_bin_path);
65    program_test
66        .add_program_from_file(LIGHT_COMPRESSED_TOKEN_ID, path.clone())
67        .inspect_err(|_| {
68            println!("Program light_compressed_token bin not found in {}", path);
69        })?;
70    let path = format!("{}/spl_noop.so", light_bin_path);
71    program_test
72        .add_program_from_file(NOOP_PROGRAM_ID, path.clone())
73        .inspect_err(|_| {
74            println!("Program spl_noop bin not found in {}", path);
75        })?;
76
77    let path = format!("{}/light_system_program_pinocchio.so", light_bin_path);
78    program_test
79        .add_program_from_file(light_sdk::constants::LIGHT_SYSTEM_PROGRAM_ID, path.clone())
80        .inspect_err(|_| {
81            println!(
82                "Program light_system_program_pinocchio bin not found in {}",
83                path
84            );
85        })?;
86
87    let registered_program = registered_program_test_account_system_program();
88    program_test
89        .set_account(
90            Pubkey::new_from_array(REGISTERED_PROGRAM_PDA),
91            registered_program,
92        )
93        .map_err(|e| {
94            RpcError::CustomError(format!("Setting registered program account failed {}", e))
95        })?;
96    let registered_program = registered_program_test_account_registry_program();
97
98    #[cfg(feature = "devenv")]
99    let registry_pda = get_registered_program_pda(&LIGHT_REGISTRY_ID);
100
101    #[cfg(not(feature = "devenv"))]
102    let registry_pda = {
103        // Compute the PDA manually in non-devenv mode
104        // This is the registered program PDA for light_registry
105        Pubkey::find_program_address(
106            &[b"registered_program", LIGHT_REGISTRY_ID.as_ref()],
107            &ACCOUNT_COMPRESSION_ID,
108        )
109        .0
110    };
111
112    program_test
113        .set_account(registry_pda, registered_program)
114        .map_err(|e| {
115            RpcError::CustomError(format!("Setting registered program account failed {}", e))
116        })?;
117    if let Some(programs) = additional_programs {
118        let project_root_target_deploy_path = std::env::var("SBF_OUT_DIR").map_err(|_| {
119            RpcError::CustomError(
120                "SBF_OUT_DIR not set. Required when using additional_programs.".to_string(),
121            )
122        })?;
123        for (name, id) in programs {
124            let path = format!("{}/{}.so", project_root_target_deploy_path, name);
125            program_test
126                .add_program_from_file(id, path.clone())
127                .inspect_err(|_| {
128                    println!("Program {} bin not found in {}", name, path);
129                })?;
130        }
131    }
132    Ok(program_test)
133}