@veil-cash/sdk 0.6.3 → 0.6.4

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.js CHANGED
@@ -1,21 +1,15 @@
1
1
  import { ethers } from 'ethers';
2
+ import { Buffer } from 'buffer';
2
3
  import { privateKeyToAccount, privateKeyToAddress } from 'viem/accounts';
3
- import * as crypto from 'crypto';
4
+ import ethSigUtil from 'eth-sig-util';
5
+ import circomlib from 'circomlib';
4
6
  import { encodeFunctionData, parseEther, parseUnits, createPublicClient, http, formatUnits, keccak256, encodePacked, isAddress, formatEther } from 'viem';
5
7
  import { base } from 'viem/chains';
6
8
  import MerkleTree from 'fixed-merkle-tree-legacy';
7
9
  import { groth16 } from 'snarkjs';
8
- import * as path from 'path';
9
- import * as fs from 'fs';
10
- import { fileURLToPath } from 'url';
10
+ import { utils } from 'ffjavascript';
11
11
 
12
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
13
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
14
- }) : x)(function(x) {
15
- if (typeof require !== "undefined") return require.apply(this, arguments);
16
- throw Error('Dynamic require of "' + x + '" is not supported');
17
- });
18
- var circomlib = __require("circomlib");
12
+ // src/keypair.ts
19
13
  var poseidon = circomlib.poseidon;
