diff --git a/zk-compression-docs/mintlify-docs/LICENSE b/zk-compression-docs/mintlify-docs/LICENSE new file mode 100644 index 0000000..5411374 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Mintlify + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/zk-compression-docs/mintlify-docs/README.md b/zk-compression-docs/mintlify-docs/README.md new file mode 100644 index 0000000..055c983 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/README.md @@ -0,0 +1,43 @@ +# Mintlify Starter Kit + +Use the starter kit to get your docs deployed and ready to customize. + +Click the green **Use this template** button at the top of this repo to copy the Mintlify starter kit. The starter kit contains examples with + +- Guide pages +- Navigation +- Customizations +- API reference pages +- Use of popular components + +**[Follow the full quickstart guide](https://starter.mintlify.com/quickstart)** + +## Development + +Install the [Mintlify CLI](https://www.npmjs.com/package/mint) to preview your documentation changes locally. To install, use the following command: + +``` +npm i -g mint +``` + +Run the following command at the root of your documentation, where your `docs.json` is located: + +``` +mint dev +``` + +View your local preview at `http://localhost:3000`. + +## Publishing changes + +Install our GitHub app from your [dashboard](https://dashboard.mintlify.com/settings/organization/github-app) to propagate changes from your repo to your deployment. Changes are deployed to production automatically after pushing to the default branch. + +## Need help? + +### Troubleshooting + +- If your dev environment isn't running: Run `mint update` to ensure you have the most recent version of the CLI. +- If a page loads as a 404: Make sure you are running in a folder with a valid `docs.json`. + +### Resources +- [Mintlify documentation](https://mintlify.com/docs) diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/client-library.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/client-library.mdx new file mode 100644 index 0000000..8244cc2 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/client-library.mdx @@ -0,0 +1,4 @@ +--- +title: Client Library +description: Overview to Rust and Typescript client guides. Guides include step-by-step implementation and full code examples. +--- diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/create-a-program-with-compressed-pdas.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/create-a-program-with-compressed-pdas.mdx new file mode 100644 index 0000000..8a7a33e --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/create-a-program-with-compressed-pdas.mdx @@ -0,0 +1,204 @@ +--- +title: Create a Program with Compressed PDAs +description: Overview to compressed PDA core features and guide for program development +--- + +Compressed PDAs provide full functionality of accounts at PDAs, without per-account rent cost. + +| Creation | Regular PDA Account | Compressed PDA | Cost Reduction | +| :------------- | :--------------------- | :---------------------- | :------------------ | +| 100-byte PDA | ~ 0.0016 SOL | **~ 0.00001 SOL** | ***160x*** | + +Compressed PDAs are derived using a specific program address and seed, like regular PDAs. Custom programs invoke the [Light System program](#user-content-fn-1)[^1] to create and update accounts, instead of the System program. + +#### Compressed PDAs at a Glance + + + + Create accounts at program-derived addresses without upfront rent exempt balance. + + + Persistent unique identification and program ownership. + + + CPI support between compressed and regular PDAs. + + + +## Start Building + +Developing with compressed PDAs works similar to regular PDAs and involves minimal setup: + +### Prerequisites + + +Required versions: + +* **Rust**: 1.86.0 or later +* **Solana CLI**: 2.2.15 +* **Anchor CLI**: 0.31.1 +* **Zk compression CLI**: 0.27.0 or later +* **Node.js**: 23.5.0 or later + + +**Install Solana CLI:** + +```bash +sh -c "$(curl -sSfL https://release.solana.com/v2.2.15/install)" +``` + +**Install Anchor CLI:** + +```bash +cargo install --git https://github.com/coral-xyz/anchor avm --force +avm install latest +avm use latest +``` + +**Install the Light CLI:** + +```bash +npm -g i @lightprotocol/zk-compression-cli +``` + +```bash +### verify installation +light --version +``` + +### Initialize your Program + +Instantiate a template Solana program with compressed accounts with all required dependencies. + +```bash +light init testprogram +``` + + +The `light init` command creates only Anchor-based projects . For Pinocchio programs, manually configure dependencies using `light-sdk-pinocchio`. + + + + +**Rust Crates** + +* `light-sdk` - Core SDK for compressed accounts in native and anchor programs +* `light-sdk-pinocchio` Core SDK for compressed accounts in pinocchio programs +* `light-client` - RPC client and indexer for interacting with compressed accounts +* `light-program-test` - Testing utilities for compressed programs. + +**TypeScript/JavaScript Packages** + +* `@lightprotocol/stateless.js` - Client library for interacting with compressed accounts +* `@lightprotocol/zk-compression-cli` - Command-line tools for ZK compression development + + + +### Build and Test + +Now `cd testprogram` and run: + +```bash +anchor build +# Success: Finished `release` profile [optimized] target(s), after compiling. +# Note: Stack offset warnings are expected and don't prevent compilation +``` + +```bash +cargo test-sbf + +# Success: test result: ok. 1 passed; 0 failed; 0 ignored +``` + +### Common Errors + + + +```shellscript +Fix: +In your terminal, run: +1. export CC=$(xcrun -find clang) +2. export SDKROOT=$(xcrun --show-sdk-path) +3. cargo clean +4. anchor build + + +Example log: +The following warnings were emitted during compilation: + +warning: blake3@1.5.1: In file included from c/blake3_neon.c:1: +warning: blake3@1.5.1: c/blake3_impl.h:4:10: fatal error: 'assert.h' file not found +warning: blake3@1.5.1: 4 | #include +warning: blake3@1.5.1: | ^~~~~~~~~~ +warning: blake3@1.5.1: 1 error generated. + +error: failed to run custom build command for `blake3 v1.5.1` + +Caused by: + process didn't exit successfully: `/Users/you/testprogram/target/release/build/blake3-ac41d29c2eabe052/build-script-build` (exit status: 1) + --- stdout + cargo:rerun-if-env-changed=CARGO_FEATURE_PURE + cargo:rerun-if-env-changed=CARGO_FEATURE_NO_NEON + cargo:rerun-if-env-changed=CARGO_FEATURE_NEON + cargo:rerun-if-env-changed=CARGO_FEATURE_NEON + cargo:rerun-if-env-changed=CARGO_FEATURE_NO_NEON + cargo:rerun-if-env-changed=CARGO_FEATURE_PURE + cargo:rustc-cfg=blake3_neon + OUT_DIR = Some(/Users/you/testprogram/target/release/build/blake3-735a4c71d985df30/out) + TARGET = Some(aarch64-apple-darwin) + OPT_LEVEL = Some(3) + HOST = Some(aarch64-apple-darwin) + cargo:rerun-if-env-changed=CC_aarch64-apple-darwin + CC_aarch64-apple-darwin = None + cargo:rerun-if-env-changed=CC_aarch64_apple_darwin + CC_aarch64_apple_darwin = None + cargo:rerun-if-env-changed=HOST_CC + HOST_CC = None + cargo:rerun-if-env-changed=CC + CC = Some(/Users/you/.local/share/solana/install/releases/1.18.22/solana-release/bin/sdk/sbf/dependencies/platform-tools/llvm/bin/clang) + RUSTC_WRAPPER = None + cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT + cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS + CRATE_CC_NO_DEFAULTS = None + DEBUG = Some(false) + cargo:rerun-if-env-changed=MACOSX_DEPLOYMENT_TARGET + MACOSX_DEPLOYMENT_TARGET = None + cargo:rerun-if-env-changed=CFLAGS_aarch64-apple-darwin + CFLAGS_aarch64-apple-darwin = None + cargo:rerun-if-env-changed=CFLAGS_aarch64_apple_darwin + CFLAGS_aarch64_apple_darwin = None + cargo:rerun-if-env-changed=HOST_CFLAGS + HOST_CFLAGS = None + cargo:rerun-if-env-changed=CFLAGS + CFLAGS = None + cargo:warning=In file included from c/blake3_neon.c:1: + cargo:warning=c/blake3_impl.h:4:10: fatal error: 'assert.h' file not found + cargo:warning= 4 | #include + cargo:warning= | ^~~~~~~~~~ + cargo:warning=1 error generated. + + --- stderr + + + error occurred: Command env -u IPHONEOS_DEPLOYMENT_TARGET "/Users/you/.local/share/solana/install/releases/1.18.22/solana-release/bin/sdk/sbf/dependencies/platform-tools/llvm/bin/clang" "-O3" "-ffunction-sections" "-fdata-sections" "-fPIC" "--target=arm64-apple-darwin" "-mmacosx-version-min=14.4" "-Wall" "-Wextra" "-std=c11" "-o" "/Users/you/testprogram/target/release/build/blake3-735a4c71d985df30/out/db3b6bfb95261072-blake3_neon.o" "-c" "c/blake3_neon.c" with args clang did not execute successfully (status code exit status: 1). +``` + + + +## Program Examples +| Example | Description | +|:---------|:------------| +| [basic-operations/anchor](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor) | Anchor programs to create, update, close, reinitialize and burn compressed accounts with Rust and TypeScript tests | +| [basic-operations/native-rust](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/native-rust) | Native Solana program implementation to create, update, close, reinitialize and burn compressed accounts with Rust tests | +| [Counter (Anchor)](https://github.com/Lightprotocol/program-examples/tree/main/counter/anchor) | Full compressed account lifecycle (create, increment, decrement, reset, close) using Anchor framework | +| [Counter (Native)](https://github.com/Lightprotocol/program-examples/tree/main/counter/native) | Native Solana program implementation with Rust tests | +| [Counter (Pinocchio)](https://github.com/Lightprotocol/program-examples/tree/main/counter/pinocchio) | Pinocchio implementation using light-sdk-pinocchio with Rust tests | +| [Create-and-Update](https://github.com/Lightprotocol/program-examples/tree/main/create-and-update) | Create new compressed accounts and update existing ones within a single instruction and one validity proof | +| [Read-Only](https://github.com/Lightprotocol/program-examples/tree/main/read-only) | Create compressed accounts and read them on-chain | +| [Account Comparison](https://github.com/Lightprotocol/program-examples/tree/main/account-comparison) | Compare compressed accounts with standard Solana accounts | +| [ZK-ID](https://github.com/Lightprotocol/program-examples/tree/main/zk-id) | Program that uses zero-knowledge proofs for identity verification with compressed accounts | + + +## Next Steps + +Start building with compressed accounts using our guides or program examples. diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/guides.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/guides.mdx new file mode 100644 index 0000000..da4539f --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/guides.mdx @@ -0,0 +1,84 @@ +--- +title: Guides +description: Overview and comparison of guides to create, update, close, reinitialize, and burn permanently compressed accounts. Guides include step-by-step implementation and full code examples. +sidebarTitle: "Overview" +--- + +## Guides Overview + +| Guide | Description | +| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| [Create Compressed Accounts](/compressed-pdas/guides/how-to-create-compressed-accounts) | Create compressed accounts with address | +| [Update Compressed Accounts](/compressed-pdas/guides/how-to-update-compressed-accounts) | Update compressed accounts | +| [Close Compressed Accounts](/compressed-pdas/guides/how-to-close-compressed-accounts) | Close compressed accounts, retain the address | +| [Reinitialize Compressed Accounts](/compressed-pdas/guides/how-to-reinitialize-compressed-accounts) | Reinitialize closed compressed accounts with the same address and new values | +| [Burn Compressed Accounts](/compressed-pdas/guides/how-to-burn-compressed-accounts) | Burn compressed accounts and their address permanently | + +## Complete Flow Overview + + + +
+ + ![](/images/Untitled.png) + +
+
+ + ![](/images/image-22.png) + +
+
+ +
+ + ![](/images/Untitled-1.png) + +
+
+ + ![](/images/image-20.png) + +
+
+ +
+ + ![](/images/Untitled-4.png) + +
+
+ + ![](/images/image-23.png) + +
+
+ +
+ + ![](/images/program-reinit-1.png) + +
+
+ + ![](/images/program-reinit.png) + +
+
+ +
+ + ![](/images/program-burn-1.png) + +
+
+ + ![](/images/program-burn.png) + +
+
+
+ +## Next Steps + +Create a compressed account. diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx new file mode 100644 index 0000000..47abf58 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-burn-compressed-accounts.mdx @@ -0,0 +1,580 @@ +--- +title: Burn Compressed Accounts +description: Guide to burn compressed accounts in Solana programs with full code examples. +--- + + +Compressed accounts are permanently burned via CPI to the Light System Program. + +Burning a compressed account + +* consumes the existing account hash, and +* produces no output state. +* A burned account cannot be reinitialized. + + +Find [full code examples at the end](/compressed-pdas/guides/how-to-burn-compressed-accounts#full-code-example) for Anchor and native Rust. + + +## Implementation Guide + +This guide will cover the components of a Solana program that burns compressed accounts.\ +Here is the complete flow to burn compressed accounts: + +
+ + ![](/images/program-burn-1.png) + +
+
+ + ![](/images/program-burn.png) + +
+ + + + + + + +**Dependencies** + +Add dependencies to your program. + + +```toml +[dependencies] +light-sdk = "0.16.0" +anchor_lang = "0.31.1" +``` + +```toml +[dependencies] +light-sdk = "0.16.0" +borsh = "0.10.0" +solana-program = "2.2" +``` + + +* The `light-sdk` provides macros, wrappers and CPI interface to create and interact with compressed accounts. +* Add the serialization library (`borsh` for native Rust, or use `AnchorSerialize`). + +**Constants** + +Set program address and derive the CPI authority PDA to call the Light System program. + + +```rust +declare_id!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +``` + +**`CPISigner`** is the configuration struct for CPI's to the Light System Program. + +* CPIs to the Light System program must be signed with a PDA derived by your program with the seed `b"authority"` +* `derive_light_cpi_signer!` derives the CPI signer PDA for you at compile time. + +**Compressed Account** + +Define your compressed account struct. + +\#\[event] // declared as event so that it is part of the idl.#\[derive( Clone, Debug, Default, LightDiscriminator)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,}#\[derive( Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator,)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,} + +You derive + +* the standard traits (`Clone`, `Debug`, `Default`), +* `borsh` or `AnchorSerialize` to serialize account data, and +* `LightDiscriminator` to implements a unique type ID (8 bytes) to distinguish account types. The default compressed account layout enforces a discriminator in its _own field_, [not the first 8 bytes of the data field](#user-content-fn-1)[^1]. + + +The traits listed above are required for `LightAccount`. `LightAccount` wraps `MyCompressedAccount` in Step 3 to set the discriminator and create the compressed account's data. + + + + + + + +Define the instruction data with the following parameters: + + + +```rust +pub fn burn_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + account_meta: CompressedAccountMetaBurn, + current_message: String, +) -> Result<()> +``` + + + +```rust +pub struct BurnInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMetaBurn, + pub current_account: MyCompressedAccount, +} +``` + + + +1. **Validity Proof** + +* Define `proof` to include the proof that the account exists in the state tree. +* Clients fetch a validity proof with `getValidityProof()` from an RPC provider that supports ZK Compression (Helius, Triton, ...). + +2. **Specify input state** + +* Define `account_meta: CompressedAccountMetaBurn` to reference the existing account for the Light System Program to nullify permanently: + * `tree_info: PackedStateTreeInfo`: References the existing account hash in the state tree. + * `address`: The account's derived address. + + +Burn does not specify an output state tree. `CompressedAccountMetaBurn` omits `output_state_tree_index` because no output state is created. + + +3. **Current account data** + +* Define fields to include the current account data passed by the client. +* This depends on your program logic. This example includes `current_message` (or `current_account` in Native Rust). + + + + +Burn the compressed account permanently with `LightAccount::new_burn()`. No account can be reinitialized at this address in the future. + + +`new_burn()` + +1. hashes the current account data as input state and +2. creates no output state to burn the account permanently. + + + + +```rust +let my_compressed_account = LightAccount::::new_burn( + &crate::ID, + &account_meta, + MyCompressedAccount { + owner: ctx.accounts.signer.key(), + message: current_message, + }, +)?; +``` + + + +```rust +let my_compressed_account = LightAccount::::new_burn( + &ID, + &instruction_data.account_meta, + instruction_data.current_account, +)?; +``` + + + +**Pass these parameters to `new_burn()`:** + +* `&program_id`: The program's ID that owns the compressed account. +* `&account_meta`: The `CompressedAccountMetaBurn` from instruction data (_Step 2_) that identifies the existing account for the Light System Program to nullify permanently. + * Anchor: Pass `&account_meta` directly + * Native Rust: Pass `&instruction_data.account_meta` +* Include the curent account data. + * Anchor: Build `MyCompressedAccount` with `owner` and `message`. + * Native Rust: Pass `instruction_data.current_account` directly. + +**The SDK creates:** + +* A `LightAccount` wrapper that marks the account as permanently burned with no output state. + + +`new_burn()` hashes the input state. The Light System Program verifies the input hash and nullifies it in _Step 4_. + + + + + +The Light System Program CPI burns the compressed account permanently. + + +The Light System Program + +* validates the account exists in state tree with the validity, +* nullifies the existing account hash, and +* creates no output state. + + + + +```rust +let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `ctx.accounts.signer.as_ref()`: the transaction signer +* `ctx.remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts` and passes it to the instruction. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + +```rust +let (signer, remaining_accounts) = accounts + .split_first(); + +let cpi_accounts = CpiAccounts::new( + signer, + remaining_accounts, + LIGHT_CPI_SIGNER +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `signer`: account that signs and pays for the transaction +* `remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts`. + * `split_first()` extracts the fee payer from the accounts array to separate it from the Light System Program accounts needed for the CPI. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + + +| | Name | Description | +|:---|:---|:---| +| 1 | Light System Program | Verifies validity proofs, compressed account ownership checks, CPIs the account compression program to update tree accounts | +| 2 | CPI Signer | - PDA to sign CPI calls from your program to Light System Program
- Verified by Light System Program during CPI
- Derived from your program ID | +| 3 | Registered Program PDA | - Access control to the Account Compression Program | +| 4 | Noop Program | - Logs compressed account state to Solana ledger. Only used in v1.
- Indexers parse transaction logs to reconstruct compressed account state | +| 5 | Account Compression Authority | Signs CPI calls from Light System Program to Account Compression Program | +| 6 | Account Compression Program | - Writes to state and address tree accounts
- Client and the account compression program do not interact directly. | +| 7 | Invoking Program | Your program's ID, used by Light System Program to:
- Derive the CPI Signer PDA
- Verify the CPI Signer matches your program ID
- Set the owner of created compressed accounts| +| 8 | System Program | Solana System Program to transfer lamports | +
+**Build the CPI instruction**: + +* `new_cpi()` initializes the CPI instruction with the `proof` to prove the account exists in the state tree _- defined in the Instruction Data (Step 2)._ +* `with_light_account` adds the `LightAccount` wrapper configured to burn the account _- defined in Step 3_. +* `invoke(light_cpi_accounts)` calls the Light System Program with `CpiAccounts`. +
+
+ +## Full Code Example + +The example programs below implement all steps from this guide. Make sure you have your [developer environment](https://www.zkcompression.com/compressed-pdas/create-a-program-with-compressed-pdas#start-building) set up first. + + +```bash +npm -g i @lightprotocol/zk-compression-cli@0.27.1-alpha.2 +light init testprogram +``` + + +For help with debugging, see the [Error Cheatsheet](https://www.zkcompression.com/resources/error-cheatsheet). + + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/burn). + + +```rust expandable +#![allow(unexpected_cfgs)] +#![allow(deprecated)] + +use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize}; +use light_sdk::{ + account::LightAccount, + address::v1::derive_address, + cpi::{v1::CpiAccounts, CpiSigner}, + derive_light_cpi_signer, + instruction::{account_meta::CompressedAccountMetaBurn, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; + +declare_id!("BJhPWQnD31mdo6739Mac1gLuSsbbwTmpgjHsW6shf6WA"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("BJhPWQnD31mdo6739Mac1gLuSsbbwTmpgjHsW6shf6WA"); + +#[program] +pub mod burn { + + use super::*; + use light_sdk::cpi::{ + v1::LightSystemProgramCpi, InvokeLightSystemProgram, LightCpiInstruction, + }; + + /// Setup: Creates a compressed account + pub fn create_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + address_tree_info: PackedAddressTreeInfo, + output_state_tree_index: u8, + message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let (address, address_seed) = derive_address( + &[b"message", ctx.accounts.signer.key().as_ref()], + &address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ErrorCode::AccountNotEnoughKeys)?, + &crate::ID, + ); + + let mut my_compressed_account = LightAccount::::new_init( + &crate::ID, + Some(address), + output_state_tree_index, + ); + + my_compressed_account.owner = ctx.accounts.signer.key(); + my_compressed_account.message = message.clone(); + + msg!( + "Created compressed account with message: {}", + my_compressed_account.message + ); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[address_tree_info.into_new_address_params_packed(address_seed)]) + .invoke(light_cpi_accounts)?; + + Ok(()) + } + + /// Burns a compressed account permanently + pub fn burn_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + account_meta: CompressedAccountMetaBurn, + current_message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let my_compressed_account = LightAccount::::new_burn( + &crate::ID, + &account_meta, + MyCompressedAccount { + owner: ctx.accounts.signer.key(), + message: current_message, + }, + )?; + + msg!("Burning compressed account permanently"); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; + + Ok(()) + } +} + +#[derive(Accounts)] +pub struct GenericAnchorAccounts<'info> { + #[account(mut)] + pub signer: Signer<'info>, +} + +#[event] +#[derive(Clone, Debug, Default, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} +``` + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/native/programs/burn). + + +```rust expandable +#![allow(unexpected_cfgs)] + +#[cfg(any(test, feature = "test-helpers"))] +pub mod test_helpers; + +use borsh::{BorshDeserialize, BorshSerialize}; +use light_macros::pubkey; +use light_sdk::{ + account::sha::LightAccount, + address::v1::derive_address, + cpi::{ + v1::{CpiAccounts, LightSystemProgramCpi}, + CpiSigner, InvokeLightSystemProgram, LightCpiInstruction, + }, + derive_light_cpi_signer, + error::LightSdkError, + instruction::{account_meta::CompressedAccountMetaBurn, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; +use solana_program::{ + account_info::AccountInfo, entrypoint, program_error::ProgramError, pubkey::Pubkey, +}; + +pub const ID: Pubkey = pubkey!("CFWrQ8za2yT1xH8yBjYvsDUCWnBH7vXtyVJwqoX5FcNg"); +pub const LIGHT_CPI_SIGNER: CpiSigner = derive_light_cpi_signer!("CFWrQ8za2yT1xH8yBjYvsDUCWnBH7vXtyVJwqoX5FcNg"); + +#[cfg(not(feature = "no-entrypoint"))] +entrypoint!(process_instruction); + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub enum InstructionType { + Create, + Burn, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct CreateInstructionData { + pub proof: ValidityProof, + pub address_tree_info: PackedAddressTreeInfo, + pub output_state_tree_index: u8, + pub message: String, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct BurnInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMetaBurn, + pub current_account: MyCompressedAccount, +} + +#[derive(Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} + +pub fn process_instruction( + _program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> Result<(), ProgramError> { + let (instruction_type, rest) = instruction_data + .split_first() + .ok_or(ProgramError::InvalidInstructionData)?; + + match InstructionType::try_from_slice(&[*instruction_type]) + .map_err(|_| ProgramError::InvalidInstructionData)? + { + InstructionType::Create => create(accounts, rest)?, + InstructionType::Burn => burn(accounts, rest)?, + } + + Ok(()) +} + +fn create(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> { + let instruction_data = + CreateInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?; + + let signer = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?; + + let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER + ); + + let (address, address_seed) = derive_address( + &[b"message", signer.key.as_ref()], + &instruction_data + .address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ProgramError::NotEnoughAccountKeys)?, + &ID, + ); + + let new_address_params = instruction_data + .address_tree_info + .into_new_address_params_packed(address_seed); + + let mut my_compressed_account = LightAccount::::new_init( + &ID, + Some(address), + instruction_data.output_state_tree_index, + ); + my_compressed_account.owner = *signer.key; + my_compressed_account.message = instruction_data.message; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[new_address_params]) + .invoke(light_cpi_accounts)?; + + Ok(()) +} + +fn burn(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> { + let instruction_data = + BurnInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?; + + let (signer, remaining_accounts) = accounts + .split_first() + .ok_or(ProgramError::InvalidAccountData)?; + + let cpi_accounts = CpiAccounts::new( + signer, + remaining_accounts, + LIGHT_CPI_SIGNER + ); + + let my_compressed_account = LightAccount::::new_burn( + &ID, // Now the burn program owns the account since it created it + &instruction_data.account_meta, + instruction_data.current_account, + )?; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(cpi_accounts)?; + + Ok(()) +} +``` + + + +## Next Steps + +Build a client for your program or get an overview on all compressed account operations. diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-close-compressed-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-close-compressed-accounts.mdx new file mode 100644 index 0000000..7fa3b36 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-close-compressed-accounts.mdx @@ -0,0 +1,582 @@ +--- +title: Close Compressed Accounts +description: Guide to close compressed accounts in Solana programs with full code examples. +--- + +Compressed accounts are closed via CPI to the Light System Program. + +Closing a compressed account + +* consumes the existing account hash, and +* produces a new account hash with zero values to mark it as closed. +* A closed compressed account [can be reinitialized](/compressed-pdas/guides/how-to-reinitialize-compressed-accounts). + + +Find [full code examples at the end](/compressed-pdas/guides/how-to-close-compressed-accounts#full-code-example) for Anchor and native Rust. + + +## Implementation Guide + +This guide will cover the components of a Solana program that closes compressed accounts. +Here is the complete flow to close compressed accounts: + +
+ + ![](/images/program-closes.png) + +
+
+ + ![](/images/program-close.png) + +
+ + + + + + + +**Dependencies** + +Add dependencies to your program. + + +```toml +[dependencies] +light-sdk = "0.16.0" +anchor_lang = "0.31.1" +``` + +```toml +[dependencies] +light-sdk = "0.16.0" +borsh = "0.10.0" +solana-program = "2.2" +``` + +* The `light-sdk` provides macros, wrappers and CPI interface to create and interact with compressed accounts. +* Add the serialization library (`borsh` for native Rust, or use `AnchorSerialize`). + +**Constants** + +Set program address and derive the CPI authority PDA to call the Light System program. + +```rust +declare_id!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +``` + +**`CPISigner`** is the configuration struct for CPI's to the Light System Program. + +* CPIs to the Light System program must be signed with a PDA derived by your program with the seed `b"authority"` +* `derive_light_cpi_signer!` derives the CPI signer PDA for you at compile time. + +**Compressed Account** + +Define your compressed account struct. + +\#\[event] // declared as event so that it is part of the idl.#\[derive( Clone, Debug, Default, LightDiscriminator)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,}#\[derive( Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator,)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,} + +You derive + +* the standard traits (`Clone`, `Debug`, `Default`), +* `borsh` or `AnchorSerialize` to serialize account data, and +* `LightDiscriminator` to implements a unique type ID (8 bytes) to distinguish account types. The default compressed account layout enforces a discriminator in its _own field_, [not the first 8 bytes of the data field](#user-content-fn-1)[^1]. + + +The traits listed above are required for `LightAccount`. `LightAccount` wraps `MyCompressedAccount` in Step 3 to set the discriminator and create the compressed account's data. + + + + + + + +Define the instruction data with the following parameters: + + + +```rust +pub fn close_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + account_meta: CompressedAccountMeta, + current_message: String, +) -> Result<()> +``` + + + +```rust +pub struct CloseInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMeta, + pub current_message: String, +} +``` + + + +1. **Validity Proof** + +* Define `proof` to include the proof that the account exists in the state tree. +* Clients fetch a validity proof with `getValidityProof()` from an RPC provider that supports ZK Compression (Helius, Triton, ...). + +2. **Specify input state and output state tree (stores closed account hash)** + +* Define `account_meta: CompressedAccountMeta` to reference the existing account and specify the state tree to store the new hash with zero values: + * `tree_info: PackedStateTreeInfo`: References the existing account hash in the state tree. + * `address`: The account's derived address. + * `output_state_tree_index` points to the state tree that will store the updated hash with a zero-byte hash to mark the account as closed. + + +Clients fetch the current account with `getCompressedAccount()` and populate `CompressedAccountMeta` with the account's metadata. + + +3. **Current data** + +* Define fields to include the current account data passed by the client. +* This depends on your program logic. This example includes the `current_message` field. + + + + +Load the compressed account and mark it as closed with `LightAccount::new_close()`. + + +`new_close()` + +1. hashes the current account data as input state and +2. marks the account for closure for the Light System Program. + + + + +```rust +let my_compressed_account = LightAccount::::new_close( + &crate::ID, + &account_meta, + MyCompressedAccount { + owner: ctx.accounts.signer.key(), + message: current_message, + }, +)?; +``` + + + +```rust +let my_compressed_account = LightAccount::::new_close( + &ID, + &instruction_data.account_meta, + MyCompressedAccount { + owner: *signer.key, + message: instruction_data.current_message, + }, +)?; +``` + + + +**Pass these parameters to `new_close()`:** + +* `&program_id`: The program's ID that owns the compressed account. +* `&account_meta`: The `CompressedAccountMeta` from instruction data (_Step 2_) that identifies the existing account and specifies the output state tree. +* Current account data: The existing account data. The SDK hashes this input state for verification by the Light System Program. + * Anchor: Construct `MyCompressedAccount` with `ctx.accounts.signer.key()` and `current_message` + * Native: Construct `MyCompressedAccount` with data from `instruction_data` + +**The SDK creates:** + +* A `LightAccount` wrapper similar to Anchor's `Account` that marks the account for closure. + + +`new_close()` hashes the input state and marks the account for closure. The Light System Program creates output state with zero values: + +* a zero discriminator (`0u8; 8`) removes type identification of the account, +* the output contains zeroes as data hash that indicates no data content, and +* the data field contains an empty vector, instead of serialized account fields. + + + + + +Invoke the Light System Program to close the compressed account. This empty account can be reinitialized with `LightAccount::new_empty()`. + + +The Light System Program + +* validates the account exists in state tree, +* nullifies the existing account hash, and +* appends the new account hash with zero values to the state tree to mark it as closed. + + + + +```rust +let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `ctx.accounts.signer.as_ref()`: the transaction signer +* `ctx.remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts` and passes it to the instruction. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + +```rust +let (signer, remaining_accounts) = accounts + .split_first(); + +let cpi_accounts = CpiAccounts::new( + signer, + remaining_accounts, + LIGHT_CPI_SIGNER +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `signer`: account that signs and pays for the transaction +* `remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts`. + * `split_first()` extracts the fee payer from the accounts array to separate it from the Light System Program accounts needed for the CPI. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + + +| | Name | Description | +|:---|:---|:---| +| 1 | Light System Program | Verifies validity proofs, compressed account ownership checks, cpis the account compression program to update tree accounts | +| 2 | CPI Signer | - PDA to sign CPI calls from your program to Light System Program
- Verified by Light System Program during CPI
- Derived from your program ID | +| 3 | Registered Program PDA | - Access control to the Account Compression Program | +| 4 | Noop Program | - Logs compressed account state to Solana ledger. Only used in v1.
- Indexers parse transaction logs to reconstruct compressed account state | +| 5 | Account Compression Authority | Signs CPI calls from Light System Program to Account Compression Program | +| 6 | Account Compression Program | - Writes to state and address tree accounts
- Client and the account compression program do not interact directly. | +| 7 | Invoking Program | Your program's ID, used by Light System Program to:
- Derive the CPI Signer PDA
- Verify the CPI Signer matches your program ID
- Set the owner of created compressed accounts | +| 8 | System Program | Solana System Program to transfer lamports | +
+ +**Build the CPI instruction**: + +* `new_cpi()` initializes the CPI instruction with the `proof` to prove the compressed account exists in the state tree _- defined in the Instruction Data (Step 2)._ +* `with_light_account` adds the `LightAccount` wrapper configured to close the account with the zero values _- defined in Step 3_. +* `invoke()` calls the Light System Program with `CpiAccounts`. +
+
+ +## Full Code Example + +The example programs below implement all steps from this guide. Make sure you have your [developer environment](https://www.zkcompression.com/compressed-pdas/create-a-program-with-compressed-pdas#start-building) set up first, or simply run: + +```bash +npm -g i @lightprotocol/zk-compression-cli@0.27.1-alpha.2 +light init testprogram +``` + + + + +Find the source code for this example [here](https://github.com/Lightprotocol/program-examples/blob/3a9ff76d0b8b9778be0e14aaee35e041cabfb8b2/counter/anchor/programs/counter/src/lib.rs#L167). + + +```rust expandable +#![allow(unexpected_cfgs)] +#![allow(deprecated)] + +use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize}; +use light_sdk::{ + account::LightAccount, + address::v1::derive_address, + cpi::{v1::CpiAccounts, CpiSigner}, + derive_light_cpi_signer, + instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; + +declare_id!("DzQ3za3DVCpXkXhmZVSrNchwbbSsJXmi9MBc8v5tvZuQ"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("DzQ3za3DVCpXkXhmZVSrNchwbbSsJXmi9MBc8v5tvZuQ"); + +#[program] +pub mod close { + + use super::*; + use light_sdk::cpi::{ + v1::LightSystemProgramCpi, InvokeLightSystemProgram, LightCpiInstruction, + }; + + /// Setup: Create a compressed account + pub fn create_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + address_tree_info: PackedAddressTreeInfo, + output_state_tree_index: u8, + message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let (address, address_seed) = derive_address( + &[b"message", ctx.accounts.signer.key().as_ref()], + &address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ErrorCode::AccountNotEnoughKeys)?, + &crate::ID, + ); + + let mut my_compressed_account = LightAccount::::new_init( + &crate::ID, + Some(address), + output_state_tree_index, + ); + + my_compressed_account.owner = ctx.accounts.signer.key(); + my_compressed_account.message = message.clone(); + + msg!( + "Created compressed account with message: {}", + my_compressed_account.message + ); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[address_tree_info.into_new_address_params_packed(address_seed)]) + .invoke(light_cpi_accounts)?; + + Ok(()) + } + + /// Close compressed account + pub fn close_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + account_meta: CompressedAccountMeta, + current_message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let my_compressed_account = LightAccount::::new_close( + &crate::ID, + &account_meta, + MyCompressedAccount { + owner: ctx.accounts.signer.key(), + message: current_message, + }, + )?; + + msg!("Close compressed account."); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; + + Ok(()) + } +} + +#[derive(Accounts)] +pub struct GenericAnchorAccounts<'info> { + #[account(mut)] + pub signer: Signer<'info>, +} + +#[event] +#[derive(Clone, Debug, Default, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} +``` + + + + +Find the source code for this example [here](https://github.com/Lightprotocol/program-examples/blob/3a9ff76d0b8b9778be0e14aaee35e041cabfb8b2/counter/native/src/lib.rs#L277). + + +```rust expandable +#![allow(unexpected_cfgs)] + +#[cfg(any(test, feature = "test-helpers"))] +pub mod test_helpers; + +use borsh::{BorshDeserialize, BorshSerialize}; +use light_macros::pubkey; +use light_sdk::{ + account::sha::LightAccount, + address::v1::derive_address, + cpi::{ + v1::{CpiAccounts, LightSystemProgramCpi}, + CpiSigner, InvokeLightSystemProgram, LightCpiInstruction, + }, + derive_light_cpi_signer, + error::LightSdkError, + instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; +use solana_program::{ + account_info::AccountInfo, entrypoint, program_error::ProgramError, pubkey::Pubkey, +}; + +pub const ID: Pubkey = pubkey!("NLusgr6vsEjYDvF6nDxpdrhMUxUC19s4XoyshSrGFVN"); +pub const LIGHT_CPI_SIGNER: CpiSigner = derive_light_cpi_signer!("NLusgr6vsEjYDvF6nDxpdrhMUxUC19s4XoyshSrGFVN"); + +#[cfg(not(feature = "no-entrypoint"))] +entrypoint!(process_instruction); + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub enum InstructionType { + Create, + Close, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct CreateInstructionData { + pub proof: ValidityProof, + pub address_tree_info: PackedAddressTreeInfo, + pub output_state_tree_index: u8, + pub message: String, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct CloseInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMeta, + pub current_message: String, +} + +#[derive(Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} + +pub fn process_instruction( + _program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> Result<(), ProgramError> { + let (instruction_type, rest) = instruction_data + .split_first() + .ok_or(ProgramError::InvalidInstructionData)?; + + match InstructionType::try_from_slice(&[*instruction_type]) + .map_err(|_| ProgramError::InvalidInstructionData)? + { + InstructionType::Create => create(accounts, rest)?, + InstructionType::Close => close(accounts, rest)?, + } + + Ok(()) +} + +fn create(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> { + let instruction_data = + CreateInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?; + + let signer = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?; + + let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER + ); + + let (address, address_seed) = derive_address( + &[b"message", signer.key.as_ref()], + &instruction_data + .address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ProgramError::NotEnoughAccountKeys)?, + &ID, + ); + + let new_address_params = instruction_data + .address_tree_info + .into_new_address_params_packed(address_seed); + + let mut my_compressed_account = LightAccount::::new_init( + &ID, + Some(address), + instruction_data.output_state_tree_index, + ); + my_compressed_account.owner = *signer.key; + my_compressed_account.message = instruction_data.message; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[new_address_params]) + .invoke(light_cpi_accounts)?; + + Ok(()) +} + +fn close(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> { + let instruction_data = + CloseInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?; + + let (signer, remaining_accounts) = accounts + .split_first() + .ok_or(ProgramError::InvalidAccountData)?; + + let cpi_accounts = CpiAccounts::new( + signer, + remaining_accounts, + LIGHT_CPI_SIGNER + ); + + let my_compressed_account = LightAccount::::new_close( + &ID, + &instruction_data.account_meta, + MyCompressedAccount { + owner: *signer.key, + message: instruction_data.current_message, + }, + )?; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(cpi_accounts)?; + + Ok(()) +} +``` + + + +## Next Steps + +Build a client for your program or learn how to reinitialize compressed accounts. diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-create-compressed-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-create-compressed-accounts.mdx new file mode 100644 index 0000000..3ca2052 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-create-compressed-accounts.mdx @@ -0,0 +1,624 @@ +--- +title: Create Compressed Accounts +description: Guide to create compressed accounts in Solana programs with full code examples. +--- + +Compressed accounts and addresses are created via CPI to the Light System Program. + +* Compressed and regular Solana accounts share the same functionality and are fully composable. +* A compressed account has two identifiers: the account hash and its address (optional). In comparison, regular Solana accounts are identified by their address. +* The account hash is not persistent and changes with every write to the account. +* For Solana PDA like behavior your compressed account needs an address as persistent identifier.\ + Fungible state like [compressed token accounts](/compressed-tokens/guides/how-to-create-compressed-token-accounts) do not need addresses. + + +Find [full code examples at the end](/compressed-pdas/guides/how-to-create-compressed-accounts#full-code-example) for Anchor and native Rust. + + +## Implementation Guide + +This guide will cover the components of a Solana program that creates compressed accounts.\ +Here is the complete flow: + +
+ + ![](/images/program-create-1.png) + +
+
+ + ![](/images/program-create.png) + +
+ + + + +Add dependencies to your program. + + +```toml Anchor +[dependencies] +light-sdk = "0.16.0" +anchor_lang = "0.31.1" +``` + +```toml Native Rust +[dependencies] +light-sdk = "0.16.0" +borsh = "0.10.0" +solana-program = "2.2" +``` + + +* The `light-sdk` provides macros, wrappers and CPI interface to create and interact with compressed accounts. +* Add the serialization library (`borsh` for native Rust, or use `AnchorSerialize`). + + + + +Set program address and derive the CPI authority PDA to call the Light System program. + + +```rust Anchor +declare_id!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +``` + +```rust Native Rust +pub const ID: Pubkey = pubkey!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +``` + + +**`CPISigner`** is the configuration struct for CPIs to the Light System Program. + +* CPI to the Light System program must be signed with a PDA derived by your program with the seed `b"authority"` +* `derive_light_cpi_signer!` derives the CPI signer PDA for you at compile time. + + + + + +```rust Anchor +#[event] // declared as event so that it is part of the idl. +#[derive( + Clone, + Debug, + Default, + LightDiscriminator +)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} +``` +```rust Native Rust +#[derive( + Clone, + Debug, + Default, + BorshSerialize, + BorshDeserialize, + LightDiscriminator +)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} +``` + + +Define your compressed account struct and derive + +* the standard traits (`Clone`, `Debug`, `Default`), +* `borsh` or `AnchorSerialize` to serialize account data, and +* `LightDiscriminator` to implements a unique type ID (8 bytes) to distinguish account types. The default compressed account layout enforces a discriminator in its _own field_, not the first 8 bytes of the data field. + + +The traits listed above are required for `LightAccount`. `LightAccount` wraps `my-compressed-account` in Step 7 to set the discriminator and create the compressed account's data. + + + + + +Define the instruction data with the following parameters: + + + +Anchor handles instruction deserialization automatically. Pass the parameters directly to the instruction function: + +```rust +pub fn create_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + address_tree_info: PackedAddressTreeInfo, + output_state_tree_index: u8, + message: String, +) -> Result<()> +``` + + +Define an instruction data struct that will be deserialized from the instruction data: + +```rust Native Rust +pub struct CreateInstructionData { + pub proof: ValidityProof, + pub address_tree_info: PackedAddressTreeInfo, + pub output_state_tree_index: u8, + pub message: String, +} +``` + + + +1. **Validity Proof** + +* Define `proof` to include the proof that the address does not exist yet in the specified address tree. +* Clients fetch a validity proof with `getValidityProof()` from an RPC provider that supports ZK Compression (Helius, Triton, ...). + +2. **Specify Merkle trees to store address and account hash** + +* Define `address_tree_info: PackedAddressTreeInfo` to reference the address tree account used to derive the address in the next step. +* Define `output_state_tree_index` to reference the state tree account that stores the compressed account hash. + + +Clients pack accounts into the accounts array to reduce transaction size. Packed structs like `PackedAddressTreeInfo` contain account indices (u8) instead of 32 byte pubkeys. The indices point to the account in the accounts array to retrieve the public key and other metadata. + + +3. **Initial account data** + +* Define fields for your program logic. Clients pass the initial values. +* This example includes the `message` field to define the initial state of the account. + + + + +Derive the address as a persistent unique identifier for the compressed account. + + + +```rust Anchor +let (address, address_seed) = derive_address( + &[b"message", ctx.accounts.signer.key().as_ref()], + &address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + &crate::ID, +); +``` +```rust Native Rust +let (address, address_seed) = derive_address( + &[b"message", signer.key.as_ref()], + &instruction_data + .address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + &ID, +); +``` + + +**Pass these parameters to `derive_address()`:** + +* `&custom_seeds`: Predefined inputs, such as strings, numbers or other account addresses. This example uses `b"message"` and the signer's pubkey. +* `&address_tree_pubkey`: The pubkey of the address tree where the address will be created. + * Retrieved by calling `get_tree_pubkey()` on `address_tree_info`, which unpacks the index from the accounts array. + * This parameter ensures an address is unique to an address tree. Different trees produce different addresses from identical seeds. +* `&program_id`: Your program's ID. + +**The SDK returns:** + +* `address`: The derived address for the compressed account. +* `address_seed`: Pass this to the Light System Program CPI in _Step 8_ to create the address. + + + + +Ensure global uniqueness of an address by verifying that the address tree pubkey matches the program's tree constant. + + +Every address is unique, but the same seeds can be used to create different addresses in different address trees. To enforce that a compressed PDA can only be created once with the same seed, you must check the address tree pubkey. + + + +```rust +let address_tree = light_cpi_accounts.tree_pubkeys().unwrap() + [address_tree_info.address_merkle_tree_pubkey_index as usize]; + +if address_tree != light_sdk::constants::ADDRESS_TREE_V2 { + return Err(ProgramError::InvalidAccountData.into()); +} +``` + + + + +Initialize the compressed account struct with `LightAccount::new_init()`. + + +`new_init()` creates a `LightAccount` instance similar to anchor `Account` and lets your program define the initial account data. + + + +```rust Anchor +let mut my_compressed_account = LightAccount::::new_init( + &crate::ID, + Some(address), + output_state_tree_index, +); + +my_compressed_account.owner = ctx.accounts.signer.key(); +my_compressed_account.message = message.clone(); +``` +```rust Native Rust +let mut my_compressed_account = LightAccount::::new_init( + &ID, + Some(address), + instruction_data.output_state_tree_index, +); +my_compressed_account.owner = *signer.key; +my_compressed_account.message = instruction_data.message; +``` + + +**Pass these parameters to `new_init()`:** + +* `&owner`: The program's ID that owns the compressed account. +* `Some(address)`: The derived address from _Step 5_. Pass `None` for accounts without addresses. +* `output_state_tree_index`: References the state tree account that will store the updated account hash, defined in instruction data (_Step 4_) + +**The SDK creates:** + +* A `LightAccount` wrapper similar to Anchor's `Account.` +* `new_init()` lets the program set the initial data. This example sets: + * `owner` to the signer's pubkey + * `message` to an arbitrary string + + + + +Invoke the Light System Program to create the compressed account and its address. + + +The Light System Program + +* verifies the validity proof against the address tree's Merkle root, +* inserts the address into the address tree, and +* appends the new account hash to the state tree. + + + + +```rust +let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, +); + +let new_address_params = address_tree_info + .into_new_address_params_packed(address_seed); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[new_address_params]) + .invoke(light_cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `ctx.accounts.signer.as_ref()`: the transaction signer +* `ctx.remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts` and passes it to the instruction. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + +```rust +let signer = accounts.first(); + +let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER +); + +let new_address_params = instruction_data + .address_tree_info + .into_new_address_params_packed(address_seed); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[new_address_params]) + .invoke(light_cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `signer`: account that signs and pays for the transaction +* `&accounts[1..]`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts`. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + + + +| | Name | Description | +|:---|:---|:---| +| 1 | Light System Program | Verifies validity proofs, compressed account ownership checks, cpis the account compression program to update tree accounts | +| 2 | CPI Signer | - PDA to sign CPI calls from your program to Light System Program
- Verified by Light System Program during CPI
- Derived from your program ID | +| 3 | Registered Program PDA | - Access control to the Account Compression Program | +| 4 | Noop Program | - Logs compressed account state to Solana ledger. Only used in v1.
- Indexers parse transaction logs to reconstruct compressed account state | +| 5 | Account Compression Authority | Signs CPI calls from Light System Program to Account Compression Program | +| 6 | Account Compression Program | - Writes to state and address tree accounts
- Client and the account compression program do not interact directly. | +| 7 | Invoking Program | Your program's ID, used by Light System Program to:
- Derive the CPI Signer PDA
- Verify the CPI Signer matches your program ID
- Set the owner of created compressed accounts | +| 8 | System Program | Solana System Program to transfer lamports | + +
+ +**Build the CPI instruction**: + +`new_cpi()` initializes the CPI instruction with the `proof` to prove that an address does not exist yet in the specified address tree _- defined in the Instruction Data (Step 4)._ + +* `with_light_account` adds the `LightAccount` with the initial compressed account data to the CPI instruction _- defined in Step 7_. +* `with_new_addresses` adds the `address_seed` and metadata to the CPI instruction data - returned by `derive_address` _in Step 5_. +* `invoke(light_cpi_accounts)` calls the Light System Program with `CpiAccounts.` +
+
+ +## Full Code Example + +The example programs below implement all steps from this guide. Make sure you have your [developer environment](https://www.zkcompression.com/compressed-pdas/create-a-program-with-compressed-pdas#start-building) set up first, or simply run: + +```bash +npm -g i @lightprotocol/zk-compression-cli@0.27.1-alpha.2 +light init testprogram +``` + + +For help with debugging, see the [Error Cheatsheet](../../resources/error-cheatsheet/). + + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/create). + + +```rust expandable +#![allow(unexpected_cfgs)] +#![allow(deprecated)] + +use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize}; +use light_sdk::{ + account::LightAccount, + address::v1::derive_address, + cpi::{v1::CpiAccounts, CpiSigner}, + derive_light_cpi_signer, + instruction::{PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; + +declare_id!("Hps5oaKdYWqjVZJnAxUE1uwbozwEgZZGCRA57p2wdqcS"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("Hps5oaKdYWqjVZJnAxUE1uwbozwEgZZGCRA57p2wdqcS"); + +#[program] +pub mod create { + + use super::*; + use light_sdk::cpi::{ + v1::LightSystemProgramCpi, InvokeLightSystemProgram, LightCpiInstruction, + }; + + /// Creates a new compressed account + pub fn create_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + address_tree_info: PackedAddressTreeInfo, + output_state_tree_index: u8, + message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let (address, address_seed) = derive_address( + &[b"message", ctx.accounts.signer.key().as_ref()], + &address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ErrorCode::AccountNotEnoughKeys)?, + &crate::ID, + ); + + let mut my_compressed_account = LightAccount::::new_init( + &crate::ID, + Some(address), + output_state_tree_index, + ); + + my_compressed_account.owner = ctx.accounts.signer.key(); + my_compressed_account.message = message.clone(); + + msg!( + "Created compressed account with message: {}", + my_compressed_account.message + ); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[address_tree_info.into_new_address_params_packed(address_seed)]) + .invoke(light_cpi_accounts)?; + + Ok(()) + } +} + +#[derive(Accounts)] +pub struct GenericAnchorAccounts<'info> { + #[account(mut)] + pub signer: Signer<'info>, +} + +// declared as event so that it is part of the idl. +#[event] +#[derive(Clone, Debug, Default, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} +``` + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/native/programs/create). + + +```rust Native Rust expandable +#![allow(unexpected_cfgs)] + +#[cfg(any(test, feature = "test-helpers"))] +pub mod test_helpers; + +use borsh::{BorshDeserialize, BorshSerialize}; +use light_macros::pubkey; +use light_sdk::{ + account::sha::LightAccount, + address::v1::derive_address, + cpi::{ + v1::{CpiAccounts, LightSystemProgramCpi}, + CpiSigner, InvokeLightSystemProgram, LightCpiInstruction, + }, + derive_light_cpi_signer, + error::LightSdkError, + instruction::{PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; +use solana_program::{ + account_info::AccountInfo, entrypoint, program_error::ProgramError, pubkey::Pubkey, +}; + +pub const ID: Pubkey = pubkey!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); + +entrypoint!(process_instruction); + +#[repr(u8)] +#[derive(Debug)] +pub enum InstructionType { + Create = 0, +} + +impl TryFrom for InstructionType { + type Error = LightSdkError; + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(InstructionType::Create), + _ => panic!("Invalid instruction discriminator."), + } + } +} + +#[derive( + Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator, +)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct CreateInstructionData { + pub proof: ValidityProof, + pub address_tree_info: PackedAddressTreeInfo, + pub output_state_tree_index: u8, + pub message: String, +} + +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> Result<(), ProgramError> { + if program_id != &ID { + return Err(ProgramError::IncorrectProgramId); + } + if instruction_data.is_empty() { + return Err(ProgramError::InvalidInstructionData); + } + + let discriminator = InstructionType::try_from(instruction_data[0]) + .map_err(|_| ProgramError::InvalidInstructionData)?; + + match discriminator { + InstructionType::Create => { + let instruction_data = + CreateInstructionData::try_from_slice(&instruction_data[1..]) + .map_err(|_| ProgramError::InvalidInstructionData)?; + create(accounts, instruction_data) + } + } +} + +pub fn create( + accounts: &[AccountInfo], + instruction_data: CreateInstructionData, +) -> Result<(), ProgramError> { + let signer = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?; + + let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER + ); + + let (address, address_seed) = derive_address( + &[b"message", signer.key.as_ref()], + &instruction_data + .address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ProgramError::NotEnoughAccountKeys)?, + &ID, + ); + + let new_address_params = instruction_data + .address_tree_info + .into_new_address_params_packed(address_seed); + + let mut my_compressed_account = LightAccount::::new_init( + &ID, + Some(address), + instruction_data.output_state_tree_index, + ); + my_compressed_account.owner = *signer.key; + my_compressed_account.message = instruction_data.message; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[new_address_params]) + .invoke(light_cpi_accounts)?; + + Ok(()) +} +``` + + + +## Next Steps + +Build a client for your program or learn how to update compressed accounts. diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx new file mode 100644 index 0000000..36781c4 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-reinitialize-compressed-accounts.mdx @@ -0,0 +1,630 @@ +--- +title: Reinitialize Compressed Accounts +description: Guide to reinitialize compressed accounts in Solana programs with full code examples. +--- + +Compressed accounts are reinitialized via CPI to the Light System Program. + +An empty compressed account can be reinitialized + +* with an account hash marked as empty with zero values and zero discriminator +* to create a new account hash at the same address with new values. + + +Find [full code examples at the end](/compressed-pdas/guides/how-to-reinitialize-compressed-accounts#full-code-example) for Anchor and native Rust. + + +## Implementation Guide + +This guide will cover the components of a Solana program that reinitializes compressed accounts. +Here is the complete flow to reinitialize compressed accounts: + +
+ + ![](/images/program-reinit-1.png) + +
+
+ + ![](/images/program-reinit.png) + +
+ + + + + + +**Dependencies** + +Add dependencies to your program. + +```toml +[dependencies] +light-sdk = "0.16.0" +anchor_lang = "0.31.1" +``` +```toml +[dependencies] +light-sdk = "0.16.0" +borsh = "0.10.0" +solana-program = "2.2" +``` + +* The `light-sdk` provides macros, wrappers and CPI interface to create and interact with compressed accounts. +* Add the serialization library (`borsh` for native Rust, or use `AnchorSerialize`). + +**Constants** + +Set program address and derive the CPI authority PDA to call the Light System program. + +```rust +declare_id!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +``` + +**`CPISigner`** is the configuration struct for CPI's to the Light System Program. + +* CPIs to the Light System program must be signed with a PDA derived by your program with the seed `b"authority"` +* `derive_light_cpi_signer!` derives the CPI signer PDA for you at compile time. + +**Compressed Account** + +Define your compressed account struct. + +\#\[event] // declared as event so that it is part of the idl.#\[derive( Clone, Debug, Default, LightDiscriminator)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,}#\[derive( Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator,)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,} + +You derive + +* the standard traits (`Clone`, `Debug`, `Default`), +* `borsh` or `AnchorSerialize` to serialize account data, and +* `LightDiscriminator` to implements a unique type ID (8 bytes) to distinguish account types. The default compressed account layout enforces a discriminator in its _own field_, [not the first 8 bytes of the data field](#user-content-fn-1)[^1]. + + +The traits listed above are required for `LightAccount`. `LightAccount` wraps `MyCompressedAccount` in Step 3 to set the discriminator and create the compressed account's data. + + + + + + + +Define the instruction data with the following parameters: + + + +```rust +pub fn reinit_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + account_meta: CompressedAccountMeta, +) -> Result<()> +``` + + + +```rust +pub struct ReinitInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMeta, +} +``` + + + +1. **Validity Proof** + +* Define `proof` to include the proof that the closed account with zero values exists in the state tree. +* Clients fetch a validity proof with `getValidityProof()` from an RPC provider that supports ZK Compression (Helius, Triton, ...). + +2. **Specify input state and output state tree (stores new account hash)** + +* Define `account_meta: CompressedAccountMeta` to reference the closed account and specify the state tree to store the new account hash: + * `tree_info: PackedStateTreeInfo`: References the existing account hash in the state tree. + * `address`: The account's derived address. + * `output_state_tree_index`: References the state tree account that will store the new compressed account hash. + + +Reinitialization does not require `current_value` parameters. `new_empty()` automatically uses the closed account as input. + + + + + +Reinitialize the closed account with `LightAccount::new_empty()`. + + +`new_empty()` + +1. reconstructs the closed account hash with zero values as input, and +2. creates output state with default-initialized values. + +You can set custom values in the same transaction: + +1. Reinitialize with `new_empty()`, and +2. Update with `new_mut()` to set custom values. + + + + +```rust +let my_compressed_account = LightAccount::::new_empty( + &crate::ID, + &account_meta, +)?; +``` + + + +```rust +let my_compressed_account = LightAccount::::new_empty( + &ID, + &instruction_data.account_meta, +)?; +``` + + + +**Pass these parameters to `new_empty()`:** + +* `&program_id`: The program's ID that owns the compressed account. +* `&account_meta`: The `CompressedAccountMeta` from instruction data (_Step 2_) that identifies the existing account and specifies the output state tree. + * Anchor: Pass `account_meta` by reference. It is automatically deserialized as a function parameter. + * Native Rust: Manually deserialize the instruction data struct, then pass the field by reference `&instruction_data.account_meta`. + +**The SDK creates:** + +* A `LightAccount` wrapper with account data automatically initialized to default values using the `Default` trait. +* This creates a zero-initialized instance: `Pubkey` as all zeros, `u64` as `0`, `String` as empty. + + +`new_empty()` reconstructs the closed account hash with zero values. The Light System Program verifies the closed account hash and creates the output hash in _Step 4_. + + + + + +Invoke the Light System Program to reinitialize the compressed account. + + +The Light System Program + +* validates the closed account hash exists in state tree, +* nullifies the closed account hash, and +* appends the new account hash with provided values to the state tree. + + + + +```rust +let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `ctx.accounts.signer.as_ref()`: the transaction signer +* `ctx.remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts` and passes it to the instruction. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + +```rust +let (signer, remaining_accounts) = accounts + .split_first(); + +let cpi_accounts = CpiAccounts::new( + signer, + remaining_accounts, + LIGHT_CPI_SIGNER +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `signer`: account that signs and pays for the transaction +* `remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts`. + * `split_first()` extracts the fee payer from the accounts array to separate it from the Light System Program accounts needed for the CPI. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + + + +| | Name | Description | +|:---|:---|:---| +| 1 | Light System Program | Verifies validity proofs, compressed account ownership checks, cpis the account compression program to update tree accounts | +| 2 | CPI Signer | - PDA to sign CPI calls from your program to Light System Program
- Verified by Light System Program during CPI
- Derived from your program ID | +| 3 | Registered Program PDA | - Access control to the Account Compression Program | +| 4 | Noop Program | - Logs compressed account state to Solana ledger. Only used in v1.
- Indexers parse transaction logs to reconstruct compressed account state | +| 5 | Account Compression Authority | Signs CPI calls from Light System Program to Account Compression Program | +| 6 | Account Compression Program | - Writes to state and address tree accounts
- Client and the account compression program do not interact directly. | +| 7 | Invoking Program | Your program's ID, used by Light System Program to:
- Derive the CPI Signer PDA
- Verify the CPI Signer matches your program ID
- Set the owner of created compressed accounts | +| 8 | System Program | Solana System Program to transfer lamports | + +
+ +**Build the CPI instruction**: + +* `new_cpi()` initializes the CPI instruction with the `proof` to prove the closed account hash exists in the state tree _- defined in the Instruction Data (Step 2)._ +* `with_light_account` adds the `LightAccount` configured with the closed account hash as input and provided values as output _- defined in Step 3_. +* `invoke(light_cpi_accounts)` calls the Light System Program with `CpiAccounts`. +
+
+ +## Full Code Example + +The counter programs below implement all steps from this guide. Make sure you have your [developer environment](https://www.zkcompression.com/compressed-pdas/create-a-program-with-compressed-pdas#start-building) set up first. + +```bash +npm -g i @lightprotocol/zk-compression-cli@0.27.1-alpha.2 +light init testprogram +``` + + +For help with debugging, see the [Error Cheatsheet](https://www.zkcompression.com/resources/error-cheatsheet). + + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor/reinit). + + +```rust expandable +#![allow(unexpected_cfgs)] +#![allow(deprecated)] + +use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize}; +use light_sdk::{ + account::LightAccount, + address::v1::derive_address, + cpi::{v1::CpiAccounts, CpiSigner}, + derive_light_cpi_signer, + instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; + +declare_id!("DeSUZ4to3qN7mQimoTgvEnBXiBWeTqMVcMz3ynLaWx1t"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("DeSUZ4to3qN7mQimoTgvEnBXiBWeTqMVcMz3ynLaWx1t"); + +#[program] +pub mod reinit { + + use super::*; + use light_sdk::cpi::{ + v1::LightSystemProgramCpi, InvokeLightSystemProgram, LightCpiInstruction, + }; + + /// Setup: Create a compressed account + pub fn create_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + address_tree_info: PackedAddressTreeInfo, + output_state_tree_index: u8, + message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let (address, address_seed) = derive_address( + &[b"message", ctx.accounts.signer.key().as_ref()], + &address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ErrorCode::AccountNotEnoughKeys)?, + &crate::ID, + ); + + let mut my_compressed_account = LightAccount::::new_init( + &crate::ID, + Some(address), + output_state_tree_index, + ); + + my_compressed_account.owner = ctx.accounts.signer.key(); + my_compressed_account.message = message.clone(); + + msg!( + "Created compressed account with message: {}", + my_compressed_account.message + ); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[address_tree_info.into_new_address_params_packed(address_seed)]) + .invoke(light_cpi_accounts)?; + + Ok(()) + } + + /// Setup: Close compressed account + pub fn close_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + account_meta: CompressedAccountMeta, + current_message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let my_compressed_account = LightAccount::::new_close( + &crate::ID, + &account_meta, + MyCompressedAccount { + owner: ctx.accounts.signer.key(), + message: current_message, + }, + )?; + + msg!("Close compressed account."); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; + + Ok(()) + } + + /// Reinitialize closed compressed account + pub fn reinit_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + account_meta: CompressedAccountMeta, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let my_compressed_account = LightAccount::::new_empty( + &crate::ID, + &account_meta, + )?; + + msg!("Reinitializing closed compressed account"); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; + + Ok(()) + } +} + +#[derive(Accounts)] +pub struct GenericAnchorAccounts<'info> { + #[account(mut)] + pub signer: Signer<'info>, +} + +#[event] +#[derive(Clone, Debug, Default, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} +``` + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/native/programs/reinit). + + +```rust expandable +#![allow(unexpected_cfgs)] + +#[cfg(any(test, feature = "test-helpers"))] +pub mod test_helpers; + +use borsh::{BorshDeserialize, BorshSerialize}; +use light_macros::pubkey; +use light_sdk::{ + account::sha::LightAccount, + address::v1::derive_address, + cpi::{ + v1::{CpiAccounts, LightSystemProgramCpi}, + CpiSigner, InvokeLightSystemProgram, LightCpiInstruction, + }, + derive_light_cpi_signer, + error::LightSdkError, + instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; +use solana_program::{ + account_info::AccountInfo, entrypoint, program_error::ProgramError, pubkey::Pubkey, +}; + +pub const ID: Pubkey = pubkey!("C9WiPUaQ5PRjEWg7vUmgekfuQtAgFZFhn12ytXEMDr8y"); +pub const LIGHT_CPI_SIGNER: CpiSigner = derive_light_cpi_signer!("C9WiPUaQ5PRjEWg7vUmgekfuQtAgFZFhn12ytXEMDr8y"); + +#[cfg(not(feature = "no-entrypoint"))] +entrypoint!(process_instruction); + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub enum InstructionType { + Create, + Close, + Reinit, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct CreateInstructionData { + pub proof: ValidityProof, + pub address_tree_info: PackedAddressTreeInfo, + pub output_state_tree_index: u8, + pub message: String, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct CloseInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMeta, + pub current_message: String, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub struct ReinitInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMeta, +} + +#[derive(Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} + +pub fn process_instruction( + _program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> Result<(), ProgramError> { + let (instruction_type, rest) = instruction_data + .split_first() + .ok_or(ProgramError::InvalidInstructionData)?; + + match InstructionType::try_from_slice(&[*instruction_type]) + .map_err(|_| ProgramError::InvalidInstructionData)? + { + InstructionType::Create => create(accounts, rest)?, + InstructionType::Close => close(accounts, rest)?, + InstructionType::Reinit => reinit(accounts, rest)?, + } + + Ok(()) +} + +fn create(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> { + let instruction_data = + CreateInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?; + + let signer = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?; + + let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER + ); + + let (address, address_seed) = derive_address( + &[b"message", signer.key.as_ref()], + &instruction_data + .address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ProgramError::NotEnoughAccountKeys)?, + &ID, + ); + + let new_address_params = instruction_data + .address_tree_info + .into_new_address_params_packed(address_seed); + + let mut my_compressed_account = LightAccount::::new_init( + &ID, + Some(address), + instruction_data.output_state_tree_index, + ); + my_compressed_account.owner = *signer.key; + my_compressed_account.message = instruction_data.message; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[new_address_params]) + .invoke(light_cpi_accounts)?; + + Ok(()) +} + +fn close(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> { + let instruction_data = + CloseInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?; + + let (signer, remaining_accounts) = accounts + .split_first() + .ok_or(ProgramError::InvalidAccountData)?; + + let cpi_accounts = CpiAccounts::new( + signer, + remaining_accounts, + LIGHT_CPI_SIGNER + ); + + let my_compressed_account = LightAccount::::new_close( + &ID, + &instruction_data.account_meta, + MyCompressedAccount { + owner: *signer.key, + message: instruction_data.current_message, + }, + )?; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(cpi_accounts)?; + + Ok(()) +} + +fn reinit(accounts: &[AccountInfo], instruction_data: &[u8]) -> Result<(), LightSdkError> { + let instruction_data = + ReinitInstructionData::try_from_slice(instruction_data).map_err(|_| LightSdkError::Borsh)?; + + let (signer, remaining_accounts) = accounts + .split_first() + .ok_or(ProgramError::InvalidAccountData)?; + + let cpi_accounts = CpiAccounts::new( + signer, + remaining_accounts, + LIGHT_CPI_SIGNER + ); + + let my_compressed_account = LightAccount::::new_empty( + &ID, + &instruction_data.account_meta, + )?; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(cpi_accounts)?; + + Ok(()) +} +``` + + + +## Next Steps + +Build a client for your program or learn how to burn compressed accounts. diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-update-compressed-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-update-compressed-accounts.mdx new file mode 100644 index 0000000..c036d27 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/guides/how-to-update-compressed-accounts.mdx @@ -0,0 +1,622 @@ +--- +title: Update Compressed Accounts +description: Guide to update compressed accounts in Solana programs with full code examples. +--- + + +Compressed accounts are updated via CPI to the Light System Program. + +The update of a compressed account follows a UTXO pattern, unlike regular Solana accounts that overwrite data in place. Each update of a compressed account + +* consumes the existing account hash and +* produces a new account hash with updated data. +* The existing account hash is nullified to prevent double spending. + + +Find [full code examples at the end](/compressed-pdas/guides/how-to-update-compressed-accounts#full-code-example) for Anchor and native Rust. + + +## Implementation Guide + +This guide will cover the components of a Solana program that updates compressed accounts.\ +Here is the complete flow: + +
+ + ![](/images/program-update-1.png) + +
+
+ + ![](/images/program-update.png) + +
+ + + + + + +**Dependencies** + +Add dependencies to your program. + +```toml +[dependencies] +light-sdk = "0.16.0" +anchor_lang = "0.31.1" +``` + +```toml +[dependencies] +light-sdk = "0.16.0" +borsh = "0.10.0" +solana-program = "2.2" +``` + +* The `light-sdk` provides macros, wrappers and CPI interface to create and interact with compressed accounts. +* Add the serialization library (`borsh` for native Rust, or use `AnchorSerialize`). + +**Constants** + +Set program address and derive the CPI authority PDA to call the Light System program. + +```rust +declare_id!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("rent4o4eAiMbxpkAM1HeXzks9YeGuz18SEgXEizVvPq"); +``` + +**`CPISigner`** is the configuration struct for CPI's to the Light System Program. + +* CPIs to the Light System program must be signed with a PDA derived by your program with the seed `b"authority"` +* `derive_light_cpi_signer!` derives the CPI signer PDA for you at compile time. + +**Compressed Account** + +Define your compressed account struct. + +\#\[event] // declared as event so that it is part of the idl.#\[derive( Clone, Debug, Default, LightDiscriminator)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,}#\[derive( Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator,)]pub struct MyCompressedAccount \{ pub owner: Pubkey, pub message: String,} + +You derive + +* the standard traits (`Clone`, `Debug`, `Default`), +* `borsh` or `AnchorSerialize` to serialize account data, and +* `LightDiscriminator` to implements a unique type ID (8 bytes) to distinguish account types. The default compressed account layout enforces a discriminator in its _own field_, [not the first 8 bytes of the data field](#user-content-fn-1)[^1]. + + +The traits listed above are required for `LightAccount`. `LightAccount` wraps `MyCompressedAccount` in Step 3 to set the discriminator and create the compressed account's data. + + + + + + + +Define the instruction data with the following parameters: + + + +Anchor handles instruction deserialization automatically. Pass the parameters directly to the instruction function: + +```rust +pub fn update_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + current_account: MyCompressedAccount, + account_meta: CompressedAccountMeta, + new_message: String, +) -> Result<()> +``` + + + +```rust +pub struct UpdateInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMeta, + pub current_message: String, + pub new_message: String, +} +``` + + + +1. **Validity Proof** + +* Define `proof` to include the proof that the account exists in the state tree. +* Clients fetch a validity proof with `getValidityProof()` from an RPC provider that supports ZK Compression (Helius, Triton, ...). + +2. **Specify input state and output state tree (stores updated account hash)** + +* Define `account_meta: CompressedAccountMeta` to reference the existing account and specify the state tree to store the updated account hash: + * `tree_info: PackedStateTreeInfo`: References the existing account hash in the state tree. + * `address`: The account's derived address. + * `output_state_tree_index`: References the state tree account that will store the updated account hash. + + +Clients fetch the current account with `getCompressedAccount()` and populate `CompressedAccountMeta` with the account's metadata. + + +3. **Current account data** + +* Define fields to include the current account data passed by the client. +* This depends on your program logic. This example includes `current_message` (or `current_account` in Anchor) and `new_message` fields. + * `new_message` contains the new data that will replace the message field of the compressed account after the update. + + + + +Load the compressed account and update it with `LightAccount::new_mut()`. + + +`new_mut()`: + +* hashes the current account data as input state and +* lets your program define the output state. + + + + +```rust +let mut my_compressed_account = LightAccount::::new_mut( + &crate::ID, + &account_meta, + current_account, +)?; + +my_compressed_account.message = new_message.clone(); +``` + + + +```rust +let mut my_compressed_account = LightAccount::::new_mut( + &ID, + &instruction_data.account_meta, + MyCompressedAccount { + owner: *signer.key, + message: instruction_data.current_message, + }, +)?; + +my_compressed_account.account.message = instruction_data.new_message; +``` + + + +**Pass these parameters to `new_mut()`:** + +* `&program_id`: The program's ID that owns the compressed account. +* `&account_meta`: The `CompressedAccountMeta` from instruction data (_Step 2_) that identifies the existing account and specifies the output state tree. +* Include the curent account data. + * Anchor: Pass `current_account` directly + * Native: Construct `MyCompressedAccount` with data from `instruction_data` + +**The SDK creates:** + +* A `LightAccount` wrapper similar to Anchor's `Account`. +* `new_mut()` lets the program modify the output state. This example sets `message` to `new_message`. + + +`new_mut()` only hashes the input state. The Light System Program verifies that input hash exists in a state tree and creates the output hash in _Step 4._ + + + + + +Invoke the Light System Program to update the compressed account. + + +The Light System Program + +* validates the account exists in state tree, +* nullifies the existing account hash in the state tree, and +* appends the updated account hash to the state tree. + + + + +```rust +let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; +``` + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `ctx.accounts.signer.as_ref()`: the transaction signer +* `ctx.remaining_accounts`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts` and passes it to the instruction. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + +```rust +let signer = accounts.first(); + +let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER +); + +LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; +``` + + +**Set up `CpiAccounts::new()`:** + +`CpiAccounts::new()` parses accounts for the CPI call to Light System Program. + +**Pass these parameters:** + +* `signer`: account that signs and pays for the transaction +* `&accounts[1..]`: Slice with `[system_accounts, ...packed_tree_accounts]`. The client builds this with `PackedAccounts`. +* `&LIGHT_CPI_SIGNER`: Your program's CPI signer PDA defined in Constants. + + + + + +| | Name | Description | +|:---|:---|:---| +| 1 | Light System Program | Verifies validity proofs, compressed account ownership checks, CPIs the account compression program to update tree accounts | +| 2 | CPI Signer | - PDA to sign CPI calls from your program to Light System Program
- Verified by Light System Program during CPI
- Derived from your program ID | +| 3 | Registered Program PDA | - Access control to the Account Compression Program | +| 4 | Noop Program | - Logs compressed account state to Solana ledger (only used in v1)
- Indexers parse transaction logs to reconstruct compressed account state | +| 5 | Account Compression Authority | Signs CPI calls from Light System Program to Account Compression Program | +| 6 | Account Compression Program | - Writes to state and address tree accounts
- Client and the account compression program do not interact directly. | +| 7 | Invoking Program | Your program's ID, used by Light System Program to:
- Derive the CPI Signer PDA
- Verify the CPI Signer matches your program ID
- Set the owner of created compressed accounts | +| 8 | System Program | Solana System Program to transfer lamports | + + +
+ +**Build the CPI instruction**: + +* `new_cpi()` initializes the CPI instruction with the `proof` to prove that the account exists in the specified state tree - _in the Instruction Data (Step 2)._ +* `with_light_account` adds the `LightAccount` with the modified compressed account data _- defined in Step 3_ +* `invoke(light_cpi_accounts)` calls the Light System Program with `CpiAccounts`. +
+
+ +## Full Code Example + +The example programs below implement all steps from this guide. Make sure you have your [developer environment](https://www.zkcompression.com/compressed-pdas/create-a-program-with-compressed-pdas#start-building) set up first, or simply run: + +```bash +npm -g i @lightprotocol/zk-compression-cli@0.27.1-alpha.2 +light init testprogram +``` + + +For help with debugging, see the [Error Cheatsheet](../../resources/error-cheatsheet/). + + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/blob/3a9ff76d0b8b9778be0e14aaee35e041cabfb8b2/counter/anchor/programs/counter/src/lib.rs#L71). + + +```rust expandable +#![allow(unexpected_cfgs)] +#![allow(deprecated)] + +use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize}; +use light_sdk::{ + account::LightAccount, + address::v1::derive_address, + cpi::{v1::CpiAccounts, CpiSigner}, + derive_light_cpi_signer, + instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; + +declare_id!("Cj3DxyqB7wJh511VKexsjKt7Hx1kvPvCBMrbLuL8grKc"); + +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("Cj3DxyqB7wJh511VKexsjKt7Hx1kvPvCBMrbLuL8grKc"); + +#[program] +pub mod update { + + use super::*; + use light_sdk::cpi::{ + v1::LightSystemProgramCpi, InvokeLightSystemProgram, LightCpiInstruction, + }; + + /// Setup: Creates a compressed account + pub fn create_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + address_tree_info: PackedAddressTreeInfo, + output_state_tree_index: u8, + message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let (address, address_seed) = derive_address( + &[b"message", ctx.accounts.signer.key().as_ref()], + &address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ErrorCode::AccountNotEnoughKeys)?, + &crate::ID, + ); + + let mut my_compressed_account = LightAccount::::new_init( + &crate::ID, + Some(address), + output_state_tree_index, + ); + + my_compressed_account.owner = ctx.accounts.signer.key(); + my_compressed_account.message = message.clone(); + + msg!( + "Created compressed account with message: {}", + my_compressed_account.message + ); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[address_tree_info.into_new_address_params_packed(address_seed)]) + .invoke(light_cpi_accounts)?; + + Ok(()) + } + + /// Updates an existing compressed account's message + pub fn update_account<'info>( + ctx: Context<'_, '_, '_, 'info, GenericAnchorAccounts<'info>>, + proof: ValidityProof, + current_account: MyCompressedAccount, + account_meta: CompressedAccountMeta, + new_message: String, + ) -> Result<()> { + let light_cpi_accounts = CpiAccounts::new( + ctx.accounts.signer.as_ref(), + ctx.remaining_accounts, + crate::LIGHT_CPI_SIGNER, + ); + + let mut my_compressed_account = LightAccount::::new_mut( + &crate::ID, + &account_meta, + current_account, + )?; + + my_compressed_account.message = new_message.clone(); + + msg!( + "Updated compressed account message to: {}", + my_compressed_account.message + ); + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; + + Ok(()) + } +} + +#[derive(Accounts)] +pub struct GenericAnchorAccounts<'info> { + #[account(mut)] + pub signer: Signer<'info>, +} + +#[event] +#[derive(Clone, Debug, Default, LightDiscriminator)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} +``` + + + + +Find the source code [here](https://github.com/Lightprotocol/program-examples/blob/3a9ff76d0b8b9778be0e14aaee35e041cabfb8b2/counter/native/src/lib.rs#L197). + + +```rust expandable +#![allow(unexpected_cfgs)] + +#[cfg(any(test, feature = "test-helpers"))] +pub mod test_helpers; + +use borsh::{BorshDeserialize, BorshSerialize}; +use light_macros::pubkey; +use light_sdk::{ + account::sha::LightAccount, + address::v1::derive_address, + cpi::{ + v1::{CpiAccounts, LightSystemProgramCpi}, + CpiSigner, InvokeLightSystemProgram, LightCpiInstruction, + }, + derive_light_cpi_signer, + error::LightSdkError, + instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof}, + LightDiscriminator, +}; +use solana_program::{ + account_info::AccountInfo, entrypoint, program_error::ProgramError, pubkey::Pubkey, +}; + +pub const ID: Pubkey = pubkey!("2m6LXA7E6kMSkK6QHq2WCznD6kvhDcVFqEKpETKAQxYe"); +pub const LIGHT_CPI_SIGNER: CpiSigner = + derive_light_cpi_signer!("2m6LXA7E6kMSkK6QHq2WCznD6kvhDcVFqEKpETKAQxYe"); + +entrypoint!(process_instruction); + +#[repr(u8)] +#[derive(Debug)] +pub enum InstructionType { + Create = 0, + Update = 1, +} + +impl TryFrom for InstructionType { + type Error = LightSdkError; + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(InstructionType::Create), + 1 => Ok(InstructionType::Update), + _ => panic!("Invalid instruction discriminator."), + } + } +} + +#[derive( + Debug, Default, Clone, BorshSerialize, BorshDeserialize, LightDiscriminator, +)] +pub struct MyCompressedAccount { + pub owner: Pubkey, + pub message: String, +} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct CreateInstructionData { + pub proof: ValidityProof, + pub address_tree_info: PackedAddressTreeInfo, + pub output_state_tree_index: u8, + pub message: String, +} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct UpdateInstructionData { + pub proof: ValidityProof, + pub account_meta: CompressedAccountMeta, + pub current_message: String, + pub new_message: String, +} + +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> Result<(), ProgramError> { + if program_id != &ID { + return Err(ProgramError::IncorrectProgramId); + } + if instruction_data.is_empty() { + return Err(ProgramError::InvalidInstructionData); + } + + let discriminator = InstructionType::try_from(instruction_data[0]) + .map_err(|_| ProgramError::InvalidInstructionData)?; + + match discriminator { + InstructionType::Create => { + let instruction_data = + CreateInstructionData::try_from_slice(&instruction_data[1..]) + .map_err(|_| ProgramError::InvalidInstructionData)?; + create(accounts, instruction_data) + } + InstructionType::Update => { + let instruction_data = + UpdateInstructionData::try_from_slice(&instruction_data[1..]) + .map_err(|_| ProgramError::InvalidInstructionData)?; + update(accounts, instruction_data) + } + } +} + +pub fn create( + accounts: &[AccountInfo], + instruction_data: CreateInstructionData, +) -> Result<(), ProgramError> { + let signer = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?; + + let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER +); + + let (address, address_seed) = derive_address( + &[b"message", signer.key.as_ref()], + &instruction_data + .address_tree_info + .get_tree_pubkey(&light_cpi_accounts) + .map_err(|_| ProgramError::NotEnoughAccountKeys)?, + &ID, + ); + + let new_address_params = instruction_data + .address_tree_info + .into_new_address_params_packed(address_seed); + + let mut my_compressed_account = LightAccount::::new_init( + &ID, + Some(address), + instruction_data.output_state_tree_index, + ); + my_compressed_account.owner = *signer.key; + my_compressed_account.message = instruction_data.message; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .with_new_addresses(&[new_address_params]) + .invoke(light_cpi_accounts)?; + + Ok(()) +} + +pub fn update( + accounts: &[AccountInfo], + instruction_data: UpdateInstructionData, +) -> Result<(), ProgramError> { + let signer = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?; + + let light_cpi_accounts = CpiAccounts::new( + signer, + &accounts[1..], + LIGHT_CPI_SIGNER +); + + let mut my_compressed_account = LightAccount::::new_mut( + &ID, + &instruction_data.account_meta, + MyCompressedAccount { + owner: *signer.key, + message: instruction_data.current_message, + }, + )?; + + // Update the account data with new message + my_compressed_account.account.message = instruction_data.new_message; + + LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, instruction_data.proof) + .with_light_account(my_compressed_account)? + .invoke(light_cpi_accounts)?; + + Ok(()) +} +``` + + + +## Next Steps + +Build a client for your program or learn how to close compressed accounts. diff --git a/zk-compression-docs/mintlify-docs/compressed-pdas/program-examples.mdx b/zk-compression-docs/mintlify-docs/compressed-pdas/program-examples.mdx new file mode 100644 index 0000000..4fb957e --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-pdas/program-examples.mdx @@ -0,0 +1,55 @@ +--- +title: Program Examples +description: Program example repository for compressed accounts with tests. +--- + + +
+ + Ask DeepWiki + + to query the program examples in natural language. +
+
+ +## Basic Operations + +* [**basic-operations/anchor**](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/anchor) - Anchor program with Rust and TypeScript tests +* [**basic-operations/native-rust**](https://github.com/Lightprotocol/program-examples/tree/main/basic-operations/native-rust) - Native Solana program with `light-sdk` and Rust tests. + + +Basic Operations include: +- **create** - Initialize a new compressed account. +- **update** - Modify data in an existing compressed account. +- **close** - Clear account data and preserve its address. +- **reinit** - Reinitialize a closed account with the same address. +- **burn** - Permanently delete a compressed account. + + +## Counter Program + +Full compressed account lifecycle (create, increment, decrement, reset, close): + +* [**counter/anchor**](https://github.com/Lightprotocol/program-examples/tree/main/counter/anchor) - Anchor program with Rust and TypeScript tests +* [**counter/native**](https://github.com/Lightprotocol/program-examples/tree/main/counter/native) - Native Solana program with `light-sdk` and Rust tests. +* [**counter/pinocchio**](https://github.com/Lightprotocol/program-examples/tree/main/counter/pinocchio) - Pinocchio program with `light-sdk-pinocchio` and Rust tests. + +## Create-and-update Program + +* [**create-and-update**](https://github.com/Lightprotocol/program-examples/tree/main/create-and-update) - Create a new compressed account and update an existing compressed account with a single validity proof in one instruction. + +## Create-and-read Program + +* [**read-only**](https://github.com/Lightprotocol/program-examples/tree/main/read-only) - Create a new compressed account and read it on-chain. + +## Compare compressed vs uncompressed Program + +* [**account-comparison**](https://github.com/Lightprotocol/program-examples/tree/main/account-comparison) - Compare compressed vs regular Solana accounts. + +## ZK-ID Program + +* [**zk-id**](https://github.com/Lightprotocol/program-examples/tree/main/zk-id) - A minimal Solana program that uses zero-knowledge proofs for identity verification with compressed accounts. + +## Build your own Program + + diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides.mdx new file mode 100644 index 0000000..8fbdbea --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides.mdx @@ -0,0 +1,15 @@ +--- +title: Advanced Guides +description: "Reference table to implementation guides. Guides for airdrops, using token-2022, and wallet support for compressed tokens." +sidebarTitle: "Overview" +--- + +| Guide | Description | +| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| [Combine Instructions in One Transaction](https://github.com/Lightprotocol/developer-content/blob/main/zk-compression-docs/compressed-tokens/guides/how-to-combine-operations-in-one-transaction.md) | Combine multiple instructions in a single transaction using instruction-level APIs | +| [Create an Airdrop without Claim](/compressed-tokens/advanced-guides/create-an-airdrop) | Create an airdrop that appears directly in recipients' wallets (with or without code) | +| [Example Airdrop with Claim](https://github.com/Lightprotocol/example-compressed-claim) | Demo for time-locked airdrop with compressed tokens | +| [Add Wallet Support for Compressed Tokens](/compressed-tokens/advanced-guides/add-wallet-support-for-compressed-tokens) | Add compressed token support in your wallet application | +| [Use Token-2022 with Compression](/compressed-tokens/advanced-guides/use-token-2022-with-compression) | Create compressed Token-2022 mints with metadata and other extensions | +| [Example Web Client](https://github.com/Lightprotocol/example-web-client) | Demonstrates how to use @lightprotocol/stateless.js in a browser environment to interact with ZK Compression | +| [Example Node.js Client](https://github.com/Lightprotocol/example-nodejs-client) | Script to execute basic compression/decompression/transfers | diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/add-wallet-support-for-compressed-tokens.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/add-wallet-support-for-compressed-tokens.mdx new file mode 100644 index 0000000..d22c7fd --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/add-wallet-support-for-compressed-tokens.mdx @@ -0,0 +1,632 @@ +--- +title: Add Wallet Support for Compressed Tokens +description: Guide to add Compressed Token Support to Your Wallet Application +--- + +## Best Practices + +* **Clear UI Indicators —** Provide clear visual distinctions between compressed and uncompressed SPL tokens +* **Transaction History** — Provide detailed transaction histories for compressed tokens +* **Decompression and Compression** — Provide a clear path for users to convert between compressed and uncompressed tokens when needed + + +Leading Solana Wallets like Phantom and Backpack already support compressed tokens. + + +## Integration Steps + + + + +### Display Compressed Token Balances + +```javascript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const connection: Rpc = createRpc(); +const publicKey = new PublicKey('CLEuMG7pzJX9xAuKCFzBP154uiG1GaNo4Fq7x6KAcAfG'); + +(async () => { + const balances = await connection.getCompressedTokenBalancesByOwnerV2(publicKey); + console.log(balances); +})(); +``` + +### Get Transaction History + +```javascript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const connection: Rpc = createRpc(); +const publicKey = new PublicKey('CLEuMG7pzJX9xAuKCFzBP154uiG1GaNo4Fq7x6KAcAfG'); + +(async () => { + const signatures = await connection.getCompressionSignaturesForOwner(publicKey); + console.log(signatures); + + if (signatures.items.length > 0) { + const parsedTransaction = await connection.getTransactionWithCompressionInfo(signatures.items[0].signature); + console.log(parsedTransaction); + } +})(); +``` + +### Send Compressed Tokens + +```typescript send-compressed-tokens.ts expandable +import { + Rpc, + createRpc, + bn, + dedupeSigner, + sendAndConfirmTx, + buildAndSignTx, +} from "@lightprotocol/stateless.js"; +import { + CompressedTokenProgram, + selectMinCompressedTokenAccountsForTransfer, +} from "@lightprotocol/compressed-token"; +import { ComputeBudgetProgram, Keypair, PublicKey } from "@solana/web3.js"; + +const connection: Rpc = createRpc(); +const mint = new PublicKey("MINT_ADDRESS"); +const payer = PAYER_KEYPAIR; +const owner = payer; +const recipient = Keypair.generate(); +const amount = bn(1e8); + +(async () => { + const compressedTokenAccounts = + await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { mint }); + + if (compressedTokenAccounts.items.length === 0) { + console.log("No compressed token accounts found"); + return; + } + + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer( + compressedTokenAccounts.items, + amount + ); + + const proof = await connection.getValidityProof( + inputAccounts.map((account) => account.compressedAccount.hash) + ); + + const ix = await CompressedTokenProgram.transfer({ + payer: payer.publicKey, + inputCompressedTokenAccounts: inputAccounts, + toAddress: recipient.publicKey, + amount, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); + + const { blockhash } = await connection.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix], + payer, + blockhash, + additionalSigners + ); + + const transferTxId = await sendAndConfirmTx(connection, signedTx); + console.log(`Transaction: ${transferTxId}`); +})(); +``` + + + + + + + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace \ with your API key before running. + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + + + +This example fetches and displays all compressed token balances for a wallet address. + +```javascript +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +// 1. Setup RPC connection to local test validator +// 2. Call getCompressedTokenBalancesByOwnerV2() to fetch compressed token balances per mint +// 3. Display results with balance amounts and mint addresses + +const connection: Rpc = createRpc(); // defaults to localhost:8899 +const publicKey = new PublicKey('CLEuMG7pzJX9xAuKCFzBP154uiG1GaNo4Fq7x6KAcAfG'); // public + +(async () => { + // Fetch compressed token balances for wallet address + // Returns balance for owner per mint - can optionally apply filter: {mint, limit, cursor} + const balances = await connection.getCompressedTokenBalancesByOwnerV2(publicKey); + console.log(balances); +})(); +``` + + + + +This example retrieves compression transaction signatures and detailed transaction information for wallet transaction history display. + +```javascript expandable +import { Rpc, createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +// 1. Setup RPC connection and fetch compression transaction signatures using getCompressionSignaturesForOwner() +// 2. Retrieve detailed transaction data with getTransactionWithCompressionInfo() including pre/post balances +// 3. Display transaction history with signature list and balance changes + +const connection: Rpc = createRpc(); // defaults to localhost:8899 +const publicKey = new PublicKey('CLEuMG7pzJX9xAuKCFzBP154uiG1GaNo4Fq7x6KAcAfG'); + +(async () => { + // Fetch compression transaction signatures for wallet address + // Returns confirmed signatures for compression transactions involving the specified account owner + const signatures = await connection.getCompressionSignaturesForOwner(publicKey); + console.log(signatures); + + // Check if any signatures exist before trying to access them + if (signatures.items.length > 0) { + // Retrieve detailed transaction information with compression data + // Returns pre- and post-compressed token balances grouped by owner + const parsedTransaction = await connection.getTransactionWithCompressionInfo(signatures.items[0].signature); + console.log(parsedTransaction); + } else { + console.log("No compression transactions found for this address"); + } +})(); +``` + + + + +First, set up a test mint to and mint 10 compressed tokens to your filesystem 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 token pool 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 token pool 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 token pool for compression + payer.publicKey, // recipient address + payer, + 10e9, + ); + + console.log(`\nMinted ${10e9 / 1e9} compressed token`); + console.log(`Transaction: ${mintToTxId}`); +})(); +``` + + + + +Make sure you add your Mint address to `send-tokens.ts`. + + +```typescript send-tokens.ts expandable +// Compressed Token Transfer - Local +// 1. Load wallet and fetch compressed token accounts with getCompressedTokenAccountsByOwner() +// 2. Select accounts for transfer using selectMinCompressedTokenAccountsForTransfer() +// and get validity proof with getValidityProof() +// 3. Create transfer instruction with CompressedTokenProgram.transfer() +// and submit transaction with sendAndConfirmTx() +// 4. Verify balances via getCompressedTokenAccountsByOwner() + +import { + Rpc, + createRpc, + bn, + dedupeSigner, + sendAndConfirmTx, + buildAndSignTx, +} from "@lightprotocol/stateless.js"; +import { + CompressedTokenProgram, + selectMinCompressedTokenAccountsForTransfer, +} from "@lightprotocol/compressed-token"; +import { ComputeBudgetProgram, Keypair, PublicKey } from "@solana/web3.js"; +import * as fs from 'fs'; +import * as os from 'os'; + +// Step 1: Setup RPC connection and define transfer parameters +const connection: Rpc = createRpc(); // defaults to localhost:8899 +const mint = new PublicKey("MINT ADDRESS"); // Replace with mint address + +// 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 owner = payer; + +const recipient = Keypair.generate(); +const amount = bn(1e8); + +(async () => { + // Step 2: Fetch compressed account hashes from state trees + const compressedTokenAccounts = + await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { + mint, // SPL mint with token pool for compression + }); + + if (compressedTokenAccounts.items.length === 0) { + console.log("No compressed token accounts found for this mint"); + return; + } + + // Show initial sender balance + const initialBalance = compressedTokenAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + console.log(`Sender balance: ${initialBalance / 1e8} compressed tokens`); + + // Step 3: Select minimum compressed accounts for transfer amount + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer( + compressedTokenAccounts.items, + amount + ); + + // Get validity proof for Merkle tree verification + const proof = await connection.getValidityProof( + inputAccounts.map((account) => account.compressedAccount.hash) + ); + + // Step 4: Create transfer instruction that consumes input accounts and creates new output accounts + const ix = await CompressedTokenProgram.transfer({ + payer: payer.publicKey, + inputCompressedTokenAccounts: inputAccounts, // accounts to consume + toAddress: recipient.publicKey, + amount, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); + + // Step 5: Build, sign, and submit transaction + const { blockhash } = await connection.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix], + payer, + blockhash, + additionalSigners + ); + const transferTxId = await sendAndConfirmTx(connection, signedTx); + + console.log(`\nTransferred ${amount.toNumber() / 1e8} compressed tokens`); + console.log(`Transaction: ${transferTxId}`); + console.log(`Recipient: ${recipient.publicKey.toString()}`); + + // Step 6: Verify via getCompressedTokenAccountsByOwner + const senderCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(payer.publicKey, { mint }); + const senderBalance = senderCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + const recipientCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(recipient.publicKey, { mint }); + const recipientBalance = recipientCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + console.log(`\nSummary compressed token balances:`); + console.log(`Sender balance: ${senderBalance / 1e8} compressed tokens`); + console.log(`Recipient balance: ${recipientBalance / 1e8} compressed token`); + + return transferTxId; +})(); +``` + + + + + + + +## Advanced Integrations + +Use these integrations to let users convert between regular and compressed format as needed. + + + + +This example converts compressed tokens to regular SPL format using `CompressedTokenProgram.decompress().` + +```typescript +import { + bn, + buildAndSignTx, + sendAndConfirmTx, + dedupeSigner, + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; +import { ComputeBudgetProgram } from "@solana/web3.js"; +import { + CompressedTokenProgram, + getTokenPoolInfos, + selectMinCompressedTokenAccountsForTransfer, + selectTokenPoolInfosForDecompression, +} from "@lightprotocol/compressed-token"; + +// 1. Setup RPC connection and fetch compressed token accounts with getCompressedTokenAccountsByOwner() +// 2. Select accounts and token pool infos using selectMinCompressedTokenAccountsForTransfer() and selectTokenPoolInfosForDecompression() +// 3. Create decompress instruction with CompressedTokenProgram.decompress() and submit transaction + +// Step 1: Setup RPC connection and define decompression parameters +const connection: Rpc = createRpc("https://mainnet.helius-rpc.com?api-key=";); +const payer = PAYER_KEYPAIR; +const owner = PAYER_KEYPAIR; +const mint = MINT_ADDRESS; +const amount = 1e5; // 100K tokens to decompress + +(async () => { + // 1. Fetch compressed token accounts + const compressedTokenAccounts = + await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { + mint, + }); + + // 2. Select + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer( + compressedTokenAccounts.items, + bn(amount) + ); + + // 3. Fetch validity proof + const proof = await connection.getValidityProof( + inputAccounts.map((account) => account.compressedAccount.hash) + ); + + // 4. Fetch & Select tokenPoolInfos + const tokenPoolInfos = await getTokenPoolInfos(connection, mint); + const selectedTokenPoolInfos = selectTokenPoolInfosForDecompression( + tokenPoolInfos, + amount + ); + + // 5. Build instruction + const ix = await CompressedTokenProgram.decompress({ + payer: payer.publicKey, + inputCompressedTokenAccounts: inputAccounts, + toAddress: owner.publicKey, + amount, + tokenPoolInfos: selectedTokenPoolInfos, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); + + + // 6. Sign, send, and confirm. + // Example with keypair: + const { blockhash } = await connection.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix], + payer, + blockhash, + additionalSigners + ); + + return await sendAndConfirmTx(connection, signedTx); +})(); +``` + + + + + +This example converts regular SPL tokens to compressed format using `CompressedTokenProgram.compress().` + +```typescript +// 1. Setup RPC connection and get user ATA with getOrCreateAssociatedTokenAccount() +// 2. Fetch state tree and token pool infos using getStateTreeInfos() and getTokenPoolInfos() +// 3. Create compress instruction with CompressedTokenProgram.compress() and submit transaction + + +import { + buildAndSignTx, + sendAndConfirmTx, + Rpc, + createRpc, + selectStateTreeInfo, +} from "@lightprotocol/stateless.js"; +import { ComputeBudgetProgram } from "@solana/web3.js"; +import { + CompressedTokenProgram, + getTokenPoolInfos, + selectTokenPoolInfo, +} from "@lightprotocol/compressed-token"; +import { getOrCreateAssociatedTokenAccount } from "@solana/spl-token"; + +// Step 1: Setup RPC connection and define compression parameters +const connection: Rpc = createRpc( + "https://mainnet.helius-rpc.com?api-key=" +); + const payer = ; + const mint = ; +const amount = 1e5; // 100K tokens to compress + +(async () => { + // Step 2: Get or create associated token account for SPL tokens + const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + payer, // fee payer + mint, // token mint address + payer.publicKey // token account owner + ); + + // Step 3: Fetch and select state tree info for compression + const treeInfos = await connection.getStateTreeInfos(); + const treeInfo = selectStateTreeInfo(treeInfos); + + // Step 4: Fetch and select token pool info for compression + const tokenPoolInfos = await getTokenPoolInfos(connection, mint); + const tokenPoolInfo = selectTokenPoolInfo(tokenPoolInfos); + + // Step 5: Create compress instruction - transfer SPL tokens to pool and create compressed accounts + const compressInstruction = await CompressedTokenProgram.compress({ + payer: payer.publicKey, // fee payer + owner: payer.publicKey, // owner of source SPL tokens + source: sourceTokenAccount.address, // source ATA address + toAddress: payer.publicKey, // recipient of compressed tokens (self) + amount, // amount to compress + mint, // token mint address + outputStateTreeInfo: treeInfo, // state tree for compressed accounts + tokenPoolInfo, // token pool for compression + }); + + // Step 6: Build, sign, and submit compression transaction + const { blockhash } = await connection.getLatestBlockhash(); + const tx = buildAndSignTx( + [ + ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), + compressInstruction, + ], + payer, // transaction signer + blockhash, + [payer] // additional signers + ); + await sendAndConfirmTx(connection, tx); +})(); +``` + + + + +## Common Errors + + + + +If `getCompressedTokenBalancesByOwnerV2` returns empty: + +* Ensure the wallet has compressed tokens (not regular SPL tokens) +* Verify you're on the correct network (devnet/mainnet) + + + + +## Next Steps + +Take a look at other compressed token guides. + diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/create-an-airdrop-with-claim.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/create-an-airdrop-with-claim.mdx new file mode 100644 index 0000000..2ed3b10 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/create-an-airdrop-with-claim.mdx @@ -0,0 +1,4 @@ +--- +title: Create an Airdrop with Claim +url: "https://github.com/Lightprotocol/example-compressed-claim" +--- diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/create-an-airdrop.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/create-an-airdrop.mdx new file mode 100644 index 0000000..028b621 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/create-an-airdrop.mdx @@ -0,0 +1,1042 @@ +--- +title: Create an Airdrop without Claim +description: Complete guide to create an airdrop – with or without code. Access to cost calculation and best practices. ZK compression is the most efficient way to distribute SPL tokens. +--- + +## Guides + +There are two ways to use ZK Compression to distribute your SPL tokens. + + + Use **Airship by Helius Labs** to airdrop to up to 200,000 recipients via Webapp. + + + Create a programmatic airdrop with this guide for more control. + + + + +### Cost Comparison + + +You can use the [Airship Calculator ](https://airship.helius.dev/calculator)to anticipate the cost of your airdrop. + + +| Airdrop Size | Regular Airdrop | ZK Compression Airdrop | +| :----------- | :--------------------- | :-------------------------- | +| 10,000 | 20.4 SOL (*$4,080) | **0.0065 SOL (*$1.3)** | +| 100,000 | 203.96 SOL (*$40,080) | **0.065 SOL (*$13)** | +| 1,000,000 | 2039.28 SOL (*$400,080)| **0.65 SOL (*$130)** | + +_\*\* assuming $200 per SOL_ + +## Programmatic Airdrop + +Choose your implementation based on your needs: + +| Tab | Best For | What You'll Get | Time | +|:-------------|:-------------|:-------------|:-------------| +| **Implementation Steps** | First-time users, learning | Step-by-step Localnet tutorial | 20 min | +| **Simple Airdrop** | \<10,000 recipients | Production-ready single script | 10 min | +| **Airdrop with Batched Instructions** | 10,000+ recipients | Batched system with retry logic | 15 min | + + + + + +**What you'll build:** A test airdrop sending compressed tokens to 3 recipients on your local validator. + + + + + +Make sure you have dependencies and developer environment set up! + + +System Requirements + +* **Node.js >= 20.18.0** (required by latest Solana packages) +* npm or yarn package manager + + + + +### Dependencies + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +#### Developer Environment + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace \ with your API key before running. + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + + + + +Run this `mint-spl-tokens.ts` to mint SPL tokens to your wallet. + + +```typescript mint-spl-tokens.ts expandable +// Mint SPL Tokens for Airdrop - LocalNet +// 1. Load wallet and connect to local validator +// 2. Create SPL mint with token pool for compression via createMint() +// 3. Create ATA and mint SPL tokens to sender for airdrop preparation +// 4. Output mint address for use in simple-airdrop.ts + +import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; +import { + createMint, + getOrCreateAssociatedTokenAccount, + mintTo, +} from "@solana/spl-token"; +import { createTokenPool } from "@lightprotocol/compressed-token"; +import * as fs from 'fs'; +import * as os from 'os'; + +// Step 1: Setup local connection and load wallet +const connection = 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)); + +(async () => { + // Step 2: Create SPL mint with token pool for compression + const mint = await createMint(connection, payer, payer.publicKey, null, 9); + const poolTxId = await createTokenPool(connection, payer, mint); + console.log(`Mint address: ${mint.toBase58()}`); + console.log(`TokenPool created: ${poolTxId}`); + + // Step 3: Create associated token account for sender + // The sender will send tokens from this account to the recipients as compressed tokens. + const ata = await getOrCreateAssociatedTokenAccount( + connection, + payer, + mint, // SPL mint with token pool for compression + payer.publicKey + ); + console.log(`ATA address: ${ata.address.toBase58()}`); + + // Step 4: Mint SPL tokens to ATA. + // The sender will send tokens from this account to the recipients as compressed tokens. + const mintToTxId = await mintTo( + connection, + payer, + mint, // SPL mint with token pool for compression + ata.address, // distributor ATA + payer.publicKey, + 100_000_000_000 // amount: 100 tokens with 9 decimals + ); + console.log(`\nSPL tokens minted and ready for distribution!`); + console.log(`Transaction: ${mintToTxId}`); + + console.log(`\nCopy mint address to your airdrop script: ${mint.toBase58()}`); +})(); +``` + + + + +Next, distribute the SPL tokens to all recipients. + + +Ensure you have the latest `@lightprotocol/stateless.js` and `@lightprotocol/compressed-token` versions `≥ 0.21.0`! + + +```typescript simple-airdrop.ts expandable highlight={29-30,45,74,100} +// Simple Airdrop - LocalNet +// 1. Load wallet and select compression infrastructure with getStateTreeInfos() and getTokenPoolInfos() +// 2. Build CompressedTokenProgram.compress() instruction for multiple recipients in one transaction +// 3. Execute transaction with compute budget and confirm compression operation with sendAndConfirmTx() +// 4. Verify distribution via getCompressedTokenAccountsByOwner + +import { Keypair, PublicKey, ComputeBudgetProgram } from "@solana/web3.js"; +import { + CompressedTokenProgram, + getTokenPoolInfos, + selectTokenPoolInfo, +} from "@lightprotocol/compressed-token"; +import { + bn, + buildAndSignTx, + calculateComputeUnitPrice, + createRpc, + dedupeSigner, + Rpc, + selectStateTreeInfo, + sendAndConfirmTx, +} from "@lightprotocol/stateless.js"; +import { getOrCreateAssociatedTokenAccount } from "@solana/spl-token"; +import * as fs from 'fs'; +import * as os from 'os'; + +// Step 1: Setup local connection and load wallet +const connection: Rpc = createRpc(); // defaults to localhost:8899 +const mint = new PublicKey("MINTADDRESS"); // Replace with mint address from mint-spl-tokens.ts +// Local uses file wallet. Use constants from .env file in production +const walletPath = `${os.homedir()}/.config/solana/id.json`; +const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); +const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); +const owner = payer; + +(async () => { + // Step 2: Select state tree and token pool + const activeStateTrees = await connection.getStateTreeInfos(); + const treeInfo = selectStateTreeInfo(activeStateTrees); + + const infos = await getTokenPoolInfos(connection, mint); + const info = selectTokenPoolInfo(infos); + + // Step 3: Get or create source token account for distribution + // The sender will send tokens from this account to the recipients as compressed tokens. + const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + payer, + mint, // SPL mint with token pool for compression + payer.publicKey + ); + + // Step 4: Define airdrop recipients and amounts + const airDropAddresses = [ + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, + ]; + + const amounts = [ + bn(20_000_000_000), // 20 tokens + bn(30_000_000_000), // 30 tokens + bn(40_000_000_000), // 40 tokens + ]; + + const totalAmount = amounts.reduce((sum, amt) => sum + amt.toNumber(), 0); + console.log(`Distributing ${totalAmount / 1e9} compressed tokens to ${airDropAddresses.length} recipients`); + + const initialSplBalance = await connection.getTokenAccountBalance(sourceTokenAccount.address); + console.log(`Sender initial balance: ${initialSplBalance.value.uiAmount} tokens`); + + // Step 5: Build transaction with compute budget and compression instruction + const instructions = []; + // Set compute unit limits based on recipient count (estimated 120k CU per recipient) + instructions.push( + ComputeBudgetProgram.setComputeUnitLimit({ units: 120_000 * airDropAddresses.length }), + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: calculateComputeUnitPrice(20_000, 120_000 * airDropAddresses.length), // dynamic priority fee + }) + ); + + // Create compression instruction for multiple recipients in one transaction + const compressInstruction = await CompressedTokenProgram.compress({ + payer: payer.publicKey, + owner: owner.publicKey, + source: sourceTokenAccount.address, // source ATA holding SPL tokens + toAddress: airDropAddresses, // recipient addresses for compressed tokens + amount: amounts, // different amounts for each recipient + mint, // SPL mint with token pool for compression + tokenPoolInfo: info, + outputStateTreeInfo: treeInfo, // destination state tree + }); + instructions.push(compressInstruction); + + // Step 6: Sign and send transaction + const additionalSigners = dedupeSigner(payer, [owner]); + const { blockhash } = await connection.getLatestBlockhash(); + const tx = buildAndSignTx(instructions, payer, blockhash, additionalSigners); + + // For production: Add address lookup table to reduce transaction size and fees + // const lookupTableAddress = new PublicKey("9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ"); // mainnet // or "qAJZMgnQJ8G6vA3WRcjD9Jan1wtKkaCFWLWskxJrR5V" for devnet + // const lookupTableAccount = (await connection.getAddressLookupTable(lookupTableAddress)).value!; + // const tx = buildAndSignTx(instructions, payer, blockhash, additionalSigners, [lookupTableAccount]); + const txId = await sendAndConfirmTx(connection, tx); + + console.log(`\nAirdrop completed!`); + console.log(`Transaction: ${txId}`); + + // Step 7: Verify distribution via getCompressedTokenAccountsByOwner + for (let i = 0; i < airDropAddresses.length; i++) { + const recipientAccounts = await connection.getCompressedTokenAccountsByOwner(airDropAddresses[i], { mint }); + const balance = recipientAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + console.log(`Recipient ${i + 1} (${airDropAddresses[i].toString()}): ${balance / 1e9} compressed tokens`); + } + + const finalSplBalance = await connection.getTokenAccountBalance(sourceTokenAccount.address); + console.log(`\nSender balance after airdrop: ${finalSplBalance.value.uiAmount} SPL tokens`); + + return txId; +})(); +``` + + + + + + + +For small airdrops (\<10,000 recipients). [View the source code here](https://github.com/Lightprotocol/example-token-distribution/blob/main/src/simple-airdrop/simple-airdrop.ts). + + + + + +Configure your environment variables: + +```bash .env +PAYER_KEYPAIR=YOUR_BASE58_ENCODED_PRIVATE_KEY +MINT_ADDRESS=YOUR_MINT_ADDRESS +``` + + + + +Mint SPL tokens to your wallet for distribution. See the [mint script example](https://github.com/Lightprotocol/example-token-distribution/blob/main/src/simple-airdrop/mint.ts). + + +You can also use an existing mint if you already have one. + + + + + +Run the airdrop script with your configured environment: + +```typescript expandable +// 1. Load environment and select compression infrastructure with getStateTreeInfos() and getTokenPoolInfos() +// 2. Build CompressedTokenProgram.compress() instruction for multiple recipients in one transaction +// 3. Execute transaction with compute budget, address lookup table, and confirm with sendAndConfirmTx() +// 4. Verify distribution via getCompressedTokenAccountsByOwner + +import { + PublicKey, + TransactionInstruction, + ComputeBudgetProgram, +} from '@solana/web3.js'; +import { + CompressedTokenProgram, + getTokenPoolInfos, + selectTokenPoolInfo, +} from '@lightprotocol/compressed-token'; +import { + bn, + buildAndSignTx, + calculateComputeUnitPrice, + createRpc, + dedupeSigner, + Rpc, + selectStateTreeInfo, + sendAndConfirmTx, +} from '@lightprotocol/stateless.js'; +import { getOrCreateAssociatedTokenAccount } from '@solana/spl-token'; +import { MINT_ADDRESS, PAYER_KEYPAIR, RPC_ENDPOINT } from '../constants'; + +(async () => { + const connection: Rpc = createRpc(RPC_ENDPOINT); + const mintAddress = MINT_ADDRESS; + const payer = PAYER_KEYPAIR; + const owner = payer; + const recipients = [ + PublicKey.default, + // ... + ]; + + // 1. Select a state tree + const treeInfos = await connection.getStateTreeInfos(); // Fixed: removed deprecated getCachedActiveStateTreeInfos + const treeInfo = selectStateTreeInfo(treeInfos); + + // 2. Select a token pool + const tokenPoolInfos = await getTokenPoolInfos(connection, mintAddress); + const tokenPoolInfo = selectTokenPoolInfo(tokenPoolInfos); + + // Create an SPL token account for the sender. + // The sender will send tokens from this account to the recipients as compressed tokens. + const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + payer, + mintAddress, + payer.publicKey, + ); + + // 1 recipient = 120_000 CU + // 5 recipients = 170_000 CU + const units = 120_000; + const amount = bn(333); + // To land faster, replace this with a dynamic fee based on network + // conditions. + const microLamports = calculateComputeUnitPrice(20_000, units); + + const instructions: TransactionInstruction[] = [ + ComputeBudgetProgram.setComputeUnitLimit({ units }), + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports, + }), + ]; + + const compressInstruction = await CompressedTokenProgram.compress({ + payer: payer.publicKey, + owner: owner.publicKey, + source: sourceTokenAccount.address, + toAddress: recipients, + amount: recipients.map(() => amount), + mint: mintAddress, + outputStateTreeInfo: treeInfo, + tokenPoolInfo, + }); + instructions.push(compressInstruction); + + // https://www.zkcompression.com/developers/protocol-addresses-and-urls#lookup-tables + const lookupTableAddress = new PublicKey( + '9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ', // mainnet + // "qAJZMgnQJ8G6vA3WRcjD9Jan1wtKkaCFWLWskxJrR5V" // devnet + ); + + // Get the lookup table account state + const lookupTableAccount = ( + await connection.getAddressLookupTable(lookupTableAddress) + ).value!; + + const additionalSigners = dedupeSigner(payer, [owner]); + + const { blockhash } = await connection.getLatestBlockhash(); + + const tx = buildAndSignTx( + instructions, + payer, + blockhash, + additionalSigners, + [lookupTableAccount], + ); + + const txId = await sendAndConfirmTx(connection, tx); + console.log(`txId: ${txId}`); +})(); +``` + + + + + + + + + +For large-scale airdrops (10,000+ recipients) we recommend batched instructions.\ +[View the source code here.](https://github.com/Lightprotocol/example-token-distribution/tree/main/src/optimized-airdrop) + + + +This implementation creates the mint and executes the airdrop in a single operation. You only need to configure your RPC endpoint and payer keypair. + + + + + +Process recipients in chunks and create batched instructions with optimized compute limits. + +```typescript create-instructions.ts expandable + +// 1. Process recipients in chunks with selectStateTreeInfo() and selectTokenPoolInfo() for each batch +// 2. Create CompressedTokenProgram.compress() instructions with ComputeBudgetProgram limits for multiple recipients +// 3. Return batched instructions for optimized large-scale airdrop execution + +import { + CompressedTokenProgram, + TokenPoolInfo, +} from "@lightprotocol/compressed-token"; +import { + bn, + selectStateTreeInfo, + StateTreeInfo, +} from "@lightprotocol/stateless.js"; +import { + ComputeBudgetProgram, + TransactionInstruction, + PublicKey, +} from "@solana/web3.js"; + +interface CreateAirdropInstructionsParams { + amount: number | bigint; + recipients: PublicKey[]; + payer: PublicKey; + sourceTokenAccount: PublicKey; + mint: PublicKey; + stateTreeInfos: StateTreeInfo[]; + tokenPoolInfos: TokenPoolInfo[]; + maxRecipientsPerInstruction?: number; + maxInstructionsPerTransaction?: number; + computeUnitLimit?: number; + computeUnitPrice?: number | undefined; +} + +export type InstructionBatch = TransactionInstruction[]; + +export async function createAirdropInstructions({ + amount, + recipients, + payer, + sourceTokenAccount, + mint, + stateTreeInfos, + tokenPoolInfos, + maxRecipientsPerInstruction = 5, + maxInstructionsPerTransaction = 3, + computeUnitLimit = 500_000, + computeUnitPrice = undefined, +}: CreateAirdropInstructionsParams): Promise { + const instructionBatches: InstructionBatch[] = []; + const amountBn = bn(amount.toString()); + + // Process recipients in chunks + for ( + let i = 0; + i < recipients.length; + i += maxRecipientsPerInstruction * maxInstructionsPerTransaction + ) { + const instructions: TransactionInstruction[] = []; + + instructions.push( + ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnitLimit }) + ); + if (computeUnitPrice) { + instructions.push( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: computeUnitPrice, + }) + ); + } + + const treeInfo = selectStateTreeInfo(stateTreeInfos); + const tokenPoolInfo = selectTokenPoolInfo(tokenPoolInfos); + + for (let j = 0; j < maxInstructionsPerTransaction; j++) { + const startIdx = i + j * maxRecipientsPerInstruction; + const recipientBatch = recipients.slice( + startIdx, + startIdx + maxRecipientsPerInstruction + ); + + if (recipientBatch.length === 0) break; + + const compressIx = await CompressedTokenProgram.compress({ + payer, + owner: payer, + source: sourceTokenAccount, + toAddress: recipientBatch, + amount: recipientBatch.map(() => amountBn), + mint, + tokenPoolInfo, + outputStateTreeInfo: treeInfo, + }); + + instructions.push(compressIx); + } + + if ( + (computeUnitPrice && instructions.length > 2) || + (!computeUnitPrice && instructions.length > 1) + ) { + instructionBatches.push(instructions); + } + } + + return instructionBatches; +} +``` + + + + +Maintain fresh blockhashes with background refresh loop using `getLatestBlockhash()` every 30 seconds. + +```typescript update-blockhash.ts expandable +import { Rpc } from "@lightprotocol/stateless.js"; + +// 1. Fetch initial blockhash with getLatestBlockhash() and store in exported variable +// 2. Set up background refresh loop with setTimeout() to update blockhash every 30 seconds +// 3. Provide AbortSignal support to stop background updates when airdrop completes + +export let currentBlockhash: string; + +export async function updateBlockhash( + connection: Rpc, + signal: AbortSignal +): Promise { + try { + const { blockhash } = await connection.getLatestBlockhash(); + currentBlockhash = blockhash; + console.log(`Initial blockhash: ${currentBlockhash}`); + } catch (error) { + console.error("Failed to fetch initial blockhash:", error); + return; + } + + // Update blockhash in the background + (function updateInBackground() { + if (signal.aborted) return; + const timeoutId = setTimeout(async () => { + if (signal.aborted) return; + try { + const { blockhash } = await connection.getLatestBlockhash(); + currentBlockhash = blockhash; + console.log(`Updated blockhash: ${currentBlockhash}`); + } catch (error) { + console.error("Failed to update blockhash:", error); + } + updateInBackground(); + }, 30_000); + + signal.addEventListener("abort", () => clearTimeout(timeoutId)); + })(); +} +``` + + + + +Execute batched transactions with `VersionedTransaction`, retry logic, and `sendAndConfirmTx()` confirmation. + +```typescript sign-and-send.ts expandable + +// 1. Initialize blockhash updates with updateBlockhash() and get address lookup table with getAddressLookupTable() +// 2. Process instruction batches with VersionedTransaction and retry logic for failed transactions +// 3. Yield batch results with sendAndConfirmTx() confirmation and comprehensive error handling + +import { Rpc, sendAndConfirmTx } from "@lightprotocol/stateless.js"; +import { + Keypair, + PublicKey, + TransactionMessage, + VersionedTransaction, +} from "@solana/web3.js"; +import { InstructionBatch } from "./create-instructions"; +import { currentBlockhash, updateBlockhash } from "./update-blockhash"; +import bs58 from "bs58"; + +export enum BatchResultType { + Success = "success", + Error = "error", +} + +export type BatchResult = + | { type: BatchResultType.Success; index: number; signature: string } + | { type: BatchResultType.Error; index: number; error: string }; + +export async function* signAndSendAirdropBatches( + batches: InstructionBatch[], + payer: Keypair, + connection: Rpc, + maxRetries = 3 +): AsyncGenerator { + const abortController = new AbortController(); + const { signal } = abortController; + + await updateBlockhash(connection, signal); + + const statusMap = new Array(batches.length).fill(0); // Initialize all as pending (0) + + // Use zk-compression look up table for your network + // https://www.zkcompression.com/developers/protocol-addresses-and-urls#lookup-tables + const lookupTableAddress = new PublicKey( + "9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ" + ); + + // Get the lookup table account + const lookupTableAccount = ( + await connection.getAddressLookupTable(lookupTableAddress) + ).value!; + + while (statusMap.includes(0)) { + // Continue until all are confirmed or errored + const pendingBatches = statusMap.filter((status) => status === 0).length; + console.log(`Sending ${pendingBatches} transactions`); + + const sends = statusMap.map(async (status, index) => { + if (status !== 0) return; // Skip non-pending batches + + let retries = 0; + while (retries < maxRetries && statusMap[index] === 0) { + if (!currentBlockhash) { + console.warn("Waiting for blockhash to be set..."); + await new Promise((resolve) => setTimeout(resolve, 1000)); + continue; + } + + try { + const tx = new VersionedTransaction( + new TransactionMessage({ + payerKey: payer.publicKey, + recentBlockhash: currentBlockhash, + instructions: batches[index], + }).compileToV0Message([lookupTableAccount]) + ); + tx.sign([payer]); + + const sig = bs58.encode(tx.signatures[0]); + console.log(`Batch ${index} signature: ${sig}`); + + const confirmedSig = await sendAndConfirmTx(connection, tx, { + skipPreflight: true, + commitment: "confirmed", + }); + + if (confirmedSig) { + statusMap[index] = 1; // Mark as confirmed + return { + type: BatchResultType.Success, + index, + signature: confirmedSig, + }; + } + } catch (e) { + retries++; + console.warn(`Retrying batch ${index}, attempt ${retries + 1}`); + if (retries >= maxRetries) { + statusMap[index] = `err: ${(e as Error).message}`; // Mark as error + return { + type: BatchResultType.Error, + index, + error: (e as Error).message, + }; + } + } + } + }); + + const results = await Promise.all(sends); + for (const result of results) { + if (result) yield result as BatchResult; + } + } + + // Stop the blockhash update loop + abortController.abort(); +} +``` + + + +Put it all together in the main airdrop file. + +```typescript airdrop.ts expandable +// 1. Create compressed mint with createMint(), mint supply with mintTo(), get infrastructure with getStateTreeInfos() and getTokenPoolInfos() +// 2. Generate batched compression instructions with createAirdropInstructions() - create CompressedTokenProgram.compress() calls +// 3. Execute batched airdrop with signAndSendAirdropBatches() - sign transactions and confirm with sendAndConfirmTx() for large-scale distribution + +import { Keypair, LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js"; +import { + calculateComputeUnitPrice, + createRpc, + Rpc, +} from "@lightprotocol/stateless.js"; +import { createMint, getTokenPoolInfos } from "@lightprotocol/compressed-token"; +import { getOrCreateAssociatedTokenAccount, mintTo } from "@solana/spl-token"; +import { createAirdropInstructions } from "./create-instructions"; +import { BatchResultType, signAndSendAirdropBatches } from "./sign-and-send"; +import dotenv from "dotenv"; +import bs58 from "bs58"; +dotenv.config(); + +// Step 1: Setup environment and RPC connection +const RPC_ENDPOINT = `https://mainnet.helius-rpc.com?api-key=${process.env.HELIUS_API_KEY}`; +const connection: Rpc = createRpc(RPC_ENDPOINT); +const PAYER = Keypair.fromSecretKey(bs58.decode(process.env.PAYER_KEYPAIR!)); + +// Step 2: Define airdrop recipient list (20 example addresses) +const recipients = [ + "GMPWaPPrCeZPse5kwSR3WUrqYAPrVZBSVwymqh7auNW7", + "GySGrTgPtPfMtYoYTmwUdUDFwVJbFMfip7QZdhgXp8dy", + "Bk1r2vcgX2uTzwV3AUyfRbSfGKktoQrQufBSrHzere74", + "8BvkadZ6ycFNmQF7S1MHRvEVNb1wvDBFdjkAUnxjK9Ug", + "EmxcvFKXsWLzUho8AhV9LCKeKRFHg5gAs4sKNJwhe5PF", + "6mqdHkSpcvNexmECjp5XLt9V9KnSQre9TvbMLGr6sEPM", + "3k4MViTWXBjFvoUZiJcNGPvzrqnTa41gcrbWCMMnV6ys", + "2k6BfYRUZQHquPtpkyJpUx3DzM7W3K6H95igtJk8ztpd", + "89jPyNNLCcqWn1RZThSS4jSqU5VCJkR5mAaSaVzuuqH4", + "3MzSRLf9jSt6d1MFFMMtPfUcDY6XziRxTB8C5mfvgxXG", + "9A1H6f3N8mpAPSdfqvYRD4cM1NwDZoMe3yF5DwibL2R2", + "PtUAhLvUsVcoesDacw198SsnMoFNVskR5pT3QvsBSQw", + "6C6W6WpgFK8TzTTMNCPMz2t9RaMs4XnkfB6jotrWWzYJ", + "8sLy9Jy8WSh6boq9xgDeBaTznn1wb1uFpyXphG3oNjL5", + "GTsQu2XCgkUczigdBFTWKrdDgNKLs885jKguyhkqdPgV", + "85UK4bjC71Jwpyn8mPSaW3oYyEAiHPbESByq9s5wLcke", + "9aEJT4CYHEUWwwSQwueZc9EUjhWSLD6AAbpVmmKDeP7H", + "CY8QjRio1zd9bYWMKiVRrDbwVenf3JzsGf5km5zLgY9n", + "CeHbdxgYifYhpB6sXGonKzmaejqEfq2ym5utTmB6XMVv", + "4z1qss12DjUzGUkK1fFesqrUwrEVJJvzPMNkwqYnbAR5", +].map((address) => new PublicKey(address)); + +(async () => { + // Step 3: Create compressed mint and register for compression + // 3a: Call createMint() to initialize mint with compression pool + const { mint, transactionSignature } = await createMint( + connection, + PAYER, // fee payer + PAYER.publicKey, // mint authority + 9 // decimals + ); + console.log( + `create-mint success! txId: ${transactionSignature}, mint: ${mint.toBase58()}` + ); + + // Step 4: Create associated token account for distributor + // 4a: Ensure PAYER has ATA for holding tokens before compression + const ata = await getOrCreateAssociatedTokenAccount( + connection, + PAYER, // fee payer + mint, // token mint + PAYER.publicKey // token owner + ); + console.log(`ATA: ${ata.address.toBase58()}`); + + // Step 5: Mint initial token supply to distributor + // 5a: Create 10 billion tokens in the ATA for airdrop distribution + const mintToTxId = await mintTo( + connection, + PAYER, // fee payer and mint authority + mint, // token mint + ata.address, // destination ATA + PAYER.publicKey, // mint authority + 10e9 * LAMPORTS_PER_SOL // amount: 10 billion tokens with decimals + ); + console.log(`mint-to success! txId: ${mintToTxId}`); + + // Step 6: Get compression infrastructure for batch operations + // 6a: Fetch available state trees for compressed account storage + const stateTreeInfos = await connection.getStateTreeInfos(); + + // 6b: Get token pool infos for compression operations + const tokenPoolInfos = await getTokenPoolInfos(connection, mint); + + // Step 7: Create instruction batches for large-scale airdrop + // 7a: Generate batched compression instructions with compute optimization + const instructionBatches = await createAirdropInstructions({ + amount: 1e6, // 1 million tokens per recipient + recipients, // array of recipient addresses + payer: PAYER.publicKey, // transaction fee payer + sourceTokenAccount: ata.address, // source ATA holding SPL tokens + mint, // token mint + stateTreeInfos, // state trees for compressed accounts + tokenPoolInfos, // token pools for compression + computeUnitPrice: calculateComputeUnitPrice(10_000, 500_000), // dynamic priority fee + }); + + // Step 8: Execute batched airdrop with error handling + // 8a: Process instruction batches with retry logic and confirmation + for await (const result of signAndSendAirdropBatches( + instructionBatches, + PAYER, + connection + )) { + if (result.type === BatchResultType.Success) { + console.log(`Batch ${result.index} confirmed: ${result.signature}`); + } else if (result.type === BatchResultType.Error) { + console.log(`Batch ${result.index} failed: ${result.error}`); + // Use result.index to access the specific batch in instructionBatches + const failedBatch = instructionBatches[result.index]; + console.log(`Failed batch instructions:`, failedBatch); + // Additional logic to handle failed instructions + } + } + + console.log("Airdrop process complete."); +})(); +``` + + + + + +### Advanced Features + + +Solana Wallets like Phantom and Backpack already support compressed tokens. +Still, you can let users decompress to SPL via your Frontend to customize claims. + + +* Full Example on Github to [create an Airdrop with Claim](https://github.com/Lightprotocol/example-compressed-claim). + +* Add decompression of SPL Tokens with this script. + +```typescript expandable +import { + bn, + buildAndSignTx, + sendAndConfirmTx, + dedupeSigner, + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; +import { ComputeBudgetProgram, Keypair, PublicKey } from "@solana/web3.js"; +import { + CompressedTokenProgram, + getTokenPoolInfos, + selectMinCompressedTokenAccountsForTransfer, + selectTokenPoolInfosForDecompression, +} from "@lightprotocol/compressed-token"; +import { getOrCreateAssociatedTokenAccount } from "@solana/spl-token"; +import bs58 from "bs58"; +import dotenv from "dotenv"; +dotenv.config(); + +// Set these values in your .env file +const RPC_ENDPOINT = process.env.RPC_ENDPOINT; +const mint = new PublicKey(process.env.MINT_ADDRESS!); +const payer = Keypair.fromSecretKey(bs58.decode(process.env.PAYER_KEYPAIR!)); + +const owner = payer; +const amount = 1e5; +const connection: Rpc = createRpc(RPC_ENDPOINT); + +(async () => { + // 1. Create an associated token account for the user if it doesn't exist + const ata = await getOrCreateAssociatedTokenAccount( + connection, + payer, + mint, + payer.publicKey + ); + + // 2. Fetch compressed token accounts + const compressedTokenAccounts = + await connection.getCompressedTokenAccountsByOwner(owner.publicKey, { + mint, + }); + + // 3. Select + const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer( + compressedTokenAccounts.items, + bn(amount) + ); + + // 4. Fetch validity proof + const proof = await connection.getValidityProof( + inputAccounts.map((account) => account.compressedAccount.hash) + ); + + // 5. Fetch token pool infos + const tokenPoolInfos = await getTokenPoolInfos(connection, mint); + + // 6. Select + const selectedTokenPoolInfos = selectTokenPoolInfosForDecompression( + tokenPoolInfos, + amount + ); + + // 7. Build instruction + const ix = await CompressedTokenProgram.decompress({ + payer: payer.publicKey, + inputCompressedTokenAccounts: inputAccounts, + toAddress: ata.address, + amount, + tokenPoolInfos: selectedTokenPoolInfos, + recentInputStateRootIndices: proof.rootIndices, + recentValidityProof: proof.compressedProof, + }); + + // 8. Sign, send, and confirm + const { blockhash } = await connection.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }), ix], + payer, + blockhash, + additionalSigners + ); + return await sendAndConfirmTx(connection, signedTx); +})(); + +``` + + +Set priority fees dynamically for decompression. Learn more [here](https://docs.helius.dev/guides/sending-transactions-on-solana#summary). + + +### Native Swap via Jup-API + +If you have a custom FE, you can let users swap compressed tokens using the Jup-API. A reference implementation is available [here](https://github.com/Lightprotocol/example-jupiter-swap-node). + +## Next Steps + +Explore more guides in our cookbook. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/example-node-js.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/example-node-js.mdx new file mode 100644 index 0000000..73d06e2 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/example-node-js.mdx @@ -0,0 +1,5 @@ +--- +title: "Example Node.js Client" +url: "https://github.com/Lightprotocol/example-nodejs-client" +--- + diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/example-web-client.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/example-web-client.mdx new file mode 100644 index 0000000..d5f244b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/example-web-client.mdx @@ -0,0 +1,5 @@ +--- +title: "Example Web Client" +url: "https://github.com/Lightprotocol/example-web-client" +--- + diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/how-to-combine-operations-in-one-transaction.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/how-to-combine-operations-in-one-transaction.mdx new file mode 100644 index 0000000..15103b1 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/how-to-combine-operations-in-one-transaction.mdx @@ -0,0 +1,262 @@ +--- +title: Combine Instructions in One Transaction +description: Guide to combine multiple instructions in a single transaction. Full code example for token pool creation and for first-time compression of existing SPL tokens. +--- + +The SDK provides instruction-level APIs that return instructions without sending transactions. Combine these instructions to build custom transactions with multiple instructions. + +This guide demonstrates creating a token pool and compressing existing SPL tokens in a single transaction. + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your API key before running. + + +Get your API Key [here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Create Token Pool + Compress + +```typescript create-pool-and-compress.ts highlight={26,71} expandable +// 1. Setup: Create regular SPL token and mint to ATA +// 2. Build instructions for create token pool and compress +// 3. Combine instructions in one transaction +// 4. Verify compressed balance + +import { + Keypair, + ComputeBudgetProgram, +} from '@solana/web3.js'; +import { + createRpc, + buildAndSignTx, + sendAndConfirmTx, + selectStateTreeInfo, +} from '@lightprotocol/stateless.js'; +import { CompressedTokenProgram } from '@lightprotocol/compressed-token'; +import { + createMint, + getOrCreateAssociatedTokenAccount, + mintTo, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token'; +import BN from 'bn.js'; + +async function createPoolAndCompress() { + // Step 1: Setup - Create regular SPL token and mint to ATA + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); + await rpc.confirmTransaction(airdropSignature); + + // Create regular SPL token mint + const mint = await createMint( + rpc, + payer, + payer.publicKey, + null, + 9, + undefined, + undefined, + TOKEN_PROGRAM_ID + ); + + // Create ATA and mint tokens to it + const ata = await getOrCreateAssociatedTokenAccount( + rpc, + payer, + mint, + payer.publicKey, + undefined, + undefined, + undefined, + TOKEN_PROGRAM_ID + ); + + await mintTo( + rpc, + payer, + mint, + ata.address, + payer, + 1_000_000_000, // 1 token with 9 decimals + undefined, + undefined, + TOKEN_PROGRAM_ID + ); + + console.log("Regular SPL token created:", mint.toBase58()); + console.log("ATA balance:", 1, "token"); + + // Step 2: Build instructions for create token pool and compress + const outputStateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); + + // Derive token pool PDA + const tokenPoolPda = CompressedTokenProgram.deriveTokenPoolPda(mint); + + // Create token pool instruction + const createTokenPoolIx = await CompressedTokenProgram.createTokenPool({ + feePayer: payer.publicKey, + mint, + tokenProgram: TOKEN_PROGRAM_ID, + }); + + // Manually construct TokenPoolInfo for first-time compression + const tokenPoolInfo = { + mint: mint, + tokenPoolPda: tokenPoolPda, + tokenProgram: TOKEN_PROGRAM_ID, + isInitialized: true, // Set to true even though pool will be created in this tx + balance: new BN(0), + poolIndex: 0, + bump: 0, // Placeholder value + }; + + // Create compress instruction + const compressIx = await CompressedTokenProgram.compress({ + outputStateTreeInfo, + tokenPoolInfo, + payer: payer.publicKey, + owner: payer.publicKey, + source: ata.address, + toAddress: payer.publicKey, + amount: new BN(1_000_000_000), + mint, + }); + + // Step 3: Combine instructions in one transaction + const { blockhash } = await rpc.getLatestBlockhash(); + + const allInstructions = [ + ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), + createTokenPoolIx, + compressIx, + ]; + + const tx = buildAndSignTx( + allInstructions, + payer, + blockhash, + [] + ); + + const txId = await sendAndConfirmTx(rpc, tx); + + console.log("Token pool created and tokens compressed"); + console.log("Transaction:", txId); + + // Step 4: Verify compressed balance + const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner( + payer.publicKey, + { mint } + ); + + const compressedBalance = compressedAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + + console.log("Compressed balance:", compressedBalance.toNumber() / 1_000_000_000, "tokens"); + + return { + transactionSignature: txId, + mint, + compressedBalance: compressedBalance.toNumber(), + }; +} + +createPoolAndCompress().catch(console.error); +``` + +## Next Steps + +Learn how to transfer compressed tokens. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/use-token-2022-with-compression.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/use-token-2022-with-compression.mdx new file mode 100644 index 0000000..9aa5c0c --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/advanced-guides/use-token-2022-with-compression.mdx @@ -0,0 +1,339 @@ +--- +title: Use Token-2022 with Compression +description: Complete guide to mint, compress and transfer tokens with Token-2022 Metadata with ZK Compression. +--- + +## What you will do + +With this guide you will mint, compress, and transfer tokens with Token-2022 Metadata. + +## Overview Token 2022 Extensions + +Token 2022 Extensions are optional features that can be added to Token 2022 mints on Solana to enable additional functionality. + +ZK Compression supports compressing the following mint-extensions: + +* MetadataPointer +* TokenMetadata +* InterestBearingConfig +* GroupPointer +* GroupMemberPointer +* TokenGroup +* TokenGroupMember + +All other extensions are not yet supported. + + +If you require support for other mint-extensions, [let us know](https://t.me/swen_light)! + + +## Get started + +### Prerequisites + + +You need the following SDK versions: + +* `@lightprotocol/stateless.js` ≥ 0.21.0 +* `@lightprotocol/compressed-token` ≥ 0.21.0 +* `@solana/web3.js` ≥ 1.95.3 + + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace \ with your API key before running. + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Mint, compress, and transfer tokens with Token-2022 Metadata + +Run `compress-t22.ts`. + +```typescript compress-t22.ts expandable +// Token-2022 with ZK Compression - Local +// 1. Load wallet and connect to local validator +// 2. Create Token-2022 mint with metadata extension and register for compression via createTokenPool() +// 3. Mint SPL tokens to ATA, compress via compress(), and transfer compressed tokens via transfer() +// 4. Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner + +import { confirmTx, createRpc } from "@lightprotocol/stateless.js"; +import { + compress, + createTokenPool, + transfer, +} from "@lightprotocol/compressed-token"; +import { + getOrCreateAssociatedTokenAccount, + mintTo as mintToSpl, + TOKEN_2022_PROGRAM_ID, + createInitializeMetadataPointerInstruction, + createInitializeMintInstruction, + ExtensionType, + getMintLen, + LENGTH_SIZE, + TYPE_SIZE, +} from "@solana/spl-token"; +import { + Keypair, + sendAndConfirmTransaction, + SystemProgram, + Transaction, +} from "@solana/web3.js"; +import { + createInitializeInstruction, + pack, + TokenMetadata, +} from "@solana/spl-token-metadata"; + +// Step 1: Setup local connection and load wallet +import * as fs from 'fs'; +import * as os from 'os'; + +const walletPath = `${os.homedir()}/.config/solana/id.json`; +const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf8')); +const payer = Keypair.fromSecretKey(Buffer.from(secretKey)); +const connection = createRpc(); // defaults to localhost:8899 + +(async () => { + + // Generate mint keypair and define Token-2022 metadata + const mint = Keypair.generate(); + const decimals = 9; + + const metadata: TokenMetadata = { + mint: mint.publicKey, + name: "Local Test Token", + symbol: "LTT", + uri: "https://example.com/token-metadata.json", + additionalMetadata: [["environment", "localnet"], ["test", "true"]], + }; + + // Calculate space requirements for Token-2022 mint with MetadataPointer extension + const mintLen = getMintLen([ExtensionType.MetadataPointer]); + const metadataLen = TYPE_SIZE + LENGTH_SIZE + pack(metadata).length; + + // Check wallet balance + const balance = await connection.getBalance(payer.publicKey); + + // Step 2: Create Token-2022 mint with metadata extension + const mintLamports = await connection.getMinimumBalanceForRentExemption( + mintLen + metadataLen + ); + + const mintTransaction = new Transaction().add( + // Create account for Token-2022 mint + SystemProgram.createAccount({ + fromPubkey: payer.publicKey, + newAccountPubkey: mint.publicKey, + space: mintLen, + lamports: mintLamports, + programId: TOKEN_2022_PROGRAM_ID, + }), + // Initialize MetadataPointer extension + createInitializeMetadataPointerInstruction( + mint.publicKey, + payer.publicKey, + mint.publicKey, + TOKEN_2022_PROGRAM_ID + ), + // Initialize Token-2022 mint account + createInitializeMintInstruction( + mint.publicKey, + decimals, + payer.publicKey, + null, + TOKEN_2022_PROGRAM_ID + ), + // Initialize token metadata + createInitializeInstruction({ + programId: TOKEN_2022_PROGRAM_ID, + mint: mint.publicKey, + metadata: mint.publicKey, + name: metadata.name, + symbol: metadata.symbol, + uri: metadata.uri, + mintAuthority: payer.publicKey, + updateAuthority: payer.publicKey, + }) + ); + + // Send Token-2022 mint creation transaction + const mintCreationTxId = await sendAndConfirmTransaction( + connection, + mintTransaction, + [payer, mint] + ); + console.log(`Token-2022 mint created with address: ${mint.publicKey.toString()}`); + + // Step 3: Call createTokenPool() to initialize omnibus account + // and register Token-2022 mint with Compressed Token Program + // Create PDA that holds SPL tokens for compressed tokens + const registerTxId = await createTokenPool( + connection, + payer, + mint.publicKey, // Token-2022 mint to register with compressed token program + undefined, + TOKEN_2022_PROGRAM_ID + ); + + // Step 4: Create associated token account and mint tokens + const ata = await getOrCreateAssociatedTokenAccount( + connection, + payer, + mint.publicKey, // Token-2022 mint with token pool for compression + payer.publicKey, + undefined, + undefined, + undefined, + TOKEN_2022_PROGRAM_ID + ); + + // Mint Token-2022 tokens to ATA + const mintAmount = 400_000_000; // 0.4 tokens + const mintToTxId = await mintToSpl( + connection, + payer, + mint.publicKey, // Token-2022 mint with token pool for compression + ata.address, // destination token account + payer.publicKey, // mint authority + mintAmount, // amount to mint + undefined, // multiSigners (not used for single authority) + undefined, + TOKEN_2022_PROGRAM_ID + ); + console.log(`Minted ${mintAmount / 1e9} Token-2022 tokens with metadata extension`); + console.log(`Transaction: ${mintToTxId}`); + + // Step 5: Call compress() to convert Token-2022 tokens to compressed format + // Transfer Token-2022 tokens to omnibus pool and mint compressed tokens + const compressAmount = 300_000_000; // 0.3 tokens + const compressTxId = await compress( + connection, + payer, + mint.publicKey, // Token-2022 mint with token pool for compression + compressAmount, // amount to compress + payer, // owner of SPL tokens + ata.address, // Source ATA for compression + payer.publicKey // recipient for compressed tokens + ); + console.log(`\nCompressed ${compressAmount / 1e9} Token-2022 tokens`); + console.log(`Transaction: ${compressTxId}`); + + // Step 6: Transfer compressed Token-2022 tokens + const transferRecipient = Keypair.generate(); // Keypair recipient + const transferAmount = 100_000_000; // 0.1 tokens + const transferTxId = await transfer( + connection, + payer, + mint.publicKey, // Token-2022 mint with token pool for compression + transferAmount, + payer, + transferRecipient.publicKey + ); + console.log(`\nTransferred ${transferAmount / 1e9} Compressed Token-2022 tokens`); + console.log(`Transaction: ${transferTxId}`); + console.log(`Recipient: ${transferRecipient.publicKey.toString()}`); + + // Step 7: Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner + const senderCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(payer.publicKey, { mint: mint.publicKey }); + const senderBalance = senderCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + const recipientCompressedAccounts = await connection.getCompressedTokenAccountsByOwner(transferRecipient.publicKey, { mint: mint.publicKey }); + const recipientBalance = recipientCompressedAccounts.items.reduce((sum, account) => sum + Number(account.parsed.amount), 0); + + const splBalance = await connection.getTokenAccountBalance(ata.address); + + console.log(`\nSummary Token-2022 balances:`); + console.log(`Sender balance: ${senderBalance / 1e9} compressed tokens / ${splBalance.value.uiAmount} SPL tokens`); + console.log(`Recipient balance: ${recipientBalance / 1e9} compressed tokens`); + +})().catch(console.error); +``` +### Success! + +You've just compressed Token-2022 tokens with metadata extensions and transferred them using ZK Compression. + +## Next Steps + +Explore more guides in our cookbook section. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides.mdx new file mode 100644 index 0000000..493c39b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides.mdx @@ -0,0 +1,18 @@ +--- +title: Guides +description: "Overview of guides to compressed token operations and reference table with descriptions. Guides include full code examples, troubleshooting, and advanced configurations." +sidebarTitle: "Overview" +--- + +| Guide | Description | +| :--- | :--- | +| [How to Create and Register a Mint Account for Compression](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression) | Create new SPL mint with token pool for compression | +| [How to Create Compressed Token Accounts](/compressed-tokens/guides/how-to-create-compressed-token-accounts) | How to create compressed and difference to regular token accounts | +| [How to Mint Compressed Tokens](/compressed-tokens/guides/how-to-mint-compressed-tokens) | Create new compressed tokens to existing mint | +| [How to Transfer Compressed Tokens](/compressed-tokens/guides/how-to-transfer-compressed-token) | Move compressed tokens between compressed accounts | +| [How to Decompress and Compress Tokens](/compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens) | Convert SPL tokens between regular and compressed format | +| [How to Compress complete SPL Token Accounts](/compressed-tokens/guides/how-to-compress-complete-spl-token-accounts) | Compress complete SPL token accounts and reclaim rent afterwards | +| [How to Merge Compressed Accounts](/compressed-tokens/guides/how-to-merge-compressed-token-accounts) | Consolidate multiple compressed accounts of the same mint into a single compressed account | +| [How to Create Token Pools for Mint Accounts](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts) | Create token pool for compression for existing SPL mints | +| [How to Approve and Revoke Delegate Authority](/compressed-tokens/guides/how-to-approve-and-revoke-delegate-authority) | Approve or revoke delegates for compressed token accounts | + diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-approve-and-revoke-delegate-authority.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-approve-and-revoke-delegate-authority.mdx new file mode 100644 index 0000000..d72f0bf --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-approve-and-revoke-delegate-authority.mdx @@ -0,0 +1,452 @@ +--- +title: Approve and Revoke Delegate Authority +description: "Complete guide to manage delegate authority for compressed tokens with `approve()` and `revoke()`, troubleshooting and advanced configurations." +--- + +The `approve()` and `revoke()` functions grant and remove delegate spending authority for compressed tokens. Only the token owner can perform these operations. + +Before we approve or revoke delegates, we need: + +* compressed token accounts to delegate or revoke delegation from, and +* an SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts). + + +```typescript approve() +// Approve delegate for spending up to the specified amount +const approveSignature = await approve( + rpc, + payer, + mint, // SPL mint with token pool for compression + amount, + owner, + delegate.publicKey, // delegate account +); +``` + +```typescript revoke() +// Get delegated accounts for revocation +const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } +); + +// Revoke delegate authority +const revokeSignature = await revoke( + rpc, + payer, + delegatedAccounts.items, // delegated compressed token accounts + owner, +); +``` + + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your API key before running. + + +Get your API Key [here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Approve / Revoke Delegates + + + +Approve delegate authority for compressed tokens. The delegate can spend up to the approved amount. + +```typescript approve-delegates.ts highlight={51-59, 65-69 } expandable lines +// 1. Setup funded payer and connect to local validator +// 2. Create mint and token pool with initial tokens +// 3. Call approve() with mint, amount, owner, delegate +// 4. Verify delegation via getCompressedTokenAccountsByDelegate + +import { Keypair } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { + createMint, + mintTo, + approve +} from '@lightprotocol/compressed-token'; +import BN from 'bn.js'; + +async function approveDelegates() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Create SPL mint with token pool and mint initial tokens + const { mint } = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + 9 // decimals + ); + + console.log("SPL mint with token pool created:", mint.toBase58()); + + const tokenOwner = Keypair.generate(); + const initialAmount = 1_000_000_000; // 1 token with 9 decimals + + await mintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + tokenOwner.publicKey, // recipient + payer, // mint authority + initialAmount + ); + + console.log("Initial tokens minted:", initialAmount / 1_000_000_000, "tokens"); + console.log("Token owner:", tokenOwner.publicKey.toBase58()); + + // Generate delegate address and define amount to approve for delegation + const delegate = Keypair.generate(); + const delegateAmount = 500_000_000; // 0.5 tokens + + // Step 3: Call approve() with mint, amount, owner, delegate + const approveTx = await approve( + rpc, + payer, + mint, // SPL mint with token pool for compression + delegateAmount, + tokenOwner, // owner keypair + delegate.publicKey // delegate address + ); + console.log("Delegate approved"); + console.log("Delegate:", delegate.publicKey.toBase58()); + console.log("Approved amount:", delegateAmount / 1_000_000_000, "tokens"); + console.log("Transaction:", approveTx); + + // Step 4: Verify delegation via getCompressedTokenAccountsByDelegate + const delegateAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } + ); + // Check delegated balance + if (delegateAccounts.items.length > 0) { + const delegatedBalance = delegateAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + console.log("Verified delegation:", delegatedBalance.toNumber() / 1_000_000_000, "tokens"); + } + + return { + mint, + tokenOwner, + delegate: delegate.publicKey, + approveTransaction: approveTx, + delegatedAmount: delegateAmount + }; +} + +approveDelegates().catch(console.error); +``` + + + +Approve delegation, then revoke it in a single script. + +```typescript approve-and-revoke-delegates.ts highlight={54-63, 69-73, 80-87, 91-95} expandable +// Complete workflow: approve and revoke delegation +// 1. Setup and create mint with initial tokens +// 2. Approve delegation +// 3. Verify delegation exists +// 4. Revoke delegation +// 5. Verify delegation removed + +import { Keypair } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { + createMint, + mintTo, + approve, + revoke +} from '@lightprotocol/compressed-token'; +import BN from 'bn.js'; + +async function approveAndRevokeDelegates() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Create SPL mint with token pool and mint initial tokens + const { mint } = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + 9 // decimals + ); + + console.log("SPL mint with token pool created:", mint.toBase58()); + + const tokenOwner = Keypair.generate(); + const initialAmount = 1_000_000_000; // 1 token with 9 decimals + + await mintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + tokenOwner.publicKey, // recipient + payer, // mint authority + initialAmount + ); + + console.log("Initial tokens minted:", initialAmount / 1_000_000_000, "tokens"); + console.log("Token owner:", tokenOwner.publicKey.toBase58()); + + // Generate delegate and define delegation amount + const delegate = Keypair.generate(); + const delegateAmount = 500_000_000; // 0.5 tokens + + // Step 2: Approve delegation + console.log("\n--- Approving Delegation ---"); + const approveTx = await approve( + rpc, + payer, + mint, + delegateAmount, + tokenOwner, + delegate.publicKey + ); + console.log("Delegate approved"); + console.log("Delegate:", delegate.publicKey.toBase58()); + console.log("Approved amount:", delegateAmount / 1_000_000_000, "tokens"); + console.log("Transaction:", approveTx); + + // Step 3: Verify delegation exists + const delegateAccountsBefore = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } + ); + const delegatedBalance = delegateAccountsBefore.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + console.log("Verified delegation:", delegatedBalance.toNumber() / 1_000_000_000, "tokens"); + + // Step 4: Revoke delegation + console.log("\n--- Revoking Delegation ---"); + const revokeTx = await revoke( + rpc, + payer, + delegateAccountsBefore.items, // delegated accounts to revoke + tokenOwner, + ); + console.log("Delegate revoked!"); + console.log("Transaction:", revokeTx); + + // Step 5: Verify delegation removed + const delegateAccountsAfter = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } + ); + const ownerAccounts = await rpc.getCompressedTokenAccountsByOwner( + tokenOwner.publicKey, + { mint } + ); + const ownerBalance = ownerAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + + console.log("\n--- Final State ---"); + console.log("Delegated accounts remaining:", delegateAccountsAfter.items.length); + console.log("Owner balance after revocation:", ownerBalance.toNumber() / 1_000_000_000, "tokens"); + + return { + approveTransaction: approveTx, + revokeTransaction: revokeTx, + finalOwnerBalance: ownerBalance + }; +} + +approveAndRevokeDelegates().catch(console.error); +``` + + + +### Troubleshooting + + + + +Attempting to revoke non-delegated accounts. + +```typescript +/// Verify accounts are delegated before revocation. +const delegateAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } +); + +if (delegateAccounts.items.length === 0) { + console.log("No delegated accounts to revoke"); + return; +} +``` + + + + +### Advanced Configuration + + + + +```typescript +const delegates = [ + Keypair.generate().publicKey, + Keypair.generate().publicKey, +]; + +const amounts = [ + 200_000_000, // 0.2 tokens to first delegate + 300_000_000, // 0.3 tokens to second delegate +]; + +// Approve each delegate +for (let i = 0; i < delegates.length; i++) { + const approveTx = await approve( + rpc, + payer, + mint, + amounts[i], + tokenOwner, + delegates[i], + ); + + console.log(`Delegate ${i + 1} approved:`, approveTx); +} +``` + + + + + +```typescript +const delegates = [ + new PublicKey("DELEGATE_1_ADDRESS"), + new PublicKey("DELEGATE_2_ADDRESS"), +]; + +// Revoke each delegate +for (const delegate of delegates) { + // Get delegated accounts for this delegate + const delegateAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate, + { mint } + ); + + if (delegateAccounts.items.length > 0) { + const revokeTx = await revoke( + rpc, + payer, + delegateAccounts.items, + tokenOwner, + ); + + console.log(`Delegate ${delegate.toBase58()} revoked:`, revokeTx); + } +} +``` + + + + +## Next Steps + +That's it! Explore more guides in our cookbook section, or check out the advanced guides. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens.mdx new file mode 100644 index 0000000..1f47e4a --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens.mdx @@ -0,0 +1,496 @@ +--- +title: Compress and Decompress SPL Tokens +description: "Complete guide to compress SPL tokens with compress() and decompress with decompress(), troubleshooting and advanced configurations." +--- + +The `compress()` and `decompress()` functions convert SPL tokens between compressed and regular format. + +Before we convert formats, we need: + +* An SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts). +* For `compress()` SPL tokens in an Associated Token Account, or +* For `decompress()` compressed token accounts with sufficient balance. + + +```typescript compress() +// Compress SPL tokens to compressed tokens +const compressionSignature = await compress( + rpc, + payer, + mint, // SPL mint with token pool for compression + amount, + payer, // owner of SPL tokens + tokenAccount.address, // source SPL token account (sourceTokenAccount parameter) + recipient, // recipient owner address (toAddress parameter) +); +``` + +```typescript decompress() +// Decompress compressed tokens to SPL tokens +const transactionSignature = await decompress( + rpc, + payer, + mint, // SPL mint with token pool for compression + amount, + payer, // owner of compressed tokens + tokenAccount.address, // destination token account (toAddress parameter) +); +``` + + + +**Function Difference and Best Practice:** + +* `compress(amount, sourceTokenAccount, toAddress)` compresses specific amounts from source to a specified recipient. Use for transfers and precise amounts. +* `compressSplTokenAccount(tokenAccount, remainingAmount)` compresses the entire SPL token account balance minus optional remaining amount only to the same owner. Use to migrate complete token accounts with optional partial retention. [Here is how](/compressed-tokens/guides/how-to-compress-complete-spl-token-accounts). + + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +#### Developer Environment + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your API key before running. + + +[Get your API key here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Compress / Decompress Tokens + + + +Compress SPL tokens to compressed format. + +```typescript compress-tokens.ts highlight={44-54} expandable +// 1. Setup funded payer and connect to local validator +// 2. Create SPL mint with token pool and mint SPL tokens to ATA +// 3. Call compress() to convert SPL tokens to compressed format +// 4. Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner + +import { Keypair } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { + createMint, + compress +} from '@lightprotocol/compressed-token'; +import { + getOrCreateAssociatedTokenAccount, + mintTo as splMintTo, + TOKEN_PROGRAM_ID +} from '@solana/spl-token'; +import BN from 'bn.js'; + +async function compressTokens() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Create SPL mint with token pool and mint SPL tokens to ATA + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + console.log("Mint with token pool created:", mint.toBase58()); + + const tokenOwner = Keypair.generate(); + const tokenAccount = await getOrCreateAssociatedTokenAccount( + rpc, payer, mint, tokenOwner.publicKey, false, TOKEN_PROGRAM_ID + ); + + // Mint SPL tokens to the ATA + const splAmount = 1_000_000_000; // 1 token with 9 decimals + await splMintTo(rpc, payer, mint, tokenAccount.address, payer, splAmount, [], undefined, TOKEN_PROGRAM_ID); + console.log("SPL tokens minted:", splAmount / 1_000_000_000, "tokens"); + + console.log("Compress Tokens"); + + const compressAmount = 400_000_000; // 0.4 tokens + + // Step 3: Call compress() to convert to compressed format + // Lock SPL tokens to pool account and mint compressed tokens + const compressTx = await compress( + rpc, + payer, + mint, // SPL mint with token pool for compression + compressAmount, // amount to compress + tokenOwner, // owner of SPL tokens + tokenAccount.address, // source token account + tokenOwner.publicKey, // recipient for compressed tokens + ); + + console.log("Compressed amount:", compressAmount / 1_000_000_000, "tokens"); + console.log("Transaction:", compressTx); + + // Step 4: Verify balances via getTokenAccountBalance and getCompressedTokenAccountsByOwner + const finalTokenBalance = await rpc.getTokenAccountBalance(tokenAccount.address); + const finalCompressedAccounts = await rpc.getCompressedTokenAccountsByOwner( + tokenOwner.publicKey, + { mint } + ); + + // Calculate total compressed balance + const finalCompressedBalance = finalCompressedAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + + console.log("\nFinal balances:"); + console.log("Regular SPL tokens:", finalTokenBalance.value.uiAmount); + console.log("Compressed tokens:", finalCompressedBalance.toNumber() / 1_000_000_000); + + return { + compressTransaction: compressTx, + finalCompressedBalance, + finalSplBalance: finalTokenBalance.value.amount + }; +} + +compressTokens().catch(console.error); +``` + + + +Compress SPL tokens and decompress in one script. + +```typescript compress-and-decompress-tokens.ts highlight={46-55, 75-83} expandable +// 1. Setup funded payer and connect to local validator +// 2. Create SPL mint with token pool and mint SPL tokens to ATA +// 3. Compress SPL tokens to compressed format +// 4. Decompress compressed tokens back to SPL format +// 5. Verify final balances + +import { Keypair } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { + createMint, + compress, + decompress +} from '@lightprotocol/compressed-token'; +import { + getOrCreateAssociatedTokenAccount, + mintTo as splMintTo, + TOKEN_PROGRAM_ID +} from '@solana/spl-token'; +import BN from 'bn.js'; + +async function compressAndDecompressTokens() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Create SPL mint with token pool and mint SPL tokens to ATA + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + console.log("Mint with token pool created:", mint.toBase58()); + + const tokenOwner = Keypair.generate(); + const tokenAccount = await getOrCreateAssociatedTokenAccount( + rpc, payer, mint, tokenOwner.publicKey, false, TOKEN_PROGRAM_ID + ); + + // Mint SPL tokens to the ATA + const splAmount = 1_000_000_000; // 1 token with 9 decimals + await splMintTo(rpc, payer, mint, tokenAccount.address, payer, splAmount, [], undefined, TOKEN_PROGRAM_ID); + console.log("SPL tokens minted:", splAmount / 1_000_000_000, "tokens"); + + console.log("\n=== Compress Tokens ==="); + + const compressAmount = 600_000_000; // 0.6 tokens + + // Step 3: Compress SPL tokens + const compressTx = await compress( + rpc, + payer, + mint, + compressAmount, + tokenOwner, + tokenAccount.address, + tokenOwner.publicKey, + ); + + console.log("Compressed amount:", compressAmount / 1_000_000_000, "tokens"); + console.log("Compress transaction:", compressTx); + + // Verify compressed balance + const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner( + tokenOwner.publicKey, + { mint } + ); + const compressedBalance = compressedAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + console.log("Compressed balance:", compressedBalance.toNumber() / 1_000_000_000, "tokens"); + + console.log("\n=== Decompress Tokens ==="); + + const decompressAmount = 300_000_000; // 0.3 tokens + + // Step 4: Decompress compressed tokens back to SPL format + const decompressTx = await decompress( + rpc, + payer, + mint, + decompressAmount, + tokenOwner, + tokenAccount.address, + ); + + console.log("Decompressed amount:", decompressAmount / 1_000_000_000, "tokens"); + console.log("Decompress transaction:", decompressTx); + + // Step 5: Verify final balances + const finalTokenBalance = await rpc.getTokenAccountBalance(tokenAccount.address); + const finalCompressedAccounts = await rpc.getCompressedTokenAccountsByOwner( + tokenOwner.publicKey, + { mint } + ); + const finalCompressedBalance = finalCompressedAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) + ); + + console.log("\n=== Final Balances ==="); + console.log("Regular SPL tokens:", finalTokenBalance.value.uiAmount); + console.log("Compressed tokens:", finalCompressedBalance.toNumber() / 1_000_000_000); + + return { + compressTransaction: compressTx, + decompressTransaction: decompressTx, + finalCompressedBalance, + finalSplBalance: finalTokenBalance.value.amount + }; +} + +compressAndDecompressTokens().catch(console.error); + +``` + + + + +### Troubleshooting + + + + +Check your balances before operations: + +```typescript +// For decompression - check compressed balance +const compressedAccounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); +const compressedBalance = compressedAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) +); + +// For compression - check SPL token balance +const tokenBalance = await rpc.getTokenAccountBalance(tokenAccount); +const splBalance = new BN(tokenBalance.value.amount); + +console.log("Can decompress up to:", compressedBalance.toString()); +console.log("Can compress up to:", splBalance.toString()); +``` + + + + + +Ensure the signer owns the tokens being decompressed/compressed: + +```typescript +// The owner parameter must be the actual owner +const decompressTx = await decompress( + rpc, + payer, // can be different (pays fees) + mint, + amount, + actualOwner, // must own compressed tokens + destinationAta, +); + +const compressTx = await compress( + rpc, + payer, // can be different (pays fees) + mint, + amount, + actualOwner, // must own SPL tokens + sourceAta, + recipient, +); +``` + + + + +### Advanced Configurations + + + + +Compress tokens directly to someone else: + +```typescript +const recipientWallet = new PublicKey("RECIPIENT_WALLET_ADDRESS"); + +// Compress your SPL tokens to recipient +const compressTx = await compress( + rpc, + payer, + mint, + amount, + tokenOwner, // current owner signs + tokenAccount, // your token account + recipientWallet, // recipient gets compressed tokens +); +``` + + + + + +Compress multiple token accounts: + +```typescript +// Compress to multiple recipients at once +const recipients = [recipient1.publicKey, recipient2.publicKey, recipient3.publicKey]; +const amounts = [1_000_000_000, 2_000_000_000, 500_000_000]; // Different amounts + +const batchCompressTx = await compress( + rpc, + payer, + mint, + amounts, // Array of amounts + owner, + tokenAccount, + recipients, // Array of recipients +); + +console.log("Batch compression completed:", batchCompressTx); +``` + + + + + +Decompress tokens using delegate authority: + +```typescript +import { decompressDelegated } from '@lightprotocol/compressed-token'; +import { getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token'; + +// Get ATA for decompressed tokens +const ataAddress = await getAssociatedTokenAddress( + mint, + recipient, + false, + TOKEN_PROGRAM_ID +); + +// Delegate decompresses tokens +await decompressDelegated( + rpc, + payer, + mint, + amount, + delegate, // Signer - owner of compressed tokens + ataAddress, // Uncompressed token account (ATA) +); +``` + + + + +## Next Steps + +Learn how to compress complete token accounts in one transaction and reclaim rent afterwards. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-compress-complete-spl-token-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-compress-complete-spl-token-accounts.mdx new file mode 100644 index 0000000..8555f29 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-compress-complete-spl-token-accounts.mdx @@ -0,0 +1,364 @@ +--- +title: Compress Complete SPL Token Accounts +description: "Complete guide to compress complete SPL Token Accounts with compressSplTokenAccount() for account migration and to reclaim rent afterwards." +--- + +The `compressSplTokenAccount` function compresses the balance of an SPL token account, with an optional `remainingAmount` parameter to leave tokens in the original account. + +Before compressing SPL token accounts, you need: + +* An SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression), and +* SPL token account (ATA) with tokens to compress. + +After compression, empty token accounts can now be closed to reclaim rent with [`closeAccount()`](https://solana.com/developers/cookbook/tokens/close-token-accounts). + + +```typescript compressSplTokenAccount() +// Compress entire SPL token account balance +const transactionSignature = await compressSplTokenAccount( + rpc, + payer, + mint, // SPL mint with token pool for compression + owner, + tokenAccount, // SPL token account to compress +); +``` + +```typescript partialCompression() +// Compress account while keeping some tokens in SPL format +const transactionSignature = await compressSplTokenAccount( + rpc, + payer, + mint, // SPL mint with token pool for compression + owner, + tokenAccount, // SPL token account to compress + remainingAmount, // amount to keep in SPL format +); +``` + + + +**Function Difference and Best Practice:** + +* `compressSplTokenAccount(tokenAccount, remainingAmount)` compresses the entire SPL token\ + account balance minus optional remaining amount only to the same owner. Use to migrate complete token\ + accounts with optional partial retention. +* `compress(amount, sourceTokenAccount, toAddress)` compresses specific amounts from\ + source to a specified recipient. Use for transfers and precise amounts. [Here is how](/compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens). + + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your actual API key. + + +[Get your API key here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Compress SPL Token Accounts + +Compress entire SPL token account balance. + +```typescript compress-full-account.ts highlight={48-55} expandable +// 1. Setup funded payer and connect to local validator +// 2. Create SPL mint with token pool and mint SPL tokens to ATA +// 3. Call compressSplTokenAccount() to compress entire account +// 4. Verify balances and rent reclaim eligibility + +import { Keypair } from '@solana/web3.js'; +import { createRpc, bn } from '@lightprotocol/stateless.js'; +import { + createMint, + compressSplTokenAccount +} from '@lightprotocol/compressed-token'; +import { + createAssociatedTokenAccount, + mintTo, + TOKEN_PROGRAM_ID +} from '@solana/spl-token'; + +async function compressFullAccount() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Create SPL mint with token pool and mint SPL tokens to ATA + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + console.log("Mint with token pool created:", mint.toBase58()); + + const tokenOwner = Keypair.generate(); + const tokenAccount = await createAssociatedTokenAccount( + rpc, + payer, + mint, + tokenOwner.publicKey + ); + console.log("SPL token account created:", tokenAccount.toBase58()); + + // Mint SPL tokens to the ATA + const splAmount = 2_000_000_000; // 2 tokens with 9 decimals + await mintTo(rpc, payer, mint, tokenAccount, payer, splAmount); + console.log("SPL tokens minted:", splAmount / 1_000_000_000, "tokens"); + + // Check balances before compression + const splBalanceBefore = await rpc.getTokenAccountBalance(tokenAccount); + console.log("\nBefore Compression:"); + console.log("SPL token balance:", Number(splBalanceBefore.value.amount) / 1_000_000_000, "tokens"); + + // Step 3: Compress entire SPL token account + const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, // SPL mint with token pool for compression + tokenOwner, + tokenAccount, // SPL token account to compress + ); + + console.log("SPL token account compressed!"); + console.log("Transaction:", compressTx); + + // Step 4: Verify balances and rent reclaim eligibility + const splBalanceAfter = await rpc.getTokenAccountBalance(tokenAccount); + const compressedAccountsAfter = await rpc.getCompressedTokenAccountsByOwner( + tokenOwner.publicKey, + { mint } + ); + + const totalCompressed = compressedAccountsAfter.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + bn(0) + ); + + console.log("\nAfter Compression:"); + console.log("SPL token balance:", Number(splBalanceAfter.value.amount) / 1_000_000_000, "tokens"); + console.log("Compressed accounts:", compressedAccountsAfter.items.length); + console.log("Total compressed balance:", totalCompressed.toNumber() / 1_000_000_000, "tokens"); + + if (Number(splBalanceAfter.value.amount) === 0) { + console.log("\nSPL token account is now empty and can be closed to reclaim rent!"); + } + + return { + compressTransaction: compressTx, + tokenAccount, + splBalanceAfter: Number(splBalanceAfter.value.amount), + compressedBalance: totalCompressed.toNumber() + }; +} + +compressFullAccount().catch(console.error); +``` + +### Troubleshooting + + + + +The token account doesn't have enough tokens for the operation. + +```typescript +// Check token account balance before compression +const balance = await rpc.getTokenAccountBalance(tokenAccount); + +if (Number(balance.value.amount) === 0) { + console.log("Token account is empty"); + return; +} + +console.log("Available balance:", Number(balance.value.amount)); + +// Proceed with compression +const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + tokenAccount, +); +``` + + + + + +The `remainingAmount` parameter exceeds the current account balance. + +```typescript +const balance = await rpc.getTokenAccountBalance(tokenAccount); +const availableAmount = Number(balance.value.amount); +const remainingAmount = bn(500_000_000); // 0.5 tokens + +if (remainingAmount.gt(bn(availableAmount))) { + console.log(`Cannot leave ${remainingAmount.toString()} tokens`); + console.log(`Available balance: ${availableAmount}`); + throw new Error("Remaining amount exceeds balance"); +} + +// Use valid remaining amount +const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + tokenAccount, + remainingAmount, // must be <= balance +); +``` + + + + +### Advanced Configuration + + + + +Compress most tokens while leaving some in SPL format: + +```typescript +import { bn } from '@lightprotocol/stateless.js'; + +// Leave 100 tokens (0.1 with 9 decimals) in SPL account +const remainingAmount = bn(100_000_000); + +const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + tokenAccount, + remainingAmount, // amount to keep in SPL format +); + +// Account will retain remainingAmount tokens +``` + + + + + +Compress several token accounts for the same mint: + +```typescript +const tokenAccounts = [ + { account: new PublicKey("ACCOUNT_1"), owner: owner1 }, + { account: new PublicKey("ACCOUNT_2"), owner: owner2 }, + { account: new PublicKey("ACCOUNT_3"), owner: owner3 }, +]; + +// Compress each account +for (const { account, owner } of tokenAccounts) { + console.log(`Compressing account: ${account.toBase58()}`); + + try { + const compressTx = await compressSplTokenAccount( + rpc, + payer, + mint, + owner, + account, + ); + console.log(`Compressed: ${compressTx}`); + } catch (error) { + console.log(`Failed: ${error.message}`); + } +} +``` + + + + +## Next Steps + +Compressed tokens need an SPL mint with token pool for compression. Learn how to create and register SPL mints with token pools for compression in the next guide. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression.mdx new file mode 100644 index 0000000..2c97553 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression.mdx @@ -0,0 +1,207 @@ +--- +title: Create and Register a Mint Account for Compression +description: "Complete guide to create and register an SPL token mint account for compression with createMint(), troubleshooting and advanced configurations." +--- + + +The mint account itself requires rent (like regular SPL mints), but individual compressed token accounts are rent-free. + + +Compressed tokens use an SPL mint that is registered with the compressed token program. Connect an existing SPL mint with [`createTokenPool()`](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts) or use `createMint()` to create a new one from scratch. + + +```typescript createMint() +// Create SPL mint with token pool for compression +const { mint, transactionSignature } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + decimals, +); +``` + + + +**Best Practice:** Each mint supports a maximum of 4 token pools total. During compression/decompression operations, token pools get write-locked. Use `addTokenPools()` to create additional pools that increase per-block write-lock capacity. + + +## Full Code Example + +### Prerequisites + + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && +npm install \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dd typescript tsx @types/node && +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your API key before running. + + +Get your API Key [here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Create SPL Mint with Token Pool for Compression + +Run this script to create a mint account with token pool for compression. + +```typescript create-mint.ts highlight={15-21} expandable +// 1. Setup funded payer and connect to local validator +// 2. Create SPL mint with token pool for compression via createMint() + +import { Keypair } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { createMint } from '@lightprotocol/compressed-token'; + +async function createCompressedMint() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Call createMint() to create mint account and token pool for compression + const { mint, transactionSignature } = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + 9 + ); + console.log("SPL mint with token pool for compression created"); + console.log("Mint address:", mint.toBase58()); + console.log("Transaction:", transactionSignature); + + + return { mint, transactionSignature }; +} + +createCompressedMint().catch(console.error); +``` + +### Advanced Configurations + + + + +Customize who can mint new compressed tokens. + +```typescript +const mintAuthority = Keypair.generate(); + +const { mint, transactionSignature } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, +); +``` + + + + + +Customize who can freeze/thaw compressed token accounts. + +```typescript +const freezeAuthority = Keypair.generate(); + +const { mint, transactionSignature } = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + 9, // decimals + Keypair.generate(), // mint keypair + undefined, // confirm options + undefined, // token program ID + freezeAuthority.publicKey, // freeze authority +); +``` + + + + +## Next Steps + +Learn how to create additional compressed token pools for your SPL mint to increase write-lock limits. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-compressed-token-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-compressed-token-accounts.mdx new file mode 100644 index 0000000..1c15519 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-compressed-token-accounts.mdx @@ -0,0 +1,17 @@ +--- +title: Create Compressed Token Accounts +description: Short guide to compressed token account creation with ZK Compression on Solana and difference to regular token accounts. +--- + +Compressed token accounts store ownership information for compressed tokens like regular token accounts with two core differences. Compressed Tokens + +* do not require an Associated Token Accounts (ATAs), and +* do not require a rent-exempt balance. + +Compressed token accounts are created in the following scenarios: + +1. `mintTo()` creates compressed token accounts for recipients. + +How to Mint Compressed Tokens + +2. `transfer()` consumes existing accounts of the sender as input, and creates new compressed token accounts with updated balances as output for the sender and recipient(s). diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts.mdx new file mode 100644 index 0000000..ed56450 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts.mdx @@ -0,0 +1,266 @@ +--- +title: Create Compressed Token Pools for Mint Accounts +description: Complete guide to create and manage token pools for compressed tokens for SPL mints with `createTokenPool()`, troubleshooting and advanced configurations. +--- + +The `createTokenPool()` function registers an existing SPL mint with the compressed token program and creates a token pool PDA. `createTokenPool()` requires only `fee_payer` and has no mint authority constraint. + + +The token pool account itself requires rent, but individual compressed token accounts are rent-free. + + +Before we create a token pool, we need an existing SPL mint account. + + +```typescript function-create-token-pool.ts +// Creates token pool account for existing SPL mint +const transactionSignature = await createTokenPool( + rpc, + payer, + mint, +); +``` + + + +**Best Practice:** Each mint supports a maximum of 4 token pools total. During compression/decompression operations, token pools get write-locked. Use `addTokenPools()` to create additional pools that increase per-block write-lock capacity. + + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +Make sure you have dependencies and developer environment set up! + + +**Prerequisites & Setup** + +#### Dependencies + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your API key before running. + + +[Get your API key here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Create Token Pool + +Run this script to create token pools for an SPL mint! + +```typescript create-token-pools.ts highlight={31-33, 43-45} lines expandable +// 1. Setup funded payer and connect to local validator +// 2. Create SPL mint +// 3. Call createTokenPool() to register mint with compressed token program +// 4. Add additional pools to increase write-lock capacity (optional) + +import { Keypair, PublicKey } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { createTokenPool, addTokenPools } from '@lightprotocol/compressed-token'; +import { createMint } from '@solana/spl-token'; + +async function createTokenPools() { + + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Create SPL mint + const mint = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + payer.publicKey, // freeze authority + 9 + ); + + console.log("SPL mint created"); + console.log("Mint address:", mint.toBase58()); + + // Step 3: Call createTokenPool() to register SPL mint with compressed token program + // Creates token pool PDA (omnibus account) that holds SPL tokens for compressed tokens + const poolTx = await createTokenPool( + rpc, + payer, + mint // existing SPL mint to register + ); + + console.log("\nToken pool created!"); + console.log("SPL mint registered with compressed token program:", mint.toBase58()); + console.log("Pool transaction:", poolTx); + + // Step 4: Add up to 3 additional pools - increase write-lock capacity for higher throughput + const additionalPoolsCount = 2; + const additionalPoolsTx = await addTokenPools( + rpc, + payer, + mint, // SPL mint with existing token pool + additionalPoolsCount, // number of additional pools (max 3 more) + ); + + console.log(`\nAdded ${additionalPoolsCount} additional token pools!`); + console.log("Additional pools transaction:", additionalPoolsTx); + + + return { + mint, + poolTransaction: poolTx, + additionalPoolsTransaction: additionalPoolsTx + }; +} + +createTokenPools().catch(console.error); +``` + +### Troubleshooting + + + + +You're trying to access a token pool that doesn't exist. + +```typescript +// Create the missing token pool +const poolTx = await createTokenPool(rpc, payer, mint); +console.log("Token pool created:", poolTx); +``` + + + + +### Advanced Configuration + + + + +Create pools for multiple mints: + +```typescript +const mints = [ + new PublicKey("MINT_1_ADDRESS"), + new PublicKey("MINT_2_ADDRESS"), + new PublicKey("MINT_3_ADDRESS"), +]; + +for (const mint of mints) { + try { + const poolTx = await createTokenPool(rpc, payer, mint); + console.log(`Pool created for ${mint.toBase58()}:`, poolTx); + } catch (error) { + console.log(`Failed for ${mint.toBase58()}:`, error.message); + } +} +``` + + + + + +Create token pools for Token-2022 mints: + +```typescript +import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token'; + +const poolTx = await createTokenPool( + rpc, + payer, + mint, // Token-2022 mint + undefined, + TOKEN_2022_PROGRAM_ID, +); +``` + + + + +## Next Steps + +Learn how to merge multiple compressed token accounts into one to simplify state management. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-merge-compressed-token-accounts.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-merge-compressed-token-accounts.mdx new file mode 100644 index 0000000..65cedb2 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-merge-compressed-token-accounts.mdx @@ -0,0 +1,320 @@ +--- +title: Merge Compressed Token Accounts +description: "Complete guide to merge multiple compressed token accounts into a single account with mergeTokenAccounts(), troubleshooting and advanced configurations." +--- + +The `mergeTokenAccounts()` function consolidates multiple compressed accounts of the same mint into a single compressed account. + +The function + +1. consumes multiple compressed token accounts (up to 8 accounts), and +2. creates a single output compressed token account with combined balance for the owner. + +Before we merge compressed accounts, we need + +* Multiple compressed token accounts of the same mint owned by the same wallet, and +* an SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts). + + +State trees where compressed account's are stored, are append only. `mergeTokenAccounts()` reduces account fragmentation to simplify balance calculations from `getCompressedTokenAccountsByOwner`. + + + +```typescript function-merge-accounts.ts +```typescript +// Combines multiple compressed token accounts into single compressed account +const transactionSignature = await mergeTokenAccounts( + rpc, + payer, + mint, // SPL mint with token pool for compression + owner, +); +``` + + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to develop create an RPC Connection. Replace `` with your API key before running. + + +[Get your API key here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Merging Compressed Accounts + +Run this script to merge multiple compressed token accounts into one! + +```typescript merge-compressed-accounts.ts highlight={60-67} expandable +// 1: Setup funded payer and connect to local validator +// 2. Create mint and multiple compressed accounts +// 3. Call mergeTokenAccounts() to consolidate multiple compressed accounts to one output +// 4. Use getCompressedTokenAccountsByOwner() to query account states before and after merge + +import { Keypair, PublicKey } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { + createMint, + mintTo, + mergeTokenAccounts +} from '@lightprotocol/compressed-token'; + +async function mergeCompressedAccounts() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Create SPL mint with token pool for compression + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + console.log("SPL Mint with token pool created:", mint.toBase58()); + + const tokenOwner = Keypair.generate(); + const amounts = [300_000_000, 200_000_000, 500_000_000]; // 0.3, 0.2, 0.5 tokens + + console.log("Creating multiple compressed accounts..."); + + for (let i = 0; i < amounts.length; i++) { + await mintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + tokenOwner.publicKey,// recipient address (toPubkey parameter) + payer, // mint authority + amounts[i], + ); + } + + // Step 2a: Get all compressed accounts before merging + const accountsBefore = await rpc.getCompressedTokenAccountsByOwner( + tokenOwner.publicKey, + { mint } + ); + + console.log("Number of accounts before merge:", accountsBefore.items.length); + + // Step 2b: Calculate total balance across all compressed accounts + const totalBalance = accountsBefore.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new (require('bn.js'))(0) + ); + console.log("Total balance:", totalBalance.toNumber() / 1_000_000_000, "tokens"); + + accountsBefore.items.forEach((account, index) => { + console.log(`Account ${index + 1}:`, account.parsed.amount.toNumber() / 1_000_000_000, "tokens"); + }); + + // Step 3: Call mergeTokenAccounts() to consolidate into single account + // Nullify old compressed accounts and create one with combined balance + const mergeTx = await mergeTokenAccounts( + rpc, + payer, + mint, // SPL mint with token pool for compression + tokenOwner, + ); + console.log("\nMerge Compressed Accounts..."); + console.log("Transaction:", mergeTx); + + // Step 4: Verify merge results - check single compressed account contains total balance + const accountsAfter = await rpc.getCompressedTokenAccountsByOwner( + tokenOwner.publicKey, + { mint } + ); + + console.log("Number of accounts after merge:", accountsAfter.items.length); + + if (accountsAfter.items.length > 0) { + const mergedBalance = accountsAfter.items[0].parsed.amount; + console.log("Merged account balance:", mergedBalance.toNumber() / 1_000_000_000, "tokens"); + } + + + return { + mint, + tokenOwner, + mergeTransaction: mergeTx, + accountsBefore: accountsBefore.items.length, + accountsAfter: accountsAfter.items.length + }; + +} + +mergeCompressedAccounts().catch(console.error); +``` + +### Troubleshooting + + + + +The owner has no compressed token accounts for the specified mint: + +```typescript +// Check if accounts exist before merging +const accounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); + +if (accounts.items.length === 0) { + console.log("No compressed token accounts found for this mint"); + console.log("Mint address:", mint.toBase58()); + console.log("Owner address:", owner.publicKey.toBase58()); + return; +} + +console.log(`Found ${accounts.items.length} accounts to merge`); +``` + + + + +### Advanced Configuration + + + + +```typescript +// Get account count +const accounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); + +// Only merge if more than 2 accounts +if (accounts.items.length > 2) { + console.log(`Merging ${accounts.items.length} accounts...`); + + const mergeTx = await mergeTokenAccounts( + rpc, + payer, + mint, + tokenOwner, + ); + + console.log("Merge completed:", mergeTx); +} else { + console.log("Merge not needed - optimal account structure"); +} +``` + + + + + +```typescript +const mints = [ + new PublicKey("MINT_1_ADDRESS"), + new PublicKey("MINT_2_ADDRESS"), +]; + +// Merge accounts for each mint +for (const mint of mints) { + console.log(`Merging accounts for mint: ${mint.toBase58()}`); + + const mergeTx = await mergeTokenAccounts( + rpc, + payer, + mint, + tokenOwner, + ); + + console.log(`Merge completed: ${mergeTx}`); +} +``` + + + + +## Next Steps + +Learn how to approve and revoke delegate authority for compressed token accounts. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-mint-compressed-tokens.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-mint-compressed-tokens.mdx new file mode 100644 index 0000000..c3c0182 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-mint-compressed-tokens.mdx @@ -0,0 +1,291 @@ +--- +title: Mint Compressed Tokens +description: "Complete guide to mint compressed tokens with mintTo(), troubleshooting, and advanced configurations." +--- + +The `mintTo()` function creates compressed token accounts for recipients and increases the mint's token supply. Only the mint authority can perform this operation. + +Before minting compressed tokens, you need an SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts). + +```typescript function-mint-compressed-tokens.ts +// Mint compressed tokens - mints SPL tokens to pool, creates compressed token accounts +const transactionSignature = await mintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + recipient, // recipient address (toPubkey parameter) + payer, // mint authority + amount, +); +``` + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +**Dependencies** + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Developer Environment** + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your API key before running. + + +Get your API Key [here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + +### Minting Compressed Tokens + +Run this script to mint compressed tokens to a recipient! + +```typescript mint-compressed-tokens.ts highlight={35-44} expandable +// 1. Setup funded payer and connect to local validator +// 2. Create SPL mint with token pool for compression +// 3. Call mintTo() with mint, recipient, and amount - mint SPL tokens to pool and create compressed token accounts +// 4. Verify via getCompressedTokenAccountsByOwner + +import { Keypair, PublicKey } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { createMint, mintTo } from '@lightprotocol/compressed-token'; + +async function mintCompressedTokens() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2: Create SPL mint with token pool for compression + const { mint, transactionSignature: mintCreateTx } = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + 9 + ); + + console.log("Mint with token pool for compression created!"); + console.log("Mint address:", mint.toBase58()); + console.log("Create mint transaction:", mintCreateTx); + + // Generate recipient keypair + const recipient = Keypair.generate(); + + // Define amount to mint + const mintAmount = 1_000_000_000; // 1 token with 9 decimals + + // Step 3: Call mintTo() with mint, recipient, and amount + // Mint SPL tokens to pool and create compressed token account + const transactionSignature = await mintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + recipient.publicKey, + payer, // mint authority + mintAmount + ); + + console.log("\nCompressed token minted!"); + console.log("Recipient:", recipient.publicKey.toBase58()); + console.log("Compressed Token Balance:", mintAmount / 1_000_000_000, "tokens"); + console.log("Mint token transaction:", transactionSignature); + + // Step 4: Verify via getCompressedTokenAccountsByOwner + const tokenAccounts = await rpc.getCompressedTokenAccountsByOwner( + recipient.publicKey, + { mint } + ); + + if (tokenAccounts.items.length > 0) { + const balance = tokenAccounts.items[0].parsed.amount; } + + return { transactionSignature, recipient: recipient.publicKey, amount: mintAmount }; +} + +mintCompressedTokens().catch(console.error); +``` + +### Troubleshooting + + + + + +```typescript +// Error message: "TokenPool not found. Please create a compressed token +// pool for mint: [ADDRESS] via createTokenPool(). +``` + +The mint does no have a token pool for compression. Ensure you created the mint using `createMint`. + +```typescript +// Create mint with token pool for compression +import { createMint } from '@lightprotocol/compressed-token'; +const { mint } = await createMint(rpc, payer, payer.publicKey, 9); +``` + + + + + +The token pool info doesn't correspond to the mint address. Ensure you're fetching the correct pool: + +```typescript +// Get the correct token pool for your mint +const tokenPoolInfo = await getTokenPoolInfos(rpc, mint); +``` + + + + + +When minting to multiple recipients, ensure arrays are the same size. + +```typescript +// Wrong: Mismatched array lengths +const recipients = [addr1, addr2, addr3]; +const amounts = [100, 200]; // Only 2 amounts for 3 recipients + +// Correct: Same length arrays +const recipients = [addr1, addr2, addr3]; +const amounts = [100, 200, 300]; // 3 amounts for 3 recipients +``` + + + + +### Advanced Configuration + + + + +```typescript +// Mint different amounts to multiple recipients +const recipients = [ + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, +]; + +const amounts = [ + 1_000_000_000, // 1 token + 2_000_000_000, // 2 tokens + 500_000_000, // 0.5 tokens +]; + +const transactionSignature = await mintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + recipients, // array of recipients (toPubkey parameter) + payer, // mint authority + amounts, // array of amounts (amount parameter) +); +``` + + + + + +Mint tokens using a custom mint authority with `approveAndMintTo()`: + +```typescript +import { approveAndMintTo } from '@lightprotocol/compressed-token'; + +// Mint tokens with a separate mint authority +const transactionSignature = await approveAndMintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + recipient.publicKey, // recipient of minted tokens (toPubkey parameter) + mintAuthority, // mint authority + mintAmount, +); +``` + + + + +## Next Steps + +Learn how to transfer compressed tokens you just minted. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-transfer-compressed-token.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-transfer-compressed-token.mdx new file mode 100644 index 0000000..c5ba320 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/guides/how-to-transfer-compressed-token.mdx @@ -0,0 +1,355 @@ +--- +title: Transfer Compressed Tokens +description: Complete guide to transfer compressed SPL tokens between compressed or regular accounts with `transfer()`, troubleshooting and advanced configurations. +--- + +The `transfer()` function moves compressed tokens between accounts. Unlike regular SPL transfers that update existing account balances, compressed transfers consume input accounts from the sender and create new output accounts for sender and recipient with updated balances. + +Before we can transfer compressed tokens, we need: + +* An SPL mint with a token pool for compression. This token pool can be created for new SPL mints via [`createMint()`](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression) or added to existing SPL mints via [`createTokenPool()`](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts)., and +* a source compressed token account with sufficient balance for the transfer amount. + + +Regular SPL token accounts can be compressed in the same transaction with `compress_or_decompress_amount`, if needed. + + +```typescript function-transfer-compressed-tokens.ts +// Transfer compressed tokens +const transactionSignature = await transfer( + rpc, + payer, + mint, // SPL mint with token pool for compression + amount, + payer, + recipient, // destination address (toAddress parameter) +) +``` + +## Full Code Example + +### Prerequisites + +Make sure you have dependencies and developer environment set up! + + + +#### Dependencies + +```bash +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +**Alternatives:** + +```bash +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +#### Developer Environment + +By default, this guide uses Localnet. + +```bash +# Install the development CLI +npm install @lightprotocol/zk-compression-cli +``` + +```bash +# Start a local test validator +light test-validator + +## ensure you have the Solana CLI accessible in your system PATH +``` + +```typescript +// createRpc() defaults to local test validator endpoints +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +const connection: Rpc = createRpc(); + +async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" +} + +main(); +``` + +**Alternative: Using Devnet** + +Follow these steps to create an RPC Connection. Replace `` with your API key before running. + + +Get your API Key [here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created!"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + + +### Transferring Compressed Tokens + +Run this script to transfer compressed tokens to a recipient! + +```typescript transfer-compressed-tokens.ts highlight={49-57} expandable +// 1. Setup funded payer and connect to local validator +// 2. Create SPL mint and token pool for compression with initial tokens +// 3. Call transfer() with mint, amount, owner, recipient +// 4. Verify transferred tokens via getCompressedTokenAccountsByOwner + +import { Keypair, PublicKey } from '@solana/web3.js'; +import { createRpc } from '@lightprotocol/stateless.js'; +import { createMint, mintTo, transfer } from '@lightprotocol/compressed-token'; + +async function transferCompressedTokens() { + // Step 1: Setup funded payer and connect to local validator + const rpc = createRpc(); // defaults to localhost:8899 + const payer = Keypair.generate(); + const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL + await rpc.confirmTransaction(airdropSignature); + + // Step 2a: Create SPL mint with token pool for compression + const { mint, transactionSignature: mintCreateTx } = await createMint( + rpc, + payer, + payer.publicKey, // mint authority + 9 + ); + + console.log("SPL mint with token pool for compression created"); + console.log("Mint address:", mint.toBase58()); + console.log("Create mint transaction:", mintCreateTx); + + // Step 2b: Create token owner and mint initial tokens + const tokenOwner = Keypair.generate(); + const initialMintAmount = 1_000_000_000; // 1 token with 9 decimals + + const mintToTx = await mintTo( + rpc, + payer, + mint, // SPL mint with token pool for compression + tokenOwner.publicKey, // recipient + payer, // mint authority + initialMintAmount + ); + + console.log("\nCompressed Tokens minted:", initialMintAmount / 1_000_000_000, "tokens"); + console.log("Mint tokens transaction:", mintToTx); + + // Generate recipient address and define transfer amount + const recipient = Keypair.generate(); + const transferAmount = 500_000_000; // 0.5 tokens + + // Step 3: Call transfer() with mint, amount, owner, recipient + const transferTx = await transfer( + rpc, + payer, + mint, // SPL mint with token pool for compression + transferAmount, + tokenOwner, // owner keypair + recipient.publicKey // recipient address + ); + + console.log("\nCompressed tokens transferred!"); + console.log("From:", tokenOwner.publicKey.toBase58()); + console.log("To:", recipient.publicKey.toBase58()); + console.log("Amount transferred:", transferAmount / 1_000_000_000, "tokens"); + console.log("Transfer transaction:", transferTx); + + // Step 4: Verify transferred tokens via getCompressedTokenAccountsByOwner + const recipientAccounts = await rpc.getCompressedTokenAccountsByOwner( + recipient.publicKey, + { mint } + ); + + // Check recipient received the tokens + if (recipientAccounts.items.length > 0) { + const receivedBalance = recipientAccounts.items[0].parsed.amount; + } + + return { + transferTransaction: transferTx, + recipient: recipient.publicKey, + amount: transferAmount + }; +} + +transferCompressedTokens().catch(console.error); +``` + +### Troubleshooting + + + + +The sender doesn't have enough compressed tokens for the requested transfer amount. + +```typescript +// Check current balance first +const tokenAccounts = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint } +); + +if (tokenAccounts.items.length === 0) { + throw new Error("No compressed token accounts found"); +} + +// Calculate total balance across all accounts +const totalBalance = tokenAccounts.items.reduce( + (sum, account) => sum.add(account.parsed.amount), + new BN(0) +); + +console.log("Available balance:", totalBalance.toString()); + +// Ensure transfer amount doesn't exceed balance +if (new BN(transferAmount).gt(totalBalance)) { + throw new Error(`Transfer amount ${transferAmount} exceeds balance ${totalBalance.toString()}`); +} +``` + + + + + +The transfer requires more than 4 compressed accounts, which exceeds the transaction limit. + +```typescript +// Error message: "Account limit exceeded: max X (4 accounts) per transaction. +// Total balance: Y (Z accounts). Consider multiple transfers to spend full balance." + +// Split into multiple smaller transfers +const maxTransferPerTx = 1_000_000_000; // Adjust based on your account sizes + +if (transferAmount > maxTransferPerTx) { + console.log("Large transfer detected, splitting into multiple transactions..."); + + let remainingAmount = transferAmount; + while (remainingAmount > 0) { + const currentTransfer = Math.min(remainingAmount, maxTransferPerTx); + + await transfer( + rpc, + payer, + mint, + currentTransfer, + owner, + recipient + ); + + remainingAmount -= currentTransfer; + console.log(`Transferred ${currentTransfer}, remaining: ${remainingAmount}`); + } +} +``` + + + + +### Advanced Configuration + + + + +Transfer to multiple recipients in separate transactions: + +```typescript +const recipients = [ + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, +]; + +const amounts = [ + 100_000_000, // 0.1 tokens + 200_000_000, // 0.2 tokens + 150_000_000, // 0.15 tokens +]; + +for (let i = 0; i < recipients.length; i++) { + const transactionSignature = await transfer( + rpc, + payer, + mint, + amounts[i], + owner, + recipients[i], + ); + + console.log(`Transfer ${i + 1} completed:`, transactionSignature); +} +``` + + + + + +Transfer tokens using delegate authority: + +```typescript +import { approve, transferDelegated } from '@lightprotocol/compressed-token'; + +// 1. Owner approves delegate +await approve( + rpc, + payer, + mint, + amount, + owner, // Signer + delegate.publicKey, // PublicKey +); + +// 2. Delegate transfers tokens +await transferDelegated( + rpc, + payer, + mint, + transferAmount, + delegate, // Signer - named "owner" in SDK + recipient, +); +``` + + + + +## Next Steps + +Learn how compress and decompress SPL Tokens. diff --git a/zk-compression-docs/mintlify-docs/compressed-tokens/overview.mdx b/zk-compression-docs/mintlify-docs/compressed-tokens/overview.mdx new file mode 100644 index 0000000..af91879 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/compressed-tokens/overview.mdx @@ -0,0 +1,159 @@ +--- +title: Overview +description: Compressed tokens provide full SPL token functionality without per-account rent cost. +--- + + +| Creation | Regular SPL Token | Compressed Token | Cost Reduction | +|:---------------------|:------------------|:----------------------|:---------------| +| 100 Token Accounts | ~ 0.2 SOL | **~ 0.00004 SOL** | **5000x** | + +Compressed token accounts store information about an individual's ownership of a specific token (mint). Different from regular token accounts, they don't require an Associated Token Account (ATA) per token holder. + +For example, this simplifies [token distribution](https://github.com/Lightprotocol/developer-content/blob/main/zk-compression-docs/compressed-tokens/implementation-guides/create-an-airdrop.md), since you don't need to allocate a token account per recipient. + +**Compressed Tokens at a Glance** + + + + Create token accounts without upfront rent exempt balance. + + + Compatible with SPL tokens and Solana programs. + + + Supported by leading wallets including Phantom and Backpack. + + + +## Start building + +Developing with compressed tokens works similar SPL tokens and involves minimal setup: + + + +Install dependencies + + +```bash npm +npm install --save-dev typescript tsx @types/node && \ +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash yarn +yarn add --dev typescript tsx @types/node && \ +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + +```bash pnpm +pnpm add --save-dev typescript tsx @types/node && \ +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + + + + +Set up your developer environment + + + By default, all guides use Localnet. + + ```bash + # Install the development CLI + npm install @lightprotocol/zk-compression-cli + ``` + + ```bash + # Start a local test validator + light test-validator + + ## ensure you have the Solana CLI accessible in your system PATH + ``` + + ```typescript + // createRpc() defaults to local test validator endpoints + import { + Rpc, + createRpc, + } from "@lightprotocol/stateless.js"; + + const connection: Rpc = createRpc(); + + async function main() { + let slot = await connection.getSlot(); + console.log(slot); + + let health = await connection.getIndexerHealth(slot); + console.log(health); + // "Ok" + } + + main(); + ``` + + **Alternative: Using Devnet** + + Replace `` with your actual API key. [Get your API key here](https://www.helius.dev/zk-compression), if you don't have one yet. + + ```typescript + import { createRpc } from "@lightprotocol/stateless.js"; + + // Helius exposes Solana and Photon RPC endpoints through a single URL + const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; + const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + + console.log("Connection created!"); + console.log("RPC Endpoint:", RPC_ENDPOINT); + ``` + + + + + + + Get started with our cookbook or advanced guides for implementations + + + +## Guides + +| Guide | Description | +| :---------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- | +| [Create and Register a Mint Account for Compression](/compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression) | Create new SPL mint with token pool for compression | +| [Create Compressed Token Accounts](/compressed-tokens/guides/how-to-create-compressed-token-accounts) | Create compressed and learn difference to regular token accounts | +| [Mint Compressed Tokens](/compressed-tokens/guides/how-to-mint-compressed-tokens) | Create new compressed tokens to existing mint | +| [Transfer Compressed Tokens](/compressed-tokens/guides/how-to-transfer-compressed-token) | Move compressed tokens between compressed accounts | +| [Decompress and Compress Tokens](/compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens) | Convert SPL tokens between regular and compressed format | +| [Compress Complete SPL Token Accounts](/compressed-tokens/guides/how-to-compress-complete-spl-token-accounts) | Compress complete SPL token accounts and reclaim rent afterwards | +| [Merge Compressed Accounts](/compressed-tokens/guides/how-to-merge-compressed-token-accounts) | Consolidate multiple compressed accounts of the same mint into one | +| [Create Token Pools for Mint Accounts](/compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts) | Create token pool for compression for existing SPL mints | +| [Approve and Revoke Delegate Authority](/compressed-tokens/guides/how-to-approve-and-revoke-delegate-authority) | Approve or revoke delegates for compressed token accounts | + + +### Advanced Guides + +| Guide | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | +| [Add Wallet Support for Compressed Tokens](https://github.com/Lightprotocol/developer-content/blob/main/zk-compression-docs/compressed-tokens/add-wallet-support-for-compressed-tokens.md) | Add compressed token support in your wallet application | +| [Use Token-2022 with Compression](https://github.com/Lightprotocol/developer-content/blob/main/zk-compression-docs/compressed-tokens/use-token-2022-with-compression.md) | Create compressed Token-2022 mints with metadata and other extensions | +| [Create an Airdrop without Claim](https://github.com/Lightprotocol/developer-content/blob/main/zk-compression-docs/compressed-tokens/create-an-airdrop.md) | Create an airdrop that appears directly in recipients' wallets (with or without code) | +| [Example Airdrop with Claim](https://github.com/Lightprotocol/example-compressed-claim) | Demo for time-locked airdrop with compressed tokens | +| [Example Web Client](https://github.com/Lightprotocol/example-web-client) | Demonstrates how to use @lightprotocol/stateless.js in a browser environment to interact with ZK Compression | +| [Example Node.js Client](https://github.com/Lightprotocol/example-nodejs-client) | Script to execute basic compression/decompression/transfers | + + +## Next Steps + +Get started with the first cookbook guide. diff --git a/zk-compression-docs/mintlify-docs/deepwiki.mdx b/zk-compression-docs/mintlify-docs/deepwiki.mdx new file mode 100644 index 0000000..1ab4d8b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/deepwiki.mdx @@ -0,0 +1,4 @@ +--- +title: DeepWiki +url: "https://deepwiki.com/Lightprotocol/light-protocol" +--- diff --git a/zk-compression-docs/mintlify-docs/discord.mdx b/zk-compression-docs/mintlify-docs/discord.mdx new file mode 100644 index 0000000..30a0efc --- /dev/null +++ b/zk-compression-docs/mintlify-docs/discord.mdx @@ -0,0 +1,5 @@ +--- +title: Discord +url: "https://discord.com/invite/CYvjBgzRFP" +--- + diff --git a/zk-compression-docs/mintlify-docs/docs.json b/zk-compression-docs/mintlify-docs/docs.json new file mode 100644 index 0000000..98658ab --- /dev/null +++ b/zk-compression-docs/mintlify-docs/docs.json @@ -0,0 +1,194 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "theme": "mint", + "name": "Lightprotocol", + "colors": { + "primary": "#0066FF", + "light": "#0066FF", + "dark": "#0066FF" + }, + "favicon": "/favicon.png", + "appearance": { + "default": "light" + }, + "navigation": { + "pages": [ + "index", + "quickstart", + "support", + { + "group": "Compressed Tokens", + "pages": [ + "compressed-tokens/overview", + { + "group": "Guides", + "pages": [ + "compressed-tokens/guides", + "compressed-tokens/guides/how-to-create-compressed-token-accounts", + "compressed-tokens/guides/how-to-mint-compressed-tokens", + "compressed-tokens/guides/how-to-transfer-compressed-token", + "compressed-tokens/guides/how-to-compress-and-decompress-spl-tokens", + "compressed-tokens/guides/how-to-compress-complete-spl-token-accounts", + "compressed-tokens/guides/how-to-create-and-register-a-mint-account-for-compression", + "compressed-tokens/guides/how-to-create-compressed-token-pools-for-mint-accounts", + "compressed-tokens/guides/how-to-merge-compressed-token-accounts", + "compressed-tokens/guides/how-to-approve-and-revoke-delegate-authority" + ] + }, + { + "group": "Advanced Guides", + "pages": [ + "compressed-tokens/advanced-guides", + "compressed-tokens/advanced-guides/how-to-combine-operations-in-one-transaction", + "compressed-tokens/advanced-guides/create-an-airdrop", + "compressed-tokens/advanced-guides/create-an-airdrop-with-claim", + "compressed-tokens/advanced-guides/add-wallet-support-for-compressed-tokens", + "compressed-tokens/advanced-guides/use-token-2022-with-compression", + "compressed-tokens/advanced-guides/example-web-client", + "compressed-tokens/advanced-guides/example-node-js" + ] + } + ] + }, + { + "group": "Compressed PDAs", + "pages": [ + "compressed-pdas/create-a-program-with-compressed-pdas", + { + "group": "Guides", + "pages": [ + "compressed-pdas/guides", + "compressed-pdas/guides/how-to-create-compressed-accounts", + "compressed-pdas/guides/how-to-update-compressed-accounts", + "compressed-pdas/guides/how-to-close-compressed-accounts", + "compressed-pdas/guides/how-to-reinitialize-compressed-accounts", + "compressed-pdas/guides/how-to-burn-compressed-accounts" + ] + }, + "compressed-pdas/program-examples" + ] + }, + { + "group": "Learn", + "pages": [ + { + "group": "Core Concepts", + "pages": [ + "learn/core-concepts", + "learn/core-concepts/compressed-account-model", + "learn/core-concepts/merkle-trees-validity-proofs", + "learn/core-concepts/transaction-lifecycle", + "learn/core-concepts/considerations" + ] + }, + "learn/ai-tools-guide" + ] + }, + { + "group": "Resources", + "pages": [ + "resources/cli-installation", + { + "group": "Error Cheatsheet", + "pages": [ + "resources/error-cheatsheet", + "resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed" + ] + }, + { + "group": "JSON RPC Methods", + "pages": [ + "resources/json-rpc-methods", + "resources/json-rpc-methods/getcompressedaccount", + "resources/json-rpc-methods/getcompressedaccountsbyowner", + "resources/json-rpc-methods/getcompressedbalancebyowner", + "resources/json-rpc-methods/getcompressedbalance", + "resources/json-rpc-methods/getcompressedminttokenholders", + "resources/json-rpc-methods/getcompressedtokenaccountbalance", + "resources/json-rpc-methods/getcompressedtokenaccountbydelegate", + "resources/json-rpc-methods/getcompressedtokenaccountsbyowner", + "resources/json-rpc-methods/getcompressedtokenbalancesbyowner", + "resources/json-rpc-methods/getcompressionsignaturesforaccount", + "resources/json-rpc-methods/getcompressionsignaturesforaddress", + "resources/json-rpc-methods/getcompressionsignaturesforowner", + "resources/json-rpc-methods/getcompressionsignaturesfortokenowner", + "resources/json-rpc-methods/getindexerhealth", + "resources/json-rpc-methods/getindexerslot", + "resources/json-rpc-methods/getlatestcompressionsignatures", + "resources/json-rpc-methods/getlatestnonvotingsignatures", + "resources/json-rpc-methods/getmultiplecompressedaccounts", + "resources/json-rpc-methods/getmultiplenewaddressproofs", + "resources/json-rpc-methods/gettransactionwithcompressioninfo", + "resources/json-rpc-methods/getvalidityproof" + ] + }, + { + "group": "SDKs", + "pages": [ + "resources/sdks", + "resources/sdks/client-development", + "resources/sdks/program-development" + ] + }, + "resources/addresses-and-urls" + ] + }, + { + "group": "References", + "pages": [ + "references/whitepaper", + "references/node-operators", + "references/terminology", + "references/security" + ] + }, + { + "group": "Links", + "pages": ["github", "discord", "deepwiki"] + } + ], + "global": { + "anchors": [ + { + "anchor": "Community", + "href": "https://discord.gg/rpddh53TeG", + "icon": "discord" + }, + { + "anchor": "About Us", + "href": "https://lightprotocol.com/blog#", + "icon": "users" + } + ] + } + }, + "logo": { + "light": "/logo/light.svg", + "dark": "/logo/dark.svg" + }, + "navbar": { + "primary": { + "type": "github", + "href": "https://github.com/Lightprotocol/light-protocol" + } + }, + "contextual": { + "options": [ + "copy", + "view", + "chatgpt", + "claude", + "perplexity", + "mcp", + "cursor", + "vscode" + ] + }, + "footer": { + "socials": { + "x": "https://x.com/LightProtocol", + "github": "https://github.com/Lightprotocol/light-protocol", + "discord": "https://discord.gg/rpddh53TeG" + } + } +} diff --git a/zk-compression-docs/mintlify-docs/favicon.png b/zk-compression-docs/mintlify-docs/favicon.png new file mode 100644 index 0000000..2997367 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/favicon.png differ diff --git a/zk-compression-docs/mintlify-docs/github.mdx b/zk-compression-docs/mintlify-docs/github.mdx new file mode 100644 index 0000000..8136ea8 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/github.mdx @@ -0,0 +1,4 @@ +--- +title: GitHub +url: "https://github.com/Lightprotocol" +--- diff --git a/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (1).svg b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (1).svg new file mode 100644 index 0000000..a0c4504 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (1).svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (2).svg b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (2).svg new file mode 100644 index 0000000..a7d0567 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (2).svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (3).svg b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (3).svg new file mode 100644 index 0000000..d5bc5b6 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (3).svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (4).svg b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (4).svg new file mode 100644 index 0000000..9c61089 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs (4).svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs.png b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs.png new file mode 100644 index 0000000..b11cfef Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs.png differ diff --git a/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs.svg b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs.svg new file mode 100644 index 0000000..9e0d508 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/1000x-cypherpunk-docs.svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/1000x-germany 1.png b/zk-compression-docs/mintlify-docs/images/1000x-germany 1.png new file mode 100644 index 0000000..eed1386 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/1000x-germany 1.png differ diff --git a/zk-compression-docs/mintlify-docs/images/1000x-germany.png b/zk-compression-docs/mintlify-docs/images/1000x-germany.png new file mode 100644 index 0000000..b85b891 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/1000x-germany.png differ diff --git a/zk-compression-docs/mintlify-docs/images/1000x-pt 1-2.png b/zk-compression-docs/mintlify-docs/images/1000x-pt 1-2.png new file mode 100644 index 0000000..63e648e Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/1000x-pt 1-2.png differ diff --git a/zk-compression-docs/mintlify-docs/images/1000xHackathon_banner.png b/zk-compression-docs/mintlify-docs/images/1000xHackathon_banner.png new file mode 100644 index 0000000..f207fcf Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/1000xHackathon_banner.png differ diff --git a/zk-compression-docs/mintlify-docs/images/1000x_35_banner.png b/zk-compression-docs/mintlify-docs/images/1000x_35_banner.png new file mode 100644 index 0000000..bddc9bb Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/1000x_35_banner.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Build_Anything.png b/zk-compression-docs/mintlify-docs/images/Build_Anything.png new file mode 100644 index 0000000..04e018f Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Build_Anything.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Design ohne Titel-2.mp4 b/zk-compression-docs/mintlify-docs/images/Design ohne Titel-2.mp4 new file mode 100644 index 0000000..b25f3f6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Design ohne Titel-2.mp4 differ diff --git a/zk-compression-docs/mintlify-docs/images/Group 632668.png b/zk-compression-docs/mintlify-docs/images/Group 632668.png new file mode 100644 index 0000000..a9f4a6d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Group 632668.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Light Protocol v2 - Batched Merkle trees (3).png b/zk-compression-docs/mintlify-docs/images/Light Protocol v2 - Batched Merkle trees (3).png new file mode 100644 index 0000000..b937bf3 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Light Protocol v2 - Batched Merkle trees (3).png differ diff --git a/zk-compression-docs/mintlify-docs/images/Light Protocol v2 - Batched Merkle trees (4) (1).png b/zk-compression-docs/mintlify-docs/images/Light Protocol v2 - Batched Merkle trees (4) (1).png new file mode 100644 index 0000000..52aceb6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Light Protocol v2 - Batched Merkle trees (4) (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/Light-Protocol-v2 -Batched-Merkle-trees-(4).png b/zk-compression-docs/mintlify-docs/images/Light-Protocol-v2 -Batched-Merkle-trees-(4).png new file mode 100644 index 0000000..52aceb6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Light-Protocol-v2 -Batched-Merkle-trees-(4).png differ diff --git a/zk-compression-docs/mintlify-docs/images/ScaleAnything (1).png b/zk-compression-docs/mintlify-docs/images/ScaleAnything (1).png new file mode 100644 index 0000000..da99be4 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/ScaleAnything (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/ScaleAnything.png b/zk-compression-docs/mintlify-docs/images/ScaleAnything.png new file mode 100644 index 0000000..6c6d571 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/ScaleAnything.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-10 at 06.22.52.png b/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-10 at 06.22.52.png new file mode 100644 index 0000000..e399eb6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-10 at 06.22.52.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-10 at 06.37.41.png b/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-10 at 06.37.41.png new file mode 100644 index 0000000..10f2e43 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-10 at 06.37.41.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-13 at 14.40.53.png b/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-13 at 14.40.53.png new file mode 100644 index 0000000..8045247 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Screenshot 2024-05-13 at 14.40.53.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Untitled (5).png b/zk-compression-docs/mintlify-docs/images/Untitled (5).png new file mode 100644 index 0000000..0f79d83 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Untitled (5).png differ diff --git a/zk-compression-docs/mintlify-docs/images/Untitled (6).png b/zk-compression-docs/mintlify-docs/images/Untitled (6).png new file mode 100644 index 0000000..d6b9296 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Untitled (6).png differ diff --git a/zk-compression-docs/mintlify-docs/images/Untitled-1.png b/zk-compression-docs/mintlify-docs/images/Untitled-1.png new file mode 100644 index 0000000..7ab901a Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Untitled-1.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Untitled-4.png b/zk-compression-docs/mintlify-docs/images/Untitled-4.png new file mode 100644 index 0000000..e8f6e3c Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Untitled-4.png differ diff --git a/zk-compression-docs/mintlify-docs/images/Untitled.png b/zk-compression-docs/mintlify-docs/images/Untitled.png new file mode 100644 index 0000000..14ab530 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/Untitled.png differ diff --git a/zk-compression-docs/mintlify-docs/images/banner-image.png b/zk-compression-docs/mintlify-docs/images/banner-image.png new file mode 100644 index 0000000..2bf791b Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/banner-image.png differ diff --git a/zk-compression-docs/mintlify-docs/images/burn-dark.png b/zk-compression-docs/mintlify-docs/images/burn-dark.png new file mode 100644 index 0000000..0892ef6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/burn-dark.png differ diff --git a/zk-compression-docs/mintlify-docs/images/burn.png b/zk-compression-docs/mintlify-docs/images/burn.png new file mode 100644 index 0000000..2facae8 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/burn.png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-burn (1).png b/zk-compression-docs/mintlify-docs/images/client-burn (1).png new file mode 100644 index 0000000..3f35764 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-burn (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-burn.png b/zk-compression-docs/mintlify-docs/images/client-burn.png new file mode 100644 index 0000000..ce1e040 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-burn.png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-close (1).png b/zk-compression-docs/mintlify-docs/images/client-close (1).png new file mode 100644 index 0000000..76c9ab2 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-close (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-close.png b/zk-compression-docs/mintlify-docs/images/client-close.png new file mode 100644 index 0000000..b2f81e7 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-close.png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-create (1).png b/zk-compression-docs/mintlify-docs/images/client-create (1).png new file mode 100644 index 0000000..d4bc0be Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-create (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-create.png b/zk-compression-docs/mintlify-docs/images/client-create.png new file mode 100644 index 0000000..a2c1e79 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-create.png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-reinit (1).png b/zk-compression-docs/mintlify-docs/images/client-reinit (1).png new file mode 100644 index 0000000..bd61b98 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-reinit (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-reinit.png b/zk-compression-docs/mintlify-docs/images/client-reinit.png new file mode 100644 index 0000000..1e2a61d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-reinit.png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-update (1).png b/zk-compression-docs/mintlify-docs/images/client-update (1).png new file mode 100644 index 0000000..04dcdcf Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-update (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/client-update.png b/zk-compression-docs/mintlify-docs/images/client-update.png new file mode 100644 index 0000000..0d30ae8 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/client-update.png differ diff --git a/zk-compression-docs/mintlify-docs/images/close-dark.png b/zk-compression-docs/mintlify-docs/images/close-dark.png new file mode 100644 index 0000000..2810120 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/close-dark.png differ diff --git a/zk-compression-docs/mintlify-docs/images/close.png b/zk-compression-docs/mintlify-docs/images/close.png new file mode 100644 index 0000000..e9e7049 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/close.png differ diff --git a/zk-compression-docs/mintlify-docs/images/create-dark.png b/zk-compression-docs/mintlify-docs/images/create-dark.png new file mode 100644 index 0000000..30abd72 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/create-dark.png differ diff --git a/zk-compression-docs/mintlify-docs/images/create.png b/zk-compression-docs/mintlify-docs/images/create.png new file mode 100644 index 0000000..e0d897d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/create.png differ diff --git a/zk-compression-docs/mintlify-docs/images/ger-banner.svg b/zk-compression-docs/mintlify-docs/images/ger-banner.svg new file mode 100644 index 0000000..5a30ebb --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/ger-banner.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/ger-card (1).svg b/zk-compression-docs/mintlify-docs/images/ger-card (1).svg new file mode 100644 index 0000000..2449e41 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/ger-card (1).svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/ger-card.png b/zk-compression-docs/mintlify-docs/images/ger-card.png new file mode 100644 index 0000000..75e75a8 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/ger-card.png differ diff --git a/zk-compression-docs/mintlify-docs/images/ger-card.svg b/zk-compression-docs/mintlify-docs/images/ger-card.svg new file mode 100644 index 0000000..7cb2f45 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/ger-card.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/image (1) (1).png b/zk-compression-docs/mintlify-docs/images/image (1) (1).png new file mode 100644 index 0000000..f5e7cba Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (1) (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (1).png b/zk-compression-docs/mintlify-docs/images/image (1).png new file mode 100644 index 0000000..8ec239a Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (10).png b/zk-compression-docs/mintlify-docs/images/image (10).png new file mode 100644 index 0000000..862e43d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (10).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (11).png b/zk-compression-docs/mintlify-docs/images/image (11).png new file mode 100644 index 0000000..3cc9dfd Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (11).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (12).png b/zk-compression-docs/mintlify-docs/images/image (12).png new file mode 100644 index 0000000..02eb33a Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (12).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (13).png b/zk-compression-docs/mintlify-docs/images/image (13).png new file mode 100644 index 0000000..e00681d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (13).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (14).png b/zk-compression-docs/mintlify-docs/images/image (14).png new file mode 100644 index 0000000..49c5ed1 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (14).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (16).png b/zk-compression-docs/mintlify-docs/images/image (16).png new file mode 100644 index 0000000..ce89a30 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (16).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (17).png b/zk-compression-docs/mintlify-docs/images/image (17).png new file mode 100644 index 0000000..7456b3b Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (17).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (18).png b/zk-compression-docs/mintlify-docs/images/image (18).png new file mode 100644 index 0000000..d9e1b88 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (18).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (19).png b/zk-compression-docs/mintlify-docs/images/image (19).png new file mode 100644 index 0000000..7be3174 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (19).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (2) (1).png b/zk-compression-docs/mintlify-docs/images/image (2) (1).png new file mode 100644 index 0000000..d7c5bc6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (2) (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (21).png b/zk-compression-docs/mintlify-docs/images/image (21).png new file mode 100644 index 0000000..b078baa Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (21).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (24).png b/zk-compression-docs/mintlify-docs/images/image (24).png new file mode 100644 index 0000000..8a629ee Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (24).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (25).png b/zk-compression-docs/mintlify-docs/images/image (25).png new file mode 100644 index 0000000..8628ab9 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (25).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (3) (1).png b/zk-compression-docs/mintlify-docs/images/image (3) (1).png new file mode 100644 index 0000000..5ba5abc Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (3) (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (32).png b/zk-compression-docs/mintlify-docs/images/image (32).png new file mode 100644 index 0000000..fc37d2d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (32).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (34).png b/zk-compression-docs/mintlify-docs/images/image (34).png new file mode 100644 index 0000000..e7a6de4 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (34).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (4).png b/zk-compression-docs/mintlify-docs/images/image (4).png new file mode 100644 index 0000000..6cf0af6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (4).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (5).png b/zk-compression-docs/mintlify-docs/images/image (5).png new file mode 100644 index 0000000..d9f386e Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (5).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (6).png b/zk-compression-docs/mintlify-docs/images/image (6).png new file mode 100644 index 0000000..2cef43a Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (6).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (7) (1).png b/zk-compression-docs/mintlify-docs/images/image (7) (1).png new file mode 100644 index 0000000..3d5601c Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (7) (1).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (7).png b/zk-compression-docs/mintlify-docs/images/image (7).png new file mode 100644 index 0000000..dcfa6e4 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (7).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (8).png b/zk-compression-docs/mintlify-docs/images/image (8).png new file mode 100644 index 0000000..ab7b724 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (8).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image (9).png b/zk-compression-docs/mintlify-docs/images/image (9).png new file mode 100644 index 0000000..d8af263 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image (9).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image-(2).png b/zk-compression-docs/mintlify-docs/images/image-(2).png new file mode 100644 index 0000000..dcbef05 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image-(2).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image-(3).png b/zk-compression-docs/mintlify-docs/images/image-(3).png new file mode 100644 index 0000000..137896f Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image-(3).png differ diff --git a/zk-compression-docs/mintlify-docs/images/image-1.png b/zk-compression-docs/mintlify-docs/images/image-1.png new file mode 100644 index 0000000..0bcf3b6 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image-1.png differ diff --git a/zk-compression-docs/mintlify-docs/images/image-20.png b/zk-compression-docs/mintlify-docs/images/image-20.png new file mode 100644 index 0000000..4e20098 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image-20.png differ diff --git a/zk-compression-docs/mintlify-docs/images/image-22.png b/zk-compression-docs/mintlify-docs/images/image-22.png new file mode 100644 index 0000000..44513c8 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image-22.png differ diff --git a/zk-compression-docs/mintlify-docs/images/image-23.png b/zk-compression-docs/mintlify-docs/images/image-23.png new file mode 100644 index 0000000..ffbb122 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/image-23.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-burn-1.png b/zk-compression-docs/mintlify-docs/images/program-burn-1.png new file mode 100644 index 0000000..8fd67a4 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-burn-1.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-burn.png b/zk-compression-docs/mintlify-docs/images/program-burn.png new file mode 100644 index 0000000..33a16d0 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-burn.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-close.png b/zk-compression-docs/mintlify-docs/images/program-close.png new file mode 100644 index 0000000..2e1121f Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-close.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-closes.png b/zk-compression-docs/mintlify-docs/images/program-closes.png new file mode 100644 index 0000000..c6ee54d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-closes.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-create-1.png b/zk-compression-docs/mintlify-docs/images/program-create-1.png new file mode 100644 index 0000000..87f0791 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-create-1.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-create.png b/zk-compression-docs/mintlify-docs/images/program-create.png new file mode 100644 index 0000000..feb2733 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-create.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-reinit-1.png b/zk-compression-docs/mintlify-docs/images/program-reinit-1.png new file mode 100644 index 0000000..f7e8137 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-reinit-1.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-reinit.png b/zk-compression-docs/mintlify-docs/images/program-reinit.png new file mode 100644 index 0000000..3db7d54 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-reinit.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-update-1.png b/zk-compression-docs/mintlify-docs/images/program-update-1.png new file mode 100644 index 0000000..2e7b149 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-update-1.png differ diff --git a/zk-compression-docs/mintlify-docs/images/program-update.png b/zk-compression-docs/mintlify-docs/images/program-update.png new file mode 100644 index 0000000..8fb6b8d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/program-update.png differ diff --git a/zk-compression-docs/mintlify-docs/images/pt-card (1).svg b/zk-compression-docs/mintlify-docs/images/pt-card (1).svg new file mode 100644 index 0000000..504ed35 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/pt-card (1).svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/pt-card.png b/zk-compression-docs/mintlify-docs/images/pt-card.png new file mode 100644 index 0000000..36f883e Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/pt-card.png differ diff --git a/zk-compression-docs/mintlify-docs/images/pt-card.svg b/zk-compression-docs/mintlify-docs/images/pt-card.svg new file mode 100644 index 0000000..a4d584b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/pt-card.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/pt-new.svg b/zk-compression-docs/mintlify-docs/images/pt-new.svg new file mode 100644 index 0000000..c84a78b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/images/pt-new.svg @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/images/reinit-dark.png b/zk-compression-docs/mintlify-docs/images/reinit-dark.png new file mode 100644 index 0000000..f2e7418 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/reinit-dark.png differ diff --git a/zk-compression-docs/mintlify-docs/images/reinit.png b/zk-compression-docs/mintlify-docs/images/reinit.png new file mode 100644 index 0000000..0e16cbb Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/reinit.png differ diff --git a/zk-compression-docs/mintlify-docs/images/solanazero-banner Large 2.jpeg b/zk-compression-docs/mintlify-docs/images/solanazero-banner Large 2.jpeg new file mode 100644 index 0000000..8d539fa Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/solanazero-banner Large 2.jpeg differ diff --git a/zk-compression-docs/mintlify-docs/images/solanazero-banner Large.jpeg b/zk-compression-docs/mintlify-docs/images/solanazero-banner Large.jpeg new file mode 100644 index 0000000..0df338b Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/solanazero-banner Large.jpeg differ diff --git a/zk-compression-docs/mintlify-docs/images/solanazero-banner.jpg b/zk-compression-docs/mintlify-docs/images/solanazero-banner.jpg new file mode 100644 index 0000000..9c67ea0 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/solanazero-banner.jpg differ diff --git a/zk-compression-docs/mintlify-docs/images/update-dark.png b/zk-compression-docs/mintlify-docs/images/update-dark.png new file mode 100644 index 0000000..1c0e983 Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/update-dark.png differ diff --git a/zk-compression-docs/mintlify-docs/images/update.png b/zk-compression-docs/mintlify-docs/images/update.png new file mode 100644 index 0000000..d933adb Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/update.png differ diff --git a/zk-compression-docs/mintlify-docs/images/zkc24-ezgif.com-video-to-gif-converter.gif b/zk-compression-docs/mintlify-docs/images/zkc24-ezgif.com-video-to-gif-converter.gif new file mode 100644 index 0000000..0816c5d Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/zkc24-ezgif.com-video-to-gif-converter.gif differ diff --git a/zk-compression-docs/mintlify-docs/images/zkcompression_1000x_banner.png b/zk-compression-docs/mintlify-docs/images/zkcompression_1000x_banner.png new file mode 100644 index 0000000..30e2dab Binary files /dev/null and b/zk-compression-docs/mintlify-docs/images/zkcompression_1000x_banner.png differ diff --git a/zk-compression-docs/mintlify-docs/index.mdx b/zk-compression-docs/mintlify-docs/index.mdx new file mode 100644 index 0000000..1321126 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/index.mdx @@ -0,0 +1,145 @@ +--- +title: Introduction +description: Solana account primitive for tokens and PDAs at a fraction of the cost - scale to millions of users without sacrificing L1 performance and security. +icon: book-open +--- + + + ![](/images/banner-image.png) + + +ZK Compression is a Solana account primitive that lets you create tokens and PDAs at a fraction of the cost. Scale your application to millions of users without sacrificing L1 performance and security guarantees. + +| Creation | Regular Account | Compressed Account | Cost Reduction | +|:-------------------------|:------------------|:-----------------------|:----------------| +| 100-byte PDA Account | 0.0016 SOL | **~ 0.00001 SOL** | **160x** | +| 100 Token Accounts | ~ 0.2 SOL | **~ 0.00004 SOL** | **5000x** | + +### Core Features + + + + Create accounts without paying upfront rent. + + + Execution and data availability on Solana. + + + Compatible with existing programs and accounts. + + + + +### Start Building + + + + Test compressed tokens in less than 5 minutes. + + + Create SPL-compatible tokens 5000x cheaper. + + + Store your app state in accounts with 98% less cost. + + + + +### What is ZK Compression? + +ZK Compression is a framework that reduces the storage cost of Solana accounts by combining generalized state compression and zero-knowledge proofs. + + + + + Instead of storing account data in millions of on-chain accounts, state compression stores account data on the Solana ledger with cryptographic security. Only a small fingerprint is stored on-chain. This fingerprint allows transactions to use the account data inside Solana's virtual machine as if it were stored on-chain. + + + The protocol uses small zero-knowledge proofs (validity proofs) to verify the integrity of the compressed accounts. By default, this is all done under the hood. You can fetch validity proofs from RPC providers that support ZK Compression. + + + +### Using AI to work with ZK Compression + +Integrate ZK Compression in your existing AI workflow by following the steps below. + +| Tool | Description | Link | +|:---------------------|:------------------------------------------------------------------------------|:--------------------------------------| +| DeepWiki/AskDevin | Query the Light Protocol codebase and documentation in natural language | Ask DeepWiki | +| MCP | Connect AI tools to the Light Protocol repository via Model Context Protocol | [Setup Guide](https://www.zkcompression.com/references/ai-tools-guide#mcp) | +| Docs AI Search | Search documentation with AI in the search bar. | Available throughout the documentation | + + +**AI powered navigation**: Use AI search to quickly find information, get code examples, and learn complex topics. Available throughout our documentation. + + + + + + + +### Resources + + + Browse ZK Compression's JSON RPC methods. + + + Explore our TypeScript and Rust SDKs. + + + Install the ZK Compression CLI for local development. + + + +### Learn & Community + + + Learn about ZK Compression's core concepts. + + + Read our external audit and formal verification reports. + + + Join our Discord for support and discussions. + + diff --git a/zk-compression-docs/mintlify-docs/learn/ai-tools-guide.mdx b/zk-compression-docs/mintlify-docs/learn/ai-tools-guide.mdx new file mode 100644 index 0000000..eed86f3 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/learn/ai-tools-guide.mdx @@ -0,0 +1,192 @@ +--- +title: "AI Tools Guide" +description: "Guidance to AI tools when working with ZK Compression. Includes MCP server, DeepWiki, and AI Search guides." +--- + +## For Docs + +- **Docs AI Search** - Search documentation with AI in the search bar. +- **llms.txt** - Site index for LLM navigation: [https://zkcompression.com/llms.txt](https://zkcompression.com/llms.txt). +- **Markdown Export** - Append `.md` to any page URL for raw markdown. + +## **For Development** + +
+

DeepWiki

+ + Ask DeepWiki + +
+ +Use DeepWiki and its search capabilities (AskDevin) to query the Light Protocol repository in natural language. + +* DeepWiki generates systematic documentation. +* Use AskDevin for help with _debugging and technical questions_: + + + + + + +You can index and query any public GitHub repository with DeepWiki to produce wikis with architecture diagrams, source links, and codebase summaries. + + +## MCP + +The Model Context Protocol (MCP) is an open standard to connect AI apps to data sources and tools. The DeepWiki MCP server provides access to the Light Protocol repository with its search capabilities (AskDevin). + +### Installation + + + + +```bash +claude mcp add -s user -t http deepwiki https://mcp.deepwiki.com/mcp +``` + + +We recommend to create a command that includes the tools listed below. Simply copy paste this snippet. + + +```markdown expandable +--- +argument-hint: +description: Query Light Protocol repository and Solana resources via DeepWiki MCP for precise technical answers and help with debugging +allowed-tools: mcp__deepwiki__* +--- + +# /ask-deepwiki + +Answer: $ARGUMENTS + +Use DeepWiki MCP to provide precise technical answers. + +## Step 1: Identify Repository Scope + +1. **State understanding and plan** + +2. **If question is vague, ask for clarification:** +- What specific component or feature? +- What problem are you solving? +- What level of detail needed (overview vs implementation)? + +3. **Repository mapping:** +- ZK Compression/Light Protocol: `Lightprotocol/light-protocol` +- Solana fundamentals: `solana-labs/solana` +- Anchor framework: `solana-foundation/anchor` +- Complex questions: Query multiple repositories + +4. **Refine question to use:** +- Exact component names: `CompressedAccountMeta` not "account metadata" +- Specific operations: "verifies proof" not "handles proof" +- Concrete function names or error messages when available + +## Step 2: Query DeepWiki + +For the identified repository, call in sequence: + +1. `mcp__deepwiki__read_wiki_structure("repo-owner/repo-name")` +2. `mcp__deepwiki__read_wiki_contents("repo-owner/repo-name")` +3. `mcp__deepwiki__ask_question("repo-owner/repo-name", refined_question)` + +Query multiple repositories if question spans different systems. + +## Step 3: Format Response + +**Structure:** +1. Direct answer with technical explanation +2. Specific implementations and data structures +3. Code examples with inline comments +4. Source references (`file:line` from DeepWiki) +5. Related concepts if relevant + +**Language precision:** + +NEVER use vague verbs: +- "handles", "manages", "processes", "enables", "provides" + +ALWAYS use exact names: +- Functions: `LightAccount::new_init()`, `derive_address()` +- Types: `CompressedAccountMeta`, `ValidityProof`, `PackedAddressTreeInfo` +- Operations: "nullifies hash", "appends to state tree", "verifies proof" +- Fields: `tree_info`, `address`, `output_state_tree_index` + +Include `file:line` references from DeepWiki responses. + +## Notes + +- Always include source file references from DeepWiki responses +- Provide runnable code examples for implementation questions +- Ask follow-up questions to DeepWiki for clarification when needed +``` + + + + +```json +{ + "mcpServers": { + "deepwiki": { + "serverUrl": "https://mcp.deepwiki.com/sse" + } + } +} +``` + + + +### Tools + +The MCP server offers three main tools: + +- **read\_wiki\_structure** - Get a list of documentation topics for a GitHub repository + +```bash +mcp__deepwiki__read_wiki_structure("Lightprotocol/light-protocol") +``` + +- **read\_wiki\_contents** - View documentation about a GitHub repository + +```bash +mcp__deepwiki__read_wiki_contents("Lightprotocol/light-protocol") +``` + +- **ask\_question** - Ask any question about the GitHub repository and get a context-grounded response + +```bash +mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "your question") +``` + + +You can specify any public GitHub repo that is indexed with DeepWiki. When you connect to the MCP, you specify the repository when calling the tools. Learn more [here](https://docs.devin.ai/work-with-devin/deepwiki-mcp). + + +## Next Steps + +Start testing your AI tools with compressed tokens or PDAs. + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/learn/core-concepts.mdx b/zk-compression-docs/mintlify-docs/learn/core-concepts.mdx new file mode 100644 index 0000000..d743419 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/learn/core-concepts.mdx @@ -0,0 +1,64 @@ +--- +title: "Core Concepts" +sidebarTitle: "Overview" +description: "Overview to ZK Compression's Core Concepts. Get a high-level system overview and learn about the compressed account model, lifecycle of a transaction, and considerations." +--- + + +
+ + Ask DeepWiki + + to query the program examples in natural language. +
+
+ +ZK Compression is an account primitive on Solana that drastically reduces on-chain state costs while maintaining Solana's security, composability, and performance. + +## High-level System Overview + +This is how it works at a high level: + +### Storage of Compressed State + +Compressed accounts store state as call data in [Solana's ledger](#user-content-fn-1)[^1], removing rent per account. + +### Accessing Compressed State + +Transactions specify state they access (read/write) and include it in the transaction payload. + +### State Validation + +Solana Programs invoke the Light System Program to update compressed state + +1. **The protocol validates the state** (validity of existing state, sum checks, ownership checks) +2. **The protocol enforces a schema:** Classic Accounts → Compressed Accounts.\ + Compressed accounts have a layout similar to classic accounts. + +### State Updates + +The new state is recorded as a log on the Solana ledger with each transaction. + +### Photon RPC Nodes + +Photon RPC nodes index the state changes, making the compressed account state available to clients via the ZK Compression RPC API. + +### Forester Nodes + +Keeper nodes that interact with the Account Compression Program to empty queues and rollover state trees. + + +Clients and custom programs do not interact with Forester nodes or the Account Compression Program. This is all done under the hood. + + +## Next Steps + +In the following sections, we'll dive into the core concepts that make ZK Compression possible: + +- **Compressed Account Model**: Understand how compressed accounts differ from regular Solana accounts (not much!) and how they enhance efficiency. +- **State Trees**: Learn about the Merkle tree structure used to store compressed accounts and how it minimizes on-chain storage. +- **Validity Proofs**: Explore how the protocol uses zero-knowledge proofs to verify data validity while keeping proof sizes small. +- **Lifecycle of a Transaction**: Follow the journey of a ZK-compressed transaction from creation to execution. +- **Considerations**: Discover the trade-offs and scenarios where ZK Compression may or may not be the best solution. + + diff --git a/zk-compression-docs/mintlify-docs/learn/core-concepts/compressed-account-model.mdx b/zk-compression-docs/mintlify-docs/learn/core-concepts/compressed-account-model.mdx new file mode 100644 index 0000000..74e5371 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/learn/core-concepts/compressed-account-model.mdx @@ -0,0 +1,177 @@ +--- +title: "Compressed Account Model" +description: "Overview to compressed accounts and comparison to Solana accounts." +--- + +## Overview + + +This guide assumes that you're familiar with [Solana's account model](https://solana.com/docs/core/accounts). + + +Compressed accounts store state and are similar to regular Solana accounts but with five main differences: + +- Each compressed account can be identified by its hash +- Each write to a compressed account changes its hash +- An `address` can optionally be set as a permanent unique ID of the compressed account. +- All compressed accounts are stored in sparse state trees. Only the tree's state root (i.e., a small fingerprint of all compressed accounts) is stored in the on-chain account space. + +These differences make compressed accounts rent-free and allow the protocol to store state as calldata on the Solana ledger instead of the costly on-chain account space. + +## In a Nutshell + +Transactions can use compressed account data inside Solana's virtual machine as if it were stored on-chain by combining state compression and zero-knowledge proofs: + +1. Millions of compressed accounts are stored as hashes in Merkle tree leaves +2. All accounts stored in a Merkle tree are compressed into a single root hash +3. The root hash is stored in one Solana account for cryptographic verification +4. Compressed account state is recorded on the Solana ledger +5. The latest compressed account state is fetched from your RPC provider +6. Compressed account state is verified against the on-chain root hash with a validity proof + + +- Merkle trees are provided by the protocol and Indexers generate validity proofs. +- Developers don't configure state Merkle trees or generate validity proofs. + +[You will learn more about Merkle trees and validity proofs in the next section](/learn/core-concepts/merkle-trees-validity-proofs). + + +## Compressed Account Structure + +Compressed accounts include the core Solana account fields (owner, lamports, data) plus additional fields to index and store compressed state. + +```rust +pub struct CompressedAccount { + pub address: Option<[u8; 32]>, // Optional persistent identifier + pub data: Option, // Account data + pub hash: [u8; 32], // Unique account hash + pub lamports: u64, // Account balance + pub owner: Pubkey, // Program that owns this account +} +``` + + +Find the [source code here](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/client/src/indexer/types.rs#L508-L520). + + + + +```rust +pub struct Account { + pub lamports: u64, // Account balance + pub data: Vec, // Arbitrary data (program state) + pub owner: Pubkey, // Program that owns this account + pub executable: bool, // Is this a program account + pub rent_epoch: Epoch, // Legacy field +} +``` + + +Find the source code here: [agave/sdk/account/src/lib.rs:48-60](https://github.com/anza-xyz/agave/blob/67412607f511ded3770031280b6aaf10607713fc/sdk/account/src/lib.rs#L48-L60) + + + + +## Address and Hash + +Each compressed account can be **identified by its hash**, regardless of whether it has an address. By definition, whenever any data of a compressed account changes, its **hash changes**. + +An **address** can serve as **optional** and additional **persistent identifier**. +* It's represented as 32 bytes in the format of a `PublicKey`. +* Addresses are optional, since ensuring that the address of a new account is unique incurs additional computational overhead. + + +- Use the address field wherever the state must be unique (such as for NFTs or certain PDAs) and requires a persistent identifier. +- You don't need the address for any fungible state (e.g., fungible tokens) + + +**Compressed Account Address Derivation** + +Compressed account addresses are derived similar to PDAs. + +* Like PDAs, compressed account addresses don't belong to a private key; rather, they're derived from the program that owns them. +* The key difference to regular PDAs is that compressed accounts require an **address tree** parameter. +* Address Merkle tree's store addresses of compressed accounts and ensure its uniqueness. + + + + +```typescript +const seed = deriveAddressSeed( + [customSeed, signer.publicKey.toBytes()], + new web3.PublicKey(programId), +); +const address = deriveAddress(seed, addressTree); +``` + + +Learn more about address derivation for a [Typescript Client here](https://github.com/Lightprotocol/developer-content/blob/main/zk-compression-docs/compressed-pdas/client-library/typescript.md#derive-address). + + + + + + +```rust +let (address, _) = derive_address( + &[b"custom_seed", keypair.pubkey().as_ref()], + &address_tree_info.tree, + &your_program::ID, +); +``` + + +Learn more about address derivation for a [Rust Client here](https://github.com/Lightprotocol/developer-content/blob/main/zk-compression-docs/compressed-pdas/client-library/rust.md#derive-address). + + + + + + + + +```typescript derive-pda.ts +const [pda, bump] = PublicKey.findProgramAddressSync( + [ + Buffer.from("seed_string"), + publicKey.toBuffer() + ], + programId +); +``` + +```rust derive-pda.rs +let (pda, bump) = Pubkey::find_program_address( + &[ + b"seed_string", + pubkey.as_ref() + ], + &program_id +); +``` + + + + +## Data Field + +The `data` field contains the compressed account's program state: + +```rust +pub struct CompressedAccountData { + pub discriminator: [u8; 8], // Type identifier for account data + pub data: Vec, // Serialized program state + pub data_hash: [u8; 32], // Hash of the data field +} +``` + +- `discriminator`: Identifies the data type for programs to correctly deserialize account data. Similar to Anchor's 8-byte account discriminator. +- `data`: Stores the account's current state as arbitrary bytes (e.g., serialized user data, balances, metadata). + * Compressed accounts have no fixed maximum size to store data like Solana's 10 MB. + * Still, Solana's 1,232-byte transaction limit constrains practical data size to roughly 1 KB per account. +- `data_hash`: Hash of the `data` field (32 bytes). + * When computing the compressed account hash for the state tree, the protocol uses this fixed-size hash instead of the variable-length data bytes. + +## Next Steps + +Learn about the role of validity proofs and Merkle trees in the protocol. diff --git a/zk-compression-docs/mintlify-docs/learn/core-concepts/considerations.mdx b/zk-compression-docs/mintlify-docs/learn/core-concepts/considerations.mdx new file mode 100644 index 0000000..ed1ed0f --- /dev/null +++ b/zk-compression-docs/mintlify-docs/learn/core-concepts/considerations.mdx @@ -0,0 +1,74 @@ +--- +title: "Considerations" +description: "Overview to considerations of ZK Compression, namely larger transaction size, higher compute unit usage, and per-transaction state cost." +--- + +## Overview + +Before using ZK Compression to scale your application state, consider the following limitations of compressed accounts: + +- Larger Transaction Size +- High Compute Unit Usage +- Per-Transaction State Cost + +## General Recommendation + + +Consider which accounts in your application benefit from ZK Compression and which don't. +- You can use both types for different parts of your application. +- You can decompress and compress accounts at will. + + +It may be preferred for an account _not_ to be permanently compressed if: + +- The account gets updated very frequently within a single block (e.g., shared liquidity pools in a DeFi protocol). +- You expect the lifetime number of writes to the same account to be very large (>>1000x). +- The account stores large amounts of data, and you need to access a large part of it (>1kb) inside one on-chain transaction. + +## Larger Transaction Size + +Solana's transaction size limit is 1232 Bytes. Transactions exceeding this limit will fail. ZK Compression increases your transaction size in two ways: + +- 128 bytes must be reserved for the validity proof, which is a constant size per transaction, assuming the transaction reads from at least one compressed account. +- You must send the account data you want to read/write on-chain. + +## High Compute Unit Usage + + +System CU usage: + +- \~100,000 CU for validity proof verification, which is a constant size per transaction, assuming the transaction reads from at least one compressed account +- \~100,000 CU system use (state tree [Poseidon](https://eprint.iacr.org/2019/458.pdf) hashing et al.) +- \~6,000 CU per compressed account read/write + +**Example**: a typical compressed token transfer uses around 292,000 CU. + + +Higher CU usage can: + +- **Lead to usage limits:** The total CU limit per transaction is 1,400,000 CU, and the per-block write lock limit per State tree is 12,000,000 CU. +- **Require your users to increase their** [**priority fee**](https://solana.com/developers/guides/advanced/how-to-use-priority-fees) **during congestion:** Whenever Solana's global per-block CU limit (48,000,000 CU) is reached, validator clients may prioritize transactions with higher per-CU priority fees. + +## State Cost per Transaction + +Each write operation incurs a small additional network cost. If you expect a single compressed account to amass a large amount of state updates, the lifetime cost of the compressed account may be higher than its uncompressed equivalent, which currently has a fixed per-byte rent cost at creation. + + +Whenever a transaction writes to a compressed account, it nullifies the previous compressed account state and appends the new compressed account as a leaf to the state tree. Both of these actions incur costs that add to Solana's base fee. + + +| Type | Lamports | Notes | +|:-|:-|:-| +| **Solana base fee** | `5000` per signature | Compensates validators for processing transactions | +| **Write new compressed account state** | ~`300` per leaf (default) | Depends on tree depth:
( 2tree_depth × tree_account_rent_cost × rollover_threshold)
≈ `300` for the default depth of `26` | +| **Nullify old compressed account state** | `5000` per transaction | Reimburses the cost of running a Forester transaction. The current default Forester node implementation can be found here | +| **Create addresses** | `5000` per transaction | Same as nullify | + +## Next Steps + +Now you're familiar with the core concepts of ZK Compression, you're ready to take the next step and start building! + + + + + diff --git a/zk-compression-docs/mintlify-docs/learn/core-concepts/merkle-trees-validity-proofs.mdx b/zk-compression-docs/mintlify-docs/learn/core-concepts/merkle-trees-validity-proofs.mdx new file mode 100644 index 0000000..3569589 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/learn/core-concepts/merkle-trees-validity-proofs.mdx @@ -0,0 +1,165 @@ +--- +title: "Merkle trees and Validity Proofs" +description: "Learn the core concepts of state trees, address trees, and validity proofs for compressed accounts." +--- + +## Overview + +The protocol uses two types of Merkle trees that serve different purposes: + +- [**State trees**](#state-trees) store compressed account hashes +- [**Address trees**](#address-merkle-trees) store addresses that serve as persistent identifiers + +The protocol maintains multiple Merkle trees to reduce write-lock contention. Solana's runtime locks accounts during writes, wherefore a single tree would become a bottleneck. Multiple trees allow parallel transactions. + + +Developers don't need to maintain or initialize Merkle trees themselves. + + +## State trees + +A state tree is a binary Merkle tree that stores data of millions of compressed Solana accounts in leaves for efficient cryptographic verification the integrity of all leaves in a tree. + + + + +A Merkle tree compresses data by hashing adjacent leaves repeatedly into a single root hash, starting from the lowest level. The hash of a compressed Solana account is stored as a leaf in a State tree. + + + + +Only this root hash is stored on chain as single value on chain to secure the integrity of all compressed state in a tree. The raw state can thus be stored as calldata in the much cheaper Solana ledger space while preserving Solana's security guarantees. + + + + + + + + + +For compressed Solana accounts, the 32 byte leaf hashes effectively mirror the regular Solana account layout: `{DataHash, StateHash; Owner, Lamports`. + +The `data_hash` represents the fingerprint of the actual account data. + +The `state_hash` ensures that each account hash is globally unique. It includes + +* the public key of the state tree's respective on-chain account (i.e., `state_tree_hash`) and +* the compressed account's position in the tree (i.e., `leafIndex`). + +Lastly, `owner_hashed` determines which program owns this account and `lamports` show the account balance. + + +For [details on the compressed account structure see this section](/learn/core-concepts/compressed-account-model#compressed-account-structure). + + + + + + + + + +In state trees, a validity proof verifies that a compressed account exists in state trees with a constant 128-byte proof size. This proof must be included in every transaction once a compressed account is created to verify the on-chain state. + + +- Developers don't need to generate validity proofs or learn about ZK to use ZK Compression. +- ZK Compression uses [Groth16](https://docs.rs/groth16-solana/latest/groth16_solana/), a well-known [pairing-based](https://en.wikipedia.org/wiki/Pairing-based_cryptography) [zk-SNARK](https://www.helius.dev/blog/zero-knowledge-proofs-its-applications-on-solana#-zk-snarks-and-circuits), for its proof system. + + +The validity proof contains one or more merkle proofs: + +- Merkle proofs consist of sibling node hashes along the path from the account's leaf to the root. +- Starting with the leaf hash, the verifier calculates up the tree using these sibling hashes. The proof path is shown with three highlighted elements in a box at the bottom right: Leaf 0, Node 1, and Node 5, representing the sibling hashes needed to verify Leaf 1. +- If the calculated root matches the on-chain root, the account is verified. + + + Merkle tree diagram illustrating a leaf proof for Leaf 1. The tree shows a purple root node at the top, branching down through intermediate nodes (Node 4 and Node 5 in green and blue respectively) to eight leaf nodes at the bottom (Leaf 0 through Leaf 7). Leaf 1 is highlighted in green and labeled as 'compressed account'. The proof path is shown with three highlighted elements in a box at the bottom right: Leaf 0, Node 1, and Node 5, representing the sibling hashes needed to verify Leaf 1's inclusion in the tree. Caption explains that a Merkle proof consists of sibling node hashes required to calculate the final root node, with only adjacent hashes along the path to the root needed. + + + +For a tree with height 26, a single proof requires 26 sibling hashes (32 bytes each) plus metadata totaling 832 bytes. The proof size grows with tree height. + +ZK Compression batches multiple Merkle proofs into a single zero-knowledge proof to achieve a constant 128-byte size regardless of how many accounts are verified: + +| Accounts Verified | Proof Components | Size | +|:-|:-|:-| +| 1 | 1 merkle proof | 832 bytes | +| 1 | 1 merkle + 1 ZK proof | 128 bytes | +| 8 | 8 merkle + 1 ZK proof | 128 bytes | + + +Two **state tree versions** with different proof mechanisms are currently supported: + +- **V1 state trees**: Always require the full 128-byte ZK proof +- **V2 batched state trees**: Can use `prove_by_index` optimization that verifies the account exists with only one byte instead of 128-bytes. + +**V2** optimizes optimize compute unit consumption by up to 70% and is **currently on Devnet**. + +When using V2 trees, RPC requests automatically choose the proof mechanism. + + + + +## Address trees + +Address trees store addresses that serve as optional, persistent identifiers for compressed accounts. + + +Every address is unique within its address tree, but the same seeds can create different addresses in different address trees. To enforce that a compressed account can only be created once with the same seed, check the address tree pubkey in your program. + + + + + +Address trees store derived addresses in an indexed structure. Unlike state trees that store account hashes, address trees store the actual address values along with pointers to maintain sorted order. + +These addresses are used only when compressed accounts require a persistent identifier that doesn't change when the account data updates. + + + + +Like state trees, only the root hash is stored on-chain to verify all addresses in the tree. The raw addresses are stored in the Solana ledger. + + + + +In address trees, validity proofs verify when creating a compressed account with an address that the address doesn't already exist in a specified address tree. This constant 128-byte proof must be included in the transaction only when creating accounts with addresses, not for subsequent compressed account interactions. + + +Two **address tree versions** are currently supported: + +- **V1 address trees** height 26 (\~67 million addresses). +- **V2 batched address trees** with height 40 (\~1 trillion addresses). + +**V2** optimizes optimize compute unit consumption by up to 70% and is **currently on Devnet**. + +When using V2 trees, RPC requests automatically choose the proof mechanism. + + + + +## Resources on ZK + +For those interested in learning more about the fundamentals of ZK and its applications on Solana, we recommend reading the following: + + + + + + + + +## Next Steps + +Learn about the lifecycle of a transaction that interacts with compressed accounts. diff --git a/zk-compression-docs/mintlify-docs/learn/core-concepts/transaction-lifecycle.mdx b/zk-compression-docs/mintlify-docs/learn/core-concepts/transaction-lifecycle.mdx new file mode 100644 index 0000000..032bddb --- /dev/null +++ b/zk-compression-docs/mintlify-docs/learn/core-concepts/transaction-lifecycle.mdx @@ -0,0 +1,176 @@ +--- +title: "Lifecycle of a Transaction" +description: "Overview to the lifecycle of a transaction that interacts with compressed accounts." +--- + +## Overview + + +This guide assumes you are familiar with transactions on Solana. If you aren't, we recommend to read the [Solana documentation on transactions](https://solana.com/docs/core/transactions). + + +Transactions to interact with compressed accounts are fully compatible with Solana's Transaction and Versioned Transaction formats. + +There are few nuances to build transactions with compressed accounts as compared to regular accounts: + +- Instructions must specify the list of all compressed accounts being read or written to. +- To read or write to a compressed account, the instruction must send the current account state on-chain and prove its validity. +- Each unique state tree that gets read or written to (via any compressed account) needs to be specified as per Solana's regular on-chain [account access lists](https://solana.com/docs/core/transactions#array-of-account-addresses). + +## Reading Compressed Accounts + +Reading compressed accounts follows a similar pattern to Solana accounts. + +- The main difference is that compressed account RPC methods query an indexer instead of the ledger directly. +- The indexer, called Photon, reconstructs compressed account state from the Solana ledger by reading transaction logs. + +The API exposed by the indexer closely mirrors existing RPC calls, with one-to-one mapping: + +| Solana RPC | Photon RPC Calls | +|:-|:-| +| getAccountInfo | getCompressedAccount | +| getBalance | getCompressedBalance | +| getTokenAccountsByOwner | getCompressedTokenAccountsByOwner | +| getProgramAccounts | getCompressedAccountsByOwner | + + + +Clients read compressed accounts similar to Solana accounts: + +1. Fetch the compressed account data from your RPC provider using its address or hash + * Here you use [`getCompressedAccount()`](/resources/json-rpc-methods/getcompressedaccount), similar to `getAccountInfo()`. +2. Deserialize the account's data field into the appropriate data structure. + + +```typescript TypeScript +// 1. Fetch compressed account from indexer +const compressedAccount = await rpc.getCompressedAccount( + bn(address.toBytes()) +); + +// 2. Deserialize account data +const accountData = coder.types.decode( + "AccountType", + compressedAccount.data.data +); +``` + +```rust Rust +// 1. Fetch compressed account from indexer +let compressed_account = rpc + .get_compressed_account(address, None) + .await? + .value + .unwrap(); + +// 2. Deserialize account data +let account_data = deserialize(&compressed_account.data)?; +``` + + + + +On-chain reading within programs requires a validity proof to verify the account exists in the state tree. + +1. Fetch the compressed account data from your RPC provider using its address or hash +2. Fetch a validity proof using the account hash via [`getValidityProof()`](/resources/json-rpc-methods/getvalidityproof). +3. Clients pass the proof to the on-chain program in the instruction data. + + +```typescript TypeScript +// 1. Fetch compressed account from indexer +const compressedAccount = await rpc.getCompressedAccount( + bn(address.toBytes()) +); + +// 2. Get validity proof using account hash +const proof = await rpc.getValidityProof( + [bn(compressedAccount.hash)] +); + +// 3. Proof is included in transaction instructions +``` + +```rust Rust +// 1. Fetch compressed account from indexer +let compressed_account = rpc + .get_compressed_account(address, None) + .await? + .value + .unwrap(); + +// 2. Get validity proof using account hash +let proof = rpc + .get_validity_proof(vec![compressed_account.hash], vec![], None) + .await? + .value; + +// 3. Proof is included in transaction instructions +``` + + + +See this [read-only program example](https://github.com/Lightprotocol/program-examples/tree/main/read-only) implementation. + + + + +## Writing to Compressed Accounts + +Writing to compressed accounts can be described more generally as: + +```bash +(state, validityProof) -> state transition -> state' +``` + +**Writing to a compressed account involves these steps:** + +1. Fetch the compressed account data from your RPC provider using its address or hash +2. Fetch a validity proof from your RPC provider using the account hash via [`getValidityProof()`](/resources/json-rpc-methods/getvalidityproof) to prove the account hash exists in the state tree. + +The Solana program executing the state transition _**Data**_** -> **_**Data'**_ requires its client to pack the instructions with: + +- `address`: persistent identifier of the compressed account (unchanged) +- `owner program`: program ID that owns this account (unchanged) +- `data`: current account data +- `data'`: updated account data +- `validity proof`: 128-byte ZK proof that verifies the current account hash exists in the state tree + + +See this [guide to update a compressed account](/compressed-pdas/guides/how-to-update-compressed-accounts). + + + + + + + +## On-chain Execution + +To write compressed state, a program invokes the Light System Program via CPI. The system program then does the following: + +1. Runs relevant checks ([sum check](https://github.com/Lightprotocol/light-protocol/blob/v.1.0.0/programs/system/src/invoke/verify_state_proof.rs#L204-L210), etc.) +2. [Verifies the validity proof](https://github.com/Lightprotocol/light-protocol/blob/v.1.0.0/programs/system/src/invoke/processor.rs#L209-L214) +3. [Nullifies](https://github.com/Lightprotocol/light-protocol/blob/v.1.0.0/programs/system/src/invoke/processor.rs#L209-L214) the existing leaf of the compressed account that is being written to, to prevent double spending. +4. [Appends](https://github.com/Lightprotocol/light-protocol/blob/v.1.0.0/programs/system/src/invoke/processor.rs#L245-L254) the new compressed account hash to the state tree and advances the tree's state root +5. [Emits](https://github.com/Lightprotocol/light-protocol/blob/v.1.0.0/programs/system/src/invoke/processor.rs#L272-L279) the new compressed account state onto the Solana ledger + +An RPC node then parses the transaction and compressed state and provides the read state to clients via the ZK Compression RPC API. + + + + + + + + + + + + + + + +## Next Steps + +Take the last step and understand what the trade-offs for compressed accounts are. diff --git a/zk-compression-docs/mintlify-docs/logo/dark.svg b/zk-compression-docs/mintlify-docs/logo/dark.svg new file mode 100644 index 0000000..7dac2fa --- /dev/null +++ b/zk-compression-docs/mintlify-docs/logo/dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/logo/light.svg b/zk-compression-docs/mintlify-docs/logo/light.svg new file mode 100644 index 0000000..28bfe06 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/logo/light.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/zk-compression-docs/mintlify-docs/openapi/api.yaml b/zk-compression-docs/mintlify-docs/openapi/api.yaml new file mode 100644 index 0000000..0434a08 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/api.yaml @@ -0,0 +1,5125 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://devnet.helius-rpc.com?api-key= +paths: + /getBatchAddressUpdateInfo: + summary: getBatchAddressUpdateInfo + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getBatchAddressUpdateInfo + params: + type: object + required: + - tree + - batchSize + properties: + batchSize: + type: integer + format: uint16 + minimum: 0 + tree: + $ref: '#/components/schemas/Hash' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - startIndex + - addresses + - nonInclusionProofs + - subtrees + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/AddressSeq' + context: + $ref: '#/components/schemas/Context' + nonInclusionProofs: + type: array + items: + $ref: '#/components/schemas/MerkleContextWithNewAddressProof' + startIndex: + type: integer + format: uint64 + minimum: 0 + subtrees: + type: array + items: + type: string + format: binary + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedAccountBalance: + summary: getCompressedAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/GetCompressedAccountProofResponseValue' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedAccountProofV2: + summary: getCompressedAccountProofV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProofV2 + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/GetCompressedAccountProofResponseValueV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedAccountV2: + summary: getCompressedAccountV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountV2 + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + dataSlice: + allOf: + - $ref: '#/components/schemas/DataSlice' + nullable: true + filters: + type: array + items: + $ref: '#/components/schemas/FilterSelector' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedAccountsByOwnerV2: + summary: getCompressedAccountsByOwnerV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwnerV2 + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + dataSlice: + allOf: + - $ref: '#/components/schemas/DataSlice' + nullable: true + filters: + type: array + items: + $ref: '#/components/schemas/FilterSelector' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountListV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedMintTokenHolders: + summary: getCompressedMintTokenHolders + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedMintTokenHolders + params: + type: object + required: + - mint + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/OwnerBalanceList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedTokenAccountsByDelegateV2: + summary: getCompressedTokenAccountsByDelegateV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegateV2 + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountListV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedTokenAccountsByOwnerV2: + summary: getCompressedTokenAccountsByOwnerV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwnerV2 + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountListV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedTokenBalancesByOwner: + summary: getCompressedTokenBalancesByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressedTokenBalancesByOwnerV2: + summary: getCompressedTokenBalancesByOwnerV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwnerV2 + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceListV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressionSignaturesForAccount: + summary: getCompressionSignaturesForAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAccount + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressionSignaturesForAddress: + summary: getCompressionSignaturesForAddress + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAddress + params: + type: object + required: + - address + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressionSignaturesForOwner: + summary: getCompressionSignaturesForOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForOwner + params: + type: object + required: + - owner + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getCompressionSignaturesForTokenOwner: + summary: getCompressionSignaturesForTokenOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForTokenOwner + params: + type: object + required: + - owner + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getIndexerHealth: + summary: getIndexerHealth + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getIndexerHealth + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: string + description: ok if healthy + default: ok + enum: + - ok + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getIndexerSlot: + summary: getIndexerSlot + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getIndexerSlot + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: integer + format: uint64 + default: 100 + example: 100 + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getLatestCompressionSignatures: + summary: getLatestCompressionSignatures + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getLatestCompressionSignatures + params: + type: object + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getLatestNonVotingSignatures: + summary: getLatestNonVotingSignatures + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getLatestNonVotingSignatures + params: + type: object + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoListWithError' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/GetCompressedAccountProofResponseValue' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getMultipleCompressedAccountProofsV2: + summary: getMultipleCompressedAccountProofsV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofsV2 + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/GetCompressedAccountProofResponseValueV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getMultipleCompressedAccountsV2: + summary: getMultipleCompressedAccountsV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountsV2 + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 11111112D1oxKts8YPdTJRG5FzxTNpMtWmq8hkVx3 + - 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 11111112D1oxKts8YPdTJRG5FzxTNpMtWmq8hkVx3 + - 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountListV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getMultipleNewAddressProofs: + summary: getMultipleNewAddressProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleNewAddressProofs + params: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleContextWithNewAddressProof' + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getMultipleNewAddressProofsV2: + summary: getMultipleNewAddressProofsV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleNewAddressProofsV2 + params: + type: array + items: + $ref: '#/components/schemas/AddressWithTree' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleContextWithNewAddressProof' + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getQueueElements: + summary: getQueueElements + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getQueueElements + params: + type: object + required: + - tree + - numElements + - queueType + properties: + numElements: + type: integer + format: uint16 + minimum: 0 + queueType: + type: integer + format: uint8 + minimum: 0 + startOffset: + type: integer + format: uint64 + nullable: true + minimum: 0 + tree: + $ref: '#/components/schemas/Hash' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - context + - value + - firstValueQueueIndex + properties: + context: + $ref: '#/components/schemas/Context' + firstValueQueueIndex: + type: integer + format: uint64 + minimum: 0 + value: + type: array + items: + $ref: '#/components/schemas/GetQueueElementsResponseValue' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getTransactionWithCompressionInfo: + summary: getTransactionWithCompressionInfo + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getTransactionWithCompressionInfo + params: + type: object + required: + - signature + properties: + signature: + $ref: '#/components/schemas/SerializableSignature' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + description: A Solana transaction with additional compression information + properties: + compression_info: + type: object + required: + - closedAccounts + - openedAccounts + properties: + closedAccounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + openedAccounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + additionalProperties: false + transaction: + type: object + description: An encoded confirmed transaction with status meta + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getTransactionWithCompressionInfoV2: + summary: getTransactionWithCompressionInfoV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getTransactionWithCompressionInfoV2 + params: + type: object + required: + - signature + properties: + signature: + $ref: '#/components/schemas/SerializableSignature' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + description: A Solana transaction with additional compression information + properties: + compression_info: + type: object + required: + - closedAccounts + - openedAccounts + properties: + closedAccounts: + type: array + items: + $ref: '#/components/schemas/ClosedAccountWithOptionalTokenDataV2' + openedAccounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenDataV2' + additionalProperties: false + transaction: + type: object + description: An encoded confirmed transaction with status meta + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getValidityProof: + summary: getValidityProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getValidityProof + params: + type: object + properties: + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + newAddressesWithTrees: + type: array + items: + $ref: '#/components/schemas/AddressWithTree' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - value + - context + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/CompressedProofWithContext' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + /getValidityProofV2: + summary: getValidityProofV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getValidityProofV2 + params: + type: object + properties: + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + newAddressesWithTrees: + type: array + items: + $ref: '#/components/schemas/AddressWithTree' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + description: An ID to identify the response. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + result: + type: object + required: + - value + - context + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/CompressedProofWithContextV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: object + properties: + code: + type: integer + message: + type: string + id: + type: string + jsonrpc: + type: string +components: + schemas: + Account: + type: object + required: + - hash + - owner + - lamports + - tree + - leafIndex + - slotCreated + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + AccountContext: + type: object + description: |- + This is currently used internally: + - Internal (state_updates,..) + - GetTransactionWithCompressionInfo (internally) + - GetTransactionWithCompressionInfoV2 (internally) + All endpoints return AccountV2. + required: + - queue + - inOutputQueue + - spent + - nullifiedInTree + - treeType + properties: + inOutputQueue: + type: boolean + nullifiedInTree: + type: boolean + nullifier: + $ref: '#/components/schemas/Hash' + nullifierQueueIndex: + $ref: '#/components/schemas/UnsignedInteger' + queue: + $ref: '#/components/schemas/SerializablePubkey' + spent: + type: boolean + treeType: + type: integer + format: uint16 + minimum: 0 + txHash: + $ref: '#/components/schemas/Hash' + additionalProperties: false + AccountData: + type: object + required: + - discriminator + - data + - dataHash + properties: + data: + $ref: '#/components/schemas/Base64String' + dataHash: + $ref: '#/components/schemas/Hash' + discriminator: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + AccountList: + type: object + required: + - items + properties: + items: + type: array + items: + allOf: + - $ref: '#/components/schemas/Account' + nullable: true + additionalProperties: false + AccountListV2: + type: object + required: + - items + properties: + items: + type: array + items: + allOf: + - $ref: '#/components/schemas/AccountV2' + nullable: true + AccountState: + type: string + enum: + - initialized + - frozen + AccountV2: + type: object + required: + - hash + - owner + - lamports + - leafIndex + - slotCreated + - proveByIndex + - merkleContext + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + merkleContext: + $ref: '#/components/schemas/MerkleContextV2' + owner: + $ref: '#/components/schemas/SerializablePubkey' + proveByIndex: + type: boolean + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + AccountWithContext: + type: object + required: + - account + - context + properties: + account: + $ref: '#/components/schemas/Account' + context: + $ref: '#/components/schemas/AccountContext' + additionalProperties: false + AccountWithOptionalTokenData: + type: object + required: + - account + properties: + account: + $ref: '#/components/schemas/Account' + optionalTokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + AccountWithOptionalTokenDataV2: + type: object + required: + - account + properties: + account: + $ref: '#/components/schemas/AccountV2' + optionalTokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + AddressListWithTrees: + type: array + items: + $ref: '#/components/schemas/AddressWithTree' + AddressSeq: + type: object + required: + - address + - seq + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + seq: + type: integer + format: uint64 + minimum: 0 + additionalProperties: false + AddressWithTree: + type: object + required: + - address + - tree + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + Base58String: + type: string + description: A base 58 encoded string. + default: 3J98t1WpEZ73CNm + example: 3J98t1WpEZ73CNm + Base64String: + type: string + description: A base 64 encoded string. + default: SGVsbG8sIFdvcmxkIQ== + example: SGVsbG8sIFdvcmxkIQ== + ClosedAccountV2: + type: object + required: + - account + - nullifier + - txHash + properties: + account: + $ref: '#/components/schemas/AccountV2' + nullifier: + $ref: '#/components/schemas/Hash' + txHash: + $ref: '#/components/schemas/Hash' + additionalProperties: false + ClosedAccountWithOptionalTokenDataV2: + type: object + required: + - account + properties: + account: + $ref: '#/components/schemas/ClosedAccountV2' + optionalTokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + CompressedProof: + type: object + required: + - a + - b + - c + properties: + a: + type: string + format: binary + b: + type: string + format: binary + c: + type: string + format: binary + CompressedProofWithContext: + type: object + required: + - compressedProof + - roots + - rootIndices + - leafIndices + - leaves + - merkleTrees + properties: + compressedProof: + $ref: '#/components/schemas/CompressedProof' + leafIndices: + type: array + items: + type: integer + format: uint32 + minimum: 0 + leaves: + type: array + items: + type: string + merkleTrees: + type: array + items: + type: string + rootIndices: + type: array + items: + type: integer + format: uint64 + minimum: 0 + roots: + type: array + items: + type: string + CompressedProofWithContextV2: + type: object + required: + - roots + - rootIndices + - leafIndices + - leaves + - merkleContexts + properties: + compressedProof: + $ref: '#/components/schemas/CompressedProof' + leafIndices: + type: array + items: + type: integer + format: uint32 + minimum: 0 + leaves: + type: array + items: + type: string + merkleContexts: + type: array + items: + $ref: '#/components/schemas/MerkleContextV2' + rootIndices: + type: array + items: + $ref: '#/components/schemas/RootIndex' + roots: + type: array + items: + type: string + CompressionInfoV2: + type: object + required: + - closedAccounts + - openedAccounts + properties: + closedAccounts: + type: array + items: + $ref: '#/components/schemas/ClosedAccountWithOptionalTokenDataV2' + openedAccounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenDataV2' + additionalProperties: false + Context: + type: object + required: + - slot + properties: + slot: + type: integer + format: uint64 + default: 100 + example: 100 + DataSlice: + type: object + required: + - offset + - length + properties: + length: + type: integer + minimum: 0 + offset: + type: integer + minimum: 0 + FilterSelector: + type: object + properties: + memcmp: + $ref: '#/components/schemas/Memcmp' + GetCompressedAccountProofResponseValue: + type: object + required: + - proof + - root + - leafIndex + - hash + - merkleTree + - rootSeq + properties: + hash: + $ref: '#/components/schemas/Hash' + leafIndex: + type: integer + format: uint32 + minimum: 0 + merkleTree: + $ref: '#/components/schemas/SerializablePubkey' + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: uint64 + minimum: 0 + additionalProperties: false + GetCompressedAccountProofResponseValueV2: + type: object + required: + - proof + - root + - leafIndex + - hash + - rootSeq + - proveByIndex + - treeContext + properties: + hash: + $ref: '#/components/schemas/Hash' + leafIndex: + type: integer + format: uint32 + minimum: 0 + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + proveByIndex: + type: boolean + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: uint64 + minimum: 0 + treeContext: + $ref: '#/components/schemas/TreeContextInfo' + additionalProperties: false + GetQueueElementsResponseValue: + type: object + required: + - proof + - root + - leafIndex + - leaf + - tree + - rootSeq + - accountHash + properties: + accountHash: + $ref: '#/components/schemas/Hash' + leaf: + $ref: '#/components/schemas/Hash' + leafIndex: + type: integer + format: uint64 + minimum: 0 + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: uint64 + minimum: 0 + tree: + $ref: '#/components/schemas/Hash' + txHash: + $ref: '#/components/schemas/Hash' + additionalProperties: false + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + Limit: + type: integer + format: uint64 + minimum: 0 + Memcmp: + type: object + required: + - offset + - bytes + properties: + bytes: + $ref: '#/components/schemas/Base58String' + offset: + type: integer + minimum: 0 + MerkleContextV2: + type: object + required: + - treeType + - tree + - queue + properties: + cpiContext: + $ref: '#/components/schemas/SerializablePubkey' + nextTreeContext: + $ref: '#/components/schemas/TreeContextInfo' + queue: + $ref: '#/components/schemas/SerializablePubkey' + tree: + $ref: '#/components/schemas/SerializablePubkey' + treeType: + type: integer + format: uint16 + minimum: 0 + MerkleContextWithNewAddressProof: + type: object + required: + - root + - address + - lowerRangeAddress + - higherRangeAddress + - nextIndex + - proof + - merkleTree + - rootSeq + - lowElementLeafIndex + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + higherRangeAddress: + $ref: '#/components/schemas/SerializablePubkey' + lowElementLeafIndex: + type: integer + format: uint32 + minimum: 0 + lowerRangeAddress: + $ref: '#/components/schemas/SerializablePubkey' + merkleTree: + $ref: '#/components/schemas/SerializablePubkey' + nextIndex: + type: integer + format: uint32 + minimum: 0 + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: uint64 + minimum: 0 + additionalProperties: false + OwnerBalance: + type: object + required: + - owner + - balance + properties: + balance: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + OwnerBalanceList: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/OwnerBalance' + OwnerBalancesResponse: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/OwnerBalanceList' + additionalProperties: false + PaginatedAccountList: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Hash' + items: + type: array + items: + $ref: '#/components/schemas/Account' + additionalProperties: false + PaginatedAccountListV2: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Hash' + items: + type: array + items: + $ref: '#/components/schemas/AccountV2' + additionalProperties: false + PaginatedSignatureInfoList: + type: object + required: + - items + properties: + cursor: + type: string + nullable: true + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfo' + RootIndex: + type: object + required: + - rootIndex + - proveByIndex + properties: + proveByIndex: + type: boolean + rootIndex: + type: integer + format: uint64 + minimum: 0 + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj + example: 111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + SignatureInfo: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + SignatureInfoList: + type: object + required: + - items + properties: + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfo' + SignatureInfoListWithError: + type: object + required: + - items + properties: + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfoWithError' + SignatureInfoWithError: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + error: + type: string + nullable: true + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + TokenAccount: + type: object + required: + - account + - tokenData + properties: + account: + $ref: '#/components/schemas/Account' + tokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + TokenAccountBalance: + type: object + required: + - amount + properties: + amount: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + TokenAccountList: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/TokenAccount' + TokenAccountListV2: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/TokenAccountV2' + TokenAccountV2: + type: object + required: + - account + - tokenData + properties: + account: + $ref: '#/components/schemas/AccountV2' + tokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + TokenBalance: + type: object + required: + - mint + - balance + properties: + balance: + $ref: '#/components/schemas/UnsignedInteger' + mint: + $ref: '#/components/schemas/SerializablePubkey' + TokenBalanceList: + type: object + required: + - token_balances + properties: + cursor: + $ref: '#/components/schemas/Base58String' + token_balances: + type: array + items: + $ref: '#/components/schemas/TokenBalance' + TokenBalanceListV2: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/TokenBalance' + TokenData: + type: object + required: + - mint + - owner + - amount + - state + properties: + amount: + $ref: '#/components/schemas/UnsignedInteger' + delegate: + $ref: '#/components/schemas/SerializablePubkey' + mint: + $ref: '#/components/schemas/SerializablePubkey' + owner: + $ref: '#/components/schemas/SerializablePubkey' + state: + $ref: '#/components/schemas/AccountState' + tlv: + $ref: '#/components/schemas/Base64String' + TreeContextInfo: + type: object + required: + - treeType + - tree + - queue + properties: + cpiContext: + $ref: '#/components/schemas/SerializablePubkey' + queue: + $ref: '#/components/schemas/SerializablePubkey' + tree: + $ref: '#/components/schemas/SerializablePubkey' + treeType: + type: integer + format: uint16 + minimum: 0 + UnixTimestamp: + type: integer + description: An Unix timestamp (seconds) + default: 1714081554 + example: 1714081554 + UnsignedInteger: + type: integer + format: uint64 + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedAccount.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccount.yaml new file mode 100644 index 0000000..5c8a72c --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccount.yaml @@ -0,0 +1,165 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Account: + type: object + required: + - hash + - owner + - lamports + - tree + - leafIndex + - seq + - slotCreated + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + AccountData: + type: object + required: + - discriminator + - data + - dataHash + properties: + data: + $ref: '#/components/schemas/Base64String' + dataHash: + $ref: '#/components/schemas/Hash' + discriminator: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + Base64String: + type: string + description: A base 64 encoded string. + default: SGVsbG8sIFdvcmxkIQ== + example: SGVsbG8sIFdvcmxkIQ== + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111112D1oxKts8YPdTJRG5FzxTNpMtWmq8hkVx3 + example: 11111112D1oxKts8YPdTJRG5FzxTNpMtWmq8hkVx3 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountBalance.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountBalance.yaml new file mode 100644 index 0000000..c81337b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountBalance.yaml @@ -0,0 +1,117 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getCompressedAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountProof.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountProof.yaml new file mode 100644 index 0000000..3fe5e36 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountProof.yaml @@ -0,0 +1,130 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + MerkleProofWithContext: + type: object + required: + - proof + - root + - leafIndex + - hash + - merkleTree + - rootSeq + properties: + hash: + $ref: '#/components/schemas/Hash' + leafIndex: + type: integer + format: int32 + minimum: 0 + merkleTree: + $ref: '#/components/schemas/SerializablePubkey' + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: int64 + minimum: 0 + additionalProperties: false + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111117353mdUKehx9GW6JNHznGt5oSZs9fWkVkB + example: 11111117353mdUKehx9GW6JNHznGt5oSZs9fWkVkB diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountsByOwner.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountsByOwner.yaml new file mode 100644 index 0000000..fed347a --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedAccountsByOwner.yaml @@ -0,0 +1,787 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + dataSlice: + allOf: + - $ref: '#/components/schemas/DataSlice' + nullable: true + filters: + type: array + items: + $ref: '#/components/schemas/FilterSelector' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Account: + type: object + required: + - hash + - owner + - lamports + - tree + - leafIndex + - seq + - slotCreated + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + AccountData: + type: object + required: + - discriminator + - data + - dataHash + properties: + data: + $ref: '#/components/schemas/Base64String' + dataHash: + $ref: '#/components/schemas/Hash' + discriminator: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + Base58String: + type: string + description: A base 58 encoded string. + default: 3J98t1WpEZ73CNm + example: 3J98t1WpEZ73CNm + Base64String: + type: string + description: A base 64 encoded string. + default: SGVsbG8sIFdvcmxkIQ== + example: SGVsbG8sIFdvcmxkIQ== + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + DataSlice: + type: object + required: + - offset + - length + properties: + length: + type: integer + minimum: 0 + offset: + type: integer + minimum: 0 + FilterSelector: + type: object + properties: + memcmp: + $ref: '#/components/schemas/Memcmp' + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + Limit: + type: integer + format: int64 + minimum: 0 + Memcmp: + type: object + required: + - offset + - bytes + properties: + bytes: + $ref: '#/components/schemas/Base58String' + offset: + type: integer + minimum: 0 + PaginatedAccountList: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Hash' + items: + type: array + items: + $ref: '#/components/schemas/Account' + additionalProperties: false + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111114d3RrygbPdAtMuFnDmzsN8T5fYKVQ7FVr7 + example: 11111114d3RrygbPdAtMuFnDmzsN8T5fYKVQ7FVr7 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedBalanceByOwner.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedBalanceByOwner.yaml new file mode 100644 index 0000000..5262bc8 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedBalanceByOwner.yaml @@ -0,0 +1,1143 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalance: + summary: getCompressedBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111113R2cuenjG5nFubqX9Wzuukdin2YfGQVzu5 + example: 11111113R2cuenjG5nFubqX9Wzuukdin2YfGQVzu5 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedMintTokenHolders.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedMintTokenHolders.yaml new file mode 100644 index 0000000..dcc1ad4 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedMintTokenHolders.yaml @@ -0,0 +1,140 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getCompressedMintTokenHolders + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedMintTokenHolders + params: + type: object + required: + - mint + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/OwnerBalanceList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Base58String: + type: string + description: A base 58 encoded string. + default: 3J98t1WpEZ73CNm + example: 3J98t1WpEZ73CNm + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + OwnerBalance: + type: object + required: + - owner + - balance + properties: + balance: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + OwnerBalanceList: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/OwnerBalance' + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 111111152P2r5yt6odmBLPsFCLBrFisJ3aS7LqLAT + example: 111111152P2r5yt6odmBLPsFCLBrFisJ3aS7LqLAT + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountBalance.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountBalance.yaml new file mode 100644 index 0000000..e7e9887 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountBalance.yaml @@ -0,0 +1,931 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj + example: 111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj + TokenAccountBalance: + type: object + required: + - amount + properties: + amount: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountsByDelegate.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountsByDelegate.yaml new file mode 100644 index 0000000..9f1e56d --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountsByDelegate.yaml @@ -0,0 +1,671 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Account: + type: object + required: + - hash + - owner + - lamports + - tree + - leafIndex + - seq + - slotCreated + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + AccountData: + type: object + required: + - discriminator + - data + - dataHash + properties: + data: + $ref: '#/components/schemas/Base64String' + dataHash: + $ref: '#/components/schemas/Hash' + discriminator: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + AccountState: + type: string + enum: + - initialized + - frozen + Base58String: + type: string + description: A base 58 encoded string. + default: 3J98t1WpEZ73CNm + example: 3J98t1WpEZ73CNm + Base64String: + type: string + description: A base 64 encoded string. + default: SGVsbG8sIFdvcmxkIQ== + example: SGVsbG8sIFdvcmxkIQ== + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + Limit: + type: integer + format: int64 + minimum: 0 + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111116EPqoQskEM2Pddp8KTL9JdYEBZMGF3aq7V + example: 11111116EPqoQskEM2Pddp8KTL9JdYEBZMGF3aq7V + TokenAcccount: + type: object + required: + - account + - tokenData + properties: + account: + $ref: '#/components/schemas/Account' + tokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + TokenAccountList: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/TokenAcccount' + TokenData: + type: object + required: + - mint + - owner + - amount + - state + properties: + amount: + $ref: '#/components/schemas/UnsignedInteger' + delegate: + $ref: '#/components/schemas/SerializablePubkey' + mint: + $ref: '#/components/schemas/SerializablePubkey' + owner: + $ref: '#/components/schemas/SerializablePubkey' + state: + $ref: '#/components/schemas/AccountState' + tlv: + $ref: '#/components/schemas/Base64String' + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountsByOwner.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountsByOwner.yaml new file mode 100644 index 0000000..a7ec38b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenAccountsByOwner.yaml @@ -0,0 +1,552 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Account: + type: object + required: + - hash + - owner + - lamports + - tree + - leafIndex + - seq + - slotCreated + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + AccountData: + type: object + required: + - discriminator + - data + - dataHash + properties: + data: + $ref: '#/components/schemas/Base64String' + dataHash: + $ref: '#/components/schemas/Hash' + discriminator: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + AccountState: + type: string + enum: + - initialized + - frozen + Base58String: + type: string + description: A base 58 encoded string. + default: 3J98t1WpEZ73CNm + example: 3J98t1WpEZ73CNm + Base64String: + type: string + description: A base 64 encoded string. + default: SGVsbG8sIFdvcmxkIQ== + example: SGVsbG8sIFdvcmxkIQ== + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + Limit: + type: integer + format: int64 + minimum: 0 + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111115q4EpJaTXAZWpCg3J2zppWGSZ46KXozzo9 + example: 11111115q4EpJaTXAZWpCg3J2zppWGSZ46KXozzo9 + TokenAcccount: + type: object + required: + - account + - tokenData + properties: + account: + $ref: '#/components/schemas/Account' + tokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + TokenAccountList: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/TokenAcccount' + TokenData: + type: object + required: + - mint + - owner + - amount + - state + properties: + amount: + $ref: '#/components/schemas/UnsignedInteger' + delegate: + $ref: '#/components/schemas/SerializablePubkey' + mint: + $ref: '#/components/schemas/SerializablePubkey' + owner: + $ref: '#/components/schemas/SerializablePubkey' + state: + $ref: '#/components/schemas/AccountState' + tlv: + $ref: '#/components/schemas/Base64String' + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenBalancesByOwner.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenBalancesByOwner.yaml new file mode 100644 index 0000000..5ea5580 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenBalancesByOwner.yaml @@ -0,0 +1,1292 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalance: + summary: getCompressedBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenBalancesByOwner: + summary: getCompressedTokenBalancesByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Base58String: + type: string + description: A base 58 encoded string. + default: 3J98t1WpEZ73CNm + example: 3J98t1WpEZ73CNm + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111113pNDtm61yGF8j2ycAwLEPsuWQXobye5qDR + example: 11111113pNDtm61yGF8j2ycAwLEPsuWQXobye5qDR + TokenBalance: + type: object + required: + - mint + - balance + properties: + balance: + $ref: '#/components/schemas/UnsignedInteger' + mint: + $ref: '#/components/schemas/SerializablePubkey' + TokenBalanceList: + type: object + required: + - token_balances + properties: + cursor: + $ref: '#/components/schemas/Base58String' + token_balances: + type: array + items: + $ref: '#/components/schemas/TokenBalance' + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenBalancesByOwnerV2.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenBalancesByOwnerV2.yaml new file mode 100644 index 0000000..71d1ddd --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressedTokenBalancesByOwnerV2.yaml @@ -0,0 +1,144 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getCompressedTokenBalancesByOwnerV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwnerV2 + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceListV2' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Base58String: + type: string + description: A base 58 encoded string. + default: 3J98t1WpEZ73CNm + example: 3J98t1WpEZ73CNm + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111114DhpssPJgSi1YU7hCMfYt1BJ334YgsffXm + example: 11111114DhpssPJgSi1YU7hCMfYt1BJ334YgsffXm + TokenBalance: + type: object + required: + - mint + - balance + properties: + balance: + $ref: '#/components/schemas/UnsignedInteger' + mint: + $ref: '#/components/schemas/SerializablePubkey' + TokenBalanceListV2: + type: object + required: + - items + properties: + cursor: + $ref: '#/components/schemas/Base58String' + items: + type: array + items: + $ref: '#/components/schemas/TokenBalance' + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForAccount.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForAccount.yaml new file mode 100644 index 0000000..e73a2d1 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForAccount.yaml @@ -0,0 +1,1515 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalance: + summary: getCompressedBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenBalancesByOwner: + summary: getCompressedTokenBalancesByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAccount: + summary: getCompressionSignaturesForAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAccount + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getTransactionWithCompressionInfo: + summary: getTransactionWithCompressionInfo + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getTransactionWithCompressionInfo + params: + type: object + required: + - signature + properties: + signature: + $ref: '#/components/schemas/SerializableSignature' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + description: A Solana transaction with additional compression information + properties: + compression_info: + type: object + required: + - closed_accounts + - opened_accounts + properties: + closed_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + opened_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + transaction: + type: object + description: An encoded confirmed transaction with status meta + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + SignatureInfo: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + SignatureInfoList: + type: object + required: + - items + properties: + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfo' + UnixTimestamp: + type: integer + description: An Unix timestamp (seconds) + default: 1714081554 + example: 1714081554 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForAddress.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForAddress.yaml new file mode 100644 index 0000000..f3f9850 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForAddress.yaml @@ -0,0 +1,1637 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalance: + summary: getCompressedBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenBalancesByOwner: + summary: getCompressedTokenBalancesByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAccount: + summary: getCompressionSignaturesForAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAccount + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAddress: + summary: getCompressionSignaturesForAddress + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAddress + params: + type: object + required: + - address + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getTransactionWithCompressionInfo: + summary: getTransactionWithCompressionInfo + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getTransactionWithCompressionInfo + params: + type: object + required: + - signature + properties: + signature: + $ref: '#/components/schemas/SerializableSignature' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + description: A Solana transaction with additional compression information + properties: + compression_info: + type: object + required: + - closed_accounts + - opened_accounts + properties: + closed_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + opened_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + transaction: + type: object + description: An encoded confirmed transaction with status meta + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + PaginatedSignatureInfoList: + type: object + required: + - items + properties: + cursor: + type: string + nullable: true + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfo' + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111119T6fgHG3unjQB6vpWozhBdiXDbQovvFVeF + example: 11111119T6fgHG3unjQB6vpWozhBdiXDbQovvFVeF + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + SignatureInfo: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + UnixTimestamp: + type: integer + description: An Unix timestamp (seconds) + default: 1714081554 + example: 1714081554 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForOwner.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForOwner.yaml new file mode 100644 index 0000000..5b18e04 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForOwner.yaml @@ -0,0 +1,1750 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalance: + summary: getCompressedBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenBalancesByOwner: + summary: getCompressedTokenBalancesByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAccount: + summary: getCompressionSignaturesForAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAccount + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAddress: + summary: getCompressionSignaturesForAddress + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAddress + params: + type: object + required: + - address + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForOwner: + summary: getCompressionSignaturesForOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForOwner + params: + type: object + required: + - owner + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getTransactionWithCompressionInfo: + summary: getTransactionWithCompressionInfo + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getTransactionWithCompressionInfo + params: + type: object + required: + - signature + properties: + signature: + $ref: '#/components/schemas/SerializableSignature' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + description: A Solana transaction with additional compression information + properties: + compression_info: + type: object + required: + - closed_accounts + - opened_accounts + properties: + closed_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + opened_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + transaction: + type: object + description: An encoded confirmed transaction with status meta + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + PaginatedSignatureInfoList: + type: object + required: + - items + properties: + cursor: + type: string + nullable: true + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfo' + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111119rSGfPZLcyCGzY4uYEL1fkzJr6fke9qKxb + example: 11111119rSGfPZLcyCGzY4uYEL1fkzJr6fke9qKxb + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + SignatureInfo: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + UnixTimestamp: + type: integer + description: An Unix timestamp (seconds) + default: 1714081554 + example: 1714081554 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForTokenOwner.yaml b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForTokenOwner.yaml new file mode 100644 index 0000000..b540792 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getCompressionSignaturesForTokenOwner.yaml @@ -0,0 +1,1863 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalance: + summary: getCompressedBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenBalancesByOwner: + summary: getCompressedTokenBalancesByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAccount: + summary: getCompressionSignaturesForAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAccount + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAddress: + summary: getCompressionSignaturesForAddress + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAddress + params: + type: object + required: + - address + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForOwner: + summary: getCompressionSignaturesForOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForOwner + params: + type: object + required: + - owner + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForTokenOwner: + summary: getCompressionSignaturesForTokenOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForTokenOwner + params: + type: object + required: + - owner + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getTransactionWithCompressionInfo: + summary: getTransactionWithCompressionInfo + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getTransactionWithCompressionInfo + params: + type: object + required: + - signature + properties: + signature: + $ref: '#/components/schemas/SerializableSignature' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + description: A Solana transaction with additional compression information + properties: + compression_info: + type: object + required: + - closed_accounts + - opened_accounts + properties: + closed_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + opened_accounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + transaction: + type: object + description: An encoded confirmed transaction with status meta + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + PaginatedSignatureInfoList: + type: object + required: + - items + properties: + cursor: + type: string + nullable: true + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfo' + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 1111111AFmseVrdL9f9oyCzZefL9tG6UbvhMPRAGw + example: 1111111AFmseVrdL9f9oyCzZefL9tG6UbvhMPRAGw + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + SignatureInfo: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + UnixTimestamp: + type: integer + description: An Unix timestamp (seconds) + default: 1714081554 + example: 1714081554 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getIndexerHealth.yaml b/zk-compression-docs/mintlify-docs/openapi/getIndexerHealth.yaml new file mode 100644 index 0000000..d40866c --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getIndexerHealth.yaml @@ -0,0 +1,69 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getIndexerHealth + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getIndexerHealth + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: string + description: ok if healthy + default: ok + enum: + - ok + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: {} diff --git a/zk-compression-docs/mintlify-docs/openapi/getIndexerSlot.yaml b/zk-compression-docs/mintlify-docs/openapi/getIndexerSlot.yaml new file mode 100644 index 0000000..29edaa6 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getIndexerSlot.yaml @@ -0,0 +1,67 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getIndexerSlot + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getIndexerSlot + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: integer + default: 100 + example: 100 + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: {} diff --git a/zk-compression-docs/mintlify-docs/openapi/getLatestCompressionSignatures.yaml b/zk-compression-docs/mintlify-docs/openapi/getLatestCompressionSignatures.yaml new file mode 100644 index 0000000..902f34b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getLatestCompressionSignatures.yaml @@ -0,0 +1,139 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getLatestCompressionSignatures + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getLatestCompressionSignatures + params: + type: object + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedSignatureInfoList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + PaginatedSignatureInfoList: + type: object + required: + - items + properties: + cursor: + type: string + nullable: true + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfo' + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + SignatureInfo: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + UnixTimestamp: + type: integer + description: An Unix timestamp (seconds) + default: 1714081554 + example: 1714081554 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getLatestNonVotingSignatures.yaml b/zk-compression-docs/mintlify-docs/openapi/getLatestNonVotingSignatures.yaml new file mode 100644 index 0000000..004c673 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getLatestNonVotingSignatures.yaml @@ -0,0 +1,139 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getLatestNonVotingSignatures + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getLatestNonVotingSignatures + params: + type: object + properties: + cursor: + type: string + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoListWithError' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Limit: + type: integer + format: int64 + minimum: 0 + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + SignatureInfoListWithError: + type: object + required: + - items + properties: + items: + type: array + items: + $ref: '#/components/schemas/SignatureInfoWithError' + SignatureInfoWithError: + type: object + required: + - signature + - slot + - blockTime + properties: + blockTime: + $ref: '#/components/schemas/UnixTimestamp' + error: + type: string + nullable: true + signature: + $ref: '#/components/schemas/SerializableSignature' + slot: + $ref: '#/components/schemas/UnsignedInteger' + UnixTimestamp: + type: integer + description: An Unix timestamp (seconds) + default: 1714081554 + example: 1714081554 + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getMultipleCompressedAccountProofs.yaml b/zk-compression-docs/mintlify-docs/openapi/getMultipleCompressedAccountProofs.yaml new file mode 100644 index 0000000..c520f8f --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getMultipleCompressedAccountProofs.yaml @@ -0,0 +1,129 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + MerkleProofWithContext: + type: object + required: + - proof + - root + - leafIndex + - hash + - merkleTree + - rootSeq + properties: + hash: + $ref: '#/components/schemas/Hash' + leafIndex: + type: integer + format: int32 + minimum: 0 + merkleTree: + $ref: '#/components/schemas/SerializablePubkey' + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: int64 + minimum: 0 + additionalProperties: false + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111117SQekjmcMtR25wEPPiL6m1Mb5586NkLL4X + example: 11111117SQekjmcMtR25wEPPiL6m1Mb5586NkLL4X diff --git a/zk-compression-docs/mintlify-docs/openapi/getMultipleCompressedAccounts.yaml b/zk-compression-docs/mintlify-docs/openapi/getMultipleCompressedAccounts.yaml new file mode 100644 index 0000000..de54f52 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getMultipleCompressedAccounts.yaml @@ -0,0 +1,866 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Account: + type: object + required: + - hash + - owner + - lamports + - tree + - leafIndex + - seq + - slotCreated + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + AccountData: + type: object + required: + - discriminator + - data + - dataHash + properties: + data: + $ref: '#/components/schemas/Base64String' + dataHash: + $ref: '#/components/schemas/Hash' + discriminator: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + AccountList: + type: object + required: + - items + properties: + items: + type: array + items: + allOf: + - $ref: '#/components/schemas/Account' + nullable: true + additionalProperties: false + Base64String: + type: string + description: A base 64 encoded string. + default: SGVsbG8sIFdvcmxkIQ== + example: SGVsbG8sIFdvcmxkIQ== + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111115RidqCHAoz6dzmXxGcfWLNzevYqNpaRAUo + example: 11111115RidqCHAoz6dzmXxGcfWLNzevYqNpaRAUo + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getMultipleNewAddressProofs.yaml b/zk-compression-docs/mintlify-docs/openapi/getMultipleNewAddressProofs.yaml new file mode 100644 index 0000000..95efb88 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getMultipleNewAddressProofs.yaml @@ -0,0 +1,139 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getMultipleNewAddressProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleNewAddressProofs + params: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleContextWithNewAddressProof' + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + MerkleContextWithNewAddressProof: + type: object + required: + - root + - address + - lowerRangeAddress + - higherRangeAddress + - nextIndex + - proof + - merkleTree + - rootSeq + - lowElementLeafIndex + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + higherRangeAddress: + $ref: '#/components/schemas/SerializablePubkey' + lowElementLeafIndex: + type: integer + format: int32 + minimum: 0 + lowerRangeAddress: + $ref: '#/components/schemas/SerializablePubkey' + merkleTree: + $ref: '#/components/schemas/SerializablePubkey' + nextIndex: + type: integer + format: int32 + minimum: 0 + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: int64 + minimum: 0 + additionalProperties: false + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111117qkFjr4u54stuNNUR8fRF8dNhaP35yvANs + example: 11111117qkFjr4u54stuNNUR8fRF8dNhaP35yvANs diff --git a/zk-compression-docs/mintlify-docs/openapi/getMultipleNewAddressProofsV2.yaml b/zk-compression-docs/mintlify-docs/openapi/getMultipleNewAddressProofsV2.yaml new file mode 100644 index 0000000..399efde --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getMultipleNewAddressProofsV2.yaml @@ -0,0 +1,150 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getMultipleNewAddressProofsV2 + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleNewAddressProofsV2 + params: + type: array + items: + $ref: '#/components/schemas/AddressWithTree' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleContextWithNewAddressProof' + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + AddressWithTree: + type: object + required: + - address + - tree + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + MerkleContextWithNewAddressProof: + type: object + required: + - root + - address + - lowerRangeAddress + - higherRangeAddress + - nextIndex + - proof + - merkleTree + - rootSeq + - lowElementLeafIndex + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + higherRangeAddress: + $ref: '#/components/schemas/SerializablePubkey' + lowElementLeafIndex: + type: integer + format: int32 + minimum: 0 + lowerRangeAddress: + $ref: '#/components/schemas/SerializablePubkey' + merkleTree: + $ref: '#/components/schemas/SerializablePubkey' + nextIndex: + type: integer + format: int32 + minimum: 0 + proof: + type: array + items: + $ref: '#/components/schemas/Hash' + root: + $ref: '#/components/schemas/Hash' + rootSeq: + type: integer + format: int64 + minimum: 0 + additionalProperties: false + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111118F5rixNBnFLmioWZSYzjjFuAL5dyoDVzhD + example: 11111118F5rixNBnFLmioWZSYzjjFuAL5dyoDVzhD diff --git a/zk-compression-docs/mintlify-docs/openapi/getQueueElements.yaml b/zk-compression-docs/mintlify-docs/openapi/getQueueElements.yaml new file mode 100644 index 0000000..bfe4aa0 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getQueueElements.yaml @@ -0,0 +1,89 @@ +paths: + /: + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getQueueElements + params: + type: object + required: + - queue + - batch + - startOffset + - endOffset + properties: + queue: + $ref: '#/components/schemas/Hash' + batch: + $ref: '#/components/schemas/UnsignedInteger' + startOffset: + $ref: '#/components/schemas/UnsignedInteger' + endOffset: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/Hash' + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Hash: + type: string + description: A base58 encoded hash. + default: "11111111111111111111111111111111" + example: "11111111111111111111111111111111" \ No newline at end of file diff --git a/zk-compression-docs/mintlify-docs/openapi/getTransactionWithCompressionInfo.yaml b/zk-compression-docs/mintlify-docs/openapi/getTransactionWithCompressionInfo.yaml new file mode 100644 index 0000000..a7e00ab --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getTransactionWithCompressionInfo.yaml @@ -0,0 +1,1569 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /getCompressedAccount: + summary: getCompressedAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccount + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/Account' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountProof: + summary: getCompressedAccountProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountProof + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedAccountsByOwner: + summary: getCompressedAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/PaginatedAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalance: + summary: getCompressedBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedBalanceByOwner: + summary: getCompressedBalanceByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedBalanceByOwner + params: + type: object + required: + - owner + properties: + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/UnsignedInteger' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountBalance: + summary: getCompressedTokenAccountBalance + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountBalance + params: + type: object + description: Request for compressed account data + default: + address: null + hash: '11111111111111111111111111111111' + properties: + address: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hash: + allOf: + - $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + address: null + hash: '11111111111111111111111111111111' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountBalance' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByDelegate: + summary: getCompressedTokenAccountsByDelegate + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByDelegate + params: + type: object + required: + - delegate + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + delegate: + $ref: '#/components/schemas/SerializablePubkey' + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenAccountsByOwner: + summary: getCompressedTokenAccountsByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenAccountsByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenAccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressedTokenBalancesByOwner: + summary: getCompressedTokenBalancesByOwner + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressedTokenBalancesByOwner + params: + type: object + required: + - owner + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Base58String' + nullable: true + limit: + allOf: + - $ref: '#/components/schemas/Limit' + nullable: true + mint: + allOf: + - $ref: '#/components/schemas/SerializablePubkey' + nullable: true + owner: + $ref: '#/components/schemas/SerializablePubkey' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/TokenBalanceList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getCompressionSignaturesForAccount: + summary: getCompressionSignaturesForAccount + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getCompressionSignaturesForAccount + params: + type: object + required: + - hash + properties: + hash: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/SignatureInfoList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccountProofs: + summary: getMultipleCompressedAccountProofs + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccountProofs + params: + type: array + items: + $ref: '#/components/schemas/Hash' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + type: array + items: + $ref: '#/components/schemas/MerkleProofWithContext' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getMultipleCompressedAccounts: + summary: getMultipleCompressedAccounts + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getMultipleCompressedAccounts + params: + type: object + description: Request for compressed account data + default: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + properties: + addresses: + type: array + items: + $ref: '#/components/schemas/SerializablePubkey' + nullable: true + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + nullable: true + additionalProperties: false + example: + addresses: null + hashes: + - 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM + - 1111111ogCyDbaRMvkdsHB3qfdyFYaG1WtRUAfdh + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - context + - value + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/AccountList' + '400': + description: Invalid request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '401': + description: Unauthorized request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: Request was forbidden. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The specified resource was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string + /getTransactionWithCompressionInfo: + summary: getTransactionWithCompressionInfo + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getTransactionWithCompressionInfo + params: + type: object + required: + - signature + properties: + signature: + $ref: '#/components/schemas/SerializableSignature' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + description: A Solana transaction with additional compression information + properties: + compression_info: + type: object + required: + - closedAccounts + - openedAccounts + properties: + closedAccounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + openedAccounts: + type: array + items: + $ref: '#/components/schemas/AccountWithOptionalTokenData' + additionalProperties: false + transaction: + type: object + description: An encoded confirmed transaction with status meta + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + Account: + type: object + required: + - hash + - owner + - lamports + - tree + - leafIndex + - seq + - slotCreated + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + data: + $ref: '#/components/schemas/AccountData' + hash: + $ref: '#/components/schemas/Hash' + lamports: + $ref: '#/components/schemas/UnsignedInteger' + leafIndex: + $ref: '#/components/schemas/UnsignedInteger' + owner: + $ref: '#/components/schemas/SerializablePubkey' + seq: + $ref: '#/components/schemas/UnsignedInteger' + slotCreated: + $ref: '#/components/schemas/UnsignedInteger' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + AccountData: + type: object + required: + - discriminator + - data + - dataHash + properties: + data: + $ref: '#/components/schemas/Base64String' + dataHash: + $ref: '#/components/schemas/Hash' + discriminator: + $ref: '#/components/schemas/UnsignedInteger' + additionalProperties: false + AccountState: + type: string + enum: + - initialized + - frozen + AccountWithOptionalTokenData: + type: object + required: + - account + properties: + account: + $ref: '#/components/schemas/Account' + optionalTokenData: + $ref: '#/components/schemas/TokenData' + additionalProperties: false + Base64String: + type: string + description: A base 64 encoded string. + default: SGVsbG8sIFdvcmxkIQ== + example: SGVsbG8sIFdvcmxkIQ== + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111116djSnXB2wXVGT4xDLsfTnkp1p4cCxHAfRq + example: 11111116djSnXB2wXVGT4xDLsfTnkp1p4cCxHAfRq + SerializableSignature: + type: string + description: A Solana transaction signature. + default: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + example: 5J8H5sTvEhnGcB4R8K1n7mfoiWUD9RzPVGES7e3WxC7c + TokenData: + type: object + required: + - mint + - owner + - amount + - state + properties: + amount: + $ref: '#/components/schemas/UnsignedInteger' + delegate: + $ref: '#/components/schemas/SerializablePubkey' + mint: + $ref: '#/components/schemas/SerializablePubkey' + owner: + $ref: '#/components/schemas/SerializablePubkey' + state: + $ref: '#/components/schemas/AccountState' + tlv: + $ref: '#/components/schemas/Base64String' + UnsignedInteger: + type: integer + default: 100 + example: 100 diff --git a/zk-compression-docs/mintlify-docs/openapi/getValidityProof.yaml b/zk-compression-docs/mintlify-docs/openapi/getValidityProof.yaml new file mode 100644 index 0000000..d2abd4e --- /dev/null +++ b/zk-compression-docs/mintlify-docs/openapi/getValidityProof.yaml @@ -0,0 +1,169 @@ +openapi: 3.0.3 +info: + title: photon-indexer + description: Solana indexer for general compression + license: + name: Apache-2.0 + version: 0.50.0 +servers: +- url: https://mainnet.helius-rpc.com?api-key= +paths: + /: + summary: getValidityProof + post: + requestBody: + content: + application/json: + schema: + type: object + required: + - jsonrpc + - id + - method + - params + properties: + id: + type: string + description: An ID to identify the request. + enum: + - test-account + jsonrpc: + type: string + description: The version of the JSON-RPC protocol. + enum: + - '2.0' + method: + type: string + description: The name of the method to invoke. + enum: + - getValidityProof + params: + type: object + properties: + hashes: + type: array + items: + $ref: '#/components/schemas/Hash' + newAddressesWithTrees: + type: array + items: + $ref: '#/components/schemas/AddressWithTree' + additionalProperties: false + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + required: + - value + - context + properties: + context: + $ref: '#/components/schemas/Context' + value: + $ref: '#/components/schemas/CompressedProofWithContext' + additionalProperties: false + '429': + description: Exceeded rate limit. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + description: The server encountered an unexpected condition that prevented it from fulfilling the request. + content: + application/json: + schema: + type: object + properties: + error: + type: string +components: + schemas: + AddressWithTree: + type: object + required: + - address + - tree + properties: + address: + $ref: '#/components/schemas/SerializablePubkey' + tree: + $ref: '#/components/schemas/SerializablePubkey' + additionalProperties: false + CompressedProof: + type: object + required: + - a + - b + - c + properties: + a: + type: string + format: binary + b: + type: string + format: binary + c: + type: string + format: binary + CompressedProofWithContext: + type: object + required: + - compressedProof + - roots + - rootIndices + - leafIndices + - leaves + - merkleTrees + properties: + compressedProof: + $ref: '#/components/schemas/CompressedProof' + leafIndices: + type: array + items: + type: integer + format: int32 + minimum: 0 + leaves: + type: array + items: + type: string + merkleTrees: + type: array + items: + type: string + rootIndices: + type: array + items: + type: integer + format: int64 + minimum: 0 + roots: + type: array + items: + type: string + Context: + type: object + required: + - slot + properties: + slot: + type: integer + default: 100 + example: 100 + Hash: + type: string + description: A 32-byte hash represented as a base58 string. + example: 11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP + SerializablePubkey: + type: string + description: A Solana public key represented as a base58 string. + default: 11111118eRTi4fUVRoeYEeeTyL4DPAwxatvWT5q1Z + example: 11111118eRTi4fUVRoeYEeeTyL4DPAwxatvWT5q1Z diff --git a/zk-compression-docs/mintlify-docs/quickstart.mdx b/zk-compression-docs/mintlify-docs/quickstart.mdx new file mode 100644 index 0000000..49f189f --- /dev/null +++ b/zk-compression-docs/mintlify-docs/quickstart.mdx @@ -0,0 +1,186 @@ +--- +title: Quick Start +description: Create your first compressed token in minutes. +icon: bolt +--- + + +With this guide you will mint compressed tokens in under 5 minutes. + + +Compressed tokens are SPL compatible and supported by leading wallets such as Phantom or Backpack. + + +## Install Dependencies + + + +```bash +npm install --save-dev typescript tsx @types/node && +npm install \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + + + +```bash +yarn add --dev typescript tsx @types/node && +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + + + +```bash +pnpm add --save-dev typescript tsx @types/node && +pnpm add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @solana/spl-token +``` + + + +## Create an RPC connection + +Run `test-connection.ts` to verify your setup: + + +Replace `` with your actual API key before running! Get one [here](https://www.helius.dev/zk-compression), if you don't have one yet. + + +```typescript test-connection.ts +import { createRpc } from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key=<api_key>"; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +console.log("Connection created"); +console.log("RPC Endpoint:", RPC_ENDPOINT); +``` + + +## Create and Mint Compressed Tokens + + + + + +Install Solana + +```bash +sh -c "$(curl -sSfL https://release.anza.xyz/v3.0.0/install)" +``` + + +Then run the command below to create a keypair at `.config/solana/id.json` + +```bash +solana-keygen new +``` + + +Fund wallet with devnet SOL + +```bash +# Check current balance +solana balance --url devnet + +# Airdrop 1 SOL to your default wallet +solana airdrop 1 --url devnet + +# or use https://faucet.solana.com/ +``` + + + + + +Run `quickstart.ts` with the following code: + +```typescript quickstart.ts highlight={17, 25-30, 37-45 } expandable +// ZK Compression Quickstart - DevNet +// 1. Load wallet and connect to DevNet via Helius RPC +// 2. Create SPL mint with token pool for compression via createMint() +// 3. Mint compressed tokens to recipient account via mintTo() +// 4. Verify compressed token balance via getCompressedTokenAccountsByOwner + +import { createRpc } from "@lightprotocol/stateless.js"; +import { createMint, mintTo } from "@lightprotocol/compressed-token"; +import { Keypair } from "@solana/web3.js"; +import { readFileSync } from "fs"; +import { homedir } from "os"; + +// Step 1: Load wallet from filesystem +const payer = Keypair.fromSecretKey(new Uint8Array(JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")))); + +// Helius exposes Solana and compression RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const connection = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); + +const main = async () => { + + try { + // Step 2: Create SPL mint with token pool for compression + console.log("\nCreating SPL mint with token pool for compression"); + const { mint, transactionSignature } = await createMint( + connection, + payer, + payer.publicKey, // mintAuthority + 9 + ); + + console.log(`Mint address: ${mint.toBase58()}`); + console.log(`Create mint transaction: https://explorer.solana.com/tx/${transactionSignature}?cluster=devnet`); + + // Step 3: Mint compressed tokens to recipient account + console.log("\nMinting compressed token..."); + const mintAmount = 1000000000; // mintAmount with decimals + const mintToTxId = await mintTo( + connection, + payer, + mint, // SPL mint with token pool for compression + payer.publicKey, // recipient.publicKey + payer, // mintAuthority + mintAmount + ); + + console.log(`Compressed Token minted ${mintAmount / 1e9} token`); + console.log(`Transaction: https://explorer.solana.com/tx/${mintToTxId}?cluster=devnet`); + + // Step 4: Verify compressed token balance via getCompressedTokenAccountsByOwner + const tokenAccounts = await connection.getCompressedTokenAccountsByOwner( + payer.publicKey, + { mint } // SPL mint with token pool for compression + ); + + } catch (error: any) { + console.error("Error:", error.message); + } +}; + +main().catch(console.error); +``` + +## That's it! + +You've created and minted compressed tokens. The output shows: + +* Mint address +* Create mint transaction link +* Minted token amount +* Mint transaction link +* Compressed token balance + + +## Next Steps + +Get an overview of compressed tokens or build a program with compressed accounts. diff --git a/zk-compression-docs/mintlify-docs/references/node-operators.mdx b/zk-compression-docs/mintlify-docs/references/node-operators.mdx new file mode 100644 index 0000000..4e70e3b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/references/node-operators.mdx @@ -0,0 +1,43 @@ +--- +title: "Node Operators" +description: "Learn how to run ZK Compression infrastructure, such as Forester nodes, Photon indexers and Prover nodes." +--- + + +Developers don't need to run any nodes to use ZK Compression. + + +To connect to public networks (i.e., Devnet, Mainnet-Beta), you can either work with an RPC infrastructure provider that supports ZK Compression, such as [Helius Labs](https://helius.xyz/), or run your own nodes. + + +There are three different types of nodes: + +- Photon RPC nodes +- Prover nodes +- Light forester nodes + + +#### Photon Indexer Node + +Indexer nodes use an existing connection to a Solana RPC full node to parse the transactions involving Light Protocol programs, enabling clients to read and write zk-compressed state. + +The canonical ZK Compression indexer is named Photon and is maintained by Helius Labs. It is fully open-source, and can be run locally. To set it up, simply point it to an existing Solana RPC. See the [Github repo](https://github.com/helius-labs/photon) for more info. + + +#### Prover Node + +Provers generate validity proofs for state inclusion and PDA uniqueness on behalf of app developers + +**Prover nodes** can be operated either standalone or with an RPC node: in its default configuration, the Photon RPC node implementation by [Helius Labs](https://github.com/helius-labs/photon) bundles a Prover node. The ZK Compression RPC API specification supports proof generation via the `getValidityProof` endpoint, making it easy to serve proofs using regular RPC methods via the same port. + +Please refer to the [Github repo](https://github.com/Lightprotocol/light-protocol/tree/main/light-prover) for more info: + + + + +#### Forester Node + +These nodes manage the creation, rollover, and updating of shared and program-owned state trees. Running a forester node is permissionless for your own state trees. + + + diff --git a/zk-compression-docs/mintlify-docs/references/security.mdx b/zk-compression-docs/mintlify-docs/references/security.mdx new file mode 100644 index 0000000..8b5d13a --- /dev/null +++ b/zk-compression-docs/mintlify-docs/references/security.mdx @@ -0,0 +1,30 @@ +--- +title: "Security" +description: "Overview to Light Protocol's bug bounty program, third party security audits, and formal verification of circuits." +--- + +### Bug Bounty + +Light Protocol is hosting a [bug bounty program](https://immunefi.com/bug-bounty/light-protocol/information/). + +### Security Audits + +The Light protocol on-chain programs were audited by independent security firms Neodyme, OtterSec, Accretion, and Zellic. + +- [Accretion audit report](https://github.com/Lightprotocol/light-protocol/blob/main/audits/accretion_v1_update_audit.pdf) (January '25) +- [Zellic audit report](https://github.com/Lightprotocol/light-protocol/blob/main/audits/zellic_v1_audit.pdf) (September '24) +- [Neodyme audit report](https://github.com/Lightprotocol/light-protocol/blob/main/audits/neodyme_v1_audit.pdf) (August '24) +- [OtterSec audit report](https://github.com/Lightprotocol/light-protocol/blob/main/audits/ottersec_v1_audit.pdf) (July '24) + +A complete list of 3rd party audits can be found [here](https://github.com/Lightprotocol/light-protocol/tree/main/audits). + +### Groth16 Circuit Security + +The ZK Compression circuit was formally verified by Reilabs. See the report [here](https://github.com/Lightprotocol/light-protocol/blob/main/audits/reilabs_circuits_formal_verification_report.pdf). + +Information about the Trusted Setup Ceremony for the groth16 circuits is [here](https://github.com/Lightprotocol/gnark-mt-setup/blob/main/README.md). + + +**For additional information on Light Protocol's security policy, read** [**here**](https://github.com/Lightprotocol/light-protocol/blob/main/SECURITY.md)**.** + + diff --git a/zk-compression-docs/mintlify-docs/references/terminology.mdx b/zk-compression-docs/mintlify-docs/references/terminology.mdx new file mode 100644 index 0000000..bf33768 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/references/terminology.mdx @@ -0,0 +1,411 @@ +--- +title: "Terminology" +description: "Overview to terminology related to ZK Compression and Solana" +--- + +## Account + +An entry in the Solana ledger that holds data or executable program code, stored on chain. + +There are different kinds of accounts, including + +- Data Accounts: Store arbitrary data used by programs. +- SPL Token Accounts: Manage token balances (similar to ERC-20 tokens on Ethereum). +- Program Accounts: Contain the executable code of a Solana program. + + +## Account Compression Program + +Light Protocol's program that implements state and address trees for ZK Compression. The program provides the underlying Merkle tree infrastructure used by the Light System Program to manage compressed account state transitions. + + **Source**: https://github.com/Lightprotocol/light-protocol/tree/main/programs/account-compression + + +## Account hash + +A 32-byte identifier uniquely representing a compressed account's state and position within a state tree. + + +## Account derivation + +A process to create deterministic addresses for compressed PDAs by hashing program IDs and seed values. + + +## Address tree + +A Merkle tree that stores derived addresses that serves as optional, persistent identifiers for compressed accounts. These addresses serve as persistent identifiers that don't change when account data updates. + +Address trees are separate from state trees. Unlike state trees that store account hashes, address trees store actual address values in an indexed structure with pointers to maintain sorted order. + +Two address tree versions are currently supported: + +- **V1 address trees**: Height 26 (~67 million addresses) +- **V2 batched address trees**: Height 40 (~1 trillion addresses), optimizing compute unit consumption by up to 70%. V2 is currently on Devnet. + + +## [Client](https://solana.com/docs/core/transactions#client) + +A computer program that accesses the Solana server network [cluster](https://solana.com/docs/core/transactions#cluster). + + +## [**Cluster**](https://solana.com/docs/references/terminology#cluster) + +A set of [validators](https://solana.com/docs/references/terminology#validator) maintaining a single [ledger](https://solana.com/docs/references/terminology#ledger). + + +## Compressed PDA + +Compressed accounts at Program Derived Addresses. + + +## Compressed account + +A data structure that holds arbitrary data, represented as a 32-byte hash stored in a leaf of a state Merkle tree. Compressed accounts do not require a rent exempt balance upon creation. + + +## Token mint + +An SPL token mint uniquely represents a token on the Solana network and stores global metadata about the token, including `mint_authority`, `supply`, and `decimals`. + +SPL tokens can be compressed if the mint has a token pool account set up. Anyone can create a token pool PDA for any given SPL mint. + + +## Token Pool Account + +SPL token account that holds SPL tokens corresponding to compressed tokens in circulation. Tokens are deposited during compression and withdrawn during decompression, owned by the compressed token program's CPI authority PDA. + + +## Concurrency + +The ability to process multiple Merkle tree update requests simultaneously without invalidating each other, as long as they don't modify the same leaf. + +Concurrency in ZK Compression allows parallel operations on different tree leaves without requiring locks. + + +## Compressed Token + +An SPL token in compressed form. Compressed tokens do not require an associated token account per holder. + + +## Compressed Token account + +An account type in the Compressed Token Program to store information about an individual's ownership of a specific token (mint). Compressed token accounts do not require a rent exempt balance upon creation. + + +## Compressed Token Program + +Light Protocol's SPL-compatible token program that enables compression and decompression of token accounts. The program enforces SPL token layout standards and allows for arbitrary transitions between compressed and regular format. + + +## [**Compute units**](https://solana.com/docs/references/terminology#compute-units) + +The smallest unit of measure for consumption of computational resources of the transactions on the Solana blockchain. + + +## [**Compute unit budget**](https://solana.com/docs/references/terminology#compute-budget) + +The maximum number of [compute units](https://solana.com/docs/references/terminology#compute-units) consumed per transaction. + +Developers set the compute unit budget via the`ComputeBudget`instruction, by default 200,000 CU, with a maximum of 1,400,000 CU. + +If the transaction exceeds its compute unit limit, it fails and no changes occur. + + +## Compute unit limits per block + +The total amount of compute units that all transactions in a single Solana block - the _blockspace_ - can collectively consume is currently set at 48 million CU. + +The maximum compute units that can be used to modify a single account within a block - the _write lock limit -_ is currently set at 12 million CU. + + +## [Cross-program invocation (CPI)](https://solana.com/docs/core/transactions#cross-program-invocation-cpi) + +A call from one [program](https://solana.com/docs/core/transactions#onchain-program) to another. + + For more information, see [calling between programs](https://solana.com/docs/core/cpi). + + +## Decompression + +The process of converting a compressed to a regular Solana account. SPL tokens are withdrawn from the token pool to an Associated Token Account and compressed token accounts are invalidated. + + +## Forester node / Forester + +A keeper node to incorporate state updates into state Merkle Trees for ZK Compression. + + +## Groth16 + +A zero-knowledge SNARK that produces constant-size proofs using bilinear pairings on elliptic curves. + +ZK Compression uses Groth16 to generate 128 byte validity proofs to verify compressed account state transitions against the on-chain root. + + +## [**Hash**](https://solana.com/docs/references/terminology#hash) + +A hash is a digital fingerprint of a sequence of bytes representing arbitrary data, while requiring far less storage space than the original data. + + +## Indexer + +A service that tracks state changes of compressed accounts on the Solana ledger and provides RPC APIs for querying compressed accounts and generating validity proofs. + +The ZK Compression indexer is named Photon and is maintained by Helius Labs. + +**Source**: https://github.com/helius-labs/photon + + +## [**Instruction**](https://solana.com/docs/references/terminology#instruction) + +A call to invoke a specific [instruction handler](https://solana.com/docs/references/terminology#instruction-handler) in a [program](https://solana.com/docs/references/terminology#program). + +An instruction also specifies which accounts it wants to read or modify, and additional data that serves as auxiliary input to the [instruction handler](https://solana.com/docs/references/terminology#instruction-handler). A [client](https://solana.com/docs/references/terminology#client) must include at least one instruction in a [transaction](https://solana.com/docs/references/terminology#transaction), and all instructions must complete for the transaction to be considered successful. + +For example, compressed accounts are created or updated with the `InvokeCpiInstruction` to the Light System Program. + + +## Leaf index + +The numerical position (u32) of a compressed account within a state tree, used for Merkle proof generation. + + +## Light System Program + +ZK Compression's core program that validates compressed account state transitions by verifying validity proofs and managing compressed state changes. + +The program enforces compressed account layout with ownership and sum checks, and is invoked to create and write to compressed accounts and PDAs. + +**Source**: https://github.com/Lightprotocol/light-protocol/tree/main/programs/system + + +## **Ledger** + +The ledger is an immutable historical record of all Solana transactions signed by clients since the genesis block. + +A helpful analogy to differentiate Solana ledger and state: + +- Ledger is the entire bank statement history. +- State is the current account balance, derived from all transactions in the bank statement history. + + +## Merkle tree + +A tree data structure to allow for cryptographic verification of the integrity of all leaves in a tree. + +Each leaf on a Merkle tree is a hash of that leaf's data. A Merkle tree compresses data by hashing pairs of data repeatedly into a single root hash, starting from the lowest level. Only this root hash is stored on chain. On Solana, this process is called state compression. + + +## Merkle tree account + +The public key of the on-chain Merkle tree account used in ZK Compression. This identifier references the state tree that stores compressed account hashes. + + +## Merkle proof + +A cryptographic proof consisting of sibling node hashes required to verify that a specific leaf exists within a Merkle tree and calculate the root hash. + +ZK Compression encodes Merkle proofs into zero-knowledge proofs (validity proofs). These verify compressed account operations with a constant 128-byte size without exposing the underlying variable-size Merkle proof data. + + +## Nullification + +The process of marking compressed accounts as spent to prevent double-spending. + +When compressed accounts are used as inputs in transactions, their previous states are invalidated by inserting their hashes into nullifier queues. Forester nodes process these queues to permanently update the corresponding Merkle tree leaves, ensuring each compressed account state can only be used once. + + +## Nullifier queue + +A queue where compressed accounts hashes used as input for transactions are temporarily stored to prevent double spending. A Forester node empties the queue by inserting queue elements into a state Merkle tree. + + +## [**Program**](https://solana.com/docs/references/terminology#onchain-program) + +Programs run executable code similar to smart contracts on other blockchains with optimizations specific to Solana. + +Solana programs key characteristics include: + +- Solana programs are stateless and do not store state internally. Separate accounts store state for programs to execute on, such as program, user or token data. This makes Solana's account model [different from Ethereum's](https://solana.com/news/evm-to-svm). +- Programs are typically written in Rust. +- Programs interpret the [instructions](https://solana.com/docs/references/terminology#instruction) sent inside of each [transaction](https://solana.com/docs/references/terminology#transaction) to read and modify accounts over which it has control, hence update state. + + +## Parallelism + +The ability of the SVM to execute multiple transactions simultaneously, as long as they modify different regular and/or compressed accounts. + + +## [**Program derived addresses (PDA)**](https://solana.com/docs/references/terminology#program-derived-account-pda) + +PDAs are special account addresses derived deterministically using optional seeds, a bump seed, and a program ID. + +They are off the Ed25519 curve, meaning they have no private key. The PDA itself, once derived, is 32 bytes, matching a regular public key. + + +## [**Prioritization fee**](https://solana.com/docs/references/terminology#prioritization-fee) + +An additional fee user can specify in the compute budget [instruction](https://solana.com/docs/references/terminology#instruction) to prioritize their [transactions](https://solana.com/docs/references/terminology#transaction). + +The priority fee is derived from the compute unit limit and the comput unit price. The price per compute unit set by the user in micro-lamports (1 lamport = 1,000,000 micro-lamports), rounded up to the nearest lamport. + + +## Poseidon hash + +A cryptographic hash function optimized for zero-knowledge proof systems that works natively with finite field arithmetic. + +The Poseidon hash is designed to minimize computational complexity in ZK circuits. ZK Compression uses Poseidon hashes to generate the account hashes stored as leaves in state trees. + + +## Proof verification + +The on-chain process of validating zero-knowledge proofs to confirm the correctness of compressed account state transitions. + + +## Rent + +A fee paid in SOL for the creation of [Accounts](https://solana.com/docs/references/terminology#account) to store data on the blockchain, tied to account size. When accounts do not have enough balance to pay rent, they may be Garbage Collected. + + +## [**Rent exempt**](https://solana.com/docs/references/terminology#rent-exempt) + +An account that maintains a minimum lamport balance proportional to the amount of data stored on the account. + +All newly created accounts are stored on chain permanently until the account is closed. It is not possible to create an account that falls below the rent exemption threshold. + +The rent exemption balance remains locked while an account is active and can be fully recovered when the account is closed. + +The minimum balance is paid by the creator and is calculated as follows: + +```markdown +Minimum Rent Balance = 2 × 0.00000348 SOL/byte/year × Account Size (Bytes) +``` + + +## Remote Procedure Calls (RPC) + +A bridge between users (or applications) and the blockchain to facilitate interactions and data retrieval. + +The [ZK Compression RPC API](https://www.zkcompression.com/developers/json-rpc-methods) extends [Solana's JSON RPC API](https://solana.com/docs/rpc) with additional endpoints to interact with compressed accounts, provided by Helius Labs. + +Find more information on [ZK Compression's JSON RPC Methods here](/resources/json-rpc-methods). + + +## [**Smart contract**](https://solana.com/docs/references/terminology#smart-contract) + +Smart contracts on Solana are called programs with key characteristics and optimizations. + + +## Solana Account Model + +The native framework to store and manage data on the Solana blockchain. + +Solana's Account Model separates program logic from state to optimize for parallel and faster transactions. Separate accounts store state for programs to execute on, such as program, user or token data. This makes Solana's Account Model [different from Ethereum's](https://solana.com/news/evm-to-svm). + +ZK Compression extends Solana's Account Model with Compressed Accounts. + + +## [**Solana Program Library (SPL)**](https://solana.com/docs/references/terminology#solana-program-library-spl) + +A [library of programs](https://spl.solana.com/) on Solana such as spl-token that facilitates tasks such as creating and using tokens. + + +## State + +A snapshot representing the current status of all accounts and programs on Solana. + +The state is derived from the ledger by sequentially applying every transaction. State is mutable and changes with every transaction to represent the latest state. + +State is kept in RAM by validators for transaction validation. + + +## State root + +The root hash of a Merkle tree that serves as a cryptographic fingerprint representing all compressed accounts in the tree. + +State roots are stored on-chain and used by the Light System Program to verify validity proofs during compressed account operations. Each state root represents the complete state of compressed accounts at a specific point in time. + + +## State tree + +A Merkle tree that stores compressed account hashes as leaf nodes. + +State trees organize compressed account data into a binary tree structure where each parent node is the hash of its two children nodes. The tree's root hash is stored on-chain as a cryptographic fingerprint representing all accounts in the tree. + +Two state tree versions with different proof mechanisms are currently supported: + +- **V1 state trees**: Always require the full 128-byte validity proof. With a depth of 26, a single V1 state tree stores approximately 67 million compressed accounts. +- **V2 batched state trees**: Support `prove_by_index` optimization that verifies account existence with one byte instead of 128 bytes, optimizing compute unit consumption by up to 70%. + +## State compression + +A process to lower the amount of data stored on chain using Merkle trees. + +The process of state compression involves the following steps + + + + + + + + + + +Learn more [on generalized state compression here](https://solana.com/developers/courses/state-compression/generalized-state-compression). + + +## Token account + +A token account is an account type in Solana's Token Programs that stores information about an individual's ownership of a specific token (mint). Each token account is associated with a single mint and tracks details like the token balance and owner. + + +## [**Token mint**](https://solana.com/docs/references/terminology#token-mint) + +A [mint account](https://solana.com/docs/tokens/basics/create-mint) is an account type in Solana's Token Programs that can produce (or 'mint') tokens. + +Different tokens are distinguished by their unique token mint addresses. Token mints uniquely represents a token on the network and stores global metadata about the token, including the `mint_authority`, supply, and decimals. + + +## [**Transaction**](https://solana.com/docs/references/terminology#transaction) + +One or more [instructions](https://solana.com/docs/references/terminology#instruction) signed by a [client](https://solana.com/docs/references/terminology#client) using one or more [keypairs](https://solana.com/docs/references/terminology#keypair) and executed atomically with only two possible outcomes: success or failure. + + +## Validity proof + +A zero-knowledge proof of compressed state included in a transaction to read or write compressed accounts. + +Developers don't need to generate _validity proofs_. + +The _validity proof_ is + +- constant 128 byte in size (other than Merkle proofs with varying proof size), fitting well in Solana's 1232 byte transaction limit +- verified against the respective on chain fingerprint to ensure the provided data was previously emitted +- provided and generated by indexers that support the [ZK Compression RPC API](https://www.zkcompression.com/developers/json-rpc-methods) which extend Solana's [JSON RPC API](https://solana.com/docs/rpc) to interact with compressed accounts. . + + +## Zero-knowledge proof (ZKP) + +A cryptographic proof to verify the validity of a statement without revealing the underlying data. + +ZK Compression uses a Groth16 SNARK zk proof + +- for its constant _validity_ proof size, to ensures the integrity of many compressed accounts, not for private or confidential transactions, and +- to store data in zk friendly data structures. Applications on Solana can prove custom off chain computations over zk compressed state (native zk compute). + + +## ZK-SNARK + +Zero-Knowledge Succinct Non-Interactive Arguments of Knowledge, a cryptographic proof system that enables proving knowledge of information without revealing the information itself. + +zk-SNARKs produce constant-size proofs that can be verified efficiently without interaction between prover and verifier. ZK Compression uses the Groth16 zk-SNARK construction to generate validity proofs for compressed account state transitions. + + +## ZK Compression + +A generalized compression framework to compress and verify arbitrary data with zero-knowledge proofs, to + +- enable the Compressed Account Model, the rent-free equivalent to Solana's Account Model, +- solve Solana's state growth problem, and +- build a foundation for native zk compute. diff --git a/zk-compression-docs/mintlify-docs/references/whitepaper.mdx b/zk-compression-docs/mintlify-docs/references/whitepaper.mdx new file mode 100644 index 0000000..b13474e --- /dev/null +++ b/zk-compression-docs/mintlify-docs/references/whitepaper.mdx @@ -0,0 +1,220 @@ +--- +title: "Whitepaper" +description: "Complete whitepaper introducing ZK Compression" +--- + + +
+ **Ask anything via** + + Ask DeepWiki + +
+
+ +### Scaling the Design Space for On-chain Applications with ZK Compression + +**Light Protocol Team** + +**Abstract** + +This paper proposes Light Protocol, a set of smart contracts for Solana that introduces ZK Compression. + +Solana application developers can opt-in to compress their application's on-chain state via the Light Protocol smart contracts. This reduces state cost by orders of magnitude while preserving the Solana L1's security, performance, and composability. + +For the Solana validator network, widespread adoption of ZK Compression could help solve the state growth problem by limiting the state held in active memory by validators relative to the total state produced. + +Finally, Light Protocol opens up a new design space for zero-knowledge-based protocols and applications on Solana; because ZK Compression stores data in zero-knowledge-friendly data structures, applications can efficiently prove custom off-chain computations over ZK-compressed state. + +#### 1 The Problem: Expensive On-chain State + +For developers to scale their on-chain applications to large user bases, the marginal cost of data storage must be near zero. Solana has emerged as a leading Layer 1 blockchain, attracting application developers who aim to scale to large numbers of end users. + +However, storing data on the Solana L1 has become increasingly expensive for the network, and the cost trickles down to the application developer, limiting the design space for on-chain applications with low Lifetime Value (LTV) / Customer Acquisition Cost (CAC) ratios. + +#### 2 ZK Compression + +When a Solana account gets compressed, its data is hashed and stored as a leaf in a sparse binary Merkle tree structure. The tree's state root (i.e., a small fingerprint of all compressed accounts in the tree) is stored on the blockchain. + +The underlying compressed account data is stored off-chain, e.g., as call data in the cheaper Solana ledger space. To read or write compressed state, transactions provide the compressed off-chain data and a succinct zero-knowledge proof (validity proof). + +Light Protocol verifies the validity proof against the respective on-chain state root to ensure that the provided data was previously emitted via the protocol smart contracts. The succinctness property of the zero-knowledge proof (a Groth16 SNARK \[1]) ensures that the integrity of many compressed accounts can be verified on-chain with a constant proof size of 128 bytes, which is ideal for Solana's highly constrained 1232-byte transaction size limit. + +#### 3 Light Protocol System Architecture + +The transaction flow in Light Protocol consists of the following key components: + +1. **Off-chain state storage**: State is stored off-chain, e.g., as calldata in the Solana ledger. +2. **New Transactions specify state:** Transactions include the compressed data they read or write, the state tree accounts, a pointer to a recent on-chain state root, and a corresponding validity proof, all included in the transaction payload. +3. **Applications must invoke the Light Protocol system program to write compressed state.** + 1. The system program validates the state (verifies the validity proof, performing sum checks and ownership checks) + 2. It enforces an account schema resembling the layout of classic Solana accounts. + 3. The old compressed state is nullified (inserted into the nullifier queue). + 4. The new compressed state is appended to the state Merkle Tree and recorded as call data on the Solana ledger. + 5. Any newly created addresses are inserted into the address queue. +4. **Photon Indexer** nodes index and store events to make compressed account state available to clients. A new node can always sync with the latest compressed state by sequentially processing all historical transactions from Genesis. + + + A diagram illustrating the transaction flow in the Light Protocol system architecture. The off-chain client reads the compressed state from the indexer and constructs a transaction. The transaction, which includes the compressed state, state tree accounts, a pointer to a recent on-chain state root, and a validity proof, is sent to the caller program. The caller program invokes the Light System Program, which interacts with the Account Compression Program to validate the state, nullify the old compressed state, append the new compressed state to the state Merkle Tree, and record it as call data on the Solana ledger. The Account Compression Program also updates state roots and emits events. The indexer retrieves the compressed state and validity proof from the Solana ledger and makes this information available to the off-chain client, completing the transaction flow. + + +A simplified compressed state transition can be expressed as: + +(𝑠𝑡𝑎𝑡𝑒, 𝑣𝑎𝑙𝑖𝑑𝑖𝑡𝑦𝑃𝑟𝑜𝑜𝑓) → 𝑠𝑡𝑎𝑡𝑒 𝑡𝑟𝑎𝑛𝑠𝑖𝑡𝑖𝑜𝑛 → 𝑠𝑡𝑎𝑡𝑒' + +Here, _state'_ gets emitted onto the ledger. + +- In principle, new compressed account hashes (output state) get appended to specified state trees with each state transition. +- Old compressed account hashes (input state) get invalidated via insertion into a nullifier queue. +- Compressed state transitions are atomic and instantly final. + + + A diagram illustrating the compressed state transition process in the Light Protocol system. The process is initiated by atomic user interactions with the protocol. The user interacts with the Caller Program, which invokes the Light System Program. The Light System Program then interacts with the Account Compression Program to facilitate the state transition. The Account Compression Program performs three key actions: appending the output state to the state tree, invalidating the input state by inserting it into the nullifier queue, and adding new addresses to the address queue. The Forester node asynchronously empties the queues and updates the Merkle trees, maintaining the on-chain accounts, including the state tree and address space tree, which store the compressed state. The compressed state transition follows the sequence: (𝑠𝑡𝑎𝑡𝑒, 𝑣𝑎𝑙𝑖𝑑𝑖𝑡𝑦𝑃𝑟𝑜𝑜𝑓) → 𝑠𝑡𝑎𝑡𝑒 𝑡𝑟𝑎𝑛𝑠𝑖𝑡𝑖𝑜𝑛 → 𝑠𝑡𝑎𝑡𝑒', where state' gets emitted onto the ledger. + + +**Foresters and Liveness** + +In an asynchronous process, _Forester_ nodes empty the nullifier queues. They achieve this by updating the leaf of the state Merkle tree, corresponding to the account hash previously inserted into the nullifier queue, with zeros (nullification). + +These queues enable instant finality of compressed state transitions but have a capped size. _Foresters_ are critical for protocol liveness and need to consistently empty queues. A full queue causes a liveness failure for all state stored in its associated state tree. A liveness failure is recovered by _Foresters_ emptying the queue again. Hosting a _Forester_ and foresting one's trees is permissionless. + +**3.1 Compressed Account Model** + +The Light System Program enforces an account layout that largely resembles Solana's regular account model. Key differences include: + +- Each compressed account can be identified by its hash. +- Each write to a compressed account changes its hash. +- An address can optionally be set as a permanent unique ID of the compressed account. +- All compressed accounts are stored in sparse Merkle trees. Only the trees' sparse state structure and roots (small fingerprints of all compressed accounts) are stored in the on-chain account space. + +These differences allow the protocol to store the underlying data off-chain (e.g., in the less expensive Solana ledger space) instead of in the more expensive on-chain account space. + +**Compressed PDA Accounts** + +Like regular accounts, each compressed account with a program-derived address (PDA) can be identified by its unique persistent address, represented as 32 bytes in the format of a PublicKey. + +Like PDAs, compressed account addresses don't belong to a private key; instead, they're derived from the program that owns them. + + + A diagram illustrating the structure of a compressed account in the Light Protocol system. The compressed account is owned by a program and is associated with a compressed PDA (Program Derived Address) account. The compressed account contains data bytes, lamports (account balance), an owner (the program that owns the account), and an address (represented as a public key). The owner of the compressed account has the authority to modify its data and transfer lamports from it. The compressed account is identified by its unique hash, which changes with each write operation. An address can be optionally set as a permanent unique identifier for the compressed account. Compressed accounts are stored in sparse Merkle trees, with only the trees' sparse state structure and roots stored in the on-chain account space, while the underlying data is stored off-chain. + + +The compressed PDA account layout is similar to Solana's regular PDA account layout: Data, Lamports, Owner, and an address field. The data field stores program-owned state. In contrast to Solana's account data field, Light Protocol enshrines a specific AccountData structure: Discriminator, Data, DataHash: + + + A diagram depicting the structure of a compressed PDA (Program Derived Address) account in the Light Protocol system. The compressed PDA account consists of a data field, which stores program-owned state, lamports (account balance), an owner field indicating the program that owns the account, and an address field represented as a public key. The AccountData structure within the compressed PDA account is composed of a discriminator (a unique identifier for the account type), the actual data (program state), and a DataHash (a hash of the account data). This AccountData structure is specific to the Light Protocol and differs from Solana's regular account data field. + + +**Compressed PDA Account with AccountData** + +The Anchor framework reserves the first 8 bytes of a regular account's data field for the discriminator. This helps programs distinguish between different account types. The default compressed account layout is opinionated in this regard and enforces a discriminator in the Data field. + +The dataHash is what the Protocol uses to verify the integrity of program-owned data. This enables the protocol to be agnostic as to whether or how the data underlying the dataHash is stored or passed to the Light system program. The account owner program needs to ensure the correctness of the data hash. + +**Compressed Token Accounts** + +Light Protocol provides an implementation of a compressed token program built on top of ZK Compression. + +The Compressed Token program enforces a token layout that is compatible with the SPL Token standard. The program also supports SPL compression and decompression; existing SPL token accounts can be compressed and decompressed arbitrarily. + +**Fungible Compressed Accounts** + +Each compressed account can be identified by its hash, regardless of whether it has an address. By definition, whenever the data of a compressed account changes, its hash changes. + +In contrast to Solana's regular account model, the address field is optional for compressed accounts because ensuring that a new account's address is unique incurs additional computational overhead. Addresses are not needed for fungible compressed accounts (i.e., tokens). + +**3.2 The Light Forest: Merkle Trees** + +The protocol stores compressed state in a "forest" of multiple binary Merkle trees. + +**State Trees** + +A state tree is a binary concurrent Merkle tree \[2] that organizes data into a tree structure where each parent node is the hash of its two children nodes. This leads to a single unique root hash that allows for efficient cryptographic verification of the integrity of all the leaves in the tree. The hash of each compressed account is stored as a leaf in such a state tree: + + + A diagram illustrating a binary Merkle tree with a depth of 2. The tree consists of a root node, two intermediate nodes (Node 0 and Node 1), and four leaf nodes (Leaf 0, Leaf 1, Leaf 2, and Leaf 3). The root node is the parent of Node 0 and Node 1, while Node 0 is the parent of Leaf 0 and Leaf 1, and Node 1 is the parent of Leaf 2 and Leaf 3. The tree represents a hierarchical structure where each parent node is derived from the hash of its two child nodes. + + + +Each compressed account hash is a leaf in the state tree: + + + A diagram illustrating the composition of a compressed account hash, which is stored as a leaf in a state tree. The compressed account hash consists of the DataHash, Lamports (account balance), OwnerHash, Address, Discriminator, State tree hash, and Leaf Index. The DataHash represents the hash of the account data, Lamports store the account balance, OwnerHash is the hash of the account owner, Address is an optional unique identifier for the account, Discriminator helps distinguish between different account types, State tree hash identifies the specific state tree the account belongs to, and Leaf Index represents the position of the account within the state tree. The state tree hash and leaf index ensure that each compressed account hash is globally unique. + + + +Compressed account hashes include the Public Key of the State tree's respective on-chain account (State tree hash) and the compressed account's position in the tree (leafIndex). This ensures that each account hash is globally unique. + +Each state tree has a corresponding on-chain State tree account that stores only the tree's final root hash and other metadata. Storing the final tree root hash on-chain allows the protocol to efficiently verify the validity of any leaf in the tree without needing to access the underlying compressed account state. The actual account data can thus be stored off-chain, e.g., in the much cheaper Solana ledger space, while preserving the security guarantees of the Solana L1. + +**Continuous Merkle Trees: Rollover and Rollover fees** + +For each new compressed account state, a new leaf is stored in the respective state Merkle tree. Given a tree depth of 26, the tree can support up to approximately 67 million leaves and, thus, 67 million compressed account state transitions. + +Compressed account hashes are added to the state tree until a threshold is reached. Once this threshold is met, a new state tree account and an associated nullifier queue account can be created to ensure continuous compressed transactions, a process known as a rollover. + +The costs for creating new on-chain accounts during a rollover are amortized across all transactions that add new leaves to the state tree. This marginal cost, which funds the next on-chain accounts, is usually very low and depends on the tree's depth and other factors affecting the size of the state tree and nullifier accounts. + +**Address Space Trees** + +Light Protocol supports the creation of provably unique addresses across a 254-bit address space. This is useful for applications requiring PDA-like uniqueness properties with compressed accounts, such as token-gating or creating unique identifiers. + +Transactions that create new addresses must provide a validity proof of exclusion from a given address space tree. Multiple independent address spaces can exist at the same time. Address space trees are indexed-concurrent binary Merkle tree data structures \[3]. These trees store exclusion ranges as linked lists in the tree leaves, enabling exclusion proofs across the 254-bit address space with trees of arbitrarily small depth. + +**Parallelism** + +State and address space trees can optionally be derived from and owned by custom Solana programs. This is useful for applications that want to control the write locks to their state trees. State tree accounts and nullifier accounts are separated to help elevate unnecessary write-locks. + +Suppose a tree _A_ with queue _A'_ and a tree _B_ with queue _B'._ Further, suppose a transaction _T_ nullifies a compressed account from tree _A_ but writes only to tree B; the transaction only write-locks _A'_ and _B_. _A_ and _B'_ do not get write-locked. + +**Limitations** + +ZK Compression reduces the data storage cost of all accounts to near zero, allowing developers to scale their application state to larger user bases on Solana. However, the following notable characteristics of ZK Compression can impact their utility for specific applications. ZK Compression transactions have: + +1. **Larger Transaction Size:** The transaction payload must include the compressed state to be read on-chain and a constant-size 128-byte validity proof. +2. **High Compute Unit Usage:** The protocol uses ZK primitives and on-chain hashing, which incur a relatively high base CU cost. If blocks are full, this can impact the inclusion rate of transactions. Future approaches to reducing CU cost can include optimizing the Merkle tree updates and hardware acceleration of cryptographic primitives and Syscalls used by the protocol. +3. **Per-transaction cost:** operating a _Forester_ node incurs additional hardware and transaction costs. The mechanism for efficiently nullifying multiple leaves in one Solana transaction can be improved significantly over time. + +#### 4 A World with Light Protocol + +**4.1 Light Helps Developers Scale Their Applications** + +The set of applications and protocols that benefit from ZK Compression is quite broad, including: + +1. Token-based applications and marketplaces, including applications for large-scale token distribution. +2. Applications that issue large numbers of digital assets, PDA accounts, and unique identifiers, such as decentralized social applications, name-service programs, and staking protocols. +3. Applications serving a user base with a low LTV/CAC ratio. +4. Payments infrastructure and applications. + +**4.2 Light Enables ZK-Applications** + +Light Protocol is a shared bridge to merklelized, zk-friendly state. We believe that as more state becomes compressed via ZK Compression, Light Protocol will provide ZK-based applications and protocols with the option to bootstrap and scale on Solana across globally shared compressed state. + +We believe the design space for ZK-based applications is now wide open and will continue to expand. Some exciting technologies include: + +1. Identity Protocols, +2. ZK Coprocessors, +3. Based ZK Rollups + +#### 5 Summary + +1. Light Protocol enables Solana developers to reduce their application state by orders of magnitude by introducing the ZK Compression primitive, which allows secure on-chain composability with off-chain state. +2. ZK Compression can contribute to solving Solana's state growth problem. +3. Light seeks to enable a future with a thriving ZK ecosystem on Solana where new applications, marketplaces and computation designs can all interoperate, compose, and innovate permissionlessly over shared zk-compressed state. + +**Acknowledgments** + +We are grateful to Nicolas Pennie and Pedro Mantica for their extensive feedback, which has helped shape the design of ZK Compression, and to the team at Helius Labs as a whole for building the canonical ZK Compression Indexer implementation and RPC API. + +**Legal Disclaimer** + +Please read the entirety of this "Legal Disclaimer" section carefully. If you have any doubts about the action you should take, you should consult your own legal, financial, tax, or other professional advisor(s) before engaging in any activity herewith. This paper is for general information purposes only, to receive feedback and comments from the public. It does not constitute investment advice, a recommendation, or a solicitation to buy or sell any investment. It should not be used to evaluate the merits of making any investment decision. It should not be relied upon for accounting, legal, or tax advice or any investment recommendations. This paper reflects the current opinions of the Light Protocol Team. The opinions reflected herein outline current plans, which are subject to change at its discretion, without any guarantee of being updated. The success of outlined plans will depend on many factors outside the authors' or Light Protocol Labs' control, including but not limited to factors within the data and blockchain industries. Any statements about future events are based solely on the analysis of the issues described in this White Paper. That analysis might prove to be incorrect. + +**References** + +\[1] Groth, Jens. "On the size of pairing-based non-interactive arguments. " _Advances in Cryptology–EUROCRYPT 2016: 35th Annual International Conference on the Theory and Applications of Cryptographic Techniques, Vienna, Austria, May 8-12, 2016, Proceedings, Part II 35_. Springer Berlin Heidelberg, 2016. + +\[2] _Concurrent Merkle Tree whitepaper.pdf_. (n.d.). Google Docs. [https://drive.google.com/file/d/1BOpa5OFmara50fTvL0VIVYjtg-qzHCVc/view](https://drive.google.com/file/d/1BOpa5OFmara50fTvL0VIVYjtg-qzHCVc/view) + +\[3] _Indexed Merkle Tree | Privacy-First ZKRollup | Aztec Documentation_. (n.d.). [https://docs.aztec.network/aztec/concepts/storage/trees/indexed\_merkle\_tree#indexed-merkle-tree-constructions](https://docs.aztec.network/aztec/concepts/storage/trees/indexed_merkle_tree#indexed-merkle-tree-constructions) + diff --git a/zk-compression-docs/mintlify-docs/resources/addresses-and-urls.mdx b/zk-compression-docs/mintlify-docs/resources/addresses-and-urls.mdx new file mode 100644 index 0000000..1e10277 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/addresses-and-urls.mdx @@ -0,0 +1,177 @@ +--- +title: "Addresses and URLs" +description: "Overview to all of ZK Compression's RPC URLs, Program IDs & Accounts and Lookup Tables." +--- + +### RPC URLs + + + +| Network | Service | URL | +|:-|:-|:-| +| Mainnet | Network Address (RPC) | `https://mainnet.helius-rpc.com?api-key=<api_key>` | +| Mainnet | Photon RPC API | `https://mainnet.helius-rpc.com?api-key=<api_key>` | + + + +| Network | Service | URL | +|:-|:-|:-| +| Devnet | Network Address (RPC) | `https://devnet.helius-rpc.com?api-key=<api_key>` | +| Devnet | Photon RPC API | `https://devnet.helius-rpc.com?api-key=<api_key>` | + + + + +Find all JSON RPC Methods for ZK Compression [here](/resources/json-rpc-methods). + + +### Program IDs + +| | | +|:-|:-| +| Light System Program | **SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7** | +| Compressed Token Program | **cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m** | +| Account Compression Program | **compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq** | + +### State Trees & Queues & CPI Accounts + + +**In your local test validator environment** use in Rust `TestAccounts::get_local_test_validator_accounts()` to get all pre-configured protocol, state tree, and address tree accounts. + + + + + +| | Devnet | Mainnet | Public Key | +|:-|:-:|:-:|:-| +| State Tree | ✓ | ✓ | **smt2rJAFdyJJupwMKAqTNAJwvjhmiZ4JYGZmbVRw1Ho** | +| Nullifier Queue | ✓ | ✓ | **nfq2hgS7NYemXsFaFUCe3EMXSDSfnZnAe27jC6aPP1X** | +| CPI Context | ✓ | ✓ | **cpi2cdhkH5roePvcudTgUL8ppEBfTay1desGh8G8QxK** | + + + + + +| | Devnet | Mainnet | Public Key | +|:-|:-:|:-:|:-| +| #1 State Tree | ✓ | - | **bmt1LryLZUMmF7ZtqESaw7wifBXLfXHQYoE4GAmrahU** | +| #1 Output Queue | ✓ | - | **oq1na8gojfdUhsfCpyjNt6h4JaDWtHf1yQj4koBWfto** | +| #1 CPI Context | ✓ | - | **cpi15BoVPKgEPw5o8wc2T816GE7b378nMXnhH3Xbq4y** | + +| | Devnet | Mainnet | Public Key | +|:-|:-:|:-:|:-| +| #2 State Tree | ✓ | - | **bmt2UxoBxB9xWev4BkLvkGdapsz6sZGkzViPNph7VFi** | +| #2 Output Queue | ✓ | - | **oq2UkeMsJLfXt2QHzim242SUi3nvjJs8Pn7Eac9H9vg** | +| #2 CPI Context | ✓ | - | **cpi2yGapXUR3As5SjnHBAVvmApNiLsbeZpF3euWnW6B** | + +| | Devnet | Mainnet | Public Key | +|:-|:-:|:-:|:-| +| #3 State Tree | ✓ | - | **bmt3ccLd4bqSVZVeCJnH1F6C8jNygAhaDfxDwePyyGb** | +| #3 Output Queue | ✓ | - | **oq3AxjekBWgo64gpauB6QtuZNesuv19xrhaC1ZM1THQ** | +| #3 CPI Context | ✓ | - | **cpi3mbwMpSX8FAGMZVP85AwxqCaQMfEk9Em1v8QK9Rf** | + +| | Devnet | Mainnet | Public Key | +|:-|:-:|:-:|:-| +| #4 State Tree | ✓ | - | **bmt4d3p1a4YQgk9PeZv5s4DBUmbF5NxqYpk9HGjQsd8** | +| #4 Output Queue | ✓ | - | **oq4ypwvVGzCUMoiKKHWh4S1SgZJ9vCvKpcz6RT6A8dq** | +| #4 CPI Context | ✓ | - | **cpi4yyPDc4bCgHAnsenunGA8Y77j3XEDyjgfyCKgcoc** | + +| | Devnet | Mainnet | Public Key | +|:-|:-:|:-:|:-| +| #5 State Tree | ✓ | - | **bmt5yU97jC88YXTuSukYHa8Z5Bi2ZDUtmzfkDTA2mG2** | +| #5 Output Queue | ✓ | - | **oq5oh5ZR3yGomuQgFduNDzjtGvVWfDRGLuDVjv9a96P** | +| #5 CPI Context | ✓ | - | **cpi5ZTjdgYpZ1Xr7B1cMLLUE81oTtJbNNAyKary2nV6** | + + + + +### Address Trees & Queues + + + +| Address Tree #1 | | +|:-|:-| +| Address Tree #1 | **amt1Ayt45jfbdw5YSo7iz6WZxUmnZsQTYXy82hVwyC2** | +| Address Queue #1 | **aq1S9z4reTSQAdgWHGD2zDaS39sjGrAxbR31vxJ2F4F** | + + + +| Address Tree | | +|:-|:-| +| Address Tree | **amt2kaJA14v3urZbZvnc5v2np8jqvc4Z8zDep5wbtzx** | + + + +### Token Escrow PDA + +| | | +|:-|:-| +| Token Escrow Owner PDA | **GXtd2izAiMJPwMEjfgTRH3d7k9mjn4Jq3JrWFv9gySYy** | + +### Lookup Tables + + +[Lookup tables](https://solana.com/docs/advanced/lookup-tables) reduce your transaction size. We provide pre-initialized lookup tables that cover the Light's program IDs and accounts: + + +| | | +|:-|:-| +| Lookup Table #1 (Mainnet) | **9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ** | +| Lookup Table #1 (Devnet) | **qAJZMgnQJ8G6vA3WRcjD9Jan1wtKkaCFWLWskxJrR5V** | + +We provide a helper function below if you need to extend a custom lookup table. + + + +```typescript +import { Rpc, confirmTx, createRpc } from "@lightprotocol/stateless.js"; +import { createTokenProgramLookupTable } from "@lightprotocol/compressed-token"; +import { Keypair, PublicKey} from "@solana/web3.js"; +import { RPC_ENDPOINT } from "./constants"; +const payer = Keypair.generate(); +const authority = payer; +const additionalTokenMints : PublicKey[] = []; +const additionalAccounts : PublicKey[] = []; + +// Localnet +const connection: Rpc = createRpc(); + +const main = async () => { + /// airdrop lamports to pay gas and rent + await confirmTx( + connection, + await connection.requestAirdrop(payer.publicKey, 1e7) + ); + + /// Create LUT + const { address } = await createTokenProgramLookupTable( + connection, + payer, + authority, + additionalTokenMints, + additionalAccounts + ); + + console.log("Created lookup table:", address.toBase58()); +}; + +main(); +``` + + + +## System Accounts List +| | Name | Description | +|:-|:-|:-| +| 1 | Light System Program | Verifies validity proofs, compressed account ownership checks, and CPIs the Account Compression Program to update tree accounts. | +| 2 | **CPI Signer** | - PDA to sign CPI calls from your program to the Light System Program.
- Verified by the Light System Program during CPI.
- Derived from your program ID. | +| 3 | **Registered Program PDA** | - Provides access control to the Account Compression Program. | +| 4 | Noop Program | - Logs compressed account state to the Solana ledger (used only in v1).
- Indexers parse transaction logs to reconstruct compressed account state. | +| 5 | Account Compression Authority | Signs CPI calls from the Light System Program to the Account Compression Program. | +| 6 | Account Compression Program | - Writes to state and address tree accounts.
- Clients and the Account Compression Program do not interact directly — handled internally. | +| 7 | **Invoking Program** | Your program’s ID, used by the Light System Program to:
- Derive the CPI Signer PDA.
- Verify the CPI Signer matches your program ID.
- Set the owner of created compressed accounts. | +| 8 | System Program | Solana System Program used to transfer lamports. | + +## Next Steps + +Explore all JSON RPC endpoints on Solana, best practices, and error codes. diff --git a/zk-compression-docs/mintlify-docs/resources/cli-installation.mdx b/zk-compression-docs/mintlify-docs/resources/cli-installation.mdx new file mode 100644 index 0000000..e886a5a --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/cli-installation.mdx @@ -0,0 +1,246 @@ +--- +title: "CLI Installation" +description: "Steps to set up your local environment for ZK Compression development. CLI to interact with compressed accounts and compressed tokens on Solana." +--- + + +Make sure you have a wallet set up at `~/.config/solana/id.json`. [Get one here](https://docs.solanalabs.com/cli/wallets/file-system), if you don't have one.\ +The CLI will use this wallet as the default fee payer and mint authority. + + +### Installation + + +
+ Ask anything about the ZK Compression CLI via + + Ask DeepWiki + + +
+
+ + + + + + +Ensure you have Node >= v20.9.0 installed on your machine. Windows users do not require WSL. + + +Run this single command to install the ZK Compression CLI. + +```bash +npm install -g @lightprotocol/zk-compression-cli +``` + + + + +If you prefer to build the CLI from source, follow the steps below to install the necessary prerequisites. + +**1. Activate the Development Environment** + +Ensure you are at the root of the monorepo. + +```bash +. ./scripts/devenv +``` + +**2. Install and build the monorepo from source. This also builds the CLI.** + +```bash +./scripts/install.sh +``` + +```bash +./scripts/build.sh +``` + +**3. Make your CLI available globally** + +```bash +pnpm link --global +``` + +```bash +# Verify the CLI was correctly installed +which light +``` + + + + + + +By default, the CLI interacts with localnet. You can view the current config by running: + +```bash +light config --get +``` + +**1. Once globally installed, start the Light test validator** + +```bash +light test-validator +``` + +This 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. + +```bash +# Pass --skip-indexer to start without the indexer +light test-validator --skip-indexer + +# Pass --skip-prover to start without the prover +light test-validator --skip-prover + +``` + +**Note:** + +The CLI currently runs the photon indexer and light-prover as background processes at port: `8784` and `3001` respectively. + + +**2. Ensure you have sufficient localnet funds** + +```bash +# Airdrop 1 SOL +solana airdrop 1 + +# Print your address +solana address + +# Print your balance +solana balance +``` + +Now you're all set up to run CLI commands! + + + +To switch to Devnet, point the URLs to an RPC supporting ZK Compression. For example, run: + +```bash + light config --indexerUrl "https://devnet.helius-rpc.com/?api-key=" \ + --proverUrl "https://devnet.helius-rpc.com/?api-key=" \ + --solanaRpcUrl "https://devnet.helius-rpc.com/?api-key=" +``` + +Also adjust your solana config: + +```bash +# Set config +solana config set --url "https://devnet.helius-rpc.com/?api-key=" + +# Airdrop 1 SOL +solana airdrop 1 + +# Print your address +solana address +``` + + + + + +### Commands + +**Create a compressed token mint** + +```bash +light create-mint +``` + +```bash +USAGE + $ light create-mint [--mint-keypair ] [--mint-authority ] + [--mint-decimals ] + +FLAGS + --mint-authority= Path to the mint authority keypair file. + Defaults to default local Solana wallet file + path. + --mint-decimals= Number of base 10 digits to the right + of the decimal place [default: 9]. + --mint-keypair= Path to a mint keypair file. Defaults to a + random keypair. +``` + +**Mint compressed tokens to a Solana wallet** + +```bash +light mint-to --mint "YOUR_MINT_ADDRESS" --to "YOUR_WALLET_ADDRESS" --amount 4200000000 +``` + +```bash +USAGE + $ light mint-to --mint --to --amount + [--mint-authority ] + +FLAGS + --amount= (required) Amount to mint. + --mint= (required) Mint address. + --mint-authority= File path of the mint authority keypair. + Defaults to local Solana wallet. + --to= (required) Recipient address. +``` + +**Transfer compressed tokens from one wallet to another** + +```bash +light transfer --mint "YOUR_MINT_ADDRESS" --to "RECIPIENT_WALLET_ADDRESS" --amount 4200000000 +``` + +```bash +USAGE + $ light transfer --mint --to --amount + [--fee-payer ] + +FLAGS + --amount= (required) Amount to send. + --fee-payer= Fee payer account. Defaults to the client + keypair. + --mint= (required) Mint to transfer + --to= (required) Recipient address + +``` + +**Assign native SOL to a compressed account** + +```bash +light compress-sol --amount 1000 --to "YOUR_WALLET_ADDRESS_BASE58" +``` + +```bash +USAGE + $ light compress-sol --to --amount + +FLAGS + --amount= (required) Amount to compress in lamports. + --to= (required) Specify the recipient address. +``` + +**Decompress into native SOL** + +```bash +light decompress-sol --amount 42 --to "YOUR_WALLET_ADDRESS_BASE58" +``` + +```bash +USAGE + $ light decompress-sol --to --amount + +FLAGS + --amount= (required) Amount to decompress in lamports. + --to= (required) Specify the recipient address. +``` + +#### Support + +- Always feel free to join the [Developer Discord](https://discord.gg/D2cEphnvcY) for help! +- For more info about the canonical indexer implementation built and maintained by Helius Labs, refer to the [Photon codebase](https://github.com/helius-labs/photon). + + +### Next Steps + +Get started with our cookbook guides. diff --git a/zk-compression-docs/mintlify-docs/resources/error-cheatsheet.mdx b/zk-compression-docs/mintlify-docs/resources/error-cheatsheet.mdx new file mode 100644 index 0000000..f7c2cbd --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/error-cheatsheet.mdx @@ -0,0 +1,305 @@ +--- +title: "Error Cheatsheet" +sidebarTitle: "Overview" +description: "Complete error code reference for ZK Compression. Search error codes with hex values and messages." +--- + +## How to use this page + +1. **Search your error code or hex value** with `Cmd+F`/ `Ctrl+F` +2. **Check for debug guides -** some errors have detailed troubleshooting pages +3. **Still having issues?** We're here to help! + +- Reach out on [Discord](https://discord.com/invite/CYvjBgzRFP) for support +- Share the exact error code and a reproducer (GitHub repo / gist) + + +
+ For help with debugging use the [MCP Configuration](/learn/ai-tools-guide#mcp) or AskDevin via + + Ask DeepWiki + +
+
+ + +## 6000 - 6053 / SystemProgramError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/main/programs/system/src/errors.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/programs/system/src/errors.rs#L133) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 6000 | 0x1770 | `SumCheckFailed` | "Sum check failed" | +| 6001 | 0x1771 | `SignerCheckFailed` | "Signer check failed" | +| 6002 | 0x1772 | `CpiSignerCheckFailed` | "Cpi signer check failed" | +| 6003 | 0x1773 | `ComputeInputSumFailed` | "Computing input sum failed." | +| 6004 | 0x1774 | `ComputeOutputSumFailed` | "Computing output sum failed." | +| 6005 | 0x1775 | `ComputeRpcSumFailed` | "Computing rpc sum failed." | +| 6006 | 0x1776 | `InvalidAddress` | "InvalidAddress" | +| 6007 | 0x1777 | `DeriveAddressError` | "DeriveAddressError" | +| 6008 | 0x1778 | `CompressedSolPdaUndefinedForCompressSol` | "CompressedSolPdaUndefinedForCompressSol" | +| 6009 | 0x1779 | `DecompressLamportsUndefinedForCompressSol` | "DecompressLamportsUndefinedForCompressSol" | +| 6010 | 0x177A | `CompressedSolPdaUndefinedForDecompressSol` | "CompressedSolPdaUndefinedForDecompressSol" | +| 6011 | 0x177B | `DeCompressLamportsUndefinedForDecompressSol` | "DeCompressLamportsUndefinedForDecompressSol" | +| 6012 | 0x177C | `DecompressRecipientUndefinedForDecompressSol` | "DecompressRecipientUndefinedForDecompressSol" | +| 6013 | 0x177D | `WriteAccessCheckFailed` | "WriteAccessCheckFailed" | +| 6014 | 0x177E | `InvokingProgramNotProvided` | "InvokingProgramNotProvided" | +| 6015 | 0x177F | `InvalidCapacity` | "InvalidCapacity" | +| 6016 | 0x1780 | `InvalidMerkleTreeOwner` | "InvalidMerkleTreeOwner" | +| 6017 | 0x1781 | `ProofIsNone` | "ProofIsNone" | +| 6018 | 0x1782 | `ProofIsSome` | "Proof is some but no input compressed accounts or new addresses provided." | +| 6019 | 0x1783 | `EmptyInputs` | "EmptyInputs" | +| 6020 | 0x1784 | `CpiContextAccountUndefined` | "CpiContextAccountUndefined" | +| 6021 | 0x1785 | `CpiContextEmpty` | "CpiContextEmpty" | +| 6022 | 0x1786 | `CpiContextMissing` | "CpiContextMissing" | +| 6023 | 0x1787 | `DecompressionRecipientDefined` | "DecompressionRecipientDefined" | +| 6024 | 0x1788 | `SolPoolPdaDefined` | "SolPoolPdaDefined" | +| 6025 | 0x1789 | `AppendStateFailed` | "AppendStateFailed" | +| 6026 | 0x178A | `InstructionNotCallable` | "The instruction is not callable" | +| 6027 | 0x178B | `CpiContextFeePayerMismatch` | "CpiContextFeePayerMismatch" | +| 6028 | 0x178C | `CpiContextAssociatedMerkleTreeMismatch` | "CpiContextAssociatedMerkleTreeMismatch" | +| 6029 | 0x178D | `NoInputs` | "NoInputs" | +| 6030 | 0x178E | `InputMerkleTreeIndicesNotInOrder` | "Input merkle tree indices are not in ascending order." | +| 6031 | 0x178F | `OutputMerkleTreeIndicesNotInOrder` | "Output merkle tree indices are not in ascending order." | +| 6032 | 0x1790 | `OutputMerkleTreeNotUnique` | "OutputMerkleTreeNotUnique" | +| 6033 | 0x1791 | `DataFieldUndefined` | "DataFieldUndefined" | +| 6034 | 0x1792 | `ReadOnlyAddressAlreadyExists` | "ReadOnlyAddressAlreadyExists" | +| 6035 | 0x1793 | `ReadOnlyAccountDoesNotExist` | "ReadOnlyAccountDoesNotExist" | +| 6036 | 0x1794 | `HashChainInputsLenghtInconsistent` | "HashChainInputsLenghtInconsistent" | +| 6037 | 0x1795 | `InvalidAddressTreeHeight` | "InvalidAddressTreeHeight" | +| 6038 | 0x1796 | `InvalidStateTreeHeight` | "InvalidStateTreeHeight" | +| 6039 | 0x1797 | `InvalidArgument` | "InvalidArgument" | +| 6040 | 0x1798 | `InvalidAccount` | "InvalidAccount" | +| 6041 | 0x1799 | `AddressMerkleTreeAccountDiscriminatorMismatch` | "AddressMerkleTreeAccountDiscriminatorMismatch" | +| 6042 | 0x179A | `StateMerkleTreeAccountDiscriminatorMismatch` | "StateMerkleTreeAccountDiscriminatorMismatch" | +| 6043 | 0x179B | `ProofVerificationFailed` | "Proof verification failed."
[How to debug this error](/resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed) | +| 6044 | 0x179C | `InvalidAccountMode` | "Invalid account mode." | +| 6045 | 0x179D | `InvalidInstructionDataDiscriminator` | "InvalidInstructionDataDiscriminator" | +| 6046 | 0x179E | `NewAddressAssignedIndexOutOfBounds` | "NewAddressAssignedIndexOutOfBounds" | +| 6047 | 0x179F | `AddressIsNone` | "AddressIsNone" | +| 6048 | 0x17A0 | `AddressDoesNotMatch` | "AddressDoesNotMatch" | +| 6049 | 0x17A1 | `CpiContextAlreadySet` | "CpiContextAlreadySet" | +| 6050 | 0x17A2 | `InvalidTreeHeight` | "InvalidTreeHeight" | +| 6051 | 0x17A3 | `TooManyOutputAccounts` | "TooManyOutputAccounts" | +| 6052 | 0x17A4 | `BorrowingDataFailed` | "Borrowing data failed" | +| 6053 | 0x17A5 | `DuplicateAccountInInputsAndReadOnly` | "DuplicateAccountInInputsAndReadOnly" | + +## 7001 - 7009 / HasherError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/program-libs/hasher/src/errors.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/program-libs/hasher/src/errors.rs) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 7001 | 0x1B59 | `IntegerOverflow` | "Integer overflow, value too large" | +| 7003 | 0x1B5B | `PoseidonSyscall(PoseidonSyscallError)` | "Poseidon syscall error: {0}" | +| 7005 | 0x1B5D | `InvalidInputLength(usize, usize)` | "Allowed input length {0} provided {1}" | +| 7006 | 0x1B5E | `InvalidNumFields` | "Invalid number of fields" | +| 7007 | 0x1B5F | `EmptyInput` | "Empty input" | +| 7008 | 0x1B60 | `BorshError` | "Borsh serialization failed." | +| 7009 | 0x1B61 | `OptionHashToFieldSizeZero` | "Option hash to field size returned [0u8;32], a collision with None for an Option type." | + + +## 10001 - 10014 / ConcurrentMerkleTreeError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/program-libs/concurrent-merkle-tree/src/errors.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/program-libs/concurrent-merkle-tree/src/errors.rs) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 10001 | 0x2711 | `IntegerOverflow` | "Integer overflow" | +| 10002 | 0x2712 | `HeightZero` | "Invalid height, it has to be greater than 0" | +| 10003 | 0x2713 | `InvalidHeight(usize)` | "Invalud height, expected {0}" | +| 10004 | 0x2714 | `ChangelogZero` | "Invalid changelog size, it has to be greater than 0. Changelog is used for storing Merkle paths during appends." | +| 10005 | 0x2715 | `RootsZero` | "Invalid number of roots, it has to be greater than 0" | +| 10006 | 0x2716 | `CanopyGeThanHeight` | "Canopy depth has to be lower than height" | +| 10007 | 0x2717 | `TreeIsFull` | "Merkle tree is full, cannot append more leaves." | +| 10008 | 0x2718 | `BatchGreaterThanChangelog(usize, usize)` | "Number of leaves ({0}) exceeds the changelog capacity ({1})." | +| 10009 | 0x2719 | `InvalidProofLength(usize, usize)` | "Invalid proof length, expected {0}, got {1}." | +| 10010 | 0x271A | `InvalidProof([u8; 32], [u8; 32])` | "Invalid Merkle proof, expected root: `{0:?}`, the provided proof produces root: `{1:?}`" | +| 10011 | 0x271B | `CannotUpdateLeaf` | "Attempting to update the leaf which was updated by an another newest change." | +| 10012 | 0x271C | `CannotUpdateEmpty` | "Cannot update the empty leaf" | +| 10013 | 0x271D | `EmptyLeaves` | "The batch of leaves is empty" | +| 10014 | 0x271E | `BufferSize(usize, usize)` | "Invalid buffer size, expected {0}, got {1}" | + + +## 11001 - 11009 / IndexedMerkleTreeError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/program-libs/indexed-merkle-tree/src/errors.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/program-libs/indexed-merkle-tree/src/errors.rs) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 11001 | 0x2AF9 | `IntegerOverflow` | "Integer overflow" | +| 11002 | 0x2AFA | `IndexHigherThanMax` | "Invalid index, it exceeds the number of elements." | +| 11003 | 0x2AFB | `LowElementNotFound` | "Could not find the low element." | +| 11004 | 0x2AFC | `LowElementGreaterOrEqualToNewElement` | "Low element is greater or equal to the provided new element." | +| 11005 | 0x2AFD | `NewElementGreaterOrEqualToNextElement` | "The provided new element is greater or equal to the next element." | +| 11006 | 0x2AFE | `ElementAlreadyExists` | "The element already exists, but was expected to be absent." | +| 11007 | 0x2AFF | `ElementDoesNotExist` | "The element does not exist, but was expected to be present." | +| 11008 | 0x2B00 | `ChangelogBufferSize(usize, usize)` | "Invalid changelog buffer size, expected {0}, got {1}" | +| 11009 | 0x2B01 | `ArrayFull` | "Indexed array is full, cannot append more elements" | + + +## 12006 - 12019 / AccountError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/program-libs/account-checks/src/error.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/program-libs/account-checks/src/error.rs) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 12006 | 0x2EE6 | `InvalidDiscriminator` | "Invalid Discriminator." | +| 12007 | 0x2EE7 | `AccountOwnedByWrongProgram` | "Account owned by wrong program." | +| 12008 | 0x2EE8 | `AccountNotMutable` | "Account not mutable." | +| 12009 | 0x2EE9 | `BorrowAccountDataFailed` | "Borrow account data failed." | +| 12010 | 0x2EEA | `InvalidAccountSize` | "Invalid Account size." | +| 12011 | 0x2EEB | `AccountMutable` | "Account is mutable." | +| 12012 | 0x2EEC | `AlreadyInitialized` | "Account is already initialized." | +| 12013 | 0x2EED | `InvalidAccountBalance` | "Invalid account balance." | +| 12014 | 0x2EEE | `FailedBorrowRentSysvar` | "Failed to borrow rent sysvar." | +| 12015 | 0x2EEF | `InvalidSigner` | "Invalid Signer" | +| 12016 | 0x2EF0 | `InvalidSeeds` | "Invalid Seeds" | +| 12017 | 0x2EF1 | `InvalidProgramId` | "Invalid Program Id" | +| 12018 | 0x2EF2 | `ProgramNotExecutable` | "Program not executable." | +| 12019 | 0x2EF3 | `AccountNotZeroed` | "Account not zeroed." | + + +## 14001 - 14009 / MerkleTreeMetadataError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/program-libs/merkle-tree-metadata/src/errors.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/program-libs/merkle-tree-metadata/src/errors.rs) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 14001 | 0x36B1 | `MerkleTreeAndQueueNotAssociated` | "Merkle tree and queue are not associated." | +| 14002 | 0x36B2 | `RolloverNotConfigured` | "Rollover not configured." | +| 14003 | 0x36B3 | `MerkleTreeAlreadyRolledOver` | "Merkle tree already rolled over." | +| 14004 | 0x36B4 | `InvalidQueueType` | "Invalid queue type." | +| 14005 | 0x36B5 | `InsufficientRolloverFee` | "Insufficient rollover fee." | +| 14006 | 0x36B6 | `NotReadyForRollover` | "Merkle tree not ready for rollover." | +| 14007 | 0x36B7 | `InvalidTreeType` | "Invalid tree type." | +| 14008 | 0x36B8 | `InvalidRolloverThreshold` | "Invalid Rollover Threshold." | +| 14009 | 0x36B9 | `InvalidHeight` | "Invalid Height." | + + +## 14017 - 14034 / LightSdkTypesError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/sdk-libs/sdk-types/src/error.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/sdk-libs/sdk-types/src/error.rs#L4) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 14017 | 0x36C1 | `FewerAccountsThanSystemAccounts` | "Fewer accounts than system accounts" | +| 14021 | 0x36C5 | `InitAddressIsNone` | "Address is none during initialization" | +| 14022 | 0x36C6 | `InitWithAddressIsNone` | "Address is none during initialization with address" | +| 14023 | 0x36C7 | `InitWithAddressOutputIsNone` | "Output is none during initialization with address" | +| 14024 | 0x36C8 | `MetaMutAddressIsNone` | "Address is none during meta mutation" | +| 14025 | 0x36C9 | `MetaMutInputIsNone` | "Input is none during meta mutation" | +| 14026 | 0x36CA | `MetaMutOutputLamportsIsNone` | "Output lamports is none during meta mutation" | +| 14027 | 0x36CB | `MetaMutOutputIsNone` | "Output is none during meta mutation" | +| 14028 | 0x36CC | `MetaCloseAddressIsNone` | "Address is none during meta close" | +| 14029 | 0x36CD | `MetaCloseInputIsNone` | "Input is none during meta close" | +| 14031 | 0x36CF | `CpiAccountsIndexOutOfBounds(usize)` | "CPI accounts index out of bounds: {0}" | +| 14032 | 0x36D0 | `InvalidCpiContextAccount` | "Invalid CPI context account" | +| 14033 | 0x36D1 | `InvalidSolPoolPdaAccount` | "Invalid sol pool pda account" | +| 14034 | 0x36D2 | `InvalidCpiAccountsOffset` | "CpiAccounts accounts slice starts with an invalid account. It should start with LightSystemProgram SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7." | + + +## 14301 - 14312 / BatchedMerkleTreeError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/program-libs/batched-merkle-tree/src/errors.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/program-libs/batched-merkle-tree/src/errors.rs) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 14301 | 0x37DD | `BatchNotReady` | "Batch is not ready to be inserted" | +| 14302 | 0x37DE | `BatchAlreadyInserted` | "Batch is already inserted" | +| 14303 | 0x37DF | `BatchInsertFailed` | "Batch insert failed" | +| 14304 | 0x37E0 | `LeafIndexNotInBatch` | "Leaf index not in batch." | +| 14305 | 0x37E1 | `InvalidNetworkFee` | "Invalid network fee." | +| 14306 | 0x37E2 | `BatchSizeNotDivisibleByZkpBatchSize` | "Batch size not divisible by ZKP batch size." | +| 14307 | 0x37E3 | `InclusionProofByIndexFailed` | "Inclusion proof by index failed." | +| 14308 | 0x37E4 | `InvalidBatchIndex` | "Invalid batch index" | +| 14309 | 0x37E5 | `InvalidIndex` | "Invalid index" | +| 14310 | 0x37E6 | `TreeIsFull` | "Batched Merkle tree is full." | +| 14311 | 0x37E7 | `NonInclusionCheckFailed` | "Value already exists in bloom filter." | +| 14312 | 0x37E8 | `BloomFilterNotZeroed` | "Bloom filter must be zeroed prior to reusing a batch." | + + +## 15001 - 15017 / ZeroCopyError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/program-libs/zero-copy/src/errors.rs](https://github.com/Lightprotocol/light-protocol/blob/604892ff3902292dd0b0b047cb0bfacc469ea0d4/program-libs/zero-copy/src/errors.rs) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 15001 | 0x3A99 | `Full` | "The vector is full, cannot push any new elements" | +| 15002 | 0x3A9A | `ArraySize(usize, usize)` | "Requested array of size {}, but the vector has {} elements" | +| 15003 | 0x3A9B | `IterFromOutOfBounds` | "The requested start index is out of bounds" | +| 15004 | 0x3A9C | `InsufficientMemoryAllocated(usize, usize)` | "Memory allocated {}, Memory required {}" | +| 15006 | 0x3A9E | `UnalignedPointer` | "Unaligned pointer" | +| 15007 | 0x3A9F | `MemoryNotZeroed` | "Memory not zeroed" | +| 15008 | 0x3AA0 | `InvalidConversion` | "Invalid conversion" | +| 15009 | 0x3AA1 | `InvalidData(Infallible)` | "Invalid data" | +| 15010 | 0x3AA2 | `Size` | "Invalid size" | +| 15011 | 0x3AA3 | `InvalidOptionByte(u8)` | "Invalid option byte {} must be 0 (None) or 1 (Some)" | +| 15012 | 0x3AA4 | `InvalidCapacity` | "Invalid capacity. Capacity must be greater than 0" | +| 15013 | 0x3AA5 | `LengthGreaterThanCapacity` | "Length is greater than capacity" | +| 15014 | 0x3AA6 | `CurrentIndexGreaterThanLength` | "Current index is greater than length" | +| 15015 | 0x3AA7 | `InvalidEnumValue` | "Invalid enum value" | +| 15016 | 0x3AA8 | `InsufficientCapacity` | "Insufficient capacity for operation" | +| 15017 | 0x3AA9 | `PlatformSizeOverflow` | "Value too large for platform usize" | + + +## 16001 - 16034 / LightSdkError Variants + + +Source code: [https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/sdk/src/error.rs](https://github.com/Lightprotocol/light-protocol/blob/main/sdk-libs/sdk/src/error.rs#L126) + + +| Code | Hex | Error | Message | +|:-|:-|:-|:-| +| 16001 | 0x3E81 | `ConstraintViolation` | "Constraint violation" | +| 16002 | 0x3E82 | `InvalidLightSystemProgram` | "Invalid light-system-program ID" | +| 16003 | 0x3E83 | `ExpectedAccounts` | "Expected accounts in the instruction" | +| 16004 | 0x3E84 | `ExpectedAddressTreeInfo` | "Expected address Merkle context to be provided" | +| 16005 | 0x3E85 | `ExpectedAddressRootIndex` | "Expected address root index to be provided" | +| 16006 | 0x3E86 | `ExpectedData` | "Accounts with a specified input are expected to have data" | +| 16007 | 0x3E87 | `ExpectedDiscriminator` | "Accounts with specified data are expected to have a discriminator" | +| 16008 | 0x3E88 | `ExpectedHash` | "Accounts with specified data are expected to have a hash" | +| 16009 | 0x3E89 | `ExpectedLightSystemAccount(String)` | "Expected the `{0}` light account to be provided" | +| 16010 | 0x3E8A | `ExpectedMerkleContext` | "`mut` and `close` accounts are expected to have a Merkle context" | +| 16011 | 0x3E8B | `ExpectedRootIndex` | "Expected root index to be provided" | +| 16012 | 0x3E8C | `TransferFromNoInput` | "Cannot transfer lamports from an account without input" | +| 16013 | 0x3E8D | `TransferFromNoLamports` | "Cannot transfer from an account without lamports" | +| 16014 | 0x3E8E | `TransferFromInsufficientLamports` | "Account, from which a transfer was attempted, has insufficient amount of lamports" | +| 16015 | 0x3E8F | `TransferIntegerOverflow` | "Integer overflow resulting from too large resulting amount" | +| 16016 | 0x3E90 | `Borsh` | "Borsh error." | +| 16017 | 0x3E91 | `FewerAccountsThanSystemAccounts` | "Fewer accounts than number of system accounts." | +| 16018 | 0x3E92 | `InvalidCpiSignerAccount` | "InvalidCpiSignerAccount" | +| 16019 | 0x3E93 | `MissingField(String)` | "Missing meta field: {0}" | +| 16020 | 0x3E94 | `OutputStateTreeIndexIsNone` | "Output state tree index is none. Use an CompressedAccountMeta type with output tree index to initialize or update accounts." | +| 16021 | 0x3E95 | `InitAddressIsNone` | "Address is none during initialization" | +| 16022 | 0x3E96 | `InitWithAddressIsNone` | "Address is none during initialization with address" | +| 16023 | 0x3E97 | `InitWithAddressOutputIsNone` | "Output is none during initialization with address" | +| 16024 | 0x3E98 | `MetaMutAddressIsNone` | "Address is none during meta mutation" | +| 16025 | 0x3E99 | `MetaMutInputIsNone` | "Input is none during meta mutation" | +| 16026 | 0x3E9A | `MetaMutOutputLamportsIsNone` | "Output lamports is none during meta mutation" | +| 16027 | 0x3E9B | `MetaMutOutputIsNone` | "Output is none during meta mutation" | +| 16028 | 0x3E9C | `MetaCloseAddressIsNone` | "Address is none during meta close" | +| 16029 | 0x3E9D | `MetaCloseInputIsNone` | "Input is none during meta close" | +| 16031 | 0x3E9F | `CpiAccountsIndexOutOfBounds(usize)` | "CPI accounts index out of bounds: {0}" | +| 16032 | 0x3EA0 | `InvalidCpiContextAccount` | "Invalid CPI context account" | +| 16033 | 0x3EA1 | `InvalidSolPoolPdaAccount` | "Invalid SolPool PDA account" | +| 16034 | 0x3EA2 | `InvalidCpiAccountsOffset` | "CpigAccounts accounts slice starts with an invalid account. It should start with LightSystemProgram SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7." | + diff --git a/zk-compression-docs/mintlify-docs/resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed.mdx b/zk-compression-docs/mintlify-docs/resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed.mdx new file mode 100644 index 0000000..5cc8326 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/error-cheatsheet/debug-0x179b-6043-proofverificationfailed.mdx @@ -0,0 +1,45 @@ +--- +title: "Debug ProofVerificationFailed (0x179b)" +description: "Common cause and debug steps for ProofVerificationFailed (0x179B / 6043)" +--- + +### Description + +You're passing an invalid proof. The proof provided cannot be verified against the expected state. + + +
+ For help with debugging use the [MCP Configuration](/learn/ai-tools-guide#mcp) or AskDevin via + + Ask DeepWiki + +
+
+ +### Common causes and Debug Steps + + +For a complete example of proper client+on chain flows, see the [Counter Program](https://github.com/Lightprotocol/program-examples/blob/main/counter/anchor/programs/counter/src/lib.rs#L26). + + + + +Compare client vs on chain seeds/addresses. Both should be identical. + +```typescript +// Client - log seeds/address used to request proof +console.log("Client seeds:", seeds, "address:", address); +``` + +```rust +// Onchain - log seeds/address +msg!("Program seeds: {:?}, address: {:?}", seeds, address); +``` + + + +### Still having issues? We're here to help! + +- Reach out on [Discord](https://discord.com/invite/CYvjBgzRFP) for support +- Share the exact error code and a reproducer (GitHub repo / gist) + diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods.mdx new file mode 100644 index 0000000..33ba4b0 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods.mdx @@ -0,0 +1,221 @@ +--- +title: JSON RPC Methods +description: Overview of all available ZK compression JSON RPC endpoints on Solana, best practices, and error codes. +sidebarTitle: "Overview" +--- + + +[Helius Labs](https://github.com/helius-labs) maintains the canonical RPC API and [Photon indexer implementation](https://github.com/helius-labs/photon). + + +Interact with compressed accounts directly with the ZK Compression JSON RPC API. It's a thin wrapper extending [Solana's web3.js `Connection` class](https://solana-labs.github.io/solana-web3.js/classes/Connection.html) with compression-related endpoints. + +The API exposed by the indexer closely mirrors existing RPC calls, with one-to-one mapping: + +| Solana RPC | Photon RPC Calls | +| :---------------------- | :------------------------------- | +| getAccountInfo | getCompressedAccount | +| getBalance | getCompressedBalance | +| getTokenAccountsByOwner | getCompressedTokenAccountsByOwner | +| getProgramAccounts | getCompressedAccountsByOwner | + +### Creating an RPC Connection + + + +
+ Ask anything about the ZK Compression RPC API via + + Ask DeepWiki + +
+
+ +Connect to a specific RPC endpoint + + + +```typescript highlight={6-7} +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://mainnet.helius-rpc.com?api-key="; +const PHOTON_ENDPOINT = RPC_ENDPOINT; +const PROVER_ENDPOINT = RPC_ENDPOINT; +const connection: Rpc = createRpc(RPC_ENDPOINT, PHOTON_ENDPOINT, PROVER_ENDPOINT) + +console.log("connection", connection); +``` + + + +```typescript highlight={6-7} +import { + Rpc, + createRpc, +} from "@lightprotocol/stateless.js"; + +// Helius exposes Solana and Photon RPC endpoints through a single URL +const RPC_ENDPOINT = "https://devnet.helius-rpc.com?api-key="; +const PHOTON_ENDPOINT = RPC_ENDPOINT; +const PROVER_ENDPOINT = RPC_ENDPOINT; +const connection: Rpc = createRpc(RPC_ENDPOINT, PHOTON_ENDPOINT, PROVER_ENDPOINT) + +console.log("connection", connection); +``` + + + +#### Best Practices + +| Best Practice | Description | +|:----------------------|:----------------------------------------------------------------------------------------------------------------| +| **Commitment Levels**| Use appropriate commitment levels: `processed` (fastest), `confirmed` (balanced), `finalized` (most reliable) | +| **Rate Limiting** | Implement retry logic and respect rate limits. Public endpoints: 100 req/s, Private: 1000+ req/s | +| **Batch Requests** | Use batch requests when possible to improve efficiency and reduce API calls | +| **Caching** | Cache frequently accessed data to reduce API calls and improve performance | + +#### Error Codes + +| Code | Message | Description | +| :------ | :-------------------- | :-------------------------------------------- | +| -32600 | Invalid Request | The JSON sent is not a valid Request object | +| -32601 | Method not found | The method does not exist / is not available | +| -32602 | Invalid params | Invalid method parameter(s) | +| -32603 | Internal error | Internal JSON-RPC error | +| -32000 | Account not found | The compressed account was not found | +| -32001 | Invalid account hash | The provided account hash is invalid | + +### Mainnet ZK Compression JSON RPC Methods + + + + Retrieves information about a specific compressed account by its address or hash. + + + Returns all compressed accounts owned by a specific address. + + + Retrieves the balance of a compressed account. + + + Gets the total balance of all compressed accounts owned by an address. + + + Lists all holders of a specific compressed token mint. + + + Retrieves the token balance of a compressed token account. + + + Returns all compressed token accounts delegated to a specific address. + + + Lists all compressed token accounts owned by a specific address. + + + Retrieves all token balances for compressed accounts owned by an address. + + + Returns signatures for transactions involving a compressed account. + + + Retrieves signatures for transactions involving a specific address. + + + Returns signatures for transactions where an address is the owner. + + + Lists signatures for transactions involving tokens owned by an address. + + + Returns the health status of the compression indexer. + + + Retrieves the current slot of the compression indexer. + + + Returns the most recent transaction signatures related to compression. + + + Retrieves recent non-voting transaction signatures. + + + Retrieves multiple compressed accounts in a single request. + + + Returns proofs that the new addresses are not taken already and can be created. + + + Returns transaction details with additional compression-related information. + + + Retrieves a validity proof for compressed data. + + diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedaccount.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedaccount.mdx new file mode 100644 index 0000000..93ce972 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedaccount.mdx @@ -0,0 +1,211 @@ +--- +openapi: post /getCompressedAccount +description: "Retrieve compressed account information by address or hash. RPC method guide with use cases, tips and examples." +--- + +The `getCompressedAccount` RPC method retrieves information about a specific compressed account using either its address or hash. Information includes the compressed account state, balance, and metadata. + + +You can test this methods via the OpenAPI example or custom examples below. + + +**Common Use Cases** + +- **Checking Compressed Account Balance:** Retrieve the lamport balance of any compressed account. +- **Verifying Account Existence:** Check if a compressed account exists and has been initialized with data or lamports. +- **Inspecting Compressed Account Data:** Access the stored data within a compressed account, including program-specific state. +- **Identifying Account Owner:** Determine which program owns a compressed account to understand how its data should be interpreted. +- **Merkle Tree Information:** Get the merkle tree context including leaf index and sequence number for proof generation. + +**Parameters** + +1. `address` (string, optional): The base-58 encoded address of the compressed account to query. +2. `hash` (string, optional): The base-58 encoded 32-byte hash of the compressed account. + +**Note:** Either `address` OR `hash` must be provided, but not both. If neither is provided, the request will fail. + +**Response** + +Returns compressed account information directly, or null if account not found: + +- `hash` (string): The 32-byte hash of the compressed account as a base-58 string. +- `owner` (string): The base-58 encoded public key of the program that owns this account. +- `lamports` (number): The number of lamports owned by the account. +- `tree` (string): The public key of the merkle tree storing this account. +- `leafIndex` (number): The leaf index of this account in the merkle tree. +- `seq` (number): The sequence number of this account. +- `slotCreated` (number): The slot when this account was created. +- `data` (object, optional): The account data object containing: + - `discriminator` (BN): The account discriminator as BN object. + - `data` (string): Base64 encoded account data. + - `dataHash` (string): The 32-byte hash of the account data. + +**Developer Tips** + +- **Address vs Hash**: Use `address` when you know the account's derived address, and `hash` when you have the specific hash from a previous query or transaction +- **Hash Format**: When using the `hash` parameter, pass the hash value directly as returned from other RPC methods (like `getCompressedAccountsByOwner`). Hash values must be used immediately after retrieval for accurate results +- **Error Handling**: Always check if the returned value is `null` before accessing account properties, as the account may not exist +- **Merkle Context**: The returned `leafIndex`, `tree`, and `seq` fields are crucial for generating merkle proofs when updating or transferring compressed accounts +- **Data Interpretation**: The `data` field contains program-specific information. Use the `discriminator` to identify the account type and parse the `data` accordingly +- **Rate Limits**: Be mindful of RPC rate limits when making frequent queries. Consider batching requests when possible +- **Hash Verification**: The `dataHash` field allows you to verify the integrity of the account data without storing the full data on-chain + +**Examples** + +The below examples work - just make sure you installed the dependencies. + + + +```bash +npm install @lightprotocol/stateless.js @solana/web3.js +``` + +**For Rust examples**: Create a Cargo project with these dependencies in `Cargo.toml`: + +``` +[dependencies] +tokio = { version = "1.0", features = ["full"] } +anyhow = "1.0" +solana-sdk = "1.18" +# light-client = "0.1" # Add when available +serde_json = "1.0" +``` + + +**Example: Fetching Compressed Account by Address** + +Let's fetch information for a compressed account using its address. + + +```bash cURL +curl -X POST https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getCompressedAccount", + "params": { + "address": "11111113R2cuenjG5nFubqX9Wzuukdin2YfGQVzu5" + } + }' +``` + +```typescript TypeScript expandable +import { Rpc, createRpc, createBN254, BN254, CompressedAccountWithMerkleContext } from '@lightprotocol/stateless.js'; + +async function getCompressedAccountInfo(): Promise { + const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' + ); + + try { + // Query by address + const address: BN254 = createBN254('11111113R2cuenjG5nFubqX9Wzuukdin2YfGQVzu5', 'base58'); + const accountInfo: CompressedAccountWithMerkleContext | null = + await rpc.getCompressedAccount(address); + + if (!accountInfo) { + console.log('Compressed account not found.'); + return; + } + + console.log('Compressed Account Info:', { + hash: accountInfo.hash, + owner: accountInfo.owner, + lamports: accountInfo.lamports, + tree: accountInfo.tree, + leafIndex: accountInfo.leafIndex, + sequence: accountInfo.seq, + slotCreated: accountInfo.slotCreated, + dataHash: accountInfo.data?.dataHash, + }); + } catch (error: unknown) { + console.error('Error fetching compressed account:', error); + } +} + +getCompressedAccountInfo(); +``` + +**Rust Client**: `light-client` v0.14.0 is available on crates.io. Use `LightClient` for the current stable API. + +```rust Rust expandable +// Current API: light-client 0.14.0 +use light_client::rpc::LightClient; +use solana_sdk::bs58; +use anyhow::Result; + +#[tokio::main] +async fn main() -> Result<()> { + let client = LightClient::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY".to_string()).await?; + + // Query compressed account by address + let address = "11111113R2cuenjG5nFubqX9Wzuukdin2YfGQVzu5"; + + match client.get_compressed_account(Some(address), None).await? { + Some(account_info) => { + println!("Compressed Account Info:"); + println!(" Hash: {}", account_info.hash); + println!(" Owner: {}", account_info.owner); + println!(" Lamports: {}", account_info.lamports); + println!(" Tree: {}", account_info.tree); + println!(" Leaf Index: {}", account_info.leaf_index); + } + None => { + println!("Compressed account not found."); + } + } + + Ok(()) +} +``` + + + +**Example: Fetching Compressed Account by Hash** + +You can also query a compressed account using its hash. + +```typescript TypeScript expandable +import { Rpc, createRpc, bn } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +async function getCompressedAccountByHash(): Promise { + const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' + ); + + try { + // First, get compressed accounts to obtain a real hash + const owner = new PublicKey('4LhEEtzAhM6wEXJR2YQHPEs79UEx8e6HncmeHbqbW1w1'); + const accounts = await rpc.getCompressedAccountsByOwner(owner); + + if (accounts.items.length === 0) { + console.log('No compressed accounts found'); + return; + } + + // Query by hash using a real hash from the first account + const hash = bn(accounts.items[0].hash); + const accountInfo = await rpc.getCompressedAccount(undefined, hash); + + if (accountInfo) { + console.log('Compressed Account Info:', { + hash: accountInfo.hash, + owner: accountInfo.owner, + lamports: accountInfo.lamports, + tree: accountInfo.tree, + leafIndex: accountInfo.leafIndex + }); + } else { + console.log('Compressed account not found.'); + } + } catch (error: unknown) { + console.error('Error:', error); + } +} + +getCompressedAccountByHash(); +``` diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedaccountsbyowner.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedaccountsbyowner.mdx new file mode 100644 index 0000000..a371e75 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedaccountsbyowner.mdx @@ -0,0 +1,269 @@ +--- +openapi: post /getCompressedAccountsByOwner +description: "Retrieve all compressed accounts owned by a specific address. RPC method guide with use cases, tips and examples." +--- + + +The`getCompressedAccountsByOwner` RPC method returns all compressed accounts owned by a specific address, with support for filtering, pagination, and data slicing. + + +You can test this method via the OpenAPI example or custom examples below. + + +**Common Use Cases** + +- **Portfolio Discovery**: Find all compressed accounts for a wallet +- **Token Account Enumeration**: Discover user's compressed token holdings +- **Account Migration**: Identify accounts to migrate from regular to compressed +- **Balance Aggregation**: Calculate total holdings across all accounts + +**Parameters** + +1. `owner` (PublicKey, required): Base58-encoded public key of the account owner to query compressed accounts for. +2. `options` (object, optional): Configuration object for filtering and pagination: + - `filters` (array, optional): Array of filter objects to narrow results by specific criteria + - `dataSlice` (object, optional): Slice of account data to return with `offset` and `length` fields + - `cursor` (string, optional): Cursor for pagination from previous response to fetch next page + - `limit` (BN, optional): Maximum number of accounts to return (use `bn()` helper) + +**Note**: All options parameters are optional. Without filters, returns all compressed accounts for the owner. + +**Response** + +The response contains a paginated list of compressed accounts: + +- `items` (array): Array of compressed account objects with merkle context + - `hash` (string): Unique hash identifying the account for merkle proof generation + - `address` (string, optional): Account address if available + - `lamports` (number): Account balance in lamports + - `owner` (string): Public key of the account owner + - `data` (object): Account data information including discriminator and data hash + - `tree` (string): Public key of the merkle tree storing this account + - `leafIndex` (number): Position of account in the merkle tree + - `seq` (number): Sequence number for account ordering + - `slotCreated` (number): Slot when account was created +- `cursor` (string | null): Pagination cursor for next batch, null if no more results + +**Developer Tips** + +- **Pagination Strategy**: Use cursor-based pagination for owners with many accounts to avoid timeouts and ensure consistent results +- **Data Slicing Optimization**: Implement data slicing when you only need account metadata to reduce response size and improve performance +- **Empty Response Handling**: Handle cases gracefully where new addresses have no compressed accounts - this is normal behavior +- **Caching Considerations**: Cache results appropriately as compressed account states can change with each transaction +- **Batch Size**: Start with smaller batch sizes (50-100) and adjust based on response times and data needs + +**Troubleshooting** + + + + +**Owner has no compressed accounts** + +This is normal for new addresses or those that haven't used compression: + +```typescript +const accounts = await rpc.getCompressedAccountsByOwner(owner); + +if (accounts.items.length === 0) { + console.log("No compressed accounts found for this owner"); + console.log("Create compressed accounts first using createAccountWithLamports or token operations"); +} +``` + + + +**Too many accounts returned at once** + +Use pagination and data slicing to reduce response size: + +``` +const accounts = await rpc.getCompressedAccountsByOwner(owner, { + limit: bn(50), // Smaller batch size + dataSlice: { // Reduce data per account + offset: 0, + length: 10 + } +}); +``` + + + +**Examples** + +The below examples work - just make sure you installed the dependencies. + + + +```bash +npm install @lightprotocol/stateless.js @solana/web3.js +``` + +**For Rust examples**: Requires `light-client`, `solana-sdk`, `anyhow`, and `tokio` crates. See Rust example comments for setup details. + + +**Example: Get All Compressed Accounts** + + + +```typescript expandable +import { createRpc, Rpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' +); + +async function getAllCompressedAccounts() { + const owner = new PublicKey('OWNER_ADDRESS_HERE'); + const result = await rpc.getCompressedAccountsByOwner(owner); + + console.log(\`Found ${result.items.length} compressed accounts\`); + + result.items.forEach((account, index) => { + console.log(\`Account ${index + 1}:\`); + console.log(\` Hash: ${account.hash.toString()}\`); + console.log(\` Lamports: ${account.lamports.toString()}\`); + console.log(\` Owner: ${account.owner.toBase58()}\`); + }); + + return result; +} + +getAllCompressedAccounts(); +``` + + + +```bash +curl -X POST https://devnet.helius-rpc.com?api-key=YOUR_API_KEY \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getCompressedAccountsByOwner", + "params": { + "owner": "OWNER_PUBKEY_HERE" + } + }' +``` + + + + + **Rust Client**: `light-client` v0.14.0 is available on crates.io. Use `LightClient` for the current stable API. + + +```rust expandable +// Current API: light-client 0.14.0 +use light_client::rpc::LightClient; +use solana_sdk::pubkey::Pubkey; +use std::str::FromStr; +use anyhow::Result; + +#[tokio::main] +async fn main() -> Result<()> { + let client = LightClient::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY".to_string()).await?; + + // Query compressed accounts by owner + let owner = Pubkey::from_str("OWNER_PUBKEY_HERE")?; + + match client.get_compressed_accounts_by_owner(&owner, None).await? { + response => { + println!("Found {} compressed accounts", response.value.items.len()); + + for (index, account) in response.value.items.iter().enumerate() { + println!("Account {}:", index + 1); + println!(" Hash: {}", account.hash); + println!(" Lamports: {}", account.lamports); + println!(" Owner: {}", account.owner); + println!(" Tree: {}", account.tree); + println!(" Leaf Index: {}", account.leaf_index); + } + } + } + + Ok(()) +} +``` + + + +**Example: Paginated Account Discovery with Balance Aggregation** + +```typescript TypeScript expandable +import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' +); + +async function getAllAccountsPaginated(owner: PublicKey) { + let allAccounts = []; + let cursor = undefined; + let totalBalance = bn(0); + const batchSize = 100; + + do { + const batch = await rpc.getCompressedAccountsByOwner(owner, { + cursor, + limit: bn(batchSize) + }); + + allAccounts.push(...batch.items); + cursor = batch.cursor; + + // Calculate running balance + batch.items.forEach(account => { + totalBalance = totalBalance.add(account.lamports); + }); + + console.log(\`Fetched ${batch.items.length} accounts, total: ${allAccounts.length}\`); + + // Rate limiting + await new Promise(resolve => setTimeout(resolve, 100)); + + } while (cursor); + + console.log(\`Total compressed accounts: ${allAccounts.length}\`); + console.log(\`Total balance: ${totalBalance.toString()} lamports\`); + return { accounts: allAccounts, totalBalance }; +} + +// Usage +const owner = new PublicKey('OWNER_ADDRESS_HERE'); +getAllAccountsPaginated(owner); +``` + +**Example: Filter by Data Slice** + +```typescript expandable +import { createRpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const rpc = createRpc("https://devnet.helius-rpc.com?api-key="); +const owner = new PublicKey("OWNER_PUBKEY_HERE"); + +async function getAccountsWithDataSlice() { + const accounts = await rpc.getCompressedAccountsByOwner(owner, { + dataSlice: { + offset: 0, + length: 32 // First 32 bytes only + } + }); + + console.log(\`Found ${accounts.items.length} accounts with data slice\`); + + accounts.items.forEach((account, index) => { + console.log(\`Account ${index + 1}:\`); + console.log(\` Hash: ${account.hash.toString()}\`); + console.log(\` Data length: ${account.data?.data?.length || 0} bytes\`); + }); + + return accounts; +} + +getAccountsWithDataSlice(); +``` diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedbalance.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedbalance.mdx new file mode 100644 index 0000000..ea0370a --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedbalance.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressedBalance +description: "Retrieve the lamport balance for a specific compressed account by address or hash. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedbalancebyowner.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedbalancebyowner.mdx new file mode 100644 index 0000000..9433632 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedbalancebyowner.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressedBalanceByOwner +description: "Query the total compressed token balance for a specific account owner. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedminttokenholders.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedminttokenholders.mdx new file mode 100644 index 0000000..dee47d9 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedminttokenholders.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressedMintTokenHolders +description: "Retrieve owner balances for a given mint in descending order. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountbalance.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountbalance.mdx new file mode 100644 index 0000000..dca7a37 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountbalance.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressedTokenAccountBalance +description: "Retrieve the balance for a given token account by address or hash. Overview with RPC method guide" +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountbydelegate.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountbydelegate.mdx new file mode 100644 index 0000000..a3744a0 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountbydelegate.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressedTokenAccountsByDelegate +description: "Retrieve compressed token accounts that are partially or fully delegated to a given delegate. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountsbyowner.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountsbyowner.mdx new file mode 100644 index 0000000..f9b7663 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenaccountsbyowner.mdx @@ -0,0 +1,292 @@ +--- +openapi: post /getCompressedTokenAccountsByOwner +description: "Retrieve compressed token accounts owned by a specific address. RPC method guide with use cases, tips and examples." +--- + +The`getCompressedTokenAccountsByOwner` RPC method retrieves all compressed token accounts owned by a specific public key. The method supports mint filtering to query specific tokens, cursor-based pagination for handling large result sets, and returns parsed token data with merkle context for verification. + +You can test this method via the OpenAPI example or custom examples below. + +**Common Use Cases** + +- **Token Portfolio Display**: Show all compressed tokens owned by a wallet address +- **Balance Aggregation**: Calculate total token holdings across multiple compressed accounts +- **Token Transfer Setup**: Find available token accounts to use as transfer sources +- **Wallet Integration**: Support compressed token discovery in wallet interfaces +- **DeFi Protocol Integration**: Query user token holdings for lending, trading, or staking + +**Parameters** + +1. `owner` (PublicKey, required): Base58-encoded public key of the account owner to query token accounts for. +2. `options` (object, optional): Configuration object containing filtering and pagination parameters: + - `mint` (PublicKey, optional): Base58-encoded mint address to filter results by specific token + - `cursor` (string, optional): Pagination cursor from previous response for fetching next page + - `limit` (BN, optional): Maximum number of accounts to return (use `bn()` helper function) + +**Note**: All parameters are optional within the options object. Without filters, returns all compressed token accounts for the owner. + +**Response** + +The response contains a paginated list of compressed token accounts: + +- `items` (array): Array of compressed token account objects + - `compressedAccount` (object): Compressed account data and merkle proof context + - `address` (string): Compressed account address (if available) + - `owner` (string): Account owner public key + - `lamports` (number): Account lamports + - `data` (object): Account data information + - `hash` (string): Account hash for merkle proof verification + - `parsed` (object): Parsed token-specific information + - `mint` (PublicKey): Token mint address + - `owner` (PublicKey): Token account owner + - `amount` (BN): Token amount as BN object - use .toString() for exact value + - `delegate` (PublicKey | null): Delegate address if set, null otherwise + - `state` (number): Account state (0=initialized, 1=frozen, etc.) + - `tlv` (Buffer | null): Type-Length-Value extension data if present +- `cursor` (string | null): Pagination cursor for next batch, null if no more results + +**Developer Tips** + +- **BN Object Handling**: The `amount` field is a BN object - use `.toString()` for exact values or `.toNumber()` for small amounts +- **State Values**: The `state` field is a numeric enum (0=initialized, 1=frozen, etc.) not a string +- **Parameter Types**: Use `bn()` helper function for the `limit` parameter, not raw numbers +- **Pagination**: Use cursor-based pagination for large token portfolios to avoid timeouts +- **Performance**: Filter by mint address when querying specific tokens to reduce response size +- **Empty Responses**: Handle cases where owners have no compressed token accounts gracefully + +**Examples** + +The below examples work - just make sure you installed the dependencies. + + +```bash +npm install @lightprotocol/stateless.js +``` + + +**Example: Get All Token Accounts** + + + +```bash expandable +curl -X POST https://devnet.helius-rpc.com?api-key=YOUR_API_KEY \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getCompressedTokenAccountsByOwner", + "params": { + "owner": "OWNER_PUBKEY_HERE" + } + }' +``` + + +```typescript expandable +import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' +); + +async function getAllTokenAccounts(): Promise { + const owner = new PublicKey('OWNER_ADDRESS_HERE'); + const result = await rpc.getCompressedTokenAccountsByOwner(owner); + + console.log(\`Found ${result.items.length} compressed token accounts\`); + + result.items.forEach((account, index) => { + console.log(\`Token Account ${index + 1}:\`); + console.log(\` Mint: ${account.parsed.mint.toBase58()}\`); + console.log(\` Amount: ${account.parsed.amount.toString()}\`); + console.log(\` Owner: ${account.parsed.owner.toBase58()}\`); + console.log(\` State: ${account.parsed.state}\`); + }); + + return result; +} + +getAllTokenAccounts(); +``` + + + + + **Rust Client**: `light-client` v0.14.0 is available on crates.io. Use `LightClient` for the current stable API. + + +```rust expandable +// Current API: light-client 0.14.0 +use light_client::rpc::LightClient; +use solana_sdk::pubkey::Pubkey; +use std::str::FromStr; +use anyhow::Result; + +#[tokio::main] +async fn main() -> Result<()> { + let client = LightClient::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY".to_string()).await?; + + // Query compressed token accounts by owner + let owner = Pubkey::from_str("OWNER_PUBKEY_HERE")?; + + match client.get_compressed_token_accounts_by_owner(&owner, None).await? { + response => { + println!("Found {} compressed token accounts", response.value.items.len()); + + for (index, account) in response.value.items.iter().enumerate() { + println!("Token Account {}:", index + 1); + println!(" Mint: {}", account.parsed.mint); + println!(" Amount: {}", account.parsed.amount); + println!(" Owner: {}", account.parsed.owner); + println!(" State: {}", account.parsed.state); + } + } + } + + Ok(()) +} +``` + + + +**Example: Filter by Specific Token Mint** + +```typescript TypeScript expandable +import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' +); + +async function getTokenAccountsByMint(): Promise { + const owner = new PublicKey('OWNER_ADDRESS_HERE'); + const mint = new PublicKey('TOKEN_MINT_HERE'); + + const result = await rpc.getCompressedTokenAccountsByOwner(owner, { + mint + }); + + if (result.items.length === 0) { + console.log('No compressed token accounts found for this mint'); + return; + } + + let totalBalance = bn(0); + result.items.forEach((account, index) => { + const amount = account.parsed.amount; + totalBalance = totalBalance.add(amount); + + console.log(\`Account ${index + 1}:\`); + console.log(\` Amount: ${amount.toString()}\`); + console.log(\` Hash: ${account.compressedAccount.hash}\`); + }); + + console.log(\`Total Balance: ${totalBalance.toString()}\`); + + return result; +} + +getTokenAccountsByMint(); +``` + +**Example: Paginated Token Discovery** + +```typescript TypeScript expandable +import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' +); + +async function getAllTokenAccountsPaginated(owner: PublicKey) { + let allAccounts = []; + let cursor = undefined; + const batchSize = 50; // Smaller batch size for DevNet + + do { + const batch = await rpc.getCompressedTokenAccountsByOwner(owner, { + cursor, + limit: bn(batchSize) + }); + + allAccounts.push(...batch.items); + cursor = batch.cursor; + + console.log(\`Fetched ${batch.items.length} token accounts, total: ${allAccounts.length}\`); + + // Rate limiting for DevNet + await new Promise(resolve => setTimeout(resolve, 100)); + + } while (cursor); + + // Group by mint + const accountsByMint = new Map(); + allAccounts.forEach(account => { + const mintKey = account.parsed.mint.toBase58(); + if (!accountsByMint.has(mintKey)) { + accountsByMint.set(mintKey, []); + } + accountsByMint.get(mintKey).push(account); + }); + + console.log(\`Total compressed token accounts: ${allAccounts.length}\`); + console.log(\`Unique token mints: ${accountsByMint.size}\`); + + return { allAccounts, accountsByMint }; +} + +// Usage +const owner = new PublicKey('OWNER_ADDRESS_HERE'); +getAllTokenAccountsPaginated(owner); +``` + +**Example: Calculate Token Portfolio Value** + +```typescript TypeScript expandable +import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' +); + +async function calculateTokenPortfolio(): Promise> { + const owner = new PublicKey('OWNER_ADDRESS_HERE'); + const tokenAccounts = await rpc.getCompressedTokenAccountsByOwner(owner); + + if (tokenAccounts.items.length === 0) { + console.log('No compressed token accounts found'); + return; + } + + const portfolio = new Map(); + + tokenAccounts.items.forEach(account => { + const mintKey = account.parsed.mint.toBase58(); + const amount = account.parsed.amount; + + if (portfolio.has(mintKey)) { + const existing = portfolio.get(mintKey); + portfolio.set(mintKey, existing.add(amount)); + } else { + portfolio.set(mintKey, amount); + } + }); + + console.log('Compressed Token Portfolio:'); + portfolio.forEach((balance, mint) => { + console.log(\` ${mint}: ${balance.toString()}\`); + }); + + return portfolio; +} + +calculateTokenPortfolio(); +``` diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenbalancesbyowner.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenbalancesbyowner.mdx new file mode 100644 index 0000000..a61f9df --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressedtokenbalancesbyowner.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressedTokenBalancesByOwner +description: "Retrieves all token balances for compressed accounts owned by an address. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforaccount.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforaccount.mdx new file mode 100644 index 0000000..a921706 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforaccount.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressionSignaturesForAccount +description: "Retrieve the signatures of the transactions that closed or opened a compressed account with the given hash. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforaddress.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforaddress.mdx new file mode 100644 index 0000000..6db450a --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforaddress.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressionSignaturesForAddress +description: "Retrieve the signatures of the transactions that closed or opened a compressed account with the given address. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforowner.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforowner.mdx new file mode 100644 index 0000000..05f1b8b --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesforowner.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressionSignaturesForOwner +description: "Retrieve the signatures of the transactions that have modified an owner's compressed accounts. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesfortokenowner.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesfortokenowner.mdx new file mode 100644 index 0000000..774abbc --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getcompressionsignaturesfortokenowner.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getCompressionSignaturesForTokenOwner +description: "Retrieve the signatures of the transactions that have modified an owner's compressed token accounts. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getindexerhealth.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getindexerhealth.mdx new file mode 100644 index 0000000..360a0aa --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getindexerhealth.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getIndexerHealth +description: "Retrieve an error if the indexer is stale by more than a configurable number of blocks. Otherwise, it returns ok. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getindexerslot.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getindexerslot.mdx new file mode 100644 index 0000000..e6d08de --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getindexerslot.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getIndexerSlot +description: "Retrieve the slot of the last block indexed by the indexer. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getlatestcompressionsignatures.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getlatestcompressionsignatures.mdx new file mode 100644 index 0000000..69ea3f8 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getlatestcompressionsignatures.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getLatestCompressionSignatures +description: "Retrieve the signatures of the latest transactions that used the compression program. This is a paginated endpoint. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getlatestnonvotingsignatures.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getlatestnonvotingsignatures.mdx new file mode 100644 index 0000000..f89c179 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getlatestnonvotingsignatures.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getLatestNonVotingSignatures +description: "Retrieve the signatures of the latest transactions that are not voting transactions. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getmultiplecompressedaccounts.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getmultiplecompressedaccounts.mdx new file mode 100644 index 0000000..2c8e219 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getmultiplecompressedaccounts.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getMultipleCompressedAccounts +description: "Retrieve multiple compressed accounts with the given addresses or hashes. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getmultiplenewaddressproofs.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getmultiplenewaddressproofs.mdx new file mode 100644 index 0000000..63594de --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getmultiplenewaddressproofs.mdx @@ -0,0 +1,4 @@ +--- +openapi: post /getMultipleNewAddressProofs +description: "Retrieve proofs that the new addresses are not taken already and can be created. Overview with RPC method guide." +--- diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/gettransactionwithcompressioninfo.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/gettransactionwithcompressioninfo.mdx new file mode 100644 index 0000000..6927874 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/gettransactionwithcompressioninfo.mdx @@ -0,0 +1,279 @@ +--- +openapi: post /getTransactionWithCompressionInfo +description: "Retrieve the transaction data for the transaction with the given signature along with parsed compression info. RPC method guide with use cases, tips and examples." +--- + +The`getTransactionWithCompressionInfo` RPC method returns transaction data along with compression information showing which compressed accounts were opened (created) and closed (consumed) during the transaction. This method helps with transaction analysis, account lifecycle tracking, and debugging of compression operations. + + +You can test this method via the OpenAPI example or custom examples below. + + +**Common Use Cases** + +- **Transaction Analysis**: Understand what compressed accounts were affected by a transaction +- **Account Lifecycle Tracking**: Monitor when compressed accounts are created and consumed +- **Debugging**: Identify which accounts changed during failed or unexpected transactions +- **Audit Trails**: Track compressed account state changes for compliance + +**Parameters** + +1. `signature` (string, required): Base58-encoded transaction signature to query compression information for. + +**Note**: Only transactions involving compressed accounts will return compression data. Regular Solana transactions return null. + +**Response** + +The response contains compression information and transaction data, or null if transaction not found: + +- `compressionInfo` (object): Contains details about compressed account changes + - `closedAccounts` (array): Compressed accounts consumed (spent) in this transaction + - `account` (object): Complete compressed account data with merkle context + - `maybeTokenData` (object | null): Token data if this is a compressed token account + - `openedAccounts` (array): New compressed accounts created in this transaction + - `account` (object): Complete compressed account data with merkle context + - `maybeTokenData` (object | null): Token data if this is a compressed token account + - `preTokenBalances` (array, optional): Token balances before transaction + - `owner` (PublicKey): Public key of token account owner + - `mint` (PublicKey): Public key of token mint + - `amount` (BN): Token amount as BN object + - `postTokenBalances` (array, optional): Token balances after transaction + - `owner` (PublicKey): Public key of token account owner + - `mint` (PublicKey): Public key of token mint + - `amount` (BN): Token amount as BN object +- `transaction` (object): Standard Solana transaction data + +**Developer Tips** + +- **Compression-only**: This method only works with transactions that involve compressed accounts +- **Real signatures required**: Use actual transaction signatures from compression operations +- **Account lifecycle**: opened = created, closed = consumed/spent in the transaction +- **Token data**: maybeTokenData is null for regular compressed accounts, populated for token accounts +- **Balance tracking**: Use pre/postTokenBalances for detailed token amount changes +- **State analysis**: Compare opened vs closed accounts to understand transaction effects + +**Troubleshooting** + + + +**Invalid or non-existent transaction signature** + +Verify the signature format and check transaction existence: + +```typescript +const result = await connection.getTransactionWithCompressionInfo(signature); + +if (!result) { + console.log('Transaction not found or contains no compression operations'); +} +``` + + +**Transaction exists but has no compression data** + +This method only returns data for transactions involving compressed accounts: + +```typescript +const result = await connection.getTransactionWithCompressionInfo(signature); + +if (!result) { + console.log('Transaction does not involve compressed accounts'); + console.log('Use regular getTransaction for non-compression transactions'); +} +``` + + + +**Transaction has compression info but no account changes shown** + +Some compression operations may not create/consume accounts: + +```typescript +const { compressionInfo } = result; + +if (compressionInfo.openedAccounts.length === 0 && + compressionInfo.closedAccounts.length === 0) { + console.log('Compression transaction with no visible account changes'); + console.log('May be a proof verification or state update operation'); +} +``` + + + +**Examples** + +The below examples work - just make sure you installed the dependencies. + + +```bash +npm install @lightprotocol/stateless.js +``` + + +**Example: Analyze Transaction** + + + +```typescript expandable +import { createRpc, Rpc, CompressedTransaction } from '@lightprotocol/stateless.js'; + +const rpc: Rpc = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' +); + +async function analyzeTransactionCompression(): Promise { + const signature: string = 'TRANSACTION_SIGNATURE_HERE'; + + const result: CompressedTransaction | null = + await rpc.getTransactionWithCompressionInfo(signature); + + if (!result) { + console.log('Transaction not found or has no compression info'); + return; + } + + const { compressionInfo } = result; + + console.log('Transaction Compression Summary:', { + openedCount: compressionInfo.openedAccounts.length, + closedCount: compressionInfo.closedAccounts.length, + hasTokenBalances: !!(compressionInfo.preTokenBalances || compressionInfo.postTokenBalances) + }); + + // Type-safe account analysis + compressionInfo.closedAccounts.forEach((entry, index) => { + console.log(\`Closed Account ${index + 1}:\`, { + hash: entry.account.hash.toString(), + lamports: entry.account.lamports.toString(), + hasTokenData: !!entry.maybeTokenData + }); + }); + + compressionInfo.openedAccounts.forEach((entry, index) => { + console.log(\`Opened Account ${index + 1}:\`, { + hash: entry.account.hash.toString(), + lamports: entry.account.lamports.toString(), + hasTokenData: !!entry.maybeTokenData + }); + }); +} + +analyzeTransactionCompression(); +``` + + +```bash +curl -X POST https://devnet.helius-rpc.com?api-key=YOUR_API_KEY \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getTransactionWithCompressionInfo", + "params": { + "signature": "TRANSACTION_SIGNATURE_HERE" + } + }' +``` + + + + **Rust Client**: `light-client` v0.14.0 is available on crates.io. Use `LightClient` for the current stable API. + + +```rust expandable +// Current API: light-client 0.14.0 +use light_client::rpc::LightClient; +use anyhow::Result; + +#[tokio::main] +async fn main() -> Result<()> { + let client = LightClient::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY".to_string()).await?; + + // Analyze compression transaction + let signature = "TRANSACTION_SIGNATURE_HERE"; + + match client.get_transaction_with_compression_info(signature).await? { + Some(result) => { + let compression_info = &result.compression_info; + + println!("Compression Analysis:"); + println!(" Accounts opened: {}", compression_info.opened_accounts.len()); + println!(" Accounts closed: {}", compression_info.closed_accounts.len()); + + // Show account details + for (i, entry) in compression_info.opened_accounts.iter().enumerate() { + println!(" Opened Account {}:", i + 1); + println!(" Hash: {}", entry.account.hash); + println!(" Lamports: {}", entry.account.lamports); + } + } + None => { + println!("Transaction not found or has no compression info"); + } + } + + Ok(()) +} +``` + + + +**Example: Track Token Balance Changes** + +```Typescript expandable +async function trackTokenBalanceChanges(): Promise { + const connection = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' + ); + + const signature = 'TOKEN_TRANSACTION_SIGNATURE_HERE'; + + const result = await connection.getTransactionWithCompressionInfo(signature); + + if (!result) { + console.log('Transaction not found'); + return; + } + + const { compressionInfo } = result; + + // Analyze token balance changes if available + if (compressionInfo.preTokenBalances && compressionInfo.postTokenBalances) { + console.log('Token Balance Changes:'); + + compressionInfo.preTokenBalances.forEach((preBalance, index) => { + const postBalance = compressionInfo.postTokenBalances![index]; + const change = postBalance.amount.sub(preBalance.amount); + + if (!change.isZero()) { + console.log(\` Owner: ${preBalance.owner.toBase58()}\`); + console.log(\` Mint: ${preBalance.mint.toBase58()}\`); + console.log(\` Change: ${change.toString()}\`); + } + }); + } else { + console.log('No token balance data available for this transaction'); + } + + // Analyze token accounts in opened/closed arrays + const tokenAccountsOpened = compressionInfo.openedAccounts.filter( + entry => entry.maybeTokenData !== null + ); + + const tokenAccountsClosed = compressionInfo.closedAccounts.filter( + entry => entry.maybeTokenData !== null + ); + + console.log(\`Token accounts opened: ${tokenAccountsOpened.length}\`); + console.log(\`Token accounts closed: ${tokenAccountsClosed.length}\`); + + return { + tokenAccountsOpened: tokenAccountsOpened.length, + tokenAccountsClosed: tokenAccountsClosed.length + }; +} + +trackTokenBalanceChanges(); +``` diff --git a/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getvalidityproof.mdx b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getvalidityproof.mdx new file mode 100644 index 0000000..aee8652 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/json-rpc-methods/getvalidityproof.mdx @@ -0,0 +1,225 @@ +--- +openapi: post / +description: "Retrieve a single ZK Proof used by the compression program to verify that the given accounts are valid and the new addresses can be created. RPC method guide with use cases, tips and examples." +--- + +The`getValidityProof` RPC method generates zero-knowledge proofs to verify that the given accounts are valid or the new addresses can be created. This proof is required for any operation on compressed accounts (transfer, approve, decompress, etc.) for on-chain verification of compressed state. + + +You can test this method via the OpenAPI example or custom examples below. + + + +- Proof limits per request are: + - `hashes`: 1, 2, 3, 4, or 8 + - `newAddressesWithTrees` : 1, 2 +- The `newAddresses` param field is supported but deprecated. Please use `newAddressesWithTrees`instead. + + +**Common Use Cases** + +- **Token Transfers:** Generate proofs required for transferring compressed tokens. +- **Account Operations:** Create proofs needed for any compressed account modification. +- **Batch Processing:** Generate proofs for multiple accounts in a single call. +- **State Tree Verification:** Prove account inclusion in the current state tree. +- **Transaction Building:** Obtain proof data needed for compressed transaction instructions. +- **Program Integration:** Get validity proofs for custom program operations on compressed accounts. + +**Parameters** + +1. `hashes` (BN254\[\], required): Array of BN254 objects representing compressed account hashes to generate proofs for. +2. `newAddresses` (BN254\[\], optional): Array of BN254 objects representing new addresses to include in the proof for address tree verification. + +**Response** + +The response contains ValidityProofWithContext data: + +- `compressedProof` (ValidityProof | null): The compressed validity proof object for zero-knowledge verification +- `roots` (BN\[\]): Array of merkle tree roots used in proof generation +- `rootIndices` (number\[\]): Array of indices of the roots in the state tree +- `leafIndices` (number\[\]): Array of indices of the leaves being proven +- `leaves` (BN\[\]): Array of leaf values in the merkle tree +- `treeInfos` (TreeInfo\[\]): Array of information about the state trees used +- `proveByIndices` (boolean\[\]): Array indicating whether to prove by indices for each element + +**Developer Tips** + +- **Fetch Accounts First**: Always get compressed accounts before generating proofs - you need existing account hashes +- **Batch Processing**: You can generate proofs for multiple accounts in a single call. Allowed counts: 1, 2, 3, 4, or 8 accounts +- **Proof Usage**: The proof is required for any operation that modifies compressed accounts (transfers, burns, etc.) +- **Caching**: Validity proofs are only valid for the current state - don't cache them for long periods +- **Error Handling**: If accounts don't exist or have been modified, proof generation will fail +- **Integration**: Use `proof.compressedProof` and `proof.rootIndices` when building transactions +- **State Changes**: After any transaction, previously generated proofs become invalid for those accounts + +**Examples** + +The below examples work - just make sure you installed the dependencies. + + +```bash +npm install @lightprotocol/stateless.js @solana/web3.js +``` + + +**Example: Generate Validity Proof** + +Generate a validity proof for compressed accounts. + + + +```typescript expandable +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('\nProof ready for compressed transactions'); + + } catch (error: unknown) { + console.error('Error generating validity proof:', error); + } +} + +generateValidityProof(); +``` + + + +```bash +# Use account hashes from getCompressedAccountsByOwner +curl -X POST https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getValidityProof", + "params": { + "hashes": [ + "ACCOUNT_HASH_1", + "ACCOUNT_HASH_2" + ] + } + }' +``` + + + +**Rust Client**: `light-client` v0.14.0 is available on crates.io. Use `LightClient` for the current stable API. + + +```rust expandable +use light_client::rpc::LightClient; +use solana_sdk::pubkey::Pubkey; +use std::str::FromStr; +use anyhow::Result; + +#[tokio::main] +async fn main() -> Result<()> { + let client = LightClient::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY".to_string()).await?; + + // Get compressed accounts first + let owner = "OWNER_PUBLIC_KEY_HERE"; + let accounts = client.get_compressed_accounts_by_owner(owner).await?; + + if accounts.items.is_empty() { + println!("No compressed accounts found"); + return Ok(()); + } + + // Generate validity proof for the accounts + let hashes: Vec = accounts.items.iter() + .take(2) + .map(|acc| acc.hash.clone()) + .collect(); + + let validity_proof = client.get_validity_proof(hashes.clone()).await?; + + println!("Validity Proof Generated:"); + println!(" Accounts: {}", hashes.len()); + println!(" Roots: {}", validity_proof.roots.len()); + println!(" Root Indices: {}", validity_proof.root_indices.len()); + + Ok(()) +} +``` + + + +**Example: Proof Generation for Token Transfer** + +Generate a validity proof for a compressed token transfer operation: + + +```Javascript JavaScript expandable +import { Rpc, createRpc, bn } from '@lightprotocol/stateless.js'; +import { PublicKey } from '@solana/web3.js'; + +async function generateProofForTransfer() { + const connection = createRpc( + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY', + 'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY' + ); + + try { + // Get compressed token accounts + const owner = new PublicKey('OWNER_PUBLIC_KEY_HERE'); + const mint = new PublicKey('TOKEN_MINT_HERE'); + + const tokenAccounts = await connection.getCompressedTokenAccountsByOwner( + owner, + { mint } + ); + + if (tokenAccounts.items.length === 0) { + console.log('No compressed token accounts found'); + return; + } + + // Generate proof for the token accounts (limit to allowed numbers: 1, 2, 3, 4, or 8) + const limitedAccounts = tokenAccounts.items.slice(0, 4); + const hashes = limitedAccounts.map(acc => bn(acc.compressedAccount.hash)); + const validityProof = await connection.getValidityProof(hashes); + + console.log('Validity Proof for Transfer:'); + console.log(\` Token accounts: ${hashes.length}\`); + console.log(\` Roots: ${validityProof.roots.length}\`); + + // This proof is now ready to use with CompressedTokenProgram.transfer() + console.log('\nProof ready for token transfer instruction'); + console.log('Use this with:'); + console.log(' recentValidityProof: validityProof.compressedProof'); + console.log(' recentInputStateRootIndices: validityProof.rootIndices'); + + } catch (error) { + console.error('Error generating proof:', error); + } +} + +generateProofForTransfer(); +``` diff --git a/zk-compression-docs/mintlify-docs/resources/sdks.mdx b/zk-compression-docs/mintlify-docs/resources/sdks.mdx new file mode 100644 index 0000000..6eb0582 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/sdks.mdx @@ -0,0 +1,10 @@ +--- +title: "SDKs" +sidebarTitle: "Overview" +description: "Overview to TypeScript and Rust SDKs for Client and Program Development" +--- + + + + + \ No newline at end of file diff --git a/zk-compression-docs/mintlify-docs/resources/sdks/client-development.mdx b/zk-compression-docs/mintlify-docs/resources/sdks/client-development.mdx new file mode 100644 index 0000000..5627640 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/sdks/client-development.mdx @@ -0,0 +1,109 @@ +--- +title: "Client Development" +description: Overview to Client side development. Quick access to TypeScript and Rust SDKs +--- + +Build client applications that interact with ZK Compression across web, Node.js, and native environments using our TypeScript and Rust SDKs. + +## Typescript Client + +- [**@lightprotocol/stateless.js**](https://www.npmjs.com/package/@lightprotocol/stateless.js) **-** Core compression SDK to create or interact with compressed accounts via RPC interface +- [**@lightprotocol/compressed-token**](https://www.npmjs.com/package/@lightprotocol/compressed-token) **-** SDK to mint, transfer, compress/ decompress, or delegate compressed tokens + +## Rust Client + +* For devnet and mainnet use [`light-client`](https://docs.rs/light-client) + * An RPC client for compressed accounts and tokens. Find a [full list of JSON RPC methods here](https://www.zkcompression.com/resources/json-rpc-methods). + * It connects to the Photon indexer that tracks compressed state to query compressed accounts and the prover service for validity proofs. +* For local testing use [`light-program-test`](https://docs.rs/light-program-test) + * Initializes in-process Solana VM via [LiteSVM](https://github.com/LiteSVM/LiteSVM) with auto-funded payer, local prover server and in-memory indexer. +* `LightClient` and `LightProgramTest` implement the same [`Rpc`](https://docs.rs/light-client/latest/light_client/rpc/trait.Rpc.html) and [`Indexer`](https://docs.rs/light-client/latest/light_client/indexer/trait.Indexer.html) traits. Seamlessly switch between `light-program-test`, local test validator, and public Solana networks. + +### Installation + + +```bash npm +npm install --save \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @lightprotocol/zk-compression-cli +``` + +```bash Yarn +yarn add \ + @lightprotocol/stateless.js \ + @lightprotocol/compressed-token \ + @solana/web3.js \ + @lightprotocol/zk-compression-cli +``` + + + +```toml rust-client.toml +[dependencies] +light-client = "0.13.1" +``` + +### Environments + + + +Start a local test-validator with the below command. It will start a single-node Solana cluster, an RPC node, and a prover node at ports 8899, 8784, and 3001. + +```bash +light test-validator +``` + +See the CLI Installation Guide for more. + + + + +The `Rpc` connection is used to interact with the ZK Compression JSON RPC. It's a thin wrapper extending [Solana's web3.js `Connection` class](https://solana-labs.github.io/solana-web3.js/classes/Connection.html) with compression-related endpoints. + +Here's how you set up a connection: + +```typescript +import { createRpc } from '@lightprotocol/stateless.js'; + +// Local development +const connection = createRpc(); // Uses local test validator + +// DevNet +const connection = createRpc( + "https://devnet.helius-rpc.com?api-key=YOUR_KEY", +); + +// MainNet +const connection = createRpc( + "https://mainnet.helius-rpc.com?api-key=YOUR_KEY" +); +``` + +Find all ZK Compression related RPC methods below. + + + + +### Examples + + + + + + + +### Next Steps + +Learn about SDKs for program development. diff --git a/zk-compression-docs/mintlify-docs/resources/sdks/program-development.mdx b/zk-compression-docs/mintlify-docs/resources/sdks/program-development.mdx new file mode 100644 index 0000000..4546e89 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/resources/sdks/program-development.mdx @@ -0,0 +1,73 @@ +--- +title: Program Development +description: "Overview to on-chain program development. Quick access to SDKs for Anchor, Pinocchio, or native Rust." +--- + +ZK Compression's Rust crates are published to [crates.io](https://docs.rs/releases/search?query=zk+compression) and can be found on [docs.rs](https://crates.io/search?q=zk%20compression) with the `light-` prefix. + +### Rust Crates + +- [`light-sdk`](https://github.com/Lightprotocol/light-protocol/tree/main/sdk-libs/sdk) — For Anchor and native programs. Includes CPI utilities, compressed account abstractions similar to anchor Account, and metadata structs for CPIs to the Light System program. +- [`light-sdk-pinocchio`](https://github.com/Lightprotocol/light-protocol/tree/main/sdk-libs/sdk-pinocchio) — For Pinocchio programs. Pinocchio-optimized SDK with compressed account abstractions and CPI utilities. + +### Light Programs Overview + + +Your custom program invokes the _Light system program_ via Cross-Program Invocation (CPI) to leverage ZK Compression. + + +| Program | Description | +|:-|:-| +| [light-system-program](https://github.com/Lightprotocol/light-protocol/tree/main/programs/system) | Enforces compressed account layout, ownership checks, and validity proof verification. Used to create/write compressed accounts and PDAs. | +| [light-compressed-token](https://crates.io/crates/light-compressed-token) | SPL-compatible compressed token implementation with arbitrary compression/decompression support. | +| [account-compression](https://github.com/Lightprotocol/light-protocol/tree/main/programs/account-compression) | State and address tree implementation used by the Light System program. Clients and custom programs do not interact with the Account Compression Program — this is handled under the hood. | + +### Version Requirements + +These are the required version for program development. + +- **Rust**: 1.86.0 or later +- **Solana CLI**: 2.2.15 +- **Anchor CLI**: 0.31.1 +- **Zk compression CLI**: 0.27.0 or later +- **Node.js**: 23.5.0 or later + + + +solana.com + + + + + + + +### Program Examples + + + +### Build your own program + +Get an overview of compressed PDAs and create your custom program. + + diff --git a/zk-compression-docs/mintlify-docs/style.css b/zk-compression-docs/mintlify-docs/style.css new file mode 100644 index 0000000..e4bc3b7 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/style.css @@ -0,0 +1,10 @@ +@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Montserrat:wght@600&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Montserrat:wght@600&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); + +body{ + font-family: 'Inter', 'IBM Plex Mono'; +} + +h1,h2,h3,h4,h5,h6{ + font-family: 'Inter', 'IBM Plex Mono'; +} diff --git a/zk-compression-docs/mintlify-docs/support.mdx b/zk-compression-docs/mintlify-docs/support.mdx new file mode 100644 index 0000000..e0b36d2 --- /dev/null +++ b/zk-compression-docs/mintlify-docs/support.mdx @@ -0,0 +1,28 @@ +--- +title: Support +description: Get expert help with ZK Compression, compressed tokens, compressed PDAs, local development and more. Discord community, Telegram, and Email support available. +icon: headset +--- + + + + + Head to the Light Developer Discord. + + + Head to the Helius Developer Discord. + + + Head to the Solana StackExchange. + + + +## Reporting Technical Issues + + +When reporting technical issues, + +1. include as much detail as possible in your question, +2. provide a reproducer or GitHub code snippet if possible, +3. please use text (not screenshots) to show error messages so other people with the same problem can find your question. +