@cloak.dev/sdk 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,13 +5,13 @@ per-mint pool, send privately inside the pool, withdraw to any address, or swap
5
5
  USDC/USDT with the output landing in a public token account. Groth16 proofs are generated
6
6
  client-side (snarkjs) and verified on-chain by the Cloak program.
7
7
 
8
- Version 0.2.0 targets the mainnet program deployed on 2026-08-24 and the ceremony-frozen
8
+ Version 0.2.3 targets the mainnet program deployed on 2026-08-24 and the ceremony-frozen
9
9
  `cloak-transaction-0.2.0` circuit bundle. See [Version and compatibility](#version-and-compatibility).
10
10
 
11
11
  ## Installation
12
12
 
13
13
  ```bash
14
- npm install @cloak.dev/sdk@^0.2.0 @solana/web3.js
14
+ npm install @cloak.dev/sdk@^0.2.3 @solana/web3.js
15
15
  # swaps and SPL pools also need:
16
16
  npm install @solana/spl-token
17
17
  ```
@@ -376,8 +376,11 @@ await transact(
376
376
  ```
377
377
 
378
378
  Minimum SPL deposit is 1.00 token. SOL deposits fit in a single v0 packet with the production
379
- lookup table; SPL deposits currently still create a small supplemental lookup table
380
- (about 0.0056 SOL rent, reclaimable by the depositor).
379
+ lookup table; SPL deposits by default create a small depositor-signed supplemental lookup table
380
+ (about 0.0056 SOL rent, reclaimable by the depositor), which costs a second wallet signature. Set
381
+ `relaySupplementalAlt: true` in `TransactOptions` to ask the relay to extend its own shared lookup
382
+ table instead, cutting an SPL deposit to one signature; off by default, and any relay-side failure
383
+ falls back automatically to the depositor-signed path above with no caller action needed.
381
384
 
382
385
  ### Shielded swap (SOL to USDC/USDT)
383
386
 
@@ -565,7 +568,7 @@ Deposits and private sends carry no protocol fee.
565
568
  A withdrawal or swap must exceed its fee or the program rejects it; deposits below the minimum are
566
569
  rejected with `DepositTooSmall`.
567
570
 
568
- `shared/fees.ts` mirrors the SOL pool for estimates in the UI:
571
+ `src/shared/fees.ts` mirrors the SOL pool for estimates in the UI:
569
572
 
570
573
  ```ts
571
574
  import { calculateFeeBigint, getDistributableAmount, isWithdrawAmountSufficient } from "@cloak.dev/sdk";
@@ -577,7 +580,8 @@ isWithdrawAmountSufficient(6_000_000n); // true: 0.006 SOL covers the 0.005018
577
580
 
578
581
  For USDC/USDT compute `450_000n + amount * 3n / 1000n`. Treat these as estimates: the deployed
579
582
  `PoolConfig` is the source of truth. Solana transaction fees and, for SPL deposits, the supplemental
580
- lookup-table rent are separate.
583
+ lookup-table rent are separate (see `relaySupplementalAlt` under [SPL pools](#spl-pools-usdc-usdt)
584
+ for cutting that rent's signature cost).
581
585
 
582
586
  ## Circuit artifacts
583
587
 
@@ -623,12 +627,15 @@ relay endpoint and the localhost-RPC check.
623
627
 
624
628
  ## Version and compatibility
625
629
 
626
- - SDK 0.2.0 pairs with the mainnet program at `zh1eLd6rSphLejbFfJEneUwzHRfMKxgzrgkfwA6qRkW`
627
- (deployed 2026-08-24) and the 0.2.0 circuit bundle. All flows in this README were exercised on
630
+ - SDK 0.2.3 pairs with the mainnet program at `zh1eLd6rSphLejbFfJEneUwzHRfMKxgzrgkfwA6qRkW`
631
+ (deployed 2026-08-24) and the 0.2.0 circuit bundle the program and circuit bundle are unchanged
632
+ since 0.2.0; only the SDK package version has moved. All flows in this README were exercised on
628
633
  mainnet on 2026-08-25: deposit, private send and withdraw on SOL, USDC and USDT; swaps SOL to
629
634
  USDC and USDT; viewing-key discovery followed by a spend; keypair-only deposit recovery.
635
+ - 0.2.2 adds the opt-in `TransactOptions.relaySupplementalAlt` (see [SPL pools](#spl-pools-usdc-usdt)):
636
+ off by default, and existing behavior is unchanged when it is left unset.
630
637
  - Proofs generated with the 0.1.x circuits are rejected by the mainnet program. SDK 0.1.x builds
631
- (which ship the 0.1.0 bundle) are not usable against it; upgrade to 0.2.0.
638
+ (which ship the 0.1.0 bundle) are not usable against it; upgrade to 0.2.x.
632
639
  - The note-based `CloakSDK` class is removed in 0.2.0. It targeted the pre-0.2.0 instruction layout
633
640
  and the unpublished 0.1.0 `withdraw_*` circuits, so it could not work against the current program.
634
641
  Use the UTXO API above: `transact`, `transfer`, `partialWithdraw`, `fullWithdraw`, `swapUtxo`.
@@ -712,8 +719,7 @@ npm run test:examples # dry-run the examples
712
719
  ```
713
720
 
714
721
  Notes: `docs/DEPOSIT-SIZE-NOTES.md` (deposit transaction size, confirmed-tree reads,
715
- supplemental lookup tables), `docs/transact-split.md` (how `flows/transact.ts` is split),
716
- `docs/cleanup-plan.md` (the root/scripts/examples cleanup this repo is executing).
722
+ supplemental lookup tables), `docs/transact-split.md` (how `flows/transact.ts` is split).
717
723
 
718
724
  ## Links
719
725
 
package/dist/index.cjs CHANGED
@@ -589,6 +589,7 @@ __export(index_exports, {
589
589
  VARIABLE_FEE_RATE: () => VARIABLE_FEE_RATE,
590
590
  VERSION: () => VERSION,
591
591
  assertDirectSubmissionLanded: () => assertDirectSubmissionLanded,
592
+ assertInputMints: () => assertInputMints,
592
593
  assertTransactionCircuitIntegrity: () => assertTransactionCircuitIntegrity,
593
594
  bigintToBytes32: () => bigintToBytes32,
594
595
  bigintToHex: () => bigintToHex,
@@ -6220,6 +6221,23 @@ async function computeSwapExtDataHash(outputMint, recipientAta, minOutputAmount,
6220
6221
  ]);
6221
6222
  return poseidonHasher.F.toObject(hash);
6222
6223
  }
6224
+ function assertInputMints(inputUtxos, expectedMint) {
6225
+ const funded = inputUtxos.filter((u) => u.amount > BigInt(0));
6226
+ if (funded.length === 0) return;
6227
+ const first = funded[0].mintAddress;
6228
+ for (const utxo of funded) {
6229
+ if (!utxo.mintAddress.equals(first)) {
6230
+ throw new Error(
6231
+ `Input notes span more than one mint (${first.toBase58()} and ${utxo.mintAddress.toBase58()}). Every pool holds a single mint, so this cannot be a valid spend of either. Select notes of one mint.`
6232
+ );
6233
+ }
6234
+ }
6235
+ if (expectedMint && !first.equals(expectedMint)) {
6236
+ throw new Error(
6237
+ `Input notes are ${first.toBase58()} but this transaction expects ${expectedMint.toBase58()}. The notes decide which pool is spent, so proceeding would move the wrong asset \u2014 refusing. This usually means note selection ignored the mint.`
6238
+ );
6239
+ }
6240
+ }
6223
6241
  function parseNkInput(input) {
6224
6242
  if (typeof input !== "string") {
6225
6243
  if (input.length !== 32) {
@@ -7886,6 +7904,7 @@ async function transact(params, options) {
7886
7904
  }
7887
7905
  }
7888
7906
  assertAllowedRpcConnection(connection);
7907
+ assertInputMints(inputUtxos, options.expectedMint);
7889
7908
  await ensureViewingKeyRegistered(options, onProgress, fallbackNk);
7890
7909
  const resolvedChainNoteNk = explicitChainNoteNk ?? fallbackNk ?? null;
7891
7910
  if (inputUtxos.length > 2) {
@@ -9128,6 +9147,12 @@ async function swapUtxo(params, options) {
9128
9147
  if (inputUtxos.length > 2) {
9129
9148
  throw new Error("Maximum 2 input UTXOs allowed");
9130
9149
  }
9150
+ assertInputMints(inputUtxos, NATIVE_SOL_MINT);
9151
+ if (options.expectedMint && !options.expectedMint.equals(NATIVE_SOL_MINT)) {
9152
+ throw new Error(
9153
+ `swapUtxo expects ${NATIVE_SOL_MINT.toBase58()} input notes (a swap always spends from the wSOL pool), but expectedMint was ${options.expectedMint.toBase58()}. Drop expectedMint, or spend the other mint with transact/transfer instead.`
9154
+ );
9155
+ }
9131
9156
  await preflightNullifiers(inputUtxos, connection, programId);
9132
9157
  const outputMintAccount = await connection.getAccountInfo(outputMint, {
9133
9158
  commitment: "confirmed"
@@ -11633,7 +11658,7 @@ var SimpleWallet = class {
11633
11658
  };
11634
11659
 
11635
11660
  // src/index.ts
11636
- var VERSION = "0.2.1";
11661
+ var VERSION = "0.2.3";
11637
11662
  var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
11638
11663
  // Annotate the CommonJS export names for ESM import in node:
11639
11664
  0 && (module.exports = {
@@ -11684,6 +11709,7 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
11684
11709
  VARIABLE_FEE_RATE,
11685
11710
  VERSION,
11686
11711
  assertDirectSubmissionLanded,
11712
+ assertInputMints,
11687
11713
  assertTransactionCircuitIntegrity,
11688
11714
  bigintToBytes32,
11689
11715
  bigintToHex,
package/dist/index.d.cts CHANGED
@@ -2931,6 +2931,27 @@ interface ExternalFeePayerAdapter {
2931
2931
  */
2932
2932
  getPaymentAccountHints?: () => Promise<PublicKey[]>;
2933
2933
  }
2934
+ /**
2935
+ * Refuse a transaction whose input notes do not agree on a mint, or do not
2936
+ * agree with the mint the caller says it is spending.
2937
+ *
2938
+ * TWO SEPARATE PROPERTIES, and they catch different mistakes:
2939
+ *
2940
+ * 1. HOMOGENEITY, always enforced. Every pool is a single mint, so a set of
2941
+ * inputs spanning two mints cannot be a valid spend of either. There is no
2942
+ * legitimate call that does this, so it needs no opt-in. Zero-amount
2943
+ * padding notes are exempt: they are placeholders, not value.
2944
+ *
2945
+ * 2. INTENT, enforced when `options.expectedMint` is given. Homogeneity alone
2946
+ * cannot catch the dangerous case — ONE note of the wrong mint is a
2947
+ * perfectly homogeneous set. Only the caller knows which asset the user
2948
+ * asked for, so only the caller can supply it, and this is where it is
2949
+ * checked.
2950
+ *
2951
+ * The error names both mints, because the whole failure mode is that the two
2952
+ * were assumed to be the same.
2953
+ */
2954
+ declare function assertInputMints(inputUtxos: Utxo[], expectedMint?: PublicKey): void;
2934
2955
  /**
2935
2956
  * Options for transact operation
2936
2957
  */
@@ -3184,6 +3205,31 @@ interface TransactOptions {
3184
3205
  * transaction. Omit for unchanged default behavior.
3185
3206
  */
3186
3207
  externalFeePayer?: ExternalFeePayerAdapter;
3208
+ /**
3209
+ * The mint the CALLER believes it is spending. When set, the SDK refuses the
3210
+ * transaction if the input notes say otherwise.
3211
+ *
3212
+ * ── Why this exists ────────────────────────────────────────────────────────
3213
+ * Every flow takes the pool from the notes it is handed
3214
+ * (`inputUtxos[0].mintAddress`), which is correct — the notes are the source
3215
+ * of truth for which pool they belong to. But it means the SDK cannot tell a
3216
+ * deliberate USDC withdrawal from a SOL withdrawal that was handed a USDC
3217
+ * note by mistake. Both are well-formed, both prove, and both settle.
3218
+ *
3219
+ * A consumer hit exactly that: its note selector sorted by RAW base units
3220
+ * across a store holding every mint, so with 6-decimal USDC and 9-decimal
3221
+ * SOL a stablecoin note outranked every SOL note whenever
3222
+ * `usdc > 1000 * sol`. A user sending 0.05 SOL moved ~50 USDC to the
3223
+ * recipient instead, and every layer reported SOL.
3224
+ *
3225
+ * Nothing about that is a protocol failure — the proof, the nullifier and the
3226
+ * pool accounting are all correct, and the user spent their own note. It is a
3227
+ * failure of INTENT, and intent is the one thing only the caller knows. So
3228
+ * the caller may now state it, and the SDK will hold it.
3229
+ *
3230
+ * Optional for backward compatibility, but pass it on every flow you can.
3231
+ */
3232
+ expectedMint?: PublicKey;
3187
3233
  }
3188
3234
  /**
3189
3235
  * Switchboard-style response: a pre-built instruction.
@@ -4674,8 +4720,8 @@ declare class SimpleWallet {
4674
4720
  * @packageDocumentation
4675
4721
  */
4676
4722
 
4677
- declare const VERSION = "0.2.1";
4723
+ declare const VERSION = "0.2.3";
4678
4724
  /** True when scanner supports TransactSwap (tag 1). Check this to verify the correct SDK bundle is loaded. */
4679
4725
  declare const SCANNER_SUPPORTS_TRANSACT_SWAP = true;
4680
4726
 
4681
- export { BUILD_ALLOWS_LOCAL_ENDPOINTS, type BuildRecipientDeliveryNotesParams, CHAIN_NOTE_SALT_BITS, CLOAK_PRODUCTION_RELAY_URL, CLOAK_PROGRAM_ID, type ChainNoteTxType, type CircuitVerificationResult, type CloakConfig, CloakError, type CloakKeyPair, type CloakNote, type CommitmentEntry, type CommitmentsResponse, type CompactChainNote, type ComplianceReport, type ComplianceTxType, type ConfirmSettlementParams, DEFAULT_CIRCUITS_URL, DEFAULT_TRANSACTION_CIRCUITS_URL, DELIVERY_MEMO_TAG, DELIVERY_REGISTRY_SEED, type DeliveredNote, type DepositInstructionParams, type DepositNoteSecrets, type DepositOptions, type DepositResult, type DepositStatus, type DiscoverSwapRefundsOptions, type DiscoveredSwapRefund, EXPECTED_CIRCUIT_HASHES, type EncryptedMetadataBundle, type EncryptedNote$1 as EncryptedNote, type ErrorCategory, type ExpandedSpendKey, type ExternalFeePayerAdapter, FIXED_FEE_LAMPORTS, type Groth16Proof, InsecureRandomnessError, LAMPORTS_PER_SOL, LocalStorageAdapter, type LogLevel, type Logger, MERKLE_TREE_HEIGHT, MIN_DEPOSIT_LAMPORTS, type MasterKey, type MatchChangeNoteParams, type MatchDepositNoteParams, type MatchSwapRefundLeafParams, type MaxLengthArray, MemoryStorageAdapter, type MerkleProof, type MerkleRootResponse, MerkleTree, NATIVE_SOL_MINT, type Network, type NoteData, type OnchainMerkleProof, type ParsedDeliveryCarrier, type PendingDeposit, type PendingWithdrawal, RECIPIENT_DELIVERY_CIPHERTEXT_LEN, RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN, RECIPIENT_DELIVERY_NONCE_LEN, RECIPIENT_DELIVERY_NOTE_BYTES, RECIPIENT_DELIVERY_PLAINTEXT_LEN, RECIPIENT_DELIVERY_TAG_LEN, RELAY_ORIGIN_ALLOWLIST, REQUEST_AUTH_MAX_AGE_SECONDS, REQUEST_AUTH_MAX_FUTURE_SKEW_SECONDS, type RecipientDeliveryNote, type RecoveredChangeNote, type RecoveredChangeNoteRecord, type RecoveredDepositNote, type RecoveredDepositNoteRecord, type RecoveredSwapRefund, type RelayAuthPreimage, type RelayAuthSigner, RelayInternalError, RelayService, type RelaySubmissionResult, type RiskQuoteInstructionResponse, RootNotFoundError, SCANNER_SUPPORTS_TRANSACT_SWAP, SIGN_IN_MESSAGE, SanctionsQuoteError, type ScanOptions, type ScanRecipientDeliveryOptions, type ScanResult, type ScanSummary, type ScannedTransaction, type SettlementConnection, type SettlementContext, type SettlementStatus, type SettlementVerdict, SettlementVerificationError, ShieldPoolErrors, type ShieldPoolPDAs, SimpleWallet, type SpendKey, type StorageAdapter, type SubmitTransactToRelayArgs, type SwapOptions, type SwapParams, type SwapRefundAuthorization, type SwapResult, TRANSACTION_CIRCUITS_VERSION, TRANSACT_AUTH_FIELDS, TRANSACT_SWAP_AUTH_FIELDS, type TransactOptions, type TransactParams, type TransactRequestBodyParams, type TransactResult, type TransactionMetadata, type Transfer, type TransferOptions, type TransferResult, type TxStatus, type UserFriendlyError, type Utxo, UtxoAlreadySpentError, type EncryptedNote as UtxoEncryptedNote, type UtxoKeypair, type UtxoSwapParams, type UtxoSwapResult, UtxoWallet, VARIABLE_FEE_DENOMINATOR, VARIABLE_FEE_NUMERATOR, VARIABLE_FEE_RATE, VERSION, type VerifyUtxosResult, type ViewKey, type ViewingKeyPair, type WalletAdapter, type WalletUtxo, type WithdrawOptions, type WithdrawSubmissionResult, assertDirectSubmissionLanded, assertTransactionCircuitIntegrity, bigintToBytes32$1 as bigintToBytes32, bigintToHex, buildMerkleTree, buildMerkleTreeFromChain, buildMerkleTreeFromRelay, buildRecipientDeliveryNotes, buildRelayAuthPreimage, buildTransactRequestBody, bytesToHex, calculateFee, calculateFeeBigint, calculateRelayFee, canRebuildMerkleTreeFromChain, canonicalJson, chainNoteFromBase64, chainNoteToBase64, classifyRelayError, cleanupStalePendingOperations, clearPendingDeposits, clearPendingWithdrawals, computeChainNoteHash, computeExtDataHash, computeMerkleRoot, computeProofForLatestDeposit, computeProofFromChain, computeSignature, computeSwapRefundCommitment, computeCommitment as computeUtxoCommitment, computeNullifier as computeUtxoNullifier, confirmTransactSettlement, copyNoteToClipboard, createCloakError, createDepositInstruction, createLogger, createRecoverableChangeUtxo, createRecoverableDepositUtxo, createUtxo, createZeroUtxo, decryptCompactChainNote, decryptComplianceMetadataWithMasterKey, decryptTransactionMetadata, deriveChangeNoteBlinding, deriveDepositNoteSecrets, deriveDiversifiedViewingKey, deriveDiversifier, deriveInputNullifierPdas, derivePublicKey, deriveSpendKey, deriveSwapRefundAuthorization, deriveUserCompliancePublicKey, deriveUserComplianceScalar, deriveUtxoKeypairFromSpendKey, deriveViewKey, deriveViewingKeyFromNk, deriveViewingKeyFromSpendKey, deriveViewingKeyFromUtxoPrivateKey, deserializeUtxo, detectNetworkFromRpcUrl, discoverSwapRefunds, downloadNote, encodeDeliveryCarrierMemo, encodeNoteSimple, encodeRecipientDeliveryNote, encryptCompactChainNote, encryptNoteForRecipient, encryptTransactionMetadata, encryptTransactionMetadataBundle, expandSpendKey, explainRelayAuthRejection, exportKeys, exportNote, exportWalletKeys, fetchCommitments, fetchRiskQuoteInstruction, fetchRiskQuoteIx, filterNotesByNetwork, filterWithdrawableNotes, findNoteByCommitment, formatAmount, formatComplianceCsv, formatErrorForLogging, formatSol, fullWithdraw, generateCloakKeys, generateCommitmentAsync, generateMasterSeed, generateNoteFromWallet, generateUtxoKeypair, generateViewingKeyPair, getAddressExplorerUrl, getChainNoteRegistryPDA, getCircuitsPath, getDeliveryRegistryPDA, getDistributableAmount, getExplorerUrl, getNkFromUtxoPrivateKey, getNullifierPDA, getPendingOperationsSummary, getPoolAuthorityConfigPDA, getPublicKey, getPublicViewKey, getRecipientAmount, getRpcUrlForNetwork, getShieldPoolPDAs, getSwapStatePDA, getViewKey, hasPendingOperations, hexToBigint$1 as hexToBigint, hexToBytes, importKeys, importWalletKeys, isBrowser, isBrowserLike, isDebugEnabled, isPlausibleSignature, isReactNative, isRootNotFoundError, isSubmissionOutcomeUnknownResponse, isValidHex, isValidRpcUrl, isValidSolanaAddress, isWithdrawAmountSufficient, isWithdrawable, keypairToAdapter, loadPendingDeposits, loadPendingWithdrawals, loadVerifiedCircuitArtifacts, matchChangeNote, matchDepositNote, matchSwapRefundLeaf, openRecipientDeliveryNote, parseAmount, parseDeliveryCarrierMemo, parseError, parseNote, parseRelayErrorResponse, parseRelayErrorSignature, parseTransactionError, partialWithdraw, poseidonHash, preflightCheck, preflightNullifiers, prepareEncryptedOutput, prepareEncryptedOutputForRecipient, proofToBytes, pubkeyToFieldElement, pubkeyToLimbs, randomBytes, randomChangeNoteSalt, randomDepositNoteSalt, randomFieldElement, readMerkleTreeState, recipientDeliveryNoteToBase64, registerViewingKey, removePendingDeposit, removePendingWithdrawal, resolveCircuitsBase, savePendingDeposit, savePendingWithdrawal, scanNotesForWallet, scanRecipientDeliveryNotes, scanTransactions, sdkLogger, selectUtxos, sendTransaction, serializeNote, serializeUtxo, setCircuitsPath, setDebugMode, signTransaction, splitTo2Limbs, submitTransactToRelay, sumUtxoAmounts, swapUtxo, swapWithChange, toComplianceReport, transact, transfer, truncate, tryDecryptNote, updateNoteWithDeposit, updatePendingDeposit, updatePendingWithdrawal, bigintToBytes32 as utxoBigintToBytes32, utxoEquals, hexToBigint as utxoHexToBigint, validateDepositParams, validateNote, validateOutputsSum, validateRoot, validateTransfers, validateWalletConnected, validateWithdrawableNote, verifyAllCircuits, verifyCircuitIntegrity, verifyUtxos, waitForRoot, withTiming };
4727
+ export { BUILD_ALLOWS_LOCAL_ENDPOINTS, type BuildRecipientDeliveryNotesParams, CHAIN_NOTE_SALT_BITS, CLOAK_PRODUCTION_RELAY_URL, CLOAK_PROGRAM_ID, type ChainNoteTxType, type CircuitVerificationResult, type CloakConfig, CloakError, type CloakKeyPair, type CloakNote, type CommitmentEntry, type CommitmentsResponse, type CompactChainNote, type ComplianceReport, type ComplianceTxType, type ConfirmSettlementParams, DEFAULT_CIRCUITS_URL, DEFAULT_TRANSACTION_CIRCUITS_URL, DELIVERY_MEMO_TAG, DELIVERY_REGISTRY_SEED, type DeliveredNote, type DepositInstructionParams, type DepositNoteSecrets, type DepositOptions, type DepositResult, type DepositStatus, type DiscoverSwapRefundsOptions, type DiscoveredSwapRefund, EXPECTED_CIRCUIT_HASHES, type EncryptedMetadataBundle, type EncryptedNote$1 as EncryptedNote, type ErrorCategory, type ExpandedSpendKey, type ExternalFeePayerAdapter, FIXED_FEE_LAMPORTS, type Groth16Proof, InsecureRandomnessError, LAMPORTS_PER_SOL, LocalStorageAdapter, type LogLevel, type Logger, MERKLE_TREE_HEIGHT, MIN_DEPOSIT_LAMPORTS, type MasterKey, type MatchChangeNoteParams, type MatchDepositNoteParams, type MatchSwapRefundLeafParams, type MaxLengthArray, MemoryStorageAdapter, type MerkleProof, type MerkleRootResponse, MerkleTree, NATIVE_SOL_MINT, type Network, type NoteData, type OnchainMerkleProof, type ParsedDeliveryCarrier, type PendingDeposit, type PendingWithdrawal, RECIPIENT_DELIVERY_CIPHERTEXT_LEN, RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN, RECIPIENT_DELIVERY_NONCE_LEN, RECIPIENT_DELIVERY_NOTE_BYTES, RECIPIENT_DELIVERY_PLAINTEXT_LEN, RECIPIENT_DELIVERY_TAG_LEN, RELAY_ORIGIN_ALLOWLIST, REQUEST_AUTH_MAX_AGE_SECONDS, REQUEST_AUTH_MAX_FUTURE_SKEW_SECONDS, type RecipientDeliveryNote, type RecoveredChangeNote, type RecoveredChangeNoteRecord, type RecoveredDepositNote, type RecoveredDepositNoteRecord, type RecoveredSwapRefund, type RelayAuthPreimage, type RelayAuthSigner, RelayInternalError, RelayService, type RelaySubmissionResult, type RiskQuoteInstructionResponse, RootNotFoundError, SCANNER_SUPPORTS_TRANSACT_SWAP, SIGN_IN_MESSAGE, SanctionsQuoteError, type ScanOptions, type ScanRecipientDeliveryOptions, type ScanResult, type ScanSummary, type ScannedTransaction, type SettlementConnection, type SettlementContext, type SettlementStatus, type SettlementVerdict, SettlementVerificationError, ShieldPoolErrors, type ShieldPoolPDAs, SimpleWallet, type SpendKey, type StorageAdapter, type SubmitTransactToRelayArgs, type SwapOptions, type SwapParams, type SwapRefundAuthorization, type SwapResult, TRANSACTION_CIRCUITS_VERSION, TRANSACT_AUTH_FIELDS, TRANSACT_SWAP_AUTH_FIELDS, type TransactOptions, type TransactParams, type TransactRequestBodyParams, type TransactResult, type TransactionMetadata, type Transfer, type TransferOptions, type TransferResult, type TxStatus, type UserFriendlyError, type Utxo, UtxoAlreadySpentError, type EncryptedNote as UtxoEncryptedNote, type UtxoKeypair, type UtxoSwapParams, type UtxoSwapResult, UtxoWallet, VARIABLE_FEE_DENOMINATOR, VARIABLE_FEE_NUMERATOR, VARIABLE_FEE_RATE, VERSION, type VerifyUtxosResult, type ViewKey, type ViewingKeyPair, type WalletAdapter, type WalletUtxo, type WithdrawOptions, type WithdrawSubmissionResult, assertDirectSubmissionLanded, assertInputMints, assertTransactionCircuitIntegrity, bigintToBytes32$1 as bigintToBytes32, bigintToHex, buildMerkleTree, buildMerkleTreeFromChain, buildMerkleTreeFromRelay, buildRecipientDeliveryNotes, buildRelayAuthPreimage, buildTransactRequestBody, bytesToHex, calculateFee, calculateFeeBigint, calculateRelayFee, canRebuildMerkleTreeFromChain, canonicalJson, chainNoteFromBase64, chainNoteToBase64, classifyRelayError, cleanupStalePendingOperations, clearPendingDeposits, clearPendingWithdrawals, computeChainNoteHash, computeExtDataHash, computeMerkleRoot, computeProofForLatestDeposit, computeProofFromChain, computeSignature, computeSwapRefundCommitment, computeCommitment as computeUtxoCommitment, computeNullifier as computeUtxoNullifier, confirmTransactSettlement, copyNoteToClipboard, createCloakError, createDepositInstruction, createLogger, createRecoverableChangeUtxo, createRecoverableDepositUtxo, createUtxo, createZeroUtxo, decryptCompactChainNote, decryptComplianceMetadataWithMasterKey, decryptTransactionMetadata, deriveChangeNoteBlinding, deriveDepositNoteSecrets, deriveDiversifiedViewingKey, deriveDiversifier, deriveInputNullifierPdas, derivePublicKey, deriveSpendKey, deriveSwapRefundAuthorization, deriveUserCompliancePublicKey, deriveUserComplianceScalar, deriveUtxoKeypairFromSpendKey, deriveViewKey, deriveViewingKeyFromNk, deriveViewingKeyFromSpendKey, deriveViewingKeyFromUtxoPrivateKey, deserializeUtxo, detectNetworkFromRpcUrl, discoverSwapRefunds, downloadNote, encodeDeliveryCarrierMemo, encodeNoteSimple, encodeRecipientDeliveryNote, encryptCompactChainNote, encryptNoteForRecipient, encryptTransactionMetadata, encryptTransactionMetadataBundle, expandSpendKey, explainRelayAuthRejection, exportKeys, exportNote, exportWalletKeys, fetchCommitments, fetchRiskQuoteInstruction, fetchRiskQuoteIx, filterNotesByNetwork, filterWithdrawableNotes, findNoteByCommitment, formatAmount, formatComplianceCsv, formatErrorForLogging, formatSol, fullWithdraw, generateCloakKeys, generateCommitmentAsync, generateMasterSeed, generateNoteFromWallet, generateUtxoKeypair, generateViewingKeyPair, getAddressExplorerUrl, getChainNoteRegistryPDA, getCircuitsPath, getDeliveryRegistryPDA, getDistributableAmount, getExplorerUrl, getNkFromUtxoPrivateKey, getNullifierPDA, getPendingOperationsSummary, getPoolAuthorityConfigPDA, getPublicKey, getPublicViewKey, getRecipientAmount, getRpcUrlForNetwork, getShieldPoolPDAs, getSwapStatePDA, getViewKey, hasPendingOperations, hexToBigint$1 as hexToBigint, hexToBytes, importKeys, importWalletKeys, isBrowser, isBrowserLike, isDebugEnabled, isPlausibleSignature, isReactNative, isRootNotFoundError, isSubmissionOutcomeUnknownResponse, isValidHex, isValidRpcUrl, isValidSolanaAddress, isWithdrawAmountSufficient, isWithdrawable, keypairToAdapter, loadPendingDeposits, loadPendingWithdrawals, loadVerifiedCircuitArtifacts, matchChangeNote, matchDepositNote, matchSwapRefundLeaf, openRecipientDeliveryNote, parseAmount, parseDeliveryCarrierMemo, parseError, parseNote, parseRelayErrorResponse, parseRelayErrorSignature, parseTransactionError, partialWithdraw, poseidonHash, preflightCheck, preflightNullifiers, prepareEncryptedOutput, prepareEncryptedOutputForRecipient, proofToBytes, pubkeyToFieldElement, pubkeyToLimbs, randomBytes, randomChangeNoteSalt, randomDepositNoteSalt, randomFieldElement, readMerkleTreeState, recipientDeliveryNoteToBase64, registerViewingKey, removePendingDeposit, removePendingWithdrawal, resolveCircuitsBase, savePendingDeposit, savePendingWithdrawal, scanNotesForWallet, scanRecipientDeliveryNotes, scanTransactions, sdkLogger, selectUtxos, sendTransaction, serializeNote, serializeUtxo, setCircuitsPath, setDebugMode, signTransaction, splitTo2Limbs, submitTransactToRelay, sumUtxoAmounts, swapUtxo, swapWithChange, toComplianceReport, transact, transfer, truncate, tryDecryptNote, updateNoteWithDeposit, updatePendingDeposit, updatePendingWithdrawal, bigintToBytes32 as utxoBigintToBytes32, utxoEquals, hexToBigint as utxoHexToBigint, validateDepositParams, validateNote, validateOutputsSum, validateRoot, validateTransfers, validateWalletConnected, validateWithdrawableNote, verifyAllCircuits, verifyCircuitIntegrity, verifyUtxos, waitForRoot, withTiming };
package/dist/index.d.ts CHANGED
@@ -2931,6 +2931,27 @@ interface ExternalFeePayerAdapter {
2931
2931
  */
2932
2932
  getPaymentAccountHints?: () => Promise<PublicKey[]>;
2933
2933
  }
2934
+ /**
2935
+ * Refuse a transaction whose input notes do not agree on a mint, or do not
2936
+ * agree with the mint the caller says it is spending.
2937
+ *
2938
+ * TWO SEPARATE PROPERTIES, and they catch different mistakes:
2939
+ *
2940
+ * 1. HOMOGENEITY, always enforced. Every pool is a single mint, so a set of
2941
+ * inputs spanning two mints cannot be a valid spend of either. There is no
2942
+ * legitimate call that does this, so it needs no opt-in. Zero-amount
2943
+ * padding notes are exempt: they are placeholders, not value.
2944
+ *
2945
+ * 2. INTENT, enforced when `options.expectedMint` is given. Homogeneity alone
2946
+ * cannot catch the dangerous case — ONE note of the wrong mint is a
2947
+ * perfectly homogeneous set. Only the caller knows which asset the user
2948
+ * asked for, so only the caller can supply it, and this is where it is
2949
+ * checked.
2950
+ *
2951
+ * The error names both mints, because the whole failure mode is that the two
2952
+ * were assumed to be the same.
2953
+ */
2954
+ declare function assertInputMints(inputUtxos: Utxo[], expectedMint?: PublicKey): void;
2934
2955
  /**
2935
2956
  * Options for transact operation
2936
2957
  */
@@ -3184,6 +3205,31 @@ interface TransactOptions {
3184
3205
  * transaction. Omit for unchanged default behavior.
3185
3206
  */
3186
3207
  externalFeePayer?: ExternalFeePayerAdapter;
3208
+ /**
3209
+ * The mint the CALLER believes it is spending. When set, the SDK refuses the
3210
+ * transaction if the input notes say otherwise.
3211
+ *
3212
+ * ── Why this exists ────────────────────────────────────────────────────────
3213
+ * Every flow takes the pool from the notes it is handed
3214
+ * (`inputUtxos[0].mintAddress`), which is correct — the notes are the source
3215
+ * of truth for which pool they belong to. But it means the SDK cannot tell a
3216
+ * deliberate USDC withdrawal from a SOL withdrawal that was handed a USDC
3217
+ * note by mistake. Both are well-formed, both prove, and both settle.
3218
+ *
3219
+ * A consumer hit exactly that: its note selector sorted by RAW base units
3220
+ * across a store holding every mint, so with 6-decimal USDC and 9-decimal
3221
+ * SOL a stablecoin note outranked every SOL note whenever
3222
+ * `usdc > 1000 * sol`. A user sending 0.05 SOL moved ~50 USDC to the
3223
+ * recipient instead, and every layer reported SOL.
3224
+ *
3225
+ * Nothing about that is a protocol failure — the proof, the nullifier and the
3226
+ * pool accounting are all correct, and the user spent their own note. It is a
3227
+ * failure of INTENT, and intent is the one thing only the caller knows. So
3228
+ * the caller may now state it, and the SDK will hold it.
3229
+ *
3230
+ * Optional for backward compatibility, but pass it on every flow you can.
3231
+ */
3232
+ expectedMint?: PublicKey;
3187
3233
  }
3188
3234
  /**
3189
3235
  * Switchboard-style response: a pre-built instruction.
@@ -4674,8 +4720,8 @@ declare class SimpleWallet {
4674
4720
  * @packageDocumentation
4675
4721
  */
4676
4722
 
4677
- declare const VERSION = "0.2.1";
4723
+ declare const VERSION = "0.2.3";
4678
4724
  /** True when scanner supports TransactSwap (tag 1). Check this to verify the correct SDK bundle is loaded. */
4679
4725
  declare const SCANNER_SUPPORTS_TRANSACT_SWAP = true;
4680
4726
 
4681
- export { BUILD_ALLOWS_LOCAL_ENDPOINTS, type BuildRecipientDeliveryNotesParams, CHAIN_NOTE_SALT_BITS, CLOAK_PRODUCTION_RELAY_URL, CLOAK_PROGRAM_ID, type ChainNoteTxType, type CircuitVerificationResult, type CloakConfig, CloakError, type CloakKeyPair, type CloakNote, type CommitmentEntry, type CommitmentsResponse, type CompactChainNote, type ComplianceReport, type ComplianceTxType, type ConfirmSettlementParams, DEFAULT_CIRCUITS_URL, DEFAULT_TRANSACTION_CIRCUITS_URL, DELIVERY_MEMO_TAG, DELIVERY_REGISTRY_SEED, type DeliveredNote, type DepositInstructionParams, type DepositNoteSecrets, type DepositOptions, type DepositResult, type DepositStatus, type DiscoverSwapRefundsOptions, type DiscoveredSwapRefund, EXPECTED_CIRCUIT_HASHES, type EncryptedMetadataBundle, type EncryptedNote$1 as EncryptedNote, type ErrorCategory, type ExpandedSpendKey, type ExternalFeePayerAdapter, FIXED_FEE_LAMPORTS, type Groth16Proof, InsecureRandomnessError, LAMPORTS_PER_SOL, LocalStorageAdapter, type LogLevel, type Logger, MERKLE_TREE_HEIGHT, MIN_DEPOSIT_LAMPORTS, type MasterKey, type MatchChangeNoteParams, type MatchDepositNoteParams, type MatchSwapRefundLeafParams, type MaxLengthArray, MemoryStorageAdapter, type MerkleProof, type MerkleRootResponse, MerkleTree, NATIVE_SOL_MINT, type Network, type NoteData, type OnchainMerkleProof, type ParsedDeliveryCarrier, type PendingDeposit, type PendingWithdrawal, RECIPIENT_DELIVERY_CIPHERTEXT_LEN, RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN, RECIPIENT_DELIVERY_NONCE_LEN, RECIPIENT_DELIVERY_NOTE_BYTES, RECIPIENT_DELIVERY_PLAINTEXT_LEN, RECIPIENT_DELIVERY_TAG_LEN, RELAY_ORIGIN_ALLOWLIST, REQUEST_AUTH_MAX_AGE_SECONDS, REQUEST_AUTH_MAX_FUTURE_SKEW_SECONDS, type RecipientDeliveryNote, type RecoveredChangeNote, type RecoveredChangeNoteRecord, type RecoveredDepositNote, type RecoveredDepositNoteRecord, type RecoveredSwapRefund, type RelayAuthPreimage, type RelayAuthSigner, RelayInternalError, RelayService, type RelaySubmissionResult, type RiskQuoteInstructionResponse, RootNotFoundError, SCANNER_SUPPORTS_TRANSACT_SWAP, SIGN_IN_MESSAGE, SanctionsQuoteError, type ScanOptions, type ScanRecipientDeliveryOptions, type ScanResult, type ScanSummary, type ScannedTransaction, type SettlementConnection, type SettlementContext, type SettlementStatus, type SettlementVerdict, SettlementVerificationError, ShieldPoolErrors, type ShieldPoolPDAs, SimpleWallet, type SpendKey, type StorageAdapter, type SubmitTransactToRelayArgs, type SwapOptions, type SwapParams, type SwapRefundAuthorization, type SwapResult, TRANSACTION_CIRCUITS_VERSION, TRANSACT_AUTH_FIELDS, TRANSACT_SWAP_AUTH_FIELDS, type TransactOptions, type TransactParams, type TransactRequestBodyParams, type TransactResult, type TransactionMetadata, type Transfer, type TransferOptions, type TransferResult, type TxStatus, type UserFriendlyError, type Utxo, UtxoAlreadySpentError, type EncryptedNote as UtxoEncryptedNote, type UtxoKeypair, type UtxoSwapParams, type UtxoSwapResult, UtxoWallet, VARIABLE_FEE_DENOMINATOR, VARIABLE_FEE_NUMERATOR, VARIABLE_FEE_RATE, VERSION, type VerifyUtxosResult, type ViewKey, type ViewingKeyPair, type WalletAdapter, type WalletUtxo, type WithdrawOptions, type WithdrawSubmissionResult, assertDirectSubmissionLanded, assertTransactionCircuitIntegrity, bigintToBytes32$1 as bigintToBytes32, bigintToHex, buildMerkleTree, buildMerkleTreeFromChain, buildMerkleTreeFromRelay, buildRecipientDeliveryNotes, buildRelayAuthPreimage, buildTransactRequestBody, bytesToHex, calculateFee, calculateFeeBigint, calculateRelayFee, canRebuildMerkleTreeFromChain, canonicalJson, chainNoteFromBase64, chainNoteToBase64, classifyRelayError, cleanupStalePendingOperations, clearPendingDeposits, clearPendingWithdrawals, computeChainNoteHash, computeExtDataHash, computeMerkleRoot, computeProofForLatestDeposit, computeProofFromChain, computeSignature, computeSwapRefundCommitment, computeCommitment as computeUtxoCommitment, computeNullifier as computeUtxoNullifier, confirmTransactSettlement, copyNoteToClipboard, createCloakError, createDepositInstruction, createLogger, createRecoverableChangeUtxo, createRecoverableDepositUtxo, createUtxo, createZeroUtxo, decryptCompactChainNote, decryptComplianceMetadataWithMasterKey, decryptTransactionMetadata, deriveChangeNoteBlinding, deriveDepositNoteSecrets, deriveDiversifiedViewingKey, deriveDiversifier, deriveInputNullifierPdas, derivePublicKey, deriveSpendKey, deriveSwapRefundAuthorization, deriveUserCompliancePublicKey, deriveUserComplianceScalar, deriveUtxoKeypairFromSpendKey, deriveViewKey, deriveViewingKeyFromNk, deriveViewingKeyFromSpendKey, deriveViewingKeyFromUtxoPrivateKey, deserializeUtxo, detectNetworkFromRpcUrl, discoverSwapRefunds, downloadNote, encodeDeliveryCarrierMemo, encodeNoteSimple, encodeRecipientDeliveryNote, encryptCompactChainNote, encryptNoteForRecipient, encryptTransactionMetadata, encryptTransactionMetadataBundle, expandSpendKey, explainRelayAuthRejection, exportKeys, exportNote, exportWalletKeys, fetchCommitments, fetchRiskQuoteInstruction, fetchRiskQuoteIx, filterNotesByNetwork, filterWithdrawableNotes, findNoteByCommitment, formatAmount, formatComplianceCsv, formatErrorForLogging, formatSol, fullWithdraw, generateCloakKeys, generateCommitmentAsync, generateMasterSeed, generateNoteFromWallet, generateUtxoKeypair, generateViewingKeyPair, getAddressExplorerUrl, getChainNoteRegistryPDA, getCircuitsPath, getDeliveryRegistryPDA, getDistributableAmount, getExplorerUrl, getNkFromUtxoPrivateKey, getNullifierPDA, getPendingOperationsSummary, getPoolAuthorityConfigPDA, getPublicKey, getPublicViewKey, getRecipientAmount, getRpcUrlForNetwork, getShieldPoolPDAs, getSwapStatePDA, getViewKey, hasPendingOperations, hexToBigint$1 as hexToBigint, hexToBytes, importKeys, importWalletKeys, isBrowser, isBrowserLike, isDebugEnabled, isPlausibleSignature, isReactNative, isRootNotFoundError, isSubmissionOutcomeUnknownResponse, isValidHex, isValidRpcUrl, isValidSolanaAddress, isWithdrawAmountSufficient, isWithdrawable, keypairToAdapter, loadPendingDeposits, loadPendingWithdrawals, loadVerifiedCircuitArtifacts, matchChangeNote, matchDepositNote, matchSwapRefundLeaf, openRecipientDeliveryNote, parseAmount, parseDeliveryCarrierMemo, parseError, parseNote, parseRelayErrorResponse, parseRelayErrorSignature, parseTransactionError, partialWithdraw, poseidonHash, preflightCheck, preflightNullifiers, prepareEncryptedOutput, prepareEncryptedOutputForRecipient, proofToBytes, pubkeyToFieldElement, pubkeyToLimbs, randomBytes, randomChangeNoteSalt, randomDepositNoteSalt, randomFieldElement, readMerkleTreeState, recipientDeliveryNoteToBase64, registerViewingKey, removePendingDeposit, removePendingWithdrawal, resolveCircuitsBase, savePendingDeposit, savePendingWithdrawal, scanNotesForWallet, scanRecipientDeliveryNotes, scanTransactions, sdkLogger, selectUtxos, sendTransaction, serializeNote, serializeUtxo, setCircuitsPath, setDebugMode, signTransaction, splitTo2Limbs, submitTransactToRelay, sumUtxoAmounts, swapUtxo, swapWithChange, toComplianceReport, transact, transfer, truncate, tryDecryptNote, updateNoteWithDeposit, updatePendingDeposit, updatePendingWithdrawal, bigintToBytes32 as utxoBigintToBytes32, utxoEquals, hexToBigint as utxoHexToBigint, validateDepositParams, validateNote, validateOutputsSum, validateRoot, validateTransfers, validateWalletConnected, validateWithdrawableNote, verifyAllCircuits, verifyCircuitIntegrity, verifyUtxos, waitForRoot, withTiming };
4727
+ export { BUILD_ALLOWS_LOCAL_ENDPOINTS, type BuildRecipientDeliveryNotesParams, CHAIN_NOTE_SALT_BITS, CLOAK_PRODUCTION_RELAY_URL, CLOAK_PROGRAM_ID, type ChainNoteTxType, type CircuitVerificationResult, type CloakConfig, CloakError, type CloakKeyPair, type CloakNote, type CommitmentEntry, type CommitmentsResponse, type CompactChainNote, type ComplianceReport, type ComplianceTxType, type ConfirmSettlementParams, DEFAULT_CIRCUITS_URL, DEFAULT_TRANSACTION_CIRCUITS_URL, DELIVERY_MEMO_TAG, DELIVERY_REGISTRY_SEED, type DeliveredNote, type DepositInstructionParams, type DepositNoteSecrets, type DepositOptions, type DepositResult, type DepositStatus, type DiscoverSwapRefundsOptions, type DiscoveredSwapRefund, EXPECTED_CIRCUIT_HASHES, type EncryptedMetadataBundle, type EncryptedNote$1 as EncryptedNote, type ErrorCategory, type ExpandedSpendKey, type ExternalFeePayerAdapter, FIXED_FEE_LAMPORTS, type Groth16Proof, InsecureRandomnessError, LAMPORTS_PER_SOL, LocalStorageAdapter, type LogLevel, type Logger, MERKLE_TREE_HEIGHT, MIN_DEPOSIT_LAMPORTS, type MasterKey, type MatchChangeNoteParams, type MatchDepositNoteParams, type MatchSwapRefundLeafParams, type MaxLengthArray, MemoryStorageAdapter, type MerkleProof, type MerkleRootResponse, MerkleTree, NATIVE_SOL_MINT, type Network, type NoteData, type OnchainMerkleProof, type ParsedDeliveryCarrier, type PendingDeposit, type PendingWithdrawal, RECIPIENT_DELIVERY_CIPHERTEXT_LEN, RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN, RECIPIENT_DELIVERY_NONCE_LEN, RECIPIENT_DELIVERY_NOTE_BYTES, RECIPIENT_DELIVERY_PLAINTEXT_LEN, RECIPIENT_DELIVERY_TAG_LEN, RELAY_ORIGIN_ALLOWLIST, REQUEST_AUTH_MAX_AGE_SECONDS, REQUEST_AUTH_MAX_FUTURE_SKEW_SECONDS, type RecipientDeliveryNote, type RecoveredChangeNote, type RecoveredChangeNoteRecord, type RecoveredDepositNote, type RecoveredDepositNoteRecord, type RecoveredSwapRefund, type RelayAuthPreimage, type RelayAuthSigner, RelayInternalError, RelayService, type RelaySubmissionResult, type RiskQuoteInstructionResponse, RootNotFoundError, SCANNER_SUPPORTS_TRANSACT_SWAP, SIGN_IN_MESSAGE, SanctionsQuoteError, type ScanOptions, type ScanRecipientDeliveryOptions, type ScanResult, type ScanSummary, type ScannedTransaction, type SettlementConnection, type SettlementContext, type SettlementStatus, type SettlementVerdict, SettlementVerificationError, ShieldPoolErrors, type ShieldPoolPDAs, SimpleWallet, type SpendKey, type StorageAdapter, type SubmitTransactToRelayArgs, type SwapOptions, type SwapParams, type SwapRefundAuthorization, type SwapResult, TRANSACTION_CIRCUITS_VERSION, TRANSACT_AUTH_FIELDS, TRANSACT_SWAP_AUTH_FIELDS, type TransactOptions, type TransactParams, type TransactRequestBodyParams, type TransactResult, type TransactionMetadata, type Transfer, type TransferOptions, type TransferResult, type TxStatus, type UserFriendlyError, type Utxo, UtxoAlreadySpentError, type EncryptedNote as UtxoEncryptedNote, type UtxoKeypair, type UtxoSwapParams, type UtxoSwapResult, UtxoWallet, VARIABLE_FEE_DENOMINATOR, VARIABLE_FEE_NUMERATOR, VARIABLE_FEE_RATE, VERSION, type VerifyUtxosResult, type ViewKey, type ViewingKeyPair, type WalletAdapter, type WalletUtxo, type WithdrawOptions, type WithdrawSubmissionResult, assertDirectSubmissionLanded, assertInputMints, assertTransactionCircuitIntegrity, bigintToBytes32$1 as bigintToBytes32, bigintToHex, buildMerkleTree, buildMerkleTreeFromChain, buildMerkleTreeFromRelay, buildRecipientDeliveryNotes, buildRelayAuthPreimage, buildTransactRequestBody, bytesToHex, calculateFee, calculateFeeBigint, calculateRelayFee, canRebuildMerkleTreeFromChain, canonicalJson, chainNoteFromBase64, chainNoteToBase64, classifyRelayError, cleanupStalePendingOperations, clearPendingDeposits, clearPendingWithdrawals, computeChainNoteHash, computeExtDataHash, computeMerkleRoot, computeProofForLatestDeposit, computeProofFromChain, computeSignature, computeSwapRefundCommitment, computeCommitment as computeUtxoCommitment, computeNullifier as computeUtxoNullifier, confirmTransactSettlement, copyNoteToClipboard, createCloakError, createDepositInstruction, createLogger, createRecoverableChangeUtxo, createRecoverableDepositUtxo, createUtxo, createZeroUtxo, decryptCompactChainNote, decryptComplianceMetadataWithMasterKey, decryptTransactionMetadata, deriveChangeNoteBlinding, deriveDepositNoteSecrets, deriveDiversifiedViewingKey, deriveDiversifier, deriveInputNullifierPdas, derivePublicKey, deriveSpendKey, deriveSwapRefundAuthorization, deriveUserCompliancePublicKey, deriveUserComplianceScalar, deriveUtxoKeypairFromSpendKey, deriveViewKey, deriveViewingKeyFromNk, deriveViewingKeyFromSpendKey, deriveViewingKeyFromUtxoPrivateKey, deserializeUtxo, detectNetworkFromRpcUrl, discoverSwapRefunds, downloadNote, encodeDeliveryCarrierMemo, encodeNoteSimple, encodeRecipientDeliveryNote, encryptCompactChainNote, encryptNoteForRecipient, encryptTransactionMetadata, encryptTransactionMetadataBundle, expandSpendKey, explainRelayAuthRejection, exportKeys, exportNote, exportWalletKeys, fetchCommitments, fetchRiskQuoteInstruction, fetchRiskQuoteIx, filterNotesByNetwork, filterWithdrawableNotes, findNoteByCommitment, formatAmount, formatComplianceCsv, formatErrorForLogging, formatSol, fullWithdraw, generateCloakKeys, generateCommitmentAsync, generateMasterSeed, generateNoteFromWallet, generateUtxoKeypair, generateViewingKeyPair, getAddressExplorerUrl, getChainNoteRegistryPDA, getCircuitsPath, getDeliveryRegistryPDA, getDistributableAmount, getExplorerUrl, getNkFromUtxoPrivateKey, getNullifierPDA, getPendingOperationsSummary, getPoolAuthorityConfigPDA, getPublicKey, getPublicViewKey, getRecipientAmount, getRpcUrlForNetwork, getShieldPoolPDAs, getSwapStatePDA, getViewKey, hasPendingOperations, hexToBigint$1 as hexToBigint, hexToBytes, importKeys, importWalletKeys, isBrowser, isBrowserLike, isDebugEnabled, isPlausibleSignature, isReactNative, isRootNotFoundError, isSubmissionOutcomeUnknownResponse, isValidHex, isValidRpcUrl, isValidSolanaAddress, isWithdrawAmountSufficient, isWithdrawable, keypairToAdapter, loadPendingDeposits, loadPendingWithdrawals, loadVerifiedCircuitArtifacts, matchChangeNote, matchDepositNote, matchSwapRefundLeaf, openRecipientDeliveryNote, parseAmount, parseDeliveryCarrierMemo, parseError, parseNote, parseRelayErrorResponse, parseRelayErrorSignature, parseTransactionError, partialWithdraw, poseidonHash, preflightCheck, preflightNullifiers, prepareEncryptedOutput, prepareEncryptedOutputForRecipient, proofToBytes, pubkeyToFieldElement, pubkeyToLimbs, randomBytes, randomChangeNoteSalt, randomDepositNoteSalt, randomFieldElement, readMerkleTreeState, recipientDeliveryNoteToBase64, registerViewingKey, removePendingDeposit, removePendingWithdrawal, resolveCircuitsBase, savePendingDeposit, savePendingWithdrawal, scanNotesForWallet, scanRecipientDeliveryNotes, scanTransactions, sdkLogger, selectUtxos, sendTransaction, serializeNote, serializeUtxo, setCircuitsPath, setDebugMode, signTransaction, splitTo2Limbs, submitTransactToRelay, sumUtxoAmounts, swapUtxo, swapWithChange, toComplianceReport, transact, transfer, truncate, tryDecryptNote, updateNoteWithDeposit, updatePendingDeposit, updatePendingWithdrawal, bigintToBytes32 as utxoBigintToBytes32, utxoEquals, hexToBigint as utxoHexToBigint, validateDepositParams, validateNote, validateOutputsSum, validateRoot, validateTransfers, validateWalletConnected, validateWithdrawableNote, verifyAllCircuits, verifyCircuitIntegrity, verifyUtxos, waitForRoot, withTiming };
package/dist/index.js CHANGED
@@ -5449,6 +5449,23 @@ async function computeSwapExtDataHash(outputMint, recipientAta, minOutputAmount,
5449
5449
  ]);
5450
5450
  return poseidonHasher.F.toObject(hash);
5451
5451
  }
5452
+ function assertInputMints(inputUtxos, expectedMint) {
5453
+ const funded = inputUtxos.filter((u) => u.amount > BigInt(0));
5454
+ if (funded.length === 0) return;
5455
+ const first = funded[0].mintAddress;
5456
+ for (const utxo of funded) {
5457
+ if (!utxo.mintAddress.equals(first)) {
5458
+ throw new Error(
5459
+ `Input notes span more than one mint (${first.toBase58()} and ${utxo.mintAddress.toBase58()}). Every pool holds a single mint, so this cannot be a valid spend of either. Select notes of one mint.`
5460
+ );
5461
+ }
5462
+ }
5463
+ if (expectedMint && !first.equals(expectedMint)) {
5464
+ throw new Error(
5465
+ `Input notes are ${first.toBase58()} but this transaction expects ${expectedMint.toBase58()}. The notes decide which pool is spent, so proceeding would move the wrong asset \u2014 refusing. This usually means note selection ignored the mint.`
5466
+ );
5467
+ }
5468
+ }
5452
5469
  function parseNkInput(input) {
5453
5470
  if (typeof input !== "string") {
5454
5471
  if (input.length !== 32) {
@@ -7115,6 +7132,7 @@ async function transact(params, options) {
7115
7132
  }
7116
7133
  }
7117
7134
  assertAllowedRpcConnection(connection);
7135
+ assertInputMints(inputUtxos, options.expectedMint);
7118
7136
  await ensureViewingKeyRegistered(options, onProgress, fallbackNk);
7119
7137
  const resolvedChainNoteNk = explicitChainNoteNk ?? fallbackNk ?? null;
7120
7138
  if (inputUtxos.length > 2) {
@@ -8357,6 +8375,12 @@ async function swapUtxo(params, options) {
8357
8375
  if (inputUtxos.length > 2) {
8358
8376
  throw new Error("Maximum 2 input UTXOs allowed");
8359
8377
  }
8378
+ assertInputMints(inputUtxos, NATIVE_SOL_MINT);
8379
+ if (options.expectedMint && !options.expectedMint.equals(NATIVE_SOL_MINT)) {
8380
+ throw new Error(
8381
+ `swapUtxo expects ${NATIVE_SOL_MINT.toBase58()} input notes (a swap always spends from the wSOL pool), but expectedMint was ${options.expectedMint.toBase58()}. Drop expectedMint, or spend the other mint with transact/transfer instead.`
8382
+ );
8383
+ }
8360
8384
  await preflightNullifiers(inputUtxos, connection, programId);
8361
8385
  const outputMintAccount = await connection.getAccountInfo(outputMint, {
8362
8386
  commitment: "confirmed"
@@ -10858,7 +10882,7 @@ var SimpleWallet = class {
10858
10882
  };
10859
10883
 
10860
10884
  // src/index.ts
10861
- var VERSION = "0.2.1";
10885
+ var VERSION = "0.2.3";
10862
10886
  var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
10863
10887
  export {
10864
10888
  BUILD_ALLOWS_LOCAL_ENDPOINTS,
@@ -10908,6 +10932,7 @@ export {
10908
10932
  VARIABLE_FEE_RATE,
10909
10933
  VERSION,
10910
10934
  assertDirectSubmissionLanded,
10935
+ assertInputMints,
10911
10936
  assertTransactionCircuitIntegrity,
10912
10937
  bigintToBytes32,
10913
10938
  bigintToHex,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloak.dev/sdk",
3
3
  "description": "Shield, send, and swap on Solana privately — TypeScript SDK with UTXO-based zero-knowledge transactions",
4
- "version": "0.2.2",
4
+ "version": "0.2.3",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",