Conversation
WalkthroughThe PR replaces the token-pool PDA abstraction with an SPL interface PDA throughout the ctoken SDK and token-client, adds a new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Areas needing extra attention:
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
sdk-libs/ctoken-sdk/src/error.rs (1)
68-71: Update error variants to match SPL interface terminology.The error variants still reference "token pool" terminology, which is inconsistent with the refactoring that renamed token pool PDA to SPL interface PDA throughout the codebase.
Apply this diff to align error names with the new terminology:
- #[error("Missing token pool PDA")] - MissingTokenPoolPda, - #[error("Missing token pool PDA bump")] - MissingTokenPoolPdaBump, + #[error("Missing SPL interface PDA")] + MissingSplInterfacePda, + #[error("Missing SPL interface PDA bump")] + MissingSplInterfacePdaBump,Also update the error code mappings in the
From<TokenSdkError> for u32implementation (lines 127-128) to use the new variant names.sdk-libs/ctoken-sdk/src/compressed_token/v2/mint_to_compressed/instruction.rs (1)
10-36: Newspl_interface_pdainput is currently unused in instruction constructionYou’ve added
spl_interface_pda: Option<SplInterfacePda>toMintToCompressedInputs(documented as “Required if the mint is decompressed”), butcreate_mint_to_compressed_instructionimmediately destructures it as_and never uses it, same asdecompressed_mint_configandoutput_queue_tokens.That keeps behavior aligned with the previous
token_poolsetup (so no new regression), but the API now strongly suggests that callers must provide a valid SPL interface PDA even though it has no effect.I’d recommend either:
- actually threading
spl_interface_pda(and, if needed,decompressed_mint_config) intoMintActionMetaConfig/ account metas, or- explicitly documenting that this field is reserved for future use so integrators don’t assume it’s enforced today.
Also applies to: 43-57
| pub struct SplInterface<'info> { | ||
| pub mint: AccountInfo<'info>, | ||
| pub spl_token_program: AccountInfo<'info>, | ||
| pub token_pool_pda: AccountInfo<'info>, | ||
| pub token_pool_pda_bump: u8, | ||
| pub spl_interface_pda: AccountInfo<'info>, | ||
| pub spl_interface_pda_bump: u8, | ||
| } |
There was a problem hiding this comment.
Behavior is correct, but error names still reference the old token pool abstraction
The refactor from token pool to SPL interface in this builder looks solid:
SplInterface<'info>now carriesspl_interface_pdaandspl_interface_pda_bump.with_spl_interfaceenforces presence of mint, SPL token program, SPL interface PDA, and bump before enabling SPL↔ctoken transfers.- The
invoke/invoke_signedbranches correctly plumbspl_interface_pdaand its bump intoTransferCtokenToSplAccountInfosandTransferSplToCtokenAccountInfos.
One small inconsistency is that with_spl_interface still uses:
TokenSdkError::MissingTokenPoolPda
TokenSdkError::MissingTokenPoolPdaBumpfor the SPL interface PDA and bump. Given the rest of the file and the new SplInterfaceRequired error are framed in terms of “SPL interface”, these legacy variant names (and likely their user-facing messages) will be confusing.
If you can afford it in this PR, I’d suggest:
- renaming those error variants and messages to
MissingSplInterfacePda/MissingSplInterfacePdaBump(with a deprecation alias if needed), or - at least updating their error strings to talk about “SPL interface PDA” instead of “token pool PDA”.
That keeps the error surface aligned with the new abstraction and makes debugging much clearer.
Also applies to: 56-87, 99-151, 163-221
🤖 Prompt for AI Agents
sdk-libs/ctoken-sdk/src/ctoken/transfer_interface.rs lines 12-17 (also apply
fixes in ranges 56-87, 99-151, 163-221): the builder and error usage still
reference legacy TokenSdkError::MissingTokenPoolPda and
TokenSdkError::MissingTokenPoolPdaBump which are inconsistent with the new
SplInterface abstraction; rename these error variants to MissingSplInterfacePda
and MissingSplInterfacePdaBump (or add deprecated aliases forwarding to the new
names), update all matches/returns/usages and their user-facing error strings to
say “SPL interface PDA” / “SPL interface PDA bump”, and run/adjust any tests or
docs referencing the old names so all error messages and variants consistently
reflect the SPL interface abstraction.
| spl_interface::{derive_spl_interface_pda, find_spl_interface_pda_with_index}, | ||
| }; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
SPL interface PDA wiring looks correct; consider reusing the first derivation and cleaning up naming
The decompressed-mint branch now:
- derives
(spl_interface_pda, bump)viafind_spl_interface_pda_with_index(&spl_mint_pda, 0)and storesspl_interface_pdaintoDecompressedMintConfig.token_pool_pda, and - separately calls
derive_spl_interface_pda(&spl_mint_pda, 0)to build theSplInterfacePdaforMintToCompressedInputs.
Functionally this is fine (both calls share the same seed logic), but you’re doing the PDA derivation twice for the same mint/index. You can simplify and avoid the extra call by reusing the first result:
- let decompressed_mint_config = if compressed_mint.metadata.spl_mint_initialized {
- let (spl_interface_pda, _) = find_spl_interface_pda_with_index(&spl_mint_pda, 0);
- Some(DecompressedMintConfig {
- mint_pda: spl_mint_pda,
- token_pool_pda: spl_interface_pda,
- token_program: spl_token_2022::ID,
- })
- } else {
- None
- };
-
- // Derive spl interface pda if needed for decompressed mints
- let spl_interface_pda = if compressed_mint.metadata.spl_mint_initialized {
- Some(derive_spl_interface_pda(&spl_mint_pda, 0))
- } else {
- None
- };
+ let (decompressed_mint_config, spl_interface_pda) =
+ if compressed_mint.metadata.spl_mint_initialized {
+ let (pda, bump) = find_spl_interface_pda_with_index(&spl_mint_pda, 0);
+ (
+ Some(DecompressedMintConfig {
+ mint_pda: spl_mint_pda,
+ token_pool_pda: pda,
+ token_program: spl_token_2022::ID,
+ }),
+ Some(SplInterfacePda {
+ pubkey: pda,
+ bump,
+ index: 0,
+ }),
+ )
+ } else {
+ (None, None)
+ };Also, the comment // Create decompressed mint config and token pool if mint is decompressed is now slightly misleading; renaming this to reference the SPL interface PDA would better match the new abstraction.
Also applies to: 60-78, 91-107
🤖 Prompt for AI Agents
In sdk-libs/token-client/src/instructions/mint_to_compressed.rs around lines
17-18 (and similarly at 60-78 and 91-107), you derive the same SPL interface PDA
twice: once via find_spl_interface_pda_with_index(...) whose spl_interface_pda
is stored in DecompressedMintConfig.token_pool_pda, and again via
derive_spl_interface_pda(...) to build the SplInterfacePda for
MintToCompressedInputs; instead reuse the SplInterfacePda returned from the
first derivation (or construct SplInterfacePda from that single result) and
remove the duplicate derive call, and update the comment “Create decompressed
mint config and token pool if mint is decompressed” to refer to the SPL
interface PDA instead to reflect the abstraction.
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
.github/workflows/sdk-tests.ymlis excluded by none and included by none
📒 Files selected for processing (8)
sdk-libs/ctoken-sdk/Cargo.toml(1 hunks)sdk-libs/ctoken-sdk/tests/account_metas_test.rs(1 hunks)sdk-libs/ctoken-sdk/tests/pack_test.rs(1 hunks)sdk-libs/sdk/Cargo.toml(1 hunks)sdk-libs/sdk/src/account.rs(1 hunks)sdk-libs/sdk/src/instruction/mod.rs(0 hunks)sdk-libs/sdk/src/instruction/pack_accounts.rs(1 hunks)sdk-libs/sdk/src/lib.rs(2 hunks)
💤 Files with no reviewable changes (1)
- sdk-libs/sdk/src/instruction/mod.rs
🧰 Additional context used
📓 Path-based instructions (2)
sdk-libs/*/Cargo.toml
📄 CodeRabbit inference engine (CLAUDE.md)
SDK libs must depend on program-libs, light-prover-client and external crates only; must not depend on programs without devenv feature
Files:
sdk-libs/sdk/Cargo.tomlsdk-libs/ctoken-sdk/Cargo.toml
sdk-libs/**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
Unit tests in sdk-libs must not depend on light-test-utils; integration tests must be located in sdk-tests/
Files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/sdk/src/lib.rssdk-libs/ctoken-sdk/tests/pack_test.rssdk-libs/sdk/src/instruction/pack_accounts.rssdk-libs/sdk/src/account.rs
🧠 Learnings (71)
📓 Common learnings
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use AccountInfos structs (CreateCMintAccountInfos, MintToCTokenInfos, CreateCTokenAccountInfos, CreateAssociatedTokenAccountInfos, TransferCtokenAccountInfos) from light-ctoken-sdk for typed account management
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-token-test/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:57.449Z
Learning: Applies to sdk-tests/sdk-token-test/**/*test.rs : Tests should use light-ctoken-sdk functions from sdk-libs/compressed-token-sdk for testing ctoken instructions
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use the builder pattern from `light-ctoken-sdk::ctoken` module for CPI operations in native Solana programs
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use the `invoke_signed()` method for PDA-signed CPI calls with properly derived PDA and bump seeds
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/**/create_*token_account*.rs : CToken account layout is the same as SPL tokens but implements a custom Compressible extension
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/seed_providers.rs : PDA and CToken seed provider implementations with client-side seed functions should be in `seed_providers.rs`
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/program-libs/ctoken-types/src/{state,instructions}/**/*.rs : All program state and instruction data structures must be defined in the program-libs/ctoken-types crate (light-ctoken-interface) under state/ and instructions/ directories to allow SDKs to import types without pulling in program dependencies
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Compressed tokens can be decompressed to SPL tokens, but SPL tokens are not explicitly managed by the program
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:52.783Z
Learning: Organize SDK tests by use case: General SDK (core compressed account operations), Token SDK (compressed SPL token operations), and Client SDK (RPC client for querying)
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/**/ctoken_transfer.rs : CTokenTransfer instruction is SPL-compatible and transfers between decompressed accounts only
📚 Learning: 2025-12-06T00:50:31.304Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T00:50:31.304Z
Learning: Applies to sdk-libs/*/Cargo.toml : SDK libs must depend on program-libs, light-prover-client and external crates only; must not depend on programs without devenv feature
Applied to files:
sdk-libs/sdk/Cargo.tomlsdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-12-06T00:50:31.304Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T00:50:31.304Z
Learning: Applies to programs/*/Cargo.toml : Programs must depend on program-libs and external crates only; must not depend on sdk-libs without devenv feature
Applied to files:
sdk-libs/sdk/Cargo.tomlsdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-12-06T00:49:52.783Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:52.783Z
Learning: Applies to sdk-tests/sdk-libs/light-sdk/**/*.rs : Run unit tests for light-sdk using `cargo test -p light-sdk` and with all features enabled using `cargo test -p light-sdk --all-features`
Applied to files:
sdk-libs/sdk/Cargo.tomlsdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-12-06T00:49:00.168Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/Cargo.toml : Use path references to light-protocol SDK dependencies in Cargo.toml for development and local testing
Applied to files:
sdk-libs/sdk/Cargo.tomlsdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-12-06T00:49:52.783Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:52.783Z
Learning: Applies to sdk-tests/sdk-libs/light-sdk-macros/**/*.rs : Run unit tests for light-sdk-macros using `cargo test -p light-sdk-macros` and with all features enabled using `cargo test -p light-sdk-macros --all-features`
Applied to files:
sdk-libs/sdk/Cargo.tomlsdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-12-06T00:49:52.783Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:52.783Z
Learning: Applies to sdk-tests/sdk-libs/light-ctoken-sdk/**/*.rs : Run unit tests for light-ctoken-sdk using `cargo test -p light-ctoken-sdk`
Applied to files:
sdk-libs/sdk/Cargo.tomlsdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-12-06T00:50:31.304Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T00:50:31.304Z
Learning: Applies to program-libs/*/Cargo.toml : Program-libs crates must depend on other program-libs or external crates only, not on programs or sdk-libs
Applied to files:
sdk-libs/sdk/Cargo.toml
📚 Learning: 2025-12-06T00:49:00.168Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use AccountInfos structs (CreateCMintAccountInfos, MintToCTokenInfos, CreateCTokenAccountInfos, CreateAssociatedTokenAccountInfos, TransferCtokenAccountInfos) from light-ctoken-sdk for typed account management
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/sdk/src/lib.rssdk-libs/ctoken-sdk/tests/pack_test.rssdk-libs/sdk/src/account.rs
📚 Learning: 2025-12-06T00:49:57.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-token-test/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:57.449Z
Learning: Applies to sdk-tests/sdk-token-test/**/*test.rs : Tests should use light-ctoken-sdk functions from sdk-libs/compressed-token-sdk for testing ctoken instructions
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/ctoken-sdk/tests/pack_test.rssdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-12-06T00:49:57.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-token-test/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:57.449Z
Learning: Applies to sdk-tests/sdk-token-test/**/*test.rs : Every test should only contain functional integration tests
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-12-06T00:49:00.168Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use the `invoke_signed()` method for PDA-signed CPI calls with properly derived PDA and bump seeds
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Depend on light-account-checks crate for account validation and discriminator checks
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-11-24T17:59:03.485Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_INFO_TRAIT.md:0-0
Timestamp: 2025-11-24T17:59:03.485Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/account_info/test_account_info.rs : Create a test-only AccountInfo mock implementation without external dependencies for unit testing AccountInfoTrait implementations
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-12-06T00:49:21.973Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.973Z
Learning: Applies to program-libs/compressible/src/config.rs : CompressibleConfig account structure must support serialization via Anchor, Pinocchio, and Borsh formats for Light Registry program integration
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/sdk/src/lib.rssdk-libs/ctoken-sdk/tests/pack_test.rssdk-libs/sdk/src/instruction/pack_accounts.rssdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/programs/**/*.rs : Use Anchor's `AccountDeserialize::try_deserialize` for CompressibleConfig when Anchor feature is enabled, which includes automatic discriminator validation
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-12-06T00:49:37.743Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/programs/compressed-token/anchor/src/lib.rs : Error codes must be defined in programs/compressed-token/anchor/src/lib.rs as anchor_compressed_token::ErrorCode enum and returned as ProgramError::Custom(error_code as u32) on-chain
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Depend on light-compressed-account crate for compressed account types and utilities
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/sdk/src/lib.rs
📚 Learning: 2025-12-06T00:49:21.973Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.973Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement PDA derivation methods (`derive_pda`, `derive_v1_config_pda`) on CompressibleConfig for account discovery
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Validate account ownership by Light account compression program using `check_owner` from `light-account-checks` when deserializing `BatchedQueueAccount` with `output_from_account_info`
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/sdk/src/lib.rs
📚 Learning: 2025-12-06T00:49:37.743Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/**/mint_action/*.rs : Compressed mint accounts support one extension: TokenMetadata
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-12-06T00:49:21.973Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.973Z
Learning: Applies to program-libs/compressible/src/error.rs : Support ProgramError conversions for Anchor, Pinocchio, and Solana frameworks in error implementation
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rs
📚 Learning: 2025-11-24T17:57:53.312Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/TREE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:53.312Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/*.rs : Account validation for state trees must check: (1) account ownership by Light account compression program, (2) account discriminator is `BatchMta`, and (3) tree type is `STATE_MERKLE_TREE_TYPE_V2` (4)
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/sdk/src/lib.rs
📚 Learning: 2025-12-06T00:49:37.743Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/**/create_*token_account*.rs : CToken account layout is the same as SPL tokens but implements a custom Compressible extension
Applied to files:
sdk-libs/ctoken-sdk/tests/account_metas_test.rssdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-11-24T17:59:54.233Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/PACKED_ACCOUNTS.md:0-0
Timestamp: 2025-11-24T17:59:54.233Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/**/*.rs : Provide descriptive names in ProgramPackedAccounts error messages (e.g., 'token_mint' instead of 'account')
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/sdk/src/instruction/pack_accounts.rssdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T18:00:48.449Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/SOLANA_RENT.md:0-0
Timestamp: 2025-11-24T18:00:48.449Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Implement account compressibility states in the following order: Funded (rent for current + 1 epoch) → Compressible (lacks rent for current + 1 epoch) → Claimable (funded but past epochs unclaimed)
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-12-06T00:50:17.423Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: DOCS.md:0-0
Timestamp: 2025-12-06T00:50:17.423Z
Learning: Applies to **/docs/*accounts* : Account documentation must include: description (what account represents and role), state layout (path to struct and field descriptions), associated instructions (list with discriminators), discriminator (8-byte value if applicable), size (in bytes), ownership (expected owner), serialization (zero-copy for programs and Borsh for clients with code snippets). For PDAs include derivation (seeds) and bump (stored or derived). For compressed accounts include version, hashing (method and discriminator), and data layout.
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/sdk/src/instruction/pack_accounts.rssdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/variant_enum.rs : Account variant enum (`CompressedAccountVariant`) generation and `CompressedAccountData` wrapper struct should be implemented in `variant_enum.rs`
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/decompress_context.rs : Decompression trait implementation (`DecompressContext`) with account accessors, PDA/token separation logic, and token processing delegation should be in `decompress_context.rs`
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/pack_unpack.rs : Pubkey compression logic and `PackedXxx` struct generation with Pack/Unpack trait implementations should be in `pack_unpack.rs`
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-11-24T17:59:23.357Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:59:23.357Z
Learning: Applies to program-libs/account-checks/docs/src/**/*.rs : Use 8-byte discriminators for account type identification and implement the Discriminator trait for account identification
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/sdk/src/account.rs
📚 Learning: 2025-12-06T00:49:37.743Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/**/ACCOUNTS.md : All account documentation must include: description, discriminator, state layout, serialization example, hashing (for compressed accounts only), derivation (for PDAs only), and associated instructions (create, update, close)
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Store compressed account hashes in `BatchedQueueAccount` value vectors for immediate proof-by-index access before tree insertion
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run account-compression tests using `cargo test-sbf -p account-compression-test` to test core account compression program (Merkle tree management)
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-11-24T17:57:53.312Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/TREE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:53.312Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/*.rs : When deserializing BatchedMerkleTreeAccount in Solana programs, use `BatchedMerkleTreeAccount::state_from_account_info()` for state trees and `BatchedMerkleTreeAccount::address_from_account_info()` for address trees
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-11-24T17:56:50.011Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_STATE_TREE.md:0-0
Timestamp: 2025-11-24T17:56:50.011Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_state_tree.rs : Initialize an output queue account as `BatchedQueueAccount` with `QueueType::OutputStateV2`, temporary storage for compressed account hashes before tree insertion with immediate spending capability via proof-by-index, using discriminator b`queueacc` [113, 117, 101, 117, 101, 97, 99, 99]
Applied to files:
sdk-libs/sdk/src/lib.rssdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-12-06T00:49:21.973Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.973Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement state validation methods (`validate_active`, `validate_not_inactive`) on CompressibleConfig account structure
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/queue.rs : Output queues must store compressed account hashes in value vectors (one per batch) enabling access by leaf index before tree insertion
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run system CPI V1 tests using `cargo test-sbf -p system-cpi-test` to test Cross-Program Invocation with Light system program V1
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-12-06T00:49:00.168Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use the `invoke()` method for regular CPI calls where the program acts as authority
Applied to files:
sdk-libs/sdk/src/lib.rs
📚 Learning: 2025-12-06T00:49:52.782Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:52.782Z
Learning: Applies to sdk-tests/sdk-token-test/**/*.rs : Run integration tests for compressed token SDK operations using `cargo test-sbf -p sdk-token-test`
Applied to files:
sdk-libs/ctoken-sdk/tests/pack_test.rssdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run compressed token core tests using `cargo test-sbf -p compressed-token-test --test ctoken`, `--test v1`, `--test mint`, and `--test transfer2`
Applied to files:
sdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-12-06T00:49:52.783Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:52.783Z
Learning: Applies to sdk-tests/sdk-libs/light-compressed-token-types/**/*.rs : Run unit tests for light-compressed-token-types using `cargo test -p light-compressed-token-types`
Applied to files:
sdk-libs/ctoken-sdk/tests/pack_test.rssdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-12-06T00:49:00.168Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-tests/sdk-ctoken-test/README.md:0-0
Timestamp: 2025-12-06T00:49:00.168Z
Learning: Applies to sdk-tests/sdk-ctoken-test/**/*.rs : Use the builder pattern from `light-ctoken-sdk::ctoken` module for CPI operations in native Solana programs
Applied to files:
sdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-11-24T17:59:23.357Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:59:23.357Z
Learning: Applies to program-libs/account-checks/docs/src/**/packed_accounts.rs : Implement index-based dynamic account access with bounds checking for handling variable account sets (mint, owner, delegate accounts)
Applied to files:
sdk-libs/ctoken-sdk/tests/pack_test.rssdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T18:01:30.012Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:30.012Z
Learning: Run Light system program compression tests using `cargo test-sbf -p system-test -- test_with_compression` and `cargo test-sbf -p system-test --test test_re_init_cpi_account` to test compressed account operations
Applied to files:
sdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/*.rs : Use CompressibleConfig discriminator `[180, 4, 231, 26, 220, 144, 55, 168]` for account validation in Solana programs and clients
Applied to files:
sdk-libs/ctoken-sdk/tests/pack_test.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/account_compression_cpi/*.rs : Create wrapper instruction module at `src/account_compression_cpi/new_operation.rs` with `NewOperationContext` struct defining required accounts
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T17:59:13.714Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/ACCOUNT_ITERATOR.md:0-0
Timestamp: 2025-11-24T17:59:13.714Z
Learning: Applies to program-libs/account-checks/docs/**/*.rs : Use descriptive account names when calling AccountIterator methods (e.g., `iter.next_account("token_mint")` instead of `iter.next_account("account_3")`)
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T17:59:54.233Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/PACKED_ACCOUNTS.md:0-0
Timestamp: 2025-11-24T17:59:54.233Z
Learning: Applies to program-libs/account-checks/docs/program-libs/account-checks/src/**/*.rs : Use `ProgramPackedAccounts` for index-based access to dynamically sized account arrays in Rust programs
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-12-06T00:49:12.998Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:12.998Z
Learning: Applies to program-libs/account-checks/src/packed_accounts.rs : Use index-based account access with bounds-checked retrieval for dynamic account sets
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T18:01:54.689Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/docs/instructions/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:01:54.689Z
Learning: Applies to programs/compressed-token/program/docs/instructions/**/ACCOUNTS.md : ACCOUNTS.md must contain complete account layouts and data structures with references to code paths
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T18:02:15.670Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/registry/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:02:15.670Z
Learning: Applies to programs/registry/src/account_compression_cpi/mod.rs : Export new wrapper modules in `account_compression_cpi/mod.rs` using `pub mod new_operation;` and `pub use new_operation::*;`, then import in `lib.rs`
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/initialize_state_tree.rs : State tree initialization must create two Solana accounts: BatchedMerkleTreeAccount with integrated input queue and separate BatchedQueueAccount
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/initialize_address_tree.rs : Initialize address tree with integrated address queue in `src/initialize_address_tree.rs`. Creates one `BatchedMerkleTreeAccount` with account layout defined in `src/merkle_tree.rs`, metadata in `src/merkle_tree_metadata.rs`, tree type `TreeType::AddressV2` (5), initial root `ADDRESS_TREE_INIT_ROOT_40`, starts at next_index 1, and discriminator `BatchMta` (8 bytes).
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T17:56:20.711Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/INITIALIZE_ADDRESS_TREE.md:0-0
Timestamp: 2025-11-24T17:56:20.711Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/merkle_tree.rs : Define `BatchedMerkleTreeAccount` account layout in `src/merkle_tree.rs`. Include method `get_merkle_tree_account_size` to calculate account size based on input_queue_batch_size, bloom_filter_capacity, input_queue_zkp_batch_size, root_history_capacity, and height.
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-11-24T17:59:54.233Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/PACKED_ACCOUNTS.md:0-0
Timestamp: 2025-11-24T17:59:54.233Z
Learning: Use ProgramPackedAccounts when account indices come from instruction data and accounts can be accessed in any order
Applied to files:
sdk-libs/sdk/src/instruction/pack_accounts.rs
📚 Learning: 2025-12-06T00:49:21.973Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.973Z
Learning: Applies to program-libs/compressible/src/config.rs : Implement default initialization for CToken V1 config in CompressibleConfig structure
Applied to files:
sdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-12-06T00:49:37.743Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: programs/compressed-token/program/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:37.743Z
Learning: Applies to programs/compressed-token/program/program-libs/ctoken-types/src/{state,instructions}/**/*.rs : All program state and instruction data structures must be defined in the program-libs/ctoken-types crate (light-ctoken-interface) under state/ and instructions/ directories to allow SDKs to import types without pulling in program dependencies
Applied to files:
sdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-11-24T17:55:17.323Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/src/compressible/README.md:0-0
Timestamp: 2025-11-24T17:55:17.323Z
Learning: Applies to sdk-libs/macros/src/compressible/**/seed_providers.rs : PDA and CToken seed provider implementations with client-side seed functions should be in `seed_providers.rs`
Applied to files:
sdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-11-24T18:00:13.178Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/CONFIG_ACCOUNT.md:0-0
Timestamp: 2025-11-24T18:00:13.178Z
Learning: Applies to program-libs/compressible/docs/**/config.rs : Set CompressibleConfig default values for CToken V1: base_rent = 1220, compression_cost = 11000, lamports_per_byte_per_epoch = 10, and address_space[0] = `amt2kaJA14v3urZbZvnc5v2np8jqvc4Z8zDep5wbtzx`
Applied to files:
sdk-libs/ctoken-sdk/Cargo.toml
📚 Learning: 2025-11-24T17:54:57.953Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/README.md:0-0
Timestamp: 2025-11-24T17:54:57.953Z
Learning: Applies to sdk-libs/macros/**/*.rs : Use `#[hash]` attribute to truncate field data to BN254 field size for large types in LightHasher derive macro
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:59:36.701Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/DISCRIMINATOR.md:0-0
Timestamp: 2025-11-24T17:59:36.701Z
Learning: Applies to program-libs/account-checks/docs/**/account-checks/**/*.rs : Ensure discriminator validation is Anchor-compatible by using sha256 hashing for consistency with Anchor accounts
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:59:36.701Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/DISCRIMINATOR.md:0-0
Timestamp: 2025-11-24T17:59:36.701Z
Learning: Applies to program-libs/account-checks/docs/**/account-checks/**/*.rs : Use human-readable ASCII string discriminators or hash-derived values, documented with byte values in comments
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:54:57.953Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: sdk-libs/macros/README.md:0-0
Timestamp: 2025-11-24T17:54:57.953Z
Learning: Applies to sdk-libs/macros/**/*.rs : Implement LightHasher derive macro to provide implementations of `ToByteArray` and `DataHasher` traits for struct types
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:59:36.701Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/DISCRIMINATOR.md:0-0
Timestamp: 2025-11-24T17:59:36.701Z
Learning: Applies to program-libs/account-checks/docs/**/account-checks/**/*.rs : Document discriminator values in code comments to make account types discoverable and maintainable
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:59:36.701Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/account-checks/docs/DISCRIMINATOR.md:0-0
Timestamp: 2025-11-24T17:59:36.701Z
Learning: Applies to program-libs/account-checks/docs/**/account-checks/**/*.rs : Implement the Discriminator trait for account types, providing 8-byte LIGHT_DISCRIMINATOR constant and LIGHT_DISCRIMINATOR_SLICE reference in Rust account structures
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:56:00.229Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/CLAUDE.md:0-0
Timestamp: 2025-11-24T17:56:00.229Z
Learning: Applies to program-libs/batched-merkle-tree/docs/**/Cargo.toml : Depend on light-hasher crate for Poseidon hash implementation in hash chains and tree operations
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T18:00:21.501Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/docs/ERRORS.md:0-0
Timestamp: 2025-11-24T18:00:21.501Z
Learning: HasherError conversions: Automatic conversion from `light_hasher::HasherError` (7xxx error codes) is supported. Refer to the light-hasher crate documentation for specific hasher error details.
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-12-06T00:49:21.973Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/compressible/CLAUDE.md:0-0
Timestamp: 2025-12-06T00:49:21.973Z
Learning: Applies to program-libs/compressible/src/error.rs : PropagateHasher errors from light-hasher module with 7xxx code range in error handling
Applied to files:
sdk-libs/sdk/src/account.rs
📚 Learning: 2025-11-24T17:57:39.230Z
Learnt from: CR
Repo: Lightprotocol/light-protocol PR: 0
File: program-libs/batched-merkle-tree/docs/QUEUE_ACCOUNT.md:0-0
Timestamp: 2025-11-24T17:57:39.230Z
Learning: Applies to program-libs/batched-merkle-tree/docs/src/queue.rs : Implement two hash chain stores (`[ZeroCopyVecU64<[u8; 32]>; 2]`), one per batch, each with `batch_size / zkp_batch_size` hash chains storing Poseidon hashes of ZKP batches in `BatchedQueueAccount`
Applied to files:
sdk-libs/sdk/src/account.rs
🧬 Code graph analysis (1)
sdk-libs/ctoken-sdk/tests/pack_test.rs (2)
sdk-libs/sdk/src/account.rs (1)
owner(302-304)program-libs/compressed-account/src/pubkey.rs (1)
new_unique(200-202)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Forester e2e test
- GitHub Check: Test program-libs-slow
- GitHub Check: Test batched-merkle-tree-simulate
- GitHub Check: Test program-libs-fast
- GitHub Check: programs (compressed-token-and-e2e, ["cargo test -p light-compressed-token", "cargo-test-sbf -p c...
- GitHub Check: programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-test -- ...
- GitHub Check: programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test -- func...
- GitHub Check: programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-prog...
- GitHub Check: programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test", "cargo...
🔇 Additional comments (9)
sdk-libs/sdk/src/instruction/pack_accounts.rs (1)
130-130: Documentation wording improvement approved.The refined description "Builder to collect accounts for compressed account instructions" is more concise and equally clear. The change doesn't affect functionality, and the comprehensive documentation—with examples, diagrams, and guidance for Anchor programs—remains well-maintained.
sdk-libs/ctoken-sdk/tests/pack_test.rs (4)
1-2: LGTM! Feature gating is correctly applied.The crate-level
compressiblefeature gate ensures these tests only run when the feature is enabled, which aligns with the PR's introduction of conditional re-exports and feature gates.
3-8: LGTM! Import structure is appropriate.The imports correctly use the refactored SDK modules and comply with the coding guideline that unit tests in sdk-libs must not depend on light-test-utils.
45-81: LGTM! Variant packing test is well-designed.This test correctly validates that the packing mechanism preserves the variant while properly packing the embedded TokenData structure. The use of a locally-defined MyVariant enum for testing is appropriate, and the assertions comprehensively verify both variant preservation and data packing.
83-119: LGTM! Excellent test for deduplication behavior.This test validates a critical property of the packing system: that shared pubkeys across multiple TokenData instances are deduplicated and assigned the same indices. This is essential for both correctness and efficiency, as it prevents redundant storage of identical pubkeys in remaining_accounts.
sdk-libs/sdk/Cargo.toml (1)
13-29: Enablingv2by default changes downstream compilation behaviourSwitching
defaultfrom empty to["v2"]means any crate depending onlight-sdkwithout explicitly managing features will now compile with thev2code paths enabled. That’s probably intentional given the broader refactor, but it is a behaviour change for all consumers.I’d recommend double‑checking that:
- All internal crates expecting v1 behaviour explicitly gate any v1‑only usage, and
- CI runs the affected crates’ tests with the new default (and, if relevant, with
--no-default-features+ explicitv2) so regressions around feature assumptions are caught.sdk-libs/ctoken-sdk/tests/account_metas_test.rs (1)
1-1:#![cfg(feature = "v1")]will silently skip this test crate unlessv1is enabledGating the entire integration test crate on
feature = "v1"is consistent with the new v1 feature, but note that:
- Running
cargo test -p light-ctoken-sdkwithout--features v1will completely omit these tests (they won’t even be compiled), so failures in v1 paths won’t be seen.- To keep coverage, your CI and local workflows should run something like
cargo test -p light-ctoken-sdk --features v1(and any other relevant feature combos).If that silent skip is not desired, we could instead gate only the v1‑specific modules or tests.
sdk-libs/sdk/src/lib.rs (1)
3-52: Docs around compressed account trees and client flow look accurateThe added clarification that state lives in state Merkle trees and addresses in address Merkle trees, plus the “Client Program Interaction Flow” block, match the existing architecture and don’t change behaviour. Nice documentation improvement.
sdk-libs/ctoken-sdk/Cargo.toml (1)
6-9: Feature scaffolding (default,v1,compressible) is consistent but verify intended defaultsDefining empty features for
v1andcompressiblewithdefault = []is fine and matches the newcfg(feature = "...")usage elsewhere (e.g. tests gated onv1). This makes those code paths opt‑in.Please confirm that:
- All call sites expecting v1 behaviour or compressible helpers explicitly enable these features, and
- Your CI matrix includes runs with
--features v1,--features compressible, or both, so gated code and tests are exercised.No new program dependencies were added here, so the sdk‑libs Cargo guideline about avoiding program deps remains satisfied. Based on learnings, this matches the “SDK libs must depend on program‑libs and external crates only” rule.
| #[test] | ||
| fn test_token_data_packing() { | ||
| let mut remaining_accounts = PackedAccounts::default(); | ||
|
|
||
| let owner = Pubkey::new_unique(); | ||
| let mint = Pubkey::new_unique(); | ||
| let delegate = Pubkey::new_unique(); | ||
|
|
||
| let token_data = TokenData { | ||
| owner, | ||
| mint, | ||
| amount: 1000, | ||
| delegate: Some(delegate), | ||
| state: Default::default(), | ||
| tlv: None, | ||
| }; | ||
| use light_sdk::instruction::PackedAccounts; | ||
| use solana_pubkey::Pubkey; | ||
|
|
||
| #[test] | ||
| fn test_token_data_packing() { | ||
| let mut remaining_accounts = PackedAccounts::default(); | ||
|
|
||
| let owner = Pubkey::new_unique(); | ||
| let mint = Pubkey::new_unique(); | ||
| let delegate = Pubkey::new_unique(); | ||
|
|
||
| let token_data = TokenData { | ||
| owner, | ||
| mint, | ||
| amount: 1000, | ||
| delegate: Some(delegate), | ||
| state: Default::default(), | ||
| tlv: None, | ||
| }; | ||
|
|
||
| // Pack the token data | ||
| let packed = token_data.pack(&mut remaining_accounts); | ||
|
|
||
| // Verify the packed data | ||
| assert_eq!(packed.owner, 0); // First pubkey gets index 0 | ||
| assert_eq!(packed.mint, 1); // Second pubkey gets index 1 | ||
| assert_eq!(packed.delegate, 2); // Third pubkey gets index 2 | ||
| assert_eq!(packed.amount, 1000); | ||
| assert!(packed.has_delegate); | ||
| assert_eq!(packed.version, 3); // TokenDataVersion::ShaFlat | ||
|
|
||
| // Verify remaining_accounts contains the pubkeys | ||
| let pubkeys = remaining_accounts.packed_pubkeys(); | ||
| assert_eq!(pubkeys[0], owner); | ||
| assert_eq!(pubkeys[1], mint); | ||
| assert_eq!(pubkeys[2], delegate); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_token_data_with_variant_packing() { | ||
| use anchor_lang::{AnchorDeserialize, AnchorSerialize}; | ||
|
|
||
| #[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize)] | ||
| enum MyVariant { | ||
| TypeA = 0, | ||
| TypeB = 1, | ||
| } | ||
|
|
||
| let mut remaining_accounts = PackedAccounts::default(); | ||
|
|
||
| let token_with_variant = TokenDataWithVariant { | ||
| variant: MyVariant::TypeA, | ||
| token_data: TokenData { | ||
| owner: Pubkey::new_unique(), | ||
| mint: Pubkey::new_unique(), | ||
| amount: 500, | ||
| delegate: None, | ||
| state: Default::default(), | ||
| tlv: None, | ||
| }, | ||
| }; | ||
|
|
||
| // Pack the wrapper | ||
| let packed: PackedCTokenDataWithVariant<MyVariant> = | ||
| token_with_variant.pack(&mut remaining_accounts); | ||
|
|
||
| // Verify variant is unchanged | ||
| assert!(matches!(packed.variant, MyVariant::TypeA)); | ||
|
|
||
| // Verify token data is packed | ||
| assert_eq!(packed.token_data.owner, 0); | ||
| assert_eq!(packed.token_data.mint, 1); | ||
| assert_eq!(packed.token_data.amount, 500); | ||
| assert!(!packed.token_data.has_delegate); | ||
| } | ||
| // Pack the token data | ||
| let packed = token_data.pack(&mut remaining_accounts); | ||
|
|
||
| // Verify the packed data | ||
| assert_eq!(packed.owner, 0); // First pubkey gets index 0 | ||
| assert_eq!(packed.mint, 1); // Second pubkey gets index 1 | ||
| assert_eq!(packed.delegate, 2); // Third pubkey gets index 2 | ||
| assert_eq!(packed.amount, 1000); | ||
| assert!(packed.has_delegate); | ||
| assert_eq!(packed.version, 3); // TokenDataVersion::ShaFlat | ||
|
|
||
| // Verify remaining_accounts contains the pubkeys | ||
| let pubkeys = remaining_accounts.packed_pubkeys(); | ||
| assert_eq!(pubkeys[0], owner); | ||
| assert_eq!(pubkeys[1], mint); | ||
| assert_eq!(pubkeys[2], delegate); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Use enum constant instead of magic number for version.
The test logic is sound and provides good coverage of the packing functionality. However, line 36 uses a magic number 3 with a comment rather than the actual enum constant.
Apply this diff to improve maintainability:
- assert_eq!(packed.version, 3); // TokenDataVersion::ShaFlat
+ assert_eq!(packed.version, TokenDataVersion::ShaFlat as u8);This ensures the test fails at compile-time if the enum structure changes, rather than silently passing with an incorrect version value.
Note: The overall test logic correctly verifies indices, amounts, delegate flags, and remaining_accounts pubkeys.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #[test] | |
| fn test_token_data_packing() { | |
| let mut remaining_accounts = PackedAccounts::default(); | |
| let owner = Pubkey::new_unique(); | |
| let mint = Pubkey::new_unique(); | |
| let delegate = Pubkey::new_unique(); | |
| let token_data = TokenData { | |
| owner, | |
| mint, | |
| amount: 1000, | |
| delegate: Some(delegate), | |
| state: Default::default(), | |
| tlv: None, | |
| }; | |
| use light_sdk::instruction::PackedAccounts; | |
| use solana_pubkey::Pubkey; | |
| #[test] | |
| fn test_token_data_packing() { | |
| let mut remaining_accounts = PackedAccounts::default(); | |
| let owner = Pubkey::new_unique(); | |
| let mint = Pubkey::new_unique(); | |
| let delegate = Pubkey::new_unique(); | |
| let token_data = TokenData { | |
| owner, | |
| mint, | |
| amount: 1000, | |
| delegate: Some(delegate), | |
| state: Default::default(), | |
| tlv: None, | |
| }; | |
| // Pack the token data | |
| let packed = token_data.pack(&mut remaining_accounts); | |
| // Verify the packed data | |
| assert_eq!(packed.owner, 0); // First pubkey gets index 0 | |
| assert_eq!(packed.mint, 1); // Second pubkey gets index 1 | |
| assert_eq!(packed.delegate, 2); // Third pubkey gets index 2 | |
| assert_eq!(packed.amount, 1000); | |
| assert!(packed.has_delegate); | |
| assert_eq!(packed.version, 3); // TokenDataVersion::ShaFlat | |
| // Verify remaining_accounts contains the pubkeys | |
| let pubkeys = remaining_accounts.packed_pubkeys(); | |
| assert_eq!(pubkeys[0], owner); | |
| assert_eq!(pubkeys[1], mint); | |
| assert_eq!(pubkeys[2], delegate); | |
| } | |
| #[test] | |
| fn test_token_data_with_variant_packing() { | |
| use anchor_lang::{AnchorDeserialize, AnchorSerialize}; | |
| #[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize)] | |
| enum MyVariant { | |
| TypeA = 0, | |
| TypeB = 1, | |
| } | |
| let mut remaining_accounts = PackedAccounts::default(); | |
| let token_with_variant = TokenDataWithVariant { | |
| variant: MyVariant::TypeA, | |
| token_data: TokenData { | |
| owner: Pubkey::new_unique(), | |
| mint: Pubkey::new_unique(), | |
| amount: 500, | |
| delegate: None, | |
| state: Default::default(), | |
| tlv: None, | |
| }, | |
| }; | |
| // Pack the wrapper | |
| let packed: PackedCTokenDataWithVariant<MyVariant> = | |
| token_with_variant.pack(&mut remaining_accounts); | |
| // Verify variant is unchanged | |
| assert!(matches!(packed.variant, MyVariant::TypeA)); | |
| // Verify token data is packed | |
| assert_eq!(packed.token_data.owner, 0); | |
| assert_eq!(packed.token_data.mint, 1); | |
| assert_eq!(packed.token_data.amount, 500); | |
| assert!(!packed.token_data.has_delegate); | |
| } | |
| // Pack the token data | |
| let packed = token_data.pack(&mut remaining_accounts); | |
| // Verify the packed data | |
| assert_eq!(packed.owner, 0); // First pubkey gets index 0 | |
| assert_eq!(packed.mint, 1); // Second pubkey gets index 1 | |
| assert_eq!(packed.delegate, 2); // Third pubkey gets index 2 | |
| assert_eq!(packed.amount, 1000); | |
| assert!(packed.has_delegate); | |
| assert_eq!(packed.version, 3); // TokenDataVersion::ShaFlat | |
| // Verify remaining_accounts contains the pubkeys | |
| let pubkeys = remaining_accounts.packed_pubkeys(); | |
| assert_eq!(pubkeys[0], owner); | |
| assert_eq!(pubkeys[1], mint); | |
| assert_eq!(pubkeys[2], delegate); | |
| } | |
| #[test] | |
| fn test_token_data_packing() { | |
| let mut remaining_accounts = PackedAccounts::default(); | |
| let owner = Pubkey::new_unique(); | |
| let mint = Pubkey::new_unique(); | |
| let delegate = Pubkey::new_unique(); | |
| let token_data = TokenData { | |
| owner, | |
| mint, | |
| amount: 1000, | |
| delegate: Some(delegate), | |
| state: Default::default(), | |
| tlv: None, | |
| }; | |
| // Pack the token data | |
| let packed = token_data.pack(&mut remaining_accounts); | |
| // Verify the packed data | |
| assert_eq!(packed.owner, 0); // First pubkey gets index 0 | |
| assert_eq!(packed.mint, 1); // Second pubkey gets index 1 | |
| assert_eq!(packed.delegate, 2); // Third pubkey gets index 2 | |
| assert_eq!(packed.amount, 1000); | |
| assert!(packed.has_delegate); | |
| assert_eq!(packed.version, TokenDataVersion::ShaFlat as u8); | |
| // Verify remaining_accounts contains the pubkeys | |
| let pubkeys = remaining_accounts.packed_pubkeys(); | |
| assert_eq!(pubkeys[0], owner); | |
| assert_eq!(pubkeys[1], mint); | |
| assert_eq!(pubkeys[2], delegate); | |
| } |
🤖 Prompt for AI Agents
In sdk-libs/ctoken-sdk/tests/pack_test.rs around lines 10 to 43, replace the
magic number assertion assert_eq!(packed.version, 3) with an assertion using the
enum constant (e.g., assert_eq!(packed.version, TokenDataVersion::ShaFlat as u8)
or the appropriate variant cast) so the test references the TokenDataVersion
enum directly; update imports if necessary to bring TokenDataVersion into scope.
| //! Sha256 data hashing is recommended for most use cases. | ||
| //! Account data is serialized into a vector with borsh and hashed with Sha256. | ||
| //! | ||
| //! Poseidon data hashing is recommended zk use cases. | ||
| //! The data struct needs to implement the DataHasher implementation. | ||
| //! The LightHasher derives, the DataHasher trait a hashing scheme from the compressed account layout. | ||
| //! Poseidon data hashing is recommended for zk use cases. | ||
| //! The data struct needs to implement the DataHasher trait. | ||
| //! The LightHasher macro derives, the DataHasher trait. The hashing scheme resembles the struct layout. | ||
| //! Alternatively, DataHasher can be implemented manually. | ||
| //! Poseidon hashing is CU intensive and has limitations with regards to hash inputs see Poseidon module for details. |
There was a problem hiding this comment.
Minor wording fix in hashing documentation
The semantics are correct (Sha256 for general use, Poseidon + DataHasher/LightHasher for zk use), but there’s a small grammar/punctuation glitch:
The LightHasher macro derives, the DataHasher trait.
Consider tightening this sentence to avoid confusion:
-//! The LightHasher macro derives, the DataHasher trait. The hashing scheme resembles the struct layout.
+//! The LightHasher macro derives the DataHasher trait. The hashing scheme resembles the struct layout.This keeps the docs crisp and easier to read for users learning the hashing model.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| //! Sha256 data hashing is recommended for most use cases. | |
| //! Account data is serialized into a vector with borsh and hashed with Sha256. | |
| //! | |
| //! Poseidon data hashing is recommended zk use cases. | |
| //! The data struct needs to implement the DataHasher implementation. | |
| //! The LightHasher derives, the DataHasher trait a hashing scheme from the compressed account layout. | |
| //! Poseidon data hashing is recommended for zk use cases. | |
| //! The data struct needs to implement the DataHasher trait. | |
| //! The LightHasher macro derives, the DataHasher trait. The hashing scheme resembles the struct layout. | |
| //! Alternatively, DataHasher can be implemented manually. | |
| //! Poseidon hashing is CU intensive and has limitations with regards to hash inputs see Poseidon module for details. | |
| //! Sha256 data hashing is recommended for most use cases. | |
| //! Account data is serialized into a vector with borsh and hashed with Sha256. | |
| //! | |
| //! Poseidon data hashing is recommended for zk use cases. | |
| //! The data struct needs to implement the DataHasher trait. | |
| //! The LightHasher macro derives the DataHasher trait. The hashing scheme resembles the struct layout. | |
| //! Alternatively, DataHasher can be implemented manually. | |
| //! Poseidon hashing is CU intensive and has limitations with regards to hash inputs see Poseidon module for details. |
🤖 Prompt for AI Agents
In sdk-libs/sdk/src/account.rs around lines 13 to 20, fix the minor
grammar/punctuation issue in the documentation sentence "The LightHasher macro
derives, the DataHasher trait." — remove the stray comma and tighten the wording
so it reads clearly (for example: "The LightHasher macro derives the DataHasher
trait.") and ensure punctuation and spacing in surrounding sentences remain
consistent.
Summary by CodeRabbit
New Features
Changes
Removed
✏️ Tip: You can customize this high-level summary in your review settings.