@permissionless-technologies/upp-sdk 0.1.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.
Files changed (140) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +194 -0
  3. package/dist/asp-TXSAFFD3.cjs +53 -0
  4. package/dist/asp-TXSAFFD3.cjs.map +1 -0
  5. package/dist/asp-ZA3RGN7G.js +4 -0
  6. package/dist/asp-ZA3RGN7G.js.map +1 -0
  7. package/dist/babyjubjub-2MGQVCKB.js +5 -0
  8. package/dist/babyjubjub-2MGQVCKB.js.map +1 -0
  9. package/dist/babyjubjub-MWZLJOVZ.cjs +66 -0
  10. package/dist/babyjubjub-MWZLJOVZ.cjs.map +1 -0
  11. package/dist/chunk-2JQISXBD.js +150 -0
  12. package/dist/chunk-2JQISXBD.js.map +1 -0
  13. package/dist/chunk-3HQ7A6ZM.cjs +61 -0
  14. package/dist/chunk-3HQ7A6ZM.cjs.map +1 -0
  15. package/dist/chunk-5AKBSMEQ.cjs +1008 -0
  16. package/dist/chunk-5AKBSMEQ.cjs.map +1 -0
  17. package/dist/chunk-5V5HSN6Y.js +81 -0
  18. package/dist/chunk-5V5HSN6Y.js.map +1 -0
  19. package/dist/chunk-BH24DZ5S.cjs +91 -0
  20. package/dist/chunk-BH24DZ5S.cjs.map +1 -0
  21. package/dist/chunk-C7QQOJ7T.cjs +67 -0
  22. package/dist/chunk-C7QQOJ7T.cjs.map +1 -0
  23. package/dist/chunk-ERQE57IA.cjs +404 -0
  24. package/dist/chunk-ERQE57IA.cjs.map +1 -0
  25. package/dist/chunk-EUP7MBAH.cjs +165 -0
  26. package/dist/chunk-EUP7MBAH.cjs.map +1 -0
  27. package/dist/chunk-G7VZBCD6.cjs +35 -0
  28. package/dist/chunk-G7VZBCD6.cjs.map +1 -0
  29. package/dist/chunk-GQV47S3N.cjs +10 -0
  30. package/dist/chunk-GQV47S3N.cjs.map +1 -0
  31. package/dist/chunk-GXZ3MTCQ.cjs +527 -0
  32. package/dist/chunk-GXZ3MTCQ.cjs.map +1 -0
  33. package/dist/chunk-JWNXBALH.cjs +57 -0
  34. package/dist/chunk-JWNXBALH.cjs.map +1 -0
  35. package/dist/chunk-KIKBPJXJ.cjs +348 -0
  36. package/dist/chunk-KIKBPJXJ.cjs.map +1 -0
  37. package/dist/chunk-NCW4AE7L.js +8 -0
  38. package/dist/chunk-NCW4AE7L.js.map +1 -0
  39. package/dist/chunk-NDM5EJEV.cjs +70 -0
  40. package/dist/chunk-NDM5EJEV.cjs.map +1 -0
  41. package/dist/chunk-NUIQHTSA.js +489 -0
  42. package/dist/chunk-NUIQHTSA.js.map +1 -0
  43. package/dist/chunk-OQDSHMXU.js +1002 -0
  44. package/dist/chunk-OQDSHMXU.js.map +1 -0
  45. package/dist/chunk-P37MRZ73.js +58 -0
  46. package/dist/chunk-P37MRZ73.js.map +1 -0
  47. package/dist/chunk-PWHOUQOZ.js +335 -0
  48. package/dist/chunk-PWHOUQOZ.js.map +1 -0
  49. package/dist/chunk-S4B7GYLN.js +112 -0
  50. package/dist/chunk-S4B7GYLN.js.map +1 -0
  51. package/dist/chunk-SGZZL5AC.js +59 -0
  52. package/dist/chunk-SGZZL5AC.js.map +1 -0
  53. package/dist/chunk-SQKBT2SH.cjs +122 -0
  54. package/dist/chunk-SQKBT2SH.cjs.map +1 -0
  55. package/dist/chunk-TSF6HEVS.cjs +201 -0
  56. package/dist/chunk-TSF6HEVS.cjs.map +1 -0
  57. package/dist/chunk-V23OSL25.js +48 -0
  58. package/dist/chunk-V23OSL25.js.map +1 -0
  59. package/dist/chunk-W77GRBO4.js +53 -0
  60. package/dist/chunk-W77GRBO4.js.map +1 -0
  61. package/dist/chunk-XV72HNHN.js +399 -0
  62. package/dist/chunk-XV72HNHN.js.map +1 -0
  63. package/dist/chunk-YOWDERVC.js +186 -0
  64. package/dist/chunk-YOWDERVC.js.map +1 -0
  65. package/dist/chunk-Z6ZWNWWR.js +30 -0
  66. package/dist/chunk-Z6ZWNWWR.js.map +1 -0
  67. package/dist/chunk-ZKZV6OI3.cjs +165 -0
  68. package/dist/chunk-ZKZV6OI3.cjs.map +1 -0
  69. package/dist/chunk-ZU6J7KMY.js +159 -0
  70. package/dist/chunk-ZU6J7KMY.js.map +1 -0
  71. package/dist/core/index.cjs +300 -0
  72. package/dist/core/index.cjs.map +1 -0
  73. package/dist/core/index.d.cts +9 -0
  74. package/dist/core/index.d.ts +9 -0
  75. package/dist/core/index.js +11 -0
  76. package/dist/core/index.js.map +1 -0
  77. package/dist/index-BBzvvrhG.d.ts +757 -0
  78. package/dist/index-BGvapsJy.d.cts +2811 -0
  79. package/dist/index-C-jSNw6j.d.cts +757 -0
  80. package/dist/index-ChGaGPzP.d.ts +2811 -0
  81. package/dist/index.cjs +3652 -0
  82. package/dist/index.cjs.map +1 -0
  83. package/dist/index.d.cts +12 -0
  84. package/dist/index.d.ts +12 -0
  85. package/dist/index.js +3112 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/indexer/index.cjs +58 -0
  88. package/dist/indexer/index.cjs.map +1 -0
  89. package/dist/indexer/index.d.cts +206 -0
  90. package/dist/indexer/index.d.ts +206 -0
  91. package/dist/indexer/index.js +5 -0
  92. package/dist/indexer/index.js.map +1 -0
  93. package/dist/keccak-m31-B_AqBbRF.d.cts +70 -0
  94. package/dist/keccak-m31-B_AqBbRF.d.ts +70 -0
  95. package/dist/keys/index.cjs +68 -0
  96. package/dist/keys/index.cjs.map +1 -0
  97. package/dist/keys/index.d.cts +158 -0
  98. package/dist/keys/index.d.ts +158 -0
  99. package/dist/keys/index.js +7 -0
  100. package/dist/keys/index.js.map +1 -0
  101. package/dist/merkle-7KS2EHRF.js +5 -0
  102. package/dist/merkle-7KS2EHRF.js.map +1 -0
  103. package/dist/merkle-HGDC6OB4.cjs +30 -0
  104. package/dist/merkle-HGDC6OB4.cjs.map +1 -0
  105. package/dist/merkle-mteVOlDf.d.cts +188 -0
  106. package/dist/merkle-mteVOlDf.d.ts +188 -0
  107. package/dist/poseidon-UHTJLWQM.js +7 -0
  108. package/dist/poseidon-UHTJLWQM.js.map +1 -0
  109. package/dist/poseidon-WHJSZSNP.cjs +45 -0
  110. package/dist/poseidon-WHJSZSNP.cjs.map +1 -0
  111. package/dist/proof-5OECB3RQ.cjs +45 -0
  112. package/dist/proof-5OECB3RQ.cjs.map +1 -0
  113. package/dist/proof-C4YBP6RY.js +4 -0
  114. package/dist/proof-C4YBP6RY.js.map +1 -0
  115. package/dist/react/index.cjs +2641 -0
  116. package/dist/react/index.cjs.map +1 -0
  117. package/dist/react/index.d.cts +757 -0
  118. package/dist/react/index.d.ts +757 -0
  119. package/dist/react/index.js +2598 -0
  120. package/dist/react/index.js.map +1 -0
  121. package/dist/transfer-2UDHDS7Q.cjs +37 -0
  122. package/dist/transfer-2UDHDS7Q.cjs.map +1 -0
  123. package/dist/transfer-BlmbO-Rd.d.ts +1270 -0
  124. package/dist/transfer-DKZuJnRM.d.cts +1270 -0
  125. package/dist/transfer-KTCXKHS4.js +8 -0
  126. package/dist/transfer-KTCXKHS4.js.map +1 -0
  127. package/dist/types-CJSbxv4q.d.cts +143 -0
  128. package/dist/types-mLybMxNR.d.ts +143 -0
  129. package/dist/utils/index.cjs +178 -0
  130. package/dist/utils/index.cjs.map +1 -0
  131. package/dist/utils/index.d.cts +88 -0
  132. package/dist/utils/index.d.ts +88 -0
  133. package/dist/utils/index.js +9 -0
  134. package/dist/utils/index.js.map +1 -0
  135. package/package.json +119 -0
  136. package/src/contracts/interfaces/IASPRegistry.sol +36 -0
  137. package/src/contracts/interfaces/IUniversalPrivatePool.sol +260 -0
  138. package/src/contracts/interfaces/IVerifiers.sol +68 -0
  139. package/src/deployments/11155111.json +19 -0
  140. package/src/deployments/31337.json +19 -0
