Skip to content

chore: js sdk beta fixes#2354

Merged
SwenSchaeferjohann merged 7 commits intomainfrom
swen/transferToAccountinterface
Mar 20, 2026
Merged

chore: js sdk beta fixes#2354
SwenSchaeferjohann merged 7 commits intomainfrom
swen/transferToAccountinterface

Conversation

@SwenSchaeferjohann
Copy link
Contributor

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (14)
  • 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/payment-integration.md 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/transfer-interface.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/unified/index.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/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/v3-interface-migration.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

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: 67173bf2-30d6-4da6-ba7f-27a2880ac7d8

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
  • Commit unit tests in branch swen/transferToAccountinterface
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@ananas-block
Copy link
Contributor

TransferToAccountOptions / TransferOptions duplication

There are now two names for the same shape:

export interface TransferToAccountOptions extends InterfaceOptions {
    wrap?: boolean;
    programId?: PublicKey;
}
export type TransferOptions = TransferToAccountOptions;

TransferToAccountOptions is only used in three places internally (actions/transfer-interface.ts:172, unified/index.ts:41,388,496). TransferOptions is the older public name and is still wired into instructions/transfer-interface.ts and re-exported from the unified path.

Could we just drop TransferToAccountOptions and the alias, and keep TransferOptions as the one canonical name? That would mean:

  • delete the TransferToAccountOptions interface
  • delete export type TransferOptions = TransferToAccountOptions
  • replace the three internal TransferToAccountOptions references with TransferOptions

No public API change, one fewer type.

@ananas-block
Copy link
Contributor

Dead code: batches.length === 0 guard at actions/transfer-interface.ts:204

if (batches.length === 0) return [[ensureRecipientAtaIx]];

createTransferToAccountInterfaceInstructions never returns an empty array — every non-throwing path returns at least [[CU, transferIx]]. This guard is unreachable and can be deleted.

@ananas-block
Copy link
Contributor

Redundant pre-conversion in transferToAccountInterface (actions/transfer-interface.ts:63)

const amountBigInt = BigInt(amount.toString()); // line 63

The underlying builder (createTransferToAccountInterfaceInstructions in instructions/transfer-interface.ts) always converts amount itself at line 156, so this pre-conversion is a no-op. transferInterface correctly passes amount raw. The fix is to remove the pre-conversion in transferToAccountInterface (and the amountBigInt variable) so both action functions are consistent.

@ananas-block
Copy link
Contributor

Duplicate send loop and source validation in actions/transfer-interface.ts

transferInterface and transferToAccountInterface share two identical blocks verbatim.

Send loop (lines 82–93 and 142–153):

const additionalSigners = dedupeSigner(payer, [owner]);
const { rest: loads, last: transferIxs } = sliceLast(batches);
await Promise.all(loads.map(async ixs => {
    const { blockhash } = await rpc.getLatestBlockhash();
    const tx = buildAndSignTx(ixs, payer, blockhash, additionalSigners);
    return sendAndConfirmTx(rpc, tx, confirmOptions);
}));
const { blockhash } = await rpc.getLatestBlockhash();
const tx = buildAndSignTx(transferIxs, payer, blockhash, additionalSigners);
return sendAndConfirmTx(rpc, tx, confirmOptions);

Source validation (lines 50–61 and 112–123):

const effectiveOwner = options?.owner ?? owner.publicKey;
const expectedSource = getAssociatedTokenAddressInterface(mint, effectiveOwner, false, programId);
if (!source.equals(expectedSource)) {
    throw new Error(`Source mismatch. Expected ${expectedSource.toBase58()}, got ${source.toBase58()}`);
}

Both could be extracted into private helpers, e.g. validateSource(...) and executeBatches(...), reducing the file by ~25 lines and making future changes to the send logic apply in one place.

tilo-14 pushed a commit that referenced this pull request Mar 19, 2026
Update transferDelegatedInterface and
createTransferDelegatedInterfaceInstructions to accept a recipient
wallet address instead of an explicit destination token account,
matching the transferInterface convention from PR #2354.

ATA derivation and idempotent creation now happen internally for
all programId variants (light-token, SPL, Token-2022).
@SwenSchaeferjohann SwenSchaeferjohann merged commit b61099f into main Mar 20, 2026
15 checks passed
tilo-14 pushed a commit that referenced this pull request Mar 20, 2026
Update transferDelegatedInterface and
createTransferDelegatedInterfaceInstructions to accept a recipient
wallet address instead of an explicit destination token account,
matching the transferInterface convention from PR #2354.

ATA derivation and idempotent creation now happen internally for
all programId variants (light-token, SPL, Token-2022).
@ananas-block ananas-block deleted the swen/transferToAccountinterface branch March 20, 2026 11:46
SwenSchaeferjohann added a commit that referenced this pull request Mar 21, 2026
* feat(compressed-token): add approve/revoke delegation for light-token ATAs

Add TypeScript SDK functions to call the on-chain CTokenApprove (discriminator 4)
and CTokenRevoke (discriminator 5) instruction handlers for light-token associated
token accounts.

New files:
- instructions/approve-revoke.ts: sync instruction builders matching Rust SDK layout
- actions/approve-interface.ts: async actions with cold loading + tx sending
- tests/e2e/approve-revoke-light-token.test.ts: unit + E2E tests

Also adds getLightTokenDelegate helper and extends FrozenOperation type.

* fix(sdk): make decimals optional in unified approve/revoke wrappers

Avoid unnecessary getMintInterface RPC call when caller provides decimals.

* feat(sdk): add transferDelegated for light-token ATAs

Add transferDelegatedInterface action and unified wrapper, completing
the approve → transfer → revoke delegation flow for light-token ATAs.

* add spl t22 support

* refactor(sdk): align transferDelegated with wallet-recipient API

Update transferDelegatedInterface and
createTransferDelegatedInterfaceInstructions to accept a recipient
wallet address instead of an explicit destination token account,
matching the transferInterface convention from PR #2354.

ATA derivation and idempotent creation now happen internally for
all programId variants (light-token, SPL, Token-2022).

* 1st batch commnets

* docs(sdk): document load-all behavior in approve/revoke JSDoc; add owner==feePayer E2E test

Add @remarks to approve/revoke functions documenting that for light-token
mints, all cold (compressed) balances are loaded into the hot ATA regardless
of the delegation amount. Add E2E test covering the owner==feePayer code
path which was previously only tested at the unit level.

* add regression tests

* fixes

* update changelog

* upd changelog

* fix: packedaccounts in js should not turn bool to number

* cherry pick bool fix

* bump versions again

---------

Co-authored-by: tilo-14 <tilo@luminouslabs.com>
Co-authored-by: Swenschaeferjohann <swen@lightprotocol.com>
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