@cloak.dev/sdk 0.2.0 → 0.2.1

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/dist/index.d.cts CHANGED
@@ -1,4 +1,24 @@
1
- import { PublicKey, Transaction, Connection, AddressLookupTableAccount, TransactionInstruction, Keypair, SendOptions, VersionedTransaction } from '@solana/web3.js';
1
+ import { PublicKey, Transaction, AddressLookupTableAccount, Connection, TransactionInstruction, Keypair, SendOptions, VersionedTransaction } from '@solana/web3.js';
2
+
3
+ /**
4
+ * The deployed Cloak program.
5
+ *
6
+ * This lived in `core/CloakSDK.ts` until that class was removed. It is protocol
7
+ * configuration, not client state: every PDA derivation, every scan and every
8
+ * `transact()` submission is addressed to it, so it belongs beside the other
9
+ * pinned protocol facts in `config/` rather than inside one client object.
10
+ */
11
+
12
+ /**
13
+ * Address of the Cloak shield-pool program on Solana mainnet.
14
+ *
15
+ * The same address is used by every environment the SDK talks to (a local
16
+ * Surfpool fork mirrors mainnet, so it carries the same program id). Callers
17
+ * that need a different deployment pass an explicit `programId` to the function
18
+ * they are calling — `getShieldPoolPDAs`, `transact`, `scanTransactions` and
19
+ * friends all take one.
20
+ */
21
+ declare const CLOAK_PROGRAM_ID: PublicKey;
2
22
 
3
23
  type ComplianceTxType = "deposit" | "withdraw" | "send" | "swap";