@@ -0,0 +1,757 @@
1
+ import { PublicClient, WalletClient, Address, Hex } from 'viem';
2
+ import { r as ShieldParams, h as Note, O as TransferParams, M as MergeParams, Y as WithdrawParams, E as EncryptedNote } from './transfer-DKZuJnRM.cjs';
3
+ import { M as MasterKeys, O as OneTimeKeys, b as StarkMasterKeys } from './types-CJSbxv4q.cjs';
4
+ import { a as M31Digest } from './keccak-m31-B_AqBbRF.cjs';
5
+ import { P as Point } from './merkle-mteVOlDf.cjs';
6
+
7
+ /**
8
+ * Main UPP Client
9
+ *
10
+ * Provides high-level API for interacting with the Universal Private Pool.
11
+ */
12
+
13
+ /**
14
+ * UPP Client configuration
15
+ */
16
+ interface UPPClientConfig {
17
+ /** Viem public client for reading chain state */
18
+ publicClient: PublicClient;
19
+ /** Viem wallet client for sending transactions */
20
+ walletClient: WalletClient;
21
+ /** Universal Private Pool contract address */
22
+ poolAddress: Address;
23
+ /** ASP Registry Hub contract address */
24
+ aspHubAddress: Address;
25
+ /** Chain ID (optional, derived from clients if not provided) */
26
+ chainId?: number;
27
+ }
28
+ /**
29
+ * UPP Client interface
30
+ */
31
+ interface UPPClient {
32
+ /** Shield tokens into the private pool */
33
+ shield(params: ShieldParams): Promise<{
34
+ commitment: `0x${string}`;
35
+ note: Note;
36
+ }>;
37
+ /** Transfer tokens privately */
38
+ transfer(params: TransferParams): Promise<{
39
+ nullifier: `0x${string}`;
40
+ changeNote?: Note;
41
+ }>;
42
+ /** Merge multiple notes into one */
43
+ merge(params: MergeParams): Promise<{
44
+ commitment: `0x${string}`;
45
+ note: Note;
46
+ }>;
47
+ /** Withdraw tokens from the private pool */
48
+ withdraw(params: WithdrawParams): Promise<{
49
+ txHash: `0x${string}`;
50
+ }>;
51
+ /** Scan for notes belonging to a viewing key */
52
+ scanNotes(viewingKey: `0x${string}`): Promise<Note[]>;
53
+ /** Get the current state root */
54
+ getStateRoot(): Promise<bigint>;
55
+ /** Check if a nullifier has been spent */
56
+ isNullifierSpent(nullifier: `0x${string}`): Promise<boolean>;
57
+ }
58
+ /**
59
+ * Create a UPP client instance
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * import { createUPPClient } from '@upp/sdk'
64
+ * import { createPublicClient, createWalletClient, http } from 'viem'
65
+ * import { sepolia } from 'viem/chains'
66
+ *
67
+ * const publicClient = createPublicClient({
68
+ * chain: sepolia,
69
+ * transport: http(),
70
+ * })
71
+ *
72
+ * const walletClient = createWalletClient({
73
+ * chain: sepolia,
74
+ * transport: http(),
75
+ * })
76
+ *
77
+ * const client = createUPPClient({
78
+ * publicClient,
79
+ * walletClient,
80
+ * poolAddress: '0x...',
81
+ * aspHubAddress: '0x...',
82
+ * })
83
+ * ```
84
+ */
85
+ declare function createUPPClient(_config: UPPClientConfig): UPPClient;
86
+
87
+ /**
88
+ * Note management utilities
89
+ *
90
+ * Create, encrypt, and decrypt private notes.
91
+ */
92
+
93
+ /**
94
+ * Parameters for creating a new note
95
+ */
96
+ interface CreateNoteParams {
97
+ /** Token amount */
98
+ amount: bigint;
99
+ /** ERC20 token address */
100
+ token: Address;
101
+ /** Origin address (who is responsible) */
102
+ origin: Address;
103
+ /** Sender address */
104
+ sender: Address;
105
+ /** Optional memo */
106
+ memo?: string;
107
+ /** Optional blinding factor (generated if not provided) */
108
+ blinding?: bigint;
109
+ }
110
+ /**
111
+ * Create a new private note
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * const note = createNote({
116
+ * amount: 1000n * 10n ** 18n,
117
+ * token: '0x...',
118
+ * origin: '0xMyAddress...',
119
+ * sender: '0xMyAddress...',
120
+ * memo: 'Payment for services',
121
+ * })
122
+ * ```
123
+ */
124
+ declare function createNote(params: CreateNoteParams): Note;
125
+ /**
126
+ * Encrypt a note for a recipient
127
+ *
128
+ * @param note - The note to encrypt
129
+ * @param sharedSecret - ECDH shared secret with recipient
130
+ * @returns Encrypted note data
131
+ */
132
+ declare function encryptNote(_note: Note, _sharedSecret: Uint8Array): EncryptedNote;
133
+ /**
134
+ * Decrypt a received note
135
+ *
136
+ * @param encrypted - The encrypted note data
137
+ * @param sharedSecret - ECDH shared secret
138
+ * @returns Decrypted note or null if decryption fails
139
+ */
140
+ declare function decryptNote(_encrypted: EncryptedNote, _sharedSecret: Uint8Array): Note | null;
141
+
142
+ /**
143
+ * Stealth Address Utilities (Post-Quantum, Hash-Based)
144
+ *
145
+ * Implements stealth addresses using Poseidon hashes with bech32m encoding.
146
+ * No BabyJubJub curve operations — ownership is proven via hash preimage.
147
+ *
148
+ * Address Format (bech32m):
149
+ * 0zk1<version><chainId><ownerHash><viewingHash>
150
+ *
151
+ * Key Flow (self-shield):
152
+ * 1. User derives ownerHash = Poseidon(spendingSecret)
153
+ * 2. Commitment = Poseidon(amount, ownerHash, blinding, origin, token)
154
+ * 3. Encrypt note with key derived from viewingSecret
155
+ *
156
+ * Key Flow (send to others, future):
157
+ * 1. Decode recipient's stealth address (ownerHash, viewingHash)
158
+ * 2. Generate per-note secret and derive ownerHash for the note
159
+ * 3. Encrypt note so recipient's viewingSecret can decrypt
160
+ */
161
+
162
+ /**
163
+ * Stealth address prefix
164
+ */
165
+ declare const STEALTH_ADDRESS_PREFIX = "0zk";
166
+ /**
167
+ * Address version (v2 = hash-based, post-quantum)
168
+ */
169
+ declare const ADDRESS_VERSION = 2;
170
+ /**
171
+ * Encode a stealth address in bech32m format
172
+ *
173
+ * Format: 0zk1<version><chainId><ownerHash><viewingHash>
174
+ *
175
+ * @param ownerHash - Owner hash = Poseidon(spendingSecret)
176
+ * @param viewingHash - Viewing hash = Poseidon(viewingSecret)
177
+ * @param chainId - Optional chain ID (0 = any chain)
178
+ * @returns bech32m encoded stealth address
179
+ */
180
+ declare function encodeStealthAddress(ownerHash: bigint, viewingHash: bigint, chainId?: number): string;
181
+ /**
182
+ * Decode a bech32m stealth address
183
+ *
184
+ * @param address - bech32m encoded stealth address
185
+ * @returns Decoded hash values
186
+ */
187
+ declare function decodeStealthAddress(address: string): {
188
+ version: number;
189
+ chainId: number;
190
+ ownerHash: bigint;
191
+ viewingHash: bigint;
192
+ };
193
+ /**
194
+ * Validate a stealth address format
195
+ */
196
+ declare function isValidStealthAddress(address: string): boolean;
197
+ /**
198
+ * Generate stealth address from master keys
199
+ */
200
+ declare function generateStealthAddress(keys: MasterKeys, chainId?: number): string;
201
+ /**
202
+ * Create one-time keys for a transaction (hash-based)
203
+ *
204
+ * For self-shield: the user uses their own spendingSecret directly
205
+ * as the ownerSecret, producing ownerHash = Poseidon(spendingSecret).
206
+ *
207
+ * For sending to others (future): generate a random oneTimeSecret
208
+ * and derive ownerHash = Poseidon(oneTimeSecret).
209
+ *
210
+ * @param recipientOwnerHash - Recipient's owner hash (for verification)
211
+ * @param selfSecret - If self-shield, the user's spending secret
212
+ * @returns One-time keys for the note
213
+ */
214
+ declare function createOneTimeKeys(_recipientOwnerHash?: bigint, selfSecret?: bigint): Promise<OneTimeKeys>;
215
+ /**
216
+ * Verify ownership of a note by checking hash preimage
217
+ *
218
+ * @param secret - Claimed spending secret
219
+ * @param expectedOwnerHash - Owner hash from the note commitment
220
+ * @returns True if the secret hashes to the expected owner hash
221
+ */
222
+ declare function verifyOwnership(secret: bigint, expectedOwnerHash: bigint): Promise<boolean>;
223
+ /**
224
+ * Compute shared secret for note encryption/decryption (hash-based)
225
+ *
226
+ * For self-shield: just uses the viewing secret directly.
227
+ * For sending to others (future): use Poseidon(viewingSecret, recipientViewingHash)
228
+ *
229
+ * @param viewingSecret - Sender's or recipient's viewing secret
230
+ * @param nonce - Optional nonce for key derivation
231
+ * @returns Encryption key as bigint
232
+ */
233
+ declare function computeNoteEncryptionKey(viewingSecret: bigint, nonce?: bigint): Promise<bigint>;
234
+ /**
235
+ * STARK stealth address prefix
236
+ */
237
+ declare const STARK_STEALTH_ADDRESS_PREFIX = "0zs";
238
+ /**
239
+ * STARK address version (v1 = M31/Keccak)
240
+ */
241
+ declare const STARK_ADDRESS_VERSION = 1;
242
+ /**
243
+ * Encode a STARK stealth address in bech32m format
244
+ *
245
+ * Format: 0zs1<version><chainId><ownerHash[0..3]><viewingHash[0..3]>
246
+ *
247
+ * Each M31 element is encoded as 4 bytes (little-endian).
248
+ * Total data: 1 (version) + 4 (chainId) + 16 (ownerHash) + 16 (viewingHash) = 37 bytes.
249
+ *
250
+ * @param ownerHash - 4 M31 elements: keccak_m31(starkSecret)
251
+ * @param viewingHash - 4 M31 elements: keccak_m31(starkViewingSecret)
252
+ * @param chainId - Optional chain ID (0 = any chain)
253
+ */
254
+ declare function encodeStarkStealthAddress(ownerHash: M31Digest, viewingHash: M31Digest, chainId?: number): string;
255
+ /**
256
+ * Decode a STARK stealth address (0zs prefix)
257
+ */
258
+ declare function decodeStarkStealthAddress(address: string): {
259
+ version: number;
260
+ chainId: number;
261
+ ownerHash: M31Digest;
262
+ viewingHash: M31Digest;
263
+ };
264
+ /**
265
+ * Validate a STARK stealth address format
266
+ */
267
+ declare function isValidStarkStealthAddress(address: string): boolean;
268
+ /**
269
+ * Generate a STARK stealth address from STARK master keys
270
+ */
271
+ declare function generateStarkStealthAddress(keys: StarkMasterKeys, chainId?: number): string;
272
+ /**
273
+ * Detect whether an address is SNARK (0zk) or STARK (0zs)
274
+ */
275
+ declare function detectAddressType(address: string): 'snark' | 'stark' | 'unknown';
276
+
277
+ /**
278
+ * Account Adapter — Pluggable account creation
279
+ *
280
+ * Abstracts how master keys are derived/loaded.
281
+ * The SDK doesn't care if keys come from a wallet signature,
282
+ * seed phrase, hardware wallet, or external KMS.
283
+ */
284
+
285
+ /**
286
+ * Account adapter interface — pluggable key source.
287
+ *
288
+ * Implement this to bring your own key derivation:
289
+ * - SignatureAccountAdapter: EIP-712 wallet signature (built-in)
290
+ * - DirectAccountAdapter: pre-derived keys (built-in, for testing/KMS)
291
+ * - SeedPhraseAccountAdapter: BIP-39 seed phrase (custom)
292
+ * - HardwareWalletAccountAdapter: Ledger/Trezor (custom)
293
+ */
294
+ interface IAccountAdapter {
295
+ /** Derive or load SNARK master keys */
296
+ getKeys(): Promise<MasterKeys>;
297
+ /** Derive or load STARK master keys (optional) */
298
+ getStarkKeys?(): Promise<StarkMasterKeys>;
299
+ /** Persist keys (adapter decides where/how) */
300
+ save?(): Promise<void>;
301
+ /** Clear persisted keys */
302
+ clear?(): Promise<void>;
303
+ }
304
+ /**
305
+ * Direct account adapter — accepts pre-derived keys.
306
+ *
307
+ * Use for testing, external KMS, or when keys are derived
308
+ * outside the SDK (e.g., from a seed phrase).
309
+ *
310
+ * @example
311
+ * ```ts
312
+ * const adapter = new DirectAccountAdapter({
313
+ * spendingSecret: 12345n,
314
+ * ownerHash: await poseidon([12345n]),
315
+ * viewingSecret: 67890n,
316
+ * viewingHash: await poseidon([67890n]),
317
+ * })
318
+ * const keys = await adapter.getKeys()
319
+ * ```
320
+ */
321
+ declare class DirectAccountAdapter implements IAccountAdapter {
322
+ private keys;
323
+ private starkKeys?;
324
+ constructor(keys: MasterKeys, starkKeys?: StarkMasterKeys | undefined);
325
+ getKeys(): Promise<MasterKeys>;
326
+ getStarkKeys(): Promise<StarkMasterKeys>;
327
+ }
328
+
329
+ /**
330
+ * ASP Provider — Pluggable compliance layer
331
+ *
332
+ * Abstracts where ASP membership proofs come from.
333
+ * The pool protocol doesn't care which ASP you use —
334
+ * it's the operator who makes the rules.
335
+ *
336
+ * Built-in: none (ASP is optional, ragequit always available)
337
+ * Implementations:
338
+ * - RestASPProvider: fetch from ASP service API (e.g., asp-whitelist.upd.io)
339
+ * - LocalASPProvider: generate from local tree (via upc-sdk)
340
+ * - Custom: any source that can provide Merkle proofs
341
+ */
342
+
343
+ interface ASPMembershipProof {
344
+ /** Merkle root of the ASP tree */
345
+ root: bigint;
346
+ /** Path elements (siblings) */
347
+ pathElements: bigint[];
348
+ /** Path indices (0 = left, 1 = right) */
349
+ pathIndices: number[];
350
+ }
351
+ /**
352
+ * ASP provider interface — pluggable compliance.
353
+ *
354
+ * Implement this to bring your own ASP:
355
+ * - Each operator runs their own ASP service
356
+ * - Users are whitelisted by the operator's rules
357
+ * - Proofs are fetched from the operator's service
358
+ *
359
+ * If no ASP is configured, users can always ragequit
360
+ * (withdraw their own deposits without ASP approval).
361
+ */
362
+ interface IASPProvider {
363
+ /** ASP ID registered on-chain */
364
+ getASPId(): bigint;
365
+ /** Fetch a membership proof for an address */
366
+ getProof(address: Address): Promise<ASPMembershipProof | null>;
367
+ /** Check if an address is whitelisted (without fetching full proof) */
368
+ isWhitelisted(address: Address): Promise<boolean>;
369
+ }
370
+
371
+ /**
372
+ * Indexer Types
373
+ *
374
+ * Types for the pluggable indexer module that handles note scanning and persistence.
375
+ */
376
+
377
+ /**
378
+ * Status of a shielded note
379
+ */
380
+ type NoteStatus$1 = 'pending' | 'confirmed' | 'spent';
381
+ /**
382
+ * A shielded note (UTXO) stored by the indexer
383
+ */
384
+ interface IndexedNote {
385
+ /** Amount of tokens */
386
+ amount: bigint;
387
+ /** Random blinding factor */
388
+ blinding: bigint;
389
+ /** Commitment hash (hex) */
390
+ commitment: Hex;
391
+ /** One-time spending secret (hex) */
392
+ oneTimeSecret: Hex;
393
+ /** One-time public key X (hex) */
394
+ oneTimePubkeyX: Hex;
395
+ /** One-time public key Y (hex) */
396
+ oneTimePubkeyY: Hex;
397
+ /** Position in Merkle tree */
398
+ leafIndex: number;
399
+ /** Transaction hash */
400
+ txHash?: Hex;
401
+ /** Note status */
402
+ status: NoteStatus$1;
403
+ /** Block number where note was created */
404
+ blockNumber: number;
405
+ /** Timestamp (Unix seconds) */
406
+ timestamp: number;
407
+ /** Origin address (original depositor for ASP proofs) */
408
+ origin?: Address;
409
+ /** Token address (for multi-token pools) */
410
+ token?: Address;
411
+ /** Ephemeral public key X (R.x — used as viewing key nonce) */
412
+ ephemeralX?: Hex;
413
+ /** Ephemeral public key Y (R.y) */
414
+ ephemeralY?: Hex;
415
+ }
416
+ /**
417
+ * Serialized note for storage (bigints as strings)
418
+ */
419
+ interface SerializedNote {
420
+ amount: string;
421
+ blinding: string;
422
+ commitment: string;
423
+ oneTimeSecret: string;
424
+ oneTimePubkeyX: string;
425
+ oneTimePubkeyY: string;
426
+ leafIndex: number;
427
+ txHash?: string;
428
+ status: NoteStatus$1;
429
+ blockNumber: number;
430
+ timestamp: number;
431
+ origin?: string;
432
+ token?: string;
433
+ ephemeralX?: string;
434
+ ephemeralY?: string;
435
+ }
436
+ /**
437
+ * Sync state persisted by the indexer
438
+ */
439
+ interface SyncState {
440
+ /** Last processed block number */
441
+ lastBlock: number;
442
+ /** Chain ID for validation */
443
+ chainId: number;
444
+ /** Pool contract address */
445
+ contractAddress: Address;
446
+ /** Timestamp of last sync */
447
+ lastSyncTimestamp: number;
448
+ }
449
+ /**
450
+ * Full indexer state for persistence
451
+ */
452
+ interface IndexerState {
453
+ /** Sync metadata */
454
+ sync: SyncState;
455
+ /** All indexed notes */
456
+ notes: SerializedNote[];
457
+ /** Nullifier hashes of spent notes */
458
+ nullifiers: Hex[];
459
+ }
460
+ /**
461
+ * Storage adapter interface for pluggable persistence
462
+ *
463
+ * Implementations must be async-safe and handle concurrent access.
464
+ */
465
+ interface StorageAdapter {
466
+ /**
467
+ * Get a value by key
468
+ */
469
+ get<T>(key: string): Promise<T | null>;
470
+ /**
471
+ * Set a value
472
+ */
473
+ set<T>(key: string, value: T): Promise<void>;
474
+ /**
475
+ * Delete a value
476
+ */
477
+ delete(key: string): Promise<void>;
478
+ /**
479
+ * Clear all data
480
+ */
481
+ clear(): Promise<void>;
482
+ /**
483
+ * Check if storage is available
484
+ */
485
+ isAvailable(): boolean;
486
+ }
487
+ /**
488
+ * Result of a sync operation
489
+ */
490
+ interface SyncResult {
491
+ /** Number of new notes discovered */
492
+ newNotesCount: number;
493
+ /** Number of notes marked as spent */
494
+ spentNotesCount: number;
495
+ /** Last block synced to */
496
+ lastBlock: number;
497
+ /** Time taken in milliseconds */
498
+ durationMs: number;
499
+ /** Any errors encountered (non-fatal) */
500
+ errors?: string[];
501
+ }
502
+ /**
503
+ * Progress information during sync
504
+ */
505
+ interface SyncProgress {
506
+ /** Current block being processed */
507
+ currentBlock: number;
508
+ /** Target block (latest block) */
509
+ targetBlock: number;
510
+ /** Total events processed */
511
+ eventsProcessed: number;
512
+ /** Notes found so far */
513
+ notesFound: number;
514
+ /** Progress percentage (0-100) */
515
+ percent: number;
516
+ /** Events skipped by search tag filtering */
517
+ eventsSkipped: number;
518
+ }
519
+ /**
520
+ * Configuration for sync operation
521
+ */
522
+ interface SyncConfig {
523
+ /** Callback for progress updates */
524
+ onProgress?: (progress: SyncProgress) => void;
525
+ /** Enable search tag filtering (default: true) */
526
+ useSearchTagFiltering?: boolean;
527
+ /** Enable debug logging */
528
+ debug?: boolean;
529
+ }
530
+ /**
531
+ * Filter options for querying notes
532
+ */
533
+ interface NoteFilters {
534
+ /** Filter by status */
535
+ status?: NoteStatus$1 | NoteStatus$1[];
536
+ /** Filter by token address */
537
+ token?: Address;
538
+ /** Minimum amount */
539
+ minAmount?: bigint;
540
+ /** Maximum amount */
541
+ maxAmount?: bigint;
542
+ }
543
+ /**
544
+ * Configuration for RPC indexer
545
+ */
546
+ interface RpcIndexerConfig {
547
+ /** viem PublicClient instance */
548
+ client: any;
549
+ /** Pool contract address */
550
+ contractAddress: Address;
551
+ /** Chain ID */
552
+ chainId: number;
553
+ /** Initial batch size for getLogs (will adapt on rate limits) */
554
+ batchSize?: number;
555
+ /** Minimum batch size (won't go below this) */
556
+ minBatchSize?: number;
557
+ /** Delay between batches in ms */
558
+ batchDelayMs?: number;
559
+ /** Storage adapter (defaults to IndexedDB) */
560
+ storage?: StorageAdapter;
561
+ /** Spending secret for trial decryption */
562
+ spendingSecret: bigint;
563
+ /** Spending public key for verification */
564
+ spendingPubkey: Point;
565
+ /** Master viewing secret for DVK derivation */
566
+ masterViewingSecret: bigint;
567
+ /** Master viewing public key for EVK/DVK derivation */
568
+ masterViewingPubKey: Point;
569
+ /** Initial starting block (if no saved state). Useful to skip blocks before account creation. */
570
+ fromBlock?: number;
571
+ }
572
+ /**
573
+ * Live sync configuration
574
+ */
575
+ interface LiveSyncConfig {
576
+ /** Interval between syncs in ms (default 30000) */
577
+ intervalMs?: number;
578
+ /** Callback when new notes are found */
579
+ onNewNotes?: (notes: IndexedNote[]) => void;
580
+ /** Callback when notes are spent */
581
+ onNotesSpent?: (commitments: Hex[]) => void;
582
+ /** Callback on sync error */
583
+ onError?: (error: Error) => void;
584
+ }
585
+ /**
586
+ * Indexer interface
587
+ *
588
+ * Provides note scanning, balance calculation, and state management.
589
+ */
590
+ interface Indexer {
591
+ /**
592
+ * Sync notes from blockchain
593
+ *
594
+ * Fetches new events since last sync and tries to decrypt them.
595
+ *
596
+ * @param config - Optional sync configuration (progress callbacks, etc.)
597
+ */
598
+ sync(config?: SyncConfig): Promise<SyncResult>;
599
+ /**
600
+ * Get total balance of unspent notes
601
+ *
602
+ * @param token - Optional token address filter
603
+ */
604
+ getBalance(token?: Address): bigint;
605
+ /**
606
+ * Get all notes matching filters
607
+ */
608
+ getNotes(filters?: NoteFilters): IndexedNote[];
609
+ /**
610
+ * Get unspent notes
611
+ */
612
+ getUnspentNotes(): IndexedNote[];
613
+ /**
614
+ * Get the last synced block number
615
+ */
616
+ getLastBlock(): number;
617
+ /**
618
+ * Mark a note as spent (e.g., after a transfer)
619
+ */
620
+ markSpent(commitment: Hex): void;
621
+ /**
622
+ * Add a note directly (e.g., after shielding)
623
+ */
624
+ addNote(note: IndexedNote): void;
625
+ /**
626
+ * Start live sync (polls for new blocks)
627
+ */
628
+ startLiveSync(config?: LiveSyncConfig): void;
629
+ /**
630
+ * Stop live sync
631
+ */
632
+ stopLiveSync(): void;
633
+ /**
634
+ * Check if live sync is running
635
+ */
636
+ isLiveSyncing(): boolean;
637
+ /**
638
+ * Clear all indexed data
639
+ */
640
+ clear(): Promise<void>;
641
+ /**
642
+ * Export current state (for backup/migration)
643
+ */
644
+ exportState(): Promise<IndexerState>;
645
+ /**
646
+ * Import state (for restore)
647
+ */
648
+ importState(state: IndexerState): Promise<void>;
649
+ }
650
+ /**
651
+ * CommitmentInserted event args
652
+ */
653
+ interface CommitmentInsertedArgs {
654
+ commitment: Hex;
655
+ leafIndex: number;
656
+ timestamp: bigint;
657
+ }
658
+ /**
659
+ * StealthTransact event args
660
+ */
661
+ interface StealthTransactArgs {
662
+ commitment: Hex;
663
+ searchTag: bigint;
664
+ ephemeralPubkeyX: bigint;
665
+ ephemeralPubkeyY: bigint;
666
+ encryptedNote: Hex;
667
+ }
668
+ /**
669
+ * Nullified event args
670
+ */
671
+ interface NullifiedArgs {
672
+ nullifier: Hex;
673
+ }
674
+
675
+ /**
676
+ * NoteStore — Single source of truth for note state
677
+ *
678
+ * Framework-agnostic. Uses StorageAdapter for persistence.
679
+ * Handles deduplication, status management, balance calculation.
680
+ *
681
+ * Usage:
682
+ * const store = new NoteStore(createMemoryAdapter())
683
+ * await store.load()
684
+ * store.addNote(note) // returns false if duplicate
685
+ * store.getBalance() // sum of unspent notes
686
+ */
687
+
688
+ type NoteStatus = 'pending' | 'confirmed' | 'spent';
689
+ type ProofSystem = 'snark' | 'stark';
690
+ interface ShieldedNote {
691
+ amount: bigint;
692
+ blinding: bigint;
693
+ commitment: string;
694
+ ownerSecret: string;
695
+ ownerHash: string;
696
+ leafIndex: number;
697
+ origin: string;
698
+ token: string;
699
+ txHash?: string;
700
+ status: NoteStatus;
701
+ timestamp: number;
702
+ proofSystem?: ProofSystem;
703
+ }
704
+ interface INoteStore {
705
+ getNotes(): ShieldedNote[];
706
+ getUnspentNotes(proofSystem?: ProofSystem): ShieldedNote[];
707
+ getBalance(token?: string, proofSystem?: ProofSystem): bigint;
708
+ addNote(note: ShieldedNote): boolean;
709
+ addNotes(notes: ShieldedNote[]): number;
710
+ markSpent(commitment: string): void;
711
+ unmarkSpent(commitment: string): void;
712
+ updateLeafIndex(commitment: string, leafIndex: number): void;
713
+ load(): Promise<void>;
714
+ persist(): Promise<void>;
715
+ clear(): Promise<void>;
716
+ onChange(callback: () => void): () => void;
717
+ }
718
+ declare class NoteStore implements INoteStore {
719
+ private storage;
720
+ private storageKey;
721
+ private notes;
722
+ private commitmentSet;
723
+ private listeners;
724
+ private dirty;
725
+ constructor(storage: StorageAdapter, storageKey?: string);
726
+ getNotes(): ShieldedNote[];
727
+ getUnspentNotes(proofSystem?: ProofSystem): ShieldedNote[];
728
+ getBalance(token?: string, proofSystem?: ProofSystem): bigint;
729
+ /**
730
+ * Add a note. Returns false if duplicate (by commitment).
731
+ * Normalizes token and origin addresses.
732
+ */
733
+ addNote(note: ShieldedNote): boolean;
734
+ /**
735
+ * Add multiple notes. Returns count of actually added (non-duplicate).
736
+ */
737
+ addNotes(notes: ShieldedNote[]): number;
738
+ /**
739
+ * Mark a note as spent (optimistic — syncNotes reconciles via nullifier check).
740
+ */
741
+ markSpent(commitment: string): void;
742
+ /**
743
+ * Un-mark a note as spent (reconciliation: nullifier not found on-chain).
744
+ */
745
+ unmarkSpent(commitment: string): void;
746
+ /**
747
+ * Update the leafIndex for a note (e.g., after confirming on-chain).
748
+ */
749
+ updateLeafIndex(commitment: string, leafIndex: number): void;
750
+ load(): Promise<void>;
751
+ persist(): Promise<void>;
752
+ clear(): Promise<void>;
753
+ onChange(callback: () => void): () => void;
754
+ private notify;
755
+ }
756
+
757
+ export { ADDRESS_VERSION as A, decryptNote as B, type CommitmentInsertedArgs as C, DirectAccountAdapter as D, detectAddressType as E, encodeStarkStealthAddress as F, encodeStealthAddress as G, encryptNote as H, type Indexer as I, generateStarkStealthAddress as J, generateStealthAddress as K, type LiveSyncConfig as L, isValidStarkStealthAddress as M, type NoteStatus$1 as N, isValidStealthAddress as O, type ProofSystem as P, verifyOwnership as Q, type RpcIndexerConfig as R, type StorageAdapter as S, type NoteStatus as T, type UPPClient as U, type IndexedNote as a, type NoteFilters as b, type SyncResult as c, type SyncProgress as d, type SyncConfig as e, type IndexerState as f, type SyncState as g, type SerializedNote as h, type StealthTransactArgs as i, type NullifiedArgs as j, type ASPMembershipProof as k, type IASPProvider as l, type IAccountAdapter as m, type INoteStore as n, NoteStore as o, STARK_ADDRESS_VERSION as p, STARK_STEALTH_ADDRESS_PREFIX as q, STEALTH_ADDRESS_PREFIX as r, type ShieldedNote as s, type UPPClientConfig as t, computeNoteEncryptionKey as u, createNote as v, createOneTimeKeys as w, createUPPClient as x, decodeStarkStealthAddress as y, decodeStealthAddress as z };