@veil-cash/sdk 0.6.3 → 0.6.5

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,24 @@
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 * as _ethSigUtil from 'eth-sig-util';
5
+ import * as _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
13
+ function resolveInterop(mod) {
14
+ if (mod && typeof mod === "object" && "default" in mod) {
15
+ const defaultVal = mod.default;
16
+ if (defaultVal != null) return defaultVal;
17
+ }
18
+ return mod;
19
+ }
20
+ var ethSigUtil = resolveInterop(_ethSigUtil);
21
+ var circomlib = resolveInterop(_circomlib);
19
22
  var poseidon = circomlib.poseidon;
20
23
  var FIELD_SIZE = BigInt(
21
24
  "21888242871839275222246405745257275088548364400416034343698204186575808495617"
@@ -23,7 +26,11 @@ var FIELD_SIZE = BigInt(
23
26
  var poseidonHash = (items) => BigInt(poseidon(items).toString());
24
27
  var poseidonHash2 = (a, b) => poseidonHash([a, b]);
25
28
  var randomBN = (nbytes = 31) => {
26
- const bytes = crypto.randomBytes(nbytes);
29
+ const cryptoApi = globalThis.crypto;
30
+ if (!cryptoApi?.getRandomValues) {
31
+ throw new Error("Secure random number generation is unavailable in this runtime");
32
+ }
33
+ const bytes = cryptoApi.getRandomValues(new Uint8Array(nbytes));
27
34
  let hex = "0x";
28
35
  for (let i = 0; i < bytes.length; i++) {
29
36
  hex += bytes[i].toString(16).padStart(2, "0");
@@ -50,8 +57,7 @@ var toBuffer = (value, length) => {
50
57
  return Buffer.from(hex, "hex");
51
58
  };
52
59
  function getExtDataHash(extData) {
53
- const { ethers: ethers2 } = __require("ethers");
54
- const abi = ethers2.AbiCoder.defaultAbiCoder();
60
+ const abi = ethers.AbiCoder.defaultAbiCoder();
55
61
  const encodedData = abi.encode(
56
62
  ["tuple(address,int256,address,uint256,bytes,bytes)"],
57
63
  [[
@@ -63,7 +69,7 @@ function getExtDataHash(extData) {
63
69
  extData.encryptedOutput2
64
70
  ]]
65
71
  );
66
- const hash = ethers2.keccak256(encodedData);
72
+ const hash = ethers.keccak256(encodedData);
67
73
  return BigInt(hash) % FIELD_SIZE;
68
74
  }
69
75
  function shuffle(array) {
@@ -79,7 +85,6 @@ function shuffle(array) {
79
85
 
80
86
  // src/keypair.ts
81
87
  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
88
  function packEncryptedMessage(encryptedMessage) {
84
89
  const nonceBuf = Buffer.from(encryptedMessage.nonce, "base64");
85
90
  const ephemPublicKeyBuf = Buffer.from(encryptedMessage.ephemPublicKey, "base64");
@@ -262,8 +267,6 @@ var Keypair = class _Keypair {
262
267
  );
263
268
  }
264
269
  };
265
-
266
- // src/utxo.ts
267
270
  var Utxo = class _Utxo {
268
271
  amount;
269
272
  blinding;
@@ -1456,21 +1459,37 @@ function getMerklePath(tree, commitment) {
1456
1459
  pathIndices: index
1457
1460
  };
1458
1461
  }
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.");
1462
+ var ffUtils = utils;
1463
+ function isBrowserRuntime() {
1464
+ return !(typeof process !== "undefined" && !!process.versions?.node);
1465
+ }
1466
+ function stripTrailingSlash(value) {
1467
+ return value.endsWith("/") ? value.slice(0, -1) : value;
1465
1468
  }
1466
- function findKeysDirectory() {
1469
+ function normalizeCircuitBasePath(provingKeyPath, circuitName) {
1470
+ const resolvedPath = typeof provingKeyPath === "function" ? provingKeyPath(circuitName) : provingKeyPath;
1471
+ const withoutExtension = resolvedPath.replace(/\.(wasm|zkey)$/i, "");
1472
+ if (withoutExtension.endsWith(`/${circuitName}`) || withoutExtension.endsWith(`\\${circuitName}`)) {
1473
+ return withoutExtension;
1474
+ }
1475
+ return `${stripTrailingSlash(withoutExtension)}/${circuitName}`;
1476
+ }
1477
+ function importNodeModule(specifier) {
1478
+ const dynamicImport = new Function("specifier", "return import(specifier)");
1479
+ return dynamicImport(specifier);
1480
+ }
1481
+ async function findNodeKeysDirectory() {
1482
+ const [{ existsSync }, pathModule, { fileURLToPath }] = await Promise.all([
1483
+ importNodeModule("node:fs"),
1484
+ importNodeModule("node:path"),
1485
+ importNodeModule("node:url")
1486
+ ]);
1487
+ const path = pathModule;
1467
1488
  const possiblePaths = [
1468
1489
  // When running from package (installed via npm)
1469
- path.resolve(__dirname, "..", "keys"),
1470
- path.resolve(__dirname, "..", "..", "keys"),
1490
+ path.resolve(process.cwd(), "node_modules", "@veil-cash", "sdk", "keys"),
1471
1491
  // When running from source
1472
1492
  path.resolve(process.cwd(), "keys")
1473
- // ESM module path
1474
1493
  ];
1475
1494
  try {
1476
1495
  const currentFilePath = fileURLToPath(import.meta.url);
@@ -1479,7 +1498,7 @@ function findKeysDirectory() {
1479
1498
  } catch {
1480
1499
  }
1481
1500
  for (const p of possiblePaths) {
1482
- if (fs.existsSync(p) && fs.existsSync(path.join(p, "transaction2.wasm"))) {
1501
+ if (existsSync(p) && existsSync(path.join(p, "transaction2.wasm"))) {
1483
1502
  return p;
1484
1503
  }
1485
1504
  }
@@ -1487,26 +1506,48 @@ function findKeysDirectory() {
1487
1506
  "Circuit keys not found. Expected to find keys/ directory with transaction2.wasm and transaction2.zkey files."
1488
1507
  );
1489
1508
  }
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");
1509
+ async function resolveProvingKeyPaths(circuitName, provingKeyPath) {
1510
+ if (provingKeyPath) {
1511
+ const circuitBasePath = normalizeCircuitBasePath(provingKeyPath, circuitName);
1512
+ return {
1513
+ wasmPath: `${circuitBasePath}.wasm`,
1514
+ zkeyPath: `${circuitBasePath}.zkey`
1515
+ };
1493
1516
  }
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)) {
1517
+ if (isBrowserRuntime()) {
1518
+ return {
1519
+ wasmPath: `/keys/${circuitName}.wasm`,
1520
+ zkeyPath: `/keys/${circuitName}.zkey`
1521
+ };
1522
+ }
1523
+ const keysDir = await findNodeKeysDirectory();
1524
+ return {
1525
+ wasmPath: `${keysDir}/${circuitName}.wasm`,
1526
+ zkeyPath: `${keysDir}/${circuitName}.zkey`
1527
+ };
1528
+ }
1529
+ async function assertNodeKeyFilesExist(wasmPath, zkeyPath) {
1530
+ if (isBrowserRuntime() || wasmPath.startsWith("http://") || wasmPath.startsWith("https://")) {
1531
+ return;
1532
+ }
1533
+ const { existsSync } = await importNodeModule("node:fs");
1534
+ if (!existsSync(wasmPath)) {
1498
1535
  throw new Error(`Circuit WASM file not found: ${wasmPath}`);
1499
1536
  }
1500
- if (!fs.existsSync(zkeyPath)) {
1537
+ if (!existsSync(zkeyPath)) {
1501
1538
  throw new Error(`Circuit zkey file not found: ${zkeyPath}`);
1502
1539
  }
1540
+ }
1541
+ async function prove(input, circuitName, options = {}) {
1542
+ const { wasmPath, zkeyPath } = await resolveProvingKeyPaths(circuitName, options.provingKeyPath);
1543
+ await assertNodeKeyFilesExist(wasmPath, zkeyPath);
1503
1544
  const result = await groth16.fullProve(
1504
- utils.stringifyBigInts(input),
1545
+ ffUtils.stringifyBigInts(input),
1505
1546
  wasmPath,
1506
1547
  zkeyPath,
1507
1548
  void 0,
1508
1549
  void 0,
1509
- { singleThread: true }
1550
+ { singleThread: options.singleThread ?? true }
1510
1551
  );
1511
1552
  const proof = result.proof;
1512
1553
  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 +1575,8 @@ async function getProof({
1534
1575
  fee,
1535
1576
  recipient,
1536
1577
  relayer,
1537
- onProgress
1578
+ onProgress,
1579
+ provingKeyPath
1538
1580
  }) {
1539
1581
  inputs = shuffle([...inputs]);
1540
1582
  outputs = shuffle([...outputs]);
@@ -1594,7 +1636,7 @@ async function getProof({
1594
1636
  };
1595
1637
  onProgress?.("Generating ZK proof...", `${inputs.length} inputs`);
1596
1638
  const circuitName = selectCircuit(inputs.length);
1597
- const proof = await prove(proofInput, circuitName);
1639
+ const proof = await prove(proofInput, circuitName, { provingKeyPath });
1598
1640
  const args = {
1599
1641
  proof,
1600
1642
  root: toFixedHex(proofInput.root),
@@ -1616,7 +1658,8 @@ async function prepareTransaction({
1616
1658
  fee = 0,
1617
1659
  recipient = 0,
1618
1660
  relayer = 0,
1619
- onProgress
1661
+ onProgress,
1662
+ provingKeyPath
1620
1663
  }) {
1621
1664
  if (inputs.length > 16 || outputs.length > 2) {
1622
1665
  throw new Error("Incorrect inputs/outputs count. Maximum: 16 inputs, 2 outputs.");
@@ -1638,7 +1681,8 @@ async function prepareTransaction({
1638
1681
  fee: BigInt(fee),
1639
1682
  recipient: String(recipient),
1640
1683
  relayer: String(relayer),
1641
- onProgress
1684
+ onProgress,
1685
+ provingKeyPath
1642
1686
  });
1643
1687
  return result;
1644
1688
  }
@@ -1796,6 +1840,7 @@ async function buildWithdrawProof(options) {
1796
1840
  keypair,
1797
1841
  pool = "eth",
1798
1842
  rpcUrl,
1843
+ provingKeyPath,
1799
1844
  onProgress
1800
1845
  } = options;
1801
1846
  const poolConfig = POOL_CONFIG[pool];
@@ -1859,7 +1904,8 @@ async function buildWithdrawProof(options) {
1859
1904
  fee: 0,
1860
1905
  recipient,
1861
1906
  relayer: "0x0000000000000000000000000000000000000000",
1862
- onProgress
1907
+ onProgress,
1908
+ provingKeyPath
1863
1909
  });
1864
1910
  return {
1865
1911
  proofArgs: {
@@ -1956,6 +2002,7 @@ async function buildTransferProof(options) {
1956
2002
  senderKeypair,
1957
2003
  pool = "eth",
1958
2004
  rpcUrl,
2005
+ provingKeyPath,
1959
2006
  onProgress
1960
2007
  } = options;
1961
2008
  const poolConfig = POOL_CONFIG[pool];
@@ -2034,7 +2081,8 @@ async function buildTransferProof(options) {
2034
2081
  fee: 0,
2035
2082
  recipient: "0x0000000000000000000000000000000000000000",
2036
2083
  relayer: "0x0000000000000000000000000000000000000000",
2037
- onProgress
2084
+ onProgress,
2085
+ provingKeyPath
2038
2086
  });
2039
2087
  return {
2040
2088
  proofArgs: {
@@ -2076,7 +2124,7 @@ async function transfer(options) {
2076
2124
  };
2077
2125
  }
2078
2126
  async function mergeUtxos(options) {
2079
- const { amount, keypair, pool = "eth", rpcUrl, onProgress } = options;
2127
+ const { amount, keypair, pool = "eth", rpcUrl, provingKeyPath, onProgress } = options;
2080
2128
  const poolConfig = POOL_CONFIG[pool];
2081
2129
  const poolAddress = getPoolAddress(pool);
2082
2130
  onProgress?.("Fetching your UTXOs...");
@@ -2144,7 +2192,8 @@ async function mergeUtxos(options) {
2144
2192
  fee: 0,
2145
2193
  recipient: "0x0000000000000000000000000000000000000000",
2146
2194
  relayer: "0x0000000000000000000000000000000000000000",
2147
- onProgress
2195
+ onProgress,
2196
+ provingKeyPath
2148
2197
  });
2149
2198
  onProgress?.("Submitting to relay...");
2150
2199
  const relayResult = await submitRelay({
@@ -2556,6 +2605,7 @@ async function mergeSubaccount(options) {
2556
2605
  pool = "eth",
2557
2606
  rpcUrl,
2558
2607
  relayUrl,
2608
+ provingKeyPath,
2559
2609
  onProgress
2560
2610
  } = options;
2561
2611
  const normalizedSlot = normalizeSlot(slot);
@@ -2648,7 +2698,8 @@ async function mergeSubaccount(options) {
2648
2698
  fee: 0,
2649
2699
  recipient: "0x0000000000000000000000000000000000000000",
2650
2700
  relayer: "0x0000000000000000000000000000000000000000",
2651
- onProgress
2701
+ onProgress,
2702
+ provingKeyPath
2652
2703
  });
2653
2704
  onProgress?.("Submitting to relay...");
2654
2705
  const relayResult = await submitRelay({