4
24
  interface TransactionMetadata {
@@ -454,415 +474,6 @@ declare function exportKeys(keys: CloakKeyPair): string;
454
474
  */
455
475
  declare function importKeys(exported: string): CloakKeyPair;
456
476
 
457
- /**
458
- * Storage Interface
459
- *
460
- * Defines a pluggable storage interface for notes and keys.
461
- * Applications can implement their own storage (localStorage, IndexedDB, file system, etc.)
462
- */
463
-
464
- /**
465
- * Storage adapter interface
466
- *
467
- * Implement this interface to provide custom storage for notes and keys.
468
- * The SDK will use this adapter for all persistence operations.
469
- */
470
- interface StorageAdapter {
471
- /**
472
- * Save a note
473
- */
474
- saveNote(note: CloakNote): Promise<void> | void;
475
- /**
476
- * Load all notes
477
- */
478
- loadAllNotes(): Promise<CloakNote[]> | CloakNote[];
479
- /**
480
- * Update a note
481
- */
482
- updateNote(commitment: string, updates: Partial<CloakNote>): Promise<void> | void;
483
- /**
484
- * Delete a note
485
- */
486
- deleteNote(commitment: string): Promise<void> | void;
487
- /**
488
- * Clear all notes
489
- */
490
- clearAllNotes(): Promise<void> | void;
491
- /**
492
- * Save wallet keys
493
- */
494
- saveKeys(keys: CloakKeyPair): Promise<void> | void;
495
- /**
496
- * Load wallet keys
497
- */
498
- loadKeys(): Promise<CloakKeyPair | null> | CloakKeyPair | null;
499
- /**
500
- * Delete wallet keys
501
- */
502
- deleteKeys(): Promise<void> | void;
503
- }
504
- /**
505
- * In-memory storage adapter (default, no persistence)
506
- *
507
- * Useful for testing or when storage is handled externally
508
- */
509
- declare class MemoryStorageAdapter implements StorageAdapter {
510
- private notes;
511
- private keys;
512
- saveNote(note: CloakNote): void;
513
- loadAllNotes(): CloakNote[];
514
- updateNote(commitment: string, updates: Partial<CloakNote>): void;
515
- deleteNote(commitment: string): void;
516
- clearAllNotes(): void;
517
- saveKeys(keys: CloakKeyPair): void;
518
- loadKeys(): CloakKeyPair | null;
519
- deleteKeys(): void;
520
- }
521
- /**
522
- * Browser localStorage adapter (optional, for browser environments)
523
- *
524
- * Only use this if you're in a browser environment and want localStorage persistence.
525
- * Import from a separate browser-specific module.
526
- */
527
- declare class LocalStorageAdapter implements StorageAdapter {
528
- private notesKey;
529
- private keysKey;
530
- constructor(notesKey?: string, keysKey?: string);
531
- private getStorage;
532
- saveNote(note: CloakNote): void;
533
- loadAllNotes(): CloakNote[];
534
- updateNote(commitment: string, updates: Partial<CloakNote>): void;
535
- deleteNote(commitment: string): void;
536
- clearAllNotes(): void;
537
- saveKeys(keys: CloakKeyPair): void;
538
- loadKeys(): CloakKeyPair | null;
539
- deleteKeys(): void;
540
- }
541
-
542
- /** Default Cloak Program ID on Solana */
543
- declare const CLOAK_PROGRAM_ID: PublicKey;
544
- /**
545
- * Main Cloak SDK
546
- *
547
- * Provides high-level API for interacting with the Cloak protocol,
548
- * including deposits, withdrawals, and private transfers.
549
- *
550
- * Supports two modes:
551
- * 1. Node.js mode with keypairBytes - for scripts and backend services
552
- * 2. Wallet adapter mode - for browser applications with wallet integration
553
- */
554
- declare class CloakSDK {
555
- private config;
556
- private keypair?;
557
- private wallet?;
558
- private cloakKeys?;
559
- private relay;
560
- private storage;
561
- /**
562
- * Create a new Cloak SDK client
563
- *
564
- * @param config - Client configuration
565
- *
566
- * @example Node.js mode (with keypair)
567
- * ```typescript
568
- * const sdk = new CloakSDK({
569
- * keypairBytes: keypair.secretKey,
570
- * network: "devnet"
571
- * });
572
- * ```
573
- *
574
- * @example Browser mode (with wallet adapter)
575
- * ```typescript
576
- * const sdk = new CloakSDK({
577
- * wallet: walletAdapter,
578
- * network: "devnet"
579
- * });
580
- * ```
581
- */
582
- constructor(config: {
583
- /** Keypair bytes for signing (Node.js mode) */
584
- keypairBytes?: Uint8Array;
585
- /** Wallet adapter for signing (Browser mode) */
586
- wallet?: WalletAdapter;
587
- network?: Network;
588
- cloakKeys?: CloakKeyPair;
589
- storage?: StorageAdapter;
590
- programId?: PublicKey;
591
- relayUrl?: string;
592
- /** Enable debug logging with structured output */
593
- debug?: boolean;
594
- });
595
- /**
596
- * Get the public key for deposits (from keypair or wallet)
597
- */
598
- getPublicKey(): PublicKey;
599
- /**
600
- * Check if the SDK is using a wallet adapter
601
- */
602
- isWalletMode(): boolean;
603
- /**
604
- * Deposit SOL into the Cloak protocol
605
- *
606
- * Creates a new note (or uses a provided one), submits a deposit transaction,
607
- * and registers with the indexer.
608
- *
609
- * @param connection - Solana connection
610
- * @param payer - Payer wallet with sendTransaction method
611
- * @param amountOrNote - Amount in lamports OR an existing note to deposit
612
- * @param options - Optional configuration
613
- * @returns Deposit result with note and transaction info
614
- *
615
- * @example
616
- * ```typescript
617
- * // Generate and deposit in one step
618
- * const result = await client.deposit(
619
- * connection,
620
- * wallet,
621
- * 1_000_000_000,
622
- * {
623
- * onProgress: (status) => console.log(status)
624
- * }
625
- * );
626
- *
627
- * // Or deposit a pre-generated note
628
- * const note = client.generateNote(1_000_000_000);
629
- * const result = await client.deposit(connection, wallet, note);
630
- * ```
631
- */
632
- deposit(connection: Connection, amountOrNote: number | CloakNote, options?: DepositOptions): Promise<DepositResult>;
633
- /**
634
- * Private transfer with up to 5 recipients
635
- *
636
- * Handles the complete private transfer flow:
637
- * 1. If note is not deposited, deposits it first and waits for confirmation
638
- * 2. Generates a zero-knowledge proof
639
- * 3. Submits the withdrawal via relay service to recipients
640
- *
641
- * This is the main method for performing private transfers - it handles everything!
642
- *
643
- * @param connection - Solana connection (required for deposit if not already deposited)
644
- * @param payer - Payer wallet (required for deposit if not already deposited)
645
- * @param note - Note to spend (can be deposited or not)
646
- * @param recipients - Array of 1-5 recipients with amounts
647
- * @param options - Optional configuration
648
- * @returns Transfer result with signature and outputs
649
- *
650
- * @example
651
- * ```typescript
652
- * // Create a note (not deposited yet)
653
- * const note = client.generateNote(1_000_000_000);
654
- *
655
- * // privateTransfer handles the full flow: deposit + withdraw
656
- * const result = await client.privateTransfer(
657
- * connection,
658
- * wallet,
659
- * note,
660
- * [
661
- * { recipient: new PublicKey("..."), amount: 500_000_000 },
662
- * { recipient: new PublicKey("..."), amount: 492_500_000 }
663
- * ],
664
- * {
665
- * relayFeeBps: 50, // 0.5%
666
- * onProgress: (status) => console.log(status),
667
- * onProofProgress: (pct) => console.log(`Proof: ${pct}%`)
668
- * }
669
- * );
670
- * console.log(`Success! TX: ${result.signature}`);
671
- * ```
672
- */
673
- privateTransfer(connection: Connection, note: CloakNote, recipients: MaxLengthArray<Transfer, 5>, options?: TransferOptions): Promise<TransferResult>;
674
- /**
675
- * Withdraw to a single recipient
676
- *
677
- * Convenience method for withdrawing to one address.
678
- * Handles the complete flow: deposits if needed, then withdraws.
679
- *
680
- * @param connection - Solana connection
681
- * @param payer - Payer wallet
682
- * @param note - Note to spend
683
- * @param recipient - Recipient address
684
- * @param options - Optional configuration
685
- * @returns Transfer result
686
- *
687
- * @example
688
- * ```typescript
689
- * const note = client.generateNote(1_000_000_000);
690
- * const result = await client.withdraw(
691
- * connection,
692
- * wallet,
693
- * note,
694
- * new PublicKey("..."),
695
- * { withdrawAll: true }
696
- * );
697
- * ```
698
- */
699
- withdraw(connection: Connection, note: CloakNote, recipient: PublicKey, options?: WithdrawOptions): Promise<TransferResult>;
700
- /**
701
- * Send SOL privately to multiple recipients
702
- *
703
- * Convenience method that wraps privateTransfer with a simpler API.
704
- * Handles the complete flow: deposits if needed, then sends to recipients.
705
- *
706
- * @param connection - Solana connection
707
- * @param note - Note to spend
708
- * @param recipients - Array of 1-5 recipients with amounts
709
- * @param options - Optional configuration
710
- * @returns Transfer result
711
- *
712
- * @example
713
- * ```typescript
714
- * const note = client.generateNote(1_000_000_000);
715
- * const result = await client.send(
716
- * connection,
717
- * note,
718
- * [
719
- * { recipient: new PublicKey("..."), amount: 500_000_000 },
720
- * { recipient: new PublicKey("..."), amount: 492_500_000 }
721
- * ]
722
- * );
723
- * ```
724
- */
725
- send(connection: Connection, note: CloakNote, recipients: MaxLengthArray<Transfer, 5>, options?: TransferOptions): Promise<TransferResult>;
726
- /**
727
- * Swap SOL for tokens privately
728
- *
729
- * Withdraws SOL from a note and swaps it for tokens via the relay service.
730
- * Handles the complete flow: deposits if needed, generates proof, and submits swap.
731
- *
732
- * @param connection - Solana connection
733
- * @param note - Note to spend
734
- * @param recipient - Recipient address (will receive tokens)
735
- * @param options - Swap configuration
736
- * @returns Swap result with transaction signature
737
- *
738
- * @example
739
- * ```typescript
740
- * const note = client.generateNote(1_000_000_000);
741
- * const result = await client.swap(
742
- * connection,
743
- * note,
744
- * new PublicKey("..."), // recipient
745
- * {
746
- * outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
747
- * slippageBps: 100, // 1%
748
- * getQuote: async (amount, mint, slippage) => {
749
- * // Fetch quote from your swap API
750
- * const quote = await fetchSwapQuote(amount, mint, slippage);
751
- * return {
752
- * outAmount: quote.outAmount,
753
- * minOutputAmount: quote.minOutputAmount
754
- * };
755
- * }
756
- * }
757
- * );
758
- * ```
759
- */
760
- swap(connection: Connection, note: CloakNote, recipient: PublicKey, options: SwapOptions): Promise<SwapResult>;
761
- /**
762
- * Generate a new note without depositing
763
- *
764
- * @param amountLamports - Amount for the note
765
- * @param useWalletKeys - Whether to use wallet keys (v2.0 recommended)
766
- * @returns New note (not yet deposited)
767
- */
768
- generateNote(amountLamports: number, useWalletKeys?: boolean): Promise<CloakNote>;
769
- /**
770
- * Parse a note from JSON string
771
- *
772
- * @param jsonString - JSON representation
773
- * @returns Parsed note
774
- */
775
- parseNote(jsonString: string): CloakNote;
776
- /**
777
- * Export a note to JSON string
778
- *
779
- * @param note - Note to export
780
- * @param pretty - Format with indentation
781
- * @returns JSON string
782
- */
783
- exportNote(note: CloakNote, pretty?: boolean): string;
784
- /**
785
- * Check if a note is ready for withdrawal
786
- *
787
- * @param note - Note to check
788
- * @returns True if withdrawable
789
- */
790
- isWithdrawable(note: CloakNote): boolean;
791
- /**
792
- * Get Merkle proof for a leaf index directly from on-chain state
793
- *
794
- * @param connection - Solana connection
795
- * @param leafIndex - Leaf index in tree
796
- * @returns Merkle proof computed from on-chain data
797
- */
798
- getMerkleProof(connection: Connection, leafIndex: number): Promise<MerkleProof>;
799
- /**
800
- * Get current Merkle root directly from on-chain state
801
- *
802
- * @param connection - Solana connection
803
- * @returns Current root hash from on-chain tree
804
- */
805
- getCurrentRoot(connection: Connection): Promise<string>;
806
- /**
807
- * Get transaction status from relay service
808
- *
809
- * @param requestId - Request ID from previous submission
810
- * @returns Current status
811
- */
812
- getTransactionStatus(requestId: string): Promise<TxStatus>;
813
- /**
814
- * Fetch and decrypt this user's transaction metadata history.
815
- * DEPRECATED: This functionality is no longer supported
816
- */
817
- getTransactionMetadata(_options?: {
818
- _after?: number;
819
- _before?: number;
820
- }): Promise<TransactionMetadata[]>;
821
- /**
822
- * Load all notes from storage
823
- *
824
- * @returns Array of saved notes
825
- */
826
- loadNotes(): Promise<CloakNote[]>;
827
- /**
828
- * Save a note to storage
829
- *
830
- * @param note - Note to save
831
- */
832
- saveNote(note: CloakNote): Promise<void>;
833
- /**
834
- * Find a note by its commitment
835
- *
836
- * @param commitment - Commitment hash
837
- * @returns Note if found
838
- */
839
- findNote(commitment: string): Promise<CloakNote | undefined>;
840
- /**
841
- * Import wallet keys from JSON
842
- *
843
- * @param keysJson - JSON string containing keys
844
- */
845
- importWalletKeys(keysJson: string): Promise<void>;
846
- /**
847
- * Export wallet keys to JSON
848
- *
849
- * WARNING: This exports secret keys! Store securely.
850
- *
851
- * @returns JSON string with keys
852
- */
853
- exportWalletKeys(): string;
854
- /**
855
- * Get the configuration
856
- */
857
- getConfig(): CloakConfig;
858
- /**
859
- * Wrap errors with better categorization and user-friendly messages
860
- *
861
- * @private
862
- */
863
- private wrapError;
864
- }
865
-
866
477
  /**
867
478
  * Serialize a note to JSON string
868
479
  *
@@ -1013,18 +624,12 @@ declare function calculateRelayFee(amountLamports: number, feeBps: number): numb
1013
624
  * Storage is handled externally via StorageAdapter.
1014
625
  *
1015
626
  * Core functionality:
1016
- * - Generate notes (v1.0 and v2.0)
627
+ * - Generate notes from wallet keys
1017
628
  * - Parse and validate notes
1018
629
  * - Note utilities (formatting, fees, etc.)
1019
630
  * - Key management (without storage)
1020
631
  */
1021
632
 
1022
- /**
1023
- * Generate a new note without wallet keys (legacy v1.0)
1024
- * Uses Poseidon hashing to match circuit implementation
1025
- * @deprecated Use generateNoteFromWallet instead for enhanced security
1026
- */
1027
- declare function generateNote(amountLamports: number, network?: Network): Promise<CloakNote>;
1028
633
  /**
1029
634
  * Generate a note using wallet's spend key (v2.0 recommended)
1030
635
  * Uses Poseidon hashing to match circuit implementation
@@ -1091,6 +696,91 @@ declare function getViewKey(keys: CloakKeyPair): ViewKey;
1091
696
  */
1092
697
  declare function getRecipientAmount(amountLamports: number): number;
1093
698
 
699
+ /**
700
+ * Storage Interface
701
+ *
702
+ * Defines a pluggable storage interface for notes and keys.
703
+ * Applications can implement their own storage (localStorage, IndexedDB, file system, etc.)
704
+ */
705
+
706
+ /**
707
+ * Storage adapter interface
708
+ *
709
+ * Implement this interface to provide custom storage for notes and keys.
710
+ * The SDK will use this adapter for all persistence operations.
711
+ */
712
+ interface StorageAdapter {
713
+ /**
714
+ * Save a note
715
+ */
716
+ saveNote(note: CloakNote): Promise<void> | void;
717
+ /**
718
+ * Load all notes
719
+ */
720
+ loadAllNotes(): Promise<CloakNote[]> | CloakNote[];
721
+ /**
722
+ * Update a note
723
+ */
724
+ updateNote(commitment: string, updates: Partial<CloakNote>): Promise<void> | void;
725
+ /**
726
+ * Delete a note
727
+ */
728
+ deleteNote(commitment: string): Promise<void> | void;
729
+ /**
730
+ * Clear all notes
731
+ */
732
+ clearAllNotes(): Promise<void> | void;
733
+ /**
734
+ * Save wallet keys
735
+ */
736
+ saveKeys(keys: CloakKeyPair): Promise<void> | void;
737
+ /**
738
+ * Load wallet keys
739
+ */
740
+ loadKeys(): Promise<CloakKeyPair | null> | CloakKeyPair | null;
741
+ /**
742
+ * Delete wallet keys
743
+ */
744
+ deleteKeys(): Promise<void> | void;
745
+ }
746
+ /**
747
+ * In-memory storage adapter (default, no persistence)
748
+ *
749
+ * Useful for testing or when storage is handled externally
750
+ */
751
+ declare class MemoryStorageAdapter implements StorageAdapter {
752
+ private notes;
753
+ private keys;
754
+ saveNote(note: CloakNote): void;
755
+ loadAllNotes(): CloakNote[];
756
+ updateNote(commitment: string, updates: Partial<CloakNote>): void;
757
+ deleteNote(commitment: string): void;
758
+ clearAllNotes(): void;
759
+ saveKeys(keys: CloakKeyPair): void;
760
+ loadKeys(): CloakKeyPair | null;
761
+ deleteKeys(): void;
762
+ }
763
+ /**
764
+ * Browser localStorage adapter (optional, for browser environments)
765
+ *
766
+ * Only use this if you're in a browser environment and want localStorage persistence.
767
+ * Import from a separate browser-specific module.
768
+ */
769
+ declare class LocalStorageAdapter implements StorageAdapter {
770
+ private notesKey;
771
+ private keysKey;
772
+ constructor(notesKey?: string, keysKey?: string);
773
+ private getStorage;
774
+ saveNote(note: CloakNote): void;
775
+ loadAllNotes(): CloakNote[];
776
+ updateNote(commitment: string, updates: Partial<CloakNote>): void;
777
+ deleteNote(commitment: string): void;
778
+ clearAllNotes(): void;
779
+ saveKeys(keys: CloakKeyPair): void;
780
+ loadKeys(): CloakKeyPair | null;
781
+ deleteKeys(): void;
782
+ }
783
+
1094
784
  interface ViewingKeyPair {
1095
785
  privateKey: Uint8Array;
1096
786
  publicKey: Uint8Array;
@@ -1243,26 +933,13 @@ declare function computeMerkleRoot(leaf: bigint, pathElements: bigint[], pathInd
1243
933
  * Convert hex string to bigint
1244
934
  */
1245
935
  declare function hexToBigint$1(hex: string): bigint;
1246
- /**
1247
- * Compute commitment = Poseidon(amount, r0, r1, pk_spend)
1248
- * where pk_spend = Poseidon(sk0, sk1)
1249
- * (matching withdraw_regular.circom)
1250
- *
1251
- * This is the test-style function that takes bigints directly
1252
- *
1253
- * @param amount - Amount as bigint
1254
- * @param r - Randomness as bigint
1255
- * @param sk_spend - Spending secret key as bigint
1256
- * @returns Commitment hash as bigint
1257
- */
1258
- declare function computeCommitment$1(amount: bigint, r: bigint, sk_spend: bigint): Promise<bigint>;
1259
936
  /**
1260
937
  * Generate a Poseidon commitment for a note
1261
938
  *
1262
939
  * Formula: Poseidon(amount, r0, r1, pk_spend)
1263
940
  * where pk_spend = Poseidon(sk0, sk1)
1264
941
  *
1265
- * This matches the withdraw_regular.circom circuit
942
+ * Legacy CloakNote commitment layout (see `computeCommitment`).
1266
943
  *
1267
944
  * @param amountLamports - Amount in lamports
1268
945
  * @param r - Randomness bytes (32 bytes)
@@ -1270,110 +947,6 @@ declare function computeCommitment$1(amount: bigint, r: bigint, sk_spend: bigint
1270
947
  * @returns Commitment hash as bigint
1271
948
  */
1272
949
  declare function generateCommitmentAsync(amountLamports: number, r: Uint8Array, skSpend: Uint8Array): Promise<bigint>;
1273
- /**
1274
- * Generate a Poseidon commitment for a note (sync wrapper)
1275
- * Returns bytes instead of bigint for backward compatibility
1276
- *
1277
- * @deprecated Use generateCommitmentAsync instead
1278
- */
1279
- declare function generateCommitment(_amountLamports: number, _r: Uint8Array, _skSpend: Uint8Array): Uint8Array;
1280
- /**
1281
- * Compute nullifier = Poseidon(sk0, sk1, leaf_index)
1282
- * (matching withdraw_regular.circom)
1283
- *
1284
- * This is the test-style function that takes bigint directly
1285
- *
1286
- * @param sk_spend - Spending secret key as bigint
1287
- * @param leafIndex - Index in the Merkle tree as bigint
1288
- * @returns Nullifier as bigint
1289
- */
1290
- declare function computeNullifier$1(sk_spend: bigint, leafIndex: bigint): Promise<bigint>;
1291
- /**
1292
- * Compute nullifier from spending key and leaf index
1293
- *
1294
- * Formula: Poseidon(sk0, sk1, leaf_index)
1295
- *
1296
- * This matches the circuit's nullifier computation
1297
- *
1298
- * @param skSpend - Spending secret key bytes (32 bytes) or hex string
1299
- * @param leafIndex - Index in the Merkle tree
1300
- * @returns Nullifier as bigint
1301
- */
1302
- declare function computeNullifierAsync(skSpend: Uint8Array | string, leafIndex: number): Promise<bigint>;
1303
- /**
1304
- * Compute nullifier (sync wrapper for backward compatibility)
1305
- * @deprecated Use computeNullifierAsync instead
1306
- */
1307
- declare function computeNullifierSync(_skSpend: Uint8Array, _leafIndex: number): Uint8Array;
1308
- /**
1309
- * Compute outputs hash from recipients and amounts
1310
- *
1311
- * Formula: Chain of Poseidon(prev_hash, addr_lo, addr_hi, amount) for each active output
1312
- *
1313
- * This matches the withdraw_regular.circom circuit's outputs hash computation
1314
- *
1315
- * @param outputs - Array of {recipient: PublicKey, amount: number}
1316
- * @returns Outputs hash as bigint
1317
- */
1318
- declare function computeOutputsHashAsync(outputs: Array<{
1319
- recipient: PublicKey;
1320
- amount: number;
1321
- }>): Promise<bigint>;
1322
- /**
1323
- * Compute outputs hash for withdraw_regular circuit
1324
- * outputs_hash = chain of Poseidon(prev_hash, addr_lo, addr_hi, amount) for each active output
1325
- *
1326
- * This is the test-style function that takes raw limbs
1327
- *
1328
- * @param outAddr - Array of [lo, hi] limb pairs for each address (5x2 array)
1329
- * @param outAmount - Array of amounts as bigints (5 elements)
1330
- * @param outFlags - Array of flags (1 = active, 0 = inactive) (5 elements)
1331
- * @returns Outputs hash as bigint
1332
- */
1333
- declare function computeOutputsHash(outAddr: bigint[][], outAmount: bigint[], outFlags: number[]): Promise<bigint>;
1334
- /**
1335
- * Compute outputs hash (sync wrapper for backward compatibility)
1336
- * @deprecated Use computeOutputsHashAsync instead
1337
- */
1338
- declare function computeOutputsHashSync(_outputs: Array<{
1339
- recipient: PublicKey;
1340
- amount: number;
1341
- }>): Uint8Array;
1342
- /**
1343
- * Compute outputs hash for withdraw_swap circuit
1344
- * outputs_hash = Poseidon(input_mint limbs, output_mint limbs, recipient_ata limbs, min_output_amount, public_amount)
1345
- *
1346
- * This is the test-style function that takes raw limbs
1347
- *
1348
- * @param inputMintLimbs - Input mint address as [lo, hi] limbs
1349
- * @param outputMintLimbs - Output mint address as [lo, hi] limbs
1350
- * @param recipientAtaLimbs - Recipient ATA as [lo, hi] limbs
1351
- * @param minOutputAmount - Minimum output amount as bigint
1352
- * @param publicAmount - Public amount as bigint
1353
- * @returns Outputs hash as bigint
1354
- */
1355
- declare function computeSwapOutputsHash(inputMintLimbs: [bigint, bigint], outputMintLimbs: [bigint, bigint], recipientAtaLimbs: [bigint, bigint], minOutputAmount: bigint, publicAmount: bigint): Promise<bigint>;
1356
- /**
1357
- * Compute outputs hash for swap transactions
1358
- *
1359
- * Formula: Poseidon(input_mint_lo, input_mint_hi, output_mint_lo, output_mint_hi,
1360
- * recipient_ata_lo, recipient_ata_hi, min_output_amount, public_amount)
1361
- *
1362
- * This matches the withdraw_swap.circom circuit
1363
- *
1364
- * @param inputMint - Input token mint address (SOL = SystemProgram)
1365
- * @param outputMint - Output token mint address
1366
- * @param recipientAta - Recipient's associated token account
1367
- * @param minOutputAmount - Minimum output amount in token's smallest unit
1368
- * @param amount - Note amount in lamports (public_amount)
1369
- * @returns Outputs hash as bigint
1370
- */
1371
- declare function computeSwapOutputsHashAsync(inputMint: PublicKey, outputMint: PublicKey, recipientAta: PublicKey, minOutputAmount: number, amount: number): Promise<bigint>;
1372
- /**
1373
- * Compute swap outputs hash (sync wrapper for backward compatibility)
1374
- * @deprecated Use computeSwapOutputsHashAsync instead
1375
- */
1376
- declare function computeSwapOutputsHashSync(_outputMint: PublicKey, _recipientAta: PublicKey, _minOutputAmount: number, _amount: number): Uint8Array;
1377
950
  /**
1378
951
  * Convert bigint to 32-byte big-endian Uint8Array
1379
952
  */
@@ -1446,11 +1019,6 @@ interface Groth16Proof {
1446
1019
  * Format: pi_a (64) + pi_b (128) + pi_c (64) = 256 bytes
1447
1020
  */
1448
1021
  declare function proofToBytes(proof: Groth16Proof): Uint8Array;
1449
- /**
1450
- * Build public inputs bytes for on-chain verification
1451
- * Format: root (32) + nullifier (32) + outputs_hash (32) + public_amount (8) = 104 bytes
1452
- */
1453
- declare function buildPublicInputsBytes(root: bigint, nullifier: bigint, outputsHash: bigint, publicAmount: bigint): Uint8Array;
1454
1022
 
1455
1023
  /**
1456
1024
  * Validate a Solana public key
@@ -1692,7 +1260,7 @@ declare class RelayInternalError extends Error {
1692
1260
  /**
1693
1261
  * Raised when a submission's outcome could NOT be established as "landed" from chain state.
1694
1262
  *
1695
- * This is the failure side of settlement verification (see `core/settlement.ts`). It exists
1263
+ * This is the failure side of settlement verification (see `flows/settlement.ts`). It exists
1696
1264
  * because the campaign's worst outcome was not a failed transaction — it was an AMBIGUOUS one
1697
1265
  * whose error text carried no signature (REL-A-10: seven POSTs, the transaction landed, the SDK
1698
1266
  * threw `RelayInternalError`, and the user had nothing to look up). Losing the signature is what
@@ -2124,7 +1692,7 @@ interface VerifyUtxosResult {
2124
1692
  declare function verifyUtxos(utxos: Utxo[], connection: Connection, programId: PublicKey, commitment?: "processed" | "confirmed" | "finalized"): Promise<VerifyUtxosResult>;
2125
1693
  /**
2126
1694
  * Pre-flight gate: throw `UtxoAlreadySpentError` if any input is already
2127
- * spent on-chain. Called at the top of spend entry points in core/transact.
1695
+ * spent on-chain. Called at the top of spend entry points in flows/transact.
2128
1696
  *
2129
1697
  * Browser-safe: uses one batched RPC call.
2130
1698
  */
@@ -2272,7 +1840,7 @@ declare function assertDirectSubmissionLanded(params: {
2272
1840
  * 2026-01-23T00:51:46.489317Z INFO cloak::module: 📥 Message key=value
2273
1841
  *
2274
1842
  * Enable via:
2275
- * - SDK config: new CloakSDK({ debug: true })
1843
+ * - Code: setDebugMode(true)
2276
1844
  * - Environment: CLOAK_DEBUG=1 or DEBUG=cloak:*
2277
1845
  */
2278
1846
  type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR";
@@ -2724,20 +2292,8 @@ declare function getNullifierPDA(poolPubkey: PublicKey, nullifier: Uint8Array |
2724
2292
  */
2725
2293
  declare function getSwapStatePDA(poolPubkey: PublicKey, nullifier: Uint8Array | Buffer, programId?: PublicKey): [PublicKey, number];
2726
2294
  /**
2727
- * H-04: derive the per-pool RefundLedger PDA (conservation counter).
2728
- *
2729
- * Seeds: ["refund_ledger", pool_mint]
2730
- */
2731
- declare function getRefundLedgerPDA(mint?: PublicKey, programId?: PublicKey): [PublicKey, number];
2732
- /**
2733
- * H-04: derive the one-time RefundClaim PDA (replay guard for a voucher).
2734
- *
2735
- * Seeds: ["refund_claim", claim_id]
2736
- */
2737
- declare function getRefundClaimPDA(claimId: Uint8Array | Buffer, programId?: PublicKey): [PublicKey, number];
2738
- /**
2739
- * M-07/H-04: derive the per-pool PoolAuthorityConfig PDA (holds the
2740
- * withdraw-authorizer the refund voucher must be signed by).
2295
+ * M-07: derive the per-pool PoolAuthorityConfig PDA (holds the mint-scoped
2296
+ * withdraw-authorizer).
2741
2297
  *
2742
2298
  * Seeds: ["pool_authority", pool_mint]
2743
2299
  */
@@ -2759,76 +2315,6 @@ declare function getDeliveryRegistryPDA(programId?: PublicKey): PublicKey;
2759
2315
  */
2760
2316
  declare function getChainNoteRegistryPDA(programId?: PublicKey): PublicKey;
2761
2317
 
2762
- /**
2763
- * H-04 — claim-based timeout refund (SDK).
2764
- *
2765
- * When a private swap times out, `CloseSwapState` returns the parked principal
2766
- * to the pool and credits the on-chain `RefundLedger`. The user later reclaims
2767
- * that principal as a FRESH shielded note via `ClaimRefund`, gated by a
2768
- * withdraw-authorizer voucher (signed by the relay) and a deposit-shape Groth16
2769
- * proof — with no on-chain link back to the original swap.
2770
- *
2771
- * This module:
2772
- * 1. asks the relay to sign the 81-byte refund voucher for `claim_id`,
2773
- * 2. generates a deposit-shape proof (publicAmount = +refund_amount, zero
2774
- * inputs, one fresh output note `C_r`) bound to the live merkle root,
2775
- * 3. builds and submits the `[ed25519 voucher][CU][ClaimRefund]` transaction,
2776
- * 4. returns the fresh refund UTXO for the caller to store/spend later.
2777
- *
2778
- * The proof construction is byte-for-byte the same as the standalone
2779
- * `audit-tests/h-04/gen-claim-proof.cjs` generator that the program-side soak
2780
- * verified, so the proof verifies against the deployed transaction vkey.
2781
- */
2782
-
2783
- /** A relay-signed refund voucher, as returned by `POST /refund-voucher`. */
2784
- interface RefundVoucher {
2785
- /** base64 Ed25519 signature over the 81-byte message. */
2786
- signature: string;
2787
- /** hex 81-byte voucher message. */
2788
- message: string;
2789
- /** base58 signer (pool withdraw-authorizer). */
2790
- signer_pubkey: string;
2791
- /** expiry slot bound into the voucher. */
2792
- expiry_slot?: number;
2793
- }
2794
- interface ClaimTimeoutRefundParams {
2795
- /** Refund principal in lamports (must equal the closed swap's parked amount). */
2796
- refundAmount: bigint;
2797
- /** Pool mint; ClaimRefund is SOL-pool only (defaults to WSOL sentinel). */
2798
- poolMint?: PublicKey;
2799
- /** 32-byte claim id = H(user secret). Random if omitted. */
2800
- claimId?: Uint8Array;
2801
- /** Supply a pre-fetched voucher to skip the relay round-trip. */
2802
- voucher?: RefundVoucher;
2803
- }
2804
- interface ClaimTimeoutRefundOptions {
2805
- connection: Connection;
2806
- programId: PublicKey;
2807
- /** Relay base URL (used to fetch the voucher when not supplied). */
2808
- relayUrl?: string;
2809
- /** Pays fees + signs the claim tx (relay-submitted is a documented follow-up). */
2810
- payerKeypair: Keypair;
2811
- onProgress?: (message: string) => void;
2812
- }
2813
- interface ClaimTimeoutRefundResult {
2814
- /** Submitted ClaimRefund transaction signature. */
2815
- signature: string;
2816
- /** The fresh refund note created by the claim — store this to spend later. */
2817
- refundUtxo: Utxo;
2818
- /** The claim id consumed (hex). */
2819
- claimId: string;
2820
- /** The merkle leaf index where the refund note `C_r` landed. */
2821
- leafIndex: number;
2822
- }
2823
- /**
2824
- * Reclaim a timed-out swap's principal as a fresh shielded note via ClaimRefund.
2825
- *
2826
- * Front-running note: this self-submits the claim. The production default is
2827
- * relay submission (decision #3) to avoid mempool exposure of the voucher; a
2828
- * relay `/claim-refund` endpoint is the documented follow-up.
2829
- */
2830
- declare function claimTimeoutRefund(params: ClaimTimeoutRefundParams, options: ClaimTimeoutRefundOptions): Promise<ClaimTimeoutRefundResult>;
2831
-
2832
2318
  /**
2833
2319
  * On-chain Merkle proof computation
2834
2320
  *
@@ -2889,6 +2375,86 @@ declare function computeProofForLatestDeposit(connection: Connection, merkleTree
2889
2375
  leafIndex: number;
2890
2376
  }>;
2891
2377
 
2378
+ /**
2379
+ * The Cloak endpoints THIS BUILD of the SDK is allowed to talk to.
2380
+ *
2381
+ * ── Why this is a checked-in constant and not configuration ───────────────────────────────────
2382
+ * `dist/` is what `package.json` main/module/types resolve to, so `dist/` is what every consumer
2383
+ * executes. Anything a consumer can set at THEIR build or run time — `NODE_ENV`, an environment
2384
+ * variable, a bundler define, a call option — is not a pin, because we do not own the moment it is
2385
+ * resolved. `process.env.NODE_ENV === "production"` in particular is defeated by one line in a
2386
+ * consumer's bundler config or one `NODE_ENV=development` in front of `node`, so it is deliberately
2387
+ * not used anywhere in this package.
2388
+ *
2389
+ * The only value a published artifact carries that a consumer cannot supply is one that was decided
2390
+ * when WE built it. That is this file. It is compiled into the bundle, it is greppable in the
2391
+ * bundle, and changing it requires editing source and rebuilding.
2392
+ *
2393
+ * ── How to point the SDK somewhere else ───────────────────────────────────────────────────────
2394
+ * REPLACE the entry in {@link RELAY_ORIGIN_ALLOWLIST} with your local origin. Do not append:
2395
+ * appending leaves production reachable from a local build, which is exactly the pairing that made
2396
+ * a rehearsal POST real proof data to production (see SQ-F1 in
2397
+ * `src/__tests__/relay-url-no-production-default.test.ts`). Replacing makes production *unreachable*
2398
+ * from a local build, at every egress point, rather than merely "not the default".
2399
+ *
2400
+ * export const RELAY_ORIGIN_ALLOWLIST: readonly string[] = ["http://127.0.0.1:5500"];
2401
+ *
2402
+ * Inside this repo nothing else has to happen: jest (`roots: src`), `tsx examples/...` and
2403
+ * `scripts/` all resolve `@cloak.dev/sdk` to `src/index.ts` through the tsconfig path mapping, so
2404
+ * they pick the edit up with no build step. Only a consumer that imports `dist/` — the soak harness,
2405
+ * or a web/mobile checkout linked with `file:` / `npm link` — needs `npm run build` afterwards.
2406
+ *
2407
+ * `src/__tests__/relay-origin-lock.test.ts` goes red while the allowlist is local. That is the
2408
+ * mechanism working: a local allowlist cannot be committed or published without one deliberate red
2409
+ * test and a one-line `git diff` saying so. Run `git checkout src/config/relay.ts` before pushing.
2410
+ *
2411
+ * ── Scope, stated honestly ────────────────────────────────────────────────────────────────────
2412
+ * This is an integrity and product-control mechanism, not a security boundary. Anyone who can run
2413
+ * code in the consumer's process can `sed` this literal in `node_modules`, `patch-package` it, alias
2414
+ * the module, monkey-patch `globalThis.fetch`, or skip the SDK entirely. What it buys is that the
2415
+ * correct endpoint is the only one reachable BY ACCIDENT, and that any deviation is a deliberate,
2416
+ * visible, auditable edit.
2417
+ */
2418
+ /**
2419
+ * Identity of Cloak's production endpoint. This is a NAME, never a default: no code path in this
2420
+ * SDK falls back to it, and `resolveRelayUrl` still returns `undefined` when the caller passes
2421
+ * nothing (SQ-F1). It exists so a caller who genuinely wants production can say so by importing a
2422
+ * value instead of re-typing a host.
2423
+ */
2424
+ declare const CLOAK_PRODUCTION_RELAY_URL = "https://api.cloak.ag";
2425
+ /**
2426
+ * The origins this build may send a request to. Enforced at every network egress in the package by
2427
+ * `assertAllowedRelayOrigin` / `relayFetch` in `src/relay/endpoint.ts`, so it covers the entry
2428
+ * points that take a URL directly (`submitTransactToRelay`, `RelayService`, `fetchCommitments`,
2429
+ * `registerViewingKey`, `readMerkleTreeState`, …) and not only the `relayUrl` transact option.
2430
+ *
2431
+ * Typed `readonly string[]` and not `as const` on purpose: a developer replaces the entry, and a
2432
+ * literal tuple type would make that edit a `tsc` error in unrelated files.
2433
+ */
2434
+ declare const RELAY_ORIGIN_ALLOWLIST: readonly string[];
2435
+ /**
2436
+ * ONE switch, DERIVED — not a second flag to keep in sync.
2437
+ *
2438
+ * True exactly when {@link RELAY_ORIGIN_ALLOWLIST} names a loopback origin, i.e. when this artifact
2439
+ * was built for a local stack. It is what "this build is a production artifact" means for the
2440
+ * localhost-RPC guard, and because it is derived there is no state where the endpoint is local but
2441
+ * the RPC guard is still armed. The single edit above flips both.
2442
+ *
2443
+ * ── Why the build, and not the program id, the RPC URL, or the relay URL ──────────────────────
2444
+ * - **Program id**: identical on mainnet and on the whole local estate by design — a Surfpool fork
2445
+ * mirrors mainnet, so it carries the same program id (see `src/program/ids.ts`). Zero
2446
+ * discriminating power.
2447
+ * - **`detectNetworkFromRpcUrl`**: answers "localnet" for any localhost URL and defaults unknown
2448
+ * strings to "mainnet" (`src/shared/network.ts`). For Surfpool — a localhost URL mirroring
2449
+ * mainnet — that is exactly inverted, which is why `src/relay/risk-quote.ts` calls it and
2450
+ * immediately undoes the answer. It also reads its own environment variable.
2451
+ * - **"the relay URL is the production one"**: the same fact as this flag, reached by string
2452
+ * comparison, and undefined on the `relayUrl: ""` self-submit path.
2453
+ * - **This flag**: fixed at the same instant the endpoint is fixed, unchangeable by a consumer
2454
+ * without forking, and needs no run-time classification of an attacker-supplied string.
2455
+ */
2456
+ declare const BUILD_ALLOWS_LOCAL_ENDPOINTS: boolean;
2457
+
2892
2458
  /**
2893
2459
  * Relay client utilities for fetching data from the relay service
2894
2460
  */
@@ -3008,11 +2574,11 @@ declare function preflightCheck(relayUrl: string, rootHex: string): Promise<{
3008
2574
  * The merkle-from-chain rebuild was guarded by TWO independently written predicates that disagreed
3009
2575
  * about React Native:
3010
2576
  *
3011
- * - the GATE in `core/transact.ts` — `!IS_BROWSER && isMerkleClass && relayUrl`, where
2577
+ * - the GATE in `flows/transact.ts` — `!IS_BROWSER && isMerkleClass && relayUrl`, where
3012
2578
  * `IS_BROWSER` was `typeof window !== "undefined" || typeof globalThis.document !== "undefined"`,
3013
2579
  * with NO React-Native carve-out. React Native defines `window`, so RN read as a browser and the
3014
2580
  * last-resort chain replay was silently skipped there.
3015
- * - the BUILDER it guards — `utils/relay-client.ts::buildMerkleTreeFromChain`, whose own
2581
+ * - the BUILDER it guards — `relay/client.ts::buildMerkleTreeFromChain`, whose own
3016
2582
  * `isBrowser()` short-circuits on `navigator.product === "ReactNative"` and therefore explicitly
3017
2583
  * PERMITS React Native to rebuild from chain.
3018
2584
  *
@@ -3050,7 +2616,7 @@ declare function preflightCheck(relayUrl: string, rootHex: string): Promise<{
3050
2616
  */
3051
2617
  /**
3052
2618
  * True on React Native. `navigator.product === "ReactNative"` is the canonical flag and is what
3053
- * `utils/proof-generation.ts` has always used.
2619
+ * `proving/artifacts.ts` has always used.
3054
2620
  */
3055
2621
  declare function isReactNative(): boolean;
3056
2622
  /**
@@ -3068,42 +2634,137 @@ declare function isBrowser(): boolean;
3068
2634
  declare function isBrowserLike(): boolean;
3069
2635
 
3070
2636
  /**
3071
- * Circuit artifact releases the single source of truth for
3072
- * "which bundle version" and "which bytes are that bundle".
3073
- *
3074
- * Why this file exists
3075
- * -------------------
3076
- * The version segment of the artifact base URL and the pinned SHA-256 digests
3077
- * used to be written out by hand in two unrelated places
3078
- * (`utils/proof-generation.ts` held `.../circuits/0.1.0` plus a digest table,
3079
- * `core/transact.ts` held its own copy of the same URL literal). They drifted:
3080
- * the default base pointed at the `0.1.0` bundle while the pinned `transaction`
3081
- * digests were the `0.2.0` trusted-setup ceremony output, so every default-config
3082
- * proof died on a digest mismatch several megabytes into proof generation.
3083
- *
3084
- * Here a bundle is declared once, as a version plus the digests of the artifacts
3085
- * that version contains, and the base URL is *derived* from that version by
3086
- * {@link defineCircuitBundle}. There is no way to write a URL whose version
3087
- * segment disagrees with the digests next to it:
3088
- *
3089
- * - **compile time** `baseUrl` is typed `` `${string}/circuits/${V}` ``, where
3090
- * `V` is the bundle's own `version` literal, and {@link BUNDLE_BY_CIRCUIT} is
3091
- * an exhaustive `Record<CircuitName, …>`, so a new circuit with no bundle, or
3092
- * an assertion about a version the bundle does not carry, fails `tsc`.
3093
- * - **startup** {@link assertCircuitReleaseConsistency} runs at module load
3094
- * and throws if a bundle's digests are malformed, if a bundle does not pin the
3095
- * circuit that maps to it, or if a hand-edited base URL stops ending in its own
3096
- * version. That is an import-time failure, not a failure deep inside
3097
- * `groth16.fullProve`.
3098
- *
3099
- * Publication is deliberately *not* assumed. A bundle whose bytes this SDK has
3100
- * not verified at a public location carries `baseUrl: null`; callers must point
3101
- * the SDK at a location themselves (`setCircuitsPath`). Nothing here silently
3102
- * defaults to a URL that has not been checked against the digests below.
3103
- */
3104
- /** Circuits whose artifacts carry a pinned SHA-256 digest in this SDK. */
3105
- type CircuitName = 'withdraw_regular' | 'withdraw_swap' | 'transaction';
3106
- /** Version of the trusted-setup ceremony bundle that froze the `transaction` circuit. */
2637
+ * How long the relay accepts a signed request after its `auth_issued_at`
2638
+ * (`REQUEST_AUTH_MAX_AGE_SECONDS`, `api/request_auth.rs`).
2639
+ *
2640
+ * A FIRST-USE request past this window is rejected outright. The expiry exception the relay grants
2641
+ * applies only to an exact replay of a request whose durable row already exists, which by
2642
+ * definition never happens for a request that has not been accepted once.
2643
+ */
2644
+ declare const REQUEST_AUTH_MAX_AGE_SECONDS = 300;
2645
+ /**
2646
+ * How far ahead of the relay's clock a request may be stamped
2647
+ * (`REQUEST_AUTH_MAX_FUTURE_SKEW_SECONDS`, `api/request_auth.rs`).
2648
+ *
2649
+ * `auth_issued_at` comes from `Date.now()`. On a server that is NTP-disciplined; in a browser it
2650
+ * is the user's own machine clock, and a laptop more than 30 seconds fast cannot authenticate at
2651
+ * all until its clock is corrected.
2652
+ */
2653
+ declare const REQUEST_AUTH_MAX_FUTURE_SKEW_SECONDS = 30;
2654
+ /**
2655
+ * The exact fields each endpoint signs. Both lists mirror the relay's `*_auth_request` builders and
2656
+ * must stay in lockstep with them: adding a field on one side alone silently invalidates every
2657
+ * signature, and the failure surfaces as a bare 401 with nothing pointing here.
2658
+ */
2659
+ declare const TRANSACT_AUTH_FIELDS: readonly ["encrypted_notes", "max_fee", "mint", "proof_bytes", "public_inputs", "recipient", "recipient_delivery_notes", "risk_quote", "sender"];
2660
+ declare const TRANSACT_SWAP_AUTH_FIELDS: readonly ["close_timed_out", "dexes", "encrypted_notes", "exclude_dexes", "max_fee", "min_output_amount", "output_mint", "proof_bytes", "public_inputs", "recipient", "recipient_ata", "refund_blinding", "refund_pubkey", "retry_request_id", "risk_quote", "route_retry_attempts", "sender", "slippage_bps", "swap_max_retries"];
2661
+ /**
2662
+ * Serialize exactly like the relay's `canonical_json`: keys sorted bytewise, no whitespace.
2663
+ *
2664
+ * SCOPE. This is the SDK's half of a byte-for-byte agreement with one specific Rust function over
2665
+ * one specific schema: the values reachable through {@link TRANSACT_AUTH_FIELDS} and
2666
+ * {@link TRANSACT_SWAP_AUTH_FIELDS}, which are ASCII keys over strings, small unsigned integers,
2667
+ * booleans, nulls, arrays and plain objects. Inside that schema the two implementations agree.
2668
+ *
2669
+ * Outside it they need not, so anything that could serialize differently on the two sides is
2670
+ * REFUSED here rather than signed into a digest that silently fails to match:
2671
+ *
2672
+ * - Non-integer, non-finite and beyond-safe-integer numbers. `serde_json` renders an f64 as Rust
2673
+ * does (`1e21`) where JavaScript renders `1e+21`, and `0.1 + 0.2` has no single spelling. Every
2674
+ * number in both field lists is a small unsigned integer (`slippage_bps`, `route_retry_attempts`,
2675
+ * `swap_max_retries`); u64 amounts already travel as decimal STRINGS for exactly this reason.
2676
+ * - Functions and symbols as object VALUES. `JSON.stringify` drops such a key from the wire body
2677
+ * while it stays in the signed view, so the two digests can never agree.
2678
+ *
2679
+ * `undefined` is NOT refused: it serializes as `null` here, `JSON.stringify` omits the key on the
2680
+ * wire, and every optional field on the relay side is `Option<T>` with `#[serde(default)]`, so the
2681
+ * relay sees `null` too. That is the same agreement {@link buildAuthRequest} relies on. The one
2682
+ * field where it does not hold is `slippage_bps`, which is why that field is checked by name.
2683
+ *
2684
+ * `bigint` is accepted and rendered as a bare decimal integer, matching serde's u64/i64 output.
2685
+ * Note that such a value cannot also go on the wire: `JSON.stringify` throws on a bigint. Use a
2686
+ * decimal string in the body, as every SDK-built body does.
2687
+ */
2688
+ declare function canonicalJson(value: unknown): string;
2689
+ /**
2690
+ * Everything an authenticated request needs EXCEPT the signature: the three fields that go on the
2691
+ * wire alongside it, plus the exact bytes to sign.
2692
+ *
2693
+ * This exists because the holder of the pen is not always a `Keypair`. A browser wallet adapter
2694
+ * exposes `signMessage(bytes): Promise<Uint8Array>` and no secret key at all, so the scheme has to
2695
+ * be reachable in two halves: build the preimage here, sign it wherever the key actually lives,
2696
+ * then put `sender` / `auth_issued_at` / `auth_nonce` and the base64 signature on the body.
2697
+ *
2698
+ * `message` is a plain ed25519 detached-signature preimage — nothing about the scheme changes
2699
+ * between a local keypair and a wallet, only who signs it.
2700
+ */
2701
+ interface RelayAuthPreimage {
2702
+ sender: string;
2703
+ auth_issued_at: string;
2704
+ auth_nonce: string;
2705
+ message: Uint8Array;
2706
+ }
2707
+ /**
2708
+ * Build the signed view and its preimage for one request, WITHOUT signing.
2709
+ *
2710
+ * `sender` is bound into the signed view and returned for the body — the relay rejects a request
2711
+ * whose authenticated sender is not also present inside the signed payload. It must be the end
2712
+ * user's own wallet: `sender` is the key screened for sanctions on a shield-to-shield send, so
2713
+ * substituting an ephemeral or service key here moves the screening off the actual user.
2714
+ *
2715
+ * `nonce` and `issued_at` are generated here, once per call. Callers that re-POST a request must
2716
+ * reuse the same preimage rather than rebuilding it, or the relay sees a brand-new request.
2717
+ */
2718
+ declare function buildRelayAuthPreimage(endpoint: string, programId: PublicKey, body: Record<string, unknown>, sender: PublicKey, nowSeconds?: number, fields?: readonly string[]): RelayAuthPreimage;
2719
+ /**
2720
+ * An async message signer standing in for a `Keypair`.
2721
+ *
2722
+ * A browser wallet adapter has no secret key to hand over — it exposes `signMessage`, and what
2723
+ * this scheme needs signed is a plain ed25519 detached signature, which is exactly what that
2724
+ * produces. Only the holder of the pen changes.
2725
+ *
2726
+ * COMPLIANCE — `walletPublicKey` becomes the request's authenticated `sender`, and `sender` is the
2727
+ * key screened for sanctions on a shield-to-shield send. It MUST be the end user's own wallet.
2728
+ * Putting an ephemeral, service-held or otherwise substituted key here moves the screening onto a
2729
+ * key that is not the user: a compliance regression, not a shortcut.
2730
+ */
2731
+ interface RelayAuthSigner {
2732
+ /** The end user's real wallet. Becomes the authenticated `sender`. Never an ephemeral key. */
2733
+ walletPublicKey: PublicKey;
2734
+ /** Wallet-adapter `signMessage`; must return the 64-byte ed25519 detached signature. */
2735
+ signMessage: (message: Uint8Array) => Promise<Uint8Array>;
2736
+ }
2737
+ /**
2738
+ * Turn a relay rejection into something the person in front of the screen can act on.
2739
+ *
2740
+ * Every string matched here is an `Error::Unauthorized` from `api/request_auth.rs`, and all of them
2741
+ * arrive as the same bare 401. Two of them are not the caller's mistake at all: an approval that
2742
+ * sat too long, and a machine clock that is simply wrong. Returns `null` for anything that is not
2743
+ * an authentication rejection, so callers can append it only when there is something to add.
2744
+ */
2745
+ declare function explainRelayAuthRejection(responseText: string): string | null;
2746
+
2747
+ /**
2748
+ * The circuit artifacts this SDK build proves against.
2749
+ *
2750
+ * One program, one circuit, one bundle: the deployed shield-pool embeds the
2751
+ * ceremony verifying key, so any other artifact set produces proofs the program
2752
+ * rejects (0x1010). There is deliberately no table, no bundle registry and no
2753
+ * version negotiation here -- an SDK build either matches the deployed program
2754
+ * or it is the wrong build.
2755
+ *
2756
+ * The digests are the security control: `loadVerifiedCircuitArtifacts` hashes
2757
+ * whatever it fetched and refuses to prove on a mismatch, so a compromised or
2758
+ * stale CDN cannot feed this build artifacts from another ceremony.
2759
+ *
2760
+ * Published and verified 2026-08-12; re-verify after any publish with
2761
+ * `packages/scripts/publish-circuits.sh --verify-only`. Two things that publish
2762
+ * established, both worth keeping in mind here:
2763
+ * - the prefix once held a half-finished upload (zkey and wasm, no witness
2764
+ * helpers), which is exactly what these digests defend against;
2765
+ * - the edge served the previous wasm for ~50 minutes after a correct upload,
2766
+ * so uploading the right bytes is not the same as serving them.
2767
+ */
3107
2768
  declare const TRANSACTION_CIRCUITS_VERSION = "0.2.0";
3108
2769
 
3109
2770
  /**
@@ -3123,7 +2784,7 @@ declare const TRANSACTION_CIRCUITS_VERSION = "0.2.0";
3123
2784
  * RN defines `window`, so the old inline `typeof window !== "undefined" || typeof document !==
3124
2785
  * "undefined"` classified RN as a browser and skipped the rebuild, removing RN's only recovery path
3125
2786
  * from a drifted relay tree while the builder was perfectly willing to serve it. Both now come from
3126
- * `utils/environment`, so they cannot disagree about React Native again.
2787
+ * `shared/environment`, so they cannot disagree about React Native again.
3127
2788
  *
3128
2789
  * The SSR conservatism is kept: `isBrowserLike()` is true when EITHER `window` or `document` exists,
3129
2790
  * because an SSR host that polyfills only `document` must not be mistaken for Node and made to run a
@@ -3137,7 +2798,7 @@ declare function canRebuildMerkleTreeFromChain(): boolean;
3137
2798
  /**
3138
2799
  * Base the ceremony-frozen `transaction` artifacts are fetched from by default.
3139
2800
  *
3140
- * Derived from {@link TRANSACTION_CIRCUIT_BUNDLE} — the same record that pins the
2801
+ * Derived from {@link TRANSACTION_CIRCUITS_BASE_URL} — the same record that pins the
3141
2802
  * digests — so the version in the URL and the digests checked against it cannot
3142
2803
  * drift apart. It is `null` while this SDK build pins no location whose bytes
3143
2804
  * were verified to hash to those digests; that makes an unconfigured SDK a
@@ -3151,9 +2812,26 @@ declare const DEFAULT_TRANSACTION_CIRCUITS_URL: string | null;
3151
2812
  * Set circuits base path: local directory containing `transaction_js/` and `transaction_final.zkey`,
3152
2813
  * or an `http(s)` base URL to those artifacts (loaded into memory once per process).
3153
2814
  *
2815
+ * ── Kept, not removed, and now checked ────────────────────────────────────────────────────────
2816
+ * It stays public API for one reason the pin cannot serve: an offline, air-gapped or React-Native
2817
+ * caller must be able to name a LOCAL directory holding the ceremony artifacts, and every example
2818
+ * in this repo calls it. What changed is that the string is no longer honoured verbatim. It goes
2819
+ * through {@link assertAllowedCircuitsBase}, the same shape of check `relayUrl` gets: a local
2820
+ * directory is accepted (it puts nothing on the wire, and the unconditional digest check governs
2821
+ * its bytes), an `http(s)` base must be at or under this build's pinned bundle base, and a loopback
2822
+ * base is accepted only in a build whose relay allowlist is already local.
2823
+ *
2824
+ * Asserted HERE for a good early error, and again at the read itself in `proving/artifacts.ts` —
2825
+ * because this setter is not the only door: `loadVerifiedCircuitArtifacts`, `verifyCircuitIntegrity`,
2826
+ * `assertTransactionCircuitIntegrity` and `verifyAllCircuits` are all exported and all take a base
2827
+ * directly. A setter-only check would have been theatre, exactly as it would have been for the
2828
+ * relay URL.
2829
+ *
3154
2830
  * No cache invalidation is needed here: verified artifact buffers are memoised
3155
- * per base inside `proof-generation.ts`, so a new base loads and re-verifies its
2831
+ * per base inside `proving/artifacts.ts`, so a new base loads and re-verifies its
3156
2832
  * own bytes.
2833
+ *
2834
+ * @throws when `next` names a location this build may not read circuit artifacts from.
3157
2835
  */
3158
2836
  declare function setCircuitsPath(next: string): void;
3159
2837
  /**
@@ -3162,13 +2840,22 @@ declare function setCircuitsPath(next: string): void;
3162
2840
  */
3163
2841
  declare function getCircuitsPath(): string | null;
3164
2842
  /**
3165
- * Resolve a base to prove from: an explicit argument, else `CLOAK_CIRCUITS_PATH`
3166
- * / `CLOAK_CIRCUITS` from the environment, else this build's pinned default.
2843
+ * Resolve a base to prove from: an explicit argument, else this build's pinned default.
2844
+ *
2845
+ * ── The environment reads are gone ────────────────────────────────────────────────────────────
2846
+ * This used to fall back to `CLOAK_CIRCUITS_PATH` / `CLOAK_CIRCUITS`. Both resolve in the
2847
+ * CONSUMER's process, which is the same reason `NODE_ENV` is not used anywhere in this package:
2848
+ * `CLOAK_CIRCUITS_PATH=http://evil.example/circuits node app.js`, or one
2849
+ * `--define:process.env.CLOAK_CIRCUITS_PATH='"http://evil.example/circuits"'` in a consumer's
2850
+ * bundler, silently moved where the witness generator came from — and the witness generator is
2851
+ * handed the spend key. An integrator who genuinely needs a different location passes it
2852
+ * explicitly and it is checked against the pin like any other.
3167
2853
  *
3168
2854
  * Use this instead of writing an artifact URL out by hand — a hand-written URL
3169
2855
  * is exactly how the base's version segment came to disagree with the digests
3170
2856
  * this SDK checks against. Throws an explanatory error (naming the expected
3171
- * bundle version and both expected digests) when nothing resolves.
2857
+ * bundle version and both expected digests) when nothing resolves, and refuses a
2858
+ * base this build may not read from.
3172
2859
  */
3173
2860
  declare function resolveCircuitsBase(explicit?: string): string;
3174
2861
  /**
@@ -3182,6 +2869,68 @@ declare function resolveCircuitsBase(explicit?: string): string;
3182
2869
  */
3183
2870
  declare function computeChainNoteHash(publicAmount: bigint, extDataHash: bigint, noteTimestamp: bigint, noteCommitment: bigint, noteSalt: bigint, outAmount0: bigint, outPubkey0: bigint, noteIsSendToSelfKey0: bigint): Promise<bigint>;
3184
2871
  declare function computeExtDataHash(recipient: PublicKey | null, relayerFee: bigint, relayer: PublicKey | null, maxFee?: bigint): Promise<bigint>;
2872
+ /**
2873
+ * Adapter for a third-party fee-payer relayer (e.g. Kora, https://github.com/solana-foundation/kora)
2874
+ * that lets the depositor pay network fees — and, via `buildTopUpInstructions`, the on-chain rent
2875
+ * this deposit itself needs — in an SPL token instead of native SOL. Only consulted on the deposit
2876
+ * path (externalAmount > 0); ignored for transfers/withdrawals/swaps, which already go through the
2877
+ * relay's own SOL-funded fee payer. Optional — omitting this leaves every existing caller (including
2878
+ * the web app) byte-for-byte unchanged: the depositor remains the fee payer and must hold SOL.
2879
+ */
2880
+ interface ExternalFeePayerAdapter {
2881
+ /** Returns the external fee payer's pubkey (Kora's `getPayerSigner`). */
2882
+ getPayerPubkey: () => Promise<PublicKey>;
2883
+ /**
2884
+ * Instructions to insert right after the risk-quote instruction (if any) and before every
2885
+ * instruction that spends the depositor's own SOL balance — typically a single
2886
+ * `SystemProgram.transfer(payerPubkey → depositor, neededLamports)`, so the depositor never
2887
+ * needs to hold SOL up front. Return an empty array when no top-up is needed (the depositor
2888
+ * already has enough SOL for on-chain rent).
2889
+ *
2890
+ * A plain transfer works because the external payer's own fee-pricing engine (e.g. Kora's
2891
+ * `calculate_fee_payer_outflow`) already accounts for ANY lamport outflow from its own account
2892
+ * across the whole transaction — not just the base network fee — when it prices
2893
+ * `getPaymentInstruction`. No swap instruction or DEX integration is needed on the client: the
2894
+ * payer's server-side pricing (margin/fixed, its own config) charges for this transfer
2895
+ * automatically. The payer is expected to replenish its own SOL out-of-band (e.g. periodically
2896
+ * converting collected SPL fees back to SOL) — that is entirely the payer's operational concern,
2897
+ * invisible to this adapter and to the depositor.
2898
+ *
2899
+ * Must NOT be inserted before the risk-quote instruction: the on-chain program verifies the risk
2900
+ * quote's Ed25519 signature via instruction introspection at a fixed transaction-level index (0),
2901
+ * so the risk-quote instruction must remain first no matter what else this adapter adds.
2902
+ *
2903
+ * Must NOT include ComputeBudgetProgram instructions of its own — the transaction already
2904
+ * carries one of each, sized for the whole thing including this top-up; a second pair is
2905
+ * rejected by the runtime as duplicate instructions.
2906
+ */
2907
+ buildTopUpInstructions: (payerPubkey: PublicKey) => Promise<TransactionInstruction[]>;
2908
+ /**
2909
+ * Given a base64-encoded, unsigned V0 transaction (feePayer = the external payer's pubkey, every
2910
+ * instruction the deposit needs including any top-up, fresh blockhash), returns the fee-payment
2911
+ * instruction to append before final signing (Kora's `getPaymentInstruction`).
2912
+ */
2913
+ getPaymentInstruction: (unsignedTxBase64: string) => Promise<TransactionInstruction>;
2914
+ /**
2915
+ * Given a base64-encoded transaction the depositor has already partially signed (their own signer
2916
+ * slot filled; the external payer's slot still empty — same instructions plus the payment
2917
+ * instruction, fresh blockhash), returns the fully co-signed transaction, base64-encoded (Kora's
2918
+ * `signTransaction`).
2919
+ */
2920
+ cosign: (partiallySignedTxBase64: string) => Promise<string>;
2921
+ /**
2922
+ * Optional: accounts the payment instruction will reference, resolvable BEFORE that instruction
2923
+ * exists (for Kora: the fee payer's and depositor's fee-token ATAs).
2924
+ *
2925
+ * Purely a size optimization, never correctness — the real accounts always come from
2926
+ * `getPaymentInstruction`. Without it, the supplemental ALT built for the quote transaction can't
2927
+ * know about the payment instruction's accounts, so a deposit that lands just over the packet
2928
+ * limit once that instruction is appended needs a SECOND supplemental ALT (an extra on-chain
2929
+ * transaction and extra rent, paid by the external payer). Measured on the first real deposit:
2930
+ * 1236 bytes vs the 1232 limit — over by 4. With the hint, one ALT covers the final transaction.
2931
+ */
2932
+ getPaymentAccountHints?: () => Promise<PublicKey[]>;
2933
+ }
3185
2934
  /**
3186
2935
  * Options for transact operation
3187
2936
  */
@@ -3199,8 +2948,19 @@ interface TransactOptions {
3199
2948
  /** Relayer address for fee payment */
3200
2949
  relayer?: PublicKey;
3201
2950
  /**
3202
- * Relay URL. Never defaulted: resolved from this option, then from `CLOAK_RELAY_URL`.
3203
- * Name production explicitly (`https://api.cloak.ag`).
2951
+ * Cloak endpoint to submit through.
2952
+ *
2953
+ * This option no longer SELECTS the endpoint — the endpoint is pinned when the SDK is built
2954
+ * (`RELAY_ORIGIN_ALLOWLIST` in `src/config/relay.ts`). Only two values are accepted:
2955
+ *
2956
+ * - an origin on this build's allowlist — say `CLOAK_PRODUCTION_RELAY_URL` rather than typing a
2957
+ * host; anything else throws, naming the value and the allowlist;
2958
+ * - `""`, which means NO endpoint: the caller signs and submits the deposit itself. Unchanged,
2959
+ * still supported, and checked before any validation.
2960
+ *
2961
+ * Never defaulted. Omitting it still yields `undefined` (SQ-F1), not production. To point at a
2962
+ * local stack, edit `src/config/relay.ts` and rebuild — not an option, not an environment
2963
+ * variable, because a published build must not be repointable at either.
3204
2964
  */
3205
2965
  relayUrl?: string;
3206
2966
  /** Keypair of the depositor (signs the deposit transaction) - for programmatic use */
@@ -3219,6 +2979,16 @@ interface TransactOptions {
3219
2979
  walletPublicKey?: PublicKey;
3220
2980
  /** Maximum retries on RootNotFound error (default: 5) */
3221
2981
  maxRootRetries?: number;
2982
+ /**
2983
+ * How many times a wallet adapter may be asked to approve ONE swap (default: 5).
2984
+ *
2985
+ * Only applies to the wallet-adapter path, and only to `swapUtxo` / `swapWithChange`: a swap
2986
+ * re-proves on every retry, so every retry needs a fresh approval, and `maxRootRetries` alone
2987
+ * would allow 41 dialogs for a single swap. A `depositorKeypair` signs without prompting and is
2988
+ * bounded by `maxRootRetries` as before. A private send or withdrawal signs exactly once,
2989
+ * whatever happens on the network.
2990
+ */
2991
+ maxWalletApprovals?: number;
3222
2992
  /** Delay between retries in ms (default: 3000) */
3223
2993
  retryDelayMs?: number;
3224
2994
  /**
@@ -3231,6 +3001,12 @@ interface TransactOptions {
3231
3001
  * Used for deposits when riskOracleQueue is set. The backend must return a signed
3232
3002
  * quote instruction for the depositor wallet so the program can verify at index 0.
3233
3003
  * Defaults to `${relayUrl}/range-quote` when relayUrl is set.
3004
+ *
3005
+ * Held to the SAME build-pinned allowlist as `relayUrl`: it is fetched directly and it is
3006
+ * converted back into a base URL by `deriveRelayUrlFromRiskQuoteUrl`, so leaving it unchecked
3007
+ * would leave a second door onto the first. It must therefore be an ABSOLUTE URL on this build's
3008
+ * allowlist; a relative path (e.g. `/api/risk-quote`) is no longer resolved against the page
3009
+ * origin. `""` disables the SDK-side prefetch, unchanged.
3234
3010
  */
3235
3011
  riskQuoteUrl?: string;
3236
3012
  /**
@@ -3352,7 +3128,7 @@ interface TransactOptions {
3352
3128
  useUniqueNullifiers?: boolean;
3353
3129
  /**
3354
3130
  * Optional DEX allow-list for swaps (Jupiter `dexes`).
3355
- * Example: ["Orca V2", "Raydium CLMM"]
3131
+ * Example: ["Meteora DLMM", "Raydium CLMM"]
3356
3132
  */
3357
3133
  swapDexes?: string[];
3358
3134
  /**
@@ -3392,8 +3168,24 @@ interface TransactOptions {
3392
3168
  * Use when relay may be behind the chain (e.g. commitment_sync lag) to avoid ProofInvalid.
3393
3169
  */
3394
3170
  useChainRootForProof?: boolean;
3171
+ /**
3172
+ * Optional external fee-payer adapter (e.g. Kora) for deposits only. When set, the depositor no
3173
+ * longer needs to hold SOL: the adapter's payer covers the network fee (and, via
3174
+ * `buildTopUpInstructions`, any on-chain rent) and is reimbursed in an SPL token within the same
3175
+ * transaction. Omit for unchanged default behavior.
3176
+ */
3177
+ externalFeePayer?: ExternalFeePayerAdapter;
3395
3178
  }
3396
- /** Switchboard-style response: pre-built instruction. */
3179
+ /**
3180
+ * Switchboard-style response: a pre-built instruction.
3181
+ *
3182
+ * @deprecated No longer accepted. `fetchRiskQuote` rejects this shape outright:
3183
+ * a relay that can name the program id, the account metas and the data of an
3184
+ * instruction the user's wallet signs is a signing oracle. The relay only ever
3185
+ * returns `{ signature, message, signer_pubkey }`, which the SDK verifies and
3186
+ * rebuilds locally as an account-free Ed25519 instruction. The type is kept as
3187
+ * an export purely so consumers importing it still compile.
3188
+ */
3397
3189
  interface RiskQuoteInstructionResponse {
3398
3190
  instruction: {
3399
3191
  programId: string;
@@ -3470,12 +3262,23 @@ type RelaySubmissionResult = {
3470
3262
  kind: "failed";
3471
3263
  error: Error;
3472
3264
  };
3265
+
3473
3266
  interface SubmitTransactToRelayArgs {
3474
3267
  relayUrl: string;
3475
3268
  /** The exact body to POST. Auth fields are added ONCE, in place, and then never changed. */
3476
3269
  requestBody: Record<string, unknown>;
3477
3270
  programId: PublicKey;
3478
3271
  depositorKeypair?: Keypair;
3272
+ /**
3273
+ * Wallet-adapter alternative to `depositorKeypair` for request authentication, used only when
3274
+ * no keypair is supplied. Lets a browser or mobile caller — which holds no secret key — submit
3275
+ * through this same function instead of hand-rolling the scheme.
3276
+ *
3277
+ * COMPLIANCE: `walletPublicKey` becomes the authenticated `sender`, which is the key screened
3278
+ * for sanctions on shield-to-shield sends. It must be the end user's real wallet; an ephemeral
3279
+ * or server-side key here is a compliance regression, not a shortcut.
3280
+ */
3281
+ relayAuthSigner?: RelayAuthSigner;
3479
3282
  settlement: SettlementContext;
3480
3283
  /** True while the caller still has a re-prove budget for a stale root. */
3481
3284
  canRetryStaleRoot: boolean;
@@ -3606,9 +3409,9 @@ interface UtxoSwapResult extends TransactResult {
3606
3409
  * Execute a UTXO swap withdrawal
3607
3410
  *
3608
3411
  * This spends input UTXOs and creates a SwapState PDA for swapping SOL to SPL tokens.
3609
- * After this transaction, the relay can execute:
3610
- * 1. PrepareSwapSol - Wrap SOL to wSOL
3611
- * 2. ExecuteSwapViaOrca - Execute the swap on Orca
3412
+ * The swap is then completed on-chain in two follow-up instructions:
3413
+ * 1. PrepareSwapSol - Wrap the SOL held by the SwapState PDA into wSOL
3414
+ * 2. ExecuteSwap - Route the wSOL through Jupiter and deliver the output token to `recipientAta`
3612
3415
  *
3613
3416
  * @param params Swap parameters
3614
3417
  * @param options Transaction options
@@ -3630,129 +3433,59 @@ declare function swapUtxo(params: UtxoSwapParams, options: TransactOptions): Pro
3630
3433
  declare function swapWithChange(inputUtxos: Utxo[], swapAmount: bigint, outputMint: PublicKey, recipientAta: PublicKey, minOutputAmount: bigint, options: TransactOptions, recipientWallet?: PublicKey): Promise<UtxoSwapResult>;
3631
3434
 
3632
3435
  /**
3633
- * Direct Circom WASM Proof Generation
3436
+ * Circuit artifact loading and integrity verification.
3634
3437
  *
3635
- * This module provides direct proof generation using snarkjs and Circom WASM,
3636
- * matching the approach used in services-new/tests/src/proof.ts
3438
+ * Artifacts come from the pinned bundle in `config/circuits`, verified
3439
+ * by digest; no backend prover service is required. Proof generation itself
3440
+ * lives with the flows that own it (`flows/transact.ts`), which passes the
3441
+ * verified buffers this module returns straight to `snarkjs.groth16.fullProve`.
3637
3442
  *
3638
- * Artifacts come from the pinned per-bundle hosts in `config/circuit-release`,
3639
- * verified by digest; no backend prover service is required.
3640
- */
3641
-
3642
- /**
3643
- * Default base URL for the legacy `withdraw_regular` / `withdraw_swap` artifacts.
3644
- *
3645
- * Derived from {@link LEGACY_WITHDRAW_CIRCUIT_BUNDLE}, so the version segment is
3646
- * the same one the pinned digests were declared under. Do not write this URL out
3647
- * by hand anywhere — change the bundle instead.
3648
- *
3649
- * This is NOT the base for the ceremony-frozen `transaction` circuit: that
3650
- * circuit lives in a different bundle ({@link TRANSACTION_CIRCUIT_BUNDLE}) with
3651
- * different digests, and is configured through `setCircuitsPath()`.
3652
- *
3653
- * `string | null` — null when the bundle has no published host, which is the
3654
- * case for the legacy withdraw artifacts.
3655
- *
3656
- * RESOLVED LAZILY ON PURPOSE. This was previously
3657
- * `requirePinnedBaseUrl('withdraw_regular')` evaluated at module scope, so an
3658
- * unpinned bundle made merely IMPORTING the SDK throw — breaking every consumer,
3659
- * including those that never touch a legacy withdraw path. The diagnostic is
3660
- * still raised, by `resolveCircuitsUrl` and `getDefaultCircuitsPath` at the
3661
- * point of use, where a caller can actually act on it.
3662
- */
3663
- declare const DEFAULT_CIRCUITS_URL: string | null;
3664
- interface WithdrawRegularInputs {
3665
- root: bigint;
3666
- nullifier: bigint;
3667
- outputs_hash: bigint;
3668
- public_amount: bigint;
3669
- amount: bigint;
3670
- leaf_index: bigint;
3671
- sk: [bigint, bigint];
3672
- r: [bigint, bigint];
3673
- pathElements: bigint[];
3674
- pathIndices: number[];
3675
- num_outputs: number;
3676
- out_addr: bigint[][];
3677
- out_amount: bigint[];
3678
- out_flags: number[];
3679
- var_fee: bigint;
3680
- rem: bigint;
3681
- }
3682
- interface WithdrawSwapInputs {
3683
- sk_spend: bigint;
3684
- r: bigint;
3685
- amount: bigint;
3686
- leaf_index: bigint;
3687
- path_elements: bigint[];
3688
- path_indices: number[];
3689
- root: bigint;
3690
- nullifier: bigint;
3691
- outputs_hash: bigint;
3692
- public_amount: bigint;
3693
- input_mint: bigint[];
3694
- output_mint: bigint[];
3695
- recipient_ata: bigint[];
3696
- min_output_amount: bigint;
3697
- var_fee: bigint;
3698
- rem: bigint;
3699
- }
3700
- interface ProofResult {
3701
- proof: Groth16Proof;
3702
- publicSignals: string[];
3703
- proofBytes: Uint8Array;
3704
- publicInputsBytes: Uint8Array;
3705
- }
3706
- /**
3707
- * Generate Groth16 proof for regular withdrawal using Circom WASM
3708
- *
3709
- * This matches the approach in services-new/tests/src/proof.ts
3443
+ * The bytes are canonical HERE and copied out: every hand-off mints a fresh buffer from an
3444
+ * intrinsic captured at module load, and hashes a twin of that buffer, so the digest covers what is
3445
+ * used and not merely what was once loaded, and the buffer that is used was allocated by something
3446
+ * a consumer cannot redefine. See the note on `_verifiedArtifacts` for the break that made the copy
3447
+ * necessary (F7), and THE PRIMORDIALS for the one that made the copy's PROVENANCE necessary (F9).
3710
3448
  *
3711
- * @param inputs - Circuit inputs
3712
- * @param circuitsPath - Ignored. Proof generation always uses pinned S3 circuits.
3449
+ * Only the ceremony-frozen `transaction` circuit exists here. The deployed
3450
+ * program verifies proofs against that circuit's verifying key and nothing
3451
+ * else, so the pre-ceremony `withdraw_regular` / `withdraw_swap` circuits —
3452
+ * and every code path that loaded them — were removed rather than kept as
3453
+ * compatibility the program would reject anyway.
3713
3454
  */
3714
- declare function generateWithdrawRegularProof(inputs: WithdrawRegularInputs, circuitsPath: string): Promise<ProofResult>;
3455
+
3715
3456
  /**
3716
- * Generate Groth16 proof for swap withdrawal using Circom WASM
3457
+ * Base URL of the only bundle this SDK pins: the ceremony `transaction` bundle.
3717
3458
  *
3718
- * This matches the approach in services-new/tests/src/proof.ts
3459
+ * Identical to `DEFAULT_TRANSACTION_CIRCUITS_URL` in `flows/transact`; kept
3460
+ * under this name so existing imports keep resolving. Derived from
3461
+ * {@link TRANSACTION_CIRCUITS_BASE_URL}, so the version segment is the same one
3462
+ * the pinned digests were declared under — do not write this URL out by hand
3463
+ * anywhere; change the bundle instead.
3719
3464
  *
3720
- * @param inputs - Circuit inputs
3721
- * @param circuitsPath - Ignored. Proof generation always uses pinned S3 circuits.
3722
- */
3723
- declare function generateWithdrawSwapProof(inputs: WithdrawSwapInputs, circuitsPath: string): Promise<ProofResult>;
3724
- /**
3725
- * Check if circuits are available from the pinned S3 source.
3465
+ * `string | null` `null` when this build pins no location whose bytes were
3466
+ * verified against the bundle's digests.
3726
3467
  */
3727
- declare function areCircuitsAvailable(circuitsPath: string): Promise<boolean>;
3728
- /**
3729
- * Get default circuits URL.
3730
- */
3731
- declare function getDefaultCircuitsPath(): Promise<string>;
3468
+ declare const DEFAULT_CIRCUITS_URL: string;
3732
3469
  /**
3733
3470
  * Pinned circuit artifact hashes (SHA-256), flattened from the release table in
3734
- * `config/circuit-release.ts`.
3471
+ * `proving/circuits.ts`.
3735
3472
  *
3736
- * This is a *view*, not the source of truth: edit the bundle, not this object.
3737
- * It stays writable because the artifact TOCTOU tests re-pin it to synthetic
3738
- * fixtures; production code must not mutate it.
3473
+ * A read-only VIEW of {@link PINNED_TRANSACTION_WASM_DIGEST} / {@link PINNED_TRANSACTION_ZKEY_DIGEST},
3474
+ * kept because it is part of the published surface and integrators print it in start-up
3475
+ * diagnostics. FROZEN: it is not the source of truth and must not be able to pretend it is. Writing
3476
+ * to it throws in strict mode (every ES module is strict) and is a silent no-op in sloppy CJS
3477
+ * scope — either way the digests the check uses are unchanged.
3739
3478
  */
3740
- declare const EXPECTED_CIRCUIT_HASHES: {
3741
- withdraw_regular_wasm: string;
3742
- withdraw_regular_zkey: string;
3743
- withdraw_swap_wasm: string;
3744
- withdraw_swap_zkey: string;
3479
+ declare const EXPECTED_CIRCUIT_HASHES: Readonly<{
3745
3480
  transaction_wasm: string;
3746
3481
  transaction_zkey: string;
3747
- };
3482
+ }>;
3748
3483
  /**
3749
3484
  * Circuit verification result
3750
3485
  */
3751
3486
  interface CircuitVerificationResult {
3752
3487
  /** Whether verification passed */
3753
3488
  valid: boolean;
3754
- /** Which circuit was checked */
3755
- circuit: CircuitName;
3756
3489
  /** Error message if verification failed */
3757
3490
  error?: string;
3758
3491
  computed?: {
@@ -3764,13 +3497,25 @@ interface CircuitVerificationResult {
3764
3497
  zkey: string;
3765
3498
  };
3766
3499
  }
3767
- /** Circuit artifact bytes together with the digests computed over those bytes. */
3500
+ /**
3501
+ * Circuit artifact bytes together with the digests computed over those bytes.
3502
+ *
3503
+ * The buffers are a PRIVATE COPY, minted for this call from an intrinsic captured at module load
3504
+ * and hashed via a throwaway twin after they were copied. Nothing outside this module was handed
3505
+ * the object or a view onto it, so `digests` describes `wasm`/`zkey` as of the moment they were
3506
+ * handed over rather than as of some earlier load. Mutate them if you like; the SDK's canonical
3507
+ * bytes are elsewhere and the next call re-copies and re-hashes.
3508
+ *
3509
+ * The guarantee stops at the hand-off, and stops honestly. Once these buffers are inside
3510
+ * `snarkjs.groth16.fullProve` what snarkjs does with them is snarkjs's business; what this module
3511
+ * promises is that the bytes it handed over are the bytes whose SHA-256 it reported.
3512
+ */
3768
3513
  interface VerifiedCircuitArtifacts {
3769
- /** `<circuit>_js/<circuit>.wasm` bytes. */
3514
+ /** `<circuit>_js/<circuit>.wasm` bytes. A fresh copy, not shared with any other caller. */
3770
3515
  wasm: Uint8Array;
3771
- /** `<circuit>_final.zkey` bytes. */
3516
+ /** `<circuit>_final.zkey` bytes. A fresh copy, not shared with any other caller. */
3772
3517
  zkey: Uint8Array;
3773
- /** SHA-256 (lowercase hex) of the buffers in this object. */
3518
+ /** SHA-256 (lowercase hex) of the buffers in this object, computed over these very buffers. */
3774
3519
  digests: {
3775
3520
  wasm: string;
3776
3521
  zkey: string;
@@ -3789,8 +3534,23 @@ interface VerifiedCircuitArtifacts {
3789
3534
  * Fails closed: any digest mismatch, unreachable artifact, or environment that
3790
3535
  * cannot produce bytes (a browser pointed at a local directory) throws rather
3791
3536
  * than falling back to an unverified source.
3537
+ *
3538
+ * Returns a FRESH COPY on every call, hashed after it was copied — see
3539
+ * {@link copyAndVerify} and the note on {@link _verifiedArtifacts}. Two calls never share a buffer,
3540
+ * and the digests in the returned object are the digests of the buffers in that same object, taken
3541
+ * at that call. Mutating what you are given affects nothing but your own copy.
3542
+ *
3543
+ * The environment cannot switch any of this off. It used to be skippable with
3544
+ * `CLOAK_SKIP_CIRCUIT_INTEGRITY_CHECK=1`, and that escape hatch was the worst hole in the package:
3545
+ * the variable resolves in the CONSUMER's process, so one deploy variable — or one
3546
+ * `--define:process.env.CLOAK_SKIP_CIRCUIT_INTEGRITY_CHECK='"1"'` in a consumer's bundler, which
3547
+ * compiles the guard down to a constant `true` — made this function accept whatever bytes the base
3548
+ * served. Paired with a repointable base that meant attacker wasm, and attacker wasm sees the spend
3549
+ * key. A check an environment variable disables is not a check. If a local build genuinely needs
3550
+ * different artifacts it needs different DIGESTS, which is a source edit and a rebuild, exactly
3551
+ * like the endpoint pin.
3792
3552
  */
3793
- declare function loadVerifiedCircuitArtifacts(circuitsPath: string | null, circuit: CircuitName): Promise<VerifiedCircuitArtifacts>;
3553
+ declare function loadVerifiedCircuitArtifacts(circuitsPath: string | null): Promise<VerifiedCircuitArtifacts>;
3794
3554
  /**
3795
3555
  * Report whether a circuit's artifacts match the digests pinned in this SDK.
3796
3556
  *
@@ -3800,35 +3560,38 @@ declare function loadVerifiedCircuitArtifacts(circuitsPath: string | null, circu
3800
3560
  * Proof paths must call {@link loadVerifiedCircuitArtifacts} and hand the bytes
3801
3561
  * it returns to snarkjs.
3802
3562
  *
3563
+ * Reports digests, never bytes. It can read the canonical memo to avoid a second download, but the
3564
+ * result object carries only hex strings, so calling this cannot obtain a handle on the bytes a
3565
+ * later proof will run over — which is the other half of the F7 fix, and the reason this function
3566
+ * and `loadVerifiedCircuitArtifacts` can no longer disagree about the same cache entry.
3567
+ *
3803
3568
  * IMPORTANT: If the hashes don't match, the circuit may produce proofs
3804
3569
  * that will be rejected by the on-chain verifier!
3805
3570
  *
3806
- * @param circuitsPath - Ignored for the legacy withdraw circuits (they always use
3807
- * their own pinned bundle); honoured for `transaction`.
3571
+ * @param circuitsPath - Base directory or URL holding the circuit's artifacts;
3572
+ * honoured verbatim.
3808
3573
  * @param circuit - Which circuit to verify
3809
3574
  * @returns Verification result
3810
3575
  *
3811
3576
  * @example
3812
3577
  * ```typescript
3813
- * const result = await verifyCircuitIntegrity(DEFAULT_CIRCUITS_URL, 'withdraw_regular');
3578
+ * const result = await verifyCircuitIntegrity(getCircuitsPath(), 'transaction');
3814
3579
  * if (!result.valid) {
3815
3580
  * console.error('Circuit verification failed:', result.error);
3816
3581
  * // Don't proceed with proof generation!
3817
3582
  * }
3818
3583
  * ```
3819
3584
  */
3820
- declare function verifyCircuitIntegrity(circuitsPath: string | null, circuit: CircuitName, prefetched?: {
3585
+ declare function verifyCircuitIntegrity(circuitsPath: string | null, prefetched?: {
3821
3586
  wasm: Uint8Array;
3822
3587
  zkey: Uint8Array;
3823
3588
  }): Promise<CircuitVerificationResult>;
3824
3589
  /**
3825
3590
  * Assert the ceremony-frozen `transaction` circuit artifacts are the pinned ones.
3826
3591
  *
3827
- * Throws (fail-closed) when the digests do not match, mirroring how
3828
- * `generateWithdrawRegularProof` / `generateWithdrawSwapProof` gate the legacy
3829
- * circuits. Proving against an unpinned zkey silently produces proofs the
3830
- * on-chain verifying key rejects, so failing here is strictly better than
3831
- * failing on-chain.
3592
+ * Throws (fail-closed) when the digests do not match. Proving against an
3593
+ * unpinned zkey silently produces proofs the on-chain verifying key rejects,
3594
+ * so failing here is strictly better than failing on-chain.
3832
3595
  *
3833
3596
  * @param circuitsPath - Base directory or URL holding `transaction_js/transaction.wasm`
3834
3597
  * and `transaction_final.zkey`.
@@ -3839,18 +3602,21 @@ declare function assertTransactionCircuitIntegrity(circuitsPath: string | null,
3839
3602
  zkey: Uint8Array;
3840
3603
  }): Promise<void>;
3841
3604
  /**
3842
- * Verify all circuits before use
3605
+ * Verify every circuit this SDK pins — which is exactly one: the ceremony
3606
+ * `transaction` circuit.
3843
3607
  *
3844
3608
  * Call this at SDK initialization to ensure circuits are valid.
3845
3609
  *
3846
- * @param circuitsPath - For the legacy withdraw circuits this is ignored; verification
3847
- * always uses their own pinned bundle.
3848
- * @param transactionCircuitsPath - Base for the ceremony-frozen `transaction` circuit.
3610
+ * @param circuitsPath - Base for the ceremony-frozen `transaction` circuit.
3849
3611
  * Pass `getCircuitsPath()` when the caller has reconfigured it;
3850
3612
  * `null` reports the "no base configured" state rather than throwing.
3613
+ * @param transactionCircuitsPath - Same base; takes precedence when given. Kept so
3614
+ * two-argument callers from before the legacy withdraw
3615
+ * circuits were removed keep compiling, with unchanged
3616
+ * behaviour for the `transaction` entry.
3851
3617
  * @returns Array of verification results (one per circuit)
3852
3618
  */
3853
- declare function verifyAllCircuits(circuitsPath: string, transactionCircuitsPath?: string | null): Promise<CircuitVerificationResult[]>;
3619
+ declare function verifyAllCircuits(circuitsPath: string | null, transactionCircuitsPath?: string | null): Promise<CircuitVerificationResult[]>;
3854
3620
 
3855
3621
  /**
3856
3622
  * Pending Operations Manager
@@ -4000,7 +3766,7 @@ declare function cleanupStalePendingOperations(maxAgeMs?: number): {
4000
3766
  *
4001
3767
  * ── Crypto ────────────────────────────────────────────────────────────────────────────────────
4002
3768
  * X25519 ECDH + XSalsa20-Poly1305, i.e. `nacl.box`, reusing the exact construction already in
4003
- * `core/keys.ts` (`nacl.box.before` + `nacl.secretbox`). No new primitive is introduced here.
3769
+ * `notes/keypair.ts` (`nacl.box.before` + `nacl.secretbox`). No new primitive is introduced here.
4004
3770
  */
4005
3771
 
4006
3772
  /** Ephemeral X25519 public key, at offset 0. */
@@ -4126,7 +3892,7 @@ declare function parseDeliveryCarrierMemo(data: Uint8Array): ParsedDeliveryCarri
4126
3892
  * transaction actually published. That equality is the authentication: it is not a heuristic, and a
4127
3893
  * wrong `nk` cannot produce it. Zero extra bytes on chain, no new envelope, no relay change.
4128
3894
  *
4129
- * This is the same shape already blessed for swap timeout refunds in `core/swap-refund.ts`
3895
+ * This is the same shape already blessed for swap timeout refunds in `notes/swap-refund.ts`
4130
3896
  * (PRF(nk, nullifier0)), for the same reason: unrecoverable randomness becomes recoverable
4131
3897
  * randomness without changing anything an observer can see.
4132
3898
  *
@@ -4749,8 +4515,8 @@ declare class SimpleWallet {
4749
4515
  * @packageDocumentation
4750
4516
  */
4751
4517
 
4752
- declare const VERSION = "0.2.0";
4518
+ declare const VERSION = "0.2.1";
4753
4519
  /** True when scanner supports TransactSwap (tag 1). Check this to verify the correct SDK bundle is loaded. */
4754
4520
  declare const SCANNER_SUPPORTS_TRANSACT_SWAP = true;
4755
4521
 
4756
- export { type BuildRecipientDeliveryNotesParams, CHAIN_NOTE_SALT_BITS, CLOAK_PROGRAM_ID, type ChainNoteTxType, type CircuitName, type CircuitVerificationResult, type ClaimTimeoutRefundOptions, type ClaimTimeoutRefundParams, type ClaimTimeoutRefundResult, type CloakConfig, CloakError, type CloakKeyPair, type CloakNote, CloakSDK, 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, FIXED_FEE_LAMPORTS, type Groth16Proof, InsecureRandomnessError, LAMPORTS_PER_SOL, LocalStorageAdapter, type LogLevel, type Logger, MERKLE_TREE_HEIGHT, MIN_DEPOSIT_LAMPORTS, type MasterKey, 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, type ProofResult, 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, type RecipientDeliveryNote, type RecoveredDepositNote, type RecoveredDepositNoteRecord, type RecoveredSwapRefund, type RefundVoucher, 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, 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 WithdrawRegularInputs, type WithdrawSubmissionResult, type WithdrawSwapInputs, areCircuitsAvailable, assertDirectSubmissionLanded, assertTransactionCircuitIntegrity, bigintToBytes32$1 as bigintToBytes32, bigintToHex, buildMerkleTree, buildMerkleTreeFromChain, buildMerkleTreeFromRelay, buildPublicInputsBytes, buildRecipientDeliveryNotes, buildTransactRequestBody, bytesToHex, calculateFee, calculateFeeBigint, calculateRelayFee, canRebuildMerkleTreeFromChain, chainNoteFromBase64, chainNoteToBase64, claimTimeoutRefund, classifyRelayError, cleanupStalePendingOperations, clearPendingDeposits, clearPendingWithdrawals, computeChainNoteHash, computeCommitment$1 as computeCommitment, computeExtDataHash, computeMerkleRoot, computeNullifier$1 as computeNullifier, computeNullifierAsync, computeNullifierSync, computeOutputsHash, computeOutputsHashAsync, computeOutputsHashSync, computeProofForLatestDeposit, computeProofFromChain, computeSignature, computeSwapOutputsHash, computeSwapOutputsHashAsync, computeSwapOutputsHashSync, computeSwapRefundCommitment, computeCommitment as computeUtxoCommitment, computeNullifier as computeUtxoNullifier, confirmTransactSettlement, copyNoteToClipboard, createCloakError, createDepositInstruction, createLogger, createRecoverableDepositUtxo, createUtxo, createZeroUtxo, decryptCompactChainNote, decryptComplianceMetadataWithMasterKey, decryptTransactionMetadata, 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, exportKeys, exportNote, exportWalletKeys, fetchCommitments, fetchRiskQuoteInstruction, fetchRiskQuoteIx, filterNotesByNetwork, filterWithdrawableNotes, findNoteByCommitment, formatAmount, formatComplianceCsv, formatErrorForLogging, formatSol, fullWithdraw, generateCloakKeys, generateCommitment, generateCommitmentAsync, generateMasterSeed, generateNote, generateNoteFromWallet, generateUtxoKeypair, generateViewingKeyPair, generateWithdrawRegularProof, generateWithdrawSwapProof, getAddressExplorerUrl, getChainNoteRegistryPDA, getCircuitsPath, getDefaultCircuitsPath, getDeliveryRegistryPDA, getDistributableAmount, getExplorerUrl, getNkFromUtxoPrivateKey, getNullifierPDA, getPendingOperationsSummary, getPoolAuthorityConfigPDA, getPublicKey, getPublicViewKey, getRecipientAmount, getRefundClaimPDA, getRefundLedgerPDA, 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, matchDepositNote, matchSwapRefundLeaf, openRecipientDeliveryNote, parseAmount, parseDeliveryCarrierMemo, parseError, parseNote, parseRelayErrorResponse, parseRelayErrorSignature, parseTransactionError, partialWithdraw, poseidonHash, preflightCheck, preflightNullifiers, prepareEncryptedOutput, prepareEncryptedOutputForRecipient, proofToBytes, pubkeyToFieldElement, pubkeyToLimbs, randomBytes, 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 };
4522
+ 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 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 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, createRecoverableDepositUtxo, createUtxo, createZeroUtxo, decryptCompactChainNote, decryptComplianceMetadataWithMasterKey, decryptTransactionMetadata, 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, matchDepositNote, matchSwapRefundLeaf, openRecipientDeliveryNote, parseAmount, parseDeliveryCarrierMemo, parseError, parseNote, parseRelayErrorResponse, parseRelayErrorSignature, parseTransactionError, partialWithdraw, poseidonHash, preflightCheck, preflightNullifiers, prepareEncryptedOutput, prepareEncryptedOutputForRecipient, proofToBytes, pubkeyToFieldElement, pubkeyToLimbs, randomBytes, 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 };