@cloak.ag/sdk 1.0.2 → 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 +140 -606
- package/dist/index.d.cts +14 -209
- package/dist/index.d.ts +14 -209
- package/dist/index.js +129 -593
- package/package.json +9 -5
package/dist/index.cjs
CHANGED
|
@@ -30,7 +30,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
ArtifactProverService: () => ArtifactProverService,
|
|
34
33
|
CLOAK_PROGRAM_ID: () => CLOAK_PROGRAM_ID,
|
|
35
34
|
CloakError: () => CloakError,
|
|
36
35
|
CloakSDK: () => CloakSDK,
|
|
@@ -40,7 +39,6 @@ __export(index_exports, {
|
|
|
40
39
|
LAMPORTS_PER_SOL: () => LAMPORTS_PER_SOL,
|
|
41
40
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
42
41
|
MemoryStorageAdapter: () => MemoryStorageAdapter,
|
|
43
|
-
ProverService: () => ProverService,
|
|
44
42
|
RelayService: () => RelayService,
|
|
45
43
|
VARIABLE_FEE_RATE: () => VARIABLE_FEE_RATE,
|
|
46
44
|
VERSION: () => VERSION,
|
|
@@ -129,7 +127,7 @@ __export(index_exports, {
|
|
|
129
127
|
module.exports = __toCommonJS(index_exports);
|
|
130
128
|
|
|
131
129
|
// src/core/CloakSDK.ts
|
|
132
|
-
var
|
|
130
|
+
var import_web35 = require("@solana/web3.js");
|
|
133
131
|
|
|
134
132
|
// src/core/types.ts
|
|
135
133
|
var CloakError = class extends Error {
|
|
@@ -147,7 +145,6 @@ var import_blake3 = require("@noble/hashes/blake3.js");
|
|
|
147
145
|
var import_tweetnacl = __toESM(require("tweetnacl"), 1);
|
|
148
146
|
|
|
149
147
|
// src/utils/crypto.ts
|
|
150
|
-
var import_web3 = require("@solana/web3.js");
|
|
151
148
|
var import_circomlibjs = require("circomlibjs");
|
|
152
149
|
var poseidon = null;
|
|
153
150
|
async function getPoseidon() {
|
|
@@ -168,7 +165,7 @@ function splitTo2Limbs(value) {
|
|
|
168
165
|
return [lo, hi];
|
|
169
166
|
}
|
|
170
167
|
function pubkeyToLimbs(pubkey) {
|
|
171
|
-
const bytes = pubkey
|
|
168
|
+
const bytes = typeof pubkey.toBytes === "function" ? pubkey.toBytes() : pubkey;
|
|
172
169
|
const value = BigInt("0x" + Buffer.from(bytes).toString("hex"));
|
|
173
170
|
return splitTo2Limbs(value);
|
|
174
171
|
}
|
|
@@ -796,10 +793,10 @@ var LocalStorageAdapter = class {
|
|
|
796
793
|
};
|
|
797
794
|
|
|
798
795
|
// src/utils/validation.ts
|
|
799
|
-
var
|
|
796
|
+
var import_web3 = require("@solana/web3.js");
|
|
800
797
|
function isValidSolanaAddress(address) {
|
|
801
798
|
try {
|
|
802
|
-
new
|
|
799
|
+
new import_web3.PublicKey(address);
|
|
803
800
|
return true;
|
|
804
801
|
} catch {
|
|
805
802
|
return false;
|
|
@@ -898,8 +895,9 @@ function validateTransfers(recipients, totalAmount) {
|
|
|
898
895
|
}
|
|
899
896
|
for (let i = 0; i < recipients.length; i++) {
|
|
900
897
|
const transfer = recipients[i];
|
|
901
|
-
|
|
902
|
-
|
|
898
|
+
const isPublicKeyLike = transfer.recipient && typeof transfer.recipient.toBase58 === "function" && typeof transfer.recipient.toBuffer === "function";
|
|
899
|
+
if (!isPublicKeyLike) {
|
|
900
|
+
throw new Error(`Recipient ${i} must be a PublicKey (got ${typeof transfer.recipient})`);
|
|
903
901
|
}
|
|
904
902
|
if (typeof transfer.amount !== "number" || transfer.amount <= 0) {
|
|
905
903
|
throw new Error(`Recipient ${i} amount must be a positive number`);
|
|
@@ -1144,254 +1142,6 @@ var IndexerService = class {
|
|
|
1144
1142
|
}
|
|
1145
1143
|
};
|
|
1146
1144
|
|
|
1147
|
-
// src/services/ArtifactProverService.ts
|
|
1148
|
-
var ArtifactProverService = class {
|
|
1149
|
-
/**
|
|
1150
|
-
* Create a new Artifact Prover Service client
|
|
1151
|
-
*
|
|
1152
|
-
* @param indexerUrl - Indexer service base URL
|
|
1153
|
-
* @param timeout - Proof generation timeout in ms (default: 5 minutes)
|
|
1154
|
-
* @param pollInterval - Polling interval for status checks (default: 2 seconds)
|
|
1155
|
-
*/
|
|
1156
|
-
constructor(indexerUrl, timeout = 5 * 60 * 1e3, pollInterval = 2e3) {
|
|
1157
|
-
this.indexerUrl = indexerUrl.replace(/\/$/, "");
|
|
1158
|
-
this.timeout = timeout;
|
|
1159
|
-
this.pollInterval = pollInterval;
|
|
1160
|
-
}
|
|
1161
|
-
/**
|
|
1162
|
-
* Generate a zero-knowledge proof using artifact-based flow
|
|
1163
|
-
*
|
|
1164
|
-
* This process typically takes 30-180 seconds depending on the TEE.
|
|
1165
|
-
* Private inputs are uploaded directly to TEE, never passing through backend.
|
|
1166
|
-
*
|
|
1167
|
-
* @param inputs - Circuit inputs (private + public + outputs)
|
|
1168
|
-
* @param options - Optional progress tracking and callbacks
|
|
1169
|
-
* @returns Proof result with hex-encoded proof and public inputs
|
|
1170
|
-
*
|
|
1171
|
-
* @example
|
|
1172
|
-
* ```typescript
|
|
1173
|
-
* const result = await prover.generateProof(inputs);
|
|
1174
|
-
* if (result.success) {
|
|
1175
|
-
* console.log(`Proof: ${result.proof}`);
|
|
1176
|
-
* }
|
|
1177
|
-
* ```
|
|
1178
|
-
*/
|
|
1179
|
-
async generateProof(inputs, options) {
|
|
1180
|
-
const startTime = Date.now();
|
|
1181
|
-
const actualTimeout = options?.timeout || this.timeout;
|
|
1182
|
-
const pollInterval = options?.pollInterval || this.pollInterval;
|
|
1183
|
-
options?.onStart?.();
|
|
1184
|
-
options?.onProgress?.(5);
|
|
1185
|
-
try {
|
|
1186
|
-
options?.onProgress?.(10);
|
|
1187
|
-
const artifactResponse = await fetch(`${this.indexerUrl}/api/v1/tee/artifact`, {
|
|
1188
|
-
method: "POST",
|
|
1189
|
-
headers: {
|
|
1190
|
-
"Content-Type": "application/json"
|
|
1191
|
-
},
|
|
1192
|
-
body: JSON.stringify({
|
|
1193
|
-
program_id: null
|
|
1194
|
-
// Optional, can be null
|
|
1195
|
-
})
|
|
1196
|
-
});
|
|
1197
|
-
if (!artifactResponse.ok) {
|
|
1198
|
-
const errorText = await artifactResponse.text();
|
|
1199
|
-
const errorMessage2 = `Failed to create artifact: ${errorText}`;
|
|
1200
|
-
options?.onError?.(errorMessage2);
|
|
1201
|
-
return {
|
|
1202
|
-
success: false,
|
|
1203
|
-
generationTimeMs: Date.now() - startTime,
|
|
1204
|
-
error: errorMessage2
|
|
1205
|
-
};
|
|
1206
|
-
}
|
|
1207
|
-
const artifactData = await artifactResponse.json();
|
|
1208
|
-
const { artifact_id, upload_url } = artifactData;
|
|
1209
|
-
if (!artifact_id || !upload_url) {
|
|
1210
|
-
const errorMessage2 = "Invalid artifact response: missing artifact_id or upload_url";
|
|
1211
|
-
options?.onError?.(errorMessage2);
|
|
1212
|
-
return {
|
|
1213
|
-
success: false,
|
|
1214
|
-
generationTimeMs: Date.now() - startTime,
|
|
1215
|
-
error: errorMessage2
|
|
1216
|
-
};
|
|
1217
|
-
}
|
|
1218
|
-
const fullUploadUrl = upload_url.startsWith("http") ? upload_url : `${this.indexerUrl}${upload_url}`;
|
|
1219
|
-
options?.onProgress?.(20);
|
|
1220
|
-
const stdinPayload = JSON.stringify({
|
|
1221
|
-
private: inputs.privateInputs,
|
|
1222
|
-
public: inputs.publicInputs,
|
|
1223
|
-
outputs: inputs.outputs,
|
|
1224
|
-
// Include swap_params if present (for swap transactions)
|
|
1225
|
-
...inputs.swapParams && { swap_params: inputs.swapParams }
|
|
1226
|
-
});
|
|
1227
|
-
const uploadResponse = await fetch(fullUploadUrl, {
|
|
1228
|
-
method: "POST",
|
|
1229
|
-
headers: {
|
|
1230
|
-
"Content-Type": "application/json"
|
|
1231
|
-
},
|
|
1232
|
-
body: stdinPayload
|
|
1233
|
-
});
|
|
1234
|
-
if (!uploadResponse.ok) {
|
|
1235
|
-
const errorText = await uploadResponse.text();
|
|
1236
|
-
const errorMessage2 = `Failed to upload stdin to TEE: ${errorText}`;
|
|
1237
|
-
options?.onError?.(errorMessage2);
|
|
1238
|
-
return {
|
|
1239
|
-
success: false,
|
|
1240
|
-
generationTimeMs: Date.now() - startTime,
|
|
1241
|
-
error: errorMessage2
|
|
1242
|
-
};
|
|
1243
|
-
}
|
|
1244
|
-
options?.onProgress?.(30);
|
|
1245
|
-
const requestProofBody = {
|
|
1246
|
-
artifact_id,
|
|
1247
|
-
program_id: null,
|
|
1248
|
-
public_inputs: JSON.stringify(inputs.publicInputs)
|
|
1249
|
-
};
|
|
1250
|
-
const requestProofResponse = await fetch(
|
|
1251
|
-
`${this.indexerUrl}/api/v1/tee/request-proof`,
|
|
1252
|
-
{
|
|
1253
|
-
method: "POST",
|
|
1254
|
-
headers: {
|
|
1255
|
-
"Content-Type": "application/json"
|
|
1256
|
-
},
|
|
1257
|
-
body: JSON.stringify(requestProofBody)
|
|
1258
|
-
}
|
|
1259
|
-
);
|
|
1260
|
-
if (!requestProofResponse.ok) {
|
|
1261
|
-
const errorText = await requestProofResponse.text();
|
|
1262
|
-
const errorMessage2 = `Failed to request proof: ${errorText}`;
|
|
1263
|
-
options?.onError?.(errorMessage2);
|
|
1264
|
-
return {
|
|
1265
|
-
success: false,
|
|
1266
|
-
generationTimeMs: Date.now() - startTime,
|
|
1267
|
-
error: errorMessage2
|
|
1268
|
-
};
|
|
1269
|
-
}
|
|
1270
|
-
const requestProofData = await requestProofResponse.json();
|
|
1271
|
-
const { request_id } = requestProofData;
|
|
1272
|
-
if (!request_id) {
|
|
1273
|
-
const errorMessage2 = "Invalid proof request response: missing request_id";
|
|
1274
|
-
options?.onError?.(errorMessage2);
|
|
1275
|
-
return {
|
|
1276
|
-
success: false,
|
|
1277
|
-
generationTimeMs: Date.now() - startTime,
|
|
1278
|
-
error: errorMessage2
|
|
1279
|
-
};
|
|
1280
|
-
}
|
|
1281
|
-
options?.onProgress?.(40);
|
|
1282
|
-
const pollStartTime = Date.now();
|
|
1283
|
-
let lastProgress = 40;
|
|
1284
|
-
while (Date.now() - pollStartTime < actualTimeout) {
|
|
1285
|
-
const statusResponse = await fetch(
|
|
1286
|
-
`${this.indexerUrl}/api/v1/tee/proof-status?request_id=${request_id}`,
|
|
1287
|
-
{
|
|
1288
|
-
method: "GET"
|
|
1289
|
-
}
|
|
1290
|
-
);
|
|
1291
|
-
if (!statusResponse.ok) {
|
|
1292
|
-
const errorText = await statusResponse.text();
|
|
1293
|
-
const errorMessage2 = `Failed to check proof status: ${errorText}`;
|
|
1294
|
-
options?.onError?.(errorMessage2);
|
|
1295
|
-
return {
|
|
1296
|
-
success: false,
|
|
1297
|
-
generationTimeMs: Date.now() - startTime,
|
|
1298
|
-
error: errorMessage2
|
|
1299
|
-
};
|
|
1300
|
-
}
|
|
1301
|
-
const statusData = await statusResponse.json();
|
|
1302
|
-
const { status, proof, public_inputs, generation_time_ms, error } = statusData;
|
|
1303
|
-
if (status === "ready") {
|
|
1304
|
-
options?.onProgress?.(100);
|
|
1305
|
-
if (!proof || !public_inputs) {
|
|
1306
|
-
const errorMessage2 = "Proof status is 'ready' but proof or public_inputs is missing";
|
|
1307
|
-
options?.onError?.(errorMessage2);
|
|
1308
|
-
return {
|
|
1309
|
-
success: false,
|
|
1310
|
-
generationTimeMs: Date.now() - startTime,
|
|
1311
|
-
error: errorMessage2
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
const result = {
|
|
1315
|
-
success: true,
|
|
1316
|
-
proof,
|
|
1317
|
-
publicInputs: public_inputs,
|
|
1318
|
-
generationTimeMs: generation_time_ms || Date.now() - startTime
|
|
1319
|
-
};
|
|
1320
|
-
options?.onSuccess?.(result);
|
|
1321
|
-
return result;
|
|
1322
|
-
}
|
|
1323
|
-
if (status === "failed") {
|
|
1324
|
-
const errorMessage2 = error || "Proof generation failed";
|
|
1325
|
-
options?.onError?.(errorMessage2);
|
|
1326
|
-
return {
|
|
1327
|
-
success: false,
|
|
1328
|
-
generationTimeMs: Date.now() - startTime,
|
|
1329
|
-
error: errorMessage2
|
|
1330
|
-
};
|
|
1331
|
-
}
|
|
1332
|
-
const elapsed = Date.now() - pollStartTime;
|
|
1333
|
-
const progress = Math.min(90, 40 + Math.floor(elapsed / actualTimeout * 50));
|
|
1334
|
-
if (progress > lastProgress) {
|
|
1335
|
-
lastProgress = progress;
|
|
1336
|
-
options?.onProgress?.(progress);
|
|
1337
|
-
}
|
|
1338
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
1339
|
-
}
|
|
1340
|
-
const errorMessage = `Proof generation timed out after ${actualTimeout}ms`;
|
|
1341
|
-
options?.onError?.(errorMessage);
|
|
1342
|
-
return {
|
|
1343
|
-
success: false,
|
|
1344
|
-
generationTimeMs: Date.now() - startTime,
|
|
1345
|
-
error: errorMessage
|
|
1346
|
-
};
|
|
1347
|
-
} catch (error) {
|
|
1348
|
-
const totalTime = Date.now() - startTime;
|
|
1349
|
-
let errorMessage;
|
|
1350
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
1351
|
-
errorMessage = `Proof generation timed out after ${actualTimeout}ms`;
|
|
1352
|
-
} else {
|
|
1353
|
-
errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1354
|
-
}
|
|
1355
|
-
options?.onError?.(errorMessage);
|
|
1356
|
-
return {
|
|
1357
|
-
success: false,
|
|
1358
|
-
generationTimeMs: totalTime,
|
|
1359
|
-
error: errorMessage
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
/**
|
|
1364
|
-
* Check if the artifact prover service is available
|
|
1365
|
-
*
|
|
1366
|
-
* @returns True if service is healthy
|
|
1367
|
-
*/
|
|
1368
|
-
async healthCheck() {
|
|
1369
|
-
try {
|
|
1370
|
-
const response = await fetch(`${this.indexerUrl}/health`, {
|
|
1371
|
-
method: "GET"
|
|
1372
|
-
});
|
|
1373
|
-
return response.ok;
|
|
1374
|
-
} catch {
|
|
1375
|
-
return false;
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
/**
|
|
1379
|
-
* Get the configured timeout
|
|
1380
|
-
*/
|
|
1381
|
-
getTimeout() {
|
|
1382
|
-
return this.timeout;
|
|
1383
|
-
}
|
|
1384
|
-
/**
|
|
1385
|
-
* Set a new timeout
|
|
1386
|
-
*/
|
|
1387
|
-
setTimeout(timeout) {
|
|
1388
|
-
if (timeout <= 0) {
|
|
1389
|
-
throw new Error("Timeout must be positive");
|
|
1390
|
-
}
|
|
1391
|
-
this.timeout = timeout;
|
|
1392
|
-
}
|
|
1393
|
-
};
|
|
1394
|
-
|
|
1395
1145
|
// src/services/RelayService.ts
|
|
1396
1146
|
var RelayService = class {
|
|
1397
1147
|
/**
|
|
@@ -1634,7 +1384,7 @@ var RelayService = class {
|
|
|
1634
1384
|
};
|
|
1635
1385
|
|
|
1636
1386
|
// src/services/DepositRecoveryService.ts
|
|
1637
|
-
var
|
|
1387
|
+
var import_web32 = require("@solana/web3.js");
|
|
1638
1388
|
|
|
1639
1389
|
// src/helpers/encrypted-output.ts
|
|
1640
1390
|
function prepareEncryptedOutput(note, cloakKeys) {
|
|
@@ -1725,7 +1475,7 @@ var DepositRecoveryService = class {
|
|
|
1725
1475
|
} catch (e) {
|
|
1726
1476
|
}
|
|
1727
1477
|
onProgress?.("Fetching transaction details...");
|
|
1728
|
-
const connection = new
|
|
1478
|
+
const connection = new import_web32.Connection(
|
|
1729
1479
|
process.env.NEXT_PUBLIC_SOLANA_RPC_URL || "https://api.devnet.solana.com"
|
|
1730
1480
|
);
|
|
1731
1481
|
const txDetails = await connection.getTransaction(signature, {
|
|
@@ -1887,7 +1637,7 @@ var DepositRecoveryService = class {
|
|
|
1887
1637
|
};
|
|
1888
1638
|
|
|
1889
1639
|
// src/solana/instructions.ts
|
|
1890
|
-
var
|
|
1640
|
+
var import_web33 = require("@solana/web3.js");
|
|
1891
1641
|
function createDepositInstruction(params) {
|
|
1892
1642
|
if (params.commitment.length !== 32) {
|
|
1893
1643
|
throw new Error(
|
|
@@ -1909,7 +1659,7 @@ function createDepositInstruction(params) {
|
|
|
1909
1659
|
data.set(discriminant, 0);
|
|
1910
1660
|
data.set(amountBytes, 1);
|
|
1911
1661
|
data.set(params.commitment, 9);
|
|
1912
|
-
return new
|
|
1662
|
+
return new import_web33.TransactionInstruction({
|
|
1913
1663
|
programId: params.programId,
|
|
1914
1664
|
keys: [
|
|
1915
1665
|
// Account 0: Payer (signer, writable) - pays for transaction
|
|
@@ -1917,7 +1667,7 @@ function createDepositInstruction(params) {
|
|
|
1917
1667
|
// Account 1: Pool (writable) - receives SOL
|
|
1918
1668
|
{ pubkey: params.pool, isSigner: false, isWritable: true },
|
|
1919
1669
|
// Account 2: System Program (readonly) - for transfers
|
|
1920
|
-
{ pubkey:
|
|
1670
|
+
{ pubkey: import_web33.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
1921
1671
|
// Account 3: Merkle Tree (writable) - stores on-chain Merkle tree
|
|
1922
1672
|
{ pubkey: params.merkleTree, isSigner: false, isWritable: true }
|
|
1923
1673
|
],
|
|
@@ -1925,16 +1675,16 @@ function createDepositInstruction(params) {
|
|
|
1925
1675
|
});
|
|
1926
1676
|
}
|
|
1927
1677
|
function validateDepositParams(params) {
|
|
1928
|
-
if (!(params.programId instanceof
|
|
1678
|
+
if (!(params.programId instanceof import_web33.PublicKey)) {
|
|
1929
1679
|
throw new Error("programId must be a PublicKey");
|
|
1930
1680
|
}
|
|
1931
|
-
if (!(params.payer instanceof
|
|
1681
|
+
if (!(params.payer instanceof import_web33.PublicKey)) {
|
|
1932
1682
|
throw new Error("payer must be a PublicKey");
|
|
1933
1683
|
}
|
|
1934
|
-
if (!(params.pool instanceof
|
|
1684
|
+
if (!(params.pool instanceof import_web33.PublicKey)) {
|
|
1935
1685
|
throw new Error("pool must be a PublicKey");
|
|
1936
1686
|
}
|
|
1937
|
-
if (!(params.merkleTree instanceof
|
|
1687
|
+
if (!(params.merkleTree instanceof import_web33.PublicKey)) {
|
|
1938
1688
|
throw new Error("merkleTree must be a PublicKey");
|
|
1939
1689
|
}
|
|
1940
1690
|
if (typeof params.amount !== "number" || params.amount <= 0) {
|
|
@@ -1951,34 +1701,34 @@ function validateDepositParams(params) {
|
|
|
1951
1701
|
}
|
|
1952
1702
|
|
|
1953
1703
|
// src/utils/pda.ts
|
|
1954
|
-
var
|
|
1704
|
+
var import_web34 = require("@solana/web3.js");
|
|
1955
1705
|
function getShieldPoolPDAs(programId, mint) {
|
|
1956
1706
|
const pid = programId || CLOAK_PROGRAM_ID;
|
|
1957
|
-
const mintKey = mint ?? new
|
|
1707
|
+
const mintKey = mint ?? new import_web34.PublicKey(
|
|
1958
1708
|
// 32 zero bytes, matching Rust `Pubkey::default()`
|
|
1959
1709
|
new Uint8Array(32)
|
|
1960
1710
|
);
|
|
1961
|
-
const [pool] =
|
|
1711
|
+
const [pool] = import_web34.PublicKey.findProgramAddressSync(
|
|
1962
1712
|
[Buffer.from("pool"), mintKey.toBytes()],
|
|
1963
1713
|
pid
|
|
1964
1714
|
);
|
|
1965
|
-
const [merkleTree] =
|
|
1715
|
+
const [merkleTree] = import_web34.PublicKey.findProgramAddressSync(
|
|
1966
1716
|
[Buffer.from("merkle_tree"), mintKey.toBytes()],
|
|
1967
1717
|
pid
|
|
1968
1718
|
);
|
|
1969
|
-
const [commitments] =
|
|
1719
|
+
const [commitments] = import_web34.PublicKey.findProgramAddressSync(
|
|
1970
1720
|
[Buffer.from("commitments"), mintKey.toBytes()],
|
|
1971
1721
|
pid
|
|
1972
1722
|
);
|
|
1973
|
-
const [rootsRing] =
|
|
1723
|
+
const [rootsRing] = import_web34.PublicKey.findProgramAddressSync(
|
|
1974
1724
|
[Buffer.from("roots_ring"), mintKey.toBytes()],
|
|
1975
1725
|
pid
|
|
1976
1726
|
);
|
|
1977
|
-
const [nullifierShard] =
|
|
1727
|
+
const [nullifierShard] = import_web34.PublicKey.findProgramAddressSync(
|
|
1978
1728
|
[Buffer.from("nullifier_shard"), mintKey.toBytes()],
|
|
1979
1729
|
pid
|
|
1980
1730
|
);
|
|
1981
|
-
const [treasury] =
|
|
1731
|
+
const [treasury] = import_web34.PublicKey.findProgramAddressSync(
|
|
1982
1732
|
[Buffer.from("treasury"), mintKey.toBytes()],
|
|
1983
1733
|
pid
|
|
1984
1734
|
);
|
|
@@ -2025,6 +1775,15 @@ async function fileExists(filePath) {
|
|
|
2025
1775
|
return false;
|
|
2026
1776
|
}
|
|
2027
1777
|
}
|
|
1778
|
+
const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
|
|
1779
|
+
if (isBrowser) {
|
|
1780
|
+
try {
|
|
1781
|
+
const response = await fetch(filePath, { method: "HEAD" });
|
|
1782
|
+
return response.ok;
|
|
1783
|
+
} catch {
|
|
1784
|
+
return false;
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
2028
1787
|
return false;
|
|
2029
1788
|
}
|
|
2030
1789
|
async function generateWithdrawRegularProof(inputs, circuitsPath) {
|
|
@@ -2068,11 +1827,7 @@ async function generateWithdrawRegularProof(inputs, circuitsPath) {
|
|
|
2068
1827
|
var_fee: inputs.var_fee.toString(),
|
|
2069
1828
|
rem: inputs.rem.toString()
|
|
2070
1829
|
};
|
|
2071
|
-
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
|
2072
|
-
circuitInputs,
|
|
2073
|
-
wasmPath,
|
|
2074
|
-
zkeyPath
|
|
2075
|
-
);
|
|
1830
|
+
const { proof, publicSignals } = await snarkjs.groth16.fullProve(circuitInputs, wasmPath, zkeyPath);
|
|
2076
1831
|
const proofBytes = proofToBytes(proof);
|
|
2077
1832
|
return {
|
|
2078
1833
|
proof,
|
|
@@ -2141,6 +1896,10 @@ async function generateWithdrawSwapProof(inputs, circuitsPath) {
|
|
|
2141
1896
|
};
|
|
2142
1897
|
}
|
|
2143
1898
|
async function areCircuitsAvailable(circuitsPath) {
|
|
1899
|
+
const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
|
|
1900
|
+
if (isBrowser) {
|
|
1901
|
+
return Boolean(circuitsPath && circuitsPath !== "");
|
|
1902
|
+
}
|
|
2144
1903
|
const wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
|
|
2145
1904
|
const zkeyPath = joinPath(circuitsPath, "build", "withdraw_regular_final.zkey");
|
|
2146
1905
|
const wasmExists = await fileExists(wasmPath);
|
|
@@ -2172,11 +1931,11 @@ async function getDefaultCircuitsPath() {
|
|
|
2172
1931
|
}
|
|
2173
1932
|
|
|
2174
1933
|
// src/core/CloakSDK.ts
|
|
2175
|
-
var CLOAK_PROGRAM_ID = new
|
|
1934
|
+
var CLOAK_PROGRAM_ID = new import_web35.PublicKey("c1oak6tetxYnNfvXKFkpn1d98FxtK7B68vBQLYQpWKp");
|
|
2176
1935
|
var CLOAK_API_URL = "https://api.cloak.ag";
|
|
2177
1936
|
var CloakSDK = class {
|
|
2178
1937
|
/**
|
|
2179
|
-
|
|
1938
|
+
* Create a new Cloak SDK client
|
|
2180
1939
|
*
|
|
2181
1940
|
* @param config - Client configuration
|
|
2182
1941
|
*
|
|
@@ -2201,7 +1960,7 @@ var CloakSDK = class {
|
|
|
2201
1960
|
throw new Error("Must provide either keypairBytes (Node.js) or wallet (Browser)");
|
|
2202
1961
|
}
|
|
2203
1962
|
if (config.keypairBytes) {
|
|
2204
|
-
this.keypair =
|
|
1963
|
+
this.keypair = import_web35.Keypair.fromSecretKey(config.keypairBytes);
|
|
2205
1964
|
}
|
|
2206
1965
|
this.wallet = config.wallet;
|
|
2207
1966
|
this.cloakKeys = config.cloakKeys;
|
|
@@ -2209,7 +1968,6 @@ var CloakSDK = class {
|
|
|
2209
1968
|
const indexerUrl = config.indexerUrl || typeof process !== "undefined" && process.env?.CLOAK_INDEXER_URL || CLOAK_API_URL;
|
|
2210
1969
|
const relayUrl = config.relayUrl || typeof process !== "undefined" && process.env?.CLOAK_RELAY_URL || CLOAK_API_URL;
|
|
2211
1970
|
this.indexer = new IndexerService(indexerUrl);
|
|
2212
|
-
this.artifactProver = new ArtifactProverService(indexerUrl, 5 * 60 * 1e3, 2e3);
|
|
2213
1971
|
this.relay = new RelayService(relayUrl);
|
|
2214
1972
|
this.depositRecovery = new DepositRecoveryService(this.indexer, indexerUrl);
|
|
2215
1973
|
if (!this.cloakKeys) {
|
|
@@ -2312,29 +2070,50 @@ var CloakSDK = class {
|
|
|
2312
2070
|
commitment: commitmentBytes
|
|
2313
2071
|
});
|
|
2314
2072
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
2315
|
-
const transaction = new
|
|
2073
|
+
const transaction = new import_web35.Transaction({
|
|
2316
2074
|
feePayer: payerPubkey,
|
|
2317
|
-
blockhash
|
|
2318
|
-
lastValidBlockHeight
|
|
2075
|
+
recentBlockhash: blockhash
|
|
2319
2076
|
}).add(depositIx);
|
|
2320
|
-
if (!
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
`Transaction simulation failed: ${JSON.stringify(simulation.value.err)}
|
|
2326
|
-
Logs:
|
|
2327
|
-
${logs}`
|
|
2328
|
-
);
|
|
2329
|
-
}
|
|
2077
|
+
if (!transaction.feePayer) {
|
|
2078
|
+
throw new Error("Transaction feePayer is not set");
|
|
2079
|
+
}
|
|
2080
|
+
if (!transaction.recentBlockhash) {
|
|
2081
|
+
throw new Error("Transaction recentBlockhash is not set");
|
|
2330
2082
|
}
|
|
2331
2083
|
let signature;
|
|
2332
|
-
if (this.wallet
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2084
|
+
if (this.wallet) {
|
|
2085
|
+
if (!this.wallet.publicKey) {
|
|
2086
|
+
throw new Error("Wallet not connected - publicKey is null");
|
|
2087
|
+
}
|
|
2088
|
+
if (this.wallet.signTransaction) {
|
|
2089
|
+
try {
|
|
2090
|
+
const signedTransaction = await this.wallet.signTransaction(transaction);
|
|
2091
|
+
const rawTransaction = signedTransaction.serialize();
|
|
2092
|
+
signature = await connection.sendRawTransaction(rawTransaction, {
|
|
2093
|
+
skipPreflight: options?.skipPreflight || false,
|
|
2094
|
+
preflightCommitment: "confirmed",
|
|
2095
|
+
maxRetries: 3
|
|
2096
|
+
});
|
|
2097
|
+
} catch (signError) {
|
|
2098
|
+
if (this.wallet.sendTransaction) {
|
|
2099
|
+
signature = await this.wallet.sendTransaction(transaction, connection, {
|
|
2100
|
+
skipPreflight: options?.skipPreflight || false,
|
|
2101
|
+
preflightCommitment: "confirmed",
|
|
2102
|
+
maxRetries: 3
|
|
2103
|
+
});
|
|
2104
|
+
} else {
|
|
2105
|
+
throw signError;
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
} else if (this.wallet.sendTransaction) {
|
|
2109
|
+
signature = await this.wallet.sendTransaction(transaction, connection, {
|
|
2110
|
+
skipPreflight: options?.skipPreflight || false,
|
|
2111
|
+
preflightCommitment: "confirmed",
|
|
2112
|
+
maxRetries: 3
|
|
2113
|
+
});
|
|
2114
|
+
} else {
|
|
2115
|
+
throw new Error("Wallet adapter must provide either sendTransaction or signTransaction");
|
|
2116
|
+
}
|
|
2338
2117
|
} else if (this.keypair) {
|
|
2339
2118
|
signature = await connection.sendTransaction(transaction, [this.keypair], {
|
|
2340
2119
|
skipPreflight: options?.skipPreflight || false,
|
|
@@ -2419,7 +2198,7 @@ ${logs}`
|
|
|
2419
2198
|
}
|
|
2420
2199
|
if (leafIndex === null) {
|
|
2421
2200
|
const programId2 = this.config.programId || CLOAK_PROGRAM_ID;
|
|
2422
|
-
const mintForSOL = new
|
|
2201
|
+
const mintForSOL = new import_web35.PublicKey(new Uint8Array(32));
|
|
2423
2202
|
const { merkleTree } = getShieldPoolPDAs(programId2, mintForSOL);
|
|
2424
2203
|
const merkleTreeAccount = await connection.getAccountInfo(merkleTree);
|
|
2425
2204
|
if (!merkleTreeAccount) {
|
|
@@ -2524,17 +2303,10 @@ ${logs}`
|
|
|
2524
2303
|
const feeBps = Math.ceil(protocolFee * 1e4 / note.amount);
|
|
2525
2304
|
const distributableAmount = getDistributableAmount2(note.amount);
|
|
2526
2305
|
validateTransfers(recipients, distributableAmount);
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
if (
|
|
2530
|
-
|
|
2531
|
-
pathElements: note.merkleProof.pathElements,
|
|
2532
|
-
pathIndices: note.merkleProof.pathIndices
|
|
2533
|
-
};
|
|
2534
|
-
merkleRoot = note.root;
|
|
2535
|
-
} else {
|
|
2536
|
-
merkleProof = await this.indexer.getMerkleProof(note.leafIndex);
|
|
2537
|
-
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");
|
|
2538
2310
|
}
|
|
2539
2311
|
const nullifier = await computeNullifierAsync(note.sk_spend, note.leafIndex);
|
|
2540
2312
|
const nullifierHex = nullifier.toString(16).padStart(64, "0");
|
|
@@ -2570,7 +2342,8 @@ ${logs}`
|
|
|
2570
2342
|
throw new Error(`Merkle proof path element at position ${i} must be 64 hex characters (32 bytes)`);
|
|
2571
2343
|
}
|
|
2572
2344
|
}
|
|
2573
|
-
const
|
|
2345
|
+
const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
|
|
2346
|
+
const circuitsPath = isBrowser ? "/circuits" : typeof process !== "undefined" && process.env?.CIRCUITS_PATH || await getDefaultCircuitsPath();
|
|
2574
2347
|
const useDirectProof = await areCircuitsAvailable(circuitsPath);
|
|
2575
2348
|
let proofHex;
|
|
2576
2349
|
let finalPublicInputs;
|
|
@@ -2607,6 +2380,13 @@ ${logs}`
|
|
|
2607
2380
|
}
|
|
2608
2381
|
const sk = splitTo2Limbs(sk_spend_bigint);
|
|
2609
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
|
+
}
|
|
2610
2390
|
const proofInputs = {
|
|
2611
2391
|
root: root_bigint,
|
|
2612
2392
|
nullifier: nullifier_bigint,
|
|
@@ -2625,7 +2405,9 @@ ${logs}`
|
|
|
2625
2405
|
var_fee: varFee,
|
|
2626
2406
|
rem
|
|
2627
2407
|
};
|
|
2408
|
+
options?.onProgress?.("proof_generating");
|
|
2628
2409
|
const proofResult = await generateWithdrawRegularProof(proofInputs, circuitsPath);
|
|
2410
|
+
options?.onProgress?.("proof_complete");
|
|
2629
2411
|
proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
|
|
2630
2412
|
finalPublicInputs = {
|
|
2631
2413
|
root: merkleRoot,
|
|
@@ -2634,43 +2416,9 @@ ${logs}`
|
|
|
2634
2416
|
amount: note.amount
|
|
2635
2417
|
};
|
|
2636
2418
|
} else {
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
r: note.r,
|
|
2641
|
-
sk_spend: note.sk_spend,
|
|
2642
|
-
leaf_index: note.leafIndex,
|
|
2643
|
-
merkle_path: {
|
|
2644
|
-
path_elements: merkleProof.pathElements,
|
|
2645
|
-
path_indices: merkleProof.pathIndices
|
|
2646
|
-
}
|
|
2647
|
-
},
|
|
2648
|
-
publicInputs: {
|
|
2649
|
-
root: merkleRoot,
|
|
2650
|
-
nf: nullifierHex,
|
|
2651
|
-
outputs_hash: outputsHashHex,
|
|
2652
|
-
amount: note.amount
|
|
2653
|
-
},
|
|
2654
|
-
outputs: recipients.map((r) => ({
|
|
2655
|
-
address: r.recipient.toBase58(),
|
|
2656
|
-
amount: r.amount
|
|
2657
|
-
}))
|
|
2658
|
-
};
|
|
2659
|
-
const proofResult = await this.artifactProver.generateProof(proofInputs, {
|
|
2660
|
-
onProgress: options?.onProofProgress,
|
|
2661
|
-
onError: options?.onProgress ? (error) => options.onProgress?.(`Proof generation error: ${error}`) : void 0
|
|
2662
|
-
});
|
|
2663
|
-
if (!proofResult.success || !proofResult.proof) {
|
|
2664
|
-
let errorMessage = proofResult.error || "Proof generation failed";
|
|
2665
|
-
if (errorMessage.startsWith("Proof generation failed: ")) {
|
|
2666
|
-
errorMessage = errorMessage.substring("Proof generation failed: ".length);
|
|
2667
|
-
}
|
|
2668
|
-
errorMessage += `
|
|
2669
|
-
Note details: leafIndex=${note.leafIndex}, root=${merkleRoot.slice(0, 16)}..., nullifier=${nullifierHex.slice(0, 16)}...`;
|
|
2670
|
-
throw new Error(errorMessage);
|
|
2671
|
-
}
|
|
2672
|
-
proofHex = proofResult.proof;
|
|
2673
|
-
finalPublicInputs = proofInputs.publicInputs;
|
|
2419
|
+
throw new Error(
|
|
2420
|
+
`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.`
|
|
2421
|
+
);
|
|
2674
2422
|
}
|
|
2675
2423
|
const signature = await this.relay.submitWithdraw(
|
|
2676
2424
|
{
|
|
@@ -2825,35 +2573,32 @@ Note details: leafIndex=${note.leafIndex}, root=${merkleRoot.slice(0, 16)}..., n
|
|
|
2825
2573
|
);
|
|
2826
2574
|
}
|
|
2827
2575
|
let recipientAta;
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
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
|
+
);
|
|
2833
2591
|
}
|
|
2834
|
-
const outputMint2 = new import_web36.PublicKey(options.outputMint);
|
|
2835
|
-
recipientAta = await getAssociatedTokenAddress(outputMint2, recipient);
|
|
2836
|
-
} catch (error) {
|
|
2837
|
-
throw new Error(
|
|
2838
|
-
`Failed to get associated token account: ${error instanceof Error ? error.message : String(error)}. Please install @solana/spl-token or provide recipientAta in options.`
|
|
2839
|
-
);
|
|
2840
2592
|
}
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
if (
|
|
2844
|
-
|
|
2845
|
-
pathElements: note.merkleProof.pathElements,
|
|
2846
|
-
pathIndices: note.merkleProof.pathIndices
|
|
2847
|
-
};
|
|
2848
|
-
merkleRoot = note.root;
|
|
2849
|
-
} else {
|
|
2850
|
-
merkleProof = await this.indexer.getMerkleProof(note.leafIndex);
|
|
2851
|
-
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");
|
|
2852
2597
|
}
|
|
2853
2598
|
const nullifier = await computeNullifierAsync(note.sk_spend, note.leafIndex);
|
|
2854
2599
|
const nullifierHex = nullifier.toString(16).padStart(64, "0");
|
|
2855
|
-
const inputMint = new
|
|
2856
|
-
const outputMint = new
|
|
2600
|
+
const inputMint = new import_web35.PublicKey("11111111111111111111111111111111");
|
|
2601
|
+
const outputMint = new import_web35.PublicKey(options.outputMint);
|
|
2857
2602
|
const outputsHash = await computeSwapOutputsHashAsync(
|
|
2858
2603
|
inputMint,
|
|
2859
2604
|
outputMint,
|
|
@@ -2868,7 +2613,8 @@ Note details: leafIndex=${note.leafIndex}, root=${merkleRoot.slice(0, 16)}..., n
|
|
|
2868
2613
|
if (!merkleProof.pathElements || merkleProof.pathElements.length === 0) {
|
|
2869
2614
|
throw new Error("Merkle proof is invalid: missing path elements");
|
|
2870
2615
|
}
|
|
2871
|
-
const
|
|
2616
|
+
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;
|
|
2617
|
+
const circuitsPath = envCircuitsPath || await getDefaultCircuitsPath();
|
|
2872
2618
|
const useDirectProof = await areCircuitsAvailable(circuitsPath);
|
|
2873
2619
|
let proofHex;
|
|
2874
2620
|
let finalPublicInputs;
|
|
@@ -2883,6 +2629,13 @@ Note details: leafIndex=${note.leafIndex}, root=${merkleRoot.slice(0, 16)}..., n
|
|
|
2883
2629
|
const inputMintLimbs = pubkeyToLimbs(inputMint.toBytes());
|
|
2884
2630
|
const outputMintLimbs = pubkeyToLimbs(outputMint.toBytes());
|
|
2885
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
|
+
}
|
|
2886
2639
|
const t = amount_bigint * 5n;
|
|
2887
2640
|
const varFee = t / 1000n;
|
|
2888
2641
|
const rem = t % 1000n;
|
|
@@ -2904,7 +2657,9 @@ Note details: leafIndex=${note.leafIndex}, root=${merkleRoot.slice(0, 16)}..., n
|
|
|
2904
2657
|
var_fee: varFee,
|
|
2905
2658
|
rem
|
|
2906
2659
|
};
|
|
2660
|
+
options?.onProgress?.("proof_generating");
|
|
2907
2661
|
const proofResult = await generateWithdrawSwapProof(proofInputs, circuitsPath);
|
|
2662
|
+
options?.onProgress?.("proof_complete");
|
|
2908
2663
|
proofHex = Buffer.from(proofResult.proofBytes).toString("hex");
|
|
2909
2664
|
finalPublicInputs = {
|
|
2910
2665
|
root: merkleRoot,
|
|
@@ -2913,46 +2668,9 @@ Note details: leafIndex=${note.leafIndex}, root=${merkleRoot.slice(0, 16)}..., n
|
|
|
2913
2668
|
amount: note.amount
|
|
2914
2669
|
};
|
|
2915
2670
|
} else {
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
r: note.r,
|
|
2920
|
-
sk_spend: note.sk_spend,
|
|
2921
|
-
leaf_index: note.leafIndex,
|
|
2922
|
-
merkle_path: {
|
|
2923
|
-
path_elements: merkleProof.pathElements,
|
|
2924
|
-
path_indices: merkleProof.pathIndices
|
|
2925
|
-
}
|
|
2926
|
-
},
|
|
2927
|
-
publicInputs: {
|
|
2928
|
-
root: merkleRoot,
|
|
2929
|
-
nf: nullifierHex,
|
|
2930
|
-
outputs_hash: outputsHashHex,
|
|
2931
|
-
amount: note.amount
|
|
2932
|
-
},
|
|
2933
|
-
outputs: [],
|
|
2934
|
-
// Empty for swaps
|
|
2935
|
-
swapParams: {
|
|
2936
|
-
output_mint: options.outputMint,
|
|
2937
|
-
recipient_ata: recipientAta.toBase58(),
|
|
2938
|
-
min_output_amount: minOutputAmount
|
|
2939
|
-
}
|
|
2940
|
-
};
|
|
2941
|
-
const proofResult = await this.artifactProver.generateProof(proofInputs, {
|
|
2942
|
-
onProgress: options.onProofProgress,
|
|
2943
|
-
onError: options.onProgress ? (error) => options.onProgress?.(`Proof generation error: ${error}`) : void 0
|
|
2944
|
-
});
|
|
2945
|
-
if (!proofResult.success || !proofResult.proof) {
|
|
2946
|
-
let errorMessage = proofResult.error || "Proof generation failed";
|
|
2947
|
-
if (errorMessage.startsWith("Proof generation failed: ")) {
|
|
2948
|
-
errorMessage = errorMessage.substring("Proof generation failed: ".length);
|
|
2949
|
-
}
|
|
2950
|
-
errorMessage += `
|
|
2951
|
-
Note details: leafIndex=${note.leafIndex}, root=${merkleRoot.slice(0, 16)}..., nullifier=${nullifierHex.slice(0, 16)}...`;
|
|
2952
|
-
throw new Error(errorMessage);
|
|
2953
|
-
}
|
|
2954
|
-
proofHex = proofResult.proof;
|
|
2955
|
-
finalPublicInputs = proofInputs.publicInputs;
|
|
2671
|
+
throw new Error(
|
|
2672
|
+
`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.`
|
|
2673
|
+
);
|
|
2956
2674
|
}
|
|
2957
2675
|
const signature = await this.relay.submitSwap(
|
|
2958
2676
|
{
|
|
@@ -3461,192 +3179,10 @@ function formatErrorForLogging(error) {
|
|
|
3461
3179
|
return String(error);
|
|
3462
3180
|
}
|
|
3463
3181
|
|
|
3464
|
-
// src/services/ProverService.ts
|
|
3465
|
-
var ProverService = class {
|
|
3466
|
-
/**
|
|
3467
|
-
* Create a new Prover Service client
|
|
3468
|
-
*
|
|
3469
|
-
* @param indexerUrl - Indexer/Prover service base URL
|
|
3470
|
-
* @param timeout - Proof generation timeout in ms (default: 5 minutes)
|
|
3471
|
-
*/
|
|
3472
|
-
constructor(indexerUrl, timeout = 5 * 60 * 1e3) {
|
|
3473
|
-
this.indexerUrl = indexerUrl.replace(/\/$/, "");
|
|
3474
|
-
this.timeout = timeout;
|
|
3475
|
-
}
|
|
3476
|
-
/**
|
|
3477
|
-
* Generate a zero-knowledge proof for withdrawal
|
|
3478
|
-
*
|
|
3479
|
-
* This process typically takes 30-180 seconds depending on the backend.
|
|
3480
|
-
*
|
|
3481
|
-
* @param inputs - Circuit inputs (private + public + outputs)
|
|
3482
|
-
* @param options - Optional progress tracking and callbacks
|
|
3483
|
-
* @returns Proof result with hex-encoded proof and public inputs
|
|
3484
|
-
*
|
|
3485
|
-
* @example
|
|
3486
|
-
* ```typescript
|
|
3487
|
-
* const result = await prover.generateProof(inputs);
|
|
3488
|
-
* if (result.success) {
|
|
3489
|
-
* console.log(`Proof: ${result.proof}`);
|
|
3490
|
-
* }
|
|
3491
|
-
* ```
|
|
3492
|
-
*
|
|
3493
|
-
* @example
|
|
3494
|
-
* ```typescript
|
|
3495
|
-
* // With progress tracking
|
|
3496
|
-
* const result = await prover.generateProof(inputs, {
|
|
3497
|
-
* onProgress: (progress) => console.log(`Progress: ${progress}%`),
|
|
3498
|
-
* onStart: () => console.log("Starting proof generation..."),
|
|
3499
|
-
* onSuccess: (result) => console.log("Proof generated!"),
|
|
3500
|
-
* onError: (error) => console.error("Failed:", error)
|
|
3501
|
-
* });
|
|
3502
|
-
* ```
|
|
3503
|
-
*/
|
|
3504
|
-
async generateProof(inputs, options) {
|
|
3505
|
-
const startTime = Date.now();
|
|
3506
|
-
const actualTimeout = options?.timeout || this.timeout;
|
|
3507
|
-
options?.onStart?.();
|
|
3508
|
-
let progressInterval;
|
|
3509
|
-
try {
|
|
3510
|
-
const requestBody = {
|
|
3511
|
-
private_inputs: JSON.stringify(inputs.privateInputs),
|
|
3512
|
-
public_inputs: JSON.stringify(inputs.publicInputs),
|
|
3513
|
-
outputs: JSON.stringify(inputs.outputs)
|
|
3514
|
-
};
|
|
3515
|
-
if (inputs.swapParams) {
|
|
3516
|
-
requestBody.swap_params = inputs.swapParams;
|
|
3517
|
-
}
|
|
3518
|
-
const controller = new AbortController();
|
|
3519
|
-
const timeoutId = setTimeout(() => controller.abort(), actualTimeout);
|
|
3520
|
-
if (options?.onProgress) {
|
|
3521
|
-
let progress = 0;
|
|
3522
|
-
progressInterval = setInterval(() => {
|
|
3523
|
-
progress = Math.min(90, progress + Math.random() * 10);
|
|
3524
|
-
options.onProgress(Math.floor(progress));
|
|
3525
|
-
}, 2e3);
|
|
3526
|
-
}
|
|
3527
|
-
const response = await fetch(`${this.indexerUrl}/api/v1/prove`, {
|
|
3528
|
-
method: "POST",
|
|
3529
|
-
headers: {
|
|
3530
|
-
"Content-Type": "application/json"
|
|
3531
|
-
},
|
|
3532
|
-
body: JSON.stringify(requestBody),
|
|
3533
|
-
signal: controller.signal
|
|
3534
|
-
});
|
|
3535
|
-
clearTimeout(timeoutId);
|
|
3536
|
-
if (progressInterval) clearInterval(progressInterval);
|
|
3537
|
-
if (!response.ok) {
|
|
3538
|
-
let errorMessage = `${response.status} ${response.statusText}`;
|
|
3539
|
-
try {
|
|
3540
|
-
const errorText = await response.text();
|
|
3541
|
-
try {
|
|
3542
|
-
const errorJson = JSON.parse(errorText);
|
|
3543
|
-
errorMessage = errorJson.error || errorJson.message || errorText;
|
|
3544
|
-
} catch {
|
|
3545
|
-
errorMessage = errorText || errorMessage;
|
|
3546
|
-
}
|
|
3547
|
-
} catch {
|
|
3548
|
-
}
|
|
3549
|
-
options?.onError?.(errorMessage);
|
|
3550
|
-
return {
|
|
3551
|
-
success: false,
|
|
3552
|
-
generationTimeMs: Date.now() - startTime,
|
|
3553
|
-
error: errorMessage
|
|
3554
|
-
};
|
|
3555
|
-
}
|
|
3556
|
-
options?.onProgress?.(100);
|
|
3557
|
-
const rawData = await response.json();
|
|
3558
|
-
const result = {
|
|
3559
|
-
success: rawData.success,
|
|
3560
|
-
proof: rawData.proof,
|
|
3561
|
-
publicInputs: rawData.public_inputs,
|
|
3562
|
-
// Map snake_case
|
|
3563
|
-
generationTimeMs: rawData.generation_time_ms || Date.now() - startTime,
|
|
3564
|
-
error: rawData.error
|
|
3565
|
-
};
|
|
3566
|
-
if (!result.success && rawData.execution_report) {
|
|
3567
|
-
}
|
|
3568
|
-
if (!result.success && result.error) {
|
|
3569
|
-
try {
|
|
3570
|
-
const errorObj = typeof result.error === "string" ? JSON.parse(result.error) : result.error;
|
|
3571
|
-
if (errorObj?.error && typeof errorObj.error === "string") {
|
|
3572
|
-
result.error = errorObj.error;
|
|
3573
|
-
} else if (typeof errorObj === "string") {
|
|
3574
|
-
result.error = errorObj;
|
|
3575
|
-
}
|
|
3576
|
-
if (errorObj?.execution_report && typeof errorObj.execution_report === "string") {
|
|
3577
|
-
result.error += `
|
|
3578
|
-
Execution report: ${errorObj.execution_report}`;
|
|
3579
|
-
}
|
|
3580
|
-
if (errorObj?.total_cycles !== void 0) {
|
|
3581
|
-
result.error += `
|
|
3582
|
-
Total cycles: ${errorObj.total_cycles}`;
|
|
3583
|
-
}
|
|
3584
|
-
if (errorObj?.total_syscalls !== void 0) {
|
|
3585
|
-
result.error += `
|
|
3586
|
-
Total syscalls: ${errorObj.total_syscalls}`;
|
|
3587
|
-
}
|
|
3588
|
-
} catch {
|
|
3589
|
-
}
|
|
3590
|
-
}
|
|
3591
|
-
if (result.success) {
|
|
3592
|
-
options?.onSuccess?.(result);
|
|
3593
|
-
} else if (result.error) {
|
|
3594
|
-
options?.onError?.(result.error);
|
|
3595
|
-
}
|
|
3596
|
-
return result;
|
|
3597
|
-
} catch (error) {
|
|
3598
|
-
const totalTime = Date.now() - startTime;
|
|
3599
|
-
if (progressInterval) clearInterval(progressInterval);
|
|
3600
|
-
let errorMessage;
|
|
3601
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
3602
|
-
errorMessage = `Proof generation timed out after ${actualTimeout}ms`;
|
|
3603
|
-
} else {
|
|
3604
|
-
errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
3605
|
-
}
|
|
3606
|
-
options?.onError?.(errorMessage);
|
|
3607
|
-
return {
|
|
3608
|
-
success: false,
|
|
3609
|
-
generationTimeMs: totalTime,
|
|
3610
|
-
error: errorMessage
|
|
3611
|
-
};
|
|
3612
|
-
}
|
|
3613
|
-
}
|
|
3614
|
-
/**
|
|
3615
|
-
* Check if the prover service is available
|
|
3616
|
-
*
|
|
3617
|
-
* @returns True if service is healthy
|
|
3618
|
-
*/
|
|
3619
|
-
async healthCheck() {
|
|
3620
|
-
try {
|
|
3621
|
-
const response = await fetch(`${this.indexerUrl}/health`, {
|
|
3622
|
-
method: "GET"
|
|
3623
|
-
});
|
|
3624
|
-
return response.ok;
|
|
3625
|
-
} catch {
|
|
3626
|
-
return false;
|
|
3627
|
-
}
|
|
3628
|
-
}
|
|
3629
|
-
/**
|
|
3630
|
-
* Get the configured timeout
|
|
3631
|
-
*/
|
|
3632
|
-
getTimeout() {
|
|
3633
|
-
return this.timeout;
|
|
3634
|
-
}
|
|
3635
|
-
/**
|
|
3636
|
-
* Set a new timeout
|
|
3637
|
-
*/
|
|
3638
|
-
setTimeout(timeout) {
|
|
3639
|
-
if (timeout <= 0) {
|
|
3640
|
-
throw new Error("Timeout must be positive");
|
|
3641
|
-
}
|
|
3642
|
-
this.timeout = timeout;
|
|
3643
|
-
}
|
|
3644
|
-
};
|
|
3645
|
-
|
|
3646
3182
|
// src/helpers/wallet-integration.ts
|
|
3647
|
-
var
|
|
3183
|
+
var import_web36 = require("@solana/web3.js");
|
|
3648
3184
|
function validateWalletConnected(wallet) {
|
|
3649
|
-
if (wallet instanceof
|
|
3185
|
+
if (wallet instanceof import_web36.Keypair) {
|
|
3650
3186
|
return;
|
|
3651
3187
|
}
|
|
3652
3188
|
if (!wallet.publicKey) {
|
|
@@ -3658,7 +3194,7 @@ function validateWalletConnected(wallet) {
|
|
|
3658
3194
|
}
|
|
3659
3195
|
}
|
|
3660
3196
|
function getPublicKey(wallet) {
|
|
3661
|
-
if (wallet instanceof
|
|
3197
|
+
if (wallet instanceof import_web36.Keypair) {
|
|
3662
3198
|
return wallet.publicKey;
|
|
3663
3199
|
}
|
|
3664
3200
|
if (!wallet.publicKey) {
|
|
@@ -3671,7 +3207,7 @@ function getPublicKey(wallet) {
|
|
|
3671
3207
|
return wallet.publicKey;
|
|
3672
3208
|
}
|
|
3673
3209
|
async function sendTransaction(transaction, wallet, connection, options) {
|
|
3674
|
-
if (wallet instanceof
|
|
3210
|
+
if (wallet instanceof import_web36.Keypair) {
|
|
3675
3211
|
return await connection.sendTransaction(transaction, [wallet], options);
|
|
3676
3212
|
}
|
|
3677
3213
|
if (wallet.sendTransaction) {
|
|
@@ -3688,7 +3224,7 @@ async function sendTransaction(transaction, wallet, connection, options) {
|
|
|
3688
3224
|
}
|
|
3689
3225
|
}
|
|
3690
3226
|
async function signTransaction(transaction, wallet) {
|
|
3691
|
-
if (wallet instanceof
|
|
3227
|
+
if (wallet instanceof import_web36.Keypair) {
|
|
3692
3228
|
transaction.sign(wallet);
|
|
3693
3229
|
return transaction;
|
|
3694
3230
|
}
|
|
@@ -3719,7 +3255,6 @@ function keypairToAdapter(keypair) {
|
|
|
3719
3255
|
var VERSION = "1.0.0";
|
|
3720
3256
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3721
3257
|
0 && (module.exports = {
|
|
3722
|
-
ArtifactProverService,
|
|
3723
3258
|
CLOAK_PROGRAM_ID,
|
|
3724
3259
|
CloakError,
|
|
3725
3260
|
CloakSDK,
|
|
@@ -3729,7 +3264,6 @@ var VERSION = "1.0.0";
|
|
|
3729
3264
|
LAMPORTS_PER_SOL,
|
|
3730
3265
|
LocalStorageAdapter,
|
|
3731
3266
|
MemoryStorageAdapter,
|
|
3732
|
-
ProverService,
|
|
3733
3267
|
RelayService,
|
|
3734
3268
|
VARIABLE_FEE_RATE,
|
|
3735
3269
|
VERSION,
|