Skip to content

chore: js, load, new call sigs, renames#2316

Merged
SwenSchaeferjohann merged 37 commits into
mainfrom
swen/renames
Mar 12, 2026
Merged

chore: js, load, new call sigs, renames#2316
SwenSchaeferjohann merged 37 commits into
mainfrom
swen/renames

Conversation

@SwenSchaeferjohann
Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 27, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (100)
  • .github/workflows/js-v2.yml is excluded by none and included by none
  • .github/workflows/lint.yml is excluded by none and included by none
  • js/compressed-token/CHANGELOG.md is excluded by none and included by none
  • js/compressed-token/docs/interface.md is excluded by none and included by none
  • js/compressed-token/docs/load-flow-audit.md is excluded by none and included by none
  • js/compressed-token/docs/payment-integration.md is excluded by none and included by none
  • js/compressed-token/package.json is excluded by none and included by none
  • js/compressed-token/src/constants.ts is excluded by none and included by none
  • js/compressed-token/src/index.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/create-associated-light-token.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/create-ata-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/create-mint-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/decompress-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/decompress-mint.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/get-or-create-ata-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/index.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/load-ata.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/mint-to-compressed.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/mint-to-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/slice-last.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/transfer-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/unwrap.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/update-metadata.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/update-mint.ts is excluded by none and included by none
  • js/compressed-token/src/v3/actions/wrap.ts is excluded by none and included by none
  • js/compressed-token/src/v3/assert-v2-only.ts is excluded by none and included by none
  • js/compressed-token/src/v3/ata-utils.ts is excluded by none and included by none
  • js/compressed-token/src/v3/derivation.ts is excluded by none and included by none
  • js/compressed-token/src/v3/errors.ts is excluded by none and included by none
  • js/compressed-token/src/v3/get-account-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/get-mint-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/calculate-combined-cu.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/create-associated-light-token.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/create-ata-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/create-decompress-interface-instruction.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/create-load-accounts-params.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/create-mint.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/decompress-mint.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/freeze-thaw.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/index.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/load-ata.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/mint-to-compressed.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/mint-to-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/mint-to.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/transfer-interface.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/unwrap.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/update-metadata.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/update-mint.ts is excluded by none and included by none
  • js/compressed-token/src/v3/instructions/wrap.ts is excluded by none and included by none
  • js/compressed-token/src/v3/layout/index.ts is excluded by none and included by none
  • js/compressed-token/src/v3/layout/layout-mint-action.ts is excluded by none and included by none
  • js/compressed-token/src/v3/layout/layout-mint.ts is excluded by none and included by none
  • js/compressed-token/src/v3/layout/layout-transfer2.ts is excluded by none and included by none
  • js/compressed-token/src/v3/layout/serde.ts is excluded by none and included by none
  • js/compressed-token/src/v3/unified/index.ts is excluded by none and included by none
  • js/compressed-token/src/v3/utils/estimate-tx-size.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/compress.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/compressible-load.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/create-associated-light-token.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/create-ata-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/create-mint-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/decompress.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/decompress2.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/freeze-thaw-light-token.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/get-account-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/get-mint-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/get-or-create-ata-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/input-selection.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/light-token-account-helpers.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/load-ata-combined.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/load-ata-freeze.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/load-ata-spl-t22.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/load-ata-standard.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/load-ata-unified.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/mint-to-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/mint-to-light-token.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/mint-to.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/multi-cold-inputs-batching.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/multi-cold-inputs.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/payment-flows.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/transfer-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/unwrap.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/v3-interface-migration.test.ts is excluded by none and included by none
  • js/compressed-token/tests/e2e/wrap.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/decompress-interface-version.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/delegate-merge-semantics.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/estimate-tx-size.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/get-account-interface-errors.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/get-associated-token-address-interface.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/get-mint-interface-errors.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/layout-mint-action.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/layout-serde.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/layout-transfer2.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/load-transfer-cu.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/parse-account-fields.test.ts is excluded by none and included by none
  • js/compressed-token/tests/unit/unified-guards.test.ts is excluded by none and included by none
  • js/stateless.js/src/rpc.ts is excluded by none and included by none
  • js/stateless.js/tests/unit/rpc/get-account-info-interface.test.ts is excluded by none and included by none
  • scripts/lint.sh is excluded by none and included by none
  • sdk-tests/csdk-anchor-full-derived-test/tests/integration_tests.rs is excluded by none and included by none

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4a836202-91d1-46f1-aac5-213759500461

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch swen/renames
📝 Coding Plan for PR comments
  • Generate coding plan

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@SwenSchaeferjohann SwenSchaeferjohann marked this pull request as ready for review February 27, 2026 18:24
@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] "c-token" in JSDoc of brand-new freeze-thaw.ts

File: src/v3/instructions/freeze-thaw.ts (lines 18, 25, 29-30, 51, 58, 62-63)

New file uses "c-token" 8 times in JSDoc despite being added on the rename branch. Should say "light-token".

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] CHANGELOG incomplete -- only documents decompressInterface removal

File: CHANGELOG.md

Does not document the many other breaking changes:

  • All CToken -> LightToken renames (createAssociatedCTokenAccountInstruction, CTokenConfig, parseCTokenHot, parseCTokenCold, mintToCToken, etc.)
  • Removed exports (createLoadAccountsParams, calculateCompressibleLoadComputeUnits, associated types)
  • New freeze/thaw instructions
  • Removed layout/serde module

Also uses "c-token" terminology in the new entry (line 6).

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] Test filename uses old naming: freeze-thaw-ctoken.test.ts

File: tests/e2e/freeze-thaw-ctoken.test.ts

Should be freeze-thaw-light-token.test.ts to match the rename effort.

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] Misleading test name: "partial freeze" tests full freeze

File: tests/e2e/freeze-thaw-ctoken.test.ts (lines 646-700)

Test named should throw "Insufficient" when requested amount exceeds unfrozen balance (partial freeze) actually freezes all 600 tokens (not partial). The "Insufficient" assertion is never reached because the frozen check fires first. Either implement the actual partial-freeze scenario or rename the test to match what it actually tests.

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] Unused addressTreeInfo in 10 test cases

File: tests/e2e/create-associated-light-token.test.ts (10 locations)

const addressTreeInfo = getDefaultAddressTreeInfo() is assigned but never referenced in every test case. Remove all 10 instances and the getDefaultAddressTreeInfo import.

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] Unused imports in mint-to-light-token.test.ts

File: tests/e2e/mint-to-light-token.test.ts

  • ComputeBudgetProgram (line 6) is imported but never used
  • findMintAddress (line 22) is imported but never used

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] Magic byte offsets in tests instead of structured deserialization

Files:

  • tests/e2e/freeze-thaw-ctoken.test.ts (lines 48-58)
  • tests/e2e/load-ata-freeze.test.ts (lines 64-80)
  • tests/e2e/decompress2.test.ts (~line 101)

Using info.data[108] and info.data.readBigUInt64LE(64) instead of structured deserialization. The helpers getLightTokenState and getLightTokenBalance are duplicated across two files. Should use parseLightTokenHot from get-account-interface instead, and extract to a shared test helper if raw parsing is needed.

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] Unified index missing freeze/thaw exports

File: src/v3/unified/index.ts

createLightTokenFreezeAccountInstruction and createLightTokenThawAccountInstruction are exported from top-level index.ts but missing from the unified index. This breaks the pattern where the unified index is a superset of available instructions.

@ananas-block
Copy link
Copy Markdown
Contributor

[Warning] Incomplete TLV extension parser

File: src/v3/instructions/create-decompress-interface-instruction.ts (lines 93-100)

parseCompressedOnlyFromTlv SIZES record only covers discriminants 29, 30, 31. Any other extension discriminant causes a silent null return. Consider logging a warning or throwing for unknown discriminants to make the failure mode explicit rather than silent.

const SIZES: Record<number, number | undefined> = {
    29: 8,
    30: 1,
    31: 17,
};
const size = SIZES[disc];
if (size === undefined) return null; // silently fails for unknown extensions

@ananas-block
Copy link
Copy Markdown
Contributor

[Nit] Redundant assertNotFrozen double-call

File: src/v3/instructions/load-ata.ts (line 189 and line 280)

assertNotFrozen is called once in createLoadAtaInstructions and again in _buildLoadBatches. The interface cannot become "more frozen" between the two calls. Remove one (preferably keep the one in _buildLoadBatches since it's also called from other paths).

@ananas-block
Copy link
Copy Markdown
Contributor

[Nit] Redundant spread property

File: src/v3/actions/transfer-interface.ts (~line 72)

owner: options?.owner after ...options spread is a no-op since owner is already included in the spread.

@ananas-block
Copy link
Copy Markdown
Contributor

[Nit] Duplicate imports from same module

File: tests/e2e/create-associated-light-token.test.ts (lines 17-18)

Two separate imports from ../../src/v3/derivation -- combine into one:

import { getAssociatedLightTokenAddress, findMintAddress } from '../../src/v3/derivation';

@ananas-block
Copy link
Copy Markdown
Contributor

[Nit] Unexplained 1-second sleep in test

File: tests/e2e/create-associated-light-token.test.ts (line 480)

Bare await new Promise(resolve => setTimeout(resolve, 1000)) without justification. Use proper transaction confirmation or remove.

@ananas-block
Copy link
Copy Markdown
Contributor

[Nit] Hardcoded program ID strings in tests

File: tests/e2e/create-associated-light-token.test.ts (lines 68, 316, 322, 530)

Uses literal 'cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m' instead of LIGHT_TOKEN_PROGRAM_ID.toBase58(). Using the constant protects against future program ID changes and is more self-documenting.

test cov: offcurve, zero-amounts

test cov: dupe hash failure, v1 reject at ixn boundary

more test cov

load, add freeze thaw, extend test cov

add tests

lint

frozen handling

more tests

mark internals

rm _tryfetchctokencoldbyaddress

cleanups

fmt
@ananas-block
Copy link
Copy Markdown
Contributor

Issue 17/22: OffChainTokenMetadata vs OffChainTokenMetadataJson structurally identical

layout/layout-token-metadata.ts defines two interfaces with identical fields: name, symbol, description?, image?, additionalMetadata?. The function toOffChainMetadataJson just copies fields from one to the other.

@ananas-block
Copy link
Copy Markdown
Contributor

Issue 18/22: Fake '' as TransactionSignature return

actions/decompress-mint.ts:75-76:

if (mintInterface.mintContext?.cmintDecompressed) {
    return '' as TransactionSignature;
}

When the mint is already decompressed, callers get an empty string. Returning null (with updated return type TransactionSignature | null) would be more explicit.

@ananas-block
Copy link
Copy Markdown
Contributor

Issue 19/22: sliceLast generic utility in domain-specific file

sliceLast<T> at actions/transfer-interface.ts:99-104 is a generic array utility with no domain logic. It's imported by actions/unwrap.ts, unified/index.ts, and re-exported from src/index.ts as public API. Should live in a utils module.

@ananas-block
Copy link
Copy Markdown
Contributor

Issue 20/22: Validity proof fetch pattern duplicated 7 times

The same rpc.getValidityProofV2([{ hash, leafIndex, treeInfo, proveByIndex }], [], DerivationMode.compressible) pattern (with the isDecompressed ? null : ... conditional in 5 of 7 cases) appears in:

  • actions/update-metadata.ts (3x: lines 66, 144, 222)
  • actions/update-mint.ts (2x: lines 59, 134)
  • actions/decompress-mint.ts (1x: line 79)
  • actions/mint-to-compressed.ts (1x: line 66)

Could be extracted into a shared helper.

@ananas-block
Copy link
Copy Markdown
Contributor

Issue 21/22: Silent catch {} swallowing all errors

actions/get-or-create-ata-interface.ts has two bare catch blocks:

Line 352-354 in createLightTokenAtaIdempotent:

} catch {
    // Ignore errors - associated token account may already exist
}

Line 406-408 in getOrCreateSplAta:

} catch {
    // Ignore all errors; for now there is no API-compatible way to selectively ignore...
}

Both catch ALL errors (network failures, insufficient funds, etc.), not just "account already exists".

@ananas-block
Copy link
Copy Markdown
Contributor

Issue 22/22: owner always isWritable: true in transfer instructions

Both createLightTokenTransferInstruction (line 89) and createLightTokenTransferCheckedInstruction (line 127) in instructions/transfer-interface.ts unconditionally set owner as isWritable: true.

By contrast, instructions/mint-to.ts:41-43 conditionally sets it:

const authorityWritable = maxTopUp !== undefined && !feePayer;

When a separate fee payer handles top-ups, owner doesn't need to be writable.

@ananas-block
Copy link
Copy Markdown
Contributor

Naming: assertNotFrozen -> checkNotFrozen

assertNotFrozen throws an Error, not an AssertionError. The assert* prefix conventionally implies a runtime assertion (process crash / assertion failure), while this function performs a validation check that throws a recoverable error. Suggest renaming to checkNotFrozen to better communicate the behavior.

@ananas-block
Copy link
Copy Markdown
Contributor

getAtaInterface throws on not-found instead of returning null

getAtaInterface / _getAccountInterface throws TokenAccountNotFoundError when the account doesn't exist. This is inconsistent with Solana's Connection.getAccountInfo() which returns AccountInfo | null.

"Account not found" is an expected condition, not an exceptional one. Using exceptions for control flow forces callers into try/catch for normal cases -- see createLoadAtaInstructions (load-ata.ts:172-187) which catches TokenAccountNotFoundError just to return [].

Suggest changing _getAccountInterface to return AccountInterface | null (null when sources.length === 0) and updating callers to use null checks instead of try/catch. This aligns with Solana conventions and simplifies call sites.

@ananas-block
Copy link
Copy Markdown
Contributor

getMintInterface throws instead of returning null for not-found

getMintInterface throws in three places when accounts aren't found:

  • Line 88-91: "Mint not found: ... Tried TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, and LIGHT_TOKEN_PROGRAM_ID."
  • Line 106: "Light mint not found for ${address}"
  • Line 123-125: "Decompressed light mint account not found on-chain for ${address}"

Return type is Promise<MintInterface> with no null path. This is inconsistent with Solana's Connection.getAccountInfo() which returns AccountInfo | null. "Mint not found" is an expected condition, not an exceptional one. Suggest returning MintInterface | null and letting callers handle with null checks.

@ananas-block
Copy link
Copy Markdown
Contributor

_tryFetchSpl / _tryFetchToken2022 / _tryFetchLightTokenHot conflate not-found and wrong-type

All three functions (get-account-interface.ts lines 424, 450, 476) use the same pattern:

if (!info || !info.owner.equals(PROGRAM_ID)) {
    throw new Error('Not a PROGRAM_ID account');
}

This makes two semantically different cases indistinguishable to the caller:

  • info is null = account doesn't exist
  • info.owner is wrong = account exists but belongs to a different program

By contrast, SPL's unpackAccount properly separates these with TokenAccountNotFoundError vs TokenInvalidAccountOwnerError. Suggest either returning null for not-found (and throwing only for wrong-type), or using distinct error types.

@ananas-block
Copy link
Copy Markdown
Contributor

Silent error swallowing makes RPC failures indistinguishable from empty results

Four .catch blocks in get-account-interface.ts silently convert errors to empty/null:

  • Line 646: coldAccountsPromise.catch(() => ({ items: [] }))
  • Line 837: hotPromise.catch(() => null)
  • Line 843: coldPromise.catch(() => ({ items: [] as any[] }))
  • Lines 652-665: Promise.allSettled rejected results silently skipped

No logging in any of these handlers. A network timeout, RPC permission error, and a genuine "no accounts found" all produce the same result. Callers cannot retry transient failures or detect RPC issues. Suggest at minimum logging caught errors, or propagating them with a flag so callers can distinguish "confirmed empty" from "fetch failed".

@SwenSchaeferjohann SwenSchaeferjohann merged commit 2ac68f1 into main Mar 12, 2026
22 checks passed
@SwenSchaeferjohann SwenSchaeferjohann deleted the swen/renames branch March 12, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants