Skip to content

feat(sdk-coin-sol): durable-nonce support in ConfidentialTransferBuilder v1 - #9968

Merged
bhavidhingra merged 1 commit into
masterfrom
bhavi/chalo-1603-sdk-v1-transfer-builder
Oct 15, 2026
Merged

bhavidhingra merged 1 commit into
masterfrom
bhavi/chalo-1603-sdk-v1-transfer-builder

Conversation

@bhavidhingra

Copy link
Copy Markdown
Contributor

Summary

Adds durable-nonce support to the Solana Token-2022 ConfidentialTransferBuilder v1 (SIMD-0296/0385) path, closing the gap where buildV1() did not inject AdvanceNonceAccount (required by compileTransactionMessage for durable nonce) even though V1TransactionBuilder already had the working pattern.

This unblocks wallet-platform's confidential-transfer (CT) v1 submission path (CHALO-1091): the server builds CT transactions with durable nonce, and the gas-tank nonce authority co-signs in message-signer order.

Changes

  • modules/sdk-coin-sol/src/lib/confidentialTransferBuilder.ts
    • buildV1() now mirrors V1TransactionBuilder:
      • Injects AdvanceNonceAccount first when durable nonce is set (nonce address + nonce authority).
      • Assembles signatures in message-signer order (fee payer first, then remaining signers in compiled account order), matching signers by pubkey and zero-filling missing slots — required for multi-signer v1 transactions such as durable-nonce CT (user + gas-tank nonce authority).
      • Carries nonceInfo on the metadata transaction (matching the v0 model).
  • modules/sdk-coin-sol/test/unit/transactionBuilder/confidentialTransferV1.ts
    • New test: durable-nonce CT build — asserts the 0x81 wire, 2 required signers (user + gas-tank nonce authority), nonce blockhash in the message, AdvanceNonceAccount discriminator (4) as the first instruction, and verifyV1Signatures round-trip.

Test plan

  • npx tsc -p tsconfig.json --noEmit — clean.
  • CT v1 suite green (incl. new durable-nonce test); full sol unit suite (873 passing).

Refs: CHALO-1091

@bhavidhingra
bhavidhingra requested a review from a team as a code owner October 14, 2026 13:44
@linear-code

linear-code Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

CHALO-1603

CHALO-1091

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Unit tests are failing on Node 26.x (Current release line, non-blocking). This is not an LTS version yet, so it does not block merge, but it signals an incompatibility to fix before Node 26.x becomes LTS.

View run

@0xPrabh 0xPrabh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

…der v1

Mirror V1TransactionBuilder's buildV1: inject AdvanceNonceAccount first when
durable nonce is set, assemble signatures in message-signer order, and carry
nonceInfo on the metadata transaction. Add a durable-nonce CT build test
asserting the 0x81 wire, 2 signers (user + gas-tank nonce authority), nonce
blockhash, and AdvanceNonceAccount discriminator. (Refs: CHALO-1091)
@bhavidhingra
bhavidhingra force-pushed the bhavi/chalo-1603-sdk-v1-transfer-builder branch from 48a0132 to b089405 Compare October 15, 2026 08:44
@bhavidhingra
bhavidhingra merged commit db6a325 into master Oct 15, 2026
26 checks passed
bhavidhingra added a commit that referenced this pull request Oct 21, 2026
…LO-1883)

- sdk-core: configureAccount opt-out flag flows through BuildTokenEnablementOptions,
  PrebuildTransactionWithIntentOptions, intent payloads, and the BuildParams codec
- sdk-coin-sol: ConfidentialTransferBuilder.createAta accepts CreateAssociatedTokenAccount
  so one v1 tx carries CreateATA + ConfigureAccount + VerifyPubkeyValidity
- sdk-coin-sol: fix ConfigureAccount data layout - add the required 32-byte
  new_account_elgamal_pubkey (span 47 -> 79, matching the on-chain
  ConfigureAccountInstructionData); the PR #9968 layout omitted it and would
  have been rejected on-chain
- sdk-coin-sol: Transaction.fromRawTransaction parses v1 (0x81) wires into a metadata
  SolTransaction (verify/explain no longer assume legacy serialization)
- sdk-coin-sol: verifyTransaction accepts CT enable txs (type ConfidentialTransfer)
  under type enabletoken, keeping token name/address spoof checks
- instructionParamsFactory: preserve CreateATA metadata on ConfidentialTransfer-typed
  parses (CT enablement round-trips keep the ATA entry)
- sdk-coin-sol: CT builder buildV1 now matches the v1 payment builder: injects
  AdvanceNonceAccount for durable nonce and fills signatures in compiled-signer
  order with zero-filled placeholders (server-side unsigned builds keep a valid
  v1 wire)
bhavidhingra added a commit that referenced this pull request Oct 21, 2026
…LO-1883)

- sdk-core: configureAccount opt-out flag flows through BuildTokenEnablementOptions,
  PrebuildTransactionWithIntentOptions, intent payloads, and the BuildParams codec
- sdk-coin-sol: ConfidentialTransferBuilder.createAta accepts CreateAssociatedTokenAccount
  so one v1 tx carries CreateATA + ConfigureAccount + VerifyPubkeyValidity
- sdk-coin-sol: fix ConfigureAccount data layout - add the required 32-byte
  new_account_elgamal_pubkey (span 47 -> 79, matching the on-chain
  ConfigureAccountInstructionData); the PR #9968 layout omitted it and would
  have been rejected on-chain
