@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/LICENSE +202 -0
- package/README.md +189 -51
- package/dist/{chunk-YX5SCAMR.js → chunk-KNM6K5NG.js} +8 -95
- package/dist/index.cjs +3143 -4276
- package/dist/index.d.cts +571 -805
- package/dist/index.d.ts +571 -805
- package/dist/index.js +3065 -4136
- package/dist/{utxo-PFJT3ETR.js → utxo-XPEGGWZ6.js} +3 -3
- package/package.json +50 -20
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
import { PublicKey, Transaction,
|
|
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
|
|
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
|
-
*
|
|
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 `
|
|
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
|
|
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
|
-
* -
|
|
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
|
-
*
|
|
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 `
|
|
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 — `
|
|
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
|
-
* `
|
|
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
|
-
*
|
|
3072
|
-
*
|
|
3073
|
-
*
|
|
3074
|
-
*
|
|
3075
|
-
*
|
|
3076
|
-
*
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
*
|
|
3081
|
-
*
|
|
3082
|
-
*
|
|
3083
|
-
*
|
|
3084
|
-
*
|
|
3085
|
-
*
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
*
|
|
3090
|
-
*
|
|
3091
|
-
*
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
*
|
|
3097
|
-
*
|
|
3098
|
-
*
|
|
3099
|
-
*
|
|
3100
|
-
*
|
|
3101
|
-
*
|
|
3102
|
-
*
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
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
|
-
* `
|
|
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
|
|
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 `
|
|
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
|
|
3166
|
-
*
|
|
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
|
-
*
|
|
3203
|
-
*
|
|
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: ["
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
3610
|
-
* 1. PrepareSwapSol - Wrap SOL
|
|
3611
|
-
* 2.
|
|
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
|
-
*
|
|
3436
|
+
* Circuit artifact loading and integrity verification.
|
|
3634
3437
|
*
|
|
3635
|
-
*
|
|
3636
|
-
*
|
|
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
|
-
*
|
|
3639
|
-
*
|
|
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
|
-
*
|
|
3712
|
-
*
|
|
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
|
-
|
|
3455
|
+
|
|
3715
3456
|
/**
|
|
3716
|
-
*
|
|
3457
|
+
* Base URL of the only bundle this SDK pins: the ceremony `transaction` bundle.
|
|
3717
3458
|
*
|
|
3718
|
-
*
|
|
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
|
-
*
|
|
3721
|
-
*
|
|
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
|
|
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
|
-
* `
|
|
3471
|
+
* `proving/circuits.ts`.
|
|
3735
3472
|
*
|
|
3736
|
-
*
|
|
3737
|
-
*
|
|
3738
|
-
*
|
|
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
|
-
/**
|
|
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
|
|
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 -
|
|
3807
|
-
*
|
|
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(
|
|
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,
|
|
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
|
|
3828
|
-
*
|
|
3829
|
-
*
|
|
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
|
|
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 -
|
|
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
|
-
* `
|
|
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 `
|
|
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.
|
|
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
|
|
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 };
|