@cloak.ag/sdk 1.0.7 → 1.0.9

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,33 +1,9 @@
1
- import {
2
- __require,
3
- bigintToBytes32,
4
- buildPublicInputsBytes,
5
- bytesToHex,
6
- computeCommitment,
7
- computeMerkleRoot,
8
- computeNullifier,
9
- computeNullifierAsync,
10
- computeNullifierSync,
11
- computeOutputsHash,
12
- computeOutputsHashAsync,
13
- computeOutputsHashSync,
14
- computeProofForLatestDeposit,
15
- computeProofFromChain,
16
- computeSwapOutputsHash,
17
- computeSwapOutputsHashAsync,
18
- computeSwapOutputsHashSync,
19
- generateCommitment,
20
- generateCommitmentAsync,
21
- hexToBigint,
22
- hexToBytes,
23
- isValidHex,
24
- poseidonHash,
25
- proofToBytes,
26
- pubkeyToLimbs,
27
- randomBytes,
28
- readMerkleTreeState,
29
- splitTo2Limbs
30
- } from "./chunk-QDMAIFO4.js";
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
31
7
 
32
8
  // src/core/CloakSDK.ts
33
9
  import {
@@ -52,6 +28,273 @@ var CloakError = class extends Error {
52
28
  // src/core/keys.ts
53
29
  import { blake3 } from "@noble/hashes/blake3";
54
30
  import nacl from "tweetnacl";
31
+
32
+ // src/utils/crypto.ts
33
+ import { buildPoseidon } from "circomlibjs";
34
+ var poseidon = null;
35
+ async function getPoseidon() {
36
+ if (!poseidon) {
37
+ poseidon = await buildPoseidon();
38
+ }
39
+ return poseidon;
40
+ }
41
+ async function poseidonHash(inputs) {
42
+ const p = await getPoseidon();
43
+ const hash = p(inputs.map((x) => p.F.e(x)));
44
+ return p.F.toObject(hash);
45
+ }
46
+ function splitTo2Limbs(value) {
47
+ const mask = (1n << 128n) - 1n;
48
+ const lo = value & mask;
49
+ const hi = value >> 128n;
50
+ return [lo, hi];
51
+ }
52
+ function pubkeyToLimbs(pubkey) {
53
+ const bytes = typeof pubkey.toBytes === "function" ? pubkey.toBytes() : pubkey;
54
+ const value = BigInt("0x" + Buffer.from(bytes).toString("hex"));
55
+ return splitTo2Limbs(value);
56
+ }
57
+ async function computeMerkleRoot(leaf, pathElements, pathIndices) {
58
+ let current = leaf;
59
+ for (let i = 0; i < pathElements.length; i++) {
60
+ if (pathIndices[i] === 0) {
61
+ current = await poseidonHash([current, pathElements[i]]);
62
+ } else {
63
+ current = await poseidonHash([pathElements[i], current]);
64
+ }
65
+ }
66
+ return current;
67
+ }
68
+ function hexToBigint(hex) {
69
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
70
+ return BigInt("0x" + cleanHex);
71
+ }
72
+ async function computeCommitment(amount, r, sk_spend) {
73
+ const [sk0, sk1] = splitTo2Limbs(sk_spend);
74
+ const [r0, r1] = splitTo2Limbs(r);
75
+ const pk_spend = await poseidonHash([sk0, sk1]);
76
+ return await poseidonHash([amount, r0, r1, pk_spend]);
77
+ }
78
+ async function generateCommitmentAsync(amountLamports, r, skSpend) {
79
+ const amount = BigInt(amountLamports);
80
+ const rValue = hexToBigint(bytesToHex(r));
81
+ const skValue = hexToBigint(bytesToHex(skSpend));
82
+ return await computeCommitment(amount, rValue, skValue);
83
+ }
84
+ function generateCommitment(_amountLamports, _r, _skSpend) {
85
+ throw new Error("generateCommitment is deprecated. Use generateCommitmentAsync instead.");
86
+ }
87
+ async function computeNullifier(sk_spend, leafIndex) {
88
+ const [sk0, sk1] = splitTo2Limbs(sk_spend);
89
+ return await poseidonHash([sk0, sk1, leafIndex]);
90
+ }
91
+ async function computeNullifierAsync(skSpend, leafIndex) {
92
+ const skValue = typeof skSpend === "string" ? hexToBigint(skSpend) : hexToBigint(bytesToHex(skSpend));
93
+ return await computeNullifier(skValue, BigInt(leafIndex));
94
+ }
95
+ function computeNullifierSync(_skSpend, _leafIndex) {
96
+ throw new Error("computeNullifierSync is deprecated. Use computeNullifierAsync instead.");
97
+ }
98
+ async function computeOutputsHashAsync(outputs) {
99
+ let hash = 0n;
100
+ for (const output of outputs) {
101
+ const [lo, hi] = pubkeyToLimbs(output.recipient);
102
+ hash = await poseidonHash([hash, lo, hi, BigInt(output.amount)]);
103
+ }
104
+ return hash;
105
+ }
106
+ async function computeOutputsHash(outAddr, outAmount, outFlags) {
107
+ let hash = 0n;
108
+ for (let i = 0; i < 5; i++) {
109
+ if (outFlags[i] === 1) {
110
+ hash = await poseidonHash([hash, outAddr[i][0], outAddr[i][1], outAmount[i]]);
111
+ }
112
+ }
113
+ return hash;
114
+ }
115
+ function computeOutputsHashSync(_outputs) {
116
+ throw new Error("computeOutputsHashSync is deprecated. Use computeOutputsHashAsync instead.");
117
+ }
118
+ async function computeSwapOutputsHash(inputMintLimbs, outputMintLimbs, recipientAtaLimbs, minOutputAmount, publicAmount) {
119
+ return await poseidonHash([
120
+ inputMintLimbs[0],
121
+ inputMintLimbs[1],
122
+ outputMintLimbs[0],
123
+ outputMintLimbs[1],
124
+ recipientAtaLimbs[0],
125
+ recipientAtaLimbs[1],
126
+ minOutputAmount,
127
+ publicAmount
128
+ ]);
129
+ }
130
+ async function computeSwapOutputsHashAsync(inputMint, outputMint, recipientAta, minOutputAmount, amount) {
131
+ const inputMintLimbs = pubkeyToLimbs(inputMint);
132
+ const outputMintLimbs = pubkeyToLimbs(outputMint);
133
+ const recipientAtaLimbs = pubkeyToLimbs(recipientAta);
134
+ return await computeSwapOutputsHash(
135
+ inputMintLimbs,
136
+ outputMintLimbs,
137
+ recipientAtaLimbs,
138
+ BigInt(minOutputAmount),
139
+ BigInt(amount)
140
+ );
141
+ }
142
+ function computeSwapOutputsHashSync(_outputMint, _recipientAta, _minOutputAmount, _amount) {
143
+ throw new Error("computeSwapOutputsHashSync is deprecated. Use computeSwapOutputsHashAsync instead.");
144
+ }
145
+ function bigintToBytes32(n) {
146
+ const hex = n.toString(16).padStart(64, "0");
147
+ const bytes = new Uint8Array(32);
148
+ for (let i = 0; i < 32; i++) {
149
+ bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
150
+ }
151
+ return bytes;
152
+ }
153
+ function hexToBytes(hex) {
154
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
155
+ const bytes = new Uint8Array(cleanHex.length / 2);
156
+ for (let i = 0; i < cleanHex.length; i += 2) {
157
+ bytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16);
158
+ }
159
+ return bytes;
160
+ }
161
+ function bytesToHex(bytes, prefix = false) {
162
+ const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
163
+ return prefix ? `0x${hex}` : hex;
164
+ }
165
+ function randomBytes(length) {
166
+ const bytes = new Uint8Array(length);
167
+ const g = globalThis;
168
+ try {
169
+ const cryptoObj = g?.crypto || g?.window?.crypto || g?.self?.crypto;
170
+ if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
171
+ cryptoObj.getRandomValues(bytes);
172
+ return bytes;
173
+ }
174
+ } catch {
175
+ }
176
+ try {
177
+ const nodeCrypto = __require("crypto");
178
+ if (nodeCrypto?.randomBytes) {
179
+ const buffer = nodeCrypto.randomBytes(length);
180
+ bytes.set(buffer);
181
+ return bytes;
182
+ }
183
+ if (nodeCrypto?.webcrypto?.getRandomValues) {
184
+ nodeCrypto.webcrypto.getRandomValues(bytes);
185
+ return bytes;
186
+ }
187
+ } catch {
188
+ }
189
+ for (let i = 0; i < length; i++) bytes[i] = Math.floor(Math.random() * 256);
190
+ return bytes;
191
+ }
192
+ function isValidHex(hex, expectedLength) {
193
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
194
+ if (!/^[0-9a-f]*$/i.test(cleanHex)) {
195
+ return false;
196
+ }
197
+ if (cleanHex.length % 2 !== 0) {
198
+ return false;
199
+ }
200
+ if (expectedLength !== void 0) {
201
+ return cleanHex.length === expectedLength * 2;
202
+ }
203
+ return true;
204
+ }
205
+ var BN254_MODULUS = BigInt("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47");
206
+ function proofToBytes(proof) {
207
+ const pi_a_x = BigInt(proof.pi_a[0]);
208
+ const pi_a_y = BigInt(proof.pi_a[1]);
209
+ const pi_a_y_neg = (BN254_MODULUS - pi_a_y) % BN254_MODULUS;
210
+ const pi_a_x_le = bigintToBytes32LE(pi_a_x);
211
+ const pi_a_y_neg_le = bigintToBytes32LE(pi_a_y_neg);
212
+ const pi_a_le = new Uint8Array(64);
213
+ pi_a_le.set(pi_a_x_le, 0);
214
+ pi_a_le.set(pi_a_y_neg_le, 32);
215
+ const pi_a_be = convertEndianness32(pi_a_le);
216
+ const pi_b_x1 = BigInt(proof.pi_b[0][0]);
217
+ const pi_b_x2 = BigInt(proof.pi_b[0][1]);
218
+ const pi_b_y1 = BigInt(proof.pi_b[1][0]);
219
+ const pi_b_y2 = BigInt(proof.pi_b[1][1]);
220
+ const pi_b_x1_le = bigintToBytes32LE(pi_b_x1);
221
+ const pi_b_x2_le = bigintToBytes32LE(pi_b_x2);
222
+ const pi_b_y1_le = bigintToBytes32LE(pi_b_y1);
223
+ const pi_b_y2_le = bigintToBytes32LE(pi_b_y2);
224
+ const pi_b_le = new Uint8Array(128);
225
+ pi_b_le.set(pi_b_x1_le, 0);
226
+ pi_b_le.set(pi_b_x2_le, 32);
227
+ pi_b_le.set(pi_b_y1_le, 64);
228
+ pi_b_le.set(pi_b_y2_le, 96);
229
+ const pi_b_be = convertEndianness64(pi_b_le);
230
+ const pi_c_x = BigInt(proof.pi_c[0]);
231
+ const pi_c_y = BigInt(proof.pi_c[1]);
232
+ const pi_c_x_le = bigintToBytes32LE(pi_c_x);
233
+ const pi_c_y_le = bigintToBytes32LE(pi_c_y);
234
+ const pi_c_le = new Uint8Array(64);
235
+ pi_c_le.set(pi_c_x_le, 0);
236
+ pi_c_le.set(pi_c_y_le, 32);
237
+ const pi_c_be = convertEndianness32(pi_c_le);
238
+ const result = new Uint8Array(256);
239
+ result.set(pi_a_be, 0);
240
+ result.set(pi_b_be, 64);
241
+ result.set(pi_c_be, 192);
242
+ return result;
243
+ }
244
+ function bigintToBytes32LE(n) {
245
+ const bytes = new Uint8Array(32);
246
+ let value = n % BN254_MODULUS;
247
+ if (value < 0) {
248
+ value = (value + BN254_MODULUS) % BN254_MODULUS;
249
+ }
250
+ for (let i = 0; i < 32; i++) {
251
+ bytes[i] = Number(value & BigInt(255));
252
+ value = value >> BigInt(8);
253
+ }
254
+ return bytes;
255
+ }
256
+ function convertEndianness32(bytes) {
257
+ if (bytes.length !== 64) {
258
+ throw new Error("convertEndianness32 expects 64 bytes");
259
+ }
260
+ const result = new Uint8Array(64);
261
+ for (let i = 0; i < 32; i++) {
262
+ result[i] = bytes[31 - i];
263
+ }
264
+ for (let i = 0; i < 32; i++) {
265
+ result[32 + i] = bytes[63 - i];
266
+ }
267
+ return result;
268
+ }
269
+ function convertEndianness64(bytes) {
270
+ if (bytes.length !== 128) {
271
+ throw new Error("convertEndianness64 expects 128 bytes");
272
+ }
273
+ const result = new Uint8Array(128);
274
+ for (let i = 0; i < 64; i++) {
275
+ result[i] = bytes[63 - i];
276
+ }
277
+ for (let i = 0; i < 64; i++) {
278
+ result[64 + i] = bytes[127 - i];
279
+ }
280
+ return result;
281
+ }
282
+ function buildPublicInputsBytes(root, nullifier, outputsHash, publicAmount) {
283
+ const result = new Uint8Array(104);
284
+ result.set(bigintToBytes32(root), 0);
285
+ result.set(bigintToBytes32(nullifier), 32);
286
+ result.set(bigintToBytes32(outputsHash), 64);
287
+ const amountBytes = new Uint8Array(8);
288
+ let amt = publicAmount;
289
+ for (let i = 7; i >= 0; i--) {
290
+ amountBytes[i] = Number(amt & 0xffn);
291
+ amt = amt >> 8n;
292
+ }
293
+ result.set(amountBytes, 96);
294
+ return result;
295
+ }
296
+
297
+ // src/core/keys.ts
55
298
  function generateMasterSeed() {
56
299
  const seed = new Uint8Array(32);
57
300
  const g = globalThis;
@@ -1633,29 +1876,84 @@ function getShieldPoolPDAs(programId, mint) {
1633
1876
  treasury
1634
1877
  };
1635
1878
  }
1879
+ function getNullifierPDA(nullifier, programId) {
1880
+ const pid = programId || CLOAK_PROGRAM_ID;
1881
+ if (nullifier.length !== 32) {
1882
+ throw new Error(`Nullifier must be 32 bytes, got ${nullifier.length}`);
1883
+ }
1884
+ return PublicKey3.findProgramAddressSync(
1885
+ [Buffer.from("nullifier"), Buffer.from(nullifier)],
1886
+ pid
1887
+ );
1888
+ }
1889
+ function getSwapStatePDA(nullifier, programId) {
1890
+ const pid = programId || CLOAK_PROGRAM_ID;
1891
+ if (nullifier.length !== 32) {
1892
+ throw new Error(`Nullifier must be 32 bytes, got ${nullifier.length}`);
1893
+ }
1894
+ return PublicKey3.findProgramAddressSync(
1895
+ [Buffer.from("swap_state"), Buffer.from(nullifier)],
1896
+ pid
1897
+ );
1898
+ }
1636
1899
 
1637
1900
  // src/utils/proof-generation.ts
1638
1901
  import * as snarkjs from "snarkjs";
1639
1902
  var IS_REACT_NATIVE = typeof navigator !== "undefined" && navigator.product === "ReactNative";
1640
1903
  var IS_BROWSER = IS_REACT_NATIVE || typeof window !== "undefined" || typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
1904
+ var DEFAULT_CIRCUITS_URL = "https://www.cloak.ag/circuits";
1905
+ function isUrl(path) {
1906
+ return path.startsWith("http://") || path.startsWith("https://");
1907
+ }
1908
+ async function fetchFileAsBuffer(url) {
1909
+ const response = await fetch(url);
1910
+ if (!response.ok) {
1911
+ throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
1912
+ }
1913
+ const arrayBuffer = await response.arrayBuffer();
1914
+ return new Uint8Array(arrayBuffer);
1915
+ }
1641
1916
  var _nodePath = null;
1642
1917
  var _nodeFs = null;
1643
1918
  var _nodeCrypto = null;
1919
+ var _fs = null;
1920
+ var _path = null;
1921
+ async function loadNodeModules() {
1922
+ if (_fs && _path) {
1923
+ return { fs: _fs, path: _path };
1924
+ }
1925
+ if (IS_BROWSER) {
1926
+ throw new Error("Node.js modules not available in browser/React Native");
1927
+ }
1928
+ const [fsModule, pathModule] = await Promise.all([
1929
+ import("fs"),
1930
+ import("path")
1931
+ ]);
1932
+ _fs = fsModule;
1933
+ _path = pathModule;
1934
+ return { fs: _fs, path: _path };
1935
+ }
1644
1936
  function nodeRequire(moduleName) {
1645
1937
  if (IS_BROWSER) {
1646
1938
  throw new Error(`Node.js ${moduleName} module not available in browser/React Native`);
1647
1939
  }
1648
- const requireFunc = new Function("moduleName", "return require(moduleName)");
1649
- return requireFunc(moduleName);
1940
+ try {
1941
+ const requireFunc = new Function("moduleName", "return require(moduleName)");
1942
+ return requireFunc(moduleName);
1943
+ } catch {
1944
+ throw new Error(`Cannot load Node.js module ${moduleName} synchronously in ESM. Use async loadNodeModules() instead.`);
1945
+ }
1650
1946
  }
1651
1947
  async function getNodePath() {
1652
1948
  if (_nodePath) return _nodePath;
1653
- _nodePath = nodeRequire("path");
1949
+ const { path } = await loadNodeModules();
1950
+ _nodePath = path;
1654
1951
  return _nodePath;
1655
1952
  }
1656
1953
  async function getNodeFs() {
1657
1954
  if (_nodeFs) return _nodeFs;
1658
- _nodeFs = nodeRequire("fs");
1955
+ const { fs } = await loadNodeModules();
1956
+ _nodeFs = fs;
1659
1957
  return _nodeFs;
1660
1958
  }
1661
1959
  async function getNodeCrypto() {
@@ -1676,29 +1974,41 @@ async function fileExists(filePath) {
1676
1974
  }
1677
1975
  }
1678
1976
  try {
1679
- const nodeFs = nodeRequire("fs");
1680
- return nodeFs.existsSync(filePath);
1977
+ const { fs } = await loadNodeModules();
1978
+ return fs.existsSync(filePath);
1681
1979
  } catch {
1682
1980
  return false;
1683
1981
  }
1684
1982
  }
1685
1983
  async function generateWithdrawRegularProof(inputs, circuitsPath) {
1686
- let wasmPath;
1687
- let zkeyPath;
1984
+ let wasmInput;
1985
+ let zkeyInput;
1986
+ const useUrl = isUrl(circuitsPath);
1688
1987
  if (IS_BROWSER) {
1689
- wasmPath = `${circuitsPath}/withdraw_regular_js/withdraw_regular.wasm`;
1690
- zkeyPath = `${circuitsPath}/withdraw_regular_final.zkey`;
1988
+ wasmInput = `${circuitsPath}/withdraw_regular_js/withdraw_regular.wasm`;
1989
+ zkeyInput = `${circuitsPath}/withdraw_regular_final.zkey`;
1990
+ } else if (useUrl) {
1991
+ const wasmUrl = `${circuitsPath}/withdraw_regular_js/withdraw_regular.wasm`;
1992
+ const zkeyUrl = `${circuitsPath}/withdraw_regular_final.zkey`;
1993
+ const [wasmData, zkeyData] = await Promise.all([
1994
+ fetchFileAsBuffer(wasmUrl),
1995
+ fetchFileAsBuffer(zkeyUrl)
1996
+ ]);
1997
+ wasmInput = wasmData;
1998
+ zkeyInput = zkeyData;
1691
1999
  } else {
1692
- wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1693
- zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
2000
+ const wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
2001
+ const zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
1694
2002
  const wasmExists = await fileExists(wasmPath);
1695
2003
  const zkeyExists = await fileExists(zkeyPath);
1696
2004
  if (!wasmExists) {
1697
- throw new Error(`Circuit WASM not found at ${wasmPath}. Run 'just circuits-compile' in packages-new/circuits first.`);
2005
+ throw new Error(`Circuit WASM not found at ${wasmPath}. Run 'just circuits-compile' in packages/ first.`);
1698
2006
  }
1699
2007
  if (!zkeyExists) {
1700
2008
  throw new Error(`Circuit zkey not found at ${zkeyPath}. Run circuit setup first.`);
1701
2009
  }
2010
+ wasmInput = wasmPath;
2011
+ zkeyInput = zkeyPath;
1702
2012
  }
1703
2013
  const circuitInputs = {
1704
2014
  // Public signals
@@ -1722,7 +2032,7 @@ async function generateWithdrawRegularProof(inputs, circuitsPath) {
1722
2032
  var_fee: inputs.var_fee.toString(),
1723
2033
  rem: inputs.rem.toString()
1724
2034
  };
1725
- const { proof, publicSignals } = await snarkjs.groth16.fullProve(circuitInputs, wasmPath, zkeyPath);
2035
+ const { proof, publicSignals } = await snarkjs.groth16.fullProve(circuitInputs, wasmInput, zkeyInput);
1726
2036
  const proofBytes = proofToBytes(proof);
1727
2037
  return {
1728
2038
  proof,
@@ -1733,22 +2043,34 @@ async function generateWithdrawRegularProof(inputs, circuitsPath) {
1733
2043
  };
1734
2044
  }
1735
2045
  async function generateWithdrawSwapProof(inputs, circuitsPath) {
1736
- let wasmPath;
1737
- let zkeyPath;
2046
+ let wasmInput;
2047
+ let zkeyInput;
2048
+ const useUrl = isUrl(circuitsPath);
1738
2049
  if (IS_BROWSER) {
1739
- wasmPath = `${circuitsPath}/withdraw_swap_js/withdraw_swap.wasm`;
1740
- zkeyPath = `${circuitsPath}/withdraw_swap_final.zkey`;
2050
+ wasmInput = `${circuitsPath}/withdraw_swap_js/withdraw_swap.wasm`;
2051
+ zkeyInput = `${circuitsPath}/withdraw_swap_final.zkey`;
2052
+ } else if (useUrl) {
2053
+ const wasmUrl = `${circuitsPath}/withdraw_swap_js/withdraw_swap.wasm`;
2054
+ const zkeyUrl = `${circuitsPath}/withdraw_swap_final.zkey`;
2055
+ const [wasmData, zkeyData] = await Promise.all([
2056
+ fetchFileAsBuffer(wasmUrl),
2057
+ fetchFileAsBuffer(zkeyUrl)
2058
+ ]);
2059
+ wasmInput = wasmData;
2060
+ zkeyInput = zkeyData;
1741
2061
  } else {
1742
- wasmPath = joinPath(circuitsPath, "build", "withdraw_swap_js", "withdraw_swap.wasm");
1743
- zkeyPath = joinPath(circuitsPath, "build", "withdraw_swap_final.zkey");
2062
+ const wasmPath = joinPath(circuitsPath, "build", "withdraw_swap_js", "withdraw_swap.wasm");
2063
+ const zkeyPath = joinPath(circuitsPath, "build", "withdraw_swap_final.zkey");
1744
2064
  const wasmExists = await fileExists(wasmPath);
1745
2065
  const zkeyExists = await fileExists(zkeyPath);
1746
2066
  if (!wasmExists) {
1747
- throw new Error(`Circuit WASM not found at ${wasmPath}. Run 'just circuits-compile' in packages-new/circuits first.`);
2067
+ throw new Error(`Circuit WASM not found at ${wasmPath}. Run 'just circuits-compile' in packages/ first.`);
1748
2068
  }
1749
2069
  if (!zkeyExists) {
1750
2070
  throw new Error(`Circuit zkey not found at ${zkeyPath}. Run circuit setup first.`);
1751
2071
  }
2072
+ wasmInput = wasmPath;
2073
+ zkeyInput = zkeyPath;
1752
2074
  }
1753
2075
  const sk = splitTo2Limbs(inputs.sk_spend);
1754
2076
  const r = splitTo2Limbs(inputs.r);
@@ -1777,8 +2099,8 @@ async function generateWithdrawSwapProof(inputs, circuitsPath) {
1777
2099
  };
1778
2100
  const { proof, publicSignals } = await snarkjs.groth16.fullProve(
1779
2101
  circuitInputs,
1780
- wasmPath,
1781
- zkeyPath
2102
+ wasmInput,
2103
+ zkeyInput
1782
2104
  );
1783
2105
  const proofBytes = proofToBytes(proof);
1784
2106
  return {
@@ -1790,8 +2112,14 @@ async function generateWithdrawSwapProof(inputs, circuitsPath) {
1790
2112
  };
1791
2113
  }
1792
2114
  async function areCircuitsAvailable(circuitsPath) {
2115
+ if (!circuitsPath || circuitsPath === "") {
2116
+ return false;
2117
+ }
2118
+ if (isUrl(circuitsPath)) {
2119
+ return true;
2120
+ }
1793
2121
  if (IS_BROWSER) {
1794
- return Boolean(circuitsPath && circuitsPath !== "");
2122
+ return true;
1795
2123
  }
1796
2124
  const wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1797
2125
  const zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
@@ -1800,22 +2128,25 @@ async function areCircuitsAvailable(circuitsPath) {
1800
2128
  return wasmExists && zkeyExists;
1801
2129
  }
1802
2130
  async function getDefaultCircuitsPath() {
2131
+ if (typeof process !== "undefined" && process.env?.CIRCUITS_PATH) {
2132
+ return process.env.CIRCUITS_PATH;
2133
+ }
1803
2134
  if (IS_BROWSER) {
1804
2135
  return "/circuits";
1805
2136
  }
1806
2137
  if (typeof process === "undefined" || !process.cwd) {
1807
- return "/circuits";
2138
+ return DEFAULT_CIRCUITS_URL;
1808
2139
  }
1809
2140
  let nodePath;
1810
2141
  try {
1811
2142
  nodePath = await getNodePath();
1812
- } catch {
1813
- return "/circuits";
2143
+ } catch (e) {
2144
+ return DEFAULT_CIRCUITS_URL;
1814
2145
  }
1815
2146
  const possiblePaths = [
1816
- nodePath.resolve(process.cwd(), "../../packages-new/circuits"),
1817
- nodePath.resolve(process.cwd(), "../packages-new/circuits"),
1818
- nodePath.resolve(process.cwd(), "packages-new/circuits"),
2147
+ nodePath.resolve(process.cwd(), "../../packages/circuits"),
2148
+ nodePath.resolve(process.cwd(), "../packages/circuits"),
2149
+ nodePath.resolve(process.cwd(), "packages/circuits"),
1819
2150
  nodePath.resolve(process.cwd(), "../../circuits"),
1820
2151
  nodePath.resolve(process.cwd(), "../circuits")
1821
2152
  ];
@@ -1824,7 +2155,7 @@ async function getDefaultCircuitsPath() {
1824
2155
  return p;
1825
2156
  }
1826
2157
  }
1827
- return possiblePaths[0];
2158
+ return DEFAULT_CIRCUITS_URL;
1828
2159
  }
1829
2160
  var EXPECTED_CIRCUIT_HASHES = {
1830
2161
  // SHA-256 of the verification key JSON from withdraw_regular circuit
@@ -1998,6 +2329,93 @@ function truncate(str, len = 20) {
1998
2329
  }
1999
2330
  var sdkLogger = createLogger("cloak::sdk");
2000
2331
 
2332
+ // src/utils/onchain-proof.ts
2333
+ var MERKLE_TREE_HEIGHT = 32;
2334
+ var SUBTREES_OFFSET = 40;
2335
+ var ROOT_OFFSET = 40 + MERKLE_TREE_HEIGHT * 32;
2336
+ var POSEIDON_ZERO_VALUES = [
2337
+ "0000000000000000000000000000000000000000000000000000000000000000"
2338
+ // level 0
2339
+ ];
2340
+ var zeroValuesComputed = false;
2341
+ async function ensureZeroValues() {
2342
+ if (zeroValuesComputed) return;
2343
+ for (let i = 1; i <= MERKLE_TREE_HEIGHT; i++) {
2344
+ const prevZeroHex = POSEIDON_ZERO_VALUES[i - 1];
2345
+ const prevZeroBigInt = BigInt("0x" + prevZeroHex);
2346
+ const hash = await poseidonHash([prevZeroBigInt, prevZeroBigInt]);
2347
+ POSEIDON_ZERO_VALUES[i] = hash.toString(16).padStart(64, "0");
2348
+ }
2349
+ zeroValuesComputed = true;
2350
+ }
2351
+ async function readMerkleTreeState(connection, merkleTreePDA) {
2352
+ const accountInfo = await connection.getAccountInfo(merkleTreePDA);
2353
+ if (!accountInfo) {
2354
+ throw new Error("Merkle tree account not found");
2355
+ }
2356
+ const data = accountInfo.data;
2357
+ const nextIndex = Number(data.readBigUInt64LE(32));
2358
+ const subtrees = [];
2359
+ for (let i = 0; i < MERKLE_TREE_HEIGHT; i++) {
2360
+ const offset = SUBTREES_OFFSET + i * 32;
2361
+ const subtree = data.slice(offset, offset + 32);
2362
+ subtrees.push(Buffer.from(subtree).toString("hex"));
2363
+ }
2364
+ const root = Buffer.from(data.slice(ROOT_OFFSET, ROOT_OFFSET + 32)).toString("hex");
2365
+ return { nextIndex, root, subtrees };
2366
+ }
2367
+ async function computeProofFromChain(connection, merkleTreePDA, leafIndex) {
2368
+ await ensureZeroValues();
2369
+ const { nextIndex, root, subtrees } = await readMerkleTreeState(connection, merkleTreePDA);
2370
+ if (leafIndex >= nextIndex) {
2371
+ throw new Error(`Leaf index ${leafIndex} is beyond next_index ${nextIndex}`);
2372
+ }
2373
+ const pathElements = [];
2374
+ const pathIndices = [];
2375
+ let index = leafIndex;
2376
+ for (let level = 0; level < MERKLE_TREE_HEIGHT; level++) {
2377
+ pathIndices.push(index % 2);
2378
+ if (index % 2 === 0) {
2379
+ const siblingIndex = index + 1;
2380
+ const levelNextIndex = Math.ceil(nextIndex / (1 << level));
2381
+ if (siblingIndex >= levelNextIndex) {
2382
+ pathElements.push(POSEIDON_ZERO_VALUES[level]);
2383
+ } else {
2384
+ pathElements.push(POSEIDON_ZERO_VALUES[level]);
2385
+ }
2386
+ } else {
2387
+ pathElements.push(subtrees[level]);
2388
+ }
2389
+ index = Math.floor(index / 2);
2390
+ }
2391
+ return { pathElements, pathIndices, root };
2392
+ }
2393
+ async function computeProofForLatestDeposit(connection, merkleTreePDA) {
2394
+ await ensureZeroValues();
2395
+ const { nextIndex, root, subtrees } = await readMerkleTreeState(connection, merkleTreePDA);
2396
+ if (nextIndex === 0) {
2397
+ throw new Error("No leaves in tree");
2398
+ }
2399
+ const leafIndex = nextIndex - 1;
2400
+ const proof = await computeProofInternal(leafIndex, nextIndex, subtrees);
2401
+ return { ...proof, root, leafIndex };
2402
+ }
2403
+ async function computeProofInternal(leafIndex, _nextIndex, subtrees) {
2404
+ const pathElements = [];
2405
+ const pathIndices = [];
2406
+ let index = leafIndex;
2407
+ for (let level = 0; level < MERKLE_TREE_HEIGHT; level++) {
2408
+ pathIndices.push(index % 2);
2409
+ if (index % 2 === 0) {
2410
+ pathElements.push(POSEIDON_ZERO_VALUES[level]);
2411
+ } else {
2412
+ pathElements.push(subtrees[level]);
2413
+ }
2414
+ index = Math.floor(index / 2);
2415
+ }
2416
+ return { pathElements, pathIndices };
2417
+ }
2418
+
2001
2419
  // src/core/CloakSDK.ts
2002
2420
  var COMPUTE_BUDGET_PROGRAM_ID = new PublicKey4("ComputeBudget111111111111111111111111111111");
2003
2421
  function createSetLoadedAccountsDataSizeLimitInstruction(bytes) {
@@ -2326,11 +2744,10 @@ var CloakSDK = class {
2326
2744
  }
2327
2745
  let merkleProof;
2328
2746
  try {
2329
- const { computeProofFromChain: computeProofFromChain2 } = await import("./onchain-proof-CY7AWF43.js");
2330
2747
  const programId2 = this.config.programId || CLOAK_PROGRAM_ID;
2331
2748
  const mintForSOL = new PublicKey4(new Uint8Array(32));
2332
2749
  const { merkleTree: merkleTreePDA } = getShieldPoolPDAs(programId2, mintForSOL);
2333
- const chainProof = await computeProofFromChain2(connection, merkleTreePDA, leafIndex);
2750
+ const chainProof = await computeProofFromChain(connection, merkleTreePDA, leafIndex);
2334
2751
  merkleProof = {
2335
2752
  pathElements: chainProof.pathElements,
2336
2753
  pathIndices: chainProof.pathIndices
@@ -2450,11 +2867,10 @@ var CloakSDK = class {
2450
2867
  merkleProof = note.merkleProof;
2451
2868
  merkleRoot = note.root;
2452
2869
  } else {
2453
- const { computeProofFromChain: computeProofFromChain2 } = await import("./onchain-proof-CY7AWF43.js");
2454
2870
  const programId = this.config.programId || CLOAK_PROGRAM_ID;
2455
2871
  const mintForSOL = new PublicKey4(new Uint8Array(32));
2456
2872
  const { merkleTree: merkleTreePDA } = getShieldPoolPDAs(programId, mintForSOL);
2457
- const chainProof = await computeProofFromChain2(
2873
+ const chainProof = await computeProofFromChain(
2458
2874
  connection,
2459
2875
  merkleTreePDA,
2460
2876
  note.leafIndex
@@ -2776,11 +3192,10 @@ var CloakSDK = class {
2776
3192
  options?.onProgress?.(`proof_refresh_${attempt + 1}`);
2777
3193
  await new Promise((resolve) => setTimeout(resolve, 1e3));
2778
3194
  }
2779
- const { computeProofFromChain: computeProofFromChain2 } = await import("./onchain-proof-CY7AWF43.js");
2780
3195
  const programId = this.config.programId || CLOAK_PROGRAM_ID;
2781
3196
  const mintForSOL = new PublicKey4(new Uint8Array(32));
2782
3197
  const { merkleTree: merkleTreePDA } = getShieldPoolPDAs(programId, mintForSOL);
2783
- const chainProof = await computeProofFromChain2(connection, merkleTreePDA, note.leafIndex);
3198
+ const chainProof = await computeProofFromChain(connection, merkleTreePDA, note.leafIndex);
2784
3199
  const merkleProof = {
2785
3200
  pathElements: chainProof.pathElements,
2786
3201
  pathIndices: chainProof.pathIndices
@@ -2950,11 +3365,10 @@ var CloakSDK = class {
2950
3365
  * @returns Merkle proof computed from on-chain data
2951
3366
  */
2952
3367
  async getMerkleProof(connection, leafIndex) {
2953
- const { computeProofFromChain: computeProofFromChain2 } = await import("./onchain-proof-CY7AWF43.js");
2954
3368
  const programId = this.config.programId || CLOAK_PROGRAM_ID;
2955
3369
  const mintForSOL = new PublicKey4(new Uint8Array(32));
2956
3370
  const { merkleTree: merkleTreePDA } = getShieldPoolPDAs(programId, mintForSOL);
2957
- const chainProof = await computeProofFromChain2(connection, merkleTreePDA, leafIndex);
3371
+ const chainProof = await computeProofFromChain(connection, merkleTreePDA, leafIndex);
2958
3372
  return {
2959
3373
  pathElements: chainProof.pathElements,
2960
3374
  pathIndices: chainProof.pathIndices,
@@ -2968,11 +3382,10 @@ var CloakSDK = class {
2968
3382
  * @returns Current root hash from on-chain tree
2969
3383
  */
2970
3384
  async getCurrentRoot(connection) {
2971
- const { readMerkleTreeState: readMerkleTreeState2 } = await import("./onchain-proof-CY7AWF43.js");
2972
3385
  const programId = this.config.programId || CLOAK_PROGRAM_ID;
2973
3386
  const mintForSOL = new PublicKey4(new Uint8Array(32));
2974
3387
  const { merkleTree: merkleTreePDA } = getShieldPoolPDAs(programId, mintForSOL);
2975
- const state = await readMerkleTreeState2(connection, merkleTreePDA);
3388
+ const state = await readMerkleTreeState(connection, merkleTreePDA);
2976
3389
  return state.root;
2977
3390
  }
2978
3391
  /**
@@ -3442,6 +3855,7 @@ export {
3442
3855
  CLOAK_PROGRAM_ID,
3443
3856
  CloakError,
3444
3857
  CloakSDK,
3858
+ DEFAULT_CIRCUITS_URL,
3445
3859
  EXPECTED_CIRCUIT_HASHES,
3446
3860
  FIXED_FEE_LAMPORTS,
3447
3861
  LAMPORTS_PER_SOL,
@@ -3452,6 +3866,7 @@ export {
3452
3866
  ShieldPoolErrors,
3453
3867
  VARIABLE_FEE_RATE,
3454
3868
  VERSION,
3869
+ areCircuitsAvailable,
3455
3870
  bigintToBytes32,
3456
3871
  buildPublicInputsBytes,
3457
3872
  bytesToHex,
@@ -3501,14 +3916,17 @@ export {
3501
3916
  generateWithdrawRegularProof,
3502
3917
  generateWithdrawSwapProof,
3503
3918
  getAddressExplorerUrl,
3919
+ getDefaultCircuitsPath,
3504
3920
  getDistributableAmount2 as getDistributableAmount,
3505
3921
  getExplorerUrl,
3922
+ getNullifierPDA,
3506
3923
  getPendingOperationsSummary,
3507
3924
  getPublicKey,
3508
3925
  getPublicViewKey,
3509
3926
  getRecipientAmount,
3510
3927
  getRpcUrlForNetwork,
3511
3928
  getShieldPoolPDAs,
3929
+ getSwapStatePDA,
3512
3930
  getViewKey,
3513
3931
  hasPendingOperations,
3514
3932
  hexToBigint,