@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.cjs +369 -315
- package/dist/index.d.cts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +489 -71
- package/package.json +3 -4
package/dist/index.js
CHANGED
|
@@ -1,33 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
1649
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1680
|
-
return
|
|
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
|
|
1687
|
-
let
|
|
1984
|
+
let wasmInput;
|
|
1985
|
+
let zkeyInput;
|
|
1986
|
+
const useUrl = isUrl(circuitsPath);
|
|
1688
1987
|
if (IS_BROWSER) {
|
|
1689
|
-
|
|
1690
|
-
|
|
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
|
|
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,
|
|
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
|
|
1737
|
-
let
|
|
2046
|
+
let wasmInput;
|
|
2047
|
+
let zkeyInput;
|
|
2048
|
+
const useUrl = isUrl(circuitsPath);
|
|
1738
2049
|
if (IS_BROWSER) {
|
|
1739
|
-
|
|
1740
|
-
|
|
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
|
|
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
|
-
|
|
1781
|
-
|
|
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
|
|
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
|
|
2138
|
+
return DEFAULT_CIRCUITS_URL;
|
|
1808
2139
|
}
|
|
1809
2140
|
let nodePath;
|
|
1810
2141
|
try {
|
|
1811
2142
|
nodePath = await getNodePath();
|
|
1812
|
-
} catch {
|
|
1813
|
-
return
|
|
2143
|
+
} catch (e) {
|
|
2144
|
+
return DEFAULT_CIRCUITS_URL;
|
|
1814
2145
|
}
|
|
1815
2146
|
const possiblePaths = [
|
|
1816
|
-
nodePath.resolve(process.cwd(), "../../packages
|
|
1817
|
-
nodePath.resolve(process.cwd(), "../packages
|
|
1818
|
-
nodePath.resolve(process.cwd(), "packages
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|