- sdk-coin-sol: Transaction.fromRawTransaction parses v1 (0x81) wires into a metadata
  SolTransaction (verify/explain no longer assume legacy serialization)
- sdk-coin-sol: verifyTransaction accepts CT enable txs (type ConfidentialTransfer)
  under type enabletoken, keeping token name/address spoof checks
- instructionParamsFactory: preserve CreateATA metadata on ConfidentialTransfer-typed
  parses (CT enablement round-trips keep the ATA entry)
- sdk-coin-sol: CT builder buildV1 now matches the v1 payment builder: injects
  AdvanceNonceAccount for durable nonce and fills signatures in compiled-signer
  order with zero-filled placeholders (server-side unsigned builds keep a valid
  v1 wire)
bhavidhingra added a commit that referenced this pull request Oct 21, 2026
…LO-1883)

- sdk-core: configureAccount opt-out flag flows through BuildTokenEnablementOptions,
  PrebuildTransactionWithIntentOptions, intent payloads, the BuildParams codec and
  the PopulatedIntent type
- sdk-coin-sol: ConfidentialTransferBuilder.createAta emits the idempotent CreateATA
  plus the Token-2022 Reallocate that adds the ConfidentialTransferAccount extension
  (ConfigureAccount fails on-chain without it)
- sdk-coin-sol: fix the ConfigureAccount data layout - add the required 32-byte
  new_account_elgamal_pubkey (span 47 -> 79, matching ConfigureAccountInstructionData);
  the PR #9968 layout omitted it and would have been rejected on-chain
- sdk-coin-sol: Transaction.fromRawTransaction parses v1 (0x81) wires, derives the
  transaction type from the parsed instructions (shared with the legacy path) and
  classifies CreateATA + ConfigureAccount txs as ConfidentialTransfer, not ATA-init
- sdk-coin-sol: verifyTransaction accepts CT enable txs (ConfidentialTransfer) under
  type enabletoken, keeping the token name/address spoof checks
- instructionParamsFactory: preserve CreateATA and CT metadata on CT-typed parses
- sdk-coin-sol: CT buildV1 parity with the v1 payment builder - AdvanceNonceAccount
  injection and compiled-order signature zero-fill for unsigned server builds
- tests: v1 enablement wire (4 instructions incl. Reallocate), CT verify acceptance
  and token-name tamper rejection
bhavidhingra added a commit that referenced this pull request Oct 21, 2026
…LO-1883)

- sdk-core: configureAccount opt-out flag flows through BuildTokenEnablementOptions,
  PrebuildTransactionWithIntentOptions, intent payloads, the BuildParams codec and
  the PopulatedIntent type
- sdk-coin-sol: ConfidentialTransferBuilder.createAta emits the idempotent CreateATA
  plus the Token-2022 Reallocate that adds the ConfidentialTransferAccount extension
  (ConfigureAccount fails on-chain without it)
- sdk-coin-sol: fix the ConfigureAccount data layout - add the required 32-byte
  new_account_elgamal_pubkey (span 47 -> 79, matching ConfigureAccountInstructionData);
  the PR #9968 layout omitted it and would have been rejected on-chain
- sdk-coin-sol: Transaction.fromRawTransaction parses v1 (0x81) wires, derives the
  transaction type from the parsed instructions (shared with the legacy path) and
  classifies CreateATA + ConfigureAccount txs as ConfidentialTransfer, not ATA-init
- sdk-coin-sol: verifyTransaction accepts CT enable txs (ConfidentialTransfer) under
  type enabletoken, keeping the token name/address spoof checks
- instructionParamsFactory: preserve CreateATA and CT metadata on CT-typed parses
- sdk-coin-sol: CT buildV1 parity with the v1 payment builder - AdvanceNonceAccount
  injection and compiled-order signature zero-fill for unsigned server builds
- tests: v1 enablement wire (4 instructions incl. Reallocate), CT verify acceptance
  and token-name tamper rejection
bhavidhingra added a commit that referenced this pull request Oct 21, 2026
…LO-1883)

- sdk-core: configureAccount opt-out flag flows through BuildTokenEnablementOptions,
  PrebuildTransactionWithIntentOptions, intent payloads, the BuildParams codec and
  the PopulatedIntent type
- sdk-coin-sol: ConfidentialTransferBuilder.createAta emits the idempotent CreateATA
  plus the Token-2022 Reallocate that adds the ConfidentialTransferAccount extension
  (ConfigureAccount fails on-chain without it)
- sdk-coin-sol: fix the ConfigureAccount data layout - add the required 32-byte
  new_account_elgamal_pubkey (span 47 -> 79, matching ConfigureAccountInstructionData);
  the PR #9968 layout omitted it and would have been rejected on-chain
- sdk-coin-sol: Transaction.fromRawTransaction parses v1 (0x81) wires, derives the
  transaction type from the parsed instructions (shared with the legacy path) and
  classifies CreateATA + ConfigureAccount txs as ConfidentialTransfer, not ATA-init
- sdk-coin-sol: verifyTransaction accepts CT enable txs (ConfidentialTransfer) under
  type enabletoken, keeping the token name/address spoof checks
- instructionParamsFactory: preserve CreateATA and CT metadata on CT-typed parses
- sdk-coin-sol: CT buildV1 parity with the v1 payment builder - AdvanceNonceAccount
  injection and compiled-order signature zero-fill for unsigned server builds
- tests: v1 enablement wire (4 instructions incl. Reallocate), CT verify acceptance
  and token-name tamper rejection
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