@hula-privacy/mixer 0.1.0 → 0.3.0

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.
@@ -0,0 +1,933 @@
1
+ import { PublicKey, TransactionInstruction, Keypair, Connection } from '@solana/web3.js';
2
+ import { BN, Program } from '@coral-xyz/anchor';
3
+ import { Poseidon } from 'circomlibjs';
4
+
5
+ /**
6
+ * Type definitions for Hula Privacy SDK
7
+ */
8
+
9
+ /**
10
+ * UTXO (Unspent Transaction Output) in the privacy pool
11
+ */
12
+ interface UTXO {
13
+ /** Amount in raw token units */
14
+ value: bigint;
15
+ /** Token mint address as bigint */
16
+ mintTokenAddress: bigint;
17
+ /** Owner hash (derived from spending key) */
18
+ owner: bigint;
19
+ /** Random blinding factor */
20
+ secret: bigint;
21
+ /** Poseidon hash commitment */
22
+ commitment: bigint;
23
+ /** Index in the merkle tree */
24
+ leafIndex: number;
25
+ /** Which tree this UTXO is in */
26
+ treeIndex: number;
27
+ }
28
+ /**
29
+ * Serializable UTXO for storage/transmission
30
+ */
31
+ interface SerializableUTXO {
32
+ value: string;
33
+ mintTokenAddress: string;
34
+ owner: string;
35
+ secret: string;
36
+ commitment: string;
37
+ leafIndex: number;
38
+ treeIndex: number;
39
+ /** Token mint public key */
40
+ mint: string;
41
+ /** Whether this UTXO has been spent */
42
+ spent: boolean;
43
+ /** Transaction that spent this UTXO */
44
+ spentTx?: string;
45
+ /** Transaction that created this UTXO */
46
+ createdTx: string;
47
+ /** Timestamp when created */
48
+ createdAt: string;
49
+ }
50
+ /**
51
+ * Wallet keys derived from spending key
52
+ */
53
+ interface WalletKeys {
54
+ /** Master spending key - KEEP SECRET */
55
+ spendingKey: bigint;
56
+ /** Owner hash - public identifier for receiving funds */
57
+ owner: bigint;
58
+ /** Viewing key - for decrypting notes */
59
+ viewingKey: bigint;
60
+ /** Nullifier key - for computing nullifiers */
61
+ nullifierKey: bigint;
62
+ /** X25519 keypair for note encryption */
63
+ encryptionKeyPair: {
64
+ publicKey: Uint8Array;
65
+ secretKey: Uint8Array;
66
+ };
67
+ }
68
+ /**
69
+ * Encrypted note attached to transactions
70
+ */
71
+ interface EncryptedNote {
72
+ /** Ephemeral public key for ECDH */
73
+ ephemeralPubKey: Uint8Array;
74
+ /** Encrypted ciphertext */
75
+ ciphertext: Uint8Array;
76
+ /** Nonce for decryption */
77
+ nonce: Uint8Array;
78
+ }
79
+ /**
80
+ * Merkle path for proving inclusion
81
+ */
82
+ interface MerklePath {
83
+ /** Sibling hashes at each level */
84
+ pathElements: bigint[];
85
+ /** Direction at each level (0 = left, 1 = right) */
86
+ pathIndices: number[];
87
+ /** Root of the tree */
88
+ root: bigint;
89
+ }
90
+ /**
91
+ * Leaf data from the relayer
92
+ */
93
+ interface LeafData {
94
+ id: string;
95
+ treeIndex: number;
96
+ leafIndex: number;
97
+ commitment: string;
98
+ slot: string;
99
+ createdAt: string;
100
+ }
101
+ /**
102
+ * Circuit inputs for ZK proof generation
103
+ */
104
+ interface CircuitInputs {
105
+ merkleRoot: string;
106
+ nullifiers: string[];
107
+ outputCommitments: string[];
108
+ publicDeposit: string;
109
+ publicWithdraw: string;
110
+ recipient: string;
111
+ mintTokenAddress: string;
112
+ fee: string;
113
+ inputSpendingKeys: string[];
114
+ inputValues: string[];
115
+ inputSecrets: string[];
116
+ inputLeafIndices: string[];
117
+ inputPathElements: string[][];
118
+ inputPathIndices: number[][];
119
+ outputValues: string[];
120
+ outputOwners: string[];
121
+ outputSecrets: string[];
122
+ }
123
+ /**
124
+ * Public inputs for the on-chain verifier
125
+ */
126
+ interface PublicInputs {
127
+ merkleRoot: number[];
128
+ nullifiers: number[][];
129
+ outputCommitments: number[][];
130
+ publicDeposit: bigint;
131
+ publicWithdraw: bigint;
132
+ recipient: PublicKey;
133
+ mintTokenAddress: PublicKey;
134
+ fee: bigint;
135
+ }
136
+ /**
137
+ * Output UTXO specification
138
+ */
139
+ interface OutputSpec {
140
+ /** Owner hash (bigint) or "self" for own wallet */
141
+ owner: bigint | "self";
142
+ /** Amount in raw token units */
143
+ amount: bigint;
144
+ /** Encryption public key for encrypted note (optional) */
145
+ encryptionPubKey?: Uint8Array;
146
+ }
147
+ /**
148
+ * Transaction request for building a privacy transaction
149
+ */
150
+ interface TransactionRequest {
151
+ /** Amount to deposit from public wallet */
152
+ depositAmount?: bigint;
153
+ /** Input UTXOs to spend */
154
+ inputUtxos?: UTXO[];
155
+ /** Output UTXOs to create */
156
+ outputs?: OutputSpec[];
157
+ /** Amount to withdraw to public wallet */
158
+ withdrawAmount?: bigint;
159
+ /** Recipient public key for withdrawal */
160
+ recipient?: PublicKey;
161
+ /** Relayer fee */
162
+ fee?: bigint;
163
+ /** Token mint address */
164
+ mint: PublicKey;
165
+ }
166
+ /**
167
+ * Built transaction ready for submission
168
+ */
169
+ interface BuiltTransaction {
170
+ /** Proof bytes (256 bytes) */
171
+ proof: Uint8Array;
172
+ /** Public inputs for the circuit */
173
+ publicInputs: PublicInputs;
174
+ /** Encrypted notes for outputs */
175
+ encryptedNotes: Buffer[];
176
+ /** Created output UTXOs (for tracking) */
177
+ outputUtxos: UTXO[];
178
+ /** Nullifiers being spent */
179
+ nullifiers: bigint[];
180
+ /** Input tree index */
181
+ inputTreeIndex: number;
182
+ /** Output tree index (current tree) */
183
+ outputTreeIndex: number;
184
+ }
185
+ /**
186
+ * Paginated response from relayer
187
+ */
188
+ interface PaginatedResponse<T> {
189
+ items: T[];
190
+ nextCursor: string | null;
191
+ hasMore: boolean;
192
+ }
193
+ /**
194
+ * Pool data from relayer
195
+ */
196
+ interface PoolData {
197
+ authority: string;
198
+ commitmentCount: string;
199
+ merkleRoot: string;
200
+ paused: boolean;
201
+ currentTreeIndex: number;
202
+ lastSlot: string;
203
+ }
204
+ /**
205
+ * Tree data from relayer
206
+ */
207
+ interface TreeData {
208
+ id: string;
209
+ treeIndex: number;
210
+ nextIndex: number;
211
+ root: string;
212
+ }
213
+ /**
214
+ * Transaction data from relayer
215
+ */
216
+ interface TransactionData {
217
+ id: string;
218
+ signature: string;
219
+ slot: string;
220
+ blockTime?: string;
221
+ payer: string;
222
+ mint: string;
223
+ outputTreeIndex: number;
224
+ publicDeposit: string;
225
+ publicWithdraw: string;
226
+ fee: string;
227
+ success: boolean;
228
+ nullifiers: string[];
229
+ encryptedNotes: {
230
+ noteIndex: number;
231
+ data: string;
232
+ }[];
233
+ }
234
+ /**
235
+ * Encrypted note data from relayer
236
+ */
237
+ interface NoteData {
238
+ id: string;
239
+ noteIndex: number;
240
+ encryptedData: string;
241
+ txSignature: string;
242
+ slot: string;
243
+ mint: string;
244
+ treeIndex: number;
245
+ }
246
+ /**
247
+ * Stats from relayer
248
+ */
249
+ interface StatsData {
250
+ pool: {
251
+ commitmentCount: string;
252
+ currentTreeIndex: number;
253
+ paused: boolean;
254
+ } | null;
255
+ treeCount: number;
256
+ leafCount: number;
257
+ transactionCount: number;
258
+ nullifierCount: number;
259
+ }
260
+ /**
261
+ * SDK configuration
262
+ */
263
+ interface HulaSDKConfig {
264
+ /** Solana RPC endpoint */
265
+ rpcUrl: string;
266
+ /** Relayer API endpoint */
267
+ relayerUrl: string;
268
+ /** Program ID for the Hula Privacy program */
269
+ programId?: PublicKey;
270
+ /** Path to circuit WASM file */
271
+ circuitWasmPath?: string;
272
+ /** Path to circuit zkey file */
273
+ circuitZkeyPath?: string;
274
+ /** Network: localnet | devnet | mainnet */
275
+ network?: "localnet" | "devnet" | "mainnet";
276
+ }
277
+ /**
278
+ * Wallet sync progress
279
+ */
280
+ interface SyncProgress {
281
+ stage: "notes" | "nullifiers" | "complete";
282
+ current: number;
283
+ total: number;
284
+ }
285
+ /**
286
+ * Wallet sync result
287
+ */
288
+ interface SyncResult {
289
+ newUtxos: number;
290
+ spentUtxos: number;
291
+ errors: string[];
292
+ }
293
+
294
+ /**
295
+ * Transaction building for Hula Privacy Protocol
296
+ *
297
+ * Builds privacy transactions with ZK proofs
298
+ */
299
+
300
+ /**
301
+ * Build a privacy transaction
302
+ *
303
+ * This handles all transaction types: deposits, transfers, and withdrawals.
304
+ */
305
+ declare function buildTransaction(request: TransactionRequest, walletKeys: WalletKeys, relayerUrl?: string): Promise<BuiltTransaction>;
306
+ /**
307
+ * Build Solana transaction accounts and instructions
308
+ *
309
+ * This creates the account list and any pre-instructions needed for the transaction.
310
+ */
311
+ declare function buildTransactionAccounts(builtTx: BuiltTransaction, payer: PublicKey, mint: PublicKey, depositAmount: bigint, withdrawAmount: bigint, recipient?: PublicKey): {
312
+ accounts: {
313
+ payer: PublicKey;
314
+ mint: PublicKey;
315
+ pool: PublicKey;
316
+ inputTree: PublicKey;
317
+ merkleTree: PublicKey;
318
+ vault: PublicKey;
319
+ depositorTokenAccount: PublicKey | null;
320
+ depositor: PublicKey | null;
321
+ recipientTokenAccount: PublicKey | null;
322
+ feeRecipientTokenAccount: PublicKey | null;
323
+ nullifierAccount0: PublicKey | null;
324
+ nullifierAccount1: PublicKey | null;
325
+ tokenProgram: PublicKey;
326
+ systemProgram: PublicKey;
327
+ };
328
+ preInstructions: TransactionInstruction[];
329
+ inputTreeIndex: number | null;
330
+ };
331
+ /**
332
+ * Convert built transaction to Anchor-compatible format
333
+ */
334
+ declare function toAnchorPublicInputs(builtTx: BuiltTransaction): {
335
+ merkleRoot: number[];
336
+ nullifiers: number[][];
337
+ outputCommitments: number[][];
338
+ publicDeposit: BN;
339
+ publicWithdraw: BN;
340
+ recipient: PublicKey;
341
+ mintTokenAddress: PublicKey;
342
+ fee: BN;
343
+ };
344
+
345
+ /**
346
+ * Wallet management for Hula Privacy Protocol
347
+ *
348
+ * High-level wallet abstraction that manages keys, UTXOs, and syncing
349
+ */
350
+
351
+ /**
352
+ * Hula Privacy Wallet
353
+ *
354
+ * High-level abstraction for managing privacy transactions
355
+ */
356
+ declare class HulaWallet {
357
+ private connection;
358
+ private relayerUrl;
359
+ private programId;
360
+ private keys;
361
+ private signer?;
362
+ private utxos;
363
+ private lastSyncedSlot;
364
+ private initialized;
365
+ private constructor();
366
+ /**
367
+ * Create a new wallet with a random spending key
368
+ */
369
+ static create(config: HulaSDKConfig): Promise<HulaWallet>;
370
+ /**
371
+ * Create a wallet from a Solana keypair
372
+ *
373
+ * Derives the spending key deterministically from the keypair's secret key.
374
+ */
375
+ static fromKeypair(keypair: Keypair, config: HulaSDKConfig): Promise<HulaWallet>;
376
+ /**
377
+ * Create a wallet from an existing spending key
378
+ */
379
+ static fromSpendingKey(spendingKey: bigint, config: HulaSDKConfig): Promise<HulaWallet>;
380
+ /**
381
+ * Create a wallet from a Solana signature (deterministic derivation)
382
+ *
383
+ * This allows recovery as long as the user can sign with their Solana wallet.
384
+ */
385
+ static fromSignature(signature: Uint8Array, config: HulaSDKConfig): Promise<HulaWallet>;
386
+ /**
387
+ * Get wallet's owner hash (public identifier)
388
+ */
389
+ get owner(): bigint;
390
+ /**
391
+ * Get wallet's owner hash as hex string
392
+ */
393
+ getOwnerHash(): string;
394
+ /**
395
+ * Get wallet's encryption public key as hex string
396
+ */
397
+ getEncryptionPublicKey(): string;
398
+ /**
399
+ * Get wallet's encryption public key as bytes
400
+ */
401
+ get encryptionPublicKey(): Uint8Array;
402
+ /**
403
+ * Get spending key (CAREFUL - this is sensitive!)
404
+ */
405
+ get spendingKey(): bigint;
406
+ /**
407
+ * Get all wallet keys
408
+ */
409
+ get walletKeys(): WalletKeys;
410
+ /**
411
+ * Get the connection
412
+ */
413
+ getConnection(): Connection;
414
+ /**
415
+ * Get the signer keypair (if available)
416
+ */
417
+ getSigner(): Keypair | undefined;
418
+ /**
419
+ * Set the signer keypair
420
+ */
421
+ setSigner(signer: Keypair): void;
422
+ /**
423
+ * Sync wallet with relayer
424
+ *
425
+ * Fetches new encrypted notes and checks for spent UTXOs.
426
+ */
427
+ sync(onProgress?: (progress: SyncProgress) => void): Promise<SyncResult>;
428
+ /**
429
+ * Get all unspent UTXOs
430
+ */
431
+ getUnspentUTXOs(): UTXO[];
432
+ /**
433
+ * Get all UTXOs (including spent)
434
+ */
435
+ getAllUTXOs(): SerializableUTXO[];
436
+ /**
437
+ * Get balance for a specific mint
438
+ */
439
+ getBalance(mint: PublicKey): bigint;
440
+ /**
441
+ * Import UTXOs (for wallet recovery or manual import)
442
+ */
443
+ importUTXOs(utxos: SerializableUTXO[]): void;
444
+ /**
445
+ * Export UTXOs for backup
446
+ */
447
+ exportUTXOs(): SerializableUTXO[];
448
+ /**
449
+ * Deposit tokens into the privacy pool
450
+ *
451
+ * @param mint - Token mint address
452
+ * @param amount - Amount in raw token units
453
+ * @returns Transaction signature
454
+ */
455
+ deposit(mint: PublicKey, amount: bigint): Promise<string>;
456
+ /**
457
+ * Transfer tokens privately to another user
458
+ *
459
+ * @param mint - Token mint address
460
+ * @param amount - Amount in raw token units
461
+ * @param recipientOwner - Recipient's owner hash (bigint)
462
+ * @param recipientEncryptionPubKey - Recipient's encryption public key
463
+ * @returns Transaction signature
464
+ */
465
+ transfer(mint: PublicKey, amount: bigint, recipientOwner: bigint, recipientEncryptionPubKey: Uint8Array): Promise<string>;
466
+ /**
467
+ * Withdraw tokens from the privacy pool to a public address
468
+ *
469
+ * @param mint - Token mint address
470
+ * @param amount - Amount in raw token units
471
+ * @param recipient - Public key to receive the tokens
472
+ * @returns Transaction signature
473
+ */
474
+ withdraw(mint: PublicKey, amount: bigint, recipient: PublicKey): Promise<string>;
475
+ /**
476
+ * Build a custom transaction
477
+ */
478
+ buildTransaction(request: Omit<TransactionRequest, "mint"> & {
479
+ mint: PublicKey;
480
+ }): Promise<{
481
+ transaction: ReturnType<typeof buildTransaction> extends Promise<infer T> ? T : never;
482
+ instructions: TransactionInstruction[];
483
+ }>;
484
+ /**
485
+ * Submit a transaction using an Anchor program
486
+ *
487
+ * @param program - Anchor program instance (any type to avoid IDL complexity)
488
+ * @param payer - Keypair for signing
489
+ * @param builtTx - Built transaction from buildTransaction()
490
+ * @param mint - Token mint
491
+ * @param depositAmount - Amount being deposited (if any)
492
+ * @param withdrawAmount - Amount being withdrawn (if any)
493
+ * @param recipient - Recipient for withdrawal (if any)
494
+ */
495
+ submitTransaction(program: Program<any>, payer: Keypair, builtTx: Awaited<ReturnType<typeof buildTransaction>>, mint: PublicKey, depositAmount?: bigint, withdrawAmount?: bigint, recipient?: PublicKey): Promise<string>;
496
+ }
497
+ /**
498
+ * Create a deterministic message for wallet key derivation
499
+ */
500
+ declare function getKeyDerivationMessage(): Uint8Array;
501
+ /**
502
+ * Quick initialization for SDK usage
503
+ */
504
+ declare function initHulaSDK(): Promise<void>;
505
+
506
+ /**
507
+ * Relayer API Client
508
+ *
509
+ * Fetches data from the relayer with cursor-based pagination
510
+ */
511
+
512
+ /**
513
+ * API client for the Hula Privacy relayer
514
+ */
515
+ declare class RelayerClient {
516
+ private baseUrl;
517
+ constructor(baseUrl?: string);
518
+ private fetch;
519
+ /**
520
+ * Health check
521
+ */
522
+ health(): Promise<{
523
+ status: string;
524
+ timestamp: string;
525
+ }>;
526
+ /**
527
+ * Get protocol stats
528
+ */
529
+ getStats(): Promise<StatsData>;
530
+ /**
531
+ * Get pool data
532
+ */
533
+ getPool(): Promise<PoolData>;
534
+ /**
535
+ * Get all merkle trees
536
+ */
537
+ getTrees(): Promise<{
538
+ trees: TreeData[];
539
+ }>;
540
+ /**
541
+ * Get tree by index
542
+ */
543
+ getTree(treeIndex: number): Promise<TreeData>;
544
+ /**
545
+ * Get leaves with cursor pagination
546
+ */
547
+ getLeaves(cursor?: string, limit?: number, treeIndex?: number): Promise<PaginatedResponse<LeafData>>;
548
+ /**
549
+ * Get leaves after a specific index (for syncing)
550
+ */
551
+ getLeavesAfter(treeIndex: number, afterLeafIndex: number, limit?: number): Promise<{
552
+ items: {
553
+ treeIndex: number;
554
+ leafIndex: number;
555
+ commitment: string;
556
+ slot: string;
557
+ }[];
558
+ hasMore: boolean;
559
+ lastLeafIndex: number;
560
+ }>;
561
+ /**
562
+ * Get all leaves for a tree (auto-paginated)
563
+ */
564
+ getAllLeavesForTree(treeIndex: number): Promise<LeafData[]>;
565
+ /**
566
+ * Get all commitment values for a tree as bigints
567
+ */
568
+ getCommitmentsForTree(treeIndex: number): Promise<bigint[]>;
569
+ /**
570
+ * Get transactions with cursor pagination
571
+ */
572
+ getTransactions(cursor?: string, limit?: number, mint?: string): Promise<PaginatedResponse<TransactionData>>;
573
+ /**
574
+ * Get transaction by signature
575
+ */
576
+ getTransaction(signature: string): Promise<TransactionData>;
577
+ /**
578
+ * Check if nullifier is spent
579
+ */
580
+ checkNullifier(nullifier: string): Promise<{
581
+ nullifier: string;
582
+ spent: boolean;
583
+ spentAt?: string;
584
+ }>;
585
+ /**
586
+ * Check multiple nullifiers at once
587
+ */
588
+ checkNullifiersBatch(nullifiers: string[]): Promise<{
589
+ results: {
590
+ nullifier: string;
591
+ spent: boolean;
592
+ }[];
593
+ }>;
594
+ /**
595
+ * Get encrypted notes with cursor pagination
596
+ */
597
+ getNotes(cursor?: string, limit?: number, afterSlot?: string): Promise<PaginatedResponse<NoteData>>;
598
+ /**
599
+ * Get all notes (auto-paginated)
600
+ */
601
+ getAllNotes(afterSlot?: string): Promise<NoteData[]>;
602
+ }
603
+ /**
604
+ * Get or create the default relayer client
605
+ */
606
+ declare function getRelayerClient(url?: string): RelayerClient;
607
+ /**
608
+ * Set the default relayer URL
609
+ */
610
+ declare function setDefaultRelayerUrl(url: string): void;
611
+
612
+ /**
613
+ * Cryptographic utilities for Hula Privacy Protocol
614
+ *
615
+ * Includes Poseidon hashing, key derivation, and encryption
616
+ */
617
+
618
+ /**
619
+ * Initialize Poseidon hasher (must be called once before using hash functions)
620
+ */
621
+ declare function initPoseidon(): Promise<void>;
622
+ /**
623
+ * Check if Poseidon is initialized
624
+ */
625
+ declare function isPoseidonInitialized(): boolean;
626
+ /**
627
+ * Get Poseidon instance (throws if not initialized)
628
+ */
629
+ declare function getPoseidon(): Poseidon;
630
+ /**
631
+ * Poseidon hash of inputs
632
+ */
633
+ declare function poseidonHash(inputs: bigint[]): bigint;
634
+ /**
635
+ * Convert bytes to bigint (big-endian)
636
+ */
637
+ declare function bytesToBigInt(bytes: Uint8Array): bigint;
638
+ /**
639
+ * Convert bigint to bytes (big-endian)
640
+ */
641
+ declare function bigIntToBytes(value: bigint, length: number): Uint8Array;
642
+ /**
643
+ * Convert bigint to 32-byte array (big-endian)
644
+ */
645
+ declare function bigIntToBytes32(value: bigint): Uint8Array;
646
+ /**
647
+ * Convert hex string to bytes
648
+ */
649
+ declare function hexToBytes(hex: string): Uint8Array;
650
+ /**
651
+ * Convert bytes to hex string
652
+ */
653
+ declare function bytesToHex(bytes: Uint8Array): string;
654
+ /**
655
+ * Convert PublicKey to bigint
656
+ */
657
+ declare function pubkeyToBigInt(pubkey: {
658
+ toBytes(): Uint8Array;
659
+ }): bigint;
660
+ /**
661
+ * Generate a new random spending key
662
+ */
663
+ declare function generateSpendingKey(): bigint;
664
+ /**
665
+ * Derive all wallet keys from spending key
666
+ */
667
+ declare function deriveKeys(spendingKey: bigint): WalletKeys;
668
+ /**
669
+ * Derive spending key from wallet signature
670
+ *
671
+ * This allows deterministic key derivation from a Solana wallet signature,
672
+ * enabling wallet recovery as long as the user has access to their wallet.
673
+ */
674
+ declare function deriveSpendingKeyFromSignature(signature: Uint8Array): bigint;
675
+ /**
676
+ * Encrypt a note for a recipient
677
+ *
678
+ * The note contains the UTXO data needed for the recipient to claim it.
679
+ * Optimized for size:
680
+ * - mintTokenAddress: only first 8 bytes (can match on-chain by prefix)
681
+ * - leafIndex: omitted (recipient can query relayer with commitment)
682
+ */
683
+ declare function encryptNote(noteData: {
684
+ value: bigint;
685
+ mintTokenAddress: bigint;
686
+ secret: bigint;
687
+ leafIndex?: number;
688
+ }, recipientEncryptionPubKey: Uint8Array): EncryptedNote;
689
+ /**
690
+ * Decrypt an encrypted note
691
+ *
692
+ * Returns null if decryption fails (not intended for this recipient)
693
+ * Note: leafIndex is not included in encrypted notes to save space.
694
+ * The recipient should query the relayer with the computed commitment.
695
+ */
696
+ declare function decryptNote(encryptedNote: EncryptedNote, encryptionSecretKey: Uint8Array): {
697
+ value: bigint;
698
+ mintPrefix: string;
699
+ secret: bigint;
700
+ } | null;
701
+ /**
702
+ * Serialize encrypted note for on-chain storage
703
+ */
704
+ declare function serializeEncryptedNote(note: EncryptedNote): Uint8Array;
705
+ /**
706
+ * Deserialize encrypted note from on-chain data
707
+ */
708
+ declare function deserializeEncryptedNote(data: Uint8Array): EncryptedNote;
709
+ /**
710
+ * Format a commitment/nullifier for display (truncated hex)
711
+ */
712
+ declare function formatCommitment(value: bigint | Uint8Array, length?: number): string;
713
+
714
+ /**
715
+ * UTXO (Unspent Transaction Output) management
716
+ *
717
+ * Provides functions for creating, scanning, and managing UTXOs
718
+ */
719
+
720
+ /**
721
+ * Compute UTXO commitment
722
+ * commitment = Poseidon(value, mintTokenAddress, owner, secret)
723
+ */
724
+ declare function computeCommitment(value: bigint, mintTokenAddress: bigint, owner: bigint, secret: bigint): bigint;
725
+ /**
726
+ * Compute nullifier for spending a UTXO
727
+ * nullifier = Poseidon(nullifierKey, commitment, leafIndex)
728
+ */
729
+ declare function computeNullifier(spendingKey: bigint, commitment: bigint, leafIndex: number): bigint;
730
+ /**
731
+ * Compute nullifier from wallet keys
732
+ */
733
+ declare function computeNullifierFromKeys(keys: WalletKeys, commitment: bigint, leafIndex: number): bigint;
734
+ /**
735
+ * Create a new UTXO with random secret
736
+ */
737
+ declare function createUTXO(value: bigint, mintTokenAddress: bigint, owner: bigint, leafIndex: number, treeIndex?: number): UTXO;
738
+ /**
739
+ * Create a dummy (zero) UTXO for padding
740
+ */
741
+ declare function createDummyUTXO(): UTXO;
742
+ /**
743
+ * Serialize UTXO for storage
744
+ */
745
+ declare function serializeUTXO(utxo: UTXO, mint: string, createdTx: string, spent?: boolean, spentTx?: string): SerializableUTXO;
746
+ /**
747
+ * Deserialize UTXO from storage
748
+ */
749
+ declare function deserializeUTXO(data: SerializableUTXO): UTXO;
750
+ /**
751
+ * Scan encrypted notes for UTXOs belonging to this wallet
752
+ *
753
+ * This attempts to decrypt each note with the wallet's encryption key.
754
+ * If successful, the note belongs to this wallet.
755
+ */
756
+ declare function scanNotesForUTXOs(notes: Array<{
757
+ encryptedData: string;
758
+ treeIndex: number;
759
+ mint: string;
760
+ txSignature: string;
761
+ }>, walletKeys: WalletKeys, commitments: Map<number, Map<number, bigint>>): SerializableUTXO[];
762
+ /**
763
+ * Sync wallet UTXOs from relayer
764
+ *
765
+ * This fetches all encrypted notes and attempts to decrypt them.
766
+ * Also checks which UTXOs have been spent.
767
+ */
768
+ declare function syncUTXOs(walletKeys: WalletKeys, existingUTXOs: SerializableUTXO[], relayerUrl?: string, afterSlot?: string): Promise<{
769
+ newUTXOs: SerializableUTXO[];
770
+ spentUTXOs: string[];
771
+ }>;
772
+ /**
773
+ * Select UTXOs for spending (greedy algorithm)
774
+ *
775
+ * Selects the largest UTXOs first until the target amount is reached.
776
+ */
777
+ declare function selectUTXOs(utxos: UTXO[], targetAmount: bigint, mint?: bigint): UTXO[];
778
+ /**
779
+ * Calculate total balance of UTXOs
780
+ */
781
+ declare function calculateBalance(utxos: UTXO[], mint?: bigint): bigint;
782
+
783
+ /**
784
+ * Merkle Tree utilities for Hula Privacy Protocol
785
+ *
786
+ * Provides functions for building merkle paths from relayer data
787
+ */
788
+
789
+ /**
790
+ * Compute zero hashes for the merkle tree using Poseidon
791
+ * ZEROS[0] = 0 (empty leaf)
792
+ * ZEROS[i+1] = Poseidon(ZEROS[i], ZEROS[i])
793
+ */
794
+ declare function computeZeros(): bigint[];
795
+ /**
796
+ * Get zero value at a specific level
797
+ */
798
+ declare function getZeroAtLevel(level: number): bigint;
799
+ /**
800
+ * Get the root of an empty merkle tree
801
+ */
802
+ declare function getEmptyTreeRoot(): bigint;
803
+ /**
804
+ * Compute merkle path from a list of leaves
805
+ *
806
+ * This builds the full tree locally and extracts the path for the given leaf.
807
+ * Use this when you have fetched all leaves from the relayer.
808
+ */
809
+ declare function computeMerklePathFromLeaves(leafIndex: number, leaves: bigint[]): MerklePath;
810
+ /**
811
+ * Compute merkle root from leaves
812
+ */
813
+ declare function computeMerkleRoot(leaves: bigint[]): bigint;
814
+ /**
815
+ * Verify a merkle path is valid
816
+ */
817
+ declare function verifyMerklePath(leafValue: bigint, path: MerklePath): boolean;
818
+ /**
819
+ * Fetch merkle path for a UTXO from the relayer
820
+ *
821
+ * This fetches all leaves for the tree and computes the path locally.
822
+ */
823
+ declare function fetchMerklePath(treeIndex: number, leafIndex: number, relayerUrl?: string): Promise<MerklePath>;
824
+ /**
825
+ * Fetch current merkle root for a tree from the relayer
826
+ */
827
+ declare function fetchMerkleRoot(treeIndex: number, relayerUrl?: string): Promise<bigint>;
828
+ /**
829
+ * Get next leaf index for a tree
830
+ */
831
+ declare function getNextLeafIndex(treeIndex: number, relayerUrl?: string): Promise<number>;
832
+ /**
833
+ * Get current active tree index
834
+ */
835
+ declare function getCurrentTreeIndex(relayerUrl?: string): Promise<number>;
836
+
837
+ /**
838
+ * ZK Proof generation utilities
839
+ *
840
+ * Uses snarkjs to generate Groth16 proofs for the transaction circuit
841
+ */
842
+
843
+ /**
844
+ * Set circuit file paths
845
+ */
846
+ declare function setCircuitPaths(wasmPath: string, zkeyPath: string): void;
847
+ /**
848
+ * Get circuit file paths (with fallback to default locations)
849
+ */
850
+ declare function getCircuitPaths(): {
851
+ wasmPath: string;
852
+ zkeyPath: string;
853
+ };
854
+ /**
855
+ * Verify circuit files exist
856
+ */
857
+ declare function verifyCircuitFiles(): void;
858
+ /**
859
+ * Parse snarkjs proof JSON into 256-byte proof array
860
+ *
861
+ * Format: proof_a (64 bytes) + proof_b (128 bytes) + proof_c (64 bytes)
862
+ */
863
+ declare function parseProof(proofJson: {
864
+ pi_a: string[];
865
+ pi_b: string[][];
866
+ pi_c: string[];
867
+ }): Uint8Array;
868
+ /**
869
+ * Generate ZK proof using snarkjs CLI (subprocess for Bun compatibility)
870
+ *
871
+ * This spawns snarkjs as a subprocess to avoid web-worker issues with Bun.
872
+ * Works in both Node.js and Bun environments.
873
+ */
874
+ declare function generateProof(circuitInputs: CircuitInputs): Promise<{
875
+ proof: Uint8Array;
876
+ publicSignals: string[];
877
+ }>;
878
+ /**
879
+ * Generate proof using snarkjs in-memory (for Node.js environments)
880
+ *
881
+ * This is more efficient but may not work in all environments.
882
+ */
883
+ declare function generateProofInMemory(circuitInputs: CircuitInputs): Promise<{
884
+ proof: Uint8Array;
885
+ publicSignals: string[];
886
+ }>;
887
+
888
+ /**
889
+ * Constants for Hula Privacy Protocol
890
+ */
891
+
892
+ /** Hula Privacy Program ID */
893
+ declare const PROGRAM_ID: PublicKey;
894
+ /** Token 2022 Program ID */
895
+ declare const TOKEN_2022_PROGRAM_ID: PublicKey;
896
+ declare const POOL_SEED: Buffer<ArrayBuffer>;
897
+ declare const VAULT_SEED: Buffer<ArrayBuffer>;
898
+ declare const MERKLE_TREE_SEED: Buffer<ArrayBuffer>;
899
+ declare const NULLIFIER_SEED: Buffer<ArrayBuffer>;
900
+ /** Number of input UTXOs in circuit */
901
+ declare const NUM_INPUT_UTXOS = 2;
902
+ /** Number of output UTXOs in circuit */
903
+ declare const NUM_OUTPUT_UTXOS = 2;
904
+ /** Depth of merkle tree */
905
+ declare const MERKLE_TREE_DEPTH = 10;
906
+ /** Maximum leaves per tree (2^DEPTH) */
907
+ declare const MAX_LEAVES: number;
908
+ /** Size of proof in bytes */
909
+ declare const PROOF_SIZE = 256;
910
+ declare const DOMAIN_OWNER = 0n;
911
+ declare const DOMAIN_VIEWING = 1n;
912
+ declare const DOMAIN_NULLIFIER = 2n;
913
+ declare const DOMAIN_ENCRYPTION = 3n;
914
+ /** BN254 field prime */
915
+ declare const FIELD_PRIME: bigint;
916
+ /**
917
+ * Derive Pool PDA
918
+ */
919
+ declare function getPoolPDA(): [PublicKey, number];
920
+ /**
921
+ * Derive Merkle Tree PDA for a specific tree index
922
+ */
923
+ declare function getMerkleTreePDA(treeIndex?: number): [PublicKey, number];
924
+ /**
925
+ * Derive Vault PDA for a specific mint
926
+ */
927
+ declare function getVaultPDA(mint: PublicKey): [PublicKey, number];
928
+ /**
929
+ * Derive Nullifier PDA for a nullifier hash
930
+ */
931
+ declare function getNullifierPDA(nullifier: Uint8Array): [PublicKey, number];
932
+
933
+ export { type BuiltTransaction, type CircuitInputs, DOMAIN_ENCRYPTION, DOMAIN_NULLIFIER, DOMAIN_OWNER, DOMAIN_VIEWING, type EncryptedNote, FIELD_PRIME, type HulaSDKConfig, HulaWallet, type LeafData, MAX_LEAVES, MERKLE_TREE_DEPTH, MERKLE_TREE_SEED, type MerklePath, NULLIFIER_SEED, NUM_INPUT_UTXOS, NUM_OUTPUT_UTXOS, type NoteData, type OutputSpec, POOL_SEED, PROGRAM_ID, PROOF_SIZE, type PaginatedResponse, type PoolData, type PublicInputs, RelayerClient, type SerializableUTXO, type StatsData, type SyncProgress, type SyncResult, TOKEN_2022_PROGRAM_ID, type TransactionData, type TransactionRequest, type TreeData, type UTXO, VAULT_SEED, type WalletKeys, bigIntToBytes, bigIntToBytes32, buildTransaction, buildTransactionAccounts, bytesToBigInt, bytesToHex, calculateBalance, computeCommitment, computeMerklePathFromLeaves, computeMerkleRoot, computeNullifier, computeNullifierFromKeys, computeZeros, createDummyUTXO, createUTXO, decryptNote, deriveKeys, deriveSpendingKeyFromSignature, deserializeEncryptedNote, deserializeUTXO, encryptNote, fetchMerklePath, fetchMerkleRoot, formatCommitment, generateProof, generateProofInMemory, generateSpendingKey, getCircuitPaths, getCurrentTreeIndex, getEmptyTreeRoot, getKeyDerivationMessage, getMerkleTreePDA, getNextLeafIndex, getNullifierPDA, getPoolPDA, getPoseidon, getRelayerClient, getVaultPDA, getZeroAtLevel, hexToBytes, initHulaSDK, initPoseidon, isPoseidonInitialized, parseProof, poseidonHash, pubkeyToBigInt, scanNotesForUTXOs, selectUTXOs, serializeEncryptedNote, serializeUTXO, setCircuitPaths, setDefaultRelayerUrl, syncUTXOs, toAnchorPublicInputs, verifyCircuitFiles, verifyMerklePath };