@veil-cash/sdk 0.6.2 → 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;
@@ -597,6 +591,14 @@ var QUEUE_ABI = [
597
591
  outputs: [{ name: "count", type: "uint256" }],
598
592
  stateMutability: "view",
599
593
  type: "function"
594
+ },
595
+ // Get remaining daily free deposits for an address (V3+)
596
+ {
597
+ inputs: [{ name: "_depositor", type: "address" }],
598
+ name: "getDailyFreeRemaining",
599
+ outputs: [{ name: "remaining", type: "uint256" }],
600
+ stateMutability: "view",
601
+ type: "function"
600
602
  }
601
603
  ];
602
604
  var POOL_ABI = [
@@ -1314,6 +1316,25 @@ async function getQueueBalance(options) {
1314
1316
  pendingCount: pendingDeposits.length
1315
1317
  };
1316
1318
  }
1319
+ async function getDailyFreeRemaining(options) {
1320
+ const { address, pool = "eth", rpcUrl } = options;
1321
+ const queueAddress = getQueueAddress(pool);
1322
+ const publicClient = createPublicClient({
1323
+ chain: base,
1324
+ transport: http(rpcUrl)
1325
+ });
1326
+ try {
1327
+ const remaining = await publicClient.readContract({
1328
+ address: queueAddress,
1329
+ abi: QUEUE_ABI,
1330
+ functionName: "getDailyFreeRemaining",
1331
+ args: [address]
1332
+ });
1333
+ return Number(remaining);
1334
+ } catch {
1335
+ return 0;
1336
+ }
1337
+ }
1317
1338
  async function getPrivateBalance(options) {
1318
1339
  const { keypair, pool = "eth", rpcUrl, onProgress } = options;
1319
1340
  const poolAddress = getPoolAddress(pool);
@@ -1429,21 +1450,37 @@ function getMerklePath(tree, commitment) {
1429
1450
  pathIndices: index
1430
1451
  };
1431
1452
  }
1432
- var utils = null;
1433
- try {
1434
- const ffjavascript = __require("ffjavascript");
1435
- utils = ffjavascript.utils;
1436
- } catch {
1437
- 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);
1438
1456
  }
1439
- function findKeysDirectory() {
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);
1471
+ }
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;
1440
1479
  const possiblePaths = [
1441
1480
  // When running from package (installed via npm)
1442
- path.resolve(__dirname, "..", "keys"),
1443
- path.resolve(__dirname, "..", "..", "keys"),
1481
+ path.resolve(process.cwd(), "node_modules", "@veil-cash", "sdk", "keys"),
1444
1482
  // When running from source
1445
1483
  path.resolve(process.cwd(), "keys")
1446
- // ESM module path
1447
1484
  ];
1448
1485
  try {
1449
1486
  const currentFilePath = fileURLToPath(import.meta.url);
@@ -1452,7 +1489,7 @@ function findKeysDirectory() {
1452
1489
  } catch {
1453
1490
  }
1454
1491
  for (const p of possiblePaths) {
1455
- if (fs.existsSync(p) && fs.existsSync(path.join(p, "transaction2.wasm"))) {
1492
+ if (existsSync(p) && existsSync(path.join(p, "transaction2.wasm"))) {
1456
1493
  return p;
1457
1494
  }
1458
1495
  }
@@ -1460,26 +1497,48 @@ function findKeysDirectory() {
1460
1497
  "Circuit keys not found. Expected to find keys/ directory with transaction2.wasm and transaction2.zkey files."
1461
1498
  );
1462
1499
  }
1463
- async function prove(input, circuitName) {
1464
- if (!utils) {
1465
- 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
+ };
1507
+ }
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;
1466
1523
  }
1467
- const keysDir = findKeysDirectory();
1468
- const wasmPath = path.join(keysDir, `${circuitName}.wasm`);
1469
- const zkeyPath = path.join(keysDir, `${circuitName}.zkey`);
1470
- if (!fs.existsSync(wasmPath)) {
1524
+ const { existsSync } = await importNodeModule("node:fs");
1525
+ if (!existsSync(wasmPath)) {
1471
1526
  throw new Error(`Circuit WASM file not found: ${wasmPath}`);
1472
1527
  }
1473
- if (!fs.existsSync(zkeyPath)) {
1528
+ if (!existsSync(zkeyPath)) {
1474
1529
  throw new Error(`Circuit zkey file not found: ${zkeyPath}`);
1475
1530
  }
1531
+ }
1532
+ async function prove(input, circuitName, options = {}) {
1533
+ const { wasmPath, zkeyPath } = await resolveProvingKeyPaths(circuitName, options.provingKeyPath);
1534
+ await assertNodeKeyFilesExist(wasmPath, zkeyPath);
1476
1535
  const result = await groth16.fullProve(
1477
- utils.stringifyBigInts(input),
1536
+ ffUtils.stringifyBigInts(input),
1478
1537
  wasmPath,
1479
1538
  zkeyPath,
1480
1539
  void 0,
1481
1540
  void 0,
1482
- { singleThread: true }
1541
+ { singleThread: options.singleThread ?? true }
1483
1542
  );
1484
1543
  const proof = result.proof;
1485
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);
@@ -1507,7 +1566,8 @@ async function getProof({
1507
1566
  fee,
1508
1567
  recipient,
1509
1568
  relayer,
1510
- onProgress
1569
+ onProgress,
1570
+ provingKeyPath
1511
1571
  }) {
1512
1572
  inputs = shuffle([...inputs]);
1513
1573
  outputs = shuffle([...outputs]);
@@ -1567,7 +1627,7 @@ async function getProof({
1567
1627
  };
1568
1628
  onProgress?.("Generating ZK proof...", `${inputs.length} inputs`);
1569
1629
  const circuitName = selectCircuit(inputs.length);
1570
- const proof = await prove(proofInput, circuitName);
1630
+ const proof = await prove(proofInput, circuitName, { provingKeyPath });
1571
1631
  const args = {
1572
1632
  proof,
1573
1633
  root: toFixedHex(proofInput.root),
@@ -1589,7 +1649,8 @@ async function prepareTransaction({
1589
1649
  fee = 0,
1590
1650
  recipient = 0,
1591
1651
  relayer = 0,
1592
- onProgress
1652
+ onProgress,
1653
+ provingKeyPath
1593
1654
  }) {
1594
1655
  if (inputs.length > 16 || outputs.length > 2) {
1595
1656
  throw new Error("Incorrect inputs/outputs count. Maximum: 16 inputs, 2 outputs.");
@@ -1611,7 +1672,8 @@ async function prepareTransaction({
1611
1672
  fee: BigInt(fee),
1612
1673
  recipient: String(recipient),
1613
1674
  relayer: String(relayer),
1614
- onProgress
1675
+ onProgress,
1676
+ provingKeyPath
1615
1677
  });
1616
1678
  return result;
1617
1679
  }
@@ -1769,6 +1831,7 @@ async function buildWithdrawProof(options) {
1769
1831
  keypair,
1770
1832
  pool = "eth",
1771
1833
  rpcUrl,
1834
+ provingKeyPath,
1772
1835
  onProgress
1773
1836
  } = options;
1774
1837
  const poolConfig = POOL_CONFIG[pool];
@@ -1832,7 +1895,8 @@ async function buildWithdrawProof(options) {
1832
1895
  fee: 0,
1833
1896
  recipient,
1834
1897
  relayer: "0x0000000000000000000000000000000000000000",
1835
- onProgress
1898
+ onProgress,
1899
+ provingKeyPath
1836
1900
  });
1837
1901
  return {
1838
1902
  proofArgs: {
@@ -1929,6 +1993,7 @@ async function buildTransferProof(options) {
1929
1993
  senderKeypair,
1930
1994
  pool = "eth",
1931
1995
  rpcUrl,
1996
+ provingKeyPath,
1932
1997
  onProgress
1933
1998
  } = options;
1934
1999
  const poolConfig = POOL_CONFIG[pool];
@@ -2007,7 +2072,8 @@ async function buildTransferProof(options) {
2007
2072
  fee: 0,
2008
2073
  recipient: "0x0000000000000000000000000000000000000000",
2009
2074
  relayer: "0x0000000000000000000000000000000000000000",
2010
- onProgress
2075
+ onProgress,
2076
+ provingKeyPath
2011
2077
  });
2012
2078
  return {
2013
2079
  proofArgs: {
@@ -2049,7 +2115,7 @@ async function transfer(options) {
2049
2115
  };
2050
2116
  }
2051
2117
  async function mergeUtxos(options) {
2052
- const { amount, keypair, pool = "eth", rpcUrl, onProgress } = options;
2118
+ const { amount, keypair, pool = "eth", rpcUrl, provingKeyPath, onProgress } = options;
2053
2119
  const poolConfig = POOL_CONFIG[pool];
2054
2120
  const poolAddress = getPoolAddress(pool);
2055
2121
  onProgress?.("Fetching your UTXOs...");
@@ -2117,7 +2183,8 @@ async function mergeUtxos(options) {
2117
2183
  fee: 0,
2118
2184
  recipient: "0x0000000000000000000000000000000000000000",
2119
2185
  relayer: "0x0000000000000000000000000000000000000000",
2120
- onProgress
2186
+ onProgress,
2187
+ provingKeyPath
2121
2188
  });
2122
2189
  onProgress?.("Submitting to relay...");
2123
2190
  const relayResult = await submitRelay({
@@ -2529,6 +2596,7 @@ async function mergeSubaccount(options) {
2529
2596
  pool = "eth",
2530
2597
  rpcUrl,
2531
2598
  relayUrl,
2599
+ provingKeyPath,
2532
2600
  onProgress
2533
2601
  } = options;
2534
2602
  const normalizedSlot = normalizeSlot(slot);
@@ -2621,7 +2689,8 @@ async function mergeSubaccount(options) {
2621
2689
  fee: 0,
2622
2690
  recipient: "0x0000000000000000000000000000000000000000",
2623
2691
  relayer: "0x0000000000000000000000000000000000000000",
2624
- onProgress
2692
+ onProgress,
2693
+ provingKeyPath
2625
2694
  });
2626
2695
  onProgress?.("Submitting to relay...");
2627
2696
  const relayResult = await submitRelay({
@@ -2654,6 +2723,6 @@ async function mergeSubaccount(options) {
2654
2723
  };
2655
2724
  }
2656
2725
 
2657
- export { ADDRESSES, CIRCUIT_CONFIG, ENTRY_ABI, ERC20_ABI, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, POOL_ABI, POOL_CONFIG, QUEUE_ABI, RelayError, Utxo, VEIL_SIGNED_MESSAGE, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountPrivateBalance, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeSubaccount, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
2726
+ export { ADDRESSES, CIRCUIT_CONFIG, ENTRY_ABI, ERC20_ABI, FIELD_SIZE, FORWARDER_ABI, FORWARDER_CONTRACT_VERSION, FORWARDER_FACTORY_ABI, Keypair, MAX_SUBACCOUNT_SLOTS, MERKLE_TREE_HEIGHT, POOL_ABI, POOL_CONFIG, QUEUE_ABI, RelayError, Utxo, VEIL_SIGNED_MESSAGE, buildApproveUSDCTx, buildChangeDepositKeyTx, buildDepositETHTx, buildDepositTx, buildDepositUSDCTx, buildMerkleTree, buildRegisterTx, buildSubaccountRecoveryTx, buildSubaccountWithdrawTypedData, buildTransferProof, buildWithdrawProof, checkRecipientRegistration, checkRelayHealth, deploySubaccountForwarder, deriveSubaccountChildDepositKey, deriveSubaccountChildOwner, deriveSubaccountChildPrivateKey, deriveSubaccountSalt, deriveSubaccountSlot, findNextSubaccountWithdrawNonce, getAddresses, getDailyFreeRemaining, getExtDataHash, getForwarderFactoryAddress, getMerklePath, getPoolAddress, getPrivateBalance, getQueueAddress, getQueueBalance, getRelayInfo, getRelayUrl, getSubaccountPrivateBalance, getSubaccountStatus, isSubaccountForwarderDeployed, isSubaccountWithdrawNonceUsed, mergeSubaccount, mergeUtxos, packEncryptedMessage, poseidonHash, poseidonHash2, predictSubaccountForwarder, prepareTransaction, prove, randomBN, selectCircuit, selectUtxosForWithdraw, shuffle, signSubaccountWithdraw, submitRelay, sweepSubaccountForwarder, toBuffer, toFixedHex, transfer, unpackEncryptedMessage, withdraw };
2658
2727
  //# sourceMappingURL=index.js.map
2659
2728
  //# sourceMappingURL=index.js.map