### RPC Connection Setup Source: https://github.com/lightprotocol/docs-v2/blob/main/api-reference/json-rpc-methods/overview.mdx Demonstrates how to establish an RPC connection using the stateless.js library, with examples for both Mainnet and Devnet. ```APIDOC ## Create an RPC connection ### Description Establish an RPC connection to interact with Solana and Photon RPC endpoints. This example uses Helius. ### Usage ```typescript import { createRpc, Rpc } from '@lightprotocol/stateless.js'; // For Mainnet const MAINNET_RPC_ENDPOINT = 'https://mainnet.helius-rpc.com?api-key=YOUR_KEY'; const mainnetConnection: Rpc = createRpc(MAINNET_RPC_ENDPOINT, MAINNET_RPC_ENDPOINT); // For Devnet const DEVNET_RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; const devnetConnection: Rpc = createRpc(DEVNET_RPC_ENDPOINT, DEVNET_RPC_ENDPOINT); ``` ### Parameters - `RPC_ENDPOINT`: The URL for the Helius RPC endpoint (Mainnet or Devnet). - `api-key`: Your Helius API key. ``` -------------------------------- ### Setup Environment Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-tokens/token-2022.mdx Sets up the local environment for development. This typically involves configuring environment variables and ensuring necessary tools are installed. ```bash solana config set --url solana config set --keypair ~/.config/solana/id.json ``` -------------------------------- ### Install Dependencies Source: https://github.com/lightprotocol/docs-v2/blob/main/api-reference/json-rpc-methods/getvalidityproof.mdx Install the necessary libraries for using the Light Protocol's stateless SDK and Solana web3.js. ```bash npm install @lightprotocol/stateless.js @solana/web3.js ``` -------------------------------- ### Install zk-compression-cli Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-pdas/guides/client-guide.mdx Install the zk-compression-cli globally using npm. ```bash npm i -g @lightprotocol/zk-compression-cli ``` -------------------------------- ### Install Light Protocol Packages with npm Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/full-setup.mdx Use npm to install the stateless.js and compressed-token packages in your working directory. Also, install the zk-compression-cli globally. ```bash npm install @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/compressed-token@^0.23.0 ``` ```bash npm install -g @lightprotocol/zk-compression-cli ``` -------------------------------- ### Compress SPL Token Accounts Guide Source: https://github.com/lightprotocol/docs-v2/blob/main/resources/legacy-compressed-tokens.mdx Provides a link to a GitHub repository containing an example of how to compress SPL token accounts. This is useful for saving rent costs for users. ```html ``` -------------------------------- ### Install Dependencies Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-tokens/token-2022.mdx Installs necessary dependencies for the project. Run this command in your terminal. ```bash npm install --save-dev @solana/web3.js @solana/spl-token @solana/spl-token-2022 @solana/spl-token-sdk @solana/compress-program @solana/compress-client ``` -------------------------------- ### Install zk-compression-cli with pnpm Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/versions/cli-install-0.28.0-beta.3.mdx Use this command to install the zk-compression-cli globally using pnpm. ```bash pnpm add -g @lightprotocol/zk-compression-cli ``` -------------------------------- ### Install SDK 2.0 Packages with npm, yarn, or pnpm Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/full-setup.mdx Install the stateless.js and token-interface packages using your preferred package manager. The zk-compression-cli is installed globally. ```bash # npm npm install @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/token-interface@^0.1.2 # yarn yarn add @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/token-interface@^0.1.2 # pnpm pnpm add @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/token-interface@^0.1.2 ``` ```bash npm install -g @lightprotocol/zk-compression-cli ``` -------------------------------- ### Install SDK 2.0 (Token Interface) Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/toolkits-setup.mdx Use this command to install the token-interface SDK for version 0.1.2 and stateless.js for version 0.23.0. ```bash npm install @lightprotocol/token-interface@^0.1.2 \ @lightprotocol/stateless.js@^0.23.0 ``` -------------------------------- ### Install SDK 2.0 Packages Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/welcome-page-install.mdx Install the stateless.js and token-interface packages for SDK 2.0 using npm, yarn, or pnpm. ```bash # npm npm install @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/token-interface@^0.1.2 # yarn yarn add @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/token-interface@^0.1.2 # pnpm pnpm add @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/token-interface@^0.1.2 ``` -------------------------------- ### Install Dependencies Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-tokens/overview.mdx Installs the necessary dependencies for working with compressed tokens. This is a prerequisite for setting up your developer environment. ```bash npm install --save @solana/web3.js @solana/spl-token @solana/spl-token-2022 @solana/compressed-nft npm install --save-dev @solana/web3.js @solana/spl-token @solana/spl-token-2022 @solana/compressed-nft ``` -------------------------------- ### Install Light Protocol Packages with pnpm Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/full-setup.mdx Use pnpm to install the stateless.js and compressed-token packages in your working directory. Also, install the zk-compression-cli globally. ```bash pnpm add @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/compressed-token@^0.23.0 ``` ```bash pnpm add -g @lightprotocol/zk-compression-cli ``` -------------------------------- ### Install zk-compression-cli with yarn Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/versions/cli-install-0.28.0-beta.3.mdx Use this command to install the zk-compression-cli globally using yarn. ```bash yarn global add @lightprotocol/zk-compression-cli ``` -------------------------------- ### Install Solana CLI Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/development-environment-setup.mdx Installs the Solana CLI toolchain. Ensure you have curl installed. ```bash sh -c "$(curl -sSfL https://release.solana.com/v2.2.15/install)" ``` -------------------------------- ### Burn Compressed Account Example Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/code-snippets/burn/typescript-client.mdx This test case demonstrates the complete process of creating and then burning a compressed account using Anchor and the Light Protocol's stateless.js library. It includes setup, account creation, verification, and the final burn operation. ```typescript import * as anchor from "@coral-xyz/anchor"; import { Program, web3 } from "@coral-xyz/anchor"; import { Burn } from "../target/types/burn"; import burnIdl from "../target/idl/burn.json"; import { bn, CompressedAccountWithMerkleContext, confirmTx, createRpc, deriveAddressV2, deriveAddressSeedV2, batchAddressTree, PackedAccounts, Rpc, sleep, SystemAccountMetaConfig, selectStateTreeInfo, TreeInfo, } from "@lightprotocol/stateless.js"; import * as assert from "assert"; const path = require("path"); const os = require("os"); require("dotenv").config(); const anchorWalletPath = path.join(os.homedir(), ".config/solana/id.json"); process.env.ANCHOR_WALLET = anchorWalletPath; describe("test-anchor-burn", () => { const burnProgram = anchor.workspace.Burn as Program; const burnCoder = new anchor.BorshCoder(burnIdl as anchor.Idl); it("burn compressed account", async () => { let signer = new web3.Keypair(); let rpc = createRpc( "http://127.0.0.1:8899", "http://127.0.0.1:8784", "http://127.0.0.1:3001", { commitment: "confirmed", }, ); let lamports = web3.LAMPORTS_PER_SOL; await rpc.requestAirdrop(signer.publicKey, lamports); await sleep(2000); const stateTreeInfos = await rpc.getStateTreeInfos(); const stateTreeInfo = selectStateTreeTreeInfo(stateTreeInfos); const addressTree = new web3.PublicKey(batchAddressTree); const messageSeed = new TextEncoder().encode("message"); const seed = deriveAddressSeedV2([messageSeed, signer.publicKey.toBytes()]); const address = deriveAddressV2( seed, addressTree, new web3.PublicKey(burnProgram.idl.address), ); // Step 1: Create compressed account with initial message const createTxId = await createCompressedAccount( rpc, addressTree, address, burnProgram, stateTreeInfo, signer, "Hello, compressed world!", ); console.log("Create Transaction ID:", createTxId); // Wait for indexer to process the create transaction let slot = await rpc.getSlot(); await rpc.confirmTransactionIndexed(slot); // Step 2: Get the created account and verify let compressedAccount = await rpc.getCompressedAccount(bn(address.toBytes())); let myAccount = burnCoder.types.decode( "MyCompressedAccount", compressedAccount.data.data, ); assert.strictEqual(myAccount.message, "Hello, compressed world!"); assert.ok(myAccount.owner.equals(signer.publicKey), "Owner should match signer public key"); console.log("Created message:", myAccount.message); // Step 3: Burn the account permanently const burnTxId = await burnCompressedAccount( rpc, compressedAccount, burnProgram, signer, "Hello, compressed world!", ); console.log("Burn Transaction ID:", burnTxId); // Wait for indexer to process the burn transaction slot = await rpc.getSlot(); await rpc.confirmTransactionIndexed(slot); // Step 4: Verify the account is burned (does not exist) try { await rpc.getCompressedAccount(bn(address.toBytes())); assert.fail("Expected account to not exist after burning"); } catch (error: any) { // Account should not exist after burn console.log("Verified account was burned"); } }); }); async function createCompressedAccount( rpc: Rpc, addressTree: anchor.web3.PublicKey, address: anchor.web3.PublicKey, program: anchor.Program, stateTreeInfo: TreeInfo, signer: anchor.web3.Keypair, message: string, ) { const proofRpcResult = await rpc.getValidityProofV0( [], [ { tree: addressTree, queue: addressTree, address: bn(address.toBytes()), }, ], ); const systemAccountConfig = new SystemAccountMetaConfig(program.programId); let remainingAccounts = new PackedAccounts(); remainingAccounts.addSystemAccountsV2(systemAccountConfig); const addressMerkleTreePubkeyIndex = remainingAccounts.insertOrGet(addressTree); const addressQueuePubkeyIndex = addressMerkleTreePubkeyIndex; const packedAddressTreeInfo = { rootIndex: proofRpcResult.rootIndices[0], addressMerkleTreePubkeyIndex, addressQueuePubkeyIndex, }; const outputStateTreeIndex = remainingAccounts.insertOrGet(stateTreeInfo.queue); let proof = { 0: proofRpcResult.compressedProof, }; const computeBudgetIx = web3.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000, }); let tx = await program.methods .createAccount(proof, packedAddressTreeInfo, outputStateTreeIndex, message) .accounts({ signer: signer.publicKey, }) .preInstructions([computeBudgetIx]) .remainingAccounts(remainingAccounts.toAccountMetas().remainingAccounts) .signers([signer]) .transaction(); tx.recentBlockhash = (await rpc.getRecentBlockhash()).blockhash; tx.sign(signer); ``` -------------------------------- ### Install Compressed Token SDK Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/toolkits-setup.mdx Use this command to install the compressed-token SDK for version 0.23.0. ```bash npm install @lightprotocol/compressed-token@^0.23.0 \ @lightprotocol/stateless.js@^0.23.0 ``` -------------------------------- ### Install Packages with npm Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/welcome-page-install.mdx Use this command to install the stateless.js and compressed-token packages in your project's working directory using npm. ```bash npm install @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/compressed-token@^0.23.0 ``` -------------------------------- ### Install Light Protocol Packages with yarn Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/full-setup.mdx Use yarn to install the stateless.js and compressed-token packages in your working directory. Also, install the zk-compression-cli globally. ```bash yarn add @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/compressed-token@^0.23.0 ``` ```bash yarn global add @lightprotocol/zk-compression-cli ``` -------------------------------- ### Install TypeScript Client SDKs Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-pdas/guides/client-guide.mdx Install the necessary TypeScript client SDKs for stateless.js, compressed-token, and web3.js using npm, yarn, or pnpm. ```bash npm install --save \ @lightprotocol/stateless.js \ @lightprotocol/compressed-token \ @solana/web3.js ``` ```bash yarn add \ @lightprotocol/stateless.js \ @lightprotocol/compressed-token \ @solana/web3.js ``` ```bash pnpm add \ @lightprotocol/stateless.js \ @lightprotocol/compressed-token \ @solana/web3.js ``` -------------------------------- ### Start Local Validator Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-pdas/guides/client-guide.mdx Start a local Solana test validator, photon indexer, and prover server on default ports. ```bash light test-validator ``` -------------------------------- ### Install TypeScript Dependencies Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/ai-prompts/cpi-programs/client-guide.mdx Installs necessary libraries for Light Protocol client development in TypeScript. ```bash npm install @lightprotocol/stateless.js @lightprotocol/compressed-token @solana/web3.js ``` -------------------------------- ### Group Pointer Example Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/extensions-table.mdx Example demonstrating the GroupPointer extension, which points a mint to the account that stores group configuration. ```typescript import { ExtensionType, GroupPointer, translateAddress } from "@solana/spl-token"; import { Connection, Keypair, PublicKey } from "@solana/web3.js"; async function main() { const connection = new Connection("http://127.0.0.1:8899", "confirmed"); const owner = Keypair.generate(); const mint = Keypair.generate(); const group = new PublicKey("99999999999999999999999999999999"); // Create a mint with the GroupPointer extension const mintArgs = { extensions: [ { extensionType: ExtensionType.GroupPointer, group: group, }, ], }; // ... (rest of the example code for creating the mint and token accounts) } main(); ``` -------------------------------- ### Install Packages with pnpm Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/welcome-page-install.mdx Use this command to install the stateless.js and compressed-token packages in your project's working directory using pnpm. ```bash pnpm add @lightprotocol/stateless.js@^0.23.0 \ @lightprotocol/compressed-token@^0.23.0 ``` -------------------------------- ### Token Metadata Example Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/extensions-table.mdx Example demonstrating the TokenMetadata extension, which stores token name, symbol, and URI directly on the mint. ```typescript import { ExtensionType, TokenMetadata, translateAddress } from "@solana/spl-token"; import { Connection, Keypair, PublicKey } from "@solana/web3.js"; async function main() { const connection = new Connection("http://127.0.0.1:8899", "confirmed"); const owner = Keypair.generate(); const mint = Keypair.generate(); // Create a mint with the TokenMetadata extension const mintArgs = { extensions: [ { extensionType: ExtensionType.TokenMetadata, name: "My Token", symbol: "MTK", uri: "https://example.com/token.json", }, ], }; // ... (rest of the example code for creating the mint and token accounts) } main(); ``` -------------------------------- ### Initialize Program with Compressed Accounts Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-pdas/overview.mdx Use the `light init` command to create a new Anchor-based project with compressed accounts and all required dependencies. For Pinocchio programs, manual configuration with `light-sdk-pinocchio` is necessary. ```bash light init testprogram ``` -------------------------------- ### POST /getCompressedAccountsByOwner Source: https://github.com/lightprotocol/docs-v2/blob/main/api-reference/json-rpc-methods/getcompressedaccountsbyowner.mdx Retrieve all compressed accounts owned by a specific address. RPC method guide with use cases, tips and examples. ```APIDOC ## POST /getCompressedAccountsByOwner ### Description Retrieve all compressed accounts owned by a specific address. This endpoint is part of the RPC method guide and includes use cases, tips, and examples. ### Method POST ### Endpoint /getCompressedAccountsByOwner ### Parameters #### Query Parameters - **owner** (string) - Required - The address of the owner whose compressed accounts are to be retrieved. ### Request Example ```json { "jsonrpc": "2.0", "id": "1", "method": "getCompressedAccountsByOwner", "params": [ "YOUR_OWNER_ADDRESS" ] } ``` ### Response #### Success Response (200) - **result** (array) - An array of compressed account objects. - **id** (string) - The ID of the request. - **jsonrpc** (string) - The JSON-RPC version. #### Response Example ```json { "jsonrpc": "2.0", "id": "1", "result": [ { "programId": "BPF1234567890abcdef1234567890abcdef1234567890", "account": "abcdef1234567890abcdef1234567890abcdef1234567890", "data": "some_base64_encoded_data", "owner": "YOUR_OWNER_ADDRESS", "executable": false, "lamports": 1000000 } ] } ``` ``` -------------------------------- ### POST /getCompressedAccount Source: https://github.com/lightprotocol/docs-v2/blob/main/api-reference/json-rpc-methods/getcompressedaccount.mdx Retrieve compressed account information by address or hash. RPC method guide with use cases, tips and examples. ```APIDOC ## POST /getCompressedAccount ### Description Retrieve compressed account information by address or hash. This endpoint serves as an RPC method guide, offering use cases, tips, and examples. ### Method POST ### Endpoint /getCompressedAccount ### Parameters #### Query Parameters - **address** (string) - Required - The address of the compressed account. - **hash** (string) - Required - The hash of the compressed account. ### Request Example ```json { "jsonrpc": "2.0", "method": "getCompressedAccount", "params": { "address": "your_account_address" }, "id": 1 } ``` ### Response #### Success Response (200) - **result** (object) - Contains the compressed account information. - **address** (string) - The address of the account. - **balance** (string) - The balance of the account. - **owner** (string) - The owner of the account. - **data** (string) - Additional data associated with the account. #### Response Example ```json { "jsonrpc": "2.0", "result": { "address": "compressed_account_address", "balance": "1000000", "owner": "owner_address", "data": "some_account_data" }, "id": 1 } ``` ``` -------------------------------- ### Set up Test Mint and Mint Compressed Tokens Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-tokens/wallet-integration.mdx This snippet demonstrates how to set up an RPC connection, load a filesystem wallet, create a new SPL mint with an interface PDA for compression, and then mint compressed tokens to the wallet. ```typescript import { Keypair } from "@solana/web3.js"; import { Rpc, confirmTx, createRpc } from '@lightprotocol/stateless.js'; import { createMint, mintTo } from '@lightprotocol/compressed-token'; import * as fs from 'fs'; import * as os from 'os'; // 1. Setup RPC connection and load filesystem wallet for mint operations // 2. Call createMint() to create SPL mint with interface PDA for compression // 3. Call mintTo() to mint compressed tokens to filesystem wallet const connection: Rpc = createRpc(); // defaults to localhost:8899 // Load wallet from filesystem const walletPath = `${os.homedir()}/.config/solana/id.json`; const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); const mintKeypair = Keypair.generate(); (async() => { // Fund payer with SOL await connection.requestAirdrop(payer.publicKey, 1e9); await new Promise(resolve => setTimeout(resolve, 1000)); // Create SPL mint with interface PDA for compression const { mint, transactionSignature } = await createMint( connection, payer, payer.publicKey, // mint authority 9, mintKeypair, ); console.log(`Mint address: ${mint.toString()}`); console.log(`Transaction: ${transactionSignature}`); // Mint compressed tokens to payer const mintToTxId = await mintTo( connection, payer, mint, // SPL mint with interface PDA for compression payer.publicKey, // recipient address payer, 10e9, ); console.log(`\nMinted ${10e9 / 1e9} compressed token`); console.log(`Transaction: ${mintToTxId}`); })(); ``` -------------------------------- ### Install Agent Skills Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/agent-skill-streaming.mdx Use the data-streaming agent skill to add Laserstream support to your project. Ensure you have the necessary setup for agent skills. ```javascript import InstallAgentSkills from "/snippets/setup/install-agent-skills.mdx"; ``` -------------------------------- ### Full v2 Client Example Source: https://github.com/lightprotocol/docs-v2/blob/main/resources/migration-v1-to-v2.mdx Demonstrates the complete process of building PackedAccounts, fetching validity proofs, and packing tree information for v2 client-side operations. ```rust use light_client::rpc::{LightClient, LightClientConfig, Rpc, Indexer}; use light_sdk:: address::v2::derive_address, instruction::{PackedAccounts, SystemAccountMetaConfig}, ; // 1. Build PackedAccounts with v2 system accounts let config = SystemAccountMetaConfig::new(YOUR_PROGRAM_ID); let mut packed = PackedAccounts::default(); packed.add_system_accounts_v2(config)?; // 2. Fetch validity proof let address_tree = rpc.get_address_tree_v2(); let (address, _) = derive_address(&[b"my_seed", &id], &address_tree.tree, &YOUR_PROGRAM_ID); let rpc_result = rpc .get_validity_proof( vec![], vec![AddressWithTree { address, tree: address_tree.tree }], None, ) .await? .value; // 3. Pack tree infos into remaining accounts let tree_infos = rpc_result.pack_tree_infos(&mut packed); let address_tree_info = tree_infos.address_trees[0]; // 4. Pack output state tree let state_tree = rpc.get_random_state_tree_info()?; let output_state_tree_index = state_tree.pack_output_tree_index(&mut packed)?; // 5. Convert to account metas for the instruction let (remaining_accounts, _system_offset, _packed_offset) = packed.to_account_metas(); ``` -------------------------------- ### Install General Agent Skills Source: https://github.com/lightprotocol/docs-v2/blob/main/ai-tools/agent-skills.mdx Use this command to add general agent skills for Light Protocol. This is the starting point for building with AI agents. ```bash npx skills add https://zkcompression.com ``` -------------------------------- ### Set Up Developer Environment Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-tokens/overview.mdx Provides instructions for setting up your developer environment, including necessary tools and configurations for compressed token development. ```jsx import { WalletAdapterNetwork } from "@solana/wallet-adapter-base"; import { ConnectionProvider, WalletProvider } from "@solana/wallet-adapter-react"; import { PhantomWalletAdapter } from "@solana/wallet-adapter-wallets"; import { useMemo } from "react"; const App = ({ children }) => { const network = WalletAdapterNetwork.Devnet; const wallets = useMemo(() => [ new PhantomWalletAdapter(), ], [network]); return ( {children} ); }; export default App; ``` -------------------------------- ### POST /getCompressedTokenAccountsByOwner Source: https://github.com/lightprotocol/docs-v2/blob/main/api-reference/json-rpc-methods/getcompressedtokenaccountsbyowner.mdx Retrieve compressed token accounts owned by a specific address. This endpoint is part of the RPC method guide and includes use cases, tips, and examples. ```APIDOC ## POST /getCompressedTokenAccountsByOwner ### Description Retrieve compressed token accounts owned by a specific address. RPC method guide with use cases, tips and examples. ### Method POST ### Endpoint /getCompressedTokenAccountsByOwner ``` -------------------------------- ### Generate Validity Proof with TypeScript Source: https://github.com/lightprotocol/docs-v2/blob/main/api-reference/json-rpc-methods/getvalidityproof.mdx This TypeScript example demonstrates how to generate a validity proof for compressed accounts using the getValidityProof RPC method. Ensure you have installed the dependencies and replaced placeholder API keys and public keys. ```typescript import { Rpc, createRpc, bn } from '@lightprotocol/stateless.js'; import { PublicKey } from '@solana/web3.js'; async function generateValidityProof(): Promise { const connection: Rpc = createRpc( 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' ); try { // Get compressed accounts const owner = new PublicKey('OWNER_PUBLIC_KEY_HERE'); const accounts = await connection.getCompressedAccountsByOwner(owner); if (accounts.items.length === 0) { console.log('No compressed accounts found'); return; } // Generate validity proof const hashes = accounts.items.slice(0, 2).map(acc => bn(acc.hash)); const validityProof = await connection.getValidityProof(hashes); console.log('Validity Proof Generated:'); console.log(` Accounts: ${hashes.length}`); console.log(` Roots: ${validityProof.roots.length}`); console.log(` Root Indices: ${validityProof.rootIndices.length} elements`); console.log(` Leaf Indices: ${validityProof.leafIndices.length} elements`); // Ready for use in transactions console.log(' Proof ready for compressed transactions'); } catch (error: unknown) { console.error('Error generating validity proof:', error); } } generateValidityProof(); ``` -------------------------------- ### Get Signatures for Owner Interface Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/code-snippets/payments/verify/get-history.mdx Use this snippet to retrieve all transaction signatures associated with a specific owner's public key. Ensure you have the necessary Solana Web3.js and Light Protocol Stateless.js libraries installed and imported. ```typescript import { PublicKey } from "@solana/web3.js"; import { createRpc } from "@lightprotocol/stateless.js"; const rpc = createRpc(); const owner = new PublicKey("YOUR_OWNER_ADDRESS"); const result = await rpc.getSignaturesForOwnerInterface(owner); console.log("Signatures:", result.signatures.length); ``` -------------------------------- ### Initialize Light Client (Rust) Source: https://github.com/lightprotocol/docs-v2/blob/main/resources/migration-v1-to-v2.mdx Configure and initialize the LightClient with RPC and Photon URLs, and an API key. ```rust use light_client::rpc::{LightClient, LightClientConfig, Rpc}; let rpc_url = "https://mainnet.helius-rpc.com/?api-key=YOUR_KEY".to_string(); let photon_url = "https://mainnet.helius-rpc.com".to_string(); let api_key = "YOUR_KEY".to_string(); let config = LightClientConfig::new(rpc_url, Some(photon_url), Some(api_key)); let mut rpc = LightClient::new(config).await?; ``` -------------------------------- ### Setup RPC and Imports Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-tokens/privy.mdx Connect to an RPC endpoint that supports ZK Compression and import necessary functions from @lightprotocol/stateless.js and @lightprotocol/compressed-token. ```typescript import { createRpc } from "@lightprotocol/stateless.js"; import { transfer, compress, decompress, selectMinCompressedTokenAccountsForTransfer, } from "@lightprotocol/compressed-token"; const rpc = createRpc(RPC_ENDPOINT); ``` -------------------------------- ### Approve, Check, and Revoke Delegate Permissions for Compressed Tokens Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/code-snippets/payments/spend-permissions/delegate-full-flow.mdx This TypeScript example demonstrates how to manage delegate permissions for compressed tokens. It first approves a delegate with a specified allowance, then checks the account's delegation status, and finally revokes all delegate permissions. Ensure you have the necessary setup from '../setup.js' and the '@lightprotocol/compressed-token' library imported. ```typescript import { Keypair } from "@solana/web3.js"; import { getAtaInterface, approveInterface, revokeInterface, } from "@lightprotocol/compressed-token/unified"; import { rpc, payer, setup } from "../setup.js"; (async function () { const { mint, senderAta } = await setup(); // 1. Owner approves delegate to spend up to 500,000,000 tokens const delegate = Keypair.generate(); const approveTx = await approveInterface( rpc, payer, senderAta, mint, delegate.publicKey, 500_000_000, payer ); console.log("1. Approved delegate:", delegate.publicKey.toBase58()); console.log(" Allowance: 500,000,000 tokens"); console.log(" Tx:", approveTx); // 2. Check delegation status const account = await getAtaInterface( rpc, senderAta, payer.publicKey, mint ); console.log("\n2. Account status after approval:"); console.log( " Delegate:", account.parsed.delegate?.toBase58() ?? "none" ); console.log( " Delegated amount:", account.parsed.delegatedAmount.toString() ); console.log(" Account balance:", account.parsed.amount.toString()); // 3. Owner revokes all delegate permissions const revokeTx = await revokeInterface(rpc, payer, senderAta, mint, payer); console.log("\n3. Revoked all delegate permissions"); console.log(" Tx:", revokeTx); // 4. Verify delegate is removed const afterRevoke = await getAtaInterface( rpc, senderAta, payer.publicKey, mint ); console.log("\n4. Account status after revoke:"); console.log( " Delegate:", afterRevoke.parsed.delegate?.toBase58() ?? "none" ); console.log(" Balance:", afterRevoke.parsed.amount.toString()); })(); ``` -------------------------------- ### Install Airdrop Dependencies Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/ai-prompts/toolkits/airdrop.mdx Installs necessary npm packages for compressed tokens and stateless operations. Ensure you have Node.js and npm installed. ```bash npm install @lightprotocol/compressed-token @lightprotocol/stateless.js @solana/spl-token ``` -------------------------------- ### Create Mint Instruction Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/migration-reference/cpi/create-mint.mdx Use this snippet to create a new mint with specified parameters. Ensure all required accounts and configurations are provided. ```rust use light_token::instruction::CreateMintCpi; CreateMintCpi { mint_seed: mint_seed.clone(), authority: authority.clone(), payer: payer.clone(), address_tree: address_tree.clone(), output_queue: output_queue.clone(), compressible_config: compressible_config.clone(), mint: mint.clone(), rent_sponsor: rent_sponsor.clone(), system_accounts, cpi_context: None, cpi_context_account: None, params, } .invoke()? ``` -------------------------------- ### Build Anchor Program Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-pdas/overview.mdx After initializing your program, navigate to the project directory and use `anchor build` to compile your Solana program. Stack offset warnings are expected and do not prevent compilation. ```bash anchor build # Success: Finished `release` profile [optimized] target(s), after compiling. # Note: Stack offset warnings are expected and don't prevent compilation ``` -------------------------------- ### Initialize Light Client Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/migration-reference/rpc/create-connection-rust.mdx Instantiate a new LightClient with the provided RPC URL. Ensure the RPC URL is valid before proceeding. ```rust use light_client::rpc::{LightClient, LightClientConfig, Rpc}; let rpc = LightClient::new( LightClientConfig::new(rpc_url.to_string(), None, None) ).await?; ``` -------------------------------- ### Verify Light CLI Installation Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/development-environment-setup.mdx Checks if the Light CLI was installed correctly by displaying its version number. ```bash light --version ``` -------------------------------- ### Create Token Account Instruction Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/migration-reference/rust/create-token-account.mdx Use this to create a new token account. Ensure all required public keys (payer, account, mint, owner) are correctly provided. ```rust use light_token::instruction::CreateTokenAccount; let ix = CreateTokenAccount::new( payer.pubkey(), account.pubkey(), mint, owner, ) .instruction()?; ``` -------------------------------- ### Metadata Pointer Example Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/extensions-table.mdx Example demonstrating the MetadataPointer extension, which points a mint to the account storing its metadata. ```typescript import { ExtensionType, TokenMetadata, translateAddress } from "@solana/spl-token"; import { Connection, Keypair, PublicKey } from "@solana/web3.js"; async function main() { const connection = new Connection("http://127.0.0.1:8899", "confirmed"); const owner = Keypair.generate(); const mint = Keypair.generate(); // Create a mint with the MetadataPointer extension const mintArgs = { extensions: [ { extensionType: ExtensionType.MetadataPointer, authority: owner.publicKey, metadata: new PublicKey("99999999999999999999999999999999"), }, ], }; // ... (rest of the example code for creating the mint and token accounts) } main(); ``` -------------------------------- ### TypeScript: Manually Fetch Proof and Build Instruction Source: https://github.com/lightprotocol/docs-v2/blob/main/compressed-pdas/nullifier-pda.mdx Manually fetch a proof using `fetchProof` and then build the nullifier instruction with `buildInstruction`. This method is useful if you need more control over the proof fetching process. Combine the instruction with your transaction. ```typescript import { fetchProof, buildInstruction } from "@lightprotocol/nullifier-program"; // Step 1: Fetch proof const proofResult = await fetchProof(rpc, id); // Step 2: Build instruction const nullifierIx = buildInstruction(payer.publicKey, id, proofResult); // Combine with your transaction const tx = new Transaction().add( nullifierIx, // your main instruction SystemProgram.transfer({ fromPubkey: payer.publicKey, toPubkey: recipient, lamports: 1_000_000, }) ); ``` -------------------------------- ### Add Dependencies for Account Burn Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/ai-prompts/cpi-programs/burn.mdx Add the necessary SDK and framework dependencies to your project. Use `light-sdk` for the Light Protocol and either `anchor-lang` for Anchor or `solana-program` and `borsh` for Native Rust. ```bash cargo add light-sdk@0.23 # For Anchor: # anchor add anchor-lang@0.31 # For Native Rust: # cargo add solana-program@2.2 --features no-entrypoint # cargo add borsh@0.10 ``` -------------------------------- ### Create and Close Compressed Account with Anchor Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/code-snippets/close/typescript-client.mdx Demonstrates the process of creating and then closing a compressed account using Anchor and the Light Protocol's stateless.js library. It includes setting up the environment, airdropping funds, creating the account, verifying its contents, and finally closing it. Ensure the RPC endpoint and relevant configurations are correctly set. ```typescript import * as anchor from "@coral-xyz/anchor"; import { Program, web3 } from "@coral-xyz/anchor"; import { Close } from "../target/types/close"; import closeIdl from "../target/idl/close.json"; import { bn, CompressedAccountWithMerkleContext, confirmTx, createRpc, deriveAddressV2, deriveAddressSeedV2, batchAddressTree, PackedAccounts, Rpc, sleep, SystemAccountMetaConfig, selectStateTreeInfo, TreeInfo, } from "@lightprotocol/stateless.js"; import * as assert from "assert"; const path = require("path"); const os = require("os"); require("dotenv").config(); const anchorWalletPath = path.join(os.homedir(), ".config/solana/id.json"); process.env.ANCHOR_WALLET = anchorWalletPath; describe("test-anchor-close", () => { const closeProgram = anchor.workspace.Close as Program; const closeCoder = new anchor.BorshCoder(closeIdl as anchor.Idl); it("close compressed account", async () => { let signer = new web3.Keypair(); let rpc = createRpc( "http://127.0.0.1:8899", "http://127.0.0.1:8784", "http://127.0.0.1:3001", { commitment: "confirmed", }, ); let lamports = web3.LAMPORTS_PER_SOL; await rpc.requestAirdrop(signer.publicKey, lamports); await sleep(2000); const stateTreeInfos = await rpc.getStateTreeInfos(); const stateTreeInfo = selectStateTreeInfo(stateTreeInfos); const addressTree = new web3.PublicKey(batchAddressTree); const messageSeed = new TextEncoder().encode("message"); const seed = deriveAddressSeedV2([messageSeed, signer.publicKey.toBytes()]); const address = deriveAddressV2( seed, addressTree, new web3.PublicKey(closeProgram.idl.address), ); const createTxId = await createCompressedAccount( rpc, addressTree, address, closeProgram, stateTreeInfo, signer, "Hello, compressed world!", ); console.log("Create Transaction ID:", createTxId); // Wait for indexer to process the create transaction let slot = await rpc.getSlot(); await rpc.confirmTransactionIndexed(slot); let compressedAccount = await rpc.getCompressedAccount(bn(address.toBytes())); let myAccount = closeCoder.types.decode( "MyCompressedAccount", compressedAccount.data.data, ); assert.strictEqual(myAccount.message, "Hello, compressed world!"); assert.ok(myAccount.owner.equals(signer.publicKey), "Owner should match signer public key"); console.log("Created message:", myAccount.message); const closeTxId = await closeCompressedAccount( rpc, compressedAccount, closeProgram, stateTreeInfo, signer, "Hello, compressed world!", ); console.log("Close Transaction ID:", closeTxId); // Wait for indexer to process the close transaction slot = await rpc.getSlot(); await rpc.confirmTransactionIndexed(slot); // After closing, the account exists with zero data. // Verify the account was closed by checking that data.data is empty. const closedAccount = await rpc.getCompressedAccount(bn(address.toBytes())); assert.ok( closedAccount.data.data === null || (Buffer.isBuffer(closedAccount.data.data) && closedAccount.data.data.length === 0), "Closed account should have null or empty data.data" ); console.log("Verified account was closed (data.data is empty as expected)"); }); }); async function createCompressedAccount( rpc: Rpc, addressTree: anchor.web3.PublicKey, address: anchor.web3.PublicKey, program: anchor.Program, stateTreeInfo: TreeInfo, signer: anchor.web3.Keypair, message: string, ) { const proofRpcResult = await rpc.getValidityProofV0( [], [ { tree: addressTree, queue: addressTree, address: bn(address.toBytes()), }, ], ); const systemAccountConfig = new SystemAccountMetaConfig(program.programId); let remainingAccounts = new PackedAccounts(); remainingAccounts.addSystemAccountsV2(systemAccountConfig); const addressMerkleTreePubkeyIndex = remainingAccounts.insertOrGet(addressTree); const addressQueuePubkeyIndex = addressMerkleTreePubkeyIndex; const packedAddressTreeInfo = { rootIndex: proofRpcResult.rootIndices[0], addressMerkleTreePubkeyIndex, addressQueuePubkeyIndex, }; const outputStateTreeIndex = remainingAccounts.insertOrGet(stateTreeInfo.queue); let proof = { 0: proofRpcResult.compressedProof, }; const computeBudgetIx = web3.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000, }); let tx = await program.methods .createAccount(proof, packedAddressTreeInfo, outputStateTreeIndex, message) .accounts({ signer: signer.publicKey, }) .preInstructions([computeBudgetIx]) .remainingAccounts(remainingAccounts.toAccountMetas().remainingAccounts) .signers([signer]) .transaction(); } ``` -------------------------------- ### Install Agent Skills Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/setup/agent-skill-router.mdx Use the light-sdk agent skill to integrate rent-free markets into your router. Ensure the light-sdk is installed. ```mdx import InstallAgentSkills from "/snippets/setup/install-agent-skills.mdx"; Use the [light-sdk](https://github.com/Lightprotocol/skills/tree/main/skills/light-sdk) agent skill to integrate rent-free markets into your router: ``` -------------------------------- ### Token Group Member Example Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/extensions-table.mdx Example demonstrating the TokenGroupMember extension, which stores group member configuration directly on the mint. ```typescript import { ExtensionType, TokenGroupMember, translateAddress } from "@solana/spl-token"; import { Connection, Keypair, PublicKey } from "@solana/web3.js"; async function main() { const connection = new Connection("http://127.0.0.1:8899", "confirmed"); const owner = Keypair.generate(); const mint = Keypair.generate(); const group = new PublicKey("99999999999999999999999999999999"); // Create a mint with the TokenGroupMember extension const mintArgs = { extensions: [ { extensionType: ExtensionType.TokenGroupMember, group: group, member: mint.publicKey, // The mint itself is the member }, ], }; // ... (rest of the example code for creating the mint and token accounts) } main(); ``` -------------------------------- ### Merge Token Accounts Example Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/code-snippets/compressed-token/merge-token-accounts/action.mdx This example demonstrates how to set up a mint, mint tokens to an owner multiple times, and then merge all of the owner's token accounts for that mint into a single account. Ensure you have your API key set in your environment variables for Devnet. ```typescript import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { createMint, mintTo, mergeTokenAccounts } from "@lightprotocol/compressed-token"; import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: // const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) ) ); (async function () { // devnet: const rpc = createRpc(RPC_URL); // localnet: // const rpc = createRpc(); // Setup: Create mint and mint multiple times to create multiple accounts const { mint } = await createMint(rpc, payer, payer.publicKey, 9); const owner = Keypair.generate(); await mintTo(rpc, payer, mint, owner.publicKey, payer, bn(100_000_000)); await mintTo(rpc, payer, mint, owner.publicKey, payer, bn(200_000_000)); await mintTo(rpc, payer, mint, owner.publicKey, payer, bn(300_000_000)); // Merge all accounts for owner const tx = await mergeTokenAccounts(rpc, payer, mint, owner); console.log("Mint:", mint.toBase58()); console.log("Tx:", tx); })(); ``` -------------------------------- ### Add Dependencies for CPI Programs Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/ai-prompts/cpi-programs/update.mdx Add the necessary SDKs for your CPI program. Use `light-sdk` for Light Protocol functionalities. Include `anchor_lang` for Anchor framework or `solana-program` and `borsh` for Native Rust. ```bash cargo add light-sdk@0.23 # For Anchor: # cargo add anchor_lang@0.31 # For Native Rust: # cargo add solana-program@2.2 borsh@0.10 ``` -------------------------------- ### Interest Bearing Config Example Source: https://github.com/lightprotocol/docs-v2/blob/main/snippets/extensions-table.mdx Example demonstrating the InterestBearingConfig extension, which displays a UI-adjusted balance that accrues interest over time. ```typescript import { ExtensionType, InterestBearingConfig, translateAddress } from "@solana/spl-token"; import { Connection, Keypair, PublicKey } from "@solana/web3.js"; async function main() { const connection = new Connection("http://127.0.0.1:8899", "confirmed"); const owner = Keypair.generate(); const mint = Keypair.generate(); // Create a mint with the InterestBearingConfig extension const mintArgs = { extensions: [ { extensionType: ExtensionType.InterestBearingConfig, interestBearingConfig: { rateAuthority: owner.publicKey, rate: 0, precision: 0, // ... other fields }, }, ], }; // ... (rest of the example code for creating the mint and token accounts) } main(); ```