20
14
  var FIELD_SIZE = BigInt(
21
15
  "21888242871839275222246405745257275088548364400416034343698204186575808495617"
@@ -23,7 +17,11 @@ var FIELD_SIZE = BigInt(
23
17
  var poseidonHash = (items) => BigInt(poseidon(items).toString());
24
18
  var poseidonHash2 = (a, b) => poseidonHash([a, b]);
25
19
  var randomBN = (nbytes = 31) => {
26
- const bytes = crypto.randomBytes(nbytes);
20
+ const cryptoApi = globalThis.crypto;
21
+ if (!cryptoApi?.getRandomValues) {
22
+ throw new Error("Secure random number generation is unavailable in this runtime");
23
+ }
24
+ const bytes = cryptoApi.getRandomValues(new Uint8Array(nbytes));
27
25
  let hex = "0x";
28
26
  for (let i = 0; i < bytes.length; i++) {
29
27
  hex += bytes[i].toString(16).padStart(2, "0");
@@ -50,8 +48,7 @@ var toBuffer = (value, length) => {
50
48
  return Buffer.from(hex, "hex");
51
49
  };
52
50
  function getExtDataHash(extData) {
53
- const { ethers: ethers2 } = __require("ethers");
54
- const abi = ethers2.AbiCoder.defaultAbiCoder();
51
+ const abi = ethers.AbiCoder.defaultAbiCoder();
55
52
  const encodedData = abi.encode(
56
53
  ["tuple(address,int256,address,uint256,bytes,bytes)"],
57
54
  [[
@@ -63,7 +60,7 @@ function getExtDataHash(extData) {
63
60
  extData.encryptedOutput2
64
61
  ]]
65
62
  );
66
- const hash = ethers2.keccak256(encodedData);
63
+ const hash = ethers.keccak256(encodedData);
67
64
  return BigInt(hash) % FIELD_SIZE;
68
65
  }
69
66
  function shuffle(array) {
@@ -79,7 +76,6 @@ function shuffle(array) {
79
76
 
80
77
  // src/keypair.ts
81
78
  var VEIL_SIGNED_MESSAGE = "Sign this message to create your Veil Wallet private key. This will be used to decrypt your balances. Ensure you are signing this message on the Veil Cash website.";
82
- var ethSigUtil = __require("eth-sig-util");
83
79
  function packEncryptedMessage(encryptedMessage) {
84
80
  const nonceBuf = Buffer.from(encryptedMessage.nonce, "base64");
85
81
  const ephemPublicKeyBuf = Buffer.from(encryptedMessage.ephemPublicKey, "base64");
@@ -262,8 +258,6 @@ var Keypair = class _Keypair {
262
258
  );
263
259
  }
264
260
  };
265
-
266
- // src/utxo.ts
267
261
  var Utxo = class _Utxo {
268
262
  amount;
269
263
  blinding;
@@ -1456,21 +1450,37 @@ function getMerklePath(tree, commitment) {
1456
1450
  pathIndices: index
1457
1451
  };
1458
1452
  }
1459
- var utils = null;
1460
- try {
1461
- const ffjavascript = __require("ffjavascript");
1462
- utils = ffjavascript.utils;
1463
- } catch {
1464
- console.warn("ffjavascript not found. Proof generation may not work.");
1453
+ var ffUtils = utils;
1454
+ function isBrowserRuntime() {
1455
+ return !(typeof process !== "undefined" && !!process.versions?.node);
1456
+ }
1457
+ function stripTrailingSlash(value) {
1458
+ return value.endsWith("/") ? value.slice(0, -1) : value;
1459
+ }
1460
+ function normalizeCircuitBasePath(provingKeyPath, circuitName) {
1461
+ const resolvedPath = typeof provingKeyPath === "function" ? provingKeyPath(circuitName) : provingKeyPath;
1462
+ const withoutExtension = resolvedPath.replace(/\.(wasm|zkey)$/i, "");
1463
+ if (withoutExtension.endsWith(`/${circuitName}`) || withoutExtension.endsWith(`\\${circuitName}`)) {
1464
+ return withoutExtension;
1465
+ }
1466
+ return `${stripTrailingSlash(withoutExtension)}/${circuitName}`;
1467
+ }
1468
+ function importNodeModule(specifier) {
1469
+ const dynamicImport = new Function("specifier", "return import(specifier)");
1470
+ return dynamicImport(specifier);
1465
1471
  }
1466
- function findKeysDirectory() {
1472
+ async function findNodeKeysDirectory() {
1473
+ const [{ existsSync }, pathModule, { fileURLToPath }] = await Promise.all([
1474
+ importNodeModule("node:fs"),
1475
+ importNodeModule("node:path"),
1476
+ importNodeModule("node:url")
1477
+ ]);
1478
+ const path = pathModule;
1467
1479
  const possiblePaths = [
1468
1480
  // When running from package (installed via npm)
1469
- path.resolve(__dirname, "..", "keys"),
1470
- path.resolve(__dirname, "..", "..", "keys"),
1481
+ path.resolve(process.cwd(), "node_modules", "@veil-cash", "sdk", "keys"),
1471
1482
  // When running from source
1472
1483
  path.resolve(process.cwd(), "keys")
1473
- // ESM module path
1474
1484
  ];
1475
1485
  try {
1476
1486
  const currentFilePath = fileURLToPath(import.meta.url);
@@ -1479,7 +1489,7 @@ function findKeysDirectory() {
1479
1489
  } catch {
1480
1490
  }
1481
1491
  for (const p of possiblePaths) {
1482
- if (fs.existsSync(p) && fs.existsSync(path.join(p, "transaction2.wasm"))) {
1492
+ if (existsSync(p) && existsSync(path.join(p, "transaction2.wasm"))) {
1483
1493
  return p;
1484
1494
  }
1485
1495
  }
@@ -1487,26 +1497,48 @@ function findKeysDirectory() {
1487
1497
  "Circuit keys not found. Expected to find keys/ directory with transaction2.wasm and transaction2.zkey files."
1488
1498
  );
1489
1499
  }
1490
- async function prove(input, circuitName) {
1491
- if (!utils) {
1492
- throw new Error("ffjavascript is required for proof generation. Please install it: npm install ffjavascript");
1500
+ async function resolveProvingKeyPaths(circuitName, provingKeyPath) {
1501
+ if (provingKeyPath) {
1502
+ const circuitBasePath = normalizeCircuitBasePath(provingKeyPath, circuitName);
1503
+ return {
1504
+ wasmPath: `${circuitBasePath}.wasm`,
1505
+ zkeyPath: `${circuitBasePath}.zkey`
1506
+ };
1493
1507
  }
1494
- const keysDir = findKeysDirectory();
1495
- const wasmPath = path.join(keysDir, `${circuitName}.wasm`);
1496
- const zkeyPath = path.join(keysDir, `${circuitName}.zkey`);
1497
- if (!fs.existsSync(wasmPath)) {
1508
+ if (isBrowserRuntime()) {
1509
+ return {
1510
+ wasmPath: `/keys/${circuitName}.wasm`,
1511
+ zkeyPath: `/keys/${circuitName}.zkey`
1512
+ };
1513
+ }
1514
+ const keysDir = await findNodeKeysDirectory();
1515
+ return {
1516
+ wasmPath: `${keysDir}/${circuitName}.wasm`,
1517
+ zkeyPath: `${keysDir}/${circuitName}.zkey`
1518
+ };
1519
+ }
1520
+ async function assertNodeKeyFilesExist(wasmPath, zkeyPath) {
1521
+ if (isBrowserRuntime() || wasmPath.startsWith("http://") || wasmPath.startsWith("https://")) {
1522
+ return;
1523
+ }
1524
+ const { existsSync } = await importNodeModule("node:fs");
1525
+ if (!existsSync(wasmPath)) {
1498
1526
  throw new Error(`Circuit WASM file not found: ${wasmPath}`);
1499
1527
  }
1500
- if (!fs.existsSync(zkeyPath)) {
1528
+ if (!existsSync(zkeyPath)) {
1501
1529
  throw new Error(`Circuit zkey file not found: ${zkeyPath}`);
1502
1530
  }
1531
+ }
1532
+ async function prove(input, circuitName, options = {}) {
1533
+ const { wasmPath, zkeyPath } = await resolveProvingKeyPaths(circuitName, options.provingKeyPath);
1534
+ await assertNodeKeyFilesExist(wasmPath, zkeyPath);
1503
1535
  const result = await groth16.fullProve(
1504
- utils.stringifyBigInts(input),
1536
+ ffUtils.stringifyBigInts(input),
1505
1537
  wasmPath,
1506
1538
  zkeyPath,
1507
1539
  void 0,
1508
1540
  void 0,
1509
- { singleThread: true }
1541
+ { singleThread: options.singleThread ?? true }
1510
1542
  );
1511
1543
  const proof = result.proof;
1512
1544
  return "0x" + toFixedHex(proof.pi_a[0]).slice(2) + toFixedHex(proof.pi_a[1]).slice(2) + toFixedHex(proof.pi_b[0][1]).slice(2) + toFixedHex(proof.pi_b[0][0]).slice(2) + toFixedHex(proof.pi_b[1][1]).slice(2) + toFixedHex(proof.pi_b[1][0]).slice(2) + toFixedHex(proof.pi_c[0]).slice(2) + toFixedHex(proof.pi_c[1]).slice(2);
@@ -1534,7 +1566,8 @@ async function getProof({
1534
1566
  fee,
1535
1567
  recipient,
1536
1568
  relayer,
1537
- onProgress
1569
+ onProgress,
1570
+ provingKeyPath
1538
1571
  }) {
1539
1572
  inputs = shuffle([...inputs]);
1540
1573
  outputs = shuffle([...outputs]);
@@ -1594,7 +1627,7 @@ async function getProof({
1594
1627
  };
1595
1628
  onProgress?.("Generating ZK proof...", `${inputs.length} inputs`);
1596
1629
  const circuitName = selectCircuit(inputs.length);
1597
- const proof = await prove(proofInput, circuitName);
1630
+ const proof = await prove(proofInput, circuitName, { provingKeyPath });
1598
1631
  const args = {
1599
1632
  proof,
1600
1633
  root: toFixedHex(proofInput.root),
@@ -1616,7 +1649,8 @@ async function prepareTransaction({
1616
1649
  fee = 0,
1617
1650
  recipient = 0,
1618
1651
  relayer = 0,
1619
- onProgress
1652
+ onProgress,
1653
+ provingKeyPath
1620
1654
  }) {
1621
1655
  if (inputs.length > 16 || outputs.length > 2) {
1622
1656
  throw new Error("Incorrect inputs/outputs count. Maximum: 16 inputs, 2 outputs.");
@@ -1638,7 +1672,8 @@ async function prepareTransaction({
1638
1672
  fee: BigInt(fee),
1639
1673
  recipient: String(recipient),
1640
1674
  relayer: String(relayer),
1641
- onProgress
1675
+ onProgress,
1676
+ provingKeyPath
1642
1677
  });
1643
1678
  return result;
1644
1679
  }
@@ -1796,6 +1831,7 @@ async function buildWithdrawProof(options) {
1796
1831
  keypair,
1797
1832
  pool = "eth",
1798
1833
  rpcUrl,
1834
+ provingKeyPath,
1799
1835
  onProgress
1800
1836
  } = options;
1801
1837
  const poolConfig = POOL_CONFIG[pool];
@@ -1859,7 +1895,8 @@ async function buildWithdrawProof(options) {
1859
1895
  fee: 0,
1860
1896
  recipient,
1861
1897
  relayer: "0x0000000000000000000000000000000000000000",
1862
- onProgress
1898
+ onProgress,
1899
+ provingKeyPath
1863
1900
  });
1864
1901
  return {
1865
1902
  proofArgs: {
@@ -1956,6 +1993,7 @@ async function buildTransferProof(options) {
1956
1993
  senderKeypair,
1957
1994
  pool = "eth",
1958
1995
  rpcUrl,
1996
+ provingKeyPath,
1959
1997
  onProgress
1960
1998
  } = options;
1961
1999
  const poolConfig = POOL_CONFIG[pool];
@@ -2034,7 +2072,8 @@ async function buildTransferProof(options) {
2034
2072
  fee: 0,
2035
2073
  recipient: "0x0000000000000000000000000000000000000000",
2036
2074
  relayer: "0x0000000000000000000000000000000000000000",
2037
- onProgress
2075
+ onProgress,
2076
+ provingKeyPath
2038
2077
  });
2039
2078
  return {
2040
2079
  proofArgs: {
@@ -2076,7 +2115,7 @@ async function transfer(options) {
2076
2115
  };
2077
2116
  }
2078
2117
  async function mergeUtxos(options) {
2079
- const { amount, keypair, pool = "eth", rpcUrl, onProgress } = options;
2118
+ const { amount, keypair, pool = "eth", rpcUrl, provingKeyPath, onProgress } = options;
2080
2119
  const poolConfig = POOL_CONFIG[pool];
2081
2120
  const poolAddress = getPoolAddress(pool);
2082
2121
  onProgress?.("Fetching your UTXOs...");
@@ -2144,7 +2183,8 @@ async function mergeUtxos(options) {
2144
2183
  fee: 0,
2145
2184
  recipient: "0x0000000000000000000000000000000000000000",
2146
2185
  relayer: "0x0000000000000000000000000000000000000000",
2147
- onProgress
2186
+ onProgress,
2187
+ provingKeyPath
2148
2188
  });
2149
2189
  onProgress?.("Submitting to relay...");
2150
2190
  const relayResult = await submitRelay({
@@ -2556,6 +2596,7 @@ async function mergeSubaccount(options) {
2556
2596
  pool = "eth",
2557
2597
  rpcUrl,
2558
2598
  relayUrl,
2599
+ provingKeyPath,
2559
2600
  onProgress
2560
2601
  } = options;
2561
2602
  const normalizedSlot = normalizeSlot(slot);
@@ -2648,7 +2689,8 @@ async function mergeSubaccount(options) {
2648
2689
  fee: 0,
2649
2690
  recipient: "0x0000000000000000000000000000000000000000",
2650
2691
  relayer: "0x0000000000000000000000000000000000000000",
2651
- onProgress
2692
+ onProgress,
2693
+ provingKeyPath
2652
2694
  });
2653
2695
  onProgress?.("Submitting to relay...");
2654
2696
  const relayResult = await submitRelay({