### Copy Example Environment File Source: https://github.com/lightprotocol/light-protocol/blob/main/forester/README.md Copy the example environment file to start configuring your environment variables. ```bash cp .env.example .env ``` -------------------------------- ### Install All Components Including Proving Keys Source: https://github.com/lightprotocol/light-protocol/blob/main/INSTALL.md Use this command to install all components, including the necessary proving keys. This is a comprehensive installation option. ```bash ./scripts/install.sh --full-keys ``` -------------------------------- ### Light Client Example Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/client/README.md Demonstrates starting a local test validator, connecting to it using LightClient, querying compressed accounts by owner, and retrieving validity proofs. Supports connecting to local, devnet, or mainnet RPC endpoints. ```rust use light_client::[ rpc::{LightClient, LightClientConfig, Rpc}, indexer::{Indexer, IndexerRpcConfig, RetryConfig}, local_test_validator::{spawn_validator, LightValidatorConfig}, ]; use solana_pubkey::Pubkey; #[tokio::main] async fn main() -> Result<(), Box> { // Start local test validator with Light Protocol programs let config = LightValidatorConfig { enable_indexer: true, enable_prover: true, wait_time: 75, sbf_programs: vec![], upgradeable_programs: vec![], limit_ledger_size: None, use_surfpool: true, validator_args: vec![], }; spawn_validator(config).await; // Connect to the validator let mut rpc = LightClient::new(LightClientConfig::local()).await?; // Or connect to devnet/mainnet (API key embedded in photon URL): // let mut rpc = LightClient::new(LightClientConfig::new( // "https://devnet.helius-rpc.com".to_string(), // Some("https://photon.helius.com?api-key=YOUR_KEY".to_string()), // )).await?; let owner = Pubkey::new_unique(); // Create indexer config for queries let slot = rpc.get_slot().await?; let config = IndexerRpcConfig { slot, retry_config: RetryConfig::default(), }; // Query compressed accounts using Indexer trait let accounts = rpc .get_compressed_accounts_by_owner(&owner, None, Some(config)) .await?; println!("Found {} compressed accounts", accounts.value.items.len()); // Get validity proofs for creating transactions let rpc_result = rpc .get_validity_proof( vec![], // add account hashes here vec![], // add addresses with address tree here None ) .await?; println!("Got validity proof and proof inputs {:?}", rpc_result.value); Ok(()) } ``` -------------------------------- ### Install All Components with install.sh Source: https://github.com/lightprotocol/light-protocol/blob/main/INSTALL.md Run this script to install all default components of the monorepo. Ensure you have cloned the repository before execution. ```bash ./scripts/install.sh ``` -------------------------------- ### Start Light Test Validator Source: https://github.com/lightprotocol/light-protocol/blob/main/cli/README.md Starts a local Solana test validator with necessary Light system programs, prover server, and Photon indexer. This is the default setup for local development. ```bash light test-validator ``` -------------------------------- ### Complete Token Initialization Example Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/features/anchor-spl-features.md Provides a comprehensive example for initializing a new token, including mint and associated token accounts, using various Anchor SPL programs. ```rust use anchor_lang::prelude::*; use light_anchor_spl::{ associated_token::AssociatedToken, token_interface::{Mint, TokenAccount, TokenInterface}, }; #[derive(Accounts)] pub struct InitializeToken<'info> { #[account(mut)] pub payer: Signer<'info>, /// The mint to create #[account( init, payer = payer, mint::decimals = 6, mint::authority = payer, mint::freeze_authority = payer, )] pub mint: InterfaceAccount<'info, Mint>, /// The payer's associated token account #[account( init, payer = payer, associated_token::mint = mint, associated_token::authority = payer, associated_token::token_program = token_program, )] pub token_account: InterfaceAccount<'info, TokenAccount>, pub token_program: Interface<'info, TokenInterface>, pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, } ``` -------------------------------- ### Install @lightprotocol/stateless.js Source: https://github.com/lightprotocol/light-protocol/blob/main/js/stateless.js/README.md Install this package in your project by running the following terminal command. ```bash npm install --save @lightprotocol/stateless.js ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/lightprotocol/light-protocol/blob/main/README.md Installs project dependencies into the `.local` directory. Use the `--full-keys` flag for production-ready keys. ```bash ./scripts/install.sh ``` ```bash ./scripts/install.sh --full-keys ``` -------------------------------- ### Install with Skipped Components Source: https://github.com/lightprotocol/light-protocol/blob/main/INSTALL.md This command allows you to skip specific components during installation. Use with caution and only if you understand the dependencies. ```bash ./scripts/install.sh --skip-components "redis,keys,go" ``` -------------------------------- ### Build and Run Light Prover Source: https://github.com/lightprotocol/light-protocol/blob/main/prover/server/README.md Build the Go binary for the light prover and start the API server using a configuration file. ```shell go build . light-prover --config path/to/config/file ``` -------------------------------- ### CreateVault Account Structure Example Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/accounts/token.md An example of a `CreateVault` account structure demonstrating the use of `#[light_account]` for defining a token account with initialization and including necessary infrastructure accounts. ```rust const VAULT_SEED: &[u8] = b"vault"; const VAULT_AUTH_SEED: &[u8] = b"vault_authority"; #[derive(Accounts, LightAccounts)] #[instruction(params: CreateVaultParams)] pub struct CreateVault<'info> { #[account(mut)] pub fee_payer: Signer<'info>, pub mint: AccountInfo<'info>, #[account(seeds = [VAULT_AUTH_SEED], bump)] pub vault_authority: UncheckedAccount<'info>, // Token account with init - creates via CreateTokenAccountCpi in pre_init #[light_account(init, token::seeds = [VAULT_SEED, self.mint.key()], // Token account PDA seeds (no bump) token::owner_seeds = [VAULT_AUTH_SEED], // Owner PDA PDA seeds (no bump) token::mint = mint, // Mint field reference token::owner = vault_authority, // Owner field reference token::bump = params.vault_bump // Optional bump )] pub vault: Account<'info, CToken>, // Infrastructure for token account creation pub light_token_config: Account<'info, CompressibleConfig>, #[account(mut)] pub light_token_rent_sponsor: Account<'info, RentSponsor>, pub light_token_cpi_authority: AccountInfo<'info>, pub system_program: Program<'info, System>, } ``` -------------------------------- ### Install and Build Monorepo from Source Source: https://github.com/lightprotocol/light-protocol/blob/main/cli/README.md Installs dependencies and builds the entire monorepo, including the CLI, from source. Requires the development environment to be activated. ```bash ./scripts/install.sh ``` ```bash ./scripts/build.sh ``` -------------------------------- ### Install ZK Compression CLI via npm Source: https://github.com/lightprotocol/light-protocol/blob/main/cli/README.md Installs the ZK Compression CLI globally using npm. Ensure Node.js is installed and meets the version requirements. ```bash npm install -g @lightprotocol/zk-compression-cli ``` -------------------------------- ### Install Light CLI Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/client/README.md Install the Light CLI globally using npm. This is a prerequisite for local test validator usage. ```bash npm i -g @lightprotocol/zk-compression-cli ``` -------------------------------- ### CI Setup for Environment Source: https://github.com/lightprotocol/light-protocol/blob/main/INSTALL.md This YAML snippet demonstrates how to set up and build the project within a CI environment, including options to skip specific components. ```yaml - name: Setup and build uses: ./.github/actions/setup-and-build with: skip-components: "redis" ``` -------------------------------- ### Start Forester with Custom Options Source: https://github.com/lightprotocol/light-protocol/blob/main/forester/README.md Use this command to start the Forester service with specific configurations for RPC, indexer, prover, payer, derivation, fallback URLs, pool sizes, processing modes, concurrency, compute limits, and priority fees. ```bash cargo run -- start \ --rpc-url "$RPC_URL" \ --indexer-url "$INDEXER_URL" \ --prover-url "$PROVER_URL" \ --payer "$PAYER" \ --derivation "$DERIVATION_PUBKEY" \ --fallback-rpc-url "$FALLBACK_RPC_URL" \ --fallback-indexer-url "$FALLBACK_INDEXER_URL" \ --rpc-pool-size 100 \ --processor-mode v2 \ --max-concurrent-sends 200 \ --cu-limit 400000 \ --priority-fee-microlamports 10000 ``` -------------------------------- ### Dynamic Account Access Example Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/PACKED_ACCOUNTS.md Demonstrates accessing accounts by index using `get_u8` for dynamic account sets, such as mint and owner accounts. ```rust use light_account_checks::{AccountInfoTrait, ProgramPackedAccounts}; fn process_with_dynamic_accounts( accounts: &[A], mint_index: u8, owner_index: u8, ) -> Result<(), AccountError> { let packed = ProgramPackedAccounts { accounts }; // Access accounts by index from instruction data let mint = packed.get_u8(mint_index, "mint")?; let owner = packed.get_u8(owner_index, "owner")?; // Validate retrieved accounts check_owner(&token_program_id, mint)?; check_signer(owner)?; Ok(()) } ``` -------------------------------- ### Program Setup with Light Accounts Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/account/README.md Set up your Anchor program to use Light Accounts by declaring the program ID and deriving the CPI signer constant. ```rust use light_account::{derive_light_cpi_signer, light_program, CpiSigner}; declare_id!("Your11111111111111111111111111111111111111"); pub const LIGHT_CPI_SIGNER: CpiSigner = derive_light_cpi_signer!("Your11111111111111111111111111111111111111"); #[light_program] #[program] pub mod my_program { // ... } ``` -------------------------------- ### Dynamic Account Access Example Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/PACKED_ACCOUNTS.md Demonstrates how to use ProgramPackedAccounts to access accounts dynamically based on indices provided in instruction data. ```APIDOC ## Dynamic Account Access ### Description This pattern shows how to access accounts by index when the indices are part of the instruction data, allowing for flexible account arrangements. ### Usage ```rust use light_account_checks::{AccountInfoTrait, ProgramPackedAccounts}; fn process_with_dynamic_accounts( accounts: &[A], mint_index: u8, owner_index: u8, ) -> Result<(), AccountError> { let packed = ProgramPackedAccounts { accounts }; // Access accounts by index from instruction data let mint = packed.get_u8(mint_index, "mint")?; let owner = packed.get_u8(owner_index, "owner")?; // Validate retrieved accounts // check_owner(&token_program_id, mint)?; // check_signer(owner)?; Ok(()) } ``` ``` -------------------------------- ### Start Test Validator with Options Source: https://github.com/lightprotocol/light-protocol/blob/main/cli/README.md Starts the Light test validator, allowing customization by skipping the indexer or prover. Use `--skip-indexer` to run without the indexer, or `--skip-prover` to run without the prover. ```bash light test-validator --skip-indexer ``` ```bash light test-validator --skip-prover ``` -------------------------------- ### Build Verifiable Light Protocol Source: https://github.com/lightprotocol/light-protocol/blob/main/README.md Execute this script to build the verifiable version of the Light Protocol. Ensure prerequisites like solana-verify and docker are installed. ```bash ./scripts/build-verifiable.sh ``` -------------------------------- ### Merkle Tree and Queue Access Example Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/PACKED_ACCOUNTS.md Shows how to access specific accounts like Merkle trees and queues using their respective indices. ```APIDOC ## Merkle Tree and Queue Access ### Description This pattern illustrates accessing specific types of accounts, such as a Merkle tree or a queue, by their designated indices within the packed account list. ### Usage ```rust fn access_merkle_accounts( accounts: &[A], tree_index: u8, queue_index: u8, ) -> Result<(), AccountError> { let packed = ProgramPackedAccounts { accounts }; let merkle_tree = packed.get_u8(tree_index, "merkle_tree")?; let queue = packed.get_u8(queue_index, "queue")?; // Validate merkle tree account // check_account_info::(&program_id, merkle_tree)?; // Validate queue account // check_account_info::(&program_id, queue)?; Ok(()) } ``` ``` -------------------------------- ### Combined Account Constraints Example Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/features/anchor-account-features.md Demonstrates combining multiple account constraints including mutability, PDA derivation, owner check, and a custom constraint with an error. ```rust #[derive(Accounts)] #[instruction(new_authority: Pubkey)] pub struct TransferAuthority<'info> { #[account( mut, seeds = [b"config"], bump = config.bump, has_one = authority, constraint = new_authority != Pubkey::default() @ MyError::InvalidAuthority )] pub config: Account<'info, Config>, pub authority: Signer<'info>, } ``` -------------------------------- ### PDA Derivation Examples Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/compressible/docs/CONFIG_ACCOUNT.md Demonstrates how to derive the Program Derived Address (PDA) for the CompressibleConfig account using different versions. This is essential for interacting with the configuration account. ```rust // Derive any version let (pda, bump) = CompressibleConfig::derive_pda( &program_id, version // u16 ); // Derive V1 config (most common) let v1_pda = CompressibleConfig::ctoken_v1_config_pda(); ``` -------------------------------- ### Start Forester Service Source: https://github.com/lightprotocol/light-protocol/blob/main/forester/README.md Start the Forester service using cargo run. You can also source your environment file before starting. ```bash cargo run -- start ``` ```bash source .env && cargo run -- start ``` -------------------------------- ### Verify CLI Installation Source: https://github.com/lightprotocol/light-protocol/blob/main/cli/README.md Verifies that the CLI has been correctly installed and is accessible in your system's PATH. This command should output the path to the installed CLI executable. ```bash which light ``` -------------------------------- ### Create a Compressed Mint with Light Macros Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/features/light-features.md Utilize `#[light_account(init, mint::...)]` to initialize a compressed mint. This runs in `light_pre_init()` after account deserialization, creating the mint via CPI to the compressed token program and linking the on-chain mint PDA to its compressed representation. ```rust #[derive(Accounts, LightAccounts)] pub struct CreateMint<'info> { #[account(mut)] pub payer: Signer<'info>, /// CHECK: Initialized in light_pre_init #[account(mut)] #[light_account(init, mint::decimals = 6, mint::authority = payer)] pub mint: UncheckedAccount<'info>, pub compressed_token_program: Program<'info, CompressedToken>, pub system_program: Program<'info, System>, } ``` -------------------------------- ### Program Setup with Light Accounts Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/account-pinocchio/README.md Set up your program ID and CPI signer constant using the provided macros. Ensure the program ID is correctly defined. ```rust use light_account_pinocchio::{derive_light_cpi_signer, CpiSigner, LightProgramPinocchio}; use pinocchio_pubkey::pubkey; pub const ID: Pubkey = pubkey!("Your11111111111111111111111111111111111111"); pub const LIGHT_CPI_SIGNER: CpiSigner = derive_light_cpi_signer!("Your11111111111111111111111111111111111111"); ``` -------------------------------- ### Install cargo-fuzz Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/README.md Install the `cargo-fuzz` tool, which requires a nightly version of Rust. ```bash cargo install cargo-fuzz ``` -------------------------------- ### Mint with All Constraints Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/features/anchor-spl-features.md Illustrates setting all possible constraints for initializing a mint account, including decimals, authorities, and the associated token program. ```rust #[account( init, payer = payer, mint::decimals = decimals, mint::authority = mint_authority, mint::freeze_authority = freeze_authority, mint::token_program = token_program, )] pub mint: InterfaceAccount<'info, Mint>, ``` -------------------------------- ### AccountIterator Usage Example Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/ACCOUNT_ITERATOR.md Example demonstrating basic instruction processing using AccountIterator. ```APIDOC ## Basic Instruction Processing ```rust use light_account_checks::{AccountIterator, AccountInfoTrait, AccountError}; fn process_transfer( accounts: &[A], ) -> Result<(), AccountError> { let mut iter = AccountIterator::new(accounts); let authority = iter.next_signer("authority")?; let source = iter.next_mut("source_account")?; let destination = iter.next_mut("destination_account")?; let mint = iter.next_non_mut("mint")?; // Process transfer... Ok(()) } ``` ``` -------------------------------- ### Mint Account Parameters for #[light_account] Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/accounts/architecture.md Initialize mint accounts using the `mint::` namespace. Required parameters include `mint::signer`, `mint::authority`, `mint::decimals`, and `mint::seeds`. Optional parameters allow for specifying freeze authority, metadata, and rent/write-up values. ```rust #[light_account(init, mint, mint::signer = mint_signer, // AccountInfo that seeds the mint PDA (required) mint::authority = authority, // Mint authority field (required) mint::decimals = params.decimals, // Token decimals (required) mint::seeds = &[MINT_SIGNER_SEED, self.authority.key().as_ref()], // PDA signer seeds (required) mint::bump = params.mint_signer_bump, // Optional: explicit bump mint::freeze_authority = freeze_auth, // Optional: freeze authority field mint::authority_seeds = &[b"auth", &[auth_bump]], // Optional: PDA seeds if authority is a PDA mint::authority_bump = params.auth_bump, // Optional: bump for authority_seeds mint::rent_payment = 16, // Optional: rent payment epochs (default: 16) mint::write_top_up = 766, // Optional: write top-up lamports (default: 766) mint::name = params.name.clone(), // Optional: TokenMetadata name mint::symbol = params.symbol.clone(), // Optional: TokenMetadata symbol mint::uri = params.uri.clone(), // Optional: TokenMetadata URI mint::update_authority = update_auth, // Optional: metadata update authority mint::additional_metadata = params.extra_metadata // Optional: additional metadata )] pub cmint: UncheckedAccount<'info>, ``` -------------------------------- ### Mint Account Initialization with LightAccounts Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/accounts/mint.md Use this macro to initialize a compressed mint account. Specify signer, authority, decimals, and seeds. Infrastructure accounts like fee payer and token program are also required. ```rust const MINT_SIGNER_SEED: &[u8] = b"mint_signer"; #[derive(AnchorSerialize, AnchorDeserialize)] pub struct CreateMintParams { pub create_accounts_proof: CreateAccountsProof, pub decimals: u8, } #[derive(Accounts, LightAccounts)] #[instruction(params: CreateMintParams)] pub struct CreateMint<'info> { #[account(mut)] pub fee_payer: Signer<'info>, pub authority: Signer<'info>, #[account(seeds = [MINT_SIGNER_SEED], bump)] pub mint_signer: AccountInfo<'info>, // Mint creation - uses CreateMintsCpi in pre_init #[light_account(init, mint::signer = mint_signer, // Seeds the mint PDA mint::authority = authority, // Mint authority mint::decimals = params.decimals, // Decimals from params mint::seeds = &[MINT_SIGNER_SEED] // Seeds WITHOUT bump )] pub cmint: Account<'info, Mint>, // Infrastructure for mint creation pub light_token_config: Account<'info, CompressibleConfig>, #[account(mut)] pub light_token_rent_sponsor: Account<'info, RentSponsor>, pub light_token_cpi_authority: AccountInfo<'info>, } ``` -------------------------------- ### Install Ubuntu Build Dependencies Source: https://github.com/lightprotocol/light-protocol/blob/main/README.md Installs essential build tools and libraries on Ubuntu systems to resolve potential build errors. ```bash sudo apt install build-essential autoconf automake libtool zlib1g-dev pkg-config libssl-dev ``` -------------------------------- ### Start Light Test Validator Source: https://github.com/lightprotocol/light-protocol/blob/main/cli/README.md Starts a local Solana test-validator with Light system programs, a prover server, and the Photon indexer. Options are available to skip the indexer or prover. ```APIDOC ## Start Light Test Validator Starts a Solana test-validator with the Light system programs and accounts, a prover server, and the Photon indexer as background processes against a clean ledger. ### Usage ```bash light test-validator ``` ### Options - `--skip-indexer`: Start without the indexer. - `--skip-prover`: Start without the prover. ### Notes The CLI currently runs the photon indexer and light-prover as background processes at port: `8784` and `3001` respectively. ``` -------------------------------- ### Rust Example: User Profile with Compression and Light Macros Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/features/light-features.md Demonstrates a Rust struct `UserProfile` that supports compression and integrates with Light Protocol macros for account management and hashing. It also shows a basic Anchor program `my_program` with a `create_profile` instruction and the corresponding `CreateProfile` accounts struct, which utilizes Light Protocol's account infrastructure. ```rust use anchor_lang::prelude::*; use light_sdk::compressible::CompressionInfo; use light_sdk_macros::*; // Data struct with compression support #[derive(Default, Debug, InitSpace, LightAccount, LightDiscriminator, LightHasherSha)] #[account] pub struct UserProfile { pub compression_info: CompressionInfo, // Non-Option, first or last field pub owner: Pubkey, #[max_len(32)] pub username: String, pub level: u8, } #[light_program] #[program] pub mod my_program { use super::*; pub fn create_profile(ctx: Context, username: String) -> Result<()> { let profile = &mut ctx.accounts.profile; profile.owner = ctx.accounts.user.key(); profile.username = username; profile.level = 1; Ok(()) } } // Accounts struct with Light support #[derive(Accounts, LightAccounts)] pub struct CreateProfile<'info> { #[account(mut)] pub user: Signer<'info>, #[account( init, payer = user, space = 8 + UserProfile::INIT_SPACE, seeds = [b"profile", user.key().as_ref()], bump )] #[light_account(init)] pub profile: Account<'info, UserProfile>, pub system_program: Program<'info, System>, // Light Protocol infrastructure (auto-detected) pub light_system_program: Program<'info, LightSystem>, pub account_compression_program: Program<'info, AccountCompression>, } ``` -------------------------------- ### Initialize Account with `init` Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/features/anchor-account-features.md Use the `init` constraint to create a new account via CPI to the System Program. Requires `payer` and `space` companions. ```rust #[account(init, payer = user, space = 8 + 64)] pub my_account: Account<'info, MyData>, ``` -------------------------------- ### get Method Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/PACKED_ACCOUNTS.md Retrieves an account at a specified index with bounds checking and descriptive error messages. ```APIDOC ## get Method ### Description Retrieves account at specified index with bounds checking. ### Signature ```rust fn get(&self, index: usize, name: &str) -> Result<&A, AccountError> ``` ### Parameters - `index` (usize): Zero-based index into account array. - `name` (str): Descriptive name for error messages. ### Returns - `Result<&A, AccountError>`: A reference to the account if found, otherwise an `AccountError`. ### Errors - `AccountError::NotEnoughAccountKeys` (12020): If the index is out of bounds. Includes location tracking. ``` -------------------------------- ### Light Account (PDA) Definition Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/account/README.md Example of defining a Light Account (PDA) with the `#[light_account(init)]` attribute. ```rust #[account(init, payer = fee_payer, space = 8 + MyRecord::INIT_SPACE, seeds = [...], bump)] #[light_account(init)] pub record: Account<'info, MyRecord>, ``` -------------------------------- ### Mark PDA Fields for Compression with #[light_account(init)] Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/accounts/architecture.md Use `#[light_account(init)]` on Account fields to mark them for compression. The tree info is automatically sourced from instruction parameters. ```rust #[derive(Accounts, LightAccounts)] #[instruction(params: CreateParams)] pub struct CreateAccounts<'info> { #[account( init, payer = fee_payer, space = 8 + UserRecord::INIT_SPACE, seeds = [b"user", params.owner.as_ref()], bump )] #[light_account(init)] // Uses address_tree_info and output_tree from CreateAccountsProof pub user_record: Account<'info, UserRecord>, } ``` -------------------------------- ### ProgramPackedAccounts get Method Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/PACKED_ACCOUNTS.md Retrieves an account at a specified index with bounds checking and descriptive error messages. ```rust fn get(&self, index: usize, name: &str) -> Result<&A, AccountError> ``` -------------------------------- ### Compile and Check Theorems with Lake Source: https://github.com/lightprotocol/light-protocol/blob/main/prover/server/README.md Navigate to the formal verification directory and use Lake to build the project, which compiles and checks the theorems. The cache get command is optional but can speed up dependency compilation. ```bash cd formal-verification lake exe cache get # optional, but speeds up dependency compilation lake build # compiles and checks the theorems ``` -------------------------------- ### Run V1 Pinocchio SDK Tests Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-tests/CLAUDE.md Execute integration tests for Light SDK V1 with the Pinocchio framework. ```bash cargo test-sbf -p sdk-pinocchio-v1-test ``` -------------------------------- ### Activate Development Environment Source: https://github.com/lightprotocol/light-protocol/blob/main/README.md Activates the development environment, allowing the use of installed dependencies without global interference. ```bash ./scripts/devenv.sh ``` -------------------------------- ### Hybrid Account Access Example Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/PACKED_ACCOUNTS.md Combines `AccountIterator` for fixed accounts with `ProgramPackedAccounts` for dynamically accessed remaining accounts. ```rust fn process_complex_instruction( accounts: &[A], dynamic_indices: Vec, ) -> Result<(), AccountError> { let mut iter = AccountIterator::new(accounts); // Fixed accounts at start let authority = iter.next_signer("authority")?; let payer = iter.next_signer_mut("payer")?; let config = iter.next_non_mut("config")?; // Remaining accounts accessed dynamically let remaining = iter.remaining()?; let packed = ProgramPackedAccounts { accounts: remaining }; // Access by indices from instruction data for (i, &index) in dynamic_indices.iter().enumerate() { let account = packed.get(index as usize, &format!("dynamic_{{}}", i))?; // Process dynamic account } Ok(()) } ``` -------------------------------- ### Anchor vs Light Protocol Execution Lifecycle Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/features/comparison.md Visual comparison of the execution flow for Anchor and Light RentFree, illustrating the distinct phases and function calls in each system. ```text ANCHOR: ================================================================================ try_accounts() ─────────────────────────────────────────────> handler() -> exit() │ ├─ Extract AccountInfo ├─ System CPI (init) ├─ Token CPI (mint::*, token::*) └─ Deserialize ================================================================================ LIGHT RENTFREE: ================================================================================ try_accounts() ───> light_pre_init() ───> handler() ───> light_finalize() -> exit() │ │ │ ├─ Extract ├─ Register address ├─ Serialize state ├─ System CPI ├─ Compressed mint CPI ├─ Create Merkle leaf └─ Deserialize └─ Compression setup └─ Update tree ================================================================================ ``` -------------------------------- ### Input Struct for Packing Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/account/architecture.md Example of an input struct for the packing process, including compression_info, Pubkey fields, and a u64 score. ```rust pub struct UserRecord { pub compression_info: CompressionInfo, pub owner: Pubkey, // 32 bytes pub authority: Pubkey, // 32 bytes pub score: u64, } ``` -------------------------------- ### Deriving LightAccount for UserRecord Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/account/architecture.md Example of deriving `LightAccount` for a `UserRecord` struct. Ensure `CompressionInfo` is the first or last field and is not an Option. ```rust use light_sdk_macros::LightAccount; use light_sdk::compressible::CompressionInfo; use solana_pubkey::Pubkey; #[derive(Default, Debug, Clone, InitSpace, LightAccount)] #[account] pub struct UserRecord { pub compression_info: CompressionInfo, // Non-Option, first or last field pub owner: Pubkey, #[max_len(32)] pub name: String, pub score: u64, } ``` -------------------------------- ### Light Protocol Macro Usage Example Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/CLAUDE.md Demonstrates the integration of various Light Protocol macros for defining state accounts, accounts structs, and program logic. Ensure necessary imports are included. ```rust use light_sdk_macros::{light_program, LightAccounts, LightAccount, LightDiscriminator, LightHasherSha}; // State account with compression support #[derive(Default, Debug, InitSpace, LightAccount, LightDiscriminator, LightHasherSha)] #[account] pub struct UserRecord { pub compression_info: CompressionInfo, // Non-Option, first or last field pub owner: Pubkey, pub score: u64, } // Accounts struct with rent-free field #[derive(Accounts, LightAccounts)] #[instruction(params: CreateParams)] pub struct Create<'info> { #[account(mut)] pub fee_payer: Signer<'info>, #[account(init, payer = fee_payer, space = 8 + UserRecord::INIT_SPACE, seeds = [b"user", params.owner.as_ref()], bump)] #[light_account(init)] pub user_record: Account<'info, UserRecord>, } // Program with auto-wrapped instructions #[light_program] #[program] pub mod my_program { pub fn create(ctx: Context, params: CreateParams) -> Result<()> { ctx.accounts.user_record.owner = params.owner; Ok(()) } } ``` -------------------------------- ### Basic Instruction Processing with AccountIterator Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/ACCOUNT_ITERATOR.md Example demonstrating how to use AccountIterator to sequentially retrieve and validate accounts for a transfer operation. ```rust use light_account_checks::{AccountIterator, AccountInfoTrait, AccountError}; fn process_transfer( accounts: &[A], ) -> Result<(), AccountError> { let mut iter = AccountIterator::new(accounts); let authority = iter.next_signer("authority")?; let source = iter.next_mut("source_account")?; let destination = iter.next_mut("destination_account")?; let mint = iter.next_non_mut("mint")?; // Process transfer... Ok(()) } ``` -------------------------------- ### Multiple Optional Accounts Example Source: https://github.com/lightprotocol/light-protocol/blob/main/program-libs/account-checks/docs/PACKED_ACCOUNTS.md Illustrates processing multiple transfers where each transfer involves accounts identified by dynamic indices. ```APIDOC ## Multiple Optional Accounts ### Description This example demonstrates iterating through a list of dynamic account indices to process multiple operations, such as individual transfers. ### Usage ```rust struct TransferInstruction { mint_indices: Vec, amounts: Vec, } fn process_multi_transfer( accounts: &[A], instruction: TransferInstruction, ) -> Result<(), AccountError> { let packed = ProgramPackedAccounts { accounts }; for (i, &mint_index) in instruction.mint_indices.iter().enumerate() { let mint = packed.get_u8(mint_index, &format!("mint_{{}}", i))?; // Process transfer for this mint // process_single_transfer(mint, instruction.amounts[i])?; } Ok(()) } ``` ``` -------------------------------- ### Create Mint Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/token-sdk/README.md Provides instructions for creating a new mint. ```APIDOC ## Create Mint ### Description Creates a new mint account. ### Instruction Builder [`CreateMint`](instruction::CreateMint) ### CPI Builder [`CreateMintCpi`](instruction::CreateMintCpi) ``` -------------------------------- ### Build the Project Source: https://github.com/lightprotocol/light-protocol/blob/main/README.md Executes the build script to compile the project. ```bash ./scripts/build.sh ``` -------------------------------- ### Zero-Copy Account PDA Initialization Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/accounts/pda.md Example of initializing a zero-copy PDA using `AccountLoader`. It requires the `zero_copy` keyword in `#[light_account]` and the data type must implement `bytemuck::Pod` and `bytemuck::Zeroable`. ```rust #[derive(AnchorSerialize, AnchorDeserialize)] pub struct CreateZcParams { pub create_accounts_proof: CreateAccountsProof, pub owner: Pubkey, } #[derive(Accounts, LightAccounts)] #[instruction(params: CreateZcParams)] pub struct CreateZc<'info> { #[account(mut)] pub fee_payer: Signer<'info>, pub compression_config: Account<'info, CompressionConfig>, #[account(mut)] pub pda_rent_sponsor: Account<'info, RentSponsor>, // Zero-copy PDA with Pod serialization - requires zero_copy keyword #[account(init, payer = fee_payer, space = 8 + core::mem::size_of::(), seeds = [b"zc_record", params.owner.as_ref()], bump)] #[light_account(init, zero_copy)] pub zc_record: AccountLoader<'info, ZcRecord>, pub system_program: Program<'info, System>, } ``` -------------------------------- ### Forester CLI Commands Source: https://github.com/lightprotocol/light-protocol/blob/main/forester/README.md The Forester service can be controlled via CLI commands. Available commands include start, status, health, and dashboard. ```bash forester ``` -------------------------------- ### Seed Provider Trait Implementation Source: https://github.com/lightprotocol/light-protocol/blob/main/sdk-libs/macros/docs/light_program/architecture.md Shows an example implementation of the PdaSeedDerivation trait for deriving PDA seeds with accounts. This is used for decompression logic. ```rust impl<'info, P: Params> PdaSeedDerivation<'info, UserRecordCtxSeeds, P> for UserRecord<'info, T> { fn derive_pda_seeds_with_accounts( &self, seeds: &UserRecordCtxSeeds, _params: P, ) -> Result<(Vec>, Pubkey), ProgramError> { Ok((seeds.to_seeds(), self.key())) } } ```