@cloak.ag/sdk 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -4
- package/dist/index.cjs +1041 -63
- package/dist/index.d.cts +318 -8
- package/dist/index.d.ts +318 -8
- package/dist/index.js +1025 -63
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -34,12 +34,14 @@ __export(index_exports, {
|
|
|
34
34
|
CloakError: () => CloakError,
|
|
35
35
|
CloakSDK: () => CloakSDK,
|
|
36
36
|
DepositRecoveryService: () => DepositRecoveryService,
|
|
37
|
+
EXPECTED_CIRCUIT_HASHES: () => EXPECTED_CIRCUIT_HASHES,
|
|
37
38
|
FIXED_FEE_LAMPORTS: () => FIXED_FEE_LAMPORTS,
|
|
38
39
|
IndexerService: () => IndexerService,
|
|
39
40
|
LAMPORTS_PER_SOL: () => LAMPORTS_PER_SOL,
|
|
40
41
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
41
42
|
MemoryStorageAdapter: () => MemoryStorageAdapter,
|
|
42
43
|
RelayService: () => RelayService,
|
|
44
|
+
ShieldPoolErrors: () => ShieldPoolErrors,
|
|
43
45
|
VARIABLE_FEE_RATE: () => VARIABLE_FEE_RATE,
|
|
44
46
|
VERSION: () => VERSION,
|
|
45
47
|
bigintToBytes32: () => bigintToBytes32,
|
|
@@ -47,6 +49,9 @@ __export(index_exports, {
|
|
|
47
49
|
bytesToHex: () => bytesToHex,
|
|
48
50
|
calculateFee: () => calculateFee2,
|
|
49
51
|
calculateRelayFee: () => calculateRelayFee,
|
|
52
|
+
cleanupStalePendingOperations: () => cleanupStalePendingOperations,
|
|
53
|
+
clearPendingDeposits: () => clearPendingDeposits,
|
|
54
|
+
clearPendingWithdrawals: () => clearPendingWithdrawals,
|
|
50
55
|
computeCommitment: () => computeCommitment,
|
|
51
56
|
computeMerkleRoot: () => computeMerkleRoot,
|
|
52
57
|
computeNullifier: () => computeNullifier,
|
|
@@ -86,12 +91,14 @@ __export(index_exports, {
|
|
|
86
91
|
getAddressExplorerUrl: () => getAddressExplorerUrl,
|
|
87
92
|
getDistributableAmount: () => getDistributableAmount2,
|
|
88
93
|
getExplorerUrl: () => getExplorerUrl,
|
|
94
|
+
getPendingOperationsSummary: () => getPendingOperationsSummary,
|
|
89
95
|
getPublicKey: () => getPublicKey,
|
|
90
96
|
getPublicViewKey: () => getPublicViewKey,
|
|
91
97
|
getRecipientAmount: () => getRecipientAmount,
|
|
92
98
|
getRpcUrlForNetwork: () => getRpcUrlForNetwork,
|
|
93
99
|
getShieldPoolPDAs: () => getShieldPoolPDAs,
|
|
94
100
|
getViewKey: () => getViewKey,
|
|
101
|
+
hasPendingOperations: () => hasPendingOperations,
|
|
95
102
|
hexToBigint: () => hexToBigint,
|
|
96
103
|
hexToBytes: () => hexToBytes,
|
|
97
104
|
importKeys: () => importKeys,
|
|
@@ -101,7 +108,10 @@ __export(index_exports, {
|
|
|
101
108
|
isValidSolanaAddress: () => isValidSolanaAddress,
|
|
102
109
|
isWithdrawable: () => isWithdrawable,
|
|
103
110
|
keypairToAdapter: () => keypairToAdapter,
|
|
111
|
+
loadPendingDeposits: () => loadPendingDeposits,
|
|
112
|
+
loadPendingWithdrawals: () => loadPendingWithdrawals,
|
|
104
113
|
parseAmount: () => parseAmount,
|
|
114
|
+
parseError: () => parseError,
|
|
105
115
|
parseNote: () => parseNote,
|
|
106
116
|
parseTransactionError: () => parseTransactionError,
|
|
107
117
|
poseidonHash: () => poseidonHash,
|
|
@@ -110,6 +120,10 @@ __export(index_exports, {
|
|
|
110
120
|
proofToBytes: () => proofToBytes,
|
|
111
121
|
pubkeyToLimbs: () => pubkeyToLimbs,
|
|
112
122
|
randomBytes: () => randomBytes,
|
|
123
|
+
removePendingDeposit: () => removePendingDeposit,
|
|
124
|
+
removePendingWithdrawal: () => removePendingWithdrawal,
|
|
125
|
+
savePendingDeposit: () => savePendingDeposit,
|
|
126
|
+
savePendingWithdrawal: () => savePendingWithdrawal,
|
|
113
127
|
scanNotesForWallet: () => scanNotesForWallet,
|
|
114
128
|
sendTransaction: () => sendTransaction,
|
|
115
129
|
serializeNote: () => serializeNote,
|
|
@@ -117,12 +131,16 @@ __export(index_exports, {
|
|
|
117
131
|
splitTo2Limbs: () => splitTo2Limbs,
|
|
118
132
|
tryDecryptNote: () => tryDecryptNote,
|
|
119
133
|
updateNoteWithDeposit: () => updateNoteWithDeposit,
|
|
134
|
+
updatePendingDeposit: () => updatePendingDeposit,
|
|
135
|
+
updatePendingWithdrawal: () => updatePendingWithdrawal,
|
|
120
136
|
validateDepositParams: () => validateDepositParams,
|
|
121
137
|
validateNote: () => validateNote,
|
|
122
138
|
validateOutputsSum: () => validateOutputsSum,
|
|
123
139
|
validateTransfers: () => validateTransfers,
|
|
124
140
|
validateWalletConnected: () => validateWalletConnected,
|
|
125
|
-
validateWithdrawableNote: () => validateWithdrawableNote
|
|
141
|
+
validateWithdrawableNote: () => validateWithdrawableNote,
|
|
142
|
+
verifyAllCircuits: () => verifyAllCircuits,
|
|
143
|
+
verifyCircuitIntegrity: () => verifyCircuitIntegrity
|
|
126
144
|
});
|
|
127
145
|
module.exports = __toCommonJS(index_exports);
|
|
128
146
|
|
|
@@ -1160,6 +1178,8 @@ var RelayService = class {
|
|
|
1160
1178
|
*
|
|
1161
1179
|
* @param params - Withdrawal parameters
|
|
1162
1180
|
* @param onStatusUpdate - Optional callback for status updates
|
|
1181
|
+
* @param onRequestId - CRITICAL: Callback when request_id is received.
|
|
1182
|
+
* Persist this ID to recover if browser crashes during polling.
|
|
1163
1183
|
* @returns Transaction signature when completed
|
|
1164
1184
|
*
|
|
1165
1185
|
* @example
|
|
@@ -1169,11 +1189,12 @@ var RelayService = class {
|
|
|
1169
1189
|
* publicInputs: { root, nf, outputs_hash, amount },
|
|
1170
1190
|
* outputs: [{ recipient: addr, amount: lamports }],
|
|
1171
1191
|
* feeBps: 50
|
|
1172
|
-
* }, (status) => console.log(`Status: ${status}`)
|
|
1192
|
+
* }, (status) => console.log(`Status: ${status}`),
|
|
1193
|
+
* (requestId) => localStorage.setItem('pending_withdraw', requestId));
|
|
1173
1194
|
* console.log(`Transaction: ${signature}`);
|
|
1174
1195
|
* ```
|
|
1175
1196
|
*/
|
|
1176
|
-
async submitWithdraw(params, onStatusUpdate) {
|
|
1197
|
+
async submitWithdraw(params, onStatusUpdate, onRequestId) {
|
|
1177
1198
|
const proofBytes = hexToBytes(params.proof);
|
|
1178
1199
|
const proofBase64 = this.bytesToBase64(proofBytes);
|
|
1179
1200
|
const requestBody = {
|
|
@@ -1214,8 +1235,55 @@ var RelayService = class {
|
|
|
1214
1235
|
if (!requestId) {
|
|
1215
1236
|
throw new Error("Relay response missing request_id");
|
|
1216
1237
|
}
|
|
1238
|
+
if (onRequestId) {
|
|
1239
|
+
onRequestId(requestId);
|
|
1240
|
+
}
|
|
1217
1241
|
return this.pollForCompletion(requestId, onStatusUpdate);
|
|
1218
1242
|
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Resume polling for a withdrawal that was previously started
|
|
1245
|
+
*
|
|
1246
|
+
* Use this after page reload to check status of a pending withdrawal.
|
|
1247
|
+
* The requestId should have been persisted via the onRequestId callback.
|
|
1248
|
+
*
|
|
1249
|
+
* @param requestId - Request ID from a previous submitWithdraw call
|
|
1250
|
+
* @param onStatusUpdate - Optional callback for status updates
|
|
1251
|
+
* @returns Transaction signature if completed, null if still pending/failed
|
|
1252
|
+
*
|
|
1253
|
+
* @example
|
|
1254
|
+
* ```typescript
|
|
1255
|
+
* // On page load, check for pending withdrawal
|
|
1256
|
+
* const pendingId = localStorage.getItem('pending_withdraw');
|
|
1257
|
+
* if (pendingId) {
|
|
1258
|
+
* const result = await relay.resumeWithdraw(pendingId);
|
|
1259
|
+
* if (result.status === 'completed') {
|
|
1260
|
+
* console.log('Withdrawal completed:', result.signature);
|
|
1261
|
+
* localStorage.removeItem('pending_withdraw');
|
|
1262
|
+
* }
|
|
1263
|
+
* }
|
|
1264
|
+
* ```
|
|
1265
|
+
*/
|
|
1266
|
+
async resumeWithdraw(requestId, onStatusUpdate) {
|
|
1267
|
+
try {
|
|
1268
|
+
const status = await this.getStatus(requestId);
|
|
1269
|
+
if (onStatusUpdate) {
|
|
1270
|
+
onStatusUpdate(status.status);
|
|
1271
|
+
}
|
|
1272
|
+
if (status.status === "completed") {
|
|
1273
|
+
return { status: "completed", signature: status.txId };
|
|
1274
|
+
} else if (status.status === "failed") {
|
|
1275
|
+
return { status: "failed", error: status.error };
|
|
1276
|
+
} else {
|
|
1277
|
+
const signature = await this.pollForCompletion(requestId, onStatusUpdate);
|
|
1278
|
+
return { status: "completed", signature };
|
|
1279
|
+
}
|
|
1280
|
+
} catch (error) {
|
|
1281
|
+
return {
|
|
1282
|
+
status: "failed",
|
|
1283
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1219
1287
|
/**
|
|
1220
1288
|
* Poll for withdrawal completion
|
|
1221
1289
|
*
|
|
@@ -1288,7 +1356,7 @@ var RelayService = class {
|
|
|
1288
1356
|
* console.log(`Transaction: ${signature}`);
|
|
1289
1357
|
* ```
|
|
1290
1358
|
*/
|
|
1291
|
-
async submitSwap(params, onStatusUpdate) {
|
|
1359
|
+
async submitSwap(params, onStatusUpdate, onRequestId) {
|
|
1292
1360
|
const proofBytes = hexToBytes(params.proof);
|
|
1293
1361
|
const proofBase64 = this.bytesToBase64(proofBytes);
|
|
1294
1362
|
const requestBody = {
|
|
@@ -1330,6 +1398,9 @@ var RelayService = class {
|
|
|
1330
1398
|
if (!requestId) {
|
|
1331
1399
|
throw new Error("Relay response missing request_id");
|
|
1332
1400
|
}
|
|
1401
|
+
if (onRequestId) {
|
|
1402
|
+
onRequestId(requestId);
|
|
1403
|
+
}
|
|
1333
1404
|
return this.pollForCompletion(requestId, onStatusUpdate);
|
|
1334
1405
|
}
|
|
1335
1406
|
/**
|
|
@@ -1566,29 +1637,94 @@ var DepositRecoveryService = class {
|
|
|
1566
1637
|
}
|
|
1567
1638
|
/**
|
|
1568
1639
|
* Check if a deposit already exists in the indexer
|
|
1640
|
+
* Uses the enhanced deposit lookup endpoint with include_proof=true
|
|
1569
1641
|
*
|
|
1570
1642
|
* @private
|
|
1571
1643
|
*/
|
|
1572
|
-
async checkExistingDeposit(
|
|
1644
|
+
async checkExistingDeposit(commitment) {
|
|
1573
1645
|
try {
|
|
1574
|
-
const
|
|
1575
|
-
const
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
return null;
|
|
1582
|
-
} catch (e) {
|
|
1583
|
-
continue;
|
|
1584
|
-
}
|
|
1646
|
+
const cleanCommit = commitment.replace(/^0x/, "").toLowerCase();
|
|
1647
|
+
const response = await fetch(
|
|
1648
|
+
`${this.apiUrl}/api/v1/deposit/${cleanCommit}?include_proof=true`
|
|
1649
|
+
);
|
|
1650
|
+
if (!response.ok) {
|
|
1651
|
+
if (response.status === 404) {
|
|
1652
|
+
return null;
|
|
1585
1653
|
}
|
|
1654
|
+
throw new Error(`Failed to check deposit: ${response.status}`);
|
|
1586
1655
|
}
|
|
1587
|
-
|
|
1656
|
+
const data = await response.json();
|
|
1657
|
+
if (!data.merkle_proof) {
|
|
1658
|
+
const merkleProof = await this.indexer.getMerkleProof(data.leaf_index);
|
|
1659
|
+
return {
|
|
1660
|
+
leafIndex: data.leaf_index,
|
|
1661
|
+
root: merkleProof.root || "",
|
|
1662
|
+
slot: data.slot,
|
|
1663
|
+
merkleProof: {
|
|
1664
|
+
pathElements: merkleProof.pathElements,
|
|
1665
|
+
pathIndices: merkleProof.pathIndices
|
|
1666
|
+
}
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1669
|
+
return {
|
|
1670
|
+
leafIndex: data.leaf_index,
|
|
1671
|
+
root: data.merkle_proof.root,
|
|
1672
|
+
slot: data.slot,
|
|
1673
|
+
merkleProof: {
|
|
1674
|
+
pathElements: data.merkle_proof.path_elements,
|
|
1675
|
+
pathIndices: data.merkle_proof.path_indices
|
|
1676
|
+
}
|
|
1677
|
+
};
|
|
1588
1678
|
} catch (error) {
|
|
1589
1679
|
return null;
|
|
1590
1680
|
}
|
|
1591
1681
|
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Recover deposit by transaction signature
|
|
1684
|
+
* Uses the indexer's signature lookup endpoint
|
|
1685
|
+
*/
|
|
1686
|
+
async recoverBySignature(signature) {
|
|
1687
|
+
try {
|
|
1688
|
+
const response = await fetch(
|
|
1689
|
+
`${this.apiUrl}/api/v1/deposit/tx/${signature}?include_proof=true`
|
|
1690
|
+
);
|
|
1691
|
+
if (!response.ok) {
|
|
1692
|
+
if (response.status === 404) {
|
|
1693
|
+
return {
|
|
1694
|
+
success: false,
|
|
1695
|
+
error: "Deposit not found for this transaction signature"
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
const errorText = await response.text();
|
|
1699
|
+
return {
|
|
1700
|
+
success: false,
|
|
1701
|
+
error: `Failed to recover deposit: ${errorText}`
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
const data = await response.json();
|
|
1705
|
+
if (!data.merkle_proof) {
|
|
1706
|
+
return {
|
|
1707
|
+
success: false,
|
|
1708
|
+
error: "Deposit found but merkle proof not available"
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
return {
|
|
1712
|
+
success: true,
|
|
1713
|
+
leafIndex: data.leaf_index,
|
|
1714
|
+
root: data.merkle_proof.root,
|
|
1715
|
+
slot: data.slot,
|
|
1716
|
+
merkleProof: {
|
|
1717
|
+
pathElements: data.merkle_proof.path_elements,
|
|
1718
|
+
pathIndices: data.merkle_proof.path_indices
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1721
|
+
} catch (error) {
|
|
1722
|
+
return {
|
|
1723
|
+
success: false,
|
|
1724
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1592
1728
|
/**
|
|
1593
1729
|
* Finalize a deposit via server API (alternative recovery method)
|
|
1594
1730
|
*
|
|
@@ -1744,39 +1880,30 @@ function getShieldPoolPDAs(programId, mint) {
|
|
|
1744
1880
|
|
|
1745
1881
|
// src/utils/proof-generation.ts
|
|
1746
1882
|
var snarkjs = __toESM(require("snarkjs"), 1);
|
|
1747
|
-
var
|
|
1748
|
-
var
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1883
|
+
var IS_BROWSER = typeof window !== "undefined" || typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
|
|
1884
|
+
var _nodePath = null;
|
|
1885
|
+
var _nodeFs = null;
|
|
1886
|
+
var _nodeCrypto = null;
|
|
1887
|
+
async function getNodePath() {
|
|
1888
|
+
if (_nodePath) return _nodePath;
|
|
1889
|
+
_nodePath = await import("path");
|
|
1890
|
+
return _nodePath;
|
|
1891
|
+
}
|
|
1892
|
+
async function getNodeFs() {
|
|
1893
|
+
if (_nodeFs) return _nodeFs;
|
|
1894
|
+
_nodeFs = await import("fs");
|
|
1895
|
+
return _nodeFs;
|
|
1896
|
+
}
|
|
1897
|
+
async function getNodeCrypto() {
|
|
1898
|
+
if (_nodeCrypto) return _nodeCrypto;
|
|
1899
|
+
_nodeCrypto = await import("crypto");
|
|
1900
|
+
return _nodeCrypto;
|
|
1761
1901
|
}
|
|
1762
1902
|
function joinPath(...parts) {
|
|
1763
|
-
const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
|
|
1764
|
-
if (!isBrowser && path) {
|
|
1765
|
-
return path.join(...parts);
|
|
1766
|
-
}
|
|
1767
1903
|
return parts.join("/").replace(/\/+/g, "/");
|
|
1768
1904
|
}
|
|
1769
1905
|
async function fileExists(filePath) {
|
|
1770
|
-
|
|
1771
|
-
if (fs2) {
|
|
1772
|
-
try {
|
|
1773
|
-
return fs2.existsSync(filePath);
|
|
1774
|
-
} catch {
|
|
1775
|
-
return false;
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
|
|
1779
|
-
if (isBrowser) {
|
|
1906
|
+
if (IS_BROWSER) {
|
|
1780
1907
|
try {
|
|
1781
1908
|
const response = await fetch(filePath, { method: "HEAD" });
|
|
1782
1909
|
return response.ok;
|
|
@@ -1784,13 +1911,21 @@ async function fileExists(filePath) {
|
|
|
1784
1911
|
return false;
|
|
1785
1912
|
}
|
|
1786
1913
|
}
|
|
1787
|
-
|
|
1914
|
+
try {
|
|
1915
|
+
const nodeFs = globalThis.require?.("fs") || (typeof require !== "undefined" ? require("fs") : null);
|
|
1916
|
+
if (nodeFs) {
|
|
1917
|
+
return nodeFs.existsSync(filePath);
|
|
1918
|
+
}
|
|
1919
|
+
const fsModule = await import("fs");
|
|
1920
|
+
return fsModule.existsSync(filePath);
|
|
1921
|
+
} catch {
|
|
1922
|
+
return false;
|
|
1923
|
+
}
|
|
1788
1924
|
}
|
|
1789
1925
|
async function generateWithdrawRegularProof(inputs, circuitsPath) {
|
|
1790
|
-
const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
|
|
1791
1926
|
let wasmPath;
|
|
1792
1927
|
let zkeyPath;
|
|
1793
|
-
if (
|
|
1928
|
+
if (IS_BROWSER) {
|
|
1794
1929
|
wasmPath = `${circuitsPath}/withdraw_regular_js/withdraw_regular.wasm`;
|
|
1795
1930
|
zkeyPath = `${circuitsPath}/withdraw_regular_final.zkey`;
|
|
1796
1931
|
} else {
|
|
@@ -1838,10 +1973,9 @@ async function generateWithdrawRegularProof(inputs, circuitsPath) {
|
|
|
1838
1973
|
};
|
|
1839
1974
|
}
|
|
1840
1975
|
async function generateWithdrawSwapProof(inputs, circuitsPath) {
|
|
1841
|
-
const isBrowser = typeof window !== "undefined" || typeof globalThis !== "undefined" && globalThis.window;
|
|
1842
1976
|
let wasmPath;
|
|
1843
1977
|
let zkeyPath;
|
|
1844
|
-
if (
|
|
1978
|
+
if (IS_BROWSER) {
|
|
1845
1979
|
wasmPath = `${circuitsPath}/withdraw_swap_js/withdraw_swap.wasm`;
|
|
1846
1980
|
zkeyPath = `${circuitsPath}/withdraw_swap_final.zkey`;
|
|
1847
1981
|
} else {
|
|
@@ -1896,8 +2030,7 @@ async function generateWithdrawSwapProof(inputs, circuitsPath) {
|
|
|
1896
2030
|
};
|
|
1897
2031
|
}
|
|
1898
2032
|
async function areCircuitsAvailable(circuitsPath) {
|
|
1899
|
-
|
|
1900
|
-
if (isBrowser) {
|
|
2033
|
+
if (IS_BROWSER) {
|
|
1901
2034
|
return Boolean(circuitsPath && circuitsPath !== "");
|
|
1902
2035
|
}
|
|
1903
2036
|
const wasmPath = joinPath(circuitsPath, "build", "withdraw_regular_js", "withdraw_regular.wasm");
|
|
@@ -1907,20 +2040,24 @@ async function areCircuitsAvailable(circuitsPath) {
|
|
|
1907
2040
|
return wasmExists && zkeyExists;
|
|
1908
2041
|
}
|
|
1909
2042
|
async function getDefaultCircuitsPath() {
|
|
1910
|
-
|
|
1911
|
-
|
|
2043
|
+
if (IS_BROWSER) {
|
|
2044
|
+
return "/circuits";
|
|
2045
|
+
}
|
|
2046
|
+
if (typeof process === "undefined" || !process.cwd) {
|
|
1912
2047
|
return "/circuits";
|
|
1913
2048
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
2049
|
+
let nodePath;
|
|
2050
|
+
try {
|
|
2051
|
+
nodePath = await getNodePath();
|
|
2052
|
+
} catch {
|
|
1916
2053
|
return "/circuits";
|
|
1917
2054
|
}
|
|
1918
2055
|
const possiblePaths = [
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
2056
|
+
nodePath.resolve(process.cwd(), "../../packages-new/circuits"),
|
|
2057
|
+
nodePath.resolve(process.cwd(), "../packages-new/circuits"),
|
|
2058
|
+
nodePath.resolve(process.cwd(), "packages-new/circuits"),
|
|
2059
|
+
nodePath.resolve(process.cwd(), "../../circuits"),
|
|
2060
|
+
nodePath.resolve(process.cwd(), "../circuits")
|
|
1924
2061
|
];
|
|
1925
2062
|
for (const p of possiblePaths) {
|
|
1926
2063
|
if (await areCircuitsAvailable(p)) {
|
|
@@ -1929,8 +2066,103 @@ async function getDefaultCircuitsPath() {
|
|
|
1929
2066
|
}
|
|
1930
2067
|
return possiblePaths[0];
|
|
1931
2068
|
}
|
|
2069
|
+
var EXPECTED_CIRCUIT_HASHES = {
|
|
2070
|
+
// SHA-256 of the verification key JSON from withdraw_regular circuit
|
|
2071
|
+
withdraw_regular_vkey: null,
|
|
2072
|
+
// Set to null to skip check during development
|
|
2073
|
+
// SHA-256 of the verification key JSON from withdraw_swap circuit
|
|
2074
|
+
withdraw_swap_vkey: null
|
|
2075
|
+
// Set to null to skip check during development
|
|
2076
|
+
};
|
|
2077
|
+
async function verifyCircuitIntegrity(circuitsPath, circuit) {
|
|
2078
|
+
const expectedHash = circuit === "withdraw_regular" ? EXPECTED_CIRCUIT_HASHES.withdraw_regular_vkey : EXPECTED_CIRCUIT_HASHES.withdraw_swap_vkey;
|
|
2079
|
+
if (!expectedHash) {
|
|
2080
|
+
return {
|
|
2081
|
+
valid: true,
|
|
2082
|
+
circuit,
|
|
2083
|
+
error: "Verification skipped (no expected hash configured)"
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
try {
|
|
2087
|
+
const vkeyPath = IS_BROWSER ? `${circuitsPath}/${circuit}_verification_key.json` : joinPath(circuitsPath, "build", `${circuit}_verification_key.json`);
|
|
2088
|
+
let vkeyData;
|
|
2089
|
+
if (IS_BROWSER) {
|
|
2090
|
+
const response = await fetch(vkeyPath);
|
|
2091
|
+
if (!response.ok) {
|
|
2092
|
+
return {
|
|
2093
|
+
valid: false,
|
|
2094
|
+
circuit,
|
|
2095
|
+
error: `Failed to fetch verification key: ${response.status}`
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
vkeyData = await response.text();
|
|
2099
|
+
} else {
|
|
2100
|
+
try {
|
|
2101
|
+
const nodeFs = await getNodeFs();
|
|
2102
|
+
vkeyData = nodeFs.readFileSync(vkeyPath, "utf8");
|
|
2103
|
+
} catch (e) {
|
|
2104
|
+
return {
|
|
2105
|
+
valid: false,
|
|
2106
|
+
circuit,
|
|
2107
|
+
error: `Failed to read verification key: ${e}`
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
let computedHash;
|
|
2112
|
+
if (IS_BROWSER) {
|
|
2113
|
+
const encoder = new TextEncoder();
|
|
2114
|
+
const data = encoder.encode(vkeyData);
|
|
2115
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
2116
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
2117
|
+
computedHash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2118
|
+
} else {
|
|
2119
|
+
const nodeCrypto = await getNodeCrypto();
|
|
2120
|
+
computedHash = nodeCrypto.createHash("sha256").update(vkeyData).digest("hex");
|
|
2121
|
+
}
|
|
2122
|
+
if (computedHash === expectedHash) {
|
|
2123
|
+
return {
|
|
2124
|
+
valid: true,
|
|
2125
|
+
circuit,
|
|
2126
|
+
computedHash,
|
|
2127
|
+
expectedHash
|
|
2128
|
+
};
|
|
2129
|
+
} else {
|
|
2130
|
+
return {
|
|
2131
|
+
valid: false,
|
|
2132
|
+
circuit,
|
|
2133
|
+
error: `Verification key hash mismatch! This circuit may produce invalid proofs.`,
|
|
2134
|
+
computedHash,
|
|
2135
|
+
expectedHash
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
} catch (error) {
|
|
2139
|
+
return {
|
|
2140
|
+
valid: false,
|
|
2141
|
+
circuit,
|
|
2142
|
+
error: `Circuit verification failed: ${error instanceof Error ? error.message : String(error)}`
|
|
2143
|
+
};
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
async function verifyAllCircuits(circuitsPath) {
|
|
2147
|
+
const results = await Promise.all([
|
|
2148
|
+
verifyCircuitIntegrity(circuitsPath, "withdraw_regular"),
|
|
2149
|
+
verifyCircuitIntegrity(circuitsPath, "withdraw_swap")
|
|
2150
|
+
]);
|
|
2151
|
+
return results;
|
|
2152
|
+
}
|
|
1932
2153
|
|
|
1933
2154
|
// src/core/CloakSDK.ts
|
|
2155
|
+
var COMPUTE_BUDGET_PROGRAM_ID = new import_web35.PublicKey("ComputeBudget111111111111111111111111111111");
|
|
2156
|
+
function createSetLoadedAccountsDataSizeLimitInstruction(bytes) {
|
|
2157
|
+
const data = Buffer.alloc(5);
|
|
2158
|
+
data.writeUInt8(4, 0);
|
|
2159
|
+
data.writeUInt32LE(bytes, 1);
|
|
2160
|
+
return new import_web35.TransactionInstruction({
|
|
2161
|
+
keys: [],
|
|
2162
|
+
programId: COMPUTE_BUDGET_PROGRAM_ID,
|
|
2163
|
+
data
|
|
2164
|
+
});
|
|
2165
|
+
}
|
|
1934
2166
|
var CLOAK_PROGRAM_ID = new import_web35.PublicKey("c1oak6tetxYnNfvXKFkpn1d98FxtK7B68vBQLYQpWKp");
|
|
1935
2167
|
var CLOAK_API_URL = "https://api.cloak.ag";
|
|
1936
2168
|
var CloakSDK = class {
|
|
@@ -2043,14 +2275,35 @@ var CloakSDK = class {
|
|
|
2043
2275
|
async deposit(connection, amountOrNote, options) {
|
|
2044
2276
|
try {
|
|
2045
2277
|
let note;
|
|
2278
|
+
let isNewNote = false;
|
|
2046
2279
|
if (typeof amountOrNote === "number") {
|
|
2280
|
+
options?.onProgress?.("generating_note", { message: "Generating note with secrets..." });
|
|
2047
2281
|
note = await generateNote(amountOrNote, this.config.network);
|
|
2282
|
+
isNewNote = true;
|
|
2048
2283
|
} else {
|
|
2049
2284
|
note = amountOrNote;
|
|
2050
2285
|
if (note.depositSignature) {
|
|
2051
2286
|
throw new Error("Note has already been deposited");
|
|
2052
2287
|
}
|
|
2053
2288
|
}
|
|
2289
|
+
if (isNewNote) {
|
|
2290
|
+
await this.storage.saveNote(note);
|
|
2291
|
+
if (options?.onNoteGenerated) {
|
|
2292
|
+
options?.onProgress?.("awaiting_note_acknowledgment", {
|
|
2293
|
+
message: "Waiting for note to be saved before proceeding with deposit..."
|
|
2294
|
+
});
|
|
2295
|
+
try {
|
|
2296
|
+
await options.onNoteGenerated(note);
|
|
2297
|
+
} catch (error) {
|
|
2298
|
+
throw new Error(
|
|
2299
|
+
`Failed to save note before deposit: ${error instanceof Error ? error.message : String(error)}. For your safety, the deposit has been aborted. Your funds are safe.`
|
|
2300
|
+
);
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
options?.onProgress?.("note_saved", {
|
|
2304
|
+
message: "Note saved. Proceeding with on-chain deposit..."
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2054
2307
|
const payerPubkey = this.getPublicKey();
|
|
2055
2308
|
const balance = await connection.getBalance(payerPubkey);
|
|
2056
2309
|
const requiredAmount = note.amount + 5e3;
|
|
@@ -2070,10 +2323,51 @@ var CloakSDK = class {
|
|
|
2070
2323
|
commitment: commitmentBytes
|
|
2071
2324
|
});
|
|
2072
2325
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
2326
|
+
const priorityFee = options?.priorityFee ?? 1e4;
|
|
2327
|
+
const cuPriceIx = import_web35.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee });
|
|
2328
|
+
const dataSizeLimit = options?.loadedAccountsDataSizeLimit ?? 256 * 1024;
|
|
2329
|
+
const dataSizeLimitIx = dataSizeLimit > 0 ? createSetLoadedAccountsDataSizeLimitInstruction(dataSizeLimit) : null;
|
|
2330
|
+
let computeUnits;
|
|
2331
|
+
if (options?.optimizeCU && this.keypair) {
|
|
2332
|
+
options?.onProgress?.("simulating", { message: "Simulating transaction for optimal CU..." });
|
|
2333
|
+
const simCuLimitIx = import_web35.ComputeBudgetProgram.setComputeUnitLimit({ units: 2e5 });
|
|
2334
|
+
const simTransaction = new import_web35.Transaction({
|
|
2335
|
+
feePayer: payerPubkey,
|
|
2336
|
+
recentBlockhash: blockhash
|
|
2337
|
+
}).add(simCuLimitIx).add(cuPriceIx);
|
|
2338
|
+
if (dataSizeLimitIx) {
|
|
2339
|
+
simTransaction.add(dataSizeLimitIx);
|
|
2340
|
+
}
|
|
2341
|
+
simTransaction.add(depositIx);
|
|
2342
|
+
try {
|
|
2343
|
+
const simulation = await connection.simulateTransaction(simTransaction, [this.keypair]);
|
|
2344
|
+
if (simulation.value.err) {
|
|
2345
|
+
console.warn("Simulation failed, using default CU:", simulation.value.err);
|
|
2346
|
+
computeUnits = 4e4;
|
|
2347
|
+
} else {
|
|
2348
|
+
const simulatedCU = simulation.value.unitsConsumed ?? 3e4;
|
|
2349
|
+
computeUnits = Math.ceil(simulatedCU * 1.2);
|
|
2350
|
+
console.log(`CU optimization: ${simulatedCU} simulated \u2192 ${computeUnits} limit`);
|
|
2351
|
+
}
|
|
2352
|
+
} catch (simError) {
|
|
2353
|
+
console.warn("Simulation RPC error, using default CU:", simError);
|
|
2354
|
+
computeUnits = 4e4;
|
|
2355
|
+
}
|
|
2356
|
+
} else if (options?.optimizeCU && this.wallet) {
|
|
2357
|
+
console.warn("CU optimization via simulation not available in wallet mode (would require double signing). Using default.");
|
|
2358
|
+
computeUnits = options?.computeUnits ?? 4e4;
|
|
2359
|
+
} else {
|
|
2360
|
+
computeUnits = options?.computeUnits ?? 4e4;
|
|
2361
|
+
}
|
|
2362
|
+
const cuLimitIx = import_web35.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits });
|
|
2073
2363
|
const transaction = new import_web35.Transaction({
|
|
2074
2364
|
feePayer: payerPubkey,
|
|
2075
2365
|
recentBlockhash: blockhash
|
|
2076
|
-
}).add(
|
|
2366
|
+
}).add(cuLimitIx).add(cuPriceIx);
|
|
2367
|
+
if (dataSizeLimitIx) {
|
|
2368
|
+
transaction.add(dataSizeLimitIx);
|
|
2369
|
+
}
|
|
2370
|
+
transaction.add(depositIx);
|
|
2077
2371
|
if (!transaction.feePayer) {
|
|
2078
2372
|
throw new Error("Transaction feePayer is not set");
|
|
2079
2373
|
}
|
|
@@ -2242,6 +2536,16 @@ var CloakSDK = class {
|
|
|
2242
2536
|
pathIndices: merkleProof.pathIndices
|
|
2243
2537
|
}
|
|
2244
2538
|
});
|
|
2539
|
+
await this.storage.updateNote(note.commitment, {
|
|
2540
|
+
depositSignature: signature,
|
|
2541
|
+
depositSlot,
|
|
2542
|
+
leafIndex,
|
|
2543
|
+
root,
|
|
2544
|
+
merkleProof: {
|
|
2545
|
+
pathElements: merkleProof.pathElements,
|
|
2546
|
+
pathIndices: merkleProof.pathIndices
|
|
2547
|
+
}
|
|
2548
|
+
});
|
|
2245
2549
|
return {
|
|
2246
2550
|
note: updatedNote,
|
|
2247
2551
|
signature,
|
|
@@ -3044,6 +3348,63 @@ async function copyNoteToClipboard(note) {
|
|
|
3044
3348
|
}
|
|
3045
3349
|
|
|
3046
3350
|
// src/utils/errors.ts
|
|
3351
|
+
var ShieldPoolErrors = {
|
|
3352
|
+
// Root management errors
|
|
3353
|
+
4096: "Invalid Merkle root",
|
|
3354
|
+
4097: "Root not found in the roots ring",
|
|
3355
|
+
4098: "Roots ring is full",
|
|
3356
|
+
// Proof verification errors
|
|
3357
|
+
4112: "Zero-knowledge proof is invalid",
|
|
3358
|
+
4113: "Invalid proof size (expected 260 bytes)",
|
|
3359
|
+
4114: "Invalid public inputs",
|
|
3360
|
+
4115: "Verification key mismatch",
|
|
3361
|
+
// Nullifier errors
|
|
3362
|
+
4128: "Double spend detected - this note has already been spent",
|
|
3363
|
+
4129: "Nullifier shard is full",
|
|
3364
|
+
4130: "Invalid nullifier",
|
|
3365
|
+
// Transaction validation errors
|
|
3366
|
+
4144: "Output addresses or amounts don't match the proof",
|
|
3367
|
+
4145: "Amount conservation failed - outputs + fee must equal input amount",
|
|
3368
|
+
4146: "Invalid outputs hash",
|
|
3369
|
+
4147: "Invalid amount (must be greater than zero)",
|
|
3370
|
+
4148: "Invalid recipient address",
|
|
3371
|
+
4149: "Commitment already exists in the tree",
|
|
3372
|
+
4150: "Commitment log is full",
|
|
3373
|
+
// Math errors
|
|
3374
|
+
4160: "Math overflow occurred",
|
|
3375
|
+
4161: "Division by zero",
|
|
3376
|
+
// Account errors
|
|
3377
|
+
4176: "Account validation failed - please check your wallet balance and try again",
|
|
3378
|
+
4177: "Pool account owner mismatch",
|
|
3379
|
+
4178: "Treasury account owner mismatch",
|
|
3380
|
+
4179: "Roots ring account owner mismatch",
|
|
3381
|
+
4180: "Nullifier shard account owner mismatch",
|
|
3382
|
+
4181: "Pool account is not writable",
|
|
3383
|
+
4182: "Treasury account is not writable",
|
|
3384
|
+
4183: "Recipient account is not writable",
|
|
3385
|
+
4184: "Insufficient lamports in pool or account",
|
|
3386
|
+
4185: "Invalid account owner",
|
|
3387
|
+
4186: "Invalid account size",
|
|
3388
|
+
4187: "Commitments account is not writable",
|
|
3389
|
+
4188: "Invalid admin authority",
|
|
3390
|
+
// Instruction errors
|
|
3391
|
+
4192: "Invalid instruction data length",
|
|
3392
|
+
4193: "Invalid instruction data format",
|
|
3393
|
+
4194: "Missing required accounts",
|
|
3394
|
+
4195: "Invalid instruction tag",
|
|
3395
|
+
// PoW/Scrambler errors
|
|
3396
|
+
4196: "Invalid miner account",
|
|
3397
|
+
4197: "Invalid claim account",
|
|
3398
|
+
4198: "Failed to consume claim",
|
|
3399
|
+
// Groth16 verifier errors
|
|
3400
|
+
4208: "Invalid G1 point length",
|
|
3401
|
+
4209: "Invalid G2 point length",
|
|
3402
|
+
4210: "Invalid public inputs length",
|
|
3403
|
+
4211: "Public input exceeds field size",
|
|
3404
|
+
4212: "G1 multiplication failed during proof preparation",
|
|
3405
|
+
4213: "G1 addition failed during proof preparation",
|
|
3406
|
+
4214: "Proof verification failed"
|
|
3407
|
+
};
|
|
3047
3408
|
var PROGRAM_ERRORS = {
|
|
3048
3409
|
// Nullifier errors
|
|
3049
3410
|
"NullifierAlreadyUsed": "This note has already been withdrawn. Each note can only be spent once.",
|
|
@@ -3072,6 +3433,438 @@ var PROGRAM_ERRORS = {
|
|
|
3072
3433
|
"AccountNotFound": "Required account not found.",
|
|
3073
3434
|
"InvalidInstruction": "Invalid instruction data."
|
|
3074
3435
|
};
|
|
3436
|
+
var ErrorPatterns = [
|
|
3437
|
+
// Wallet/User action errors
|
|
3438
|
+
{
|
|
3439
|
+
patterns: [
|
|
3440
|
+
"User rejected",
|
|
3441
|
+
"user rejected",
|
|
3442
|
+
"User denied",
|
|
3443
|
+
"user denied",
|
|
3444
|
+
"Transaction cancelled",
|
|
3445
|
+
"Transaction rejected",
|
|
3446
|
+
/code.*4001/i
|
|
3447
|
+
],
|
|
3448
|
+
result: {
|
|
3449
|
+
title: "Transaction Cancelled",
|
|
3450
|
+
message: "You cancelled the transaction.",
|
|
3451
|
+
category: "wallet",
|
|
3452
|
+
recoverable: true
|
|
3453
|
+
}
|
|
3454
|
+
},
|
|
3455
|
+
{
|
|
3456
|
+
patterns: [
|
|
3457
|
+
"Wallet not connected",
|
|
3458
|
+
"wallet not connected",
|
|
3459
|
+
"Please connect wallet",
|
|
3460
|
+
"No wallet connected"
|
|
3461
|
+
],
|
|
3462
|
+
result: {
|
|
3463
|
+
title: "Wallet Not Connected",
|
|
3464
|
+
message: "Please connect your wallet to continue.",
|
|
3465
|
+
category: "wallet",
|
|
3466
|
+
suggestion: "Click the wallet button to connect.",
|
|
3467
|
+
recoverable: true
|
|
3468
|
+
}
|
|
3469
|
+
},
|
|
3470
|
+
{
|
|
3471
|
+
patterns: [
|
|
3472
|
+
"SDK not initialized",
|
|
3473
|
+
"sdk not initialized"
|
|
3474
|
+
],
|
|
3475
|
+
result: {
|
|
3476
|
+
title: "Wallet Connection Required",
|
|
3477
|
+
message: "Your wallet connection was interrupted.",
|
|
3478
|
+
category: "wallet",
|
|
3479
|
+
suggestion: "Please reconnect your wallet and try again.",
|
|
3480
|
+
recoverable: true
|
|
3481
|
+
}
|
|
3482
|
+
},
|
|
3483
|
+
{
|
|
3484
|
+
patterns: [
|
|
3485
|
+
"Wallet does not support signing",
|
|
3486
|
+
"signTransaction"
|
|
3487
|
+
],
|
|
3488
|
+
result: {
|
|
3489
|
+
title: "Wallet Feature Not Supported",
|
|
3490
|
+
message: "Your wallet doesn't support the required signing method.",
|
|
3491
|
+
category: "wallet",
|
|
3492
|
+
suggestion: "Try using a different wallet like Phantom or Solflare.",
|
|
3493
|
+
recoverable: true
|
|
3494
|
+
}
|
|
3495
|
+
},
|
|
3496
|
+
// Balance errors
|
|
3497
|
+
{
|
|
3498
|
+
patterns: [
|
|
3499
|
+
"insufficient lamports",
|
|
3500
|
+
"Insufficient lamports",
|
|
3501
|
+
"insufficient balance",
|
|
3502
|
+
"Insufficient balance",
|
|
3503
|
+
"Insufficient SOL",
|
|
3504
|
+
"not enough SOL",
|
|
3505
|
+
"Attempt to debit an account but found no record",
|
|
3506
|
+
/0x1$/
|
|
3507
|
+
],
|
|
3508
|
+
result: {
|
|
3509
|
+
title: "Insufficient Balance",
|
|
3510
|
+
message: "You don't have enough SOL for this transaction.",
|
|
3511
|
+
category: "validation",
|
|
3512
|
+
suggestion: "Add more SOL to your wallet or reduce the amount.",
|
|
3513
|
+
recoverable: true
|
|
3514
|
+
}
|
|
3515
|
+
},
|
|
3516
|
+
{
|
|
3517
|
+
patterns: [
|
|
3518
|
+
"Insufficient funds",
|
|
3519
|
+
"insufficient funds"
|
|
3520
|
+
],
|
|
3521
|
+
result: {
|
|
3522
|
+
title: "Insufficient Funds",
|
|
3523
|
+
message: "Your wallet doesn't have enough funds for this transaction.",
|
|
3524
|
+
category: "validation",
|
|
3525
|
+
suggestion: "Add more funds to your wallet and try again.",
|
|
3526
|
+
recoverable: true
|
|
3527
|
+
}
|
|
3528
|
+
},
|
|
3529
|
+
// Network errors
|
|
3530
|
+
{
|
|
3531
|
+
patterns: [
|
|
3532
|
+
"fetch failed",
|
|
3533
|
+
"Failed to fetch",
|
|
3534
|
+
"Network error",
|
|
3535
|
+
"network error",
|
|
3536
|
+
"ECONNREFUSED",
|
|
3537
|
+
"ETIMEDOUT",
|
|
3538
|
+
"ENOTFOUND",
|
|
3539
|
+
"NetworkError",
|
|
3540
|
+
"net::ERR",
|
|
3541
|
+
"Failed to load"
|
|
3542
|
+
],
|
|
3543
|
+
result: {
|
|
3544
|
+
title: "Connection Error",
|
|
3545
|
+
message: "Unable to connect to the network.",
|
|
3546
|
+
category: "network",
|
|
3547
|
+
suggestion: "Check your internet connection and try again.",
|
|
3548
|
+
recoverable: true
|
|
3549
|
+
}
|
|
3550
|
+
},
|
|
3551
|
+
{
|
|
3552
|
+
patterns: [
|
|
3553
|
+
"timeout",
|
|
3554
|
+
"Timeout",
|
|
3555
|
+
"TIMEOUT",
|
|
3556
|
+
"timed out",
|
|
3557
|
+
"Timed out"
|
|
3558
|
+
],
|
|
3559
|
+
result: {
|
|
3560
|
+
title: "Request Timed Out",
|
|
3561
|
+
message: "The request took too long to complete.",
|
|
3562
|
+
category: "network",
|
|
3563
|
+
suggestion: "The network may be congested. Please try again in a moment.",
|
|
3564
|
+
recoverable: true
|
|
3565
|
+
}
|
|
3566
|
+
},
|
|
3567
|
+
{
|
|
3568
|
+
patterns: [
|
|
3569
|
+
"blockhash not found",
|
|
3570
|
+
"Blockhash not found",
|
|
3571
|
+
"block height exceeded"
|
|
3572
|
+
],
|
|
3573
|
+
result: {
|
|
3574
|
+
title: "Transaction Expired",
|
|
3575
|
+
message: "The transaction took too long and expired.",
|
|
3576
|
+
category: "network",
|
|
3577
|
+
suggestion: "Please try again. If this persists, the network may be congested.",
|
|
3578
|
+
recoverable: true
|
|
3579
|
+
}
|
|
3580
|
+
},
|
|
3581
|
+
// Service errors (Indexer/Relay)
|
|
3582
|
+
{
|
|
3583
|
+
patterns: [
|
|
3584
|
+
"Indexer",
|
|
3585
|
+
"indexer",
|
|
3586
|
+
/indexer.*unavailable/i,
|
|
3587
|
+
/failed.*indexer/i
|
|
3588
|
+
],
|
|
3589
|
+
result: {
|
|
3590
|
+
title: "Service Temporarily Unavailable",
|
|
3591
|
+
message: "The privacy service is temporarily unavailable.",
|
|
3592
|
+
category: "service",
|
|
3593
|
+
suggestion: "Please wait a moment and try again.",
|
|
3594
|
+
recoverable: true
|
|
3595
|
+
}
|
|
3596
|
+
},
|
|
3597
|
+
{
|
|
3598
|
+
patterns: [
|
|
3599
|
+
"Relay",
|
|
3600
|
+
"relay",
|
|
3601
|
+
/relay.*unavailable/i,
|
|
3602
|
+
/failed.*relay/i,
|
|
3603
|
+
"failed to submit",
|
|
3604
|
+
"Failed to submit"
|
|
3605
|
+
],
|
|
3606
|
+
result: {
|
|
3607
|
+
title: "Processing Service Busy",
|
|
3608
|
+
message: "The transaction processing service is busy.",
|
|
3609
|
+
category: "service",
|
|
3610
|
+
suggestion: "Please wait a moment and try again.",
|
|
3611
|
+
recoverable: true
|
|
3612
|
+
}
|
|
3613
|
+
},
|
|
3614
|
+
{
|
|
3615
|
+
patterns: [
|
|
3616
|
+
"429",
|
|
3617
|
+
"Too Many Requests",
|
|
3618
|
+
"rate limit",
|
|
3619
|
+
"Rate limit"
|
|
3620
|
+
],
|
|
3621
|
+
result: {
|
|
3622
|
+
title: "Too Many Requests",
|
|
3623
|
+
message: "You're making requests too quickly.",
|
|
3624
|
+
category: "service",
|
|
3625
|
+
suggestion: "Please wait a moment before trying again.",
|
|
3626
|
+
recoverable: true
|
|
3627
|
+
}
|
|
3628
|
+
},
|
|
3629
|
+
{
|
|
3630
|
+
patterns: [
|
|
3631
|
+
"503",
|
|
3632
|
+
"Service Unavailable",
|
|
3633
|
+
"502",
|
|
3634
|
+
"Bad Gateway"
|
|
3635
|
+
],
|
|
3636
|
+
result: {
|
|
3637
|
+
title: "Service Temporarily Unavailable",
|
|
3638
|
+
message: "Our servers are temporarily unavailable.",
|
|
3639
|
+
category: "service",
|
|
3640
|
+
suggestion: "Please try again in a few minutes.",
|
|
3641
|
+
recoverable: true
|
|
3642
|
+
}
|
|
3643
|
+
},
|
|
3644
|
+
// Proof/ZK errors
|
|
3645
|
+
{
|
|
3646
|
+
patterns: [
|
|
3647
|
+
"Circuits not available",
|
|
3648
|
+
"circuits not available",
|
|
3649
|
+
"Failed to load circuit",
|
|
3650
|
+
"WASM",
|
|
3651
|
+
"wasm",
|
|
3652
|
+
/circuit.*not.*found/i
|
|
3653
|
+
],
|
|
3654
|
+
result: {
|
|
3655
|
+
title: "Loading Error",
|
|
3656
|
+
message: "Failed to load required cryptographic components.",
|
|
3657
|
+
category: "service",
|
|
3658
|
+
suggestion: "Try refreshing the page. If the problem persists, clear your browser cache.",
|
|
3659
|
+
recoverable: true
|
|
3660
|
+
}
|
|
3661
|
+
},
|
|
3662
|
+
{
|
|
3663
|
+
patterns: [
|
|
3664
|
+
"proof generation",
|
|
3665
|
+
"Proof generation",
|
|
3666
|
+
"Failed to generate proof",
|
|
3667
|
+
"proving error"
|
|
3668
|
+
],
|
|
3669
|
+
result: {
|
|
3670
|
+
title: "Proof Generation Failed",
|
|
3671
|
+
message: "Failed to generate the privacy proof.",
|
|
3672
|
+
category: "service",
|
|
3673
|
+
suggestion: "Try again with a smaller amount or refresh the page.",
|
|
3674
|
+
recoverable: true
|
|
3675
|
+
}
|
|
3676
|
+
},
|
|
3677
|
+
// Validation errors
|
|
3678
|
+
{
|
|
3679
|
+
patterns: [
|
|
3680
|
+
"Invalid amount",
|
|
3681
|
+
"invalid amount",
|
|
3682
|
+
"Amount must be",
|
|
3683
|
+
"amount must be",
|
|
3684
|
+
"Amount too small"
|
|
3685
|
+
],
|
|
3686
|
+
result: {
|
|
3687
|
+
title: "Invalid Amount",
|
|
3688
|
+
message: "The amount you entered is not valid.",
|
|
3689
|
+
category: "validation",
|
|
3690
|
+
suggestion: "Enter an amount greater than the minimum required.",
|
|
3691
|
+
recoverable: true
|
|
3692
|
+
}
|
|
3693
|
+
},
|
|
3694
|
+
{
|
|
3695
|
+
patterns: [
|
|
3696
|
+
"Invalid recipient",
|
|
3697
|
+
"invalid recipient",
|
|
3698
|
+
"Invalid address",
|
|
3699
|
+
"invalid address",
|
|
3700
|
+
"Invalid Solana address"
|
|
3701
|
+
],
|
|
3702
|
+
result: {
|
|
3703
|
+
title: "Invalid Address",
|
|
3704
|
+
message: "The recipient address is not valid.",
|
|
3705
|
+
category: "validation",
|
|
3706
|
+
suggestion: "Check the address and make sure it's a valid Solana address.",
|
|
3707
|
+
recoverable: true
|
|
3708
|
+
}
|
|
3709
|
+
},
|
|
3710
|
+
{
|
|
3711
|
+
patterns: [
|
|
3712
|
+
"Invalid token",
|
|
3713
|
+
"invalid token",
|
|
3714
|
+
"Unsupported token"
|
|
3715
|
+
],
|
|
3716
|
+
result: {
|
|
3717
|
+
title: "Unsupported Token",
|
|
3718
|
+
message: "This token is not supported.",
|
|
3719
|
+
category: "validation",
|
|
3720
|
+
suggestion: "Select a supported token and try again.",
|
|
3721
|
+
recoverable: true
|
|
3722
|
+
}
|
|
3723
|
+
},
|
|
3724
|
+
// Swap errors
|
|
3725
|
+
{
|
|
3726
|
+
patterns: [
|
|
3727
|
+
"Failed to get quote",
|
|
3728
|
+
"failed to get quote",
|
|
3729
|
+
"No route found",
|
|
3730
|
+
"no route found",
|
|
3731
|
+
"Insufficient liquidity",
|
|
3732
|
+
"insufficient liquidity"
|
|
3733
|
+
],
|
|
3734
|
+
result: {
|
|
3735
|
+
title: "Swap Quote Unavailable",
|
|
3736
|
+
message: "Unable to get a price quote for this swap.",
|
|
3737
|
+
category: "service",
|
|
3738
|
+
suggestion: "Try a different amount or wait for better liquidity.",
|
|
3739
|
+
recoverable: true
|
|
3740
|
+
}
|
|
3741
|
+
},
|
|
3742
|
+
{
|
|
3743
|
+
patterns: [
|
|
3744
|
+
"Slippage",
|
|
3745
|
+
"slippage",
|
|
3746
|
+
"Price impact",
|
|
3747
|
+
"price impact"
|
|
3748
|
+
],
|
|
3749
|
+
result: {
|
|
3750
|
+
title: "Price Changed",
|
|
3751
|
+
message: "The price changed too much during the transaction.",
|
|
3752
|
+
category: "transaction",
|
|
3753
|
+
suggestion: "Try again or increase your slippage tolerance.",
|
|
3754
|
+
recoverable: true
|
|
3755
|
+
}
|
|
3756
|
+
},
|
|
3757
|
+
// Transaction errors
|
|
3758
|
+
{
|
|
3759
|
+
patterns: [
|
|
3760
|
+
"Double spend",
|
|
3761
|
+
"double spend",
|
|
3762
|
+
"already been spent",
|
|
3763
|
+
"already spent"
|
|
3764
|
+
],
|
|
3765
|
+
result: {
|
|
3766
|
+
title: "Already Spent",
|
|
3767
|
+
message: "This note has already been used.",
|
|
3768
|
+
category: "transaction",
|
|
3769
|
+
suggestion: "This funds have already been withdrawn.",
|
|
3770
|
+
recoverable: false
|
|
3771
|
+
}
|
|
3772
|
+
},
|
|
3773
|
+
{
|
|
3774
|
+
patterns: [
|
|
3775
|
+
"simulation failed",
|
|
3776
|
+
"Simulation failed",
|
|
3777
|
+
"Transaction simulation"
|
|
3778
|
+
],
|
|
3779
|
+
result: {
|
|
3780
|
+
title: "Transaction Failed",
|
|
3781
|
+
message: "The transaction could not be completed.",
|
|
3782
|
+
category: "transaction",
|
|
3783
|
+
suggestion: "Please try again. If the problem persists, check your balance.",
|
|
3784
|
+
recoverable: true
|
|
3785
|
+
}
|
|
3786
|
+
},
|
|
3787
|
+
{
|
|
3788
|
+
patterns: [
|
|
3789
|
+
"confirmation timeout",
|
|
3790
|
+
"Confirmation timeout",
|
|
3791
|
+
"not confirmed"
|
|
3792
|
+
],
|
|
3793
|
+
result: {
|
|
3794
|
+
title: "Confirmation Pending",
|
|
3795
|
+
message: "Transaction confirmation is taking longer than expected.",
|
|
3796
|
+
category: "network",
|
|
3797
|
+
suggestion: "Your transaction may still complete. Check your wallet or try again.",
|
|
3798
|
+
recoverable: true
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
];
|
|
3802
|
+
function parseError(error) {
|
|
3803
|
+
let errorMessage = "";
|
|
3804
|
+
let originalError = "";
|
|
3805
|
+
if (error instanceof Error) {
|
|
3806
|
+
errorMessage = error.message;
|
|
3807
|
+
originalError = error.stack || error.message;
|
|
3808
|
+
} else if (typeof error === "string") {
|
|
3809
|
+
errorMessage = error;
|
|
3810
|
+
originalError = error;
|
|
3811
|
+
} else if (error && typeof error === "object") {
|
|
3812
|
+
const err = error;
|
|
3813
|
+
errorMessage = String(err.message || err.error || err.msg || JSON.stringify(error));
|
|
3814
|
+
originalError = JSON.stringify(error);
|
|
3815
|
+
} else {
|
|
3816
|
+
errorMessage = String(error);
|
|
3817
|
+
originalError = String(error);
|
|
3818
|
+
}
|
|
3819
|
+
for (const { patterns, result } of ErrorPatterns) {
|
|
3820
|
+
for (const pattern of patterns) {
|
|
3821
|
+
if (typeof pattern === "string") {
|
|
3822
|
+
if (errorMessage.includes(pattern)) {
|
|
3823
|
+
return { ...result, originalError };
|
|
3824
|
+
}
|
|
3825
|
+
} else if (pattern instanceof RegExp) {
|
|
3826
|
+
if (pattern.test(errorMessage)) {
|
|
3827
|
+
return { ...result, originalError };
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
const programError = tryParseProgramError(errorMessage);
|
|
3833
|
+
if (programError) {
|
|
3834
|
+
return { ...programError, originalError };
|
|
3835
|
+
}
|
|
3836
|
+
return {
|
|
3837
|
+
title: "Something Went Wrong",
|
|
3838
|
+
message: "An unexpected error occurred.",
|
|
3839
|
+
category: "unknown",
|
|
3840
|
+
suggestion: "Please try again. If the problem persists, refresh the page.",
|
|
3841
|
+
recoverable: true,
|
|
3842
|
+
originalError
|
|
3843
|
+
};
|
|
3844
|
+
}
|
|
3845
|
+
function tryParseProgramError(message) {
|
|
3846
|
+
const match = message.match(/\{"InstructionError":\[(\d+),\{"Custom":(\d+)\}\]\}/);
|
|
3847
|
+
if (match) {
|
|
3848
|
+
const errorCode = parseInt(match[2]);
|
|
3849
|
+
const friendlyMessage = ShieldPoolErrors[errorCode];
|
|
3850
|
+
if (friendlyMessage) {
|
|
3851
|
+
return {
|
|
3852
|
+
title: "Transaction Failed",
|
|
3853
|
+
message: friendlyMessage,
|
|
3854
|
+
category: "transaction",
|
|
3855
|
+
recoverable: !friendlyMessage.toLowerCase().includes("double spend")
|
|
3856
|
+
};
|
|
3857
|
+
}
|
|
3858
|
+
return {
|
|
3859
|
+
title: "Transaction Failed",
|
|
3860
|
+
message: `Transaction failed with error code ${errorCode}.`,
|
|
3861
|
+
category: "transaction",
|
|
3862
|
+
suggestion: "Please try again or contact support if this persists.",
|
|
3863
|
+
recoverable: true
|
|
3864
|
+
};
|
|
3865
|
+
}
|
|
3866
|
+
return null;
|
|
3867
|
+
}
|
|
3075
3868
|
function parseTransactionError(error) {
|
|
3076
3869
|
if (!error) return "An unknown error occurred";
|
|
3077
3870
|
const errorStr = typeof error === "string" ? error : error.message || error.toString();
|
|
@@ -3251,6 +4044,173 @@ function keypairToAdapter(keypair) {
|
|
|
3251
4044
|
};
|
|
3252
4045
|
}
|
|
3253
4046
|
|
|
4047
|
+
// src/utils/pending-operations.ts
|
|
4048
|
+
var PENDING_DEPOSITS_KEY = "cloak_pending_deposits";
|
|
4049
|
+
var PENDING_WITHDRAWALS_KEY = "cloak_pending_withdrawals";
|
|
4050
|
+
function getStorage() {
|
|
4051
|
+
if (typeof globalThis !== "undefined" && globalThis.localStorage) {
|
|
4052
|
+
return globalThis.localStorage;
|
|
4053
|
+
}
|
|
4054
|
+
return null;
|
|
4055
|
+
}
|
|
4056
|
+
function savePendingDeposit(deposit) {
|
|
4057
|
+
const storage = getStorage();
|
|
4058
|
+
if (!storage) {
|
|
4059
|
+
console.warn("localStorage not available - pending deposit not persisted");
|
|
4060
|
+
return;
|
|
4061
|
+
}
|
|
4062
|
+
const deposits = loadPendingDeposits();
|
|
4063
|
+
const index = deposits.findIndex((d) => d.note.commitment === deposit.note.commitment);
|
|
4064
|
+
if (index >= 0) {
|
|
4065
|
+
deposits[index] = deposit;
|
|
4066
|
+
} else {
|
|
4067
|
+
deposits.push(deposit);
|
|
4068
|
+
}
|
|
4069
|
+
storage.setItem(PENDING_DEPOSITS_KEY, JSON.stringify(deposits));
|
|
4070
|
+
}
|
|
4071
|
+
function loadPendingDeposits() {
|
|
4072
|
+
const storage = getStorage();
|
|
4073
|
+
if (!storage) return [];
|
|
4074
|
+
const stored = storage.getItem(PENDING_DEPOSITS_KEY);
|
|
4075
|
+
if (!stored) return [];
|
|
4076
|
+
try {
|
|
4077
|
+
return JSON.parse(stored);
|
|
4078
|
+
} catch {
|
|
4079
|
+
return [];
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
function updatePendingDeposit(commitment, updates) {
|
|
4083
|
+
const storage = getStorage();
|
|
4084
|
+
if (!storage) return;
|
|
4085
|
+
const deposits = loadPendingDeposits();
|
|
4086
|
+
const index = deposits.findIndex((d) => d.note.commitment === commitment);
|
|
4087
|
+
if (index >= 0) {
|
|
4088
|
+
deposits[index] = { ...deposits[index], ...updates };
|
|
4089
|
+
storage.setItem(PENDING_DEPOSITS_KEY, JSON.stringify(deposits));
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
function removePendingDeposit(commitment) {
|
|
4093
|
+
const storage = getStorage();
|
|
4094
|
+
if (!storage) return;
|
|
4095
|
+
const deposits = loadPendingDeposits();
|
|
4096
|
+
const filtered = deposits.filter((d) => d.note.commitment !== commitment);
|
|
4097
|
+
storage.setItem(PENDING_DEPOSITS_KEY, JSON.stringify(filtered));
|
|
4098
|
+
}
|
|
4099
|
+
function clearPendingDeposits() {
|
|
4100
|
+
const storage = getStorage();
|
|
4101
|
+
if (storage) {
|
|
4102
|
+
storage.removeItem(PENDING_DEPOSITS_KEY);
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
4105
|
+
function savePendingWithdrawal(withdrawal) {
|
|
4106
|
+
const storage = getStorage();
|
|
4107
|
+
if (!storage) {
|
|
4108
|
+
console.warn("localStorage not available - pending withdrawal not persisted");
|
|
4109
|
+
return;
|
|
4110
|
+
}
|
|
4111
|
+
const withdrawals = loadPendingWithdrawals();
|
|
4112
|
+
const index = withdrawals.findIndex((w) => w.requestId === withdrawal.requestId);
|
|
4113
|
+
if (index >= 0) {
|
|
4114
|
+
withdrawals[index] = withdrawal;
|
|
4115
|
+
} else {
|
|
4116
|
+
withdrawals.push(withdrawal);
|
|
4117
|
+
}
|
|
4118
|
+
storage.setItem(PENDING_WITHDRAWALS_KEY, JSON.stringify(withdrawals));
|
|
4119
|
+
}
|
|
4120
|
+
function loadPendingWithdrawals() {
|
|
4121
|
+
const storage = getStorage();
|
|
4122
|
+
if (!storage) return [];
|
|
4123
|
+
const stored = storage.getItem(PENDING_WITHDRAWALS_KEY);
|
|
4124
|
+
if (!stored) return [];
|
|
4125
|
+
try {
|
|
4126
|
+
return JSON.parse(stored);
|
|
4127
|
+
} catch {
|
|
4128
|
+
return [];
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
function updatePendingWithdrawal(requestId, updates) {
|
|
4132
|
+
const storage = getStorage();
|
|
4133
|
+
if (!storage) return;
|
|
4134
|
+
const withdrawals = loadPendingWithdrawals();
|
|
4135
|
+
const index = withdrawals.findIndex((w) => w.requestId === requestId);
|
|
4136
|
+
if (index >= 0) {
|
|
4137
|
+
withdrawals[index] = { ...withdrawals[index], ...updates };
|
|
4138
|
+
storage.setItem(PENDING_WITHDRAWALS_KEY, JSON.stringify(withdrawals));
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
function removePendingWithdrawal(requestId) {
|
|
4142
|
+
const storage = getStorage();
|
|
4143
|
+
if (!storage) return;
|
|
4144
|
+
const withdrawals = loadPendingWithdrawals();
|
|
4145
|
+
const filtered = withdrawals.filter((w) => w.requestId !== requestId);
|
|
4146
|
+
storage.setItem(PENDING_WITHDRAWALS_KEY, JSON.stringify(filtered));
|
|
4147
|
+
}
|
|
4148
|
+
function clearPendingWithdrawals() {
|
|
4149
|
+
const storage = getStorage();
|
|
4150
|
+
if (storage) {
|
|
4151
|
+
storage.removeItem(PENDING_WITHDRAWALS_KEY);
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
function hasPendingOperations() {
|
|
4155
|
+
const deposits = loadPendingDeposits();
|
|
4156
|
+
const withdrawals = loadPendingWithdrawals();
|
|
4157
|
+
const pendingDeposits = deposits.filter(
|
|
4158
|
+
(d) => d.status === "pending" || d.status === "tx_sent"
|
|
4159
|
+
);
|
|
4160
|
+
const pendingWithdrawals = withdrawals.filter(
|
|
4161
|
+
(w) => w.status === "pending" || w.status === "processing"
|
|
4162
|
+
);
|
|
4163
|
+
return pendingDeposits.length > 0 || pendingWithdrawals.length > 0;
|
|
4164
|
+
}
|
|
4165
|
+
function getPendingOperationsSummary() {
|
|
4166
|
+
const deposits = loadPendingDeposits().filter(
|
|
4167
|
+
(d) => d.status === "pending" || d.status === "tx_sent"
|
|
4168
|
+
);
|
|
4169
|
+
const withdrawals = loadPendingWithdrawals().filter(
|
|
4170
|
+
(w) => w.status === "pending" || w.status === "processing"
|
|
4171
|
+
);
|
|
4172
|
+
return {
|
|
4173
|
+
deposits,
|
|
4174
|
+
withdrawals,
|
|
4175
|
+
totalPending: deposits.length + withdrawals.length
|
|
4176
|
+
};
|
|
4177
|
+
}
|
|
4178
|
+
function cleanupStalePendingOperations(maxAgeMs = 24 * 60 * 60 * 1e3) {
|
|
4179
|
+
const now = Date.now();
|
|
4180
|
+
let removedDeposits = 0;
|
|
4181
|
+
let removedWithdrawals = 0;
|
|
4182
|
+
const deposits = loadPendingDeposits();
|
|
4183
|
+
const activeDeposits = deposits.filter((d) => {
|
|
4184
|
+
const age = now - d.startedAt;
|
|
4185
|
+
const isStale = age > maxAgeMs;
|
|
4186
|
+
const isTerminal = d.status === "confirmed" || d.status === "failed";
|
|
4187
|
+
if (isStale || isTerminal) {
|
|
4188
|
+
removedDeposits++;
|
|
4189
|
+
return false;
|
|
4190
|
+
}
|
|
4191
|
+
return true;
|
|
4192
|
+
});
|
|
4193
|
+
const storage = getStorage();
|
|
4194
|
+
if (storage) {
|
|
4195
|
+
storage.setItem(PENDING_DEPOSITS_KEY, JSON.stringify(activeDeposits));
|
|
4196
|
+
}
|
|
4197
|
+
const withdrawals = loadPendingWithdrawals();
|
|
4198
|
+
const activeWithdrawals = withdrawals.filter((w) => {
|
|
4199
|
+
const age = now - w.startedAt;
|
|
4200
|
+
const isStale = age > maxAgeMs;
|
|
4201
|
+
const isTerminal = w.status === "completed" || w.status === "failed";
|
|
4202
|
+
if (isStale || isTerminal) {
|
|
4203
|
+
removedWithdrawals++;
|
|
4204
|
+
return false;
|
|
4205
|
+
}
|
|
4206
|
+
return true;
|
|
4207
|
+
});
|
|
4208
|
+
if (storage) {
|
|
4209
|
+
storage.setItem(PENDING_WITHDRAWALS_KEY, JSON.stringify(activeWithdrawals));
|
|
4210
|
+
}
|
|
4211
|
+
return { removedDeposits, removedWithdrawals };
|
|
4212
|
+
}
|
|
4213
|
+
|
|
3254
4214
|
// src/index.ts
|
|
3255
4215
|
var VERSION = "1.0.0";
|
|
3256
4216
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -3259,12 +4219,14 @@ var VERSION = "1.0.0";
|
|
|
3259
4219
|
CloakError,
|
|
3260
4220
|
CloakSDK,
|
|
3261
4221
|
DepositRecoveryService,
|
|
4222
|
+
EXPECTED_CIRCUIT_HASHES,
|
|
3262
4223
|
FIXED_FEE_LAMPORTS,
|
|
3263
4224
|
IndexerService,
|
|
3264
4225
|
LAMPORTS_PER_SOL,
|
|
3265
4226
|
LocalStorageAdapter,
|
|
3266
4227
|
MemoryStorageAdapter,
|
|
3267
4228
|
RelayService,
|
|
4229
|
+
ShieldPoolErrors,
|
|
3268
4230
|
VARIABLE_FEE_RATE,
|
|
3269
4231
|
VERSION,
|
|
3270
4232
|
bigintToBytes32,
|
|
@@ -3272,6 +4234,9 @@ var VERSION = "1.0.0";
|
|
|
3272
4234
|
bytesToHex,
|
|
3273
4235
|
calculateFee,
|
|
3274
4236
|
calculateRelayFee,
|
|
4237
|
+
cleanupStalePendingOperations,
|
|
4238
|
+
clearPendingDeposits,
|
|
4239
|
+
clearPendingWithdrawals,
|
|
3275
4240
|
computeCommitment,
|
|
3276
4241
|
computeMerkleRoot,
|
|
3277
4242
|
computeNullifier,
|
|
@@ -3311,12 +4276,14 @@ var VERSION = "1.0.0";
|
|
|
3311
4276
|
getAddressExplorerUrl,
|
|
3312
4277
|
getDistributableAmount,
|
|
3313
4278
|
getExplorerUrl,
|
|
4279
|
+
getPendingOperationsSummary,
|
|
3314
4280
|
getPublicKey,
|
|
3315
4281
|
getPublicViewKey,
|
|
3316
4282
|
getRecipientAmount,
|
|
3317
4283
|
getRpcUrlForNetwork,
|
|
3318
4284
|
getShieldPoolPDAs,
|
|
3319
4285
|
getViewKey,
|
|
4286
|
+
hasPendingOperations,
|
|
3320
4287
|
hexToBigint,
|
|
3321
4288
|
hexToBytes,
|
|
3322
4289
|
importKeys,
|
|
@@ -3326,7 +4293,10 @@ var VERSION = "1.0.0";
|
|
|
3326
4293
|
isValidSolanaAddress,
|
|
3327
4294
|
isWithdrawable,
|
|
3328
4295
|
keypairToAdapter,
|
|
4296
|
+
loadPendingDeposits,
|
|
4297
|
+
loadPendingWithdrawals,
|
|
3329
4298
|
parseAmount,
|
|
4299
|
+
parseError,
|
|
3330
4300
|
parseNote,
|
|
3331
4301
|
parseTransactionError,
|
|
3332
4302
|
poseidonHash,
|
|
@@ -3335,6 +4305,10 @@ var VERSION = "1.0.0";
|
|
|
3335
4305
|
proofToBytes,
|
|
3336
4306
|
pubkeyToLimbs,
|
|
3337
4307
|
randomBytes,
|
|
4308
|
+
removePendingDeposit,
|
|
4309
|
+
removePendingWithdrawal,
|
|
4310
|
+
savePendingDeposit,
|
|
4311
|
+
savePendingWithdrawal,
|
|
3338
4312
|
scanNotesForWallet,
|
|
3339
4313
|
sendTransaction,
|
|
3340
4314
|
serializeNote,
|
|
@@ -3342,10 +4316,14 @@ var VERSION = "1.0.0";
|
|
|
3342
4316
|
splitTo2Limbs,
|
|
3343
4317
|
tryDecryptNote,
|
|
3344
4318
|
updateNoteWithDeposit,
|
|
4319
|
+
updatePendingDeposit,
|
|
4320
|
+
updatePendingWithdrawal,
|
|
3345
4321
|
validateDepositParams,
|
|
3346
4322
|
validateNote,
|
|
3347
4323
|
validateOutputsSum,
|
|
3348
4324
|
validateTransfers,
|
|
3349
4325
|
validateWalletConnected,
|
|
3350
|
-
validateWithdrawableNote
|
|
4326
|
+
validateWithdrawableNote,
|
|
4327
|
+
verifyAllCircuits,
|
|
4328
|
+
verifyCircuitIntegrity
|
|
3351
4329
|
});
|