@permissionless-technologies/upp-sdk 0.4.21 → 0.4.23

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 (69) hide show
  1. package/README.md +37 -3
  2. package/dist/chunk-2BSIUEPO.js +343 -0
  3. package/dist/chunk-2BSIUEPO.js.map +1 -0
  4. package/dist/{chunk-YHBUCKVS.cjs → chunk-5MK5R7M7.cjs} +24 -24
  5. package/dist/{chunk-YHBUCKVS.cjs.map → chunk-5MK5R7M7.cjs.map} +1 -1
  6. package/dist/{chunk-V6MW5VOF.cjs → chunk-632LPXPX.cjs} +4 -4
  7. package/dist/{chunk-V6MW5VOF.cjs.map → chunk-632LPXPX.cjs.map} +1 -1
  8. package/dist/{chunk-RYEYGGE7.cjs → chunk-IX7HV5TE.cjs} +18 -5
  9. package/dist/chunk-IX7HV5TE.cjs.map +1 -0
  10. package/dist/{chunk-5H27F6W6.cjs → chunk-IYRCJAME.cjs} +13 -9
  11. package/dist/chunk-IYRCJAME.cjs.map +1 -0
  12. package/dist/{chunk-KRLRJ3HN.js → chunk-KR4GB6VC.js} +18 -5
  13. package/dist/chunk-KR4GB6VC.js.map +1 -0
  14. package/dist/{chunk-C7DUABSG.js → chunk-Q6BLTPWV.js} +13 -9
  15. package/dist/chunk-Q6BLTPWV.js.map +1 -0
  16. package/dist/{chunk-ND56VNCF.js → chunk-R4O6FOIN.js} +2 -2
  17. package/dist/{chunk-ND56VNCF.js.map → chunk-R4O6FOIN.js.map} +1 -1
  18. package/dist/{chunk-OLJFKARA.js → chunk-TVF6FYTQ.js} +16 -16
  19. package/dist/{chunk-OLJFKARA.js.map → chunk-TVF6FYTQ.js.map} +1 -1
  20. package/dist/{chunk-7VPW5T5R.js → chunk-UMWY4ICQ.js} +3 -3
  21. package/dist/{chunk-7VPW5T5R.js.map → chunk-UMWY4ICQ.js.map} +1 -1
  22. package/dist/{chunk-PZAV2S5E.cjs → chunk-UWW4GFZ3.cjs} +2 -2
  23. package/dist/{chunk-PZAV2S5E.cjs.map → chunk-UWW4GFZ3.cjs.map} +1 -1
  24. package/dist/chunk-VVW5VVY3.cjs +347 -0
  25. package/dist/chunk-VVW5VVY3.cjs.map +1 -0
  26. package/dist/core/index.cjs +85 -72
  27. package/dist/core/index.d.cts +2 -2
  28. package/dist/core/index.d.ts +2 -2
  29. package/dist/core/index.js +6 -5
  30. package/dist/core/proof-worker-entry.cjs +8 -8
  31. package/dist/core/proof-worker-entry.cjs.map +1 -1
  32. package/dist/core/proof-worker-entry.js +8 -8
  33. package/dist/core/proof-worker-entry.js.map +1 -1
  34. package/dist/{index-PgqOAfcc.d.cts → index-AooYZ0kF.d.cts} +1 -1
  35. package/dist/{index-DsXMd8zh.d.ts → index-CpfUNGm9.d.ts} +1 -1
  36. package/dist/{index-DmowSsZb.d.ts → index-De5B4r0l.d.ts} +9 -3
  37. package/dist/{index-DcfqeWvk.d.cts → index-hNuffoCo.d.cts} +9 -3
  38. package/dist/index.cjs +231 -218
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +3 -3
  41. package/dist/index.d.ts +3 -3
  42. package/dist/index.js +8 -7
  43. package/dist/index.js.map +1 -1
  44. package/dist/indexer/index.cjs +6 -6
  45. package/dist/indexer/index.d.cts +5 -5
  46. package/dist/indexer/index.d.ts +5 -5
  47. package/dist/indexer/index.js +1 -1
  48. package/dist/{proof-VINVGL4F.cjs → proof-X3MVQFFZ.cjs} +14 -13
  49. package/dist/{proof-VINVGL4F.cjs.map → proof-X3MVQFFZ.cjs.map} +1 -1
  50. package/dist/{proof-XQG5DN5N.js → proof-YMXBL4D5.js} +4 -3
  51. package/dist/{proof-XQG5DN5N.js.map → proof-YMXBL4D5.js.map} +1 -1
  52. package/dist/react/index.cjs +123 -39
  53. package/dist/react/index.cjs.map +1 -1
  54. package/dist/react/index.d.cts +44 -6
  55. package/dist/react/index.d.ts +44 -6
  56. package/dist/react/index.js +90 -18
  57. package/dist/react/index.js.map +1 -1
  58. package/dist/{transfer-Cqg235q6.d.ts → transfer-BGzySIhC.d.ts} +124 -5
  59. package/dist/{transfer-B4q3ZTJK.d.cts → transfer-BhB-UuBP.d.cts} +124 -5
  60. package/dist/{transfer-7IFAXV5K.cjs → transfer-M3PKP4PY.cjs} +12 -11
  61. package/dist/{transfer-7IFAXV5K.cjs.map → transfer-M3PKP4PY.cjs.map} +1 -1
  62. package/dist/{transfer-FWCRUWWM.js → transfer-RA7R3KQY.js} +6 -5
  63. package/dist/{transfer-FWCRUWWM.js.map → transfer-RA7R3KQY.js.map} +1 -1
  64. package/package.json +2 -2
  65. package/src/deployments/11155111.json +12 -12
  66. package/dist/chunk-5H27F6W6.cjs.map +0 -1
  67. package/dist/chunk-C7DUABSG.js.map +0 -1
  68. package/dist/chunk-KRLRJ3HN.js.map +0 -1
  69. package/dist/chunk-RYEYGGE7.cjs.map +0 -1
package/README.md CHANGED
@@ -10,7 +10,8 @@ Privacy-preserving token operations for any ERC20 token.
10
10
  - **Large anonymity set** — All token users share one Merkle tree
11
11
  - **Compliance-ready** — Pluggable ASP (Association Set Provider) with ragequit fallback
12
12
  - **Pluggable architecture** — Bring your own account adapter, ASP provider, storage backend
13
- - **SNARK + STARK** — Dual proof system support (BN254 + Circle STARK)
13
+ - **SNARK + STARK** — Dual proof system: PLONK/BLS12-381 (128-bit, EIP-2537 precompiles) + Circle STARK (post-quantum)
14
+ - **Web Worker proving** — Off-main-thread proof generation keeps UI responsive
14
15
  - **Modern stack** — Built on viem, TypeScript strict mode, ESM-first
15
16
 
16
17
  ## Installation
@@ -37,8 +38,11 @@ import { ... } from '@permissionless-technologies/upp-sdk/react'
37
38
  // Indexer: note scanning, storage adapters
38
39
  import { ... } from '@permissionless-technologies/upp-sdk/indexer'
39
40
 
40
- // Utilities: poseidon, babyjubjub, merkle trees
41
+ // Utilities: poseidon (BLS12-381), merkle trees
41
42
  import { ... } from '@permissionless-technologies/upp-sdk/utils'
43
+
44
+ // Web Worker for off-main-thread proof generation
45
+ import '@permissionless-technologies/upp-sdk/worker'
42
46
  ```
43
47
 
44
48
  ## Quick Start
@@ -97,7 +101,7 @@ await noteStore.load()
97
101
  ├── keys/ # Key derivation (signature, direct, custom)
98
102
  ├── react/ # React hooks (useUPPAccount, useShield, etc.)
99
103
  ├── indexer/ # Note scanning + pluggable storage
100
- ├── utils/ # Poseidon, BabyJubJub, Merkle trees
104
+ ├── utils/ # Poseidon (BLS12-381), Merkle trees
101
105
  ├── contracts/ # ABIs + Solidity interfaces
102
106
  └── deployments/ # Per-chain contract addresses
103
107
  ```
@@ -149,6 +153,36 @@ npm test # Run tests (176 passing)
149
153
  npm run deploy:local # Deploy to local Anvil
150
154
  ```
151
155
 
156
+ ## Circuit Build & Deploy Pipeline
157
+
158
+ After changing circuits (`.circom` files), the full pipeline is:
159
+
160
+ ```bash
161
+ # 1. Compile circuits (circom → wasm + r1cs)
162
+ npm run circuits:compile
163
+
164
+ # 2. Trusted setup (r1cs → zkey + vkey.json, per-circuit Powers of Tau)
165
+ npm run circuits:setup
166
+
167
+ # 3. Generate verifier info + VKeyDeployers.sol (vkey.json → Solidity deployer library)
168
+ npm run circuits:verifiers
169
+
170
+ # 4. Deploy contracts (Forge deploy + extract addresses)
171
+ npm run deploy:sepolia
172
+
173
+ # 5. Rebuild SDK (picks up new deployment addresses)
174
+ npm run build
175
+ ```
176
+
177
+ **Steps must run in order.** `circuits:verifiers` generates `VKeyDeployers.sol` which
178
+ contains the verification keys baked into the on-chain verifiers. If you deploy without
179
+ regenerating this file, the verifiers will have stale keys and proofs will fail with
180
+ "Invalid proof".
181
+
182
+ Circuit artifacts (`.wasm` + `.zkey`) are hosted on a CDN at `circuits.upd.io/{version}/`.
183
+ The SDK caches them in IndexedDB after first download. See `CIRCUIT_VERSION` in
184
+ `src/core/circuit-cache.ts` — bump this when uploading new artifacts.
185
+
152
186
  ## License
153
187
 
154
188
  [AGPL-3.0-or-later](./LICENSE)
@@ -0,0 +1,343 @@
1
+ // src/core/circuit-cache.ts
2
+ var CIRCUIT_VERSION = "20260330";
3
+ var CIRCUIT_CDN_BASE = `https://circuits.upd.io/${CIRCUIT_VERSION}/`;
4
+ var DB_NAME = "upp-circuit-cache";
5
+ var DB_VERSION = 1;
6
+ var STORE_NAME = "artifacts";
7
+ function openDB() {
8
+ return new Promise((resolve, reject) => {
9
+ const request = indexedDB.open(DB_NAME, DB_VERSION);
10
+ request.onupgradeneeded = () => {
11
+ const db = request.result;
12
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
13
+ db.createObjectStore(STORE_NAME, { keyPath: "key" });
14
+ }
15
+ };
16
+ request.onsuccess = () => resolve(request.result);
17
+ request.onerror = () => reject(request.error);
18
+ });
19
+ }
20
+ async function idbGet(key) {
21
+ const db = await openDB();
22
+ return new Promise((resolve, reject) => {
23
+ const tx = db.transaction(STORE_NAME, "readonly");
24
+ const store = tx.objectStore(STORE_NAME);
25
+ const req = store.get(key);
26
+ req.onsuccess = () => resolve(req.result);
27
+ req.onerror = () => reject(req.error);
28
+ tx.oncomplete = () => db.close();
29
+ });
30
+ }
31
+ async function idbPut(entry) {
32
+ const db = await openDB();
33
+ return new Promise((resolve, reject) => {
34
+ const tx = db.transaction(STORE_NAME, "readwrite");
35
+ const store = tx.objectStore(STORE_NAME);
36
+ store.put(entry);
37
+ tx.oncomplete = () => {
38
+ db.close();
39
+ resolve();
40
+ };
41
+ tx.onerror = () => {
42
+ db.close();
43
+ reject(tx.error);
44
+ };
45
+ });
46
+ }
47
+ async function idbDelete(key) {
48
+ const db = await openDB();
49
+ return new Promise((resolve, reject) => {
50
+ const tx = db.transaction(STORE_NAME, "readwrite");
51
+ const store = tx.objectStore(STORE_NAME);
52
+ store.delete(key);
53
+ tx.oncomplete = () => {
54
+ db.close();
55
+ resolve();
56
+ };
57
+ tx.onerror = () => {
58
+ db.close();
59
+ reject(tx.error);
60
+ };
61
+ });
62
+ }
63
+ async function idbGetAllKeys() {
64
+ const db = await openDB();
65
+ return new Promise((resolve, reject) => {
66
+ const tx = db.transaction(STORE_NAME, "readonly");
67
+ const store = tx.objectStore(STORE_NAME);
68
+ const req = store.getAllKeys();
69
+ req.onsuccess = () => resolve(req.result);
70
+ req.onerror = () => reject(req.error);
71
+ tx.oncomplete = () => db.close();
72
+ });
73
+ }
74
+ async function idbGetAll() {
75
+ const db = await openDB();
76
+ return new Promise((resolve, reject) => {
77
+ const tx = db.transaction(STORE_NAME, "readonly");
78
+ const store = tx.objectStore(STORE_NAME);
79
+ const req = store.getAll();
80
+ req.onsuccess = () => resolve(req.result);
81
+ req.onerror = () => reject(req.error);
82
+ tx.oncomplete = () => db.close();
83
+ });
84
+ }
85
+ async function idbClear() {
86
+ const db = await openDB();
87
+ return new Promise((resolve, reject) => {
88
+ const tx = db.transaction(STORE_NAME, "readwrite");
89
+ const store = tx.objectStore(STORE_NAME);
90
+ store.clear();
91
+ tx.oncomplete = () => {
92
+ db.close();
93
+ resolve();
94
+ };
95
+ tx.onerror = () => {
96
+ db.close();
97
+ reject(tx.error);
98
+ };
99
+ });
100
+ }
101
+ async function downloadWithProgress(url, circuitType, artifact, onProgress, signal) {
102
+ const response = await fetch(url, { signal });
103
+ if (!response.ok) {
104
+ throw new Error(`Failed to download ${artifact} for ${circuitType}: ${response.status} ${response.statusText}`);
105
+ }
106
+ const contentLength = parseInt(response.headers.get("Content-Length") ?? "0", 10);
107
+ if (response.body && contentLength > 0 && onProgress) {
108
+ const reader = response.body.getReader();
109
+ const chunks = [];
110
+ let bytesDownloaded = 0;
111
+ while (true) {
112
+ const { done, value } = await reader.read();
113
+ if (done) break;
114
+ chunks.push(value);
115
+ bytesDownloaded += value.length;
116
+ onProgress({
117
+ circuitType,
118
+ artifact,
119
+ bytesDownloaded,
120
+ totalBytes: contentLength,
121
+ percent: Math.round(bytesDownloaded / contentLength * 100)
122
+ });
123
+ }
124
+ const result = new Uint8Array(bytesDownloaded);
125
+ let offset = 0;
126
+ for (const chunk of chunks) {
127
+ result.set(chunk, offset);
128
+ offset += chunk.length;
129
+ }
130
+ return result;
131
+ }
132
+ const buffer = await response.arrayBuffer();
133
+ return new Uint8Array(buffer);
134
+ }
135
+ var ALL_CIRCUITS = [
136
+ "transfer",
137
+ "withdraw",
138
+ "merge",
139
+ "merge_transfer_2x2",
140
+ "merge_transfer_4x2",
141
+ "joinsplit"
142
+ ];
143
+ var CircuitArtifactCache = class _CircuitArtifactCache {
144
+ // Lazy singleton per JS context (main thread and workers get their own)
145
+ static _instance = null;
146
+ static shared() {
147
+ if (!_CircuitArtifactCache._instance) {
148
+ _CircuitArtifactCache._instance = new _CircuitArtifactCache();
149
+ }
150
+ return _CircuitArtifactCache._instance;
151
+ }
152
+ /** In-flight download deduplication */
153
+ inflight = /* @__PURE__ */ new Map();
154
+ constructor() {
155
+ }
156
+ // --------------------------------------------------------------------------
157
+ // Key helpers
158
+ // --------------------------------------------------------------------------
159
+ key(circuit, artifact, version = CIRCUIT_VERSION) {
160
+ return `${version}_${circuit}_${artifact}`;
161
+ }
162
+ resolveBaseUrl(baseUrl) {
163
+ const url = baseUrl ?? CIRCUIT_CDN_BASE;
164
+ return url.endsWith("/") ? url : `${url}/`;
165
+ }
166
+ // --------------------------------------------------------------------------
167
+ // Public API
168
+ // --------------------------------------------------------------------------
169
+ /**
170
+ * Check if both wasm + zkey are cached for a circuit (current CIRCUIT_VERSION).
171
+ */
172
+ async isCached(circuit) {
173
+ const [wasm, zkey] = await Promise.all([
174
+ idbGet(this.key(circuit, "wasm")),
175
+ idbGet(this.key(circuit, "zkey"))
176
+ ]);
177
+ return wasm !== void 0 && zkey !== void 0;
178
+ }
179
+ /**
180
+ * Download and cache a circuit's artifacts. No-ops if already cached.
181
+ *
182
+ * @param circuit - Which circuit to preload
183
+ * @param baseUrl - CDN base URL (defaults to `https://circuits.upd.io/${CIRCUIT_VERSION}/`)
184
+ * @param onProgress - Byte-level download progress callback
185
+ * @param signal - AbortSignal for cancellation
186
+ */
187
+ async preload(circuit, baseUrl, onProgress, signal) {
188
+ await this.getArtifacts(circuit, baseUrl, onProgress, signal);
189
+ }
190
+ /**
191
+ * Get artifacts from cache, downloading if needed.
192
+ * Returns Uint8Array data ready to pass to snarkjs.plonk.fullProve().
193
+ */
194
+ async getArtifacts(circuit, baseUrl, onProgress, signal) {
195
+ const [wasm, zkey] = await Promise.all([
196
+ this.getOrDownload(circuit, "wasm", baseUrl, onProgress, signal),
197
+ this.getOrDownload(circuit, "zkey", baseUrl, onProgress, signal)
198
+ ]);
199
+ return { wasm, zkey };
200
+ }
201
+ /**
202
+ * List all cached circuit types (current version only).
203
+ */
204
+ async getCachedCircuits() {
205
+ const keys = await idbGetAllKeys();
206
+ const prefix = `${CIRCUIT_VERSION}_`;
207
+ const cached = /* @__PURE__ */ new Set();
208
+ for (const k of keys) {
209
+ if (!k.startsWith(prefix)) continue;
210
+ const rest = k.slice(prefix.length);
211
+ const lastUnderscore = rest.lastIndexOf("_");
212
+ if (lastUnderscore > 0) {
213
+ cached.add(rest.slice(0, lastUnderscore));
214
+ }
215
+ }
216
+ return ALL_CIRCUITS.filter((c) => cached.has(c));
217
+ }
218
+ /**
219
+ * Get cache size information.
220
+ */
221
+ async getCacheSize() {
222
+ const entries = await idbGetAll();
223
+ let total = 0;
224
+ const circuits = {};
225
+ for (const entry of entries) {
226
+ total += entry.size;
227
+ const parts = entry.key.split("_");
228
+ if (parts.length >= 3) {
229
+ const circuit = parts.slice(1, -1).join("_");
230
+ circuits[circuit] = (circuits[circuit] ?? 0) + entry.size;
231
+ }
232
+ }
233
+ return { total, circuits };
234
+ }
235
+ /**
236
+ * Get cache status for all circuit types.
237
+ */
238
+ async getStatus() {
239
+ const entries = await idbGetAll();
240
+ const result = /* @__PURE__ */ new Map();
241
+ const prefix = `${CIRCUIT_VERSION}_`;
242
+ for (const c of ALL_CIRCUITS) {
243
+ result.set(c, { cached: false });
244
+ }
245
+ const wasmMap = /* @__PURE__ */ new Map();
246
+ const zkeyMap = /* @__PURE__ */ new Map();
247
+ for (const entry of entries) {
248
+ if (!entry.key.startsWith(prefix)) continue;
249
+ const rest = entry.key.slice(prefix.length);
250
+ const lastUnderscore = rest.lastIndexOf("_");
251
+ const circuit = rest.slice(0, lastUnderscore);
252
+ const artifact = rest.slice(lastUnderscore + 1);
253
+ if (artifact === "wasm") wasmMap.set(circuit, entry.size);
254
+ else if (artifact === "zkey") zkeyMap.set(circuit, entry.size);
255
+ }
256
+ for (const c of ALL_CIRCUITS) {
257
+ const hasWasm = wasmMap.has(c);
258
+ const hasZkey = zkeyMap.has(c);
259
+ result.set(c, {
260
+ cached: hasWasm && hasZkey,
261
+ wasmSize: wasmMap.get(c),
262
+ zkeySize: zkeyMap.get(c)
263
+ });
264
+ }
265
+ return result;
266
+ }
267
+ /**
268
+ * Evict a specific circuit from cache (current version).
269
+ */
270
+ async evict(circuit) {
271
+ await Promise.all([
272
+ idbDelete(this.key(circuit, "wasm")),
273
+ idbDelete(this.key(circuit, "zkey"))
274
+ ]);
275
+ }
276
+ /**
277
+ * Evict all cached circuit artifacts (all versions).
278
+ */
279
+ async evictAll() {
280
+ await idbClear();
281
+ }
282
+ /**
283
+ * Evict all artifacts for a specific version (for cleaning up after SDK updates).
284
+ */
285
+ async evictVersion(version) {
286
+ const keys = await idbGetAllKeys();
287
+ const prefix = `${version}_`;
288
+ const toDelete = keys.filter((k) => k.startsWith(prefix));
289
+ for (const k of toDelete) {
290
+ await idbDelete(k);
291
+ }
292
+ }
293
+ /**
294
+ * Request persistent storage to prevent browser from evicting the cache.
295
+ * Returns true if granted, false if denied or unavailable.
296
+ */
297
+ async requestPersistence() {
298
+ if (typeof navigator !== "undefined" && navigator.storage?.persist) {
299
+ return navigator.storage.persist();
300
+ }
301
+ return false;
302
+ }
303
+ // --------------------------------------------------------------------------
304
+ // Internal
305
+ // --------------------------------------------------------------------------
306
+ async getOrDownload(circuit, artifact, baseUrl, onProgress, signal) {
307
+ const cacheKey = this.key(circuit, artifact);
308
+ const cached = await idbGet(cacheKey);
309
+ if (cached) {
310
+ return cached.data;
311
+ }
312
+ const inflightKey = `${cacheKey}_${this.resolveBaseUrl(baseUrl)}`;
313
+ const existing = this.inflight.get(inflightKey);
314
+ if (existing) {
315
+ return existing;
316
+ }
317
+ const downloadPromise = this.downloadAndStore(circuit, artifact, baseUrl, onProgress, signal);
318
+ this.inflight.set(inflightKey, downloadPromise);
319
+ try {
320
+ const data = await downloadPromise;
321
+ return data;
322
+ } finally {
323
+ this.inflight.delete(inflightKey);
324
+ }
325
+ }
326
+ async downloadAndStore(circuit, artifact, baseUrl, onProgress, signal) {
327
+ const base = this.resolveBaseUrl(baseUrl);
328
+ const url = `${base}${circuit}.${artifact}`;
329
+ const data = await downloadWithProgress(url, circuit, artifact, onProgress, signal);
330
+ await idbPut({
331
+ key: this.key(circuit, artifact),
332
+ data,
333
+ size: data.byteLength,
334
+ cachedAt: Date.now(),
335
+ version: CIRCUIT_VERSION
336
+ });
337
+ return data;
338
+ }
339
+ };
340
+
341
+ export { CIRCUIT_CDN_BASE, CIRCUIT_VERSION, CircuitArtifactCache };
342
+ //# sourceMappingURL=chunk-2BSIUEPO.js.map
343
+ //# sourceMappingURL=chunk-2BSIUEPO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/circuit-cache.ts"],"names":[],"mappings":"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","file":"chunk-2BSIUEPO.js","sourcesContent":["/**\n * Circuit Artifact Cache — IndexedDB-based caching for PLONK circuit files.\n *\n * Downloads circuit artifacts (wasm + zkey) with progress reporting via\n * ReadableStream, caches them in IndexedDB, and returns Uint8Array data\n * that can be passed directly to snarkjs.plonk.fullProve().\n *\n * Works in both main thread and Web Worker contexts.\n */\n\nimport type { UPPCircuitType } from './proof.js'\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Current circuit artifact version (date-based).\n * Bump this when circuits are recompiled (new trusted setup, circuit changes).\n * Old cached artifacts are ignored (different key prefix in IndexedDB).\n */\nexport const CIRCUIT_VERSION = '20260330'\n\n/** Default CDN base URL for circuit artifacts */\nexport const CIRCUIT_CDN_BASE = `https://circuits.upd.io/${CIRCUIT_VERSION}/`\n\nconst DB_NAME = 'upp-circuit-cache'\nconst DB_VERSION = 1\nconst STORE_NAME = 'artifacts'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Progress report during circuit artifact download */\nexport interface DownloadProgress {\n circuitType: UPPCircuitType\n artifact: 'wasm' | 'zkey'\n bytesDownloaded: number\n totalBytes: number\n /** 0-100 */\n percent: number\n}\n\n/** Resolved (binary) circuit artifacts ready for snarkjs */\nexport interface ResolvedCircuitArtifacts {\n wasm: Uint8Array\n zkey: Uint8Array\n}\n\n/** Cache entry stored in IndexedDB */\ninterface CacheEntry {\n key: string\n data: Uint8Array\n size: number\n cachedAt: number\n version: string\n}\n\n/** Per-circuit cache status */\nexport interface CircuitCacheStatus {\n cached: boolean\n wasmSize?: number\n zkeySize?: number\n}\n\n// ============================================================================\n// IndexedDB Helpers (thin promise wrapper, no external deps)\n// ============================================================================\n\nfunction openDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION)\n\n request.onupgradeneeded = () => {\n const db = request.result\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME, { keyPath: 'key' })\n }\n }\n\n request.onsuccess = () => resolve(request.result)\n request.onerror = () => reject(request.error)\n })\n}\n\nasync function idbGet(key: string): Promise<CacheEntry | undefined> {\n const db = await openDB()\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly')\n const store = tx.objectStore(STORE_NAME)\n const req = store.get(key)\n req.onsuccess = () => resolve(req.result as CacheEntry | undefined)\n req.onerror = () => reject(req.error)\n tx.oncomplete = () => db.close()\n })\n}\n\nasync function idbPut(entry: CacheEntry): Promise<void> {\n const db = await openDB()\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n store.put(entry)\n tx.oncomplete = () => { db.close(); resolve() }\n tx.onerror = () => { db.close(); reject(tx.error) }\n })\n}\n\nasync function idbDelete(key: string): Promise<void> {\n const db = await openDB()\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n store.delete(key)\n tx.oncomplete = () => { db.close(); resolve() }\n tx.onerror = () => { db.close(); reject(tx.error) }\n })\n}\n\nasync function idbGetAllKeys(): Promise<string[]> {\n const db = await openDB()\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly')\n const store = tx.objectStore(STORE_NAME)\n const req = store.getAllKeys()\n req.onsuccess = () => resolve(req.result as string[])\n req.onerror = () => reject(req.error)\n tx.oncomplete = () => db.close()\n })\n}\n\nasync function idbGetAll(): Promise<CacheEntry[]> {\n const db = await openDB()\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readonly')\n const store = tx.objectStore(STORE_NAME)\n const req = store.getAll()\n req.onsuccess = () => resolve(req.result as CacheEntry[])\n req.onerror = () => reject(req.error)\n tx.oncomplete = () => db.close()\n })\n}\n\nasync function idbClear(): Promise<void> {\n const db = await openDB()\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n store.clear()\n tx.oncomplete = () => { db.close(); resolve() }\n tx.onerror = () => { db.close(); reject(tx.error) }\n })\n}\n\n// ============================================================================\n// Download with progress\n// ============================================================================\n\nasync function downloadWithProgress(\n url: string,\n circuitType: UPPCircuitType,\n artifact: 'wasm' | 'zkey',\n onProgress?: (p: DownloadProgress) => void,\n signal?: AbortSignal,\n): Promise<Uint8Array> {\n const response = await fetch(url, { signal })\n\n if (!response.ok) {\n throw new Error(`Failed to download ${artifact} for ${circuitType}: ${response.status} ${response.statusText}`)\n }\n\n const contentLength = parseInt(response.headers.get('Content-Length') ?? '0', 10)\n\n // If ReadableStream is available and we have Content-Length, stream with progress\n if (response.body && contentLength > 0 && onProgress) {\n const reader = response.body.getReader()\n const chunks: Uint8Array[] = []\n let bytesDownloaded = 0\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n chunks.push(value)\n bytesDownloaded += value.length\n\n onProgress({\n circuitType,\n artifact,\n bytesDownloaded,\n totalBytes: contentLength,\n percent: Math.round((bytesDownloaded / contentLength) * 100),\n })\n }\n\n // Combine chunks into single Uint8Array\n const result = new Uint8Array(bytesDownloaded)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.length\n }\n return result\n }\n\n // Fallback: no progress (ReadableStream unavailable or no Content-Length)\n const buffer = await response.arrayBuffer()\n return new Uint8Array(buffer)\n}\n\n// ============================================================================\n// CircuitArtifactCache\n// ============================================================================\n\n/** All UPP circuit types */\nconst ALL_CIRCUITS: UPPCircuitType[] = [\n 'transfer', 'withdraw', 'merge',\n 'merge_transfer_2x2', 'merge_transfer_4x2', 'joinsplit',\n]\n\nexport class CircuitArtifactCache {\n // Lazy singleton per JS context (main thread and workers get their own)\n private static _instance: CircuitArtifactCache | null = null\n\n static shared(): CircuitArtifactCache {\n if (!CircuitArtifactCache._instance) {\n CircuitArtifactCache._instance = new CircuitArtifactCache()\n }\n return CircuitArtifactCache._instance\n }\n\n /** In-flight download deduplication */\n private inflight = new Map<string, Promise<Uint8Array>>()\n\n private constructor() {}\n\n // --------------------------------------------------------------------------\n // Key helpers\n // --------------------------------------------------------------------------\n\n private key(circuit: UPPCircuitType, artifact: 'wasm' | 'zkey', version = CIRCUIT_VERSION): string {\n return `${version}_${circuit}_${artifact}`\n }\n\n private resolveBaseUrl(baseUrl?: string): string {\n const url = baseUrl ?? CIRCUIT_CDN_BASE\n return url.endsWith('/') ? url : `${url}/`\n }\n\n // --------------------------------------------------------------------------\n // Public API\n // --------------------------------------------------------------------------\n\n /**\n * Check if both wasm + zkey are cached for a circuit (current CIRCUIT_VERSION).\n */\n async isCached(circuit: UPPCircuitType): Promise<boolean> {\n const [wasm, zkey] = await Promise.all([\n idbGet(this.key(circuit, 'wasm')),\n idbGet(this.key(circuit, 'zkey')),\n ])\n return wasm !== undefined && zkey !== undefined\n }\n\n /**\n * Download and cache a circuit's artifacts. No-ops if already cached.\n *\n * @param circuit - Which circuit to preload\n * @param baseUrl - CDN base URL (defaults to `https://circuits.upd.io/${CIRCUIT_VERSION}/`)\n * @param onProgress - Byte-level download progress callback\n * @param signal - AbortSignal for cancellation\n */\n async preload(\n circuit: UPPCircuitType,\n baseUrl?: string,\n onProgress?: (p: DownloadProgress) => void,\n signal?: AbortSignal,\n ): Promise<void> {\n await this.getArtifacts(circuit, baseUrl, onProgress, signal)\n }\n\n /**\n * Get artifacts from cache, downloading if needed.\n * Returns Uint8Array data ready to pass to snarkjs.plonk.fullProve().\n */\n async getArtifacts(\n circuit: UPPCircuitType,\n baseUrl?: string,\n onProgress?: (p: DownloadProgress) => void,\n signal?: AbortSignal,\n ): Promise<ResolvedCircuitArtifacts> {\n const [wasm, zkey] = await Promise.all([\n this.getOrDownload(circuit, 'wasm', baseUrl, onProgress, signal),\n this.getOrDownload(circuit, 'zkey', baseUrl, onProgress, signal),\n ])\n return { wasm, zkey }\n }\n\n /**\n * List all cached circuit types (current version only).\n */\n async getCachedCircuits(): Promise<UPPCircuitType[]> {\n const keys = await idbGetAllKeys()\n const prefix = `${CIRCUIT_VERSION}_`\n const cached = new Set<string>()\n\n for (const k of keys) {\n if (!k.startsWith(prefix)) continue\n const rest = k.slice(prefix.length)\n // rest = \"transfer_zkey\" or \"transfer_wasm\"\n const lastUnderscore = rest.lastIndexOf('_')\n if (lastUnderscore > 0) {\n cached.add(rest.slice(0, lastUnderscore))\n }\n }\n\n return ALL_CIRCUITS.filter(c => cached.has(c))\n }\n\n /**\n * Get cache size information.\n */\n async getCacheSize(): Promise<{ total: number; circuits: Record<string, number> }> {\n const entries = await idbGetAll()\n let total = 0\n const circuits: Record<string, number> = {}\n\n for (const entry of entries) {\n total += entry.size\n // Extract circuit name from key: \"{version}_{circuit}_{artifact}\"\n const parts = entry.key.split('_')\n // Reconstruct circuit name (may contain underscores like merge_transfer_2x2)\n if (parts.length >= 3) {\n const circuit = parts.slice(1, -1).join('_')\n circuits[circuit] = (circuits[circuit] ?? 0) + entry.size\n }\n }\n\n return { total, circuits }\n }\n\n /**\n * Get cache status for all circuit types.\n */\n async getStatus(): Promise<Map<UPPCircuitType, CircuitCacheStatus>> {\n const entries = await idbGetAll()\n const result = new Map<UPPCircuitType, CircuitCacheStatus>()\n const prefix = `${CIRCUIT_VERSION}_`\n\n // Initialize all circuits as not cached\n for (const c of ALL_CIRCUITS) {\n result.set(c, { cached: false })\n }\n\n // Check what's actually cached\n const wasmMap = new Map<string, number>()\n const zkeyMap = new Map<string, number>()\n\n for (const entry of entries) {\n if (!entry.key.startsWith(prefix)) continue\n const rest = entry.key.slice(prefix.length)\n const lastUnderscore = rest.lastIndexOf('_')\n const circuit = rest.slice(0, lastUnderscore)\n const artifact = rest.slice(lastUnderscore + 1)\n\n if (artifact === 'wasm') wasmMap.set(circuit, entry.size)\n else if (artifact === 'zkey') zkeyMap.set(circuit, entry.size)\n }\n\n for (const c of ALL_CIRCUITS) {\n const hasWasm = wasmMap.has(c)\n const hasZkey = zkeyMap.has(c)\n result.set(c, {\n cached: hasWasm && hasZkey,\n wasmSize: wasmMap.get(c),\n zkeySize: zkeyMap.get(c),\n })\n }\n\n return result\n }\n\n /**\n * Evict a specific circuit from cache (current version).\n */\n async evict(circuit: UPPCircuitType): Promise<void> {\n await Promise.all([\n idbDelete(this.key(circuit, 'wasm')),\n idbDelete(this.key(circuit, 'zkey')),\n ])\n }\n\n /**\n * Evict all cached circuit artifacts (all versions).\n */\n async evictAll(): Promise<void> {\n await idbClear()\n }\n\n /**\n * Evict all artifacts for a specific version (for cleaning up after SDK updates).\n */\n async evictVersion(version: string): Promise<void> {\n const keys = await idbGetAllKeys()\n const prefix = `${version}_`\n const toDelete = keys.filter(k => k.startsWith(prefix))\n for (const k of toDelete) {\n await idbDelete(k)\n }\n }\n\n /**\n * Request persistent storage to prevent browser from evicting the cache.\n * Returns true if granted, false if denied or unavailable.\n */\n async requestPersistence(): Promise<boolean> {\n if (typeof navigator !== 'undefined' && navigator.storage?.persist) {\n return navigator.storage.persist()\n }\n return false\n }\n\n // --------------------------------------------------------------------------\n // Internal\n // --------------------------------------------------------------------------\n\n private async getOrDownload(\n circuit: UPPCircuitType,\n artifact: 'wasm' | 'zkey',\n baseUrl?: string,\n onProgress?: (p: DownloadProgress) => void,\n signal?: AbortSignal,\n ): Promise<Uint8Array> {\n const cacheKey = this.key(circuit, artifact)\n\n // Check cache first\n const cached = await idbGet(cacheKey)\n if (cached) {\n return cached.data\n }\n\n // Deduplicate in-flight downloads\n const inflightKey = `${cacheKey}_${this.resolveBaseUrl(baseUrl)}`\n const existing = this.inflight.get(inflightKey)\n if (existing) {\n return existing\n }\n\n const downloadPromise = this.downloadAndStore(circuit, artifact, baseUrl, onProgress, signal)\n\n this.inflight.set(inflightKey, downloadPromise)\n try {\n const data = await downloadPromise\n return data\n } finally {\n this.inflight.delete(inflightKey)\n }\n }\n\n private async downloadAndStore(\n circuit: UPPCircuitType,\n artifact: 'wasm' | 'zkey',\n baseUrl?: string,\n onProgress?: (p: DownloadProgress) => void,\n signal?: AbortSignal,\n ): Promise<Uint8Array> {\n const base = this.resolveBaseUrl(baseUrl)\n const url = `${base}${circuit}.${artifact}`\n\n const data = await downloadWithProgress(url, circuit, artifact, onProgress, signal)\n\n // Store in IndexedDB\n await idbPut({\n key: this.key(circuit, artifact),\n data,\n size: data.byteLength,\n cachedAt: Date.now(),\n version: CIRCUIT_VERSION,\n })\n\n return data\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkRYEYGGE7_cjs = require('./chunk-RYEYGGE7.cjs');
4
- var chunkIIUKM5VE_cjs = require('./chunk-IIUKM5VE.cjs');
3
+ var chunkIX7HV5TE_cjs = require('./chunk-IX7HV5TE.cjs');
5
4
  var chunkXVIICZKW_cjs = require('./chunk-XVIICZKW.cjs');
5
+ var chunkIIUKM5VE_cjs = require('./chunk-IIUKM5VE.cjs');
6
6
  var chunkHEHXSV47_cjs = require('./chunk-HEHXSV47.cjs');
7
7
  var viem = require('viem');
8
8
 
@@ -29,23 +29,23 @@ var __default = {
29
29
 
30
30
  // src/deployments/11155111.json
31
31
  var __default2 = {
32
- UniversalPrivatePool: "0x571f7feba5d25638ba4e05c59668a892ddfeaf4f",
32
+ UniversalPrivatePool: "0x9f9ab2c1dd781160469669e4e59931227e190219",
33
33
  ASPRegistryHub: "0xfd11c56a23314aa88dfbcc36254f33e5e8b010df",
34
- TestToken: "0xace09cebc29a3f04002800aceb26931990786538",
35
- TestToken2: "0x3f10afa4e15949fb36957b1ae3e3b5c93986312c",
34
+ TestToken: "0xe8fd56f1e78562cba4cd883b6d6def47443c9817",
35
+ TestToken2: "0x8af5e352bd8457452aacc60d4f0106fc31c96534",
36
36
  verifiers: {
37
- TransferVerifier: "0x29c822a5b740db73707ea033482cb2772e764357",
38
- MergeVerifier: "0x5fbd1596811a8971be776e477759ed50063fea22",
39
- WithdrawVerifier: "0x49e13844d5e39ba4777f237ffc793e0366212fdd",
40
- JoinSplitVerifier: "0xd0d7200b6684c21213e27713662795ea9bdd5923",
41
- MergeTransfer2x2Verifier: "0x1abf58c52ab366c5e77d7164b7e50631707f682e",
42
- MergeTransfer4x2Verifier: "0x83f097a17f9d0defab6a2fe15aa96f8e8a05f0c3"
37
+ TransferVerifier: "0x898da8e5aa7ff3a880d4faa22969d43bb4aa5d88",
38
+ MergeVerifier: "0x96841d494903e164d4e4a976d1acc84d14fa1ed4",
39
+ WithdrawVerifier: "0xa0a8087fb4e4d6b2a9556a6e6d897138c01aca68",
40
+ JoinSplitVerifier: "0x37f4611e40a9026a204beeb84802db6f5748e592",
41
+ MergeTransfer2x2Verifier: "0xb1c6c6037ec0a2ed073932ca400767cc71b74e37",
42
+ MergeTransfer4x2Verifier: "0x695dca278306aa1f0e7e339d6a00674ac6164ce6"
43
43
  },
44
44
  starkVerifiers: {
45
- CircleStarkVerifier: "0x14e8259e31ec564fe5d80680fdabe81da264baa6"
45
+ CircleStarkVerifier: "0x395ef8216ebd53cc6ddd6653a3653a776968ccc5"
46
46
  },
47
- deployBlock: 10553557,
48
- deployTimestamp: 1774873429071};
47
+ deployBlock: 10555438,
48
+ deployTimestamp: 1774896901906};
49
49
 
50
50
  // src/deployments/index.ts
51
51
  function parseDeployment(json, chainId) {
@@ -105,16 +105,16 @@ function registerDeployment(chainId, config) {
105
105
  chunkHEHXSV47_cjs.init_poseidon();
106
106
  var RPC_CHUNK_SIZE = 9000n;
107
107
  function padToStateTreeDepth(arr, padValue) {
108
- if (arr.length >= chunkRYEYGGE7_cjs.STATE_TREE_DEPTH) {
109
- return arr.slice(0, chunkRYEYGGE7_cjs.STATE_TREE_DEPTH);
108
+ if (arr.length >= chunkIX7HV5TE_cjs.STATE_TREE_DEPTH) {
109
+ return arr.slice(0, chunkIX7HV5TE_cjs.STATE_TREE_DEPTH);
110
110
  }
111
- return [...arr, ...Array(chunkRYEYGGE7_cjs.STATE_TREE_DEPTH - arr.length).fill(padValue)];
111
+ return [...arr, ...Array(chunkIX7HV5TE_cjs.STATE_TREE_DEPTH - arr.length).fill(padValue)];
112
112
  }
113
113
  function padToASPTreeDepth(arr, padValue) {
114
- if (arr.length >= chunkRYEYGGE7_cjs.ASP_TREE_DEPTH) {
115
- return arr.slice(0, chunkRYEYGGE7_cjs.ASP_TREE_DEPTH);
114
+ if (arr.length >= chunkIX7HV5TE_cjs.ASP_TREE_DEPTH) {
115
+ return arr.slice(0, chunkIX7HV5TE_cjs.ASP_TREE_DEPTH);
116
116
  }
117
- return [...arr, ...Array(chunkRYEYGGE7_cjs.ASP_TREE_DEPTH - arr.length).fill(padValue)];
117
+ return [...arr, ...Array(chunkIX7HV5TE_cjs.ASP_TREE_DEPTH - arr.length).fill(padValue)];
118
118
  }
119
119
  var COMMITMENT_INSERTED_EVENT = {
120
120
  type: "event",
@@ -297,12 +297,12 @@ async function buildTransfer(ctx, selectedNote, recipientNote, changeNote, onSta
297
297
  recipientNote,
298
298
  changeNote
299
299
  );
300
- const { proof } = await chunkRYEYGGE7_cjs.generateUPPProof(
300
+ const { proof } = await chunkIX7HV5TE_cjs.generateUPPProof(
301
301
  "transfer",
302
302
  circuitInputs,
303
303
  ctx.circuitBaseUrl ?? "/circuits/"
304
304
  );
305
- const formattedProof = await chunkRYEYGGE7_cjs.formatPlonkProofForContract(proof);
305
+ const formattedProof = await chunkIX7HV5TE_cjs.formatPlonkProofForContract(proof);
306
306
  return {
307
307
  circuit: "transfer",
308
308
  proof: formattedProof,
@@ -339,5 +339,5 @@ exports.getTokenAddress = getTokenAddress;
339
339
  exports.hasDeployment = hasDeployment;
340
340
  exports.registerDeployment = registerDeployment;
341
341
  exports.syncMerkleTree = syncMerkleTree;
342
- //# sourceMappingURL=chunk-YHBUCKVS.cjs.map
343
- //# sourceMappingURL=chunk-YHBUCKVS.cjs.map
342
+ //# sourceMappingURL=chunk-5MK5R7M7.cjs.map
343
+ //# sourceMappingURL=chunk-5MK5R7M7.cjs.map