zkenclave-sdk 0.1.6 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -17,6 +17,7 @@ interface WithdrawalRequest {
17
17
  merkleRoot?: Uint8Array;
18
18
  merklePath: Uint8Array[];
19
19
  pathIndices: boolean[];
20
+ secret?: Uint8Array;
20
21
  }
21
22
  interface WithdrawalResult {
22
23
  success: boolean;
@@ -92,11 +93,9 @@ declare class ZKProofClient {
92
93
  private loadWasm;
93
94
  generateWithdrawalProof(request: WithdrawalRequest): Promise<WithdrawalResult>;
94
95
  private generateRealProof;
95
- private generateFallbackProof;
96
- generateComplianceProof(commitment: Uint8Array, associationRoot: Uint8Array): Promise<ComplianceProof>;
96
+ generateComplianceProof(commitment: Uint8Array, associationPath: Uint8Array[], pathIndices: boolean[], associationRoot: Uint8Array): Promise<ComplianceProof>;
97
97
  verifyProof(proofResult: WithdrawalResult): Promise<boolean>;
98
98
  isWasmReady(): boolean;
99
- private computeNullifierHash;
100
99
  private addressToBytes;
101
100
  private hexToBytes;
102
101
  }
@@ -113,7 +112,7 @@ declare class PrivacyVaultSDK {
113
112
  constructor(config: VaultConfig, signer?: ethers.Signer, zkClient?: ZKProofClient);
114
113
  connect(signer: ethers.Signer): Promise<void>;
115
114
  deposit(amount: bigint): Promise<DepositResult>;
116
- withdraw(note: DepositNote, recipient: string): Promise<WithdrawalResult>;
115
+ withdraw(note: DepositNote, recipient: string, complianceProof?: Uint8Array): Promise<WithdrawalResult>;
117
116
  getLatestRoot(): Promise<Uint8Array>;
118
117
  getNextLeafIndex(): Promise<number>;
119
118
  isNullifierUsed(nullifier: Uint8Array): Promise<boolean>;
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ interface WithdrawalRequest {
17
17
  merkleRoot?: Uint8Array;
18
18
  merklePath: Uint8Array[];
19
19
  pathIndices: boolean[];
20
+ secret?: Uint8Array;
20
21
  }
21
22
  interface WithdrawalResult {
22
23
  success: boolean;
@@ -92,11 +93,9 @@ declare class ZKProofClient {
92
93
  private loadWasm;
93
94
  generateWithdrawalProof(request: WithdrawalRequest): Promise<WithdrawalResult>;
94
95
  private generateRealProof;
95
- private generateFallbackProof;
96
- generateComplianceProof(commitment: Uint8Array, associationRoot: Uint8Array): Promise<ComplianceProof>;
96
+ generateComplianceProof(commitment: Uint8Array, associationPath: Uint8Array[], pathIndices: boolean[], associationRoot: Uint8Array): Promise<ComplianceProof>;
97
97
  verifyProof(proofResult: WithdrawalResult): Promise<boolean>;
98
98
  isWasmReady(): boolean;
99
- private computeNullifierHash;
100
99
  private addressToBytes;
101
100
  private hexToBytes;
102
101
  }
@@ -113,7 +112,7 @@ declare class PrivacyVaultSDK {
113
112
  constructor(config: VaultConfig, signer?: ethers.Signer, zkClient?: ZKProofClient);
114
113
  connect(signer: ethers.Signer): Promise<void>;
115
114
  deposit(amount: bigint): Promise<DepositResult>;
116
- withdraw(note: DepositNote, recipient: string): Promise<WithdrawalResult>;
115
+ withdraw(note: DepositNote, recipient: string, complianceProof?: Uint8Array): Promise<WithdrawalResult>;
117
116
  getLatestRoot(): Promise<Uint8Array>;
118
117
  getNextLeafIndex(): Promise<number>;
119
118
  isNullifierUsed(nullifier: Uint8Array): Promise<boolean>;
package/dist/index.js CHANGED
@@ -426,33 +426,28 @@ var ZKProofClient = class {
426
426
  wasmReady = false;
427
427
  constructor(config) {
428
428
  this.config = config ?? { useRealProofs: true };
429
- if (this.config.useRealProofs) {
430
- this.loadWasm();
431
- }
429
+ this.loadWasm();
432
430
  }
433
431
  async loadWasm() {
434
432
  if (wasmModule) {
435
433
  this.wasmReady = true;
436
434
  return;
437
435
  }
438
- try {
439
- const wasmPath = this.config.wasmPath ?? "zkenclave-circuits";
440
- const module2 = await import(
441
- /* webpackIgnore: true */
442
- wasmPath
443
- );
444
- wasmModule = module2;
445
- this.wasmReady = true;
446
- } catch {
447
- console.warn("WASM module not available, falling back to mock proofs");
448
- this.wasmReady = false;
449
- }
436
+ const wasmPath = this.config.wasmPath ?? "zkenclave-circuits";
437
+ const module2 = await import(
438
+ /* webpackIgnore: true */
439
+ wasmPath
440
+ );
441
+ wasmModule = module2;
442
+ this.wasmReady = true;
450
443
  }
451
444
  async generateWithdrawalProof(request) {
452
- if (this.config.useRealProofs && this.wasmReady && wasmModule) {
453
- return this.generateRealProof(request);
445
+ if (!this.wasmReady || !wasmModule) {
446
+ throw new Error(
447
+ "WASM module not loaded. Make sure zkenclave-circuits is properly installed and configured."
448
+ );
454
449
  }
455
- return this.generateFallbackProof(request);
450
+ return this.generateRealProof(request);
456
451
  }
457
452
  async generateRealProof(request) {
458
453
  const wasmRequest = {
@@ -480,62 +475,51 @@ var ZKProofClient = class {
480
475
  timestamp: Date.now()
481
476
  };
482
477
  }
483
- async generateFallbackProof(request) {
484
- const nullifierHash = this.computeNullifierHash(
485
- request.nullifier,
486
- request.leafIndex
487
- );
488
- const merkleRoot = request.merkleRoot ?? new Uint8Array(32);
489
- const proof = new Uint8Array(256);
490
- proof[0] = 1;
491
- const amountHex = (0, import_ethers2.toBeHex)(request.amount, 32);
492
- const amountBytes = this.hexToBytes(amountHex);
493
- proof.set(amountBytes.slice(0, 32), 1);
494
- proof.set(request.commitment.slice(0, 32), 33);
495
- proof[250] = 90;
496
- proof[251] = 75;
497
- return {
498
- success: true,
499
- zkProof: proof,
500
- nullifierHash,
501
- merkleRoot,
502
- timestamp: Date.now()
478
+ async generateComplianceProof(commitment, associationPath, pathIndices, associationRoot) {
479
+ if (!this.wasmReady || !wasmModule) {
480
+ throw new Error(
481
+ "WASM module not loaded. Make sure zkenclave-circuits is properly installed and configured."
482
+ );
483
+ }
484
+ const request = {
485
+ commitment: Array.from(commitment),
486
+ association_path: associationPath.map((p) => Array.from(p)),
487
+ path_indices: pathIndices,
488
+ association_root: Array.from(associationRoot)
503
489
  };
504
- }
505
- async generateComplianceProof(commitment, associationRoot) {
506
- const proofId = (0, import_ethers2.keccak256)(
507
- new Uint8Array([...commitment, ...associationRoot])
490
+ const resultJson = wasmModule.generate_compliance_proof(
491
+ JSON.stringify(request)
508
492
  );
493
+ const result = JSON.parse(resultJson);
494
+ if (!result.success) {
495
+ throw new Error(`Compliance proof generation failed: ${result.error}`);
496
+ }
509
497
  return {
510
- id: proofId,
498
+ id: (0, import_ethers2.keccak256)(new Uint8Array(result.proof)),
511
499
  associationRoot,
512
500
  timestamp: Date.now(),
513
501
  valid: true,
514
- proof: new Uint8Array(256)
502
+ proof: new Uint8Array(result.proof)
515
503
  };
516
504
  }
517
505
  async verifyProof(proofResult) {
518
- if (this.wasmReady && wasmModule) {
519
- const proofJson = JSON.stringify({
520
- success: proofResult.success,
521
- proof: Array.from(proofResult.zkProof),
522
- nullifier_hash: Array.from(proofResult.nullifierHash),
523
- public_inputs: [],
524
- error: null
525
- });
526
- return wasmModule.verify_withdrawal_proof(proofJson);
506
+ if (!this.wasmReady || !wasmModule) {
507
+ throw new Error(
508
+ "WASM module not loaded. Make sure zkenclave-circuits is properly installed and configured."
509
+ );
527
510
  }
528
- return proofResult.success && proofResult.zkProof.length > 0 && proofResult.zkProof[250] === 90 && proofResult.zkProof[251] === 75;
511
+ const proofJson = JSON.stringify({
512
+ success: proofResult.success,
513
+ proof: Array.from(proofResult.zkProof),
514
+ nullifier_hash: Array.from(proofResult.nullifierHash),
515
+ public_inputs: [],
516
+ error: null
517
+ });
518
+ return wasmModule.verify_withdrawal_proof(proofJson);
529
519
  }
530
520
  isWasmReady() {
531
521
  return this.wasmReady;
532
522
  }
533
- computeNullifierHash(nullifier, leafIndex) {
534
- const indexBytes = new TextEncoder().encode(leafIndex.toString());
535
- const combined = new Uint8Array([...nullifier, ...indexBytes]);
536
- const hash = (0, import_ethers2.keccak256)(combined);
537
- return this.hexToBytes(hash);
538
- }
539
523
  addressToBytes(address) {
540
524
  const clean = address.startsWith("0x") ? address.slice(2) : address;
541
525
  const bytes = [];
@@ -632,7 +616,7 @@ var PrivacyVaultSDK = class {
632
616
  note
633
617
  };
634
618
  }
635
- async withdraw(note, recipient) {
619
+ async withdraw(note, recipient, complianceProof) {
636
620
  if (!this.signer) {
637
621
  throw new Error("Signer required for withdrawals");
638
622
  }
@@ -651,7 +635,8 @@ var PrivacyVaultSDK = class {
651
635
  leafIndex: note.leafIndex,
652
636
  merkleRoot: root,
653
637
  merklePath: [],
654
- pathIndices: []
638
+ pathIndices: [],
639
+ secret: note.secret
655
640
  });
656
641
  const tx = await this.vault.withdraw(
657
642
  bytesToHex(nullifierHash),
@@ -659,7 +644,7 @@ var PrivacyVaultSDK = class {
659
644
  recipient,
660
645
  note.amount,
661
646
  zkProofResult.zkProof,
662
- new Uint8Array(64),
647
+ complianceProof || new Uint8Array(64),
663
648
  { gasLimit: DEFAULT_GAS_LIMIT }
664
649
  );
665
650
  const receipt = await tx.wait();
package/dist/index.mjs CHANGED
@@ -365,40 +365,35 @@ var MerkleTree = class {
365
365
  };
366
366
 
367
367
  // src/zk-client.ts
368
- import { keccak256 as keccak2562, toBeHex } from "ethers";
368
+ import { keccak256 as keccak2562 } from "ethers";
369
369
  var wasmModule = null;
370
370
  var ZKProofClient = class {
371
371
  config;
372
372
  wasmReady = false;
373
373
  constructor(config) {
374
374
  this.config = config ?? { useRealProofs: true };
375
- if (this.config.useRealProofs) {
376
- this.loadWasm();
377
- }
375
+ this.loadWasm();
378
376
  }
379
377
  async loadWasm() {
380
378
  if (wasmModule) {
381
379
  this.wasmReady = true;
382
380
  return;
383
381
  }
384
- try {
385
- const wasmPath = this.config.wasmPath ?? "zkenclave-circuits";
386
- const module = await import(
387
- /* webpackIgnore: true */
388
- wasmPath
389
- );
390
- wasmModule = module;
391
- this.wasmReady = true;
392
- } catch {
393
- console.warn("WASM module not available, falling back to mock proofs");
394
- this.wasmReady = false;
395
- }
382
+ const wasmPath = this.config.wasmPath ?? "zkenclave-circuits";
383
+ const module = await import(
384
+ /* webpackIgnore: true */
385
+ wasmPath
386
+ );
387
+ wasmModule = module;
388
+ this.wasmReady = true;
396
389
  }
397
390
  async generateWithdrawalProof(request) {
398
- if (this.config.useRealProofs && this.wasmReady && wasmModule) {
399
- return this.generateRealProof(request);
391
+ if (!this.wasmReady || !wasmModule) {
392
+ throw new Error(
393
+ "WASM module not loaded. Make sure zkenclave-circuits is properly installed and configured."
394
+ );
400
395
  }
401
- return this.generateFallbackProof(request);
396
+ return this.generateRealProof(request);
402
397
  }
403
398
  async generateRealProof(request) {
404
399
  const wasmRequest = {
@@ -426,62 +421,51 @@ var ZKProofClient = class {
426
421
  timestamp: Date.now()
427
422
  };
428
423
  }
429
- async generateFallbackProof(request) {
430
- const nullifierHash = this.computeNullifierHash(
431
- request.nullifier,
432
- request.leafIndex
433
- );
434
- const merkleRoot = request.merkleRoot ?? new Uint8Array(32);
435
- const proof = new Uint8Array(256);
436
- proof[0] = 1;
437
- const amountHex = toBeHex(request.amount, 32);
438
- const amountBytes = this.hexToBytes(amountHex);
439
- proof.set(amountBytes.slice(0, 32), 1);
440
- proof.set(request.commitment.slice(0, 32), 33);
441
- proof[250] = 90;
442
- proof[251] = 75;
443
- return {
444
- success: true,
445
- zkProof: proof,
446
- nullifierHash,
447
- merkleRoot,
448
- timestamp: Date.now()
424
+ async generateComplianceProof(commitment, associationPath, pathIndices, associationRoot) {
425
+ if (!this.wasmReady || !wasmModule) {
426
+ throw new Error(
427
+ "WASM module not loaded. Make sure zkenclave-circuits is properly installed and configured."
428
+ );
429
+ }
430
+ const request = {
431
+ commitment: Array.from(commitment),
432
+ association_path: associationPath.map((p) => Array.from(p)),
433
+ path_indices: pathIndices,
434
+ association_root: Array.from(associationRoot)
449
435
  };
450
- }
451
- async generateComplianceProof(commitment, associationRoot) {
452
- const proofId = keccak2562(
453
- new Uint8Array([...commitment, ...associationRoot])
436
+ const resultJson = wasmModule.generate_compliance_proof(
437
+ JSON.stringify(request)
454
438
  );
439
+ const result = JSON.parse(resultJson);
440
+ if (!result.success) {
441
+ throw new Error(`Compliance proof generation failed: ${result.error}`);
442
+ }
455
443
  return {
456
- id: proofId,
444
+ id: keccak2562(new Uint8Array(result.proof)),
457
445
  associationRoot,
458
446
  timestamp: Date.now(),
459
447
  valid: true,
460
- proof: new Uint8Array(256)
448
+ proof: new Uint8Array(result.proof)
461
449
  };
462
450
  }
463
451
  async verifyProof(proofResult) {
464
- if (this.wasmReady && wasmModule) {
465
- const proofJson = JSON.stringify({
466
- success: proofResult.success,
467
- proof: Array.from(proofResult.zkProof),
468
- nullifier_hash: Array.from(proofResult.nullifierHash),
469
- public_inputs: [],
470
- error: null
471
- });
472
- return wasmModule.verify_withdrawal_proof(proofJson);
452
+ if (!this.wasmReady || !wasmModule) {
453
+ throw new Error(
454
+ "WASM module not loaded. Make sure zkenclave-circuits is properly installed and configured."
455
+ );
473
456
  }
474
- return proofResult.success && proofResult.zkProof.length > 0 && proofResult.zkProof[250] === 90 && proofResult.zkProof[251] === 75;
457
+ const proofJson = JSON.stringify({
458
+ success: proofResult.success,
459
+ proof: Array.from(proofResult.zkProof),
460
+ nullifier_hash: Array.from(proofResult.nullifierHash),
461
+ public_inputs: [],
462
+ error: null
463
+ });
464
+ return wasmModule.verify_withdrawal_proof(proofJson);
475
465
  }
476
466
  isWasmReady() {
477
467
  return this.wasmReady;
478
468
  }
479
- computeNullifierHash(nullifier, leafIndex) {
480
- const indexBytes = new TextEncoder().encode(leafIndex.toString());
481
- const combined = new Uint8Array([...nullifier, ...indexBytes]);
482
- const hash = keccak2562(combined);
483
- return this.hexToBytes(hash);
484
- }
485
469
  addressToBytes(address) {
486
470
  const clean = address.startsWith("0x") ? address.slice(2) : address;
487
471
  const bytes = [];
@@ -578,7 +562,7 @@ var PrivacyVaultSDK = class {
578
562
  note
579
563
  };
580
564
  }
581
- async withdraw(note, recipient) {
565
+ async withdraw(note, recipient, complianceProof) {
582
566
  if (!this.signer) {
583
567
  throw new Error("Signer required for withdrawals");
584
568
  }
@@ -597,7 +581,8 @@ var PrivacyVaultSDK = class {
597
581
  leafIndex: note.leafIndex,
598
582
  merkleRoot: root,
599
583
  merklePath: [],
600
- pathIndices: []
584
+ pathIndices: [],
585
+ secret: note.secret
601
586
  });
602
587
  const tx = await this.vault.withdraw(
603
588
  bytesToHex(nullifierHash),
@@ -605,7 +590,7 @@ var PrivacyVaultSDK = class {
605
590
  recipient,
606
591
  note.amount,
607
592
  zkProofResult.zkProof,
608
- new Uint8Array(64),
593
+ complianceProof || new Uint8Array(64),
609
594
  { gasLimit: DEFAULT_GAS_LIMIT }
610
595
  );
611
596
  const receipt = await tx.wait();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zkenclave-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.17",
4
4
  "description": "TypeScript SDK for privacy-preserving vault withdrawals with ZK proofs",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",