@cloak.ag/sdk 1.0.5 → 1.0.6

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
@@ -307,14 +307,14 @@ function randomBytes(length) {
307
307
  } catch {
308
308
  }
309
309
  try {
310
- const nodeCrypto2 = require("crypto");
311
- if (nodeCrypto2?.randomBytes) {
312
- const buffer = nodeCrypto2.randomBytes(length);
310
+ const nodeCrypto = require("crypto");
311
+ if (nodeCrypto?.randomBytes) {
312
+ const buffer = nodeCrypto.randomBytes(length);
313
313
  bytes.set(buffer);
314
314
  return bytes;
315
315
  }
316
- if (nodeCrypto2?.webcrypto?.getRandomValues) {
317
- nodeCrypto2.webcrypto.getRandomValues(bytes);
316
+ if (nodeCrypto?.webcrypto?.getRandomValues) {
317
+ nodeCrypto.webcrypto.getRandomValues(bytes);
318
318
  return bytes;
319
319
  }
320
320
  } catch {
@@ -436,8 +436,8 @@ function generateMasterSeed() {
436
436
  cryptoObj.getRandomValues(seed);
437
437
  } else {
438
438
  try {
439
- const nodeCrypto2 = require("crypto");
440
- const buffer = nodeCrypto2.randomBytes(32);
439
+ const nodeCrypto = require("crypto");
440
+ const buffer = nodeCrypto.randomBytes(32);
441
441
  seed.set(buffer);
442
442
  } catch {
443
443
  throw new Error("No secure random number generator available");
@@ -1881,10 +1881,25 @@ function getShieldPoolPDAs(programId, mint) {
1881
1881
  // src/utils/proof-generation.ts
1882
1882
  var snarkjs = __toESM(require("snarkjs"), 1);
1883
1883
  var IS_BROWSER = typeof window !== "undefined" || typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
1884
+ var _nodePath = null;
1885
+ var _nodeFs = null;
1886
+ var _nodeCrypto = null;
1887
+ async function getNodePath() {
1888
+ if (_nodePath) return _nodePath;
1889
+ _nodePath = await import("path");
1890
+ return _nodePath;
1891
+ }
1892
+ async function getNodeFs() {
1893
+ if (_nodeFs) return _nodeFs;
1894
+ _nodeFs = await import("fs");
1895
+ return _nodeFs;
1896
+ }
1897
+ async function getNodeCrypto() {
1898
+ if (_nodeCrypto) return _nodeCrypto;
1899
+ _nodeCrypto = await import("crypto");
1900
+ return _nodeCrypto;
1901
+ }
1884
1902
  function joinPath(...parts) {
1885
- if (IS_BROWSER) {
1886
- return parts.join("/").replace(/\/+/g, "/");
1887
- }
1888
1903
  return parts.join("/").replace(/\/+/g, "/");
1889
1904
  }
1890
1905
  async function fileExists(filePath) {
@@ -1897,9 +1912,9 @@ async function fileExists(filePath) {
1897
1912
  }
1898
1913
  }
1899
1914
  try {
1900
- const nodeFs2 = globalThis.require?.("fs") || (typeof require !== "undefined" ? require("fs") : null);
1901
- if (nodeFs2) {
1902
- return nodeFs2.existsSync(filePath);
1915
+ const nodeFs = globalThis.require?.("fs") || (typeof require !== "undefined" ? require("fs") : null);
1916
+ if (nodeFs) {
1917
+ return nodeFs.existsSync(filePath);
1903
1918
  }
1904
1919
  const fsModule = await import("fs");
1905
1920
  return fsModule.existsSync(filePath);
@@ -1907,15 +1922,15 @@ async function fileExists(filePath) {
1907
1922
  return false;
1908
1923
  }
1909
1924
  }
1910
- async function generateWithdrawRegularProof(inputs, circuitsPath2) {
1925
+ async function generateWithdrawRegularProof(inputs, circuitsPath) {
1911
1926
  let wasmPath;
1912
1927
  let zkeyPath;
1913
1928
  if (IS_BROWSER) {
1914
- wasmPath = `${circuitsPath2}/withdraw_regular_js/withdraw_regular.wasm`;
1915
- zkeyPath = `${circuitsPath2}/withdraw_regular_final.zkey`;
1929
+ wasmPath = `${circuitsPath}/withdraw_regular_js/withdraw_regular.wasm`;
1930
+ zkeyPath = `${circuitsPath}/withdraw_regular_final.zkey`;
1916
1931
  } else {
1917
- wasmPath = joinPath(circuitsPath2, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1918
- zkeyPath = joinPath(circuitsPath2, "build", "withdraw_regular_final.zkey");
1932
+ wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1933
+ zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
1919
1934
  const wasmExists = await fileExists(wasmPath);
1920
1935
  const zkeyExists = await fileExists(zkeyPath);
1921
1936
  if (!wasmExists) {
@@ -1957,15 +1972,15 @@ async function generateWithdrawRegularProof(inputs, circuitsPath2) {
1957
1972
  // Not used, kept for compatibility
1958
1973
  };
1959
1974
  }
1960
- async function generateWithdrawSwapProof(inputs, circuitsPath2) {
1975
+ async function generateWithdrawSwapProof(inputs, circuitsPath) {
1961
1976
  let wasmPath;
1962
1977
  let zkeyPath;
1963
1978
  if (IS_BROWSER) {
1964
- wasmPath = `${circuitsPath2}/withdraw_swap_js/withdraw_swap.wasm`;
1965
- zkeyPath = `${circuitsPath2}/withdraw_swap_final.zkey`;
1979
+ wasmPath = `${circuitsPath}/withdraw_swap_js/withdraw_swap.wasm`;
1980
+ zkeyPath = `${circuitsPath}/withdraw_swap_final.zkey`;
1966
1981
  } else {
1967
- wasmPath = joinPath(circuitsPath2, "build", "withdraw_swap_js", "withdraw_swap.wasm");
1968
- zkeyPath = joinPath(circuitsPath2, "build", "withdraw_swap_final.zkey");
1982
+ wasmPath = joinPath(circuitsPath, "build", "withdraw_swap_js", "withdraw_swap.wasm");
1983
+ zkeyPath = joinPath(circuitsPath, "build", "withdraw_swap_final.zkey");
1969
1984
  const wasmExists = await fileExists(wasmPath);
1970
1985
  const zkeyExists = await fileExists(zkeyPath);
1971
1986
  if (!wasmExists) {
@@ -2014,12 +2029,12 @@ async function generateWithdrawSwapProof(inputs, circuitsPath2) {
2014
2029
  // Not used, kept for compatibility
2015
2030
  };
2016
2031
  }
2017
- async function areCircuitsAvailable(circuitsPath2) {
2032
+ async function areCircuitsAvailable(circuitsPath) {
2018
2033
  if (IS_BROWSER) {
2019
- return Boolean(circuitsPath2 && circuitsPath2 !== "");
2034
+ return Boolean(circuitsPath && circuitsPath !== "");
2020
2035
  }
2021
- const wasmPath = joinPath(circuitsPath2, "build", "withdraw_regular_js", "withdraw_regular.wasm");
2022
- const zkeyPath = joinPath(circuitsPath2, "build", "withdraw_regular_final.zkey");
2036
+ const wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
2037
+ const zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
2023
2038
  const wasmExists = await fileExists(wasmPath);
2024
2039
  const zkeyExists = await fileExists(zkeyPath);
2025
2040
  return wasmExists && zkeyExists;
@@ -2033,7 +2048,7 @@ async function getDefaultCircuitsPath() {
2033
2048
  }
2034
2049
  let nodePath;
2035
2050
  try {
2036
- nodePath = eval("require")("path");
2051
+ nodePath = await getNodePath();
2037
2052
  } catch {
2038
2053
  return "/circuits";
2039
2054
  }
@@ -2083,7 +2098,7 @@ async function verifyCircuitIntegrity(circuitsPath, circuit) {
2083
2098
  vkeyData = await response.text();
2084
2099
  } else {
2085
2100
  try {
2086
- const nodeFs = eval("require")("fs");
2101
+ const nodeFs = await getNodeFs();
2087
2102
  vkeyData = nodeFs.readFileSync(vkeyPath, "utf8");
2088
2103
  } catch (e) {
2089
2104
  return {
@@ -2101,7 +2116,7 @@ async function verifyCircuitIntegrity(circuitsPath, circuit) {
2101
2116
  const hashArray = Array.from(new Uint8Array(hashBuffer));
2102
2117
  computedHash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
2103
2118
  } else {
2104
- const nodeCrypto = eval("require")("crypto");
2119
+ const nodeCrypto = await getNodeCrypto();
2105
2120
  computedHash = nodeCrypto.createHash("sha256").update(vkeyData).digest("hex");
2106
2121
  }
2107
2122
  if (computedHash === expectedHash) {
@@ -2128,15 +2143,26 @@ async function verifyCircuitIntegrity(circuitsPath, circuit) {
2128
2143
  };
2129
2144
  }
2130
2145
  }
2131
- async function verifyAllCircuits(circuitsPath2) {
2146
+ async function verifyAllCircuits(circuitsPath) {
2132
2147
  const results = await Promise.all([
2133
- verifyCircuitIntegrity(circuitsPath2, "withdraw_regular"),
2134
- verifyCircuitIntegrity(circuitsPath2, "withdraw_swap")
2148
+ verifyCircuitIntegrity(circuitsPath, "withdraw_regular"),
2149
+ verifyCircuitIntegrity(circuitsPath, "withdraw_swap")
2135
2150
  ]);
2136
2151
  return results;
2137
2152
  }
2138
2153
 
2139
2154
  // src/core/CloakSDK.ts
2155
+ var COMPUTE_BUDGET_PROGRAM_ID = new import_web35.PublicKey("ComputeBudget111111111111111111111111111111");
2156
+ function createSetLoadedAccountsDataSizeLimitInstruction(bytes) {
2157
+ const data = Buffer.alloc(5);
2158
+ data.writeUInt8(4, 0);
2159
+ data.writeUInt32LE(bytes, 1);
2160
+ return new import_web35.TransactionInstruction({
2161
+ keys: [],
2162
+ programId: COMPUTE_BUDGET_PROGRAM_ID,
2163
+ data
2164
+ });
2165
+ }
2140
2166
  var CLOAK_PROGRAM_ID = new import_web35.PublicKey("c1oak6tetxYnNfvXKFkpn1d98FxtK7B68vBQLYQpWKp");
2141
2167
  var CLOAK_API_URL = "https://api.cloak.ag";
2142
2168
  var CloakSDK = class {
@@ -2297,10 +2323,51 @@ var CloakSDK = class {
2297
2323
  commitment: commitmentBytes
2298
2324
  });
2299
2325
  const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
2326
+ const priorityFee = options?.priorityFee ?? 1e4;
2327
+ const cuPriceIx = import_web35.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee });
2328
+ const dataSizeLimit = options?.loadedAccountsDataSizeLimit ?? 256 * 1024;
2329
+ const dataSizeLimitIx = dataSizeLimit > 0 ? createSetLoadedAccountsDataSizeLimitInstruction(dataSizeLimit) : null;
2330
+ let computeUnits;
2331
+ if (options?.optimizeCU && this.keypair) {
2332
+ options?.onProgress?.("simulating", { message: "Simulating transaction for optimal CU..." });
2333
+ const simCuLimitIx = import_web35.ComputeBudgetProgram.setComputeUnitLimit({ units: 2e5 });
2334
+ const simTransaction = new import_web35.Transaction({
2335
+ feePayer: payerPubkey,
2336
+ recentBlockhash: blockhash
2337
+ }).add(simCuLimitIx).add(cuPriceIx);
2338
+ if (dataSizeLimitIx) {
2339
+ simTransaction.add(dataSizeLimitIx);
2340
+ }
2341
+ simTransaction.add(depositIx);
2342
+ try {
2343
+ const simulation = await connection.simulateTransaction(simTransaction, [this.keypair]);
2344
+ if (simulation.value.err) {
2345
+ console.warn("Simulation failed, using default CU:", simulation.value.err);
2346
+ computeUnits = 4e4;
2347
+ } else {
2348
+ const simulatedCU = simulation.value.unitsConsumed ?? 3e4;
2349
+ computeUnits = Math.ceil(simulatedCU * 1.2);
2350
+ console.log(`CU optimization: ${simulatedCU} simulated \u2192 ${computeUnits} limit`);
2351
+ }
2352
+ } catch (simError) {
2353
+ console.warn("Simulation RPC error, using default CU:", simError);
2354
+ computeUnits = 4e4;
2355
+ }
2356
+ } else if (options?.optimizeCU && this.wallet) {
2357
+ console.warn("CU optimization via simulation not available in wallet mode (would require double signing). Using default.");
2358
+ computeUnits = options?.computeUnits ?? 4e4;
2359
+ } else {
2360
+ computeUnits = options?.computeUnits ?? 4e4;
2361
+ }
2362
+ const cuLimitIx = import_web35.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits });
2300
2363
  const transaction = new import_web35.Transaction({
2301
2364
  feePayer: payerPubkey,
2302
2365
  recentBlockhash: blockhash
2303
- }).add(depositIx);
2366
+ }).add(cuLimitIx).add(cuPriceIx);
2367
+ if (dataSizeLimitIx) {
2368
+ transaction.add(dataSizeLimitIx);
2369
+ }
2370
+ transaction.add(depositIx);
2304
2371
  if (!transaction.feePayer) {
2305
2372
  throw new Error("Transaction feePayer is not set");
2306
2373
  }
@@ -2580,8 +2647,8 @@ var CloakSDK = class {
2580
2647
  }
2581
2648
  }
2582
2649
  const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
2583
- const circuitsPath2 = isBrowser ? "/circuits" : typeof process !== "undefined" && process.env?.CIRCUITS_PATH || await getDefaultCircuitsPath();
2584
- const useDirectProof = await areCircuitsAvailable(circuitsPath2);
2650
+ const circuitsPath = isBrowser ? "/circuits" : typeof process !== "undefined" && process.env?.CIRCUITS_PATH || await getDefaultCircuitsPath();
2651
+ const useDirectProof = await areCircuitsAvailable(circuitsPath);
2585
2652
  let proofHex;
2586
2653
  let finalPublicInputs;
2587
2654
  if (useDirectProof) {
@@ -2643,7 +2710,7 @@ var CloakSDK = class {
2643
2710
  rem
2644
2711
  };
2645
2712
  options?.onProgress?.("proof_generating");
2646
- const proofResult = await generateWithdrawRegularProof(proofInputs, circuitsPath2);
2713
+ const proofResult = await generateWithdrawRegularProof(proofInputs, circuitsPath);
2647
2714
  options?.onProgress?.("proof_complete");
2648
2715
  proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
2649
2716
  finalPublicInputs = {
@@ -2654,7 +2721,7 @@ var CloakSDK = class {
2654
2721
  };
2655
2722
  } else {
2656
2723
  throw new Error(
2657
- `Circuits not available at ${circuitsPath2}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2724
+ `Circuits not available at ${circuitsPath}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2658
2725
  );
2659
2726
  }
2660
2727
  const signature = await this.relay.submitWithdraw(
@@ -2851,8 +2918,8 @@ var CloakSDK = class {
2851
2918
  throw new Error("Merkle proof is invalid: missing path elements");
2852
2919
  }
2853
2920
  const envCircuitsPath = typeof window !== "undefined" ? typeof process !== "undefined" && process.env?.NEXT_PUBLIC_CIRCUITS_PATH || void 0 : typeof process !== "undefined" && process.env?.CIRCUITS_PATH || void 0;
2854
- const circuitsPath2 = envCircuitsPath || await getDefaultCircuitsPath();
2855
- const useDirectProof = await areCircuitsAvailable(circuitsPath2);
2921
+ const circuitsPath = envCircuitsPath || await getDefaultCircuitsPath();
2922
+ const useDirectProof = await areCircuitsAvailable(circuitsPath);
2856
2923
  let proofHex;
2857
2924
  let finalPublicInputs;
2858
2925
  if (useDirectProof) {
@@ -2895,7 +2962,7 @@ var CloakSDK = class {
2895
2962
  rem
2896
2963
  };
2897
2964
  options?.onProgress?.("proof_generating");
2898
- const proofResult = await generateWithdrawSwapProof(proofInputs, circuitsPath2);
2965
+ const proofResult = await generateWithdrawSwapProof(proofInputs, circuitsPath);
2899
2966
  options?.onProgress?.("proof_complete");
2900
2967
  proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
2901
2968
  finalPublicInputs = {
@@ -2906,7 +2973,7 @@ var CloakSDK = class {
2906
2973
  };
2907
2974
  } else {
2908
2975
  throw new Error(
2909
- `Circuits not available at ${circuitsPath2}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2976
+ `Circuits not available at ${circuitsPath}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2910
2977
  );
2911
2978
  }
2912
2979
  const signature = await this.relay.submitSwap(
package/dist/index.d.cts CHANGED
@@ -199,10 +199,46 @@ interface DepositOptions {
199
199
  requireNoteAcknowledgment?: boolean;
200
200
  /** Skip simulation (default: false) */
201
201
  skipPreflight?: boolean;
202
- /** Compute units to request (default: auto) */
202
+ /**
203
+ * Compute units to request.
204
+ * - If `optimizeCU` is true, this is ignored and CU is determined via simulation
205
+ * - Otherwise defaults to 40,000 (suitable for typical deposits)
206
+ */
203
207
  computeUnits?: number;
204
- /** Priority fee in micro-lamports (default: 0) */
208
+ /**
209
+ * Enable simulation-based CU optimization.
210
+ * When true, simulates the transaction first to determine actual CU usage,
211
+ * then sets an optimal limit (simulated + 20% buffer).
212
+ *
213
+ * **Note: Only works in keypair mode (Node.js/scripts).**
214
+ * In wallet/browser mode, this is ignored because simulation would require
215
+ * the user to sign twice (simulation + actual tx) which is bad UX.
216
+ *
217
+ * Trade-offs:
218
+ * - ✅ Optimal block scheduling priority
219
+ * - ❌ Adds ~200-500ms latency (extra RPC call)
220
+ * - ❌ Only available in keypair mode
221
+ *
222
+ * Default: false (uses fixed 40K CU which is ~75% efficient for typical deposits)
223
+ */
224
+ optimizeCU?: boolean;
225
+ /** Priority fee in micro-lamports (default: 10,000) */
205
226
  priorityFee?: number;
227
+ /**
228
+ * Loaded accounts data size limit in bytes.
229
+ *
230
+ * Without this, Solana defaults to 64MB which incurs CU overhead
231
+ * (charged at 8 CU per 32KB). Setting a lower limit improves priority.
232
+ *
233
+ * **Note for Cloak deposits:**
234
+ * The Shield Pool program is ~104KB, so the minimum practical limit is ~128KB.
235
+ *
236
+ * Default: 256 * 1024 (256KB) - provides safety margin above program size.
237
+ * Set to 0 to disable (use Solana 64MB default).
238
+ *
239
+ * @see https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
240
+ */
241
+ loadedAccountsDataSizeLimit?: number;
206
242
  /**
207
243
  * Optional: Encrypt output for specific recipient's view key
208
244
  * If not provided, encrypts for the wallet's own view key (for self-scanning)
package/dist/index.d.ts CHANGED
@@ -199,10 +199,46 @@ interface DepositOptions {
199
199
  requireNoteAcknowledgment?: boolean;
200
200
  /** Skip simulation (default: false) */
201
201
  skipPreflight?: boolean;
202
- /** Compute units to request (default: auto) */
202
+ /**
203
+ * Compute units to request.
204
+ * - If `optimizeCU` is true, this is ignored and CU is determined via simulation
205
+ * - Otherwise defaults to 40,000 (suitable for typical deposits)
206
+ */
203
207
  computeUnits?: number;
204
- /** Priority fee in micro-lamports (default: 0) */
208
+ /**
209
+ * Enable simulation-based CU optimization.
210
+ * When true, simulates the transaction first to determine actual CU usage,
211
+ * then sets an optimal limit (simulated + 20% buffer).
212
+ *
213
+ * **Note: Only works in keypair mode (Node.js/scripts).**
214
+ * In wallet/browser mode, this is ignored because simulation would require
215
+ * the user to sign twice (simulation + actual tx) which is bad UX.
216
+ *
217
+ * Trade-offs:
218
+ * - ✅ Optimal block scheduling priority
219
+ * - ❌ Adds ~200-500ms latency (extra RPC call)
220
+ * - ❌ Only available in keypair mode
221
+ *
222
+ * Default: false (uses fixed 40K CU which is ~75% efficient for typical deposits)
223
+ */
224
+ optimizeCU?: boolean;
225
+ /** Priority fee in micro-lamports (default: 10,000) */
205
226
  priorityFee?: number;
227
+ /**
228
+ * Loaded accounts data size limit in bytes.
229
+ *
230
+ * Without this, Solana defaults to 64MB which incurs CU overhead
231
+ * (charged at 8 CU per 32KB). Setting a lower limit improves priority.
232
+ *
233
+ * **Note for Cloak deposits:**
234
+ * The Shield Pool program is ~104KB, so the minimum practical limit is ~128KB.
235
+ *
236
+ * Default: 256 * 1024 (256KB) - provides safety margin above program size.
237
+ * Set to 0 to disable (use Solana 64MB default).
238
+ *
239
+ * @see https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
240
+ */
241
+ loadedAccountsDataSizeLimit?: number;
206
242
  /**
207
243
  * Optional: Encrypt output for specific recipient's view key
208
244
  * If not provided, encrypts for the wallet's own view key (for self-scanning)
package/dist/index.js CHANGED
@@ -9,7 +9,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
9
9
  import {
10
10
  Keypair,
11
11
  PublicKey as PublicKey4,
12
- Transaction
12
+ Transaction,
13
+ TransactionInstruction as TransactionInstruction2,
14
+ ComputeBudgetProgram
13
15
  } from "@solana/web3.js";
14
16
 
15
17
  // src/core/types.ts
@@ -172,14 +174,14 @@ function randomBytes(length) {
172
174
  } catch {
173
175
  }
174
176
  try {
175
- const nodeCrypto2 = __require("crypto");
176
- if (nodeCrypto2?.randomBytes) {
177
- const buffer = nodeCrypto2.randomBytes(length);
177
+ const nodeCrypto = __require("crypto");
178
+ if (nodeCrypto?.randomBytes) {
179
+ const buffer = nodeCrypto.randomBytes(length);
178
180
  bytes.set(buffer);
179
181
  return bytes;
180
182
  }
181
- if (nodeCrypto2?.webcrypto?.getRandomValues) {
182
- nodeCrypto2.webcrypto.getRandomValues(bytes);
183
+ if (nodeCrypto?.webcrypto?.getRandomValues) {
184
+ nodeCrypto.webcrypto.getRandomValues(bytes);
183
185
  return bytes;
184
186
  }
185
187
  } catch {
@@ -301,8 +303,8 @@ function generateMasterSeed() {
301
303
  cryptoObj.getRandomValues(seed);
302
304
  } else {
303
305
  try {
304
- const nodeCrypto2 = __require("crypto");
305
- const buffer = nodeCrypto2.randomBytes(32);
306
+ const nodeCrypto = __require("crypto");
307
+ const buffer = nodeCrypto.randomBytes(32);
306
308
  seed.set(buffer);
307
309
  } catch {
308
310
  throw new Error("No secure random number generator available");
@@ -1750,10 +1752,25 @@ function getShieldPoolPDAs(programId, mint) {
1750
1752
  // src/utils/proof-generation.ts
1751
1753
  import * as snarkjs from "snarkjs";
1752
1754
  var IS_BROWSER = typeof window !== "undefined" || typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
1755
+ var _nodePath = null;
1756
+ var _nodeFs = null;
1757
+ var _nodeCrypto = null;
1758
+ async function getNodePath() {
1759
+ if (_nodePath) return _nodePath;
1760
+ _nodePath = await import("path");
1761
+ return _nodePath;
1762
+ }
1763
+ async function getNodeFs() {
1764
+ if (_nodeFs) return _nodeFs;
1765
+ _nodeFs = await import("fs");
1766
+ return _nodeFs;
1767
+ }
1768
+ async function getNodeCrypto() {
1769
+ if (_nodeCrypto) return _nodeCrypto;
1770
+ _nodeCrypto = await import("crypto");
1771
+ return _nodeCrypto;
1772
+ }
1753
1773
  function joinPath(...parts) {
1754
- if (IS_BROWSER) {
1755
- return parts.join("/").replace(/\/+/g, "/");
1756
- }
1757
1774
  return parts.join("/").replace(/\/+/g, "/");
1758
1775
  }
1759
1776
  async function fileExists(filePath) {
@@ -1766,9 +1783,9 @@ async function fileExists(filePath) {
1766
1783
  }
1767
1784
  }
1768
1785
  try {
1769
- const nodeFs2 = globalThis.require?.("fs") || (typeof __require !== "undefined" ? __require("fs") : null);
1770
- if (nodeFs2) {
1771
- return nodeFs2.existsSync(filePath);
1786
+ const nodeFs = globalThis.require?.("fs") || (typeof __require !== "undefined" ? __require("fs") : null);
1787
+ if (nodeFs) {
1788
+ return nodeFs.existsSync(filePath);
1772
1789
  }
1773
1790
  const fsModule = await import("fs");
1774
1791
  return fsModule.existsSync(filePath);
@@ -1776,15 +1793,15 @@ async function fileExists(filePath) {
1776
1793
  return false;
1777
1794
  }
1778
1795
  }
1779
- async function generateWithdrawRegularProof(inputs, circuitsPath2) {
1796
+ async function generateWithdrawRegularProof(inputs, circuitsPath) {
1780
1797
  let wasmPath;
1781
1798
  let zkeyPath;
1782
1799
  if (IS_BROWSER) {
1783
- wasmPath = `${circuitsPath2}/withdraw_regular_js/withdraw_regular.wasm`;
1784
- zkeyPath = `${circuitsPath2}/withdraw_regular_final.zkey`;
1800
+ wasmPath = `${circuitsPath}/withdraw_regular_js/withdraw_regular.wasm`;
1801
+ zkeyPath = `${circuitsPath}/withdraw_regular_final.zkey`;
1785
1802
  } else {
1786
- wasmPath = joinPath(circuitsPath2, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1787
- zkeyPath = joinPath(circuitsPath2, "build", "withdraw_regular_final.zkey");
1803
+ wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1804
+ zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
1788
1805
  const wasmExists = await fileExists(wasmPath);
1789
1806
  const zkeyExists = await fileExists(zkeyPath);
1790
1807
  if (!wasmExists) {
@@ -1826,15 +1843,15 @@ async function generateWithdrawRegularProof(inputs, circuitsPath2) {
1826
1843
  // Not used, kept for compatibility
1827
1844
  };
1828
1845
  }
1829
- async function generateWithdrawSwapProof(inputs, circuitsPath2) {
1846
+ async function generateWithdrawSwapProof(inputs, circuitsPath) {
1830
1847
  let wasmPath;
1831
1848
  let zkeyPath;
1832
1849
  if (IS_BROWSER) {
1833
- wasmPath = `${circuitsPath2}/withdraw_swap_js/withdraw_swap.wasm`;
1834
- zkeyPath = `${circuitsPath2}/withdraw_swap_final.zkey`;
1850
+ wasmPath = `${circuitsPath}/withdraw_swap_js/withdraw_swap.wasm`;
1851
+ zkeyPath = `${circuitsPath}/withdraw_swap_final.zkey`;
1835
1852
  } else {
1836
- wasmPath = joinPath(circuitsPath2, "build", "withdraw_swap_js", "withdraw_swap.wasm");
1837
- zkeyPath = joinPath(circuitsPath2, "build", "withdraw_swap_final.zkey");
1853
+ wasmPath = joinPath(circuitsPath, "build", "withdraw_swap_js", "withdraw_swap.wasm");
1854
+ zkeyPath = joinPath(circuitsPath, "build", "withdraw_swap_final.zkey");
1838
1855
  const wasmExists = await fileExists(wasmPath);
1839
1856
  const zkeyExists = await fileExists(zkeyPath);
1840
1857
  if (!wasmExists) {
@@ -1883,12 +1900,12 @@ async function generateWithdrawSwapProof(inputs, circuitsPath2) {
1883
1900
  // Not used, kept for compatibility
1884
1901
  };
1885
1902
  }
1886
- async function areCircuitsAvailable(circuitsPath2) {
1903
+ async function areCircuitsAvailable(circuitsPath) {
1887
1904
  if (IS_BROWSER) {
1888
- return Boolean(circuitsPath2 && circuitsPath2 !== "");
1905
+ return Boolean(circuitsPath && circuitsPath !== "");
1889
1906
  }
1890
- const wasmPath = joinPath(circuitsPath2, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1891
- const zkeyPath = joinPath(circuitsPath2, "build", "withdraw_regular_final.zkey");
1907
+ const wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
1908
+ const zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
1892
1909
  const wasmExists = await fileExists(wasmPath);
1893
1910
  const zkeyExists = await fileExists(zkeyPath);
1894
1911
  return wasmExists && zkeyExists;
@@ -1902,7 +1919,7 @@ async function getDefaultCircuitsPath() {
1902
1919
  }
1903
1920
  let nodePath;
1904
1921
  try {
1905
- nodePath = eval("require")("path");
1922
+ nodePath = await getNodePath();
1906
1923
  } catch {
1907
1924
  return "/circuits";
1908
1925
  }
@@ -1952,7 +1969,7 @@ async function verifyCircuitIntegrity(circuitsPath, circuit) {
1952
1969
  vkeyData = await response.text();
1953
1970
  } else {
1954
1971
  try {
1955
- const nodeFs = eval("require")("fs");
1972
+ const nodeFs = await getNodeFs();
1956
1973
  vkeyData = nodeFs.readFileSync(vkeyPath, "utf8");
1957
1974
  } catch (e) {
1958
1975
  return {
@@ -1970,7 +1987,7 @@ async function verifyCircuitIntegrity(circuitsPath, circuit) {
1970
1987
  const hashArray = Array.from(new Uint8Array(hashBuffer));
1971
1988
  computedHash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
1972
1989
  } else {
1973
- const nodeCrypto = eval("require")("crypto");
1990
+ const nodeCrypto = await getNodeCrypto();
1974
1991
  computedHash = nodeCrypto.createHash("sha256").update(vkeyData).digest("hex");
1975
1992
  }
1976
1993
  if (computedHash === expectedHash) {
@@ -1997,15 +2014,26 @@ async function verifyCircuitIntegrity(circuitsPath, circuit) {
1997
2014
  };
1998
2015
  }
1999
2016
  }
2000
- async function verifyAllCircuits(circuitsPath2) {
2017
+ async function verifyAllCircuits(circuitsPath) {
2001
2018
  const results = await Promise.all([
2002
- verifyCircuitIntegrity(circuitsPath2, "withdraw_regular"),
2003
- verifyCircuitIntegrity(circuitsPath2, "withdraw_swap")
2019
+ verifyCircuitIntegrity(circuitsPath, "withdraw_regular"),
2020
+ verifyCircuitIntegrity(circuitsPath, "withdraw_swap")
2004
2021
  ]);
2005
2022
  return results;
2006
2023
  }
2007
2024
 
2008
2025
  // src/core/CloakSDK.ts
2026
+ var COMPUTE_BUDGET_PROGRAM_ID = new PublicKey4("ComputeBudget111111111111111111111111111111");
2027
+ function createSetLoadedAccountsDataSizeLimitInstruction(bytes) {
2028
+ const data = Buffer.alloc(5);
2029
+ data.writeUInt8(4, 0);
2030
+ data.writeUInt32LE(bytes, 1);
2031
+ return new TransactionInstruction2({
2032
+ keys: [],
2033
+ programId: COMPUTE_BUDGET_PROGRAM_ID,
2034
+ data
2035
+ });
2036
+ }
2009
2037
  var CLOAK_PROGRAM_ID = new PublicKey4("c1oak6tetxYnNfvXKFkpn1d98FxtK7B68vBQLYQpWKp");
2010
2038
  var CLOAK_API_URL = "https://api.cloak.ag";
2011
2039
  var CloakSDK = class {
@@ -2166,10 +2194,51 @@ var CloakSDK = class {
2166
2194
  commitment: commitmentBytes
2167
2195
  });
2168
2196
  const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
2197
+ const priorityFee = options?.priorityFee ?? 1e4;
2198
+ const cuPriceIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee });
2199
+ const dataSizeLimit = options?.loadedAccountsDataSizeLimit ?? 256 * 1024;
2200
+ const dataSizeLimitIx = dataSizeLimit > 0 ? createSetLoadedAccountsDataSizeLimitInstruction(dataSizeLimit) : null;
2201
+ let computeUnits;
2202
+ if (options?.optimizeCU && this.keypair) {
2203
+ options?.onProgress?.("simulating", { message: "Simulating transaction for optimal CU..." });
2204
+ const simCuLimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 2e5 });
2205
+ const simTransaction = new Transaction({
2206
+ feePayer: payerPubkey,
2207
+ recentBlockhash: blockhash
2208
+ }).add(simCuLimitIx).add(cuPriceIx);
2209
+ if (dataSizeLimitIx) {
2210
+ simTransaction.add(dataSizeLimitIx);
2211
+ }
2212
+ simTransaction.add(depositIx);
2213
+ try {
2214
+ const simulation = await connection.simulateTransaction(simTransaction, [this.keypair]);
2215
+ if (simulation.value.err) {
2216
+ console.warn("Simulation failed, using default CU:", simulation.value.err);
2217
+ computeUnits = 4e4;
2218
+ } else {
2219
+ const simulatedCU = simulation.value.unitsConsumed ?? 3e4;
2220
+ computeUnits = Math.ceil(simulatedCU * 1.2);
2221
+ console.log(`CU optimization: ${simulatedCU} simulated \u2192 ${computeUnits} limit`);
2222
+ }
2223
+ } catch (simError) {
2224
+ console.warn("Simulation RPC error, using default CU:", simError);
2225
+ computeUnits = 4e4;
2226
+ }
2227
+ } else if (options?.optimizeCU && this.wallet) {
2228
+ console.warn("CU optimization via simulation not available in wallet mode (would require double signing). Using default.");
2229
+ computeUnits = options?.computeUnits ?? 4e4;
2230
+ } else {
2231
+ computeUnits = options?.computeUnits ?? 4e4;
2232
+ }
2233
+ const cuLimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits });
2169
2234
  const transaction = new Transaction({
2170
2235
  feePayer: payerPubkey,
2171
2236
  recentBlockhash: blockhash
2172
- }).add(depositIx);
2237
+ }).add(cuLimitIx).add(cuPriceIx);
2238
+ if (dataSizeLimitIx) {
2239
+ transaction.add(dataSizeLimitIx);
2240
+ }
2241
+ transaction.add(depositIx);
2173
2242
  if (!transaction.feePayer) {
2174
2243
  throw new Error("Transaction feePayer is not set");
2175
2244
  }
@@ -2449,8 +2518,8 @@ var CloakSDK = class {
2449
2518
  }
2450
2519
  }
2451
2520
  const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
2452
- const circuitsPath2 = isBrowser ? "/circuits" : typeof process !== "undefined" && process.env?.CIRCUITS_PATH || await getDefaultCircuitsPath();
2453
- const useDirectProof = await areCircuitsAvailable(circuitsPath2);
2521
+ const circuitsPath = isBrowser ? "/circuits" : typeof process !== "undefined" && process.env?.CIRCUITS_PATH || await getDefaultCircuitsPath();
2522
+ const useDirectProof = await areCircuitsAvailable(circuitsPath);
2454
2523
  let proofHex;
2455
2524
  let finalPublicInputs;
2456
2525
  if (useDirectProof) {
@@ -2512,7 +2581,7 @@ var CloakSDK = class {
2512
2581
  rem
2513
2582
  };
2514
2583
  options?.onProgress?.("proof_generating");
2515
- const proofResult = await generateWithdrawRegularProof(proofInputs, circuitsPath2);
2584
+ const proofResult = await generateWithdrawRegularProof(proofInputs, circuitsPath);
2516
2585
  options?.onProgress?.("proof_complete");
2517
2586
  proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
2518
2587
  finalPublicInputs = {
@@ -2523,7 +2592,7 @@ var CloakSDK = class {
2523
2592
  };
2524
2593
  } else {
2525
2594
  throw new Error(
2526
- `Circuits not available at ${circuitsPath2}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2595
+ `Circuits not available at ${circuitsPath}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2527
2596
  );
2528
2597
  }
2529
2598
  const signature = await this.relay.submitWithdraw(
@@ -2720,8 +2789,8 @@ var CloakSDK = class {
2720
2789
  throw new Error("Merkle proof is invalid: missing path elements");
2721
2790
  }
2722
2791
  const envCircuitsPath = typeof window !== "undefined" ? typeof process !== "undefined" && process.env?.NEXT_PUBLIC_CIRCUITS_PATH || void 0 : typeof process !== "undefined" && process.env?.CIRCUITS_PATH || void 0;
2723
- const circuitsPath2 = envCircuitsPath || await getDefaultCircuitsPath();
2724
- const useDirectProof = await areCircuitsAvailable(circuitsPath2);
2792
+ const circuitsPath = envCircuitsPath || await getDefaultCircuitsPath();
2793
+ const useDirectProof = await areCircuitsAvailable(circuitsPath);
2725
2794
  let proofHex;
2726
2795
  let finalPublicInputs;
2727
2796
  if (useDirectProof) {
@@ -2764,7 +2833,7 @@ var CloakSDK = class {
2764
2833
  rem
2765
2834
  };
2766
2835
  options?.onProgress?.("proof_generating");
2767
- const proofResult = await generateWithdrawSwapProof(proofInputs, circuitsPath2);
2836
+ const proofResult = await generateWithdrawSwapProof(proofInputs, circuitsPath);
2768
2837
  options?.onProgress?.("proof_complete");
2769
2838
  proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
2770
2839
  finalPublicInputs = {
@@ -2775,7 +2844,7 @@ var CloakSDK = class {
2775
2844
  };
2776
2845
  } else {
2777
2846
  throw new Error(
2778
- `Circuits not available at ${circuitsPath2}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2847
+ `Circuits not available at ${circuitsPath}. Make sure circuits are built and accessible. In browser, circuits should be served from /circuits. In Node.js, set CIRCUITS_PATH environment variable or ensure circuits are in the expected location.`
2779
2848
  );
2780
2849
  }
2781
2850
  const signature = await this.relay.submitSwap(
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloak.ag/sdk",
3
3
  "description": "TypeScript SDK for Cloak",
4
- "version": "1.0.5",
4
+ "version": "1.0.6",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -14,7 +14,7 @@
14
14
  }
15
15
  },
16
16
  "scripts": {
17
- "build": "tsup src/index.ts --format cjs,esm --dts --external fs --external path",
17
+ "build": "tsup src/index.ts --format cjs,esm --dts --external fs --external path --external crypto",
18
18
  "lint": "tsc --noEmit",
19
19
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
20
20
  "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",