@izi-noir/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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +458 -0
  3. package/dist/IProvingSystem-D9TnEig0.d.ts +140 -0
  4. package/dist/IProvingSystem-TKNofoo8.d.cts +140 -0
  5. package/dist/index.cjs +2793 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +1196 -0
  8. package/dist/index.d.ts +1196 -0
  9. package/dist/index.js +2730 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/providers/arkworks.cjs +824 -0
  12. package/dist/providers/arkworks.cjs.map +1 -0
  13. package/dist/providers/arkworks.d.cts +121 -0
  14. package/dist/providers/arkworks.d.ts +121 -0
  15. package/dist/providers/arkworks.js +791 -0
  16. package/dist/providers/arkworks.js.map +1 -0
  17. package/dist/providers/barretenberg.cjs +822 -0
  18. package/dist/providers/barretenberg.cjs.map +1 -0
  19. package/dist/providers/barretenberg.d.cts +18 -0
  20. package/dist/providers/barretenberg.d.ts +18 -0
  21. package/dist/providers/barretenberg.js +790 -0
  22. package/dist/providers/barretenberg.js.map +1 -0
  23. package/dist/providers/solana.cjs +262 -0
  24. package/dist/providers/solana.cjs.map +1 -0
  25. package/dist/providers/solana.d.cts +223 -0
  26. package/dist/providers/solana.d.ts +223 -0
  27. package/dist/providers/solana.js +222 -0
  28. package/dist/providers/solana.js.map +1 -0
  29. package/dist/providers/sunspot.cjs +475 -0
  30. package/dist/providers/sunspot.cjs.map +1 -0
  31. package/dist/providers/sunspot.d.cts +210 -0
  32. package/dist/providers/sunspot.d.ts +210 -0
  33. package/dist/providers/sunspot.js +443 -0
  34. package/dist/providers/sunspot.js.map +1 -0
  35. package/dist/types-CaaigonG.d.cts +93 -0
  36. package/dist/types-CaaigonG.d.ts +93 -0
  37. package/dist/wasm/nodejs/arkworks_groth16_wasm.js +448 -0
  38. package/dist/wasm/nodejs/arkworks_groth16_wasm_bg.wasm +0 -0
  39. package/dist/wasm/web/arkworks_groth16_wasm.js +536 -0
  40. package/dist/wasm/web/arkworks_groth16_wasm_bg.wasm +0 -0
  41. package/dist/wasmInit-KV6DTj4J.d.ts +282 -0
  42. package/dist/wasmInit-iEYiiB8M.d.cts +282 -0
  43. package/package.json +87 -0
@@ -0,0 +1,791 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // src/infra/provingSystems/ArkworksWasm.ts
12
+ var ArkworksWasm_exports = {};
13
+ __export(ArkworksWasm_exports, {
14
+ ArkworksWasm: () => ArkworksWasm,
15
+ isArkworksCircuit: () => isArkworksCircuit
16
+ });
17
+ import { compile, createFileManager } from "@noir-lang/noir_wasm";
18
+ import { Noir } from "@noir-lang/noir_js";
19
+ function stringToStream(content) {
20
+ return new ReadableStream({
21
+ start(controller) {
22
+ controller.enqueue(new TextEncoder().encode(content));
23
+ controller.close();
24
+ }
25
+ });
26
+ }
27
+ function isNodeJs() {
28
+ return typeof globalThis.process !== "undefined" && globalThis.process.versions != null && globalThis.process.versions.node != null;
29
+ }
30
+ async function createTempDir() {
31
+ if (!isNodeJs()) {
32
+ return { basePath: "/", cleanup: null };
33
+ }
34
+ const fs = await import("fs/promises");
35
+ const os = await import("os");
36
+ const path = await import("path");
37
+ const basePath = await fs.mkdtemp(path.join(os.tmpdir(), "arkworks-circuit-"));
38
+ const cleanup = async () => {
39
+ await fs.rm(basePath, { recursive: true, force: true });
40
+ };
41
+ return { basePath, cleanup };
42
+ }
43
+ function isArkworksCircuit(circuit) {
44
+ return "__arkworks" in circuit && circuit.__arkworks === true;
45
+ }
46
+ async function initWasm() {
47
+ if (wasmModule) {
48
+ return wasmModule;
49
+ }
50
+ if (wasmInitPromise) {
51
+ return wasmInitPromise;
52
+ }
53
+ wasmInitPromise = (async () => {
54
+ try {
55
+ if (isNodeJs()) {
56
+ const module = await import("../wasm/nodejs/arkworks_groth16_wasm.js");
57
+ wasmModule = module;
58
+ } else {
59
+ const module = await import("../wasm/web/arkworks_groth16_wasm.js");
60
+ if (typeof module.default === "function") {
61
+ await module.default();
62
+ }
63
+ wasmModule = module;
64
+ }
65
+ return wasmModule;
66
+ } catch (error) {
67
+ wasmInitPromise = null;
68
+ throw new Error(
69
+ `Failed to initialize arkworks-groth16-wasm: ${error instanceof Error ? error.message : String(error)}
70
+ Make sure the WASM module is built: cd packages/arkworks-groth16-wasm && npm run build`
71
+ );
72
+ }
73
+ })();
74
+ return wasmInitPromise;
75
+ }
76
+ function base64ToUint8Array(b64) {
77
+ const binaryString = atob(b64);
78
+ const bytes = new Uint8Array(binaryString.length);
79
+ for (let i = 0; i < binaryString.length; i++) {
80
+ bytes[i] = binaryString.charCodeAt(i);
81
+ }
82
+ return bytes;
83
+ }
84
+ function uint8ArrayToBase64(bytes) {
85
+ let binary = "";
86
+ for (let i = 0; i < bytes.length; i++) {
87
+ binary += String.fromCharCode(bytes[i]);
88
+ }
89
+ return btoa(binary);
90
+ }
91
+ function publicInputsToGnarkBase64(publicInputs) {
92
+ const FIELD_SIZE = 32;
93
+ const bytes = new Uint8Array(publicInputs.length * FIELD_SIZE);
94
+ for (let i = 0; i < publicInputs.length; i++) {
95
+ const input = publicInputs[i];
96
+ const hex = input.startsWith("0x") ? input.slice(2) : input;
97
+ const inputBytes = hexToBytes(hex.padStart(64, "0"));
98
+ bytes.set(inputBytes, i * FIELD_SIZE);
99
+ }
100
+ return uint8ArrayToBase64(bytes);
101
+ }
102
+ function hexToBytes(hex) {
103
+ const bytes = new Uint8Array(hex.length / 2);
104
+ for (let i = 0; i < hex.length; i += 2) {
105
+ bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
106
+ }
107
+ return bytes;
108
+ }
109
+ var wasmModule, wasmInitPromise, ArkworksWasm;
110
+ var init_ArkworksWasm = __esm({
111
+ "src/infra/provingSystems/ArkworksWasm.ts"() {
112
+ "use strict";
113
+ wasmModule = null;
114
+ wasmInitPromise = null;
115
+ ArkworksWasm = class {
116
+ config;
117
+ constructor(config = {}) {
118
+ this.config = {
119
+ keepArtifacts: false,
120
+ cacheKeys: true,
121
+ ...config
122
+ };
123
+ }
124
+ /**
125
+ * Compile Noir code to a circuit with ACIR for Groth16 proving
126
+ */
127
+ async compile(noirCode) {
128
+ const wasm = await initWasm();
129
+ const { basePath, cleanup } = await createTempDir();
130
+ const fm = createFileManager(basePath);
131
+ const nargoToml = `[package]
132
+ name = "circuit"
133
+ type = "bin"
134
+ authors = [""]
135
+
136
+ [dependencies]
137
+ `;
138
+ try {
139
+ if (isNodeJs()) {
140
+ await fm.writeFile("./src/main.nr", stringToStream(noirCode));
141
+ await fm.writeFile("./Nargo.toml", stringToStream(nargoToml));
142
+ } else {
143
+ fm.writeFile("./src/main.nr", stringToStream(noirCode));
144
+ fm.writeFile("./Nargo.toml", stringToStream(nargoToml));
145
+ }
146
+ const result = await compile(fm);
147
+ const compiled = result.program;
148
+ if (!compiled || !compiled.bytecode) {
149
+ throw new Error("Compilation failed: no bytecode generated");
150
+ }
151
+ const acirJson = JSON.stringify({
152
+ functions: [
153
+ {
154
+ current_witness_index: compiled.abi.parameters.length + 1,
155
+ opcodes: [],
156
+ // Will be extracted from bytecode during prove
157
+ private_parameters: compiled.abi.parameters.filter((p) => p.visibility === "private").map((_, i) => i + 1),
158
+ public_parameters: {
159
+ witnesses: compiled.abi.parameters.filter((p) => p.visibility === "public").map((_, i) => i + 1)
160
+ },
161
+ return_values: { witnesses: [] }
162
+ }
163
+ ]
164
+ });
165
+ let provingKey;
166
+ let verifyingKey;
167
+ let verifyingKeyGnark;
168
+ if (this.config.cacheKeys) {
169
+ try {
170
+ const setupResult = wasm.setup(acirJson);
171
+ provingKey = setupResult.proving_key;
172
+ verifyingKey = setupResult.verifying_key;
173
+ verifyingKeyGnark = setupResult.verifying_key_gnark;
174
+ } catch (error) {
175
+ console.warn("Deferred setup: will run during proof generation");
176
+ }
177
+ }
178
+ const arkworksCircuit = {
179
+ ...compiled,
180
+ __arkworks: true,
181
+ acirJson,
182
+ provingKey,
183
+ verifyingKey,
184
+ verifyingKeyGnark
185
+ };
186
+ return arkworksCircuit;
187
+ } finally {
188
+ if (cleanup) {
189
+ await cleanup();
190
+ }
191
+ }
192
+ }
193
+ /**
194
+ * Generate a Groth16 proof
195
+ */
196
+ async generateProof(circuit, inputs) {
197
+ const wasm = await initWasm();
198
+ if (!isArkworksCircuit(circuit)) {
199
+ throw new Error(
200
+ "ArkworksWasm.generateProof requires an ArkworksCompiledCircuit. Use ArkworksWasm.compile() first."
201
+ );
202
+ }
203
+ const noir = new Noir(circuit);
204
+ const { witness } = await noir.execute(inputs);
205
+ const witnessMap = {};
206
+ for (const [index, value] of witness.entries()) {
207
+ witnessMap[index.toString()] = String(value);
208
+ }
209
+ const witnessJson = JSON.stringify(witnessMap);
210
+ let provingKey = circuit.provingKey;
211
+ if (!provingKey) {
212
+ const setupResult = wasm.setup(circuit.acirJson);
213
+ provingKey = setupResult.proving_key;
214
+ circuit.provingKey = provingKey;
215
+ circuit.verifyingKey = setupResult.verifying_key;
216
+ circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
217
+ }
218
+ const proofResult = wasm.prove(provingKey, circuit.acirJson, witnessJson);
219
+ const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
220
+ return {
221
+ proof: proofBytes,
222
+ publicInputs: proofResult.public_inputs
223
+ };
224
+ }
225
+ /**
226
+ * Verify a Groth16 proof
227
+ */
228
+ async verifyProof(circuit, proof, publicInputs) {
229
+ const wasm = await initWasm();
230
+ if (!isArkworksCircuit(circuit)) {
231
+ throw new Error(
232
+ "ArkworksWasm.verifyProof requires an ArkworksCompiledCircuit. Use ArkworksWasm.compile() first."
233
+ );
234
+ }
235
+ let verifyingKeyGnark = circuit.verifyingKeyGnark;
236
+ if (!verifyingKeyGnark) {
237
+ const setupResult = wasm.setup(circuit.acirJson);
238
+ circuit.provingKey = setupResult.proving_key;
239
+ circuit.verifyingKey = setupResult.verifying_key;
240
+ verifyingKeyGnark = setupResult.verifying_key_gnark;
241
+ circuit.verifyingKeyGnark = verifyingKeyGnark;
242
+ }
243
+ const proofB64 = uint8ArrayToBase64(proof);
244
+ const publicInputsGnarkB64 = publicInputsToGnarkBase64(publicInputs);
245
+ return wasm.verify_gnark(
246
+ verifyingKeyGnark,
247
+ proofB64,
248
+ publicInputsGnarkB64,
249
+ publicInputs.length
250
+ );
251
+ }
252
+ /**
253
+ * Get the verifying key in gnark format for on-chain deployment
254
+ */
255
+ async getVerifyingKeyGnark(circuit) {
256
+ const wasm = await initWasm();
257
+ if (!isArkworksCircuit(circuit)) {
258
+ throw new Error("getVerifyingKeyGnark requires an ArkworksCompiledCircuit");
259
+ }
260
+ if (!circuit.verifyingKeyGnark) {
261
+ const setupResult = wasm.setup(circuit.acirJson);
262
+ circuit.provingKey = setupResult.proving_key;
263
+ circuit.verifyingKey = setupResult.verifying_key;
264
+ circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
265
+ }
266
+ return base64ToUint8Array(circuit.verifyingKeyGnark);
267
+ }
268
+ };
269
+ }
270
+ });
271
+
272
+ // src/infra/provingSystems/Barretenberg.ts
273
+ var Barretenberg_exports = {};
274
+ __export(Barretenberg_exports, {
275
+ Barretenberg: () => Barretenberg
276
+ });
277
+ import { compile as compile2, createFileManager as createFileManager2 } from "@noir-lang/noir_wasm";
278
+ import { Noir as Noir2 } from "@noir-lang/noir_js";
279
+ import { Barretenberg as BarretenbergBackend, UltraHonkBackend } from "@aztec/bb.js";
280
+ function stringToStream2(content) {
281
+ return new ReadableStream({
282
+ start(controller) {
283
+ controller.enqueue(new TextEncoder().encode(content));
284
+ controller.close();
285
+ }
286
+ });
287
+ }
288
+ function isNodeJs3() {
289
+ return typeof globalThis.process !== "undefined" && globalThis.process.versions != null && globalThis.process.versions.node != null;
290
+ }
291
+ async function createTempDir2() {
292
+ if (!isNodeJs3()) {
293
+ return { basePath: "/", cleanup: null };
294
+ }
295
+ const fs = await import("fs/promises");
296
+ const os = await import("os");
297
+ const path = await import("path");
298
+ const basePath = await fs.mkdtemp(path.join(os.tmpdir(), "noir-circuit-"));
299
+ const cleanup = async () => {
300
+ await fs.rm(basePath, { recursive: true, force: true });
301
+ };
302
+ return { basePath, cleanup };
303
+ }
304
+ var Barretenberg;
305
+ var init_Barretenberg = __esm({
306
+ "src/infra/provingSystems/Barretenberg.ts"() {
307
+ "use strict";
308
+ Barretenberg = class {
309
+ async compile(noirCode) {
310
+ const { basePath, cleanup } = await createTempDir2();
311
+ const fm = createFileManager2(basePath);
312
+ const nargoToml = `[package]
313
+ name = "circuit"
314
+ type = "bin"
315
+ authors = [""]
316
+
317
+ [dependencies]
318
+ `;
319
+ try {
320
+ if (isNodeJs3()) {
321
+ await fm.writeFile("./src/main.nr", stringToStream2(noirCode));
322
+ await fm.writeFile("./Nargo.toml", stringToStream2(nargoToml));
323
+ } else {
324
+ fm.writeFile("./src/main.nr", stringToStream2(noirCode));
325
+ fm.writeFile("./Nargo.toml", stringToStream2(nargoToml));
326
+ }
327
+ const result = await compile2(fm);
328
+ const compiled = result.program;
329
+ if (!compiled || !compiled.bytecode) {
330
+ throw new Error("Compilation failed: no bytecode generated");
331
+ }
332
+ return compiled;
333
+ } finally {
334
+ if (cleanup) {
335
+ await cleanup();
336
+ }
337
+ }
338
+ }
339
+ async generateProof(circuit, inputs) {
340
+ const noir = new Noir2(circuit);
341
+ const { witness } = await noir.execute(inputs);
342
+ const barretenberg = await BarretenbergBackend.new({ threads: 1 });
343
+ const backend = new UltraHonkBackend(circuit.bytecode, barretenberg);
344
+ try {
345
+ const proofData = await backend.generateProof(witness);
346
+ return {
347
+ proof: proofData.proof,
348
+ publicInputs: proofData.publicInputs || []
349
+ };
350
+ } finally {
351
+ await barretenberg.destroy();
352
+ }
353
+ }
354
+ async verifyProof(circuit, proof, publicInputs) {
355
+ const barretenberg = await BarretenbergBackend.new({ threads: 1 });
356
+ const backend = new UltraHonkBackend(circuit.bytecode, barretenberg);
357
+ try {
358
+ return await backend.verifyProof({ proof, publicInputs });
359
+ } finally {
360
+ await barretenberg.destroy();
361
+ }
362
+ }
363
+ };
364
+ }
365
+ });
366
+
367
+ // src/infra/chainFormatters/SolanaFormatter.ts
368
+ var SolanaFormatter_exports = {};
369
+ __export(SolanaFormatter_exports, {
370
+ SolanaFormatter: () => SolanaFormatter
371
+ });
372
+ var G1_SIZE, G2_SIZE, SolanaFormatter;
373
+ var init_SolanaFormatter = __esm({
374
+ "src/infra/chainFormatters/SolanaFormatter.ts"() {
375
+ "use strict";
376
+ G1_SIZE = 64;
377
+ G2_SIZE = 128;
378
+ SolanaFormatter = class {
379
+ constructor(arkworksProvider) {
380
+ this.arkworksProvider = arkworksProvider;
381
+ }
382
+ chainId = "solana";
383
+ /**
384
+ * Format a generic proof for Solana on-chain verification.
385
+ *
386
+ * @param proofData - Generic proof data from Arkworks
387
+ * @param circuit - The compiled circuit (must be Arkworks circuit)
388
+ * @param metadata - Circuit metadata with public input count
389
+ * @returns SolanaProofData ready for on-chain verification
390
+ */
391
+ async formatProof(proofData, circuit, metadata) {
392
+ const vkBytes = await this.arkworksProvider.getVerifyingKeyGnark(circuit);
393
+ const vkBase64 = this.uint8ArrayToBase64(vkBytes);
394
+ const nrPublicInputs = metadata.numPublicInputs;
395
+ const publicInputsBytes = proofData.publicInputs.map((input) => {
396
+ const hex = input.startsWith("0x") ? input.slice(2) : input;
397
+ return this.hexToBytes(hex.padStart(64, "0"));
398
+ });
399
+ const { accountSize, estimatedRent } = this.getChainMetadata(nrPublicInputs);
400
+ return {
401
+ verifyingKey: {
402
+ base64: vkBase64,
403
+ bytes: vkBytes,
404
+ nrPublicInputs
405
+ },
406
+ proof: {
407
+ base64: this.uint8ArrayToBase64(proofData.proof),
408
+ bytes: proofData.proof
409
+ },
410
+ publicInputs: {
411
+ hex: proofData.publicInputs,
412
+ bytes: publicInputsBytes
413
+ },
414
+ accountSize,
415
+ estimatedRent
416
+ };
417
+ }
418
+ /**
419
+ * Get Solana-specific metadata for a circuit.
420
+ *
421
+ * @param publicInputCount - Number of public inputs in the circuit
422
+ * @returns Solana metadata with account size and rent estimates
423
+ */
424
+ getChainMetadata(publicInputCount) {
425
+ const accountSize = this.calculateVkAccountSize(publicInputCount);
426
+ const estimatedRent = this.calculateVkAccountRent(publicInputCount);
427
+ return {
428
+ chainId: "solana",
429
+ accountSize,
430
+ estimatedRent
431
+ };
432
+ }
433
+ /**
434
+ * Calculate the size of a VK account for a given number of public inputs.
435
+ * Matches the Rust `vk_account_size` function in the Solana program.
436
+ */
437
+ calculateVkAccountSize(nrPublicInputs) {
438
+ const fixedSize = 8 + 32 + 1 + G1_SIZE + G2_SIZE * 3 + 4;
439
+ return fixedSize + (nrPublicInputs + 1) * G1_SIZE;
440
+ }
441
+ /**
442
+ * Calculate the minimum rent for a VK account.
443
+ */
444
+ calculateVkAccountRent(nrPublicInputs, rentExemptionPerByte = 6960) {
445
+ const size = this.calculateVkAccountSize(nrPublicInputs);
446
+ return size * rentExemptionPerByte;
447
+ }
448
+ /**
449
+ * Convert Uint8Array to base64 string.
450
+ */
451
+ uint8ArrayToBase64(bytes) {
452
+ if (typeof btoa === "function") {
453
+ let binary = "";
454
+ for (let i = 0; i < bytes.length; i++) {
455
+ binary += String.fromCharCode(bytes[i]);
456
+ }
457
+ return btoa(binary);
458
+ }
459
+ return Buffer.from(bytes).toString("base64");
460
+ }
461
+ /**
462
+ * Convert hex string to Uint8Array.
463
+ */
464
+ hexToBytes(hex) {
465
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
466
+ const bytes = new Uint8Array(cleanHex.length / 2);
467
+ for (let i = 0; i < bytes.length; i++) {
468
+ bytes[i] = parseInt(cleanHex.substring(i * 2, i * 2 + 2), 16);
469
+ }
470
+ return bytes;
471
+ }
472
+ };
473
+ }
474
+ });
475
+
476
+ // src/providers/arkworks.ts
477
+ init_ArkworksWasm();
478
+
479
+ // src/domain/types/provider.ts
480
+ var Provider = /* @__PURE__ */ ((Provider2) => {
481
+ Provider2["Barretenberg"] = "barretenberg";
482
+ Provider2["Arkworks"] = "arkworks";
483
+ Provider2["Sunspot"] = "sunspot";
484
+ return Provider2;
485
+ })(Provider || {});
486
+
487
+ // src/infra/wasm/wasmInit.ts
488
+ var wasmInitPromise2 = null;
489
+ var wasmInitialized = false;
490
+ function isNodeJs2() {
491
+ return typeof globalThis.process !== "undefined" && globalThis.process.versions != null && globalThis.process.versions.node != null;
492
+ }
493
+ async function initNoirWasm() {
494
+ if (wasmInitialized) return;
495
+ if (!wasmInitPromise2) {
496
+ wasmInitPromise2 = initWasmInternal();
497
+ }
498
+ await wasmInitPromise2;
499
+ wasmInitialized = true;
500
+ }
501
+ async function initWasmInternal() {
502
+ if (isNodeJs2()) {
503
+ await import("@noir-lang/acvm_js/nodejs/acvm_js.js");
504
+ await import("@noir-lang/noirc_abi/nodejs/noirc_abi_wasm.js");
505
+ } else {
506
+ const [{ default: initACVM }, { default: initNoirC }] = await Promise.all([
507
+ import("@noir-lang/acvm_js"),
508
+ import("@noir-lang/noirc_abi")
509
+ ]);
510
+ await Promise.all([initACVM(), initNoirC()]);
511
+ }
512
+ }
513
+ function isWasmInitialized() {
514
+ return wasmInitialized;
515
+ }
516
+
517
+ // src/IziNoir.ts
518
+ var IziNoir = class _IziNoir {
519
+ provingSystem;
520
+ compiledCircuit = null;
521
+ chainFormatters = /* @__PURE__ */ new Map();
522
+ chain;
523
+ _verifyingKey;
524
+ _lastProof;
525
+ constructor(provingSystem, chain) {
526
+ this.provingSystem = provingSystem;
527
+ this.chain = chain;
528
+ }
529
+ /**
530
+ * Get the verifying key from the last proof generation.
531
+ * Only available after calling prove() with a chain configured.
532
+ */
533
+ get vk() {
534
+ return this._verifyingKey;
535
+ }
536
+ /**
537
+ * Get the configured chain, if any.
538
+ */
539
+ get targetChain() {
540
+ return this.chain;
541
+ }
542
+ /**
543
+ * Check if operating in offchain mode (no chain configured).
544
+ */
545
+ get isOffchain() {
546
+ return this.chain === void 0;
547
+ }
548
+ /**
549
+ * Register a chain formatter for chain-specific proof formatting.
550
+ *
551
+ * @param formatter - The chain formatter to register
552
+ */
553
+ registerChainFormatter(formatter) {
554
+ this.chainFormatters.set(formatter.chainId, formatter);
555
+ }
556
+ /**
557
+ * Get a registered chain formatter.
558
+ *
559
+ * @param chainId - The chain ID to get the formatter for
560
+ * @returns The formatter or undefined if not registered
561
+ */
562
+ getChainFormatter(chainId) {
563
+ return this.chainFormatters.get(chainId);
564
+ }
565
+ /**
566
+ * Initialize IziNoir with the specified provider and optional chain.
567
+ *
568
+ * @param config - Configuration specifying the provider, chain, and optional circuit paths
569
+ * @returns Initialized IziNoir instance
570
+ *
571
+ * @example
572
+ * ```typescript
573
+ * // On-chain mode (Solana)
574
+ * const izi = await IziNoir.init({
575
+ * provider: Provider.Arkworks,
576
+ * chain: Chain.Solana
577
+ * });
578
+ *
579
+ * // Offchain mode (no chain formatting)
580
+ * const iziOffchain = await IziNoir.init({
581
+ * provider: Provider.Arkworks
582
+ * });
583
+ *
584
+ * // Barretenberg (browser-compatible, ~16KB proofs, offchain only)
585
+ * const bb = await IziNoir.init({ provider: Provider.Barretenberg });
586
+ * ```
587
+ */
588
+ static async init(config) {
589
+ await initNoirWasm();
590
+ let provingSystem;
591
+ switch (config.provider) {
592
+ case "barretenberg" /* Barretenberg */: {
593
+ if (config.chain) {
594
+ throw new Error(
595
+ "Barretenberg provider does not support chain formatting. Use Provider.Arkworks for on-chain proofs."
596
+ );
597
+ }
598
+ const { Barretenberg: Barretenberg2 } = await Promise.resolve().then(() => (init_Barretenberg(), Barretenberg_exports));
599
+ provingSystem = new Barretenberg2();
600
+ return new _IziNoir(provingSystem);
601
+ }
602
+ case "arkworks" /* Arkworks */: {
603
+ const { ArkworksWasm: ArkworksWasm2 } = await Promise.resolve().then(() => (init_ArkworksWasm(), ArkworksWasm_exports));
604
+ const arkworksInstance = new ArkworksWasm2();
605
+ provingSystem = arkworksInstance;
606
+ const instance = new _IziNoir(provingSystem, config.chain);
607
+ if (config.chain === "solana" /* Solana */ || !config.chain) {
608
+ const { SolanaFormatter: SolanaFormatter2 } = await Promise.resolve().then(() => (init_SolanaFormatter(), SolanaFormatter_exports));
609
+ instance.registerChainFormatter(new SolanaFormatter2(arkworksInstance));
610
+ }
611
+ return instance;
612
+ }
613
+ case "sunspot" /* Sunspot */: {
614
+ throw new Error(
615
+ 'Sunspot is not available in the main entry point. Import from "@izi-noir/sdk/sunspot" for Sunspot support.'
616
+ );
617
+ }
618
+ default:
619
+ throw new Error(`Unknown provider: ${config.provider}`);
620
+ }
621
+ }
622
+ /**
623
+ * Get the underlying proving system instance.
624
+ * Useful for advanced use cases.
625
+ */
626
+ getProvingSystem() {
627
+ return this.provingSystem;
628
+ }
629
+ /**
630
+ * Get the currently compiled circuit, if any.
631
+ */
632
+ getCompiledCircuit() {
633
+ return this.compiledCircuit;
634
+ }
635
+ /**
636
+ * Compile Noir code into a circuit.
637
+ *
638
+ * @param noirCode - The Noir source code to compile
639
+ * @returns The compiled circuit
640
+ */
641
+ async compile(noirCode) {
642
+ this.compiledCircuit = await this.provingSystem.compile(noirCode);
643
+ return this.compiledCircuit;
644
+ }
645
+ /**
646
+ * Generate a proof for the given inputs.
647
+ *
648
+ * If a chain is configured, returns chain-formatted proof data and stores
649
+ * the verifying key in `this.vk`. Otherwise, returns raw proof data.
650
+ *
651
+ * @param inputs - The inputs (both public and private) for the circuit
652
+ * @param circuit - Optional circuit to use (defaults to last compiled circuit)
653
+ * @returns The proof data - type depends on configured chain
654
+ * @throws Error if no circuit is available
655
+ *
656
+ * @example
657
+ * ```typescript
658
+ * // With chain configured - returns SolanaProofData
659
+ * const izi = await IziNoir.init({ provider: Provider.Arkworks, chain: Chain.Solana });
660
+ * await izi.compile(noirCode);
661
+ * const proof = await izi.prove({ expected: '100', secret: '10' });
662
+ * // proof is SolanaProofData, izi.vk is available
663
+ *
664
+ * // Offchain mode - returns ProofData
665
+ * const iziOffchain = await IziNoir.init({ provider: Provider.Arkworks });
666
+ * await iziOffchain.compile(noirCode);
667
+ * const rawProof = await iziOffchain.prove({ expected: '100', secret: '10' });
668
+ * // rawProof is ProofData, iziOffchain.vk is undefined
669
+ * ```
670
+ */
671
+ async prove(inputs, circuit) {
672
+ const circuitToUse = circuit || this.compiledCircuit;
673
+ if (!circuitToUse) {
674
+ throw new Error("No circuit available. Call compile() first or provide a circuit.");
675
+ }
676
+ const rawProof = await this.provingSystem.generateProof(circuitToUse, inputs);
677
+ if (!this.chain) {
678
+ this._lastProof = rawProof;
679
+ return rawProof;
680
+ }
681
+ const formatter = this.chainFormatters.get(this.chain);
682
+ if (!formatter) {
683
+ throw new Error(
684
+ `No formatter registered for chain: ${this.chain}. This is an internal error - please report it.`
685
+ );
686
+ }
687
+ const metadata = {
688
+ numPublicInputs: rawProof.publicInputs.length
689
+ };
690
+ const formattedProof = await formatter.formatProof(rawProof, circuitToUse, metadata);
691
+ const chainProof = formattedProof;
692
+ this._verifyingKey = chainProof.verifyingKey;
693
+ this._lastProof = chainProof;
694
+ return chainProof;
695
+ }
696
+ /**
697
+ * Verify a proof.
698
+ * Available in both on-chain and offchain modes.
699
+ *
700
+ * @param proof - The proof bytes to verify
701
+ * @param publicInputs - The public inputs that were used
702
+ * @param circuit - Optional circuit to use (defaults to last compiled circuit)
703
+ * @returns true if the proof is valid, false otherwise
704
+ * @throws Error if no circuit is available
705
+ */
706
+ async verify(proof, publicInputs, circuit) {
707
+ const circuitToUse = circuit || this.compiledCircuit;
708
+ if (!circuitToUse) {
709
+ throw new Error("No circuit available. Call compile() first or provide a circuit.");
710
+ }
711
+ return this.provingSystem.verifyProof(circuitToUse, proof, publicInputs);
712
+ }
713
+ /**
714
+ * Convenience method: compile, prove, and verify in one call.
715
+ *
716
+ * @param noirCode - The Noir source code to compile
717
+ * @param inputs - The inputs (both public and private) for the circuit
718
+ * @returns Object containing proof data and verification result
719
+ *
720
+ * @example
721
+ * ```typescript
722
+ * const { proof, verified } = await izi.createProof(noirCode, {
723
+ * x: '100',
724
+ * y: '10',
725
+ * });
726
+ * console.log(`Verified: ${verified}`);
727
+ * ```
728
+ */
729
+ async createProof(noirCode, inputs) {
730
+ const circuit = await this.compile(noirCode);
731
+ const proof = await this.prove(inputs, circuit);
732
+ const proofBytes = "proof" in proof && proof.proof instanceof Uint8Array ? proof.proof : proof.proof.bytes;
733
+ const pubInputs = Array.isArray(proof.publicInputs) ? proof.publicInputs : proof.publicInputs.hex;
734
+ const verified = await this.verify(proofBytes, pubInputs, circuit);
735
+ return { proof, verified };
736
+ }
737
+ /**
738
+ * Get deployment data for the verifying key.
739
+ * Returns the data needed to deploy to the configured blockchain.
740
+ * Use with SolanaTransactionBuilder to build and send the transaction.
741
+ *
742
+ * @param options - Optional configuration
743
+ * @returns Deployment data that can be used with SolanaTransactionBuilder
744
+ * @throws Error if no chain is configured (offchain mode)
745
+ * @throws Error if prove() hasn't been called yet
746
+ *
747
+ * @example
748
+ * ```typescript
749
+ * const izi = await IziNoir.init({ provider: Provider.Arkworks, chain: Chain.Solana });
750
+ * await izi.compile(noirCode);
751
+ * await izi.prove(inputs);
752
+ *
753
+ * // Get deployment data
754
+ * const deployData = izi.getDeployData();
755
+ *
756
+ * // Use with SolanaTransactionBuilder in your frontend
757
+ * const builder = new SolanaTransactionBuilder({ programId: deployData.programId });
758
+ * const { initVk, rentLamports, accountSize } = builder.buildInitAndVerifyInstructions(
759
+ * deployData.proofData,
760
+ * vkAccountPubkey,
761
+ * authority,
762
+ * payer
763
+ * );
764
+ * ```
765
+ */
766
+ getDeployData(options) {
767
+ if (!this.chain) {
768
+ throw new Error("Cannot deploy in offchain mode. Initialize with a chain parameter.");
769
+ }
770
+ if (!this._verifyingKey || !this._lastProof) {
771
+ throw new Error("Must call prove() before getDeployData().");
772
+ }
773
+ if (this.chain !== "solana" /* Solana */) {
774
+ throw new Error(`Deployment for ${this.chain} is not yet supported.`);
775
+ }
776
+ return {
777
+ proofData: this._lastProof,
778
+ programId: options?.programId ?? "EYhRED7EuMyyVjx57aDXUD9h6ArnEKng64qtz8999KrS",
779
+ computeUnits: options?.computeUnits ?? 4e5
780
+ };
781
+ }
782
+ };
783
+ export {
784
+ ArkworksWasm,
785
+ IziNoir,
786
+ Provider,
787
+ initNoirWasm,
788
+ isArkworksCircuit,
789
+ isWasmInitialized
790
+ };
791
+ //# sourceMappingURL=arkworks.js.map