@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.cjs CHANGED
@@ -1,57 +1,36 @@
1
1
  'use strict';
2
2
 
3
3
  var ethers = require('ethers');
4
+ var buffer = require('buffer');
4
5
  var accounts = require('viem/accounts');
5
- var crypto = require('crypto');
6
+ var ethSigUtil = require('eth-sig-util');
7
+ var circomlib = require('circomlib');
6
8
  var viem = require('viem');
7
9
  var chains = require('viem/chains');
8
10
  var MerkleTree = require('fixed-merkle-tree-legacy');
9
11
  var snarkjs = require('snarkjs');
10
- var path = require('path');
11
- var fs = require('fs');
12
- var url = require('url');
12
+ var ffjavascript = require('ffjavascript');
13
13
 
14
14
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
15
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
16
 
17
- function _interopNamespace(e) {
18
- if (e && e.__esModule) return e;
19
- var n = Object.create(null);
20
- if (e) {
21
- Object.keys(e).forEach(function (k) {
22
- if (k !== 'default') {
23
- var d = Object.getOwnPropertyDescriptor(e, k);
24
- Object.defineProperty(n, k, d.get ? d : {
25
- enumerable: true,
26
- get: function () { return e[k]; }
27
- });
28
- }
29
- });
30
- }
31
- n.default = e;
32
- return Object.freeze(n);
33
- }
34
-
35
- var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
17
+ var ethSigUtil__default = /*#__PURE__*/_interopDefault(ethSigUtil);
18
+ var circomlib__default = /*#__PURE__*/_interopDefault(circomlib);
36
19
  var MerkleTree__default = /*#__PURE__*/_interopDefault(MerkleTree);
37
- var path__namespace = /*#__PURE__*/_interopNamespace(path);
38
- var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
39
20
 
40
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
41
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
42
- }) : x)(function(x) {
43
- if (typeof require !== "undefined") return require.apply(this, arguments);
44
- throw Error('Dynamic require of "' + x + '" is not supported');
45
- });
46
- var circomlib = __require("circomlib");
47
- var poseidon = circomlib.poseidon;
21
+ // src/keypair.ts
22
+ var poseidon = circomlib__default.default.poseidon;
48
23
  var FIELD_SIZE = BigInt(
49
24
  "21888242871839275222246405745257275088548364400416034343698204186575808495617"
50
25
  );
51
26
  var poseidonHash = (items) => BigInt(poseidon(items).toString());
52
27
  var poseidonHash2 = (a, b) => poseidonHash([a, b]);
53
28
  var randomBN = (nbytes = 31) => {
54
- const bytes = crypto__namespace.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));
55
34
  let hex = "0x";
56
35
  for (let i = 0; i < bytes.length; i++) {
57
36
  hex += bytes[i].toString(16).padStart(2, "0");
@@ -60,7 +39,7 @@ var randomBN = (nbytes = 31) => {
60
39
  };
61
40
  function toFixedHex(number, length = 32) {
62
41
  let hexValue;
63
- if (number instanceof Buffer) {
42
+ if (number instanceof buffer.Buffer) {
64
43
  hexValue = number.toString("hex");
65
44
  } else {
66
45
  let bigIntValue = BigInt(number);
@@ -75,11 +54,10 @@ function toFixedHex(number, length = 32) {
75
54
  var toBuffer = (value, length) => {
76
55
  const bigIntValue = BigInt(value);
77
56
  const hex = bigIntValue.toString(16).padStart(length * 2, "0");
78
- return Buffer.from(hex, "hex");
57
+ return buffer.Buffer.from(hex, "hex");
79
58
  };
80
59
  function getExtDataHash(extData) {
81
- const { ethers: ethers2 } = __require("ethers");
82
- const abi = ethers2.AbiCoder.defaultAbiCoder();
60
+ const abi = ethers.ethers.AbiCoder.defaultAbiCoder();
83
61
  const encodedData = abi.encode(
84
62
  ["tuple(address,int256,address,uint256,bytes,bytes)"],
85
63
  [[
@@ -91,7 +69,7 @@ function getExtDataHash(extData) {
91
69
  extData.encryptedOutput2
92
70
  ]]
93
71
  );
94
- const hash = ethers2.keccak256(encodedData);
72
+ const hash = ethers.ethers.keccak256(encodedData);
95
73
  return BigInt(hash) % FIELD_SIZE;
96
74
  }
97
75
  function shuffle(array) {
@@ -107,15 +85,14 @@ function shuffle(array) {
107
85
 
108
86
  // src/keypair.ts
109
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.";
110
- var ethSigUtil = __require("eth-sig-util");
111
88
  function packEncryptedMessage(encryptedMessage) {
112
- const nonceBuf = Buffer.from(encryptedMessage.nonce, "base64");
113
- const ephemPublicKeyBuf = Buffer.from(encryptedMessage.ephemPublicKey, "base64");
114
- const ciphertextBuf = Buffer.from(encryptedMessage.ciphertext, "base64");
115
- const messageBuff = Buffer.concat([
116
- Buffer.alloc(24 - nonceBuf.length),
89
+ const nonceBuf = buffer.Buffer.from(encryptedMessage.nonce, "base64");
90
+ const ephemPublicKeyBuf = buffer.Buffer.from(encryptedMessage.ephemPublicKey, "base64");
91
+ const ciphertextBuf = buffer.Buffer.from(encryptedMessage.ciphertext, "base64");
92
+ const messageBuff = buffer.Buffer.concat([
93
+ buffer.Buffer.alloc(24 - nonceBuf.length),
117
94
  nonceBuf,
118
- Buffer.alloc(32 - ephemPublicKeyBuf.length),
95
+ buffer.Buffer.alloc(32 - ephemPublicKeyBuf.length),
119
96
  ephemPublicKeyBuf,
120
97
  ciphertextBuf
121
98
  ]);
@@ -125,7 +102,7 @@ function unpackEncryptedMessage(encryptedMessage) {
125
102
  if (encryptedMessage.slice(0, 2) === "0x") {
126
103
  encryptedMessage = encryptedMessage.slice(2);
127
104
  }
128
- const messageBuff = Buffer.from(encryptedMessage, "hex");
105
+ const messageBuff = buffer.Buffer.from(encryptedMessage, "hex");
129
106
  const nonceBuf = messageBuff.slice(0, 24);
130
107
  const ephemPublicKeyBuf = messageBuff.slice(24, 56);
131
108
  const ciphertextBuf = messageBuff.slice(56);
@@ -150,7 +127,7 @@ var Keypair = class _Keypair {
150
127
  constructor(privkey = ethers.ethers.Wallet.createRandom().privateKey) {
151
128
  this.privkey = privkey;
152
129
  this.pubkey = poseidonHash([this.privkey]);
153
- this.encryptionKey = ethSigUtil.getEncryptionPublicKey(privkey.slice(2));
130
+ this.encryptionKey = ethSigUtil__default.default.getEncryptionPublicKey(privkey.slice(2));
154
131
  }
155
132
  /**
156
133
  * Get the deposit key for this keypair
@@ -158,7 +135,7 @@ var Keypair = class _Keypair {
158
135
  * @returns Deposit key as hex string (130 chars with 0x prefix)
159
136
  */
160
137
  toString() {
161
- return toFixedHex(this.pubkey) + Buffer.from(this.encryptionKey, "base64").toString("hex");
138
+ return toFixedHex(this.pubkey) + buffer.Buffer.from(this.encryptionKey, "base64").toString("hex");
162
139
  }
163
140
  /**
164
141
  * Alias for toString() - returns the deposit key
@@ -183,7 +160,7 @@ var Keypair = class _Keypair {
183
160
  return Object.assign(new _Keypair(), {
184
161
  privkey: null,
185
162
  pubkey: BigInt("0x" + str.slice(0, 64)),
186
- encryptionKey: Buffer.from(str.slice(64, 128), "hex").toString("base64")
163
+ encryptionKey: buffer.Buffer.from(str.slice(64, 128), "hex").toString("base64")
187
164
  });
188
165
  }
189
166
  /**
@@ -268,7 +245,7 @@ var Keypair = class _Keypair {
268
245
  */
269
246
  encrypt(bytes) {
270
247
  return packEncryptedMessage(
271
- ethSigUtil.encrypt(
248
+ ethSigUtil__default.default.encrypt(
272
249
  this.encryptionKey,
273
250
  { data: bytes.toString("base64") },
274
251
  "x25519-xsalsa20-poly1305"
@@ -284,14 +261,12 @@ var Keypair = class _Keypair {
284
261
  if (!this.privkey) {
285
262
  throw new Error("Cannot decrypt without private key");
286
263
  }
287
- return Buffer.from(
288
- ethSigUtil.decrypt(unpackEncryptedMessage(data), this.privkey.slice(2)),
264
+ return buffer.Buffer.from(
265
+ ethSigUtil__default.default.decrypt(unpackEncryptedMessage(data), this.privkey.slice(2)),
289
266
  "base64"
290
267
  );
291
268
  }
292
269
  };
293
-
294
- // src/utxo.ts
295
270
  var Utxo = class _Utxo {
296
271
  amount;
297
272
  blinding;
@@ -342,7 +317,7 @@ var Utxo = class _Utxo {
342
317
  * @returns Encrypted data as 0x-prefixed hex string
343
318
  */
344
319
  encrypt() {
345
- const bytes = Buffer.concat([
320
+ const bytes = buffer.Buffer.concat([
346
321
  toBuffer(this.amount, 31),
347
322
  toBuffer(this.blinding, 31)
348
323
  ]);
@@ -625,6 +600,14 @@ var QUEUE_ABI = [
625
600
  outputs: [{ name: "count", type: "uint256" }],
626
601
  stateMutability: "view",
627
602
  type: "function"
603
+ },
604
+ // Get remaining daily free deposits for an address (V3+)
605
+ {
606
+ inputs: [{ name: "_depositor", type: "address" }],
607
+ name: "getDailyFreeRemaining",
608
+ outputs: [{ name: "remaining", type: "uint256" }],
609
+ stateMutability: "view",
610
+ type: "function"
628
611
  }
629
612
  ];
630
613
  var POOL_ABI = [
@@ -1342,6 +1325,25 @@ async function getQueueBalance(options) {
1342
1325
  pendingCount: pendingDeposits.length
1343
1326
  };
1344
1327
  }
1328
+ async function getDailyFreeRemaining(options) {
1329
+ const { address, pool = "eth", rpcUrl } = options;
1330
+ const queueAddress = getQueueAddress(pool);
1331
+ const publicClient = viem.createPublicClient({
1332
+ chain: chains.base,
1333
+ transport: viem.http(rpcUrl)
1334
+ });
1335
+ try {
1336
+ const remaining = await publicClient.readContract({
1337
+ address: queueAddress,
1338
+ abi: QUEUE_ABI,
1339
+ functionName: "getDailyFreeRemaining",
1340
+ args: [address]
1341
+ });
1342
+ return Number(remaining);
1343
+ } catch {
1344
+ return 0;
1345
+ }
1346
+ }
1345
1347
  async function getPrivateBalance(options) {
1346
1348
  const { keypair, pool = "eth", rpcUrl, onProgress } = options;
1347
1349
  const poolAddress = getPoolAddress(pool);
@@ -1457,30 +1459,46 @@ function getMerklePath(tree, commitment) {
1457
1459
  pathIndices: index
1458
1460
  };
1459
1461
  }
1460
- var utils = null;
1461
- try {
1462
- const ffjavascript = __require("ffjavascript");
1463
- utils = ffjavascript.utils;
1464
- } catch {
1465
- console.warn("ffjavascript not found. Proof generation may not work.");
1462
+ var ffUtils = ffjavascript.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;
1468
+ }
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);
1466
1480
  }
1467
- function findKeysDirectory() {
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;
1468
1488
  const possiblePaths = [
1469
1489
  // When running from package (installed via npm)
1470
- path__namespace.resolve(__dirname, "..", "keys"),
1471
- path__namespace.resolve(__dirname, "..", "..", "keys"),
1490
+ path.resolve(process.cwd(), "node_modules", "@veil-cash", "sdk", "keys"),
1472
1491
  // When running from source
1473
- path__namespace.resolve(process.cwd(), "keys")
1474
- // ESM module path
1492
+ path.resolve(process.cwd(), "keys")
1475
1493
  ];
1476
1494
  try {
1477
- const currentFilePath = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
1478
- const currentDir = path__namespace.dirname(currentFilePath);
1479
- possiblePaths.unshift(path__namespace.resolve(currentDir, "..", "keys"));
1495
+ const currentFilePath = fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
1496
+ const currentDir = path.dirname(currentFilePath);
1497
+ possiblePaths.unshift(path.resolve(currentDir, "..", "keys"));
1480
1498
  } catch {
1481
1499
  }
1482
1500
  for (const p of possiblePaths) {
1483
- if (fs__namespace.existsSync(p) && fs__namespace.existsSync(path__namespace.join(p, "transaction2.wasm"))) {
1501
+ if (existsSync(p) && existsSync(path.join(p, "transaction2.wasm"))) {
1484
1502
  return p;
1485
1503
  }
1486
1504
  }
@@ -1488,26 +1506,48 @@ function findKeysDirectory() {
1488
1506
  "Circuit keys not found. Expected to find keys/ directory with transaction2.wasm and transaction2.zkey files."
1489
1507
  );
1490
1508
  }
1491
- async function prove(input, circuitName) {
1492
- if (!utils) {
1493
- 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
+ };
1516
+ }
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;
1494
1532
  }
1495
- const keysDir = findKeysDirectory();
1496
- const wasmPath = path__namespace.join(keysDir, `${circuitName}.wasm`);
1497
- const zkeyPath = path__namespace.join(keysDir, `${circuitName}.zkey`);
1498
- if (!fs__namespace.existsSync(wasmPath)) {
1533
+ const { existsSync } = await importNodeModule("node:fs");
1534
+ if (!existsSync(wasmPath)) {
1499
1535
  throw new Error(`Circuit WASM file not found: ${wasmPath}`);
1500
1536
  }
1501
- if (!fs__namespace.existsSync(zkeyPath)) {
1537
+ if (!existsSync(zkeyPath)) {
1502
1538
  throw new Error(`Circuit zkey file not found: ${zkeyPath}`);
1503
1539
  }
1540
+ }
1541
+ async function prove(input, circuitName, options = {}) {
1542
+ const { wasmPath, zkeyPath } = await resolveProvingKeyPaths(circuitName, options.provingKeyPath);
1543
+ await assertNodeKeyFilesExist(wasmPath, zkeyPath);
1504
1544
  const result = await snarkjs.groth16.fullProve(
1505
- utils.stringifyBigInts(input),
1545
+ ffUtils.stringifyBigInts(input),
1506
1546
  wasmPath,
1507
1547
  zkeyPath,
1508
1548
  void 0,
1509
1549
  void 0,
1510
- { singleThread: true }
1550
+ { singleThread: options.singleThread ?? true }
1511
1551
  );
1512
1552
  const proof = result.proof;
1513
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);
@@ -1535,7 +1575,8 @@ async function getProof({
1535
1575
  fee,
1536
1576
  recipient,
1537
1577
  relayer,
1538
- onProgress
1578
+ onProgress,
1579
+ provingKeyPath
1539
1580
  }) {
1540
1581
  inputs = shuffle([...inputs]);
1541
1582
  outputs = shuffle([...outputs]);
@@ -1595,7 +1636,7 @@ async function getProof({
1595
1636
  };
1596
1637
  onProgress?.("Generating ZK proof...", `${inputs.length} inputs`);
1597
1638
  const circuitName = selectCircuit(inputs.length);
1598
- const proof = await prove(proofInput, circuitName);
1639
+ const proof = await prove(proofInput, circuitName, { provingKeyPath });
1599
1640
  const args = {
1600
1641
  proof,
1601
1642
  root: toFixedHex(proofInput.root),
@@ -1617,7 +1658,8 @@ async function prepareTransaction({
1617
1658
  fee = 0,
1618
1659
  recipient = 0,
1619
1660
  relayer = 0,
1620
- onProgress
1661
+ onProgress,
1662
+ provingKeyPath
1621
1663
  }) {
1622
1664
  if (inputs.length > 16 || outputs.length > 2) {
1623
1665
  throw new Error("Incorrect inputs/outputs count. Maximum: 16 inputs, 2 outputs.");
@@ -1639,7 +1681,8 @@ async function prepareTransaction({
1639
1681
  fee: BigInt(fee),
1640
1682
  recipient: String(recipient),
1641
1683
  relayer: String(relayer),
1642
- onProgress
1684
+ onProgress,
1685
+ provingKeyPath
1643
1686
  });
1644
1687
  return result;
1645
1688
  }
@@ -1797,6 +1840,7 @@ async function buildWithdrawProof(options) {
1797
1840
  keypair,
1798
1841
  pool = "eth",
1799
1842
  rpcUrl,
1843
+ provingKeyPath,
1800
1844
  onProgress
1801
1845
  } = options;
1802
1846
  const poolConfig = POOL_CONFIG[pool];
@@ -1860,7 +1904,8 @@ async function buildWithdrawProof(options) {
1860
1904
  fee: 0,
1861
1905
  recipient,
1862
1906
  relayer: "0x0000000000000000000000000000000000000000",
1863
- onProgress
1907
+ onProgress,
1908
+ provingKeyPath
1864
1909
  });
1865
1910
  return {
1866
1911
  proofArgs: {
@@ -1957,6 +2002,7 @@ async function buildTransferProof(options) {
1957
2002
  senderKeypair,
1958
2003
  pool = "eth",
1959
2004
  rpcUrl,
2005
+ provingKeyPath,
1960
2006
  onProgress
1961
2007
  } = options;
1962
2008
  const poolConfig = POOL_CONFIG[pool];
@@ -2035,7 +2081,8 @@ async function buildTransferProof(options) {
2035
2081
  fee: 0,
2036
2082
  recipient: "0x0000000000000000000000000000000000000000",
2037
2083
  relayer: "0x0000000000000000000000000000000000000000",
2038
- onProgress
2084
+ onProgress,
2085
+ provingKeyPath
2039
2086
  });
2040
2087
  return {
2041
2088
  proofArgs: {
@@ -2077,7 +2124,7 @@ async function transfer(options) {
2077
2124
  };
2078
2125
  }
2079
2126
  async function mergeUtxos(options) {
2080
- const { amount, keypair, pool = "eth", rpcUrl, onProgress } = options;
2127
+ const { amount, keypair, pool = "eth", rpcUrl, provingKeyPath, onProgress } = options;
2081
2128
  const poolConfig = POOL_CONFIG[pool];
2082
2129
  const poolAddress = getPoolAddress(pool);
2083
2130
  onProgress?.("Fetching your UTXOs...");
@@ -2145,7 +2192,8 @@ async function mergeUtxos(options) {
2145
2192
  fee: 0,
2146
2193
  recipient: "0x0000000000000000000000000000000000000000",
2147
2194
  relayer: "0x0000000000000000000000000000000000000000",
2148
- onProgress
2195
+ onProgress,
2196
+ provingKeyPath
2149
2197
  });
2150
2198
  onProgress?.("Submitting to relay...");
2151
2199
  const relayResult = await submitRelay({
@@ -2557,6 +2605,7 @@ async function mergeSubaccount(options) {
2557
2605
  pool = "eth",
2558
2606
  rpcUrl,
2559
2607
  relayUrl,
2608
+ provingKeyPath,
2560
2609
  onProgress
2561
2610
  } = options;
2562
2611
  const normalizedSlot = normalizeSlot(slot);
@@ -2649,7 +2698,8 @@ async function mergeSubaccount(options) {
2649
2698
  fee: 0,
2650
2699
  recipient: "0x0000000000000000000000000000000000000000",
2651
2700
  relayer: "0x0000000000000000000000000000000000000000",
2652
- onProgress
2701
+ onProgress,
2702
+ provingKeyPath
2653
2703
  });
2654
2704
  onProgress?.("Submitting to relay...");
2655
2705
  const relayResult = await submitRelay({
@@ -2720,6 +2770,7 @@ exports.deriveSubaccountSalt = deriveSubaccountSalt;
2720
2770
  exports.deriveSubaccountSlot = deriveSubaccountSlot;
2721
2771
  exports.findNextSubaccountWithdrawNonce = findNextSubaccountWithdrawNonce;
2722
2772
  exports.getAddresses = getAddresses;
2773
+ exports.getDailyFreeRemaining = getDailyFreeRemaining;
2723
2774
  exports.getExtDataHash = getExtDataHash;
2724
2775
  exports.getForwarderFactoryAddress = getForwarderFactoryAddress;
2725
2776
  exports.getMerklePath = getMerklePath;