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    let project_root_target_deploy_path = std::env::var("SBF_OUT_DIR")
43        .map_err(|_| RpcError::CustomError("SBF_OUT_DIR not set.".to_string()))?;
44    // find path to bin where light cli stores program binaries.
45    let light_bin_path = find_light_bin().ok_or(RpcError::CustomError(
46        "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(),
47    ))?;
48    let light_bin_path = light_bin_path
49        .to_str()
50        .ok_or(RpcError::CustomError(format!(
51            "Found invalid light binary path {:?}",
52            light_bin_path
53        )))?;
54    let path = format!("{}/light_registry.so", light_bin_path);
55    program_test
56        .add_program_from_file(LIGHT_REGISTRY_ID, path.clone())
57        .inspect_err(|_| {
58            println!("Program light_registry bin not found in {}", path);
59        })?;
60    let path = format!("{}/account_compression.so", light_bin_path);
61    program_test
62        .add_program_from_file(ACCOUNT_COMPRESSION_ID, path.clone())
63        .inspect_err(|_| {
64            println!("Program account_compression bin not found in {}", path);
65        })?;
66    let path = format!("{}/light_compressed_token.so", light_bin_path);
67    program_test
68        .add_program_from_file(LIGHT_COMPRESSED_TOKEN_ID, path.clone())
69        .inspect_err(|_| {
70            println!("Program light_compressed_token bin not found in {}", path);
71        })?;
72    let path = format!("{}/spl_noop.so", light_bin_path);
73    program_test
74        .add_program_from_file(NOOP_PROGRAM_ID, path.clone())
75        .inspect_err(|_| {
76            println!("Program spl_noop bin not found in {}", path);
77        })?;
78
79    let path = format!("{}/light_system_program_pinocchio.so", light_bin_path);
80    program_test
81        .add_program_from_file(light_sdk::constants::LIGHT_SYSTEM_PROGRAM_ID, path.clone())
82        .inspect_err(|_| {
83            println!(
84                "Program light_system_program_pinocchio bin not found in {}",
85                path
86            );
87        })?;
88
89    let registered_program = registered_program_test_account_system_program();
90    program_test
91        .set_account(
92            Pubkey::new_from_array(REGISTERED_PROGRAM_PDA),
93            registered_program,
94        )
95        .map_err(|e| {
96            RpcError::CustomError(format!("Setting registered program account failed {}", e))
97        })?;
98    let registered_program = registered_program_test_account_registry_program();
99
100    #[cfg(feature = "devenv")]
101    let registry_pda = get_registered_program_pda(&LIGHT_REGISTRY_ID);
102
103    #[cfg(not(feature = "devenv"))]
104    let registry_pda = {
105        // Compute the PDA manually in non-devenv mode
106        // This is the registered program PDA for light_registry
107        Pubkey::find_program_address(
108            &[b"registered_program", LIGHT_REGISTRY_ID.as_ref()],
109            &ACCOUNT_COMPRESSION_ID,
110        )
111        .0
112    };
113
114    program_test
115        .set_account(registry_pda, registered_program)
116        .map_err(|e| {
117            RpcError::CustomError(format!("Setting registered program account failed {}", e))
118        })?;
119    if let Some(programs) = additional_programs {
120        for (name, id) in programs {
121            let path = format!("{}/{}.so", project_root_target_deploy_path, name);
122            program_test
123                .add_program_from_file(id, path.clone())
124                .inspect_err(|_| {
125                    println!("Program {} bin not found in {}", name, path);
126                })?;
127        }
128    }
129    Ok(program_test)
130}