@cloak.ag/sdk 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-S76QK36U.js +303 -0
- package/dist/crypto-3TOLQOOK.js +54 -0
- package/dist/index.cjs +42 -222
- package/dist/index.d.cts +9 -128
- package/dist/index.d.ts +9 -128
- package/dist/index.js +42 -221
- package/package.json +9 -5
|
@@ -0,0 +1,303 @@
|
|
|
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
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/utils/crypto.ts
|
|
9
|
+
import { buildPoseidon } from "circomlibjs";
|
|
10
|
+
var poseidon = null;
|
|
11
|
+
async function getPoseidon() {
|
|
12
|
+
if (!poseidon) {
|
|
13
|
+
poseidon = await buildPoseidon();
|
|
14
|
+
}
|
|
15
|
+
return poseidon;
|
|
16
|
+
}
|
|
17
|
+
async function poseidonHash(inputs) {
|
|
18
|
+
const p = await getPoseidon();
|
|
19
|
+
const hash = p(inputs.map((x) => p.F.e(x)));
|
|
20
|
+
return p.F.toObject(hash);
|
|
21
|
+
}
|
|
22
|
+
function splitTo2Limbs(value) {
|
|
23
|
+
const mask = (1n << 128n) - 1n;
|
|
24
|
+
const lo = value & mask;
|
|
25
|
+
const hi = value >> 128n;
|
|
26
|
+
return [lo, hi];
|
|
27
|
+
}
|
|
28
|
+
function pubkeyToLimbs(pubkey) {
|
|
29
|
+
const bytes = typeof pubkey.toBytes === "function" ? pubkey.toBytes() : pubkey;
|
|
30
|
+
const value = BigInt("0x" + Buffer.from(bytes).toString("hex"));
|
|
31
|
+
return splitTo2Limbs(value);
|
|
32
|
+
}
|
|
33
|
+
async function computeMerkleRoot(leaf, pathElements, pathIndices) {
|
|
34
|
+
let current = leaf;
|
|
35
|
+
for (let i = 0; i < pathElements.length; i++) {
|
|
36
|
+
if (pathIndices[i] === 0) {
|
|
37
|
+
current = await poseidonHash([current, pathElements[i]]);
|
|
38
|
+
} else {
|
|
39
|
+
current = await poseidonHash([pathElements[i], current]);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return current;
|
|
43
|
+
}
|
|
44
|
+
function hexToBigint(hex) {
|
|
45
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
46
|
+
return BigInt("0x" + cleanHex);
|
|
47
|
+
}
|
|
48
|
+
async function computeCommitment(amount, r, sk_spend) {
|
|
49
|
+
const [sk0, sk1] = splitTo2Limbs(sk_spend);
|
|
50
|
+
const [r0, r1] = splitTo2Limbs(r);
|
|
51
|
+
const pk_spend = await poseidonHash([sk0, sk1]);
|
|
52
|
+
return await poseidonHash([amount, r0, r1, pk_spend]);
|
|
53
|
+
}
|
|
54
|
+
async function generateCommitmentAsync(amountLamports, r, skSpend) {
|
|
55
|
+
const amount = BigInt(amountLamports);
|
|
56
|
+
const rValue = hexToBigint(bytesToHex(r));
|
|
57
|
+
const skValue = hexToBigint(bytesToHex(skSpend));
|
|
58
|
+
return await computeCommitment(amount, rValue, skValue);
|
|
59
|
+
}
|
|
60
|
+
function generateCommitment(_amountLamports, _r, _skSpend) {
|
|
61
|
+
throw new Error("generateCommitment is deprecated. Use generateCommitmentAsync instead.");
|
|
62
|
+
}
|
|
63
|
+
async function computeNullifier(sk_spend, leafIndex) {
|
|
64
|
+
const [sk0, sk1] = splitTo2Limbs(sk_spend);
|
|
65
|
+
return await poseidonHash([sk0, sk1, leafIndex]);
|
|
66
|
+
}
|
|
67
|
+
async function computeNullifierAsync(skSpend, leafIndex) {
|
|
68
|
+
const skValue = typeof skSpend === "string" ? hexToBigint(skSpend) : hexToBigint(bytesToHex(skSpend));
|
|
69
|
+
return await computeNullifier(skValue, BigInt(leafIndex));
|
|
70
|
+
}
|
|
71
|
+
function computeNullifierSync(_skSpend, _leafIndex) {
|
|
72
|
+
throw new Error("computeNullifierSync is deprecated. Use computeNullifierAsync instead.");
|
|
73
|
+
}
|
|
74
|
+
async function computeOutputsHashAsync(outputs) {
|
|
75
|
+
let hash = 0n;
|
|
76
|
+
for (const output of outputs) {
|
|
77
|
+
const [lo, hi] = pubkeyToLimbs(output.recipient);
|
|
78
|
+
hash = await poseidonHash([hash, lo, hi, BigInt(output.amount)]);
|
|
79
|
+
}
|
|
80
|
+
return hash;
|
|
81
|
+
}
|
|
82
|
+
async function computeOutputsHash(outAddr, outAmount, outFlags) {
|
|
83
|
+
let hash = 0n;
|
|
84
|
+
for (let i = 0; i < 5; i++) {
|
|
85
|
+
if (outFlags[i] === 1) {
|
|
86
|
+
hash = await poseidonHash([hash, outAddr[i][0], outAddr[i][1], outAmount[i]]);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return hash;
|
|
90
|
+
}
|
|
91
|
+
async function computeOutputsHashFromLimbs(outAddr, outAmount, outFlags) {
|
|
92
|
+
return await computeOutputsHash(outAddr, outAmount, outFlags);
|
|
93
|
+
}
|
|
94
|
+
function computeOutputsHashSync(_outputs) {
|
|
95
|
+
throw new Error("computeOutputsHashSync is deprecated. Use computeOutputsHashAsync instead.");
|
|
96
|
+
}
|
|
97
|
+
async function computeSwapOutputsHash(inputMintLimbs, outputMintLimbs, recipientAtaLimbs, minOutputAmount, publicAmount) {
|
|
98
|
+
return await poseidonHash([
|
|
99
|
+
inputMintLimbs[0],
|
|
100
|
+
inputMintLimbs[1],
|
|
101
|
+
outputMintLimbs[0],
|
|
102
|
+
outputMintLimbs[1],
|
|
103
|
+
recipientAtaLimbs[0],
|
|
104
|
+
recipientAtaLimbs[1],
|
|
105
|
+
minOutputAmount,
|
|
106
|
+
publicAmount
|
|
107
|
+
]);
|
|
108
|
+
}
|
|
109
|
+
async function computeSwapOutputsHashAsync(inputMint, outputMint, recipientAta, minOutputAmount, amount) {
|
|
110
|
+
const inputMintLimbs = pubkeyToLimbs(inputMint);
|
|
111
|
+
const outputMintLimbs = pubkeyToLimbs(outputMint);
|
|
112
|
+
const recipientAtaLimbs = pubkeyToLimbs(recipientAta);
|
|
113
|
+
return await computeSwapOutputsHash(
|
|
114
|
+
inputMintLimbs,
|
|
115
|
+
outputMintLimbs,
|
|
116
|
+
recipientAtaLimbs,
|
|
117
|
+
BigInt(minOutputAmount),
|
|
118
|
+
BigInt(amount)
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
function computeSwapOutputsHashSync(_outputMint, _recipientAta, _minOutputAmount, _amount) {
|
|
122
|
+
throw new Error("computeSwapOutputsHashSync is deprecated. Use computeSwapOutputsHashAsync instead.");
|
|
123
|
+
}
|
|
124
|
+
function bigintToBytes32(n) {
|
|
125
|
+
const hex = n.toString(16).padStart(64, "0");
|
|
126
|
+
const bytes = new Uint8Array(32);
|
|
127
|
+
for (let i = 0; i < 32; i++) {
|
|
128
|
+
bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
129
|
+
}
|
|
130
|
+
return bytes;
|
|
131
|
+
}
|
|
132
|
+
function hexToBytes(hex) {
|
|
133
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
134
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
135
|
+
for (let i = 0; i < cleanHex.length; i += 2) {
|
|
136
|
+
bytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16);
|
|
137
|
+
}
|
|
138
|
+
return bytes;
|
|
139
|
+
}
|
|
140
|
+
function bytesToHex(bytes, prefix = false) {
|
|
141
|
+
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
142
|
+
return prefix ? `0x${hex}` : hex;
|
|
143
|
+
}
|
|
144
|
+
function randomBytes(length) {
|
|
145
|
+
const bytes = new Uint8Array(length);
|
|
146
|
+
const g = globalThis;
|
|
147
|
+
try {
|
|
148
|
+
const cryptoObj = g?.crypto || g?.window?.crypto || g?.self?.crypto;
|
|
149
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
150
|
+
cryptoObj.getRandomValues(bytes);
|
|
151
|
+
return bytes;
|
|
152
|
+
}
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
const nodeCrypto = __require("crypto");
|
|
157
|
+
if (nodeCrypto?.randomBytes) {
|
|
158
|
+
const buffer = nodeCrypto.randomBytes(length);
|
|
159
|
+
bytes.set(buffer);
|
|
160
|
+
return bytes;
|
|
161
|
+
}
|
|
162
|
+
if (nodeCrypto?.webcrypto?.getRandomValues) {
|
|
163
|
+
nodeCrypto.webcrypto.getRandomValues(bytes);
|
|
164
|
+
return bytes;
|
|
165
|
+
}
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
168
|
+
for (let i = 0; i < length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
169
|
+
return bytes;
|
|
170
|
+
}
|
|
171
|
+
function isValidHex(hex, expectedLength) {
|
|
172
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
173
|
+
if (!/^[0-9a-f]*$/i.test(cleanHex)) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
if (cleanHex.length % 2 !== 0) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
if (expectedLength !== void 0) {
|
|
180
|
+
return cleanHex.length === expectedLength * 2;
|
|
181
|
+
}
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
var BN254_MODULUS = BigInt("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47");
|
|
185
|
+
function proofToBytes(proof) {
|
|
186
|
+
const pi_a_x = BigInt(proof.pi_a[0]);
|
|
187
|
+
const pi_a_y = BigInt(proof.pi_a[1]);
|
|
188
|
+
const pi_a_y_neg = (BN254_MODULUS - pi_a_y) % BN254_MODULUS;
|
|
189
|
+
const pi_a_x_le = bigintToBytes32LE(pi_a_x);
|
|
190
|
+
const pi_a_y_neg_le = bigintToBytes32LE(pi_a_y_neg);
|
|
191
|
+
const pi_a_le = new Uint8Array(64);
|
|
192
|
+
pi_a_le.set(pi_a_x_le, 0);
|
|
193
|
+
pi_a_le.set(pi_a_y_neg_le, 32);
|
|
194
|
+
const pi_a_be = convertEndianness32(pi_a_le);
|
|
195
|
+
const pi_b_x1 = BigInt(proof.pi_b[0][0]);
|
|
196
|
+
const pi_b_x2 = BigInt(proof.pi_b[0][1]);
|
|
197
|
+
const pi_b_y1 = BigInt(proof.pi_b[1][0]);
|
|
198
|
+
const pi_b_y2 = BigInt(proof.pi_b[1][1]);
|
|
199
|
+
const pi_b_x1_le = bigintToBytes32LE(pi_b_x1);
|
|
200
|
+
const pi_b_x2_le = bigintToBytes32LE(pi_b_x2);
|
|
201
|
+
const pi_b_y1_le = bigintToBytes32LE(pi_b_y1);
|
|
202
|
+
const pi_b_y2_le = bigintToBytes32LE(pi_b_y2);
|
|
203
|
+
const pi_b_le = new Uint8Array(128);
|
|
204
|
+
pi_b_le.set(pi_b_x1_le, 0);
|
|
205
|
+
pi_b_le.set(pi_b_x2_le, 32);
|
|
206
|
+
pi_b_le.set(pi_b_y1_le, 64);
|
|
207
|
+
pi_b_le.set(pi_b_y2_le, 96);
|
|
208
|
+
const pi_b_be = convertEndianness64(pi_b_le);
|
|
209
|
+
const pi_c_x = BigInt(proof.pi_c[0]);
|
|
210
|
+
const pi_c_y = BigInt(proof.pi_c[1]);
|
|
211
|
+
const pi_c_x_le = bigintToBytes32LE(pi_c_x);
|
|
212
|
+
const pi_c_y_le = bigintToBytes32LE(pi_c_y);
|
|
213
|
+
const pi_c_le = new Uint8Array(64);
|
|
214
|
+
pi_c_le.set(pi_c_x_le, 0);
|
|
215
|
+
pi_c_le.set(pi_c_y_le, 32);
|
|
216
|
+
const pi_c_be = convertEndianness32(pi_c_le);
|
|
217
|
+
const result = new Uint8Array(256);
|
|
218
|
+
result.set(pi_a_be, 0);
|
|
219
|
+
result.set(pi_b_be, 64);
|
|
220
|
+
result.set(pi_c_be, 192);
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
function bigintToBytes32LE(n) {
|
|
224
|
+
const bytes = new Uint8Array(32);
|
|
225
|
+
let value = n % BN254_MODULUS;
|
|
226
|
+
if (value < 0) {
|
|
227
|
+
value = (value + BN254_MODULUS) % BN254_MODULUS;
|
|
228
|
+
}
|
|
229
|
+
for (let i = 0; i < 32; i++) {
|
|
230
|
+
bytes[i] = Number(value & BigInt(255));
|
|
231
|
+
value = value >> BigInt(8);
|
|
232
|
+
}
|
|
233
|
+
return bytes;
|
|
234
|
+
}
|
|
235
|
+
function convertEndianness32(bytes) {
|
|
236
|
+
if (bytes.length !== 64) {
|
|
237
|
+
throw new Error("convertEndianness32 expects 64 bytes");
|
|
238
|
+
}
|
|
239
|
+
const result = new Uint8Array(64);
|
|
240
|
+
for (let i = 0; i < 32; i++) {
|
|
241
|
+
result[i] = bytes[31 - i];
|
|
242
|
+
}
|
|
243
|
+
for (let i = 0; i < 32; i++) {
|
|
244
|
+
result[32 + i] = bytes[63 - i];
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
248
|
+
function convertEndianness64(bytes) {
|
|
249
|
+
if (bytes.length !== 128) {
|
|
250
|
+
throw new Error("convertEndianness64 expects 128 bytes");
|
|
251
|
+
}
|
|
252
|
+
const result = new Uint8Array(128);
|
|
253
|
+
for (let i = 0; i < 64; i++) {
|
|
254
|
+
result[i] = bytes[63 - i];
|
|
255
|
+
}
|
|
256
|
+
for (let i = 0; i < 64; i++) {
|
|
257
|
+
result[64 + i] = bytes[127 - i];
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
function buildPublicInputsBytes(root, nullifier, outputsHash, publicAmount) {
|
|
262
|
+
const result = new Uint8Array(104);
|
|
263
|
+
result.set(bigintToBytes32(root), 0);
|
|
264
|
+
result.set(bigintToBytes32(nullifier), 32);
|
|
265
|
+
result.set(bigintToBytes32(outputsHash), 64);
|
|
266
|
+
const amountBytes = new Uint8Array(8);
|
|
267
|
+
let amt = publicAmount;
|
|
268
|
+
for (let i = 7; i >= 0; i--) {
|
|
269
|
+
amountBytes[i] = Number(amt & 0xffn);
|
|
270
|
+
amt = amt >> 8n;
|
|
271
|
+
}
|
|
272
|
+
result.set(amountBytes, 96);
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export {
|
|
277
|
+
__require,
|
|
278
|
+
poseidonHash,
|
|
279
|
+
splitTo2Limbs,
|
|
280
|
+
pubkeyToLimbs,
|
|
281
|
+
computeMerkleRoot,
|
|
282
|
+
hexToBigint,
|
|
283
|
+
computeCommitment,
|
|
284
|
+
generateCommitmentAsync,
|
|
285
|
+
generateCommitment,
|
|
286
|
+
computeNullifier,
|
|
287
|
+
computeNullifierAsync,
|
|
288
|
+
computeNullifierSync,
|
|
289
|
+
computeOutputsHashAsync,
|
|
290
|
+
computeOutputsHash,
|
|
291
|
+
computeOutputsHashFromLimbs,
|
|
292
|
+
computeOutputsHashSync,
|
|
293
|
+
computeSwapOutputsHash,
|
|
294
|
+
computeSwapOutputsHashAsync,
|
|
295
|
+
computeSwapOutputsHashSync,
|
|
296
|
+
bigintToBytes32,
|
|
297
|
+
hexToBytes,
|
|
298
|
+
bytesToHex,
|
|
299
|
+
randomBytes,
|
|
300
|
+
isValidHex,
|
|
301
|
+
proofToBytes,
|
|
302
|
+
buildPublicInputsBytes
|
|
303
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bigintToBytes32,
|
|
3
|
+
buildPublicInputsBytes,
|
|
4
|
+
bytesToHex,
|
|
5
|
+
computeCommitment,
|
|
6
|
+
computeMerkleRoot,
|
|
7
|
+
computeNullifier,
|
|
8
|
+
computeNullifierAsync,
|
|
9
|
+
computeNullifierSync,
|
|
10
|
+
computeOutputsHash,
|
|
11
|
+
computeOutputsHashAsync,
|
|
12
|
+
computeOutputsHashFromLimbs,
|
|
13
|
+
computeOutputsHashSync,
|
|
14
|
+
computeSwapOutputsHash,
|
|
15
|
+
computeSwapOutputsHashAsync,
|
|
16
|
+
computeSwapOutputsHashSync,
|
|
17
|
+
generateCommitment,
|
|
18
|
+
generateCommitmentAsync,
|
|
19
|
+
hexToBigint,
|
|
20
|
+
hexToBytes,
|
|
21
|
+
isValidHex,
|
|
22
|
+
poseidonHash,
|
|
23
|
+
proofToBytes,
|
|
24
|
+
pubkeyToLimbs,
|
|
25
|
+
randomBytes,
|
|
26
|
+
splitTo2Limbs
|
|
27
|
+
} from "./chunk-S76QK36U.js";
|
|
28
|
+
export {
|
|
29
|
+
bigintToBytes32,
|
|
30
|
+
buildPublicInputsBytes,
|
|
31
|
+
bytesToHex,
|
|
32
|
+
computeCommitment,
|
|
33
|
+
computeMerkleRoot,
|
|
34
|
+
computeNullifier,
|
|
35
|
+
computeNullifierAsync,
|
|
36
|
+
computeNullifierSync,
|
|
37
|
+
computeOutputsHash,
|
|
38
|
+
computeOutputsHashAsync,
|
|
39
|
+
computeOutputsHashFromLimbs,
|
|
40
|
+
computeOutputsHashSync,
|
|
41
|
+
computeSwapOutputsHash,
|
|
42
|
+
computeSwapOutputsHashAsync,
|
|
43
|
+
computeSwapOutputsHashSync,
|
|
44
|
+
generateCommitment,
|
|
45
|
+
generateCommitmentAsync,
|
|
46
|
+
hexToBigint,
|
|
47
|
+
hexToBytes,
|
|
48
|
+
isValidHex,
|
|
49
|
+
poseidonHash,
|
|
50
|
+
proofToBytes,
|
|
51
|
+
pubkeyToLimbs,
|
|
52
|
+
randomBytes,
|
|
53
|
+
splitTo2Limbs
|
|
54
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -39,7 +39,6 @@ __export(index_exports, {
|
|
|
39
39
|
LAMPORTS_PER_SOL: () => LAMPORTS_PER_SOL,
|
|
40
40
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
41
41
|
MemoryStorageAdapter: () => MemoryStorageAdapter,
|
|
42
|
-
ProverService: () => ProverService,
|
|
43
42
|
RelayService: () => RelayService,
|
|
44
43
|
VARIABLE_FEE_RATE: () => VARIABLE_FEE_RATE,
|
|
45
44
|
VERSION: () => VERSION,
|
|
@@ -1828,11 +1827,7 @@ async function generateWithdrawRegularProof(inputs, circuitsPath) {
|
|
|
1828
1827
|
var_fee: inputs.var_fee.toString(),
|
|
1829
1828
|
rem: inputs.rem.toString()
|
|
1830
1829
|
};
|
|
1831
|
-
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
|
1832
|
-
circuitInputs,
|
|
1833
|
-
wasmPath,
|
|
1834
|
-
zkeyPath
|
|
1835
|
-
);
|
|
1830
|
+
const { proof, publicSignals } = await snarkjs.groth16.fullProve(circuitInputs, wasmPath, zkeyPath);
|
|
1836
1831
|
const proofBytes = proofToBytes(proof);
|
|
1837
1832
|
return {
|
|
1838
1833
|
proof,
|
|
@@ -2308,17 +2303,10 @@ var CloakSDK = class {
|
|
|
2308
2303
|
const feeBps = Math.ceil(protocolFee * 1e4 / note.amount);
|
|
2309
2304
|
const distributableAmount = getDistributableAmount2(note.amount);
|
|
2310
2305
|
validateTransfers(recipients, distributableAmount);
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
if (
|
|
2314
|
-
|
|
2315
|
-
pathElements: note.merkleProof.pathElements,
|
|
2316
|
-
pathIndices: note.merkleProof.pathIndices
|
|
2317
|
-
};
|
|
2318
|
-
merkleRoot = note.root;
|
|
2319
|
-
} else {
|
|
2320
|
-
merkleProof = await this.indexer.getMerkleProof(note.leafIndex);
|
|
2321
|
-
merkleRoot = merkleProof.root || (await this.indexer.getMerkleRoot()).root;
|
|
2306
|
+
const merkleProof = await this.indexer.getMerkleProof(note.leafIndex);
|
|
2307
|
+
const merkleRoot = merkleProof.root || (await this.indexer.getMerkleRoot()).root;
|
|
2308
|
+
if (!merkleRoot) {
|
|
2309
|
+
throw new Error("Failed to get Merkle root from indexer");
|
|
2322
2310
|
}
|
|
2323
2311
|
const nullifier = await computeNullifierAsync(note.sk_spend, note.leafIndex);
|
|
2324
2312
|
const nullifierHex = nullifier.toString(16).padStart(64, "0");
|
|
@@ -2392,6 +2380,13 @@ var CloakSDK = class {
|
|
|
2392
2380
|
}
|
|
2393
2381
|
const sk = splitTo2Limbs(sk_spend_bigint);
|
|
2394
2382
|
const r = splitTo2Limbs(r_bigint);
|
|
2383
|
+
const computedCommitment = await computeCommitment(amount_bigint, r_bigint, sk_spend_bigint);
|
|
2384
|
+
const noteCommitment = BigInt("0x" + note.commitment);
|
|
2385
|
+
if (computedCommitment !== noteCommitment) {
|
|
2386
|
+
throw new Error(
|
|
2387
|
+
`Commitment mismatch! Computed: ${computedCommitment.toString(16)}, Note: ${note.commitment}. This means the note's sk_spend, r, or amount doesn't match what was deposited.`
|
|
2388
|
+
);
|
|
2389
|
+
}
|
|
2395
2390
|
const proofInputs = {
|
|
2396
2391
|
root: root_bigint,
|
|
2397
2392
|
nullifier: nullifier_bigint,
|
|
@@ -2410,7 +2405,9 @@ var CloakSDK = class {
|
|
|
2410
2405
|
var_fee: varFee,
|
|
2411
2406
|
rem
|
|
2412
2407
|
};
|
|
2408
|
+
options?.onProgress?.("proof_generating");
|
|
2413
2409
|
const proofResult = await generateWithdrawRegularProof(proofInputs, circuitsPath);
|
|
2410
|
+
options?.onProgress?.("proof_complete");
|
|
2414
2411
|
proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
|
|
2415
2412
|
finalPublicInputs = {
|
|
2416
2413
|
root: merkleRoot,
|
|
@@ -2576,30 +2573,27 @@ var CloakSDK = class {
|
|
|
2576
2573
|
);
|
|
2577
2574
|
}
|
|
2578
2575
|
let recipientAta;
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2576
|
+
if (options.recipientAta) {
|
|
2577
|
+
recipientAta = new import_web35.PublicKey(options.recipientAta);
|
|
2578
|
+
} else {
|
|
2579
|
+
try {
|
|
2580
|
+
const splTokenModule = await import("@solana/spl-token");
|
|
2581
|
+
const getAssociatedTokenAddress = splTokenModule.getAssociatedTokenAddress;
|
|
2582
|
+
if (!getAssociatedTokenAddress) {
|
|
2583
|
+
throw new Error("getAssociatedTokenAddress not found");
|
|
2584
|
+
}
|
|
2585
|
+
const outputMint2 = new import_web35.PublicKey(options.outputMint);
|
|
2586
|
+
recipientAta = await getAssociatedTokenAddress(outputMint2, recipient);
|
|
2587
|
+
} catch (error) {
|
|
2588
|
+
throw new Error(
|
|
2589
|
+
`Failed to get associated token account: ${error instanceof Error ? error.message : String(error)}. Please install @solana/spl-token or provide recipientAta in options.`
|
|
2590
|
+
);
|
|
2584
2591
|
}
|
|
2585
|
-
const outputMint2 = new import_web35.PublicKey(options.outputMint);
|
|
2586
|
-
recipientAta = await getAssociatedTokenAddress(outputMint2, recipient);
|
|
2587
|
-
} catch (error) {
|
|
2588
|
-
throw new Error(
|
|
2589
|
-
`Failed to get associated token account: ${error instanceof Error ? error.message : String(error)}. Please install @solana/spl-token or provide recipientAta in options.`
|
|
2590
|
-
);
|
|
2591
2592
|
}
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
if (
|
|
2595
|
-
|
|
2596
|
-
pathElements: note.merkleProof.pathElements,
|
|
2597
|
-
pathIndices: note.merkleProof.pathIndices
|
|
2598
|
-
};
|
|
2599
|
-
merkleRoot = note.root;
|
|
2600
|
-
} else {
|
|
2601
|
-
merkleProof = await this.indexer.getMerkleProof(note.leafIndex);
|
|
2602
|
-
merkleRoot = merkleProof.root || (await this.indexer.getMerkleRoot()).root;
|
|
2593
|
+
const merkleProof = await this.indexer.getMerkleProof(note.leafIndex);
|
|
2594
|
+
const merkleRoot = merkleProof.root || (await this.indexer.getMerkleRoot()).root;
|
|
2595
|
+
if (!merkleRoot) {
|
|
2596
|
+
throw new Error("Failed to get Merkle root from indexer");
|
|
2603
2597
|
}
|
|
2604
2598
|
const nullifier = await computeNullifierAsync(note.sk_spend, note.leafIndex);
|
|
2605
2599
|
const nullifierHex = nullifier.toString(16).padStart(64, "0");
|
|
@@ -2635,6 +2629,13 @@ var CloakSDK = class {
|
|
|
2635
2629
|
const inputMintLimbs = pubkeyToLimbs(inputMint.toBytes());
|
|
2636
2630
|
const outputMintLimbs = pubkeyToLimbs(outputMint.toBytes());
|
|
2637
2631
|
const recipientAtaLimbs = pubkeyToLimbs(recipientAta.toBytes());
|
|
2632
|
+
const computedCommitment = await computeCommitment(amount_bigint, r_bigint, sk_spend_bigint);
|
|
2633
|
+
const noteCommitment = BigInt("0x" + note.commitment);
|
|
2634
|
+
if (computedCommitment !== noteCommitment) {
|
|
2635
|
+
throw new Error(
|
|
2636
|
+
`Commitment mismatch! Computed: ${computedCommitment.toString(16)}, Note: ${note.commitment}. This means the note's sk_spend, r, or amount doesn't match what was deposited.`
|
|
2637
|
+
);
|
|
2638
|
+
}
|
|
2638
2639
|
const t = amount_bigint * 5n;
|
|
2639
2640
|
const varFee = t / 1000n;
|
|
2640
2641
|
const rem = t % 1000n;
|
|
@@ -2656,7 +2657,9 @@ var CloakSDK = class {
|
|
|
2656
2657
|
var_fee: varFee,
|
|
2657
2658
|
rem
|
|
2658
2659
|
};
|
|
2660
|
+
options?.onProgress?.("proof_generating");
|
|
2659
2661
|
const proofResult = await generateWithdrawSwapProof(proofInputs, circuitsPath);
|
|
2662
|
+
options?.onProgress?.("proof_complete");
|
|
2660
2663
|
proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
|
|
2661
2664
|
finalPublicInputs = {
|
|
2662
2665
|
root: merkleRoot,
|
|
@@ -3176,188 +3179,6 @@ function formatErrorForLogging(error) {
|
|
|
3176
3179
|
return String(error);
|
|
3177
3180
|
}
|
|
3178
3181
|
|
|
3179
|
-
// src/services/ProverService.ts
|
|
3180
|
-
var ProverService = class {
|
|
3181
|
-
/**
|
|
3182
|
-
* Create a new Prover Service client
|
|
3183
|
-
*
|
|
3184
|
-
* @param indexerUrl - Indexer/Prover service base URL
|
|
3185
|
-
* @param timeout - Proof generation timeout in ms (default: 5 minutes)
|
|
3186
|
-
*/
|
|
3187
|
-
constructor(indexerUrl, timeout = 5 * 60 * 1e3) {
|
|
3188
|
-
this.indexerUrl = indexerUrl.replace(/\/$/, "");
|
|
3189
|
-
this.timeout = timeout;
|
|
3190
|
-
}
|
|
3191
|
-
/**
|
|
3192
|
-
* Generate a zero-knowledge proof for withdrawal
|
|
3193
|
-
*
|
|
3194
|
-
* This process typically takes 30-180 seconds depending on the backend.
|
|
3195
|
-
*
|
|
3196
|
-
* @param inputs - Circuit inputs (private + public + outputs)
|
|
3197
|
-
* @param options - Optional progress tracking and callbacks
|
|
3198
|
-
* @returns Proof result with hex-encoded proof and public inputs
|
|
3199
|
-
*
|
|
3200
|
-
* @example
|
|
3201
|
-
* ```typescript
|
|
3202
|
-
* const result = await prover.generateProof(inputs);
|
|
3203
|
-
* if (result.success) {
|
|
3204
|
-
* console.log(`Proof: ${result.proof}`);
|
|
3205
|
-
* }
|
|
3206
|
-
* ```
|
|
3207
|
-
*
|
|
3208
|
-
* @example
|
|
3209
|
-
* ```typescript
|
|
3210
|
-
* // With progress tracking
|
|
3211
|
-
* const result = await prover.generateProof(inputs, {
|
|
3212
|
-
* onProgress: (progress) => console.log(`Progress: ${progress}%`),
|
|
3213
|
-
* onStart: () => console.log("Starting proof generation..."),
|
|
3214
|
-
* onSuccess: (result) => console.log("Proof generated!"),
|
|
3215
|
-
* onError: (error) => console.error("Failed:", error)
|
|
3216
|
-
* });
|
|
3217
|
-
* ```
|
|
3218
|
-
*/
|
|
3219
|
-
async generateProof(inputs, options) {
|
|
3220
|
-
const startTime = Date.now();
|
|
3221
|
-
const actualTimeout = options?.timeout || this.timeout;
|
|
3222
|
-
options?.onStart?.();
|
|
3223
|
-
let progressInterval;
|
|
3224
|
-
try {
|
|
3225
|
-
const requestBody = {
|
|
3226
|
-
private_inputs: JSON.stringify(inputs.privateInputs),
|
|
3227
|
-
public_inputs: JSON.stringify(inputs.publicInputs),
|
|
3228
|
-
outputs: JSON.stringify(inputs.outputs)
|
|
3229
|
-
};
|
|
3230
|
-
if (inputs.swapParams) {
|
|
3231
|
-
requestBody.swap_params = inputs.swapParams;
|
|
3232
|
-
}
|
|
3233
|
-
const controller = new AbortController();
|
|
3234
|
-
const timeoutId = setTimeout(() => controller.abort(), actualTimeout);
|
|
3235
|
-
if (options?.onProgress) {
|
|
3236
|
-
let progress = 0;
|
|
3237
|
-
progressInterval = setInterval(() => {
|
|
3238
|
-
progress = Math.min(90, progress + Math.random() * 10);
|
|
3239
|
-
options.onProgress(Math.floor(progress));
|
|
3240
|
-
}, 2e3);
|
|
3241
|
-
}
|
|
3242
|
-
const response = await fetch(`${this.indexerUrl}/api/v1/prove`, {
|
|
3243
|
-
method: "POST",
|
|
3244
|
-
headers: {
|
|
3245
|
-
"Content-Type": "application/json"
|
|
3246
|
-
},
|
|
3247
|
-
body: JSON.stringify(requestBody),
|
|
3248
|
-
signal: controller.signal
|
|
3249
|
-
});
|
|
3250
|
-
clearTimeout(timeoutId);
|
|
3251
|
-
if (progressInterval) clearInterval(progressInterval);
|
|
3252
|
-
if (!response.ok) {
|
|
3253
|
-
let errorMessage = `${response.status} ${response.statusText}`;
|
|
3254
|
-
try {
|
|
3255
|
-
const errorText = await response.text();
|
|
3256
|
-
try {
|
|
3257
|
-
const errorJson = JSON.parse(errorText);
|
|
3258
|
-
errorMessage = errorJson.error || errorJson.message || errorText;
|
|
3259
|
-
} catch {
|
|
3260
|
-
errorMessage = errorText || errorMessage;
|
|
3261
|
-
}
|
|
3262
|
-
} catch {
|
|
3263
|
-
}
|
|
3264
|
-
options?.onError?.(errorMessage);
|
|
3265
|
-
return {
|
|
3266
|
-
success: false,
|
|
3267
|
-
generationTimeMs: Date.now() - startTime,
|
|
3268
|
-
error: errorMessage
|
|
3269
|
-
};
|
|
3270
|
-
}
|
|
3271
|
-
options?.onProgress?.(100);
|
|
3272
|
-
const rawData = await response.json();
|
|
3273
|
-
const result = {
|
|
3274
|
-
success: rawData.success,
|
|
3275
|
-
proof: rawData.proof,
|
|
3276
|
-
publicInputs: rawData.public_inputs,
|
|
3277
|
-
// Map snake_case
|
|
3278
|
-
generationTimeMs: rawData.generation_time_ms || Date.now() - startTime,
|
|
3279
|
-
error: rawData.error
|
|
3280
|
-
};
|
|
3281
|
-
if (!result.success && rawData.execution_report) {
|
|
3282
|
-
}
|
|
3283
|
-
if (!result.success && result.error) {
|
|
3284
|
-
try {
|
|
3285
|
-
const errorObj = typeof result.error === "string" ? JSON.parse(result.error) : result.error;
|
|
3286
|
-
if (errorObj?.error && typeof errorObj.error === "string") {
|
|
3287
|
-
result.error = errorObj.error;
|
|
3288
|
-
} else if (typeof errorObj === "string") {
|
|
3289
|
-
result.error = errorObj;
|
|
3290
|
-
}
|
|
3291
|
-
if (errorObj?.execution_report && typeof errorObj.execution_report === "string") {
|
|
3292
|
-
result.error += `
|
|
3293
|
-
Execution report: ${errorObj.execution_report}`;
|
|
3294
|
-
}
|
|
3295
|
-
if (errorObj?.total_cycles !== void 0) {
|
|
3296
|
-
result.error += `
|
|
3297
|
-
Total cycles: ${errorObj.total_cycles}`;
|
|
3298
|
-
}
|
|
3299
|
-
if (errorObj?.total_syscalls !== void 0) {
|
|
3300
|
-
result.error += `
|
|
3301
|
-
Total syscalls: ${errorObj.total_syscalls}`;
|
|
3302
|
-
}
|
|
3303
|
-
} catch {
|
|
3304
|
-
}
|
|
3305
|
-
}
|
|
3306
|
-
if (result.success) {
|
|
3307
|
-
options?.onSuccess?.(result);
|
|
3308
|
-
} else if (result.error) {
|
|
3309
|
-
options?.onError?.(result.error);
|
|
3310
|
-
}
|
|
3311
|
-
return result;
|
|
3312
|
-
} catch (error) {
|
|
3313
|
-
const totalTime = Date.now() - startTime;
|
|
3314
|
-
if (progressInterval) clearInterval(progressInterval);
|
|
3315
|
-
let errorMessage;
|
|
3316
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
3317
|
-
errorMessage = `Proof generation timed out after ${actualTimeout}ms`;
|
|
3318
|
-
} else {
|
|
3319
|
-
errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
3320
|
-
}
|
|
3321
|
-
options?.onError?.(errorMessage);
|
|
3322
|
-
return {
|
|
3323
|
-
success: false,
|
|
3324
|
-
generationTimeMs: totalTime,
|
|
3325
|
-
error: errorMessage
|
|
3326
|
-
};
|
|
3327
|
-
}
|
|
3328
|
-
}
|
|
3329
|
-
/**
|
|
3330
|
-
* Check if the prover service is available
|
|
3331
|
-
*
|
|
3332
|
-
* @returns True if service is healthy
|
|
3333
|
-
*/
|
|
3334
|
-
async healthCheck() {
|
|
3335
|
-
try {
|
|
3336
|
-
const response = await fetch(`${this.indexerUrl}/health`, {
|
|
3337
|
-
method: "GET"
|
|
3338
|
-
});
|
|
3339
|
-
return response.ok;
|
|
3340
|
-
} catch {
|
|
3341
|
-
return false;
|
|
3342
|
-
}
|
|
3343
|
-
}
|
|
3344
|
-
/**
|
|
3345
|
-
* Get the configured timeout
|
|
3346
|
-
*/
|
|
3347
|
-
getTimeout() {
|
|
3348
|
-
return this.timeout;
|
|
3349
|
-
}
|
|
3350
|
-
/**
|
|
3351
|
-
* Set a new timeout
|
|
3352
|
-
*/
|
|
3353
|
-
setTimeout(timeout) {
|
|
3354
|
-
if (timeout <= 0) {
|
|
3355
|
-
throw new Error("Timeout must be positive");
|
|
3356
|
-
}
|
|
3357
|
-
this.timeout = timeout;
|
|
3358
|
-
}
|
|
3359
|
-
};
|
|
3360
|
-
|
|
3361
3182
|
// src/helpers/wallet-integration.ts
|
|
3362
3183
|
var import_web36 = require("@solana/web3.js");
|
|
3363
3184
|
function validateWalletConnected(wallet) {
|
|
@@ -3443,7 +3264,6 @@ var VERSION = "1.0.0";
|
|
|
3443
3264
|
LAMPORTS_PER_SOL,
|
|
3444
3265
|
LocalStorageAdapter,
|
|
3445
3266
|
MemoryStorageAdapter,
|
|
3446
|
-
ProverService,
|
|
3447
3267
|
RelayService,
|
|
3448
3268
|
VARIABLE_FEE_RATE,
|
|
3449
3269
|
VERSION,
|