@cloak.dev/sdk 0.1.0 → 0.1.2
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 +94 -5
- package/dist/index.cjs +151 -79
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +151 -79
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -28,12 +28,101 @@ npm install @solana/spl-token
|
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### SDK Defaults (Recommended)
|
|
32
|
+
|
|
33
|
+
- Standard integrations should use SDK defaults for program, relay, and circuits.
|
|
34
|
+
- Do not expose protocol-level config (`programId`, relay URL, circuits URL) as end-user input.
|
|
35
|
+
- `transact`, `partialWithdraw`, and `fullWithdraw` already include stale-root retry handling.
|
|
36
|
+
- For simple CLI sends, require only `SOLANA_RPC_URL` and `KEYPAIR_PATH`.
|
|
37
|
+
|
|
38
|
+
### Minimal Private SOL Send (Single File, Keypair)
|
|
39
|
+
|
|
40
|
+
Use this contract for one-shot scripts and AI-generated snippets.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { readFileSync } from "fs";
|
|
44
|
+
import {
|
|
45
|
+
CLOAK_PROGRAM_ID,
|
|
46
|
+
NATIVE_SOL_MINT,
|
|
47
|
+
createUtxo,
|
|
48
|
+
createZeroUtxo,
|
|
49
|
+
fullWithdraw,
|
|
50
|
+
generateUtxoKeypair,
|
|
51
|
+
transact,
|
|
52
|
+
} from "@cloak.dev/sdk";
|
|
53
|
+
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
|
54
|
+
|
|
55
|
+
async function main() {
|
|
56
|
+
const [recipientArg, lamportsArg] = process.argv.slice(2);
|
|
57
|
+
if (!recipientArg || !lamportsArg) {
|
|
58
|
+
throw new Error("Usage: npx tsx send-sol-private.ts <recipientPubkey> <lamports>");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const rpcUrl = process.env.SOLANA_RPC_URL;
|
|
62
|
+
const keypairPath = process.env.KEYPAIR_PATH;
|
|
63
|
+
if (!rpcUrl || !keypairPath) {
|
|
64
|
+
throw new Error("Set SOLANA_RPC_URL and KEYPAIR_PATH");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const connection = new Connection(rpcUrl, "confirmed");
|
|
68
|
+
const signer = Keypair.fromSecretKey(
|
|
69
|
+
Uint8Array.from(JSON.parse(readFileSync(keypairPath, "utf8"))),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const recipient = new PublicKey(recipientArg);
|
|
73
|
+
const amountLamports = BigInt(lamportsArg);
|
|
74
|
+
|
|
75
|
+
const owner = await generateUtxoKeypair();
|
|
76
|
+
const output = await createUtxo(amountLamports, owner, NATIVE_SOL_MINT);
|
|
77
|
+
|
|
78
|
+
const deposited = await transact(
|
|
79
|
+
{
|
|
80
|
+
inputUtxos: [await createZeroUtxo(NATIVE_SOL_MINT)],
|
|
81
|
+
outputUtxos: [output],
|
|
82
|
+
externalAmount: amountLamports,
|
|
83
|
+
depositor: signer.publicKey,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
connection,
|
|
87
|
+
programId: CLOAK_PROGRAM_ID,
|
|
88
|
+
depositorKeypair: signer,
|
|
89
|
+
walletPublicKey: signer.publicKey,
|
|
90
|
+
enforceViewingKeyRegistration: false,
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const withdrawn = await fullWithdraw(deposited.outputUtxos, recipient, {
|
|
95
|
+
connection,
|
|
96
|
+
programId: CLOAK_PROGRAM_ID,
|
|
97
|
+
depositorKeypair: signer,
|
|
98
|
+
walletPublicKey: signer.publicKey,
|
|
99
|
+
cachedMerkleTree: deposited.merkleTree,
|
|
100
|
+
enforceViewingKeyRegistration: false,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
console.log(withdrawn.signature);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
main().catch((e) => {
|
|
107
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
108
|
+
process.exit(1);
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Run:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
SOLANA_RPC_URL="https://api.mainnet-beta.solana.com" \
|
|
116
|
+
KEYPAIR_PATH="/absolute/path/to/id.json" \
|
|
117
|
+
npx tsx send-sol-private.ts <recipientPubkey> <lamports>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Hard rules for minimal scripts:
|
|
32
121
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
122
|
+
- Use lamports from CLI (`<lamports>`) and keep transaction math in `bigint`.
|
|
123
|
+
- Use `KEYPAIR_PATH`; do not ask for raw private key env vars.
|
|
124
|
+
- Do not parse SOL decimals with float math (`parseFloat`, `AMOUNT_SOL`).
|
|
125
|
+
- Keep `programId` fixed to `CLOAK_PROGRAM_ID` (no end-user override).
|
|
37
126
|
|
|
38
127
|
### Maintained Examples
|
|
39
128
|
|
package/dist/index.cjs
CHANGED
|
@@ -1863,6 +1863,22 @@ var ErrorPatterns = [
|
|
|
1863
1863
|
recoverable: true
|
|
1864
1864
|
}
|
|
1865
1865
|
},
|
|
1866
|
+
{
|
|
1867
|
+
patterns: [
|
|
1868
|
+
"Swap refunded",
|
|
1869
|
+
"swap refunded",
|
|
1870
|
+
"funds refunded as SOL",
|
|
1871
|
+
"funds were refunded",
|
|
1872
|
+
"Swap timed out and funds were refunded"
|
|
1873
|
+
],
|
|
1874
|
+
result: {
|
|
1875
|
+
title: "Swap Refunded",
|
|
1876
|
+
message: "No swap route was available. Your funds have been refunded as SOL to your wallet.",
|
|
1877
|
+
category: "service",
|
|
1878
|
+
suggestion: "Check your wallet balance \u2014 the SOL should already be there (minus the protocol fee). Try again with a different token or amount.",
|
|
1879
|
+
recoverable: true
|
|
1880
|
+
}
|
|
1881
|
+
},
|
|
1866
1882
|
{
|
|
1867
1883
|
patterns: [
|
|
1868
1884
|
"Failed to get quote",
|
|
@@ -2615,8 +2631,8 @@ var IS_REACT_NATIVE = typeof navigator !== "undefined" && navigator.product ===
|
|
|
2615
2631
|
var IS_BROWSER = IS_REACT_NATIVE || typeof window !== "undefined" || typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
|
|
2616
2632
|
var DEFAULT_CIRCUITS_URL = "https://cloak-circuits.s3.us-east-1.amazonaws.com/circuits/0.1.0";
|
|
2617
2633
|
var SKIP_CIRCUIT_VERIFY_ENV = typeof process !== "undefined" && process.env && process.env.CLOAK_SKIP_CIRCUIT_INTEGRITY_CHECK === "1";
|
|
2618
|
-
function isUrl(
|
|
2619
|
-
return
|
|
2634
|
+
function isUrl(path) {
|
|
2635
|
+
return path.startsWith("http://") || path.startsWith("https://");
|
|
2620
2636
|
}
|
|
2621
2637
|
function resolveCircuitsUrl(circuitsPath2) {
|
|
2622
2638
|
if (circuitsPath2.trim() !== "" && circuitsPath2.trim() !== DEFAULT_CIRCUITS_URL) {
|
|
@@ -3083,7 +3099,7 @@ function createSetLoadedAccountsDataSizeLimitInstruction(bytes) {
|
|
|
3083
3099
|
data
|
|
3084
3100
|
});
|
|
3085
3101
|
}
|
|
3086
|
-
var CLOAK_PROGRAM_ID = new import_web35.PublicKey("
|
|
3102
|
+
var CLOAK_PROGRAM_ID = new import_web35.PublicKey("zh1eLd6rSphLejbFfJEneUwzHRfMKxgzrgkfwA6qRkW");
|
|
3087
3103
|
var CLOAK_API_URL = "https://api.cloak.ag";
|
|
3088
3104
|
var CloakSDK = class {
|
|
3089
3105
|
/**
|
|
@@ -5560,56 +5576,39 @@ function chainNoteFromBase64(base64) {
|
|
|
5560
5576
|
// src/core/transact.ts
|
|
5561
5577
|
var import_circomlibjs4 = require("circomlibjs");
|
|
5562
5578
|
var import_tweetnacl4 = __toESM(require("tweetnacl"), 1);
|
|
5563
|
-
var
|
|
5564
|
-
var import_crypto13 = require("crypto");
|
|
5565
|
-
var import_promises = require("fs/promises");
|
|
5566
|
-
var import_os = require("os");
|
|
5579
|
+
var IS_BROWSER2 = typeof window !== "undefined" || typeof globalThis.document !== "undefined";
|
|
5567
5580
|
var DEFAULT_TRANSACTION_CIRCUITS_URL = "https://cloak-circuits.s3.us-east-1.amazonaws.com/circuits/0.1.0";
|
|
5581
|
+
var DEFAULT_CLOAK_RELAY_URL = "https://api.cloak.ag";
|
|
5568
5582
|
function resolveDefaultTransactionCircuitsPath() {
|
|
5569
5583
|
return DEFAULT_TRANSACTION_CIRCUITS_URL;
|
|
5570
5584
|
}
|
|
5571
5585
|
var circuitsPath = resolveDefaultTransactionCircuitsPath();
|
|
5572
|
-
function isHttpCircuitsPath(p) {
|
|
5573
|
-
return p.startsWith("https://") || p.startsWith("http://");
|
|
5574
|
-
}
|
|
5575
5586
|
var _remoteTxCircuitsCache = null;
|
|
5576
5587
|
async function resolveTransactionCircuitFiles() {
|
|
5577
5588
|
const base = circuitsPath;
|
|
5578
|
-
const wasmRel = path.join("transaction_js", "transaction.wasm");
|
|
5579
|
-
const zkeyRel = "transaction_final.zkey";
|
|
5580
|
-
if (!isHttpCircuitsPath(base)) {
|
|
5581
|
-
const root = base;
|
|
5582
|
-
return {
|
|
5583
|
-
wasmPath: path.join(root, wasmRel),
|
|
5584
|
-
zkeyPath: path.join(root, zkeyRel)
|
|
5585
|
-
};
|
|
5586
|
-
}
|
|
5587
5589
|
const baseNorm = base.endsWith("/") ? base : `${base}/`;
|
|
5590
|
+
const wasmUrl = `${baseNorm}transaction_js/transaction.wasm`;
|
|
5591
|
+
const zkeyUrl = `${baseNorm}transaction_final.zkey`;
|
|
5592
|
+
if (IS_BROWSER2) {
|
|
5593
|
+
return { wasmPath: wasmUrl, zkeyPath: zkeyUrl };
|
|
5594
|
+
}
|
|
5588
5595
|
if (_remoteTxCircuitsCache?.base === baseNorm) {
|
|
5589
|
-
|
|
5590
|
-
return {
|
|
5591
|
-
wasmPath: path.join(dir2, "transaction.wasm"),
|
|
5592
|
-
zkeyPath: path.join(dir2, "transaction_final.zkey")
|
|
5593
|
-
};
|
|
5596
|
+
return _remoteTxCircuitsCache.artifacts;
|
|
5594
5597
|
}
|
|
5595
|
-
const
|
|
5596
|
-
const zkeyUrl = new URL(zkeyRel, baseNorm).toString();
|
|
5597
|
-
const subdir = `cloak-tx-circuits-${(0, import_crypto13.createHash)("sha256").update(baseNorm).digest("hex").slice(0, 16)}`;
|
|
5598
|
-
const dir = path.join((0, import_os.tmpdir)(), subdir);
|
|
5599
|
-
await (0, import_promises.mkdir)(dir, { recursive: true });
|
|
5600
|
-
const wasmPath = path.join(dir, "transaction.wasm");
|
|
5601
|
-
const zkeyPath = path.join(dir, "transaction_final.zkey");
|
|
5602
|
-
const download = async (url, dest) => {
|
|
5598
|
+
const fetchAsBuffer = async (url) => {
|
|
5603
5599
|
const res = await fetch(url);
|
|
5604
5600
|
if (!res.ok) {
|
|
5605
5601
|
throw new Error(`Failed to fetch circuit artifact ${url}: ${res.status} ${res.statusText}`);
|
|
5606
5602
|
}
|
|
5607
|
-
|
|
5603
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
5608
5604
|
};
|
|
5609
|
-
await
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5605
|
+
const [wasmData, zkeyData] = await Promise.all([
|
|
5606
|
+
fetchAsBuffer(wasmUrl),
|
|
5607
|
+
fetchAsBuffer(zkeyUrl)
|
|
5608
|
+
]);
|
|
5609
|
+
const artifacts = { wasmPath: wasmData, zkeyPath: zkeyData };
|
|
5610
|
+
_remoteTxCircuitsCache = { base: baseNorm, artifacts };
|
|
5611
|
+
return artifacts;
|
|
5613
5612
|
}
|
|
5614
5613
|
var _transactPaddingSaltCounter = 0;
|
|
5615
5614
|
var _registeredViewingKeys = /* @__PURE__ */ new Set();
|
|
@@ -5703,6 +5702,12 @@ function deriveRelayUrlFromRiskQuoteUrl(riskQuoteUrl) {
|
|
|
5703
5702
|
}
|
|
5704
5703
|
return void 0;
|
|
5705
5704
|
}
|
|
5705
|
+
function resolveRelayUrl(relayUrl) {
|
|
5706
|
+
const trimmed = relayUrl?.trim();
|
|
5707
|
+
if (trimmed === "") return void 0;
|
|
5708
|
+
if (trimmed) return trimmed.replace(/\/$/, "");
|
|
5709
|
+
return DEFAULT_CLOAK_RELAY_URL;
|
|
5710
|
+
}
|
|
5706
5711
|
async function resolveAddressLookupTableAccounts(connection, relayUrl, altAddressesFromOptions, provided, onProgress) {
|
|
5707
5712
|
if (provided && provided.length > 0) {
|
|
5708
5713
|
return provided;
|
|
@@ -5800,9 +5805,8 @@ async function resolveChainNoteNk(options) {
|
|
|
5800
5805
|
}
|
|
5801
5806
|
return null;
|
|
5802
5807
|
}
|
|
5803
|
-
function shouldDefaultUseUniqueNullifiers(
|
|
5804
|
-
|
|
5805
|
-
return endpoint.includes("127.0.0.1") || endpoint.includes("localhost") || endpoint.includes("0.0.0.0");
|
|
5808
|
+
function shouldDefaultUseUniqueNullifiers(_connection) {
|
|
5809
|
+
return true;
|
|
5806
5810
|
}
|
|
5807
5811
|
function toHex(bytes) {
|
|
5808
5812
|
return Buffer.from(bytes).toString("hex");
|
|
@@ -5811,7 +5815,7 @@ async function ensureViewingKeyRegistered(options, onProgress, fallbackNk) {
|
|
|
5811
5815
|
if (options.enforceViewingKeyRegistration === false) {
|
|
5812
5816
|
return;
|
|
5813
5817
|
}
|
|
5814
|
-
const relayUrl = options.relayUrl
|
|
5818
|
+
const relayUrl = resolveRelayUrl(options.relayUrl);
|
|
5815
5819
|
if (!relayUrl) {
|
|
5816
5820
|
throw new Error("Viewing key registration is mandatory: relayUrl is required.");
|
|
5817
5821
|
}
|
|
@@ -5882,12 +5886,12 @@ async function ensureViewingKeyRegistered(options, onProgress, fallbackNk) {
|
|
|
5882
5886
|
}
|
|
5883
5887
|
async function generateTransactionProof(inputs, onProgress) {
|
|
5884
5888
|
onProgress?.(10);
|
|
5885
|
-
const { wasmPath, zkeyPath } = await resolveTransactionCircuitFiles();
|
|
5889
|
+
const { wasmPath: wasmInput, zkeyPath: zkeyInput } = await resolveTransactionCircuitFiles();
|
|
5886
5890
|
onProgress?.(30);
|
|
5887
5891
|
const { proof, publicSignals } = await snarkjs2.groth16.fullProve(
|
|
5888
5892
|
inputs,
|
|
5889
|
-
|
|
5890
|
-
|
|
5893
|
+
wasmInput,
|
|
5894
|
+
zkeyInput
|
|
5891
5895
|
);
|
|
5892
5896
|
onProgress?.(100);
|
|
5893
5897
|
return { proof, publicSignals };
|
|
@@ -6010,21 +6014,26 @@ function buildTransactInstruction(programId, payer, poolPDA, treasuryPDA, merkle
|
|
|
6010
6014
|
{ pubkey: import_web37.SystemProgram.programId, isSigner: false, isWritable: false }
|
|
6011
6015
|
// 6. system_program
|
|
6012
6016
|
];
|
|
6013
|
-
if (recipient) {
|
|
6014
|
-
accounts.push({ pubkey: recipient, isSigner: false, isWritable: true });
|
|
6015
|
-
if (enableRiskCheck) {
|
|
6016
|
-
accounts.push({ pubkey: import_web37.SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
6017
|
-
}
|
|
6018
|
-
} else if (enableRiskCheck) {
|
|
6019
|
-
const instructionsSysvar = import_web37.SYSVAR_INSTRUCTIONS_PUBKEY;
|
|
6020
|
-
accounts.push({ pubkey: instructionsSysvar, isSigner: false, isWritable: false });
|
|
6021
|
-
}
|
|
6022
6017
|
if (splAccounts) {
|
|
6023
6018
|
accounts.push({ pubkey: splAccounts.vaultAuthority, isSigner: false, isWritable: false });
|
|
6024
6019
|
accounts.push({ pubkey: splAccounts.poolVaultAta, isSigner: false, isWritable: true });
|
|
6025
6020
|
accounts.push({ pubkey: splAccounts.tokenProgram, isSigner: false, isWritable: false });
|
|
6026
6021
|
if (splAccounts.payerAta) {
|
|
6022
|
+
if (enableRiskCheck) {
|
|
6023
|
+
accounts.push({ pubkey: import_web37.SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
6024
|
+
}
|
|
6027
6025
|
accounts.push({ pubkey: splAccounts.payerAta, isSigner: false, isWritable: true });
|
|
6026
|
+
} else if (enableRiskCheck && !recipient) {
|
|
6027
|
+
accounts.push({ pubkey: import_web37.SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
6028
|
+
}
|
|
6029
|
+
} else {
|
|
6030
|
+
if (recipient) {
|
|
6031
|
+
accounts.push({ pubkey: recipient, isSigner: false, isWritable: true });
|
|
6032
|
+
if (enableRiskCheck) {
|
|
6033
|
+
accounts.push({ pubkey: import_web37.SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
6034
|
+
}
|
|
6035
|
+
} else if (enableRiskCheck) {
|
|
6036
|
+
accounts.push({ pubkey: import_web37.SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
6028
6037
|
}
|
|
6029
6038
|
}
|
|
6030
6039
|
return new import_web37.TransactionInstruction({
|
|
@@ -6140,13 +6149,7 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6140
6149
|
let riskQuoteIx = null;
|
|
6141
6150
|
const isDeposit = recipient === void 0;
|
|
6142
6151
|
const isSplPool = !mint.equals(NATIVE_SOL_MINT);
|
|
6143
|
-
const
|
|
6144
|
-
const riskCheckEnabled = !isSplPool && riskCheckRequested;
|
|
6145
|
-
if (isSplPool && riskCheckRequested) {
|
|
6146
|
-
onProgress?.(
|
|
6147
|
-
"Skipping risk quote for SPL direct transaction path (not consumed by on-chain SPL transact handler)."
|
|
6148
|
-
);
|
|
6149
|
-
}
|
|
6152
|
+
const riskCheckEnabled = true;
|
|
6150
6153
|
if (isDeposit && riskCheckEnabled && !getRiskQuoteInstruction && !riskQuoteUrl && rangeApiKey) {
|
|
6151
6154
|
onProgress?.("Fetching risk quote from Switchboard (SDK-internal)...");
|
|
6152
6155
|
const result = await fetchRiskQuoteIx(connection, depositor.publicKey, rangeApiKey);
|
|
@@ -6216,11 +6219,12 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6216
6219
|
proofBytes,
|
|
6217
6220
|
publicInputsBytes,
|
|
6218
6221
|
recipient,
|
|
6219
|
-
isDeposit && riskCheckEnabled,
|
|
6222
|
+
(isDeposit || !recipient) && riskCheckEnabled,
|
|
6220
6223
|
encryptedNoteBytes,
|
|
6221
6224
|
splAccounts
|
|
6222
6225
|
);
|
|
6223
|
-
|
|
6226
|
+
const isSend = !recipient && publicAmount === BigInt(0);
|
|
6227
|
+
if ((isDeposit || isSend) && riskCheckEnabled && !riskQuoteIx) {
|
|
6224
6228
|
if (getRiskQuoteInstruction) {
|
|
6225
6229
|
onProgress?.("Fetching risk quote (custom)...");
|
|
6226
6230
|
riskQuoteIx = await getRiskQuoteInstruction(depositor.publicKey);
|
|
@@ -6684,7 +6688,7 @@ async function transact(params, options) {
|
|
|
6684
6688
|
onProofProgress,
|
|
6685
6689
|
relayerFee = BigInt(0),
|
|
6686
6690
|
relayer,
|
|
6687
|
-
relayUrl,
|
|
6691
|
+
relayUrl: relayUrlOverride,
|
|
6688
6692
|
depositorKeypair,
|
|
6689
6693
|
signTransaction: signTransaction2,
|
|
6690
6694
|
depositorPublicKey,
|
|
@@ -6705,6 +6709,7 @@ async function transact(params, options) {
|
|
|
6705
6709
|
enforceViewingKeyRegistration = true,
|
|
6706
6710
|
useChainRootForProof = true
|
|
6707
6711
|
} = options;
|
|
6712
|
+
const relayUrl = resolveRelayUrl(relayUrlOverride);
|
|
6708
6713
|
const useUniqueNullifiersEffective = useUniqueNullifiers ?? shouldDefaultUseUniqueNullifiers(connection);
|
|
6709
6714
|
void enforceViewingKeyRegistration;
|
|
6710
6715
|
const disableAutoRiskQuoteDerive = typeof process !== "undefined" && !!process.env && (process.env.CLOAK_DISABLE_RELAY_RISK_QUOTE_AUTO_DERIVE === "1" || process.env.CLOAK_DISABLE_RELAY_RISK_QUOTE_AUTO_DERIVE === "true");
|
|
@@ -6761,6 +6766,7 @@ async function transact(params, options) {
|
|
|
6761
6766
|
const needsTreeForProof = paddedInputs.some(
|
|
6762
6767
|
(utxo) => utxo.amount > BigInt(0) && utxo.index !== void 0
|
|
6763
6768
|
);
|
|
6769
|
+
const hasCachedTree = !!cachedMerkleTree && cachedMerkleTree.length > 0;
|
|
6764
6770
|
let merkleTree = cachedMerkleTree ?? null;
|
|
6765
6771
|
let treeState = null;
|
|
6766
6772
|
const chainIndexingEnabled = options.useChainForMerkle === true || typeof process !== "undefined" && !!process.env && (process.env.CLOAK_BUILD_TREE_FROM_CHAIN === "true" || process.env.CLOAK_BUILD_TREE_FROM_CHAIN === "1");
|
|
@@ -6784,7 +6790,7 @@ async function transact(params, options) {
|
|
|
6784
6790
|
treeState = await readMerkleTreeState(connection, pdas.merkleTree, forceRefresh, relayUrl, useChainRootForProof, mint);
|
|
6785
6791
|
}
|
|
6786
6792
|
const relaySyncTargetIndex = treeState && treeState.nextIndex > 0 ? Math.max(requiredRelayIndex, treeState.nextIndex - 1) : requiredRelayIndex;
|
|
6787
|
-
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree)) {
|
|
6793
|
+
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree) && !hasCachedTree) {
|
|
6788
6794
|
if (!_relayMerkleFallbackNotifiedMints.has(relayMintKey)) {
|
|
6789
6795
|
onProgress?.(`Using on-chain proof mode for ${relayMintKey} in this environment.`);
|
|
6790
6796
|
_relayMerkleFallbackNotifiedMints.add(relayMintKey);
|
|
@@ -7596,14 +7602,40 @@ async function transact(params, options) {
|
|
|
7596
7602
|
resultTree = merkleTree;
|
|
7597
7603
|
}
|
|
7598
7604
|
} else {
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
+
if (relayUrl) {
|
|
7606
|
+
try {
|
|
7607
|
+
const maxIdx = Math.max(...commitmentIndices);
|
|
7608
|
+
if (maxIdx >= 0) {
|
|
7609
|
+
const postTree = await buildMerkleTreeFromRelay(relayUrl, {
|
|
7610
|
+
mint,
|
|
7611
|
+
sync: true,
|
|
7612
|
+
repair: true,
|
|
7613
|
+
timeoutMs: 8e3,
|
|
7614
|
+
maxRetries: 0,
|
|
7615
|
+
waitForIndex: maxIdx
|
|
7616
|
+
});
|
|
7617
|
+
if (postTree && postTree.length > 0) {
|
|
7618
|
+
const treeLenBefore = postTree.length;
|
|
7619
|
+
const toInsert = outputCommitments.filter((_, i) => commitmentIndices[i] >= treeLenBefore);
|
|
7620
|
+
if (toInsert.length > 0) {
|
|
7621
|
+
postTree.bulkInsert(toInsert);
|
|
7622
|
+
}
|
|
7623
|
+
resultTree = postTree;
|
|
7624
|
+
}
|
|
7625
|
+
}
|
|
7626
|
+
} catch {
|
|
7627
|
+
}
|
|
7628
|
+
}
|
|
7629
|
+
if (!resultTree) {
|
|
7630
|
+
try {
|
|
7631
|
+
const indexedCommitments = outputCommitments.map((c, i) => ({ c, idx: commitmentIndices[i], amount: paddedOutputs[i]?.amount ?? BigInt(0) })).filter((x) => x.idx >= 0 && x.amount > BigInt(0)).sort((a, b) => a.idx - b.idx);
|
|
7632
|
+
const isContiguousFromZero = indexedCommitments.length > 0 && indexedCommitments.every((x, i) => x.idx === i);
|
|
7633
|
+
if (isContiguousFromZero) {
|
|
7634
|
+
const leaves = indexedCommitments.map((x) => x.c);
|
|
7635
|
+
resultTree = await MerkleTree.create(32, leaves);
|
|
7636
|
+
}
|
|
7637
|
+
} catch {
|
|
7605
7638
|
}
|
|
7606
|
-
} catch {
|
|
7607
7639
|
}
|
|
7608
7640
|
}
|
|
7609
7641
|
return {
|
|
@@ -7655,9 +7687,37 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
7655
7687
|
if (inputSum < withdrawAmount) {
|
|
7656
7688
|
throw new Error(`Insufficient funds: have ${inputSum}, need ${withdrawAmount}`);
|
|
7657
7689
|
}
|
|
7658
|
-
const change = inputSum - withdrawAmount;
|
|
7659
7690
|
const myKeypair = inputUtxos[0].keypair;
|
|
7660
7691
|
const mint = inputUtxos[0].mintAddress;
|
|
7692
|
+
let utxos = [...inputUtxos];
|
|
7693
|
+
let cachedTree = options.cachedMerkleTree;
|
|
7694
|
+
while (utxos.length > 2) {
|
|
7695
|
+
options.onProgress?.(`Consolidating notes (${utxos.length} remaining)...`);
|
|
7696
|
+
utxos.sort((a, b) => a.amount > b.amount ? 1 : a.amount < b.amount ? -1 : 0);
|
|
7697
|
+
const [small1, small2, ...rest] = utxos;
|
|
7698
|
+
const mergedAmount = small1.amount + small2.amount;
|
|
7699
|
+
const mergedOutput = await createUtxo(mergedAmount, myKeypair, mint);
|
|
7700
|
+
const mergeResult = await transact(
|
|
7701
|
+
{
|
|
7702
|
+
inputUtxos: [small1, small2],
|
|
7703
|
+
outputUtxos: [mergedOutput],
|
|
7704
|
+
externalAmount: BigInt(0)
|
|
7705
|
+
// Shield-to-shield, no external movement
|
|
7706
|
+
},
|
|
7707
|
+
{
|
|
7708
|
+
...options,
|
|
7709
|
+
cachedMerkleTree: cachedTree
|
|
7710
|
+
}
|
|
7711
|
+
);
|
|
7712
|
+
cachedTree = mergeResult.merkleTree;
|
|
7713
|
+
const consolidatedUtxo = mergeResult.outputUtxos?.[0] ?? mergedOutput;
|
|
7714
|
+
if (mergeResult.commitmentIndices?.[0] >= 0) {
|
|
7715
|
+
consolidatedUtxo.index = mergeResult.commitmentIndices[0];
|
|
7716
|
+
}
|
|
7717
|
+
utxos = [consolidatedUtxo, ...rest];
|
|
7718
|
+
}
|
|
7719
|
+
const finalInputSum = sumUtxoAmounts(utxos);
|
|
7720
|
+
const change = finalInputSum - withdrawAmount;
|
|
7661
7721
|
const outputUtxos = [];
|
|
7662
7722
|
if (change > BigInt(0)) {
|
|
7663
7723
|
const changeUtxo = await createUtxo(change, myKeypair, mint);
|
|
@@ -7665,13 +7725,15 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
7665
7725
|
}
|
|
7666
7726
|
return transact(
|
|
7667
7727
|
{
|
|
7668
|
-
inputUtxos,
|
|
7728
|
+
inputUtxos: utxos,
|
|
7669
7729
|
outputUtxos,
|
|
7670
7730
|
recipient,
|
|
7671
7731
|
externalAmount: -withdrawAmount
|
|
7672
|
-
// Negative = withdraw
|
|
7673
7732
|
},
|
|
7674
|
-
|
|
7733
|
+
{
|
|
7734
|
+
...options,
|
|
7735
|
+
cachedMerkleTree: cachedTree
|
|
7736
|
+
}
|
|
7675
7737
|
);
|
|
7676
7738
|
}
|
|
7677
7739
|
async function fullWithdraw(inputUtxos, recipient, options) {
|
|
@@ -7699,6 +7761,10 @@ async function waitForSwapCompletion(relayUrl, requestId, onProgress, maxAttempt
|
|
|
7699
7761
|
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "likely refunded after timeout";
|
|
7700
7762
|
throw new Error(`Swap execution cancelled: ${detail}`);
|
|
7701
7763
|
}
|
|
7764
|
+
if (status === "refunded") {
|
|
7765
|
+
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "Swap route unavailable \u2014 funds refunded as SOL to your wallet";
|
|
7766
|
+
throw new Error(`Swap refunded: ${detail}`);
|
|
7767
|
+
}
|
|
7702
7768
|
if (swapPhase && swapPhase !== lastSwapPhase) {
|
|
7703
7769
|
lastSwapPhase = swapPhase;
|
|
7704
7770
|
if (swapPhase === "waiting_timeout") {
|
|
@@ -7711,7 +7777,7 @@ async function waitForSwapCompletion(relayUrl, requestId, onProgress, maxAttempt
|
|
|
7711
7777
|
}
|
|
7712
7778
|
} catch (e) {
|
|
7713
7779
|
const msg = e.message ?? "";
|
|
7714
|
-
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled")) {
|
|
7780
|
+
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.includes("Swap refunded") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled") || msg.toLowerCase().includes("refunded")) {
|
|
7715
7781
|
throw e;
|
|
7716
7782
|
}
|
|
7717
7783
|
}
|
|
@@ -7730,10 +7796,14 @@ async function waitForSwapCompletion(relayUrl, requestId, onProgress, maxAttempt
|
|
|
7730
7796
|
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "likely refunded after timeout";
|
|
7731
7797
|
throw new Error(`Swap execution cancelled: ${detail}`);
|
|
7732
7798
|
}
|
|
7799
|
+
if (status === "refunded") {
|
|
7800
|
+
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "Swap route unavailable \u2014 funds refunded as SOL to your wallet";
|
|
7801
|
+
throw new Error(`Swap refunded: ${detail}`);
|
|
7802
|
+
}
|
|
7733
7803
|
}
|
|
7734
7804
|
} catch (e) {
|
|
7735
7805
|
const msg = e.message ?? "";
|
|
7736
|
-
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled")) {
|
|
7806
|
+
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.includes("Swap refunded") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled") || msg.toLowerCase().includes("refunded")) {
|
|
7737
7807
|
throw e;
|
|
7738
7808
|
}
|
|
7739
7809
|
}
|
|
@@ -7758,7 +7828,7 @@ async function swapUtxo(params, options) {
|
|
|
7758
7828
|
useChainForMerkle,
|
|
7759
7829
|
relayerFee = BigInt(0),
|
|
7760
7830
|
relayer,
|
|
7761
|
-
relayUrl,
|
|
7831
|
+
relayUrl: relayUrlOverride,
|
|
7762
7832
|
riskQuoteUrl,
|
|
7763
7833
|
maxRootRetries = 40,
|
|
7764
7834
|
// Increased to handle prolonged relay sync recovery under high concurrency
|
|
@@ -7767,6 +7837,7 @@ async function swapUtxo(params, options) {
|
|
|
7767
7837
|
useUniqueNullifiers,
|
|
7768
7838
|
useChainRootForProof = true
|
|
7769
7839
|
} = options;
|
|
7840
|
+
const relayUrl = resolveRelayUrl(relayUrlOverride);
|
|
7770
7841
|
const useUniqueNullifiersEffective = useUniqueNullifiers ?? shouldDefaultUseUniqueNullifiers(connection);
|
|
7771
7842
|
if (inputUtxos.length === 0) {
|
|
7772
7843
|
throw new Error("At least one input UTXO required");
|
|
@@ -7821,6 +7892,7 @@ async function swapUtxo(params, options) {
|
|
|
7821
7892
|
const useRelayMerkleByDefault = shouldUseRelayMerkleByDefault(connection);
|
|
7822
7893
|
const relayMintKey = swapPoolMint.toBase58();
|
|
7823
7894
|
let relayTreeDisabledForMint = _relayMerkleDisabledMints.has(relayMintKey) || !useRelayMerkleByDefault;
|
|
7895
|
+
const hasCachedTree = !!cachedMerkleTree && cachedMerkleTree.length > 0;
|
|
7824
7896
|
const requiredRelayIndex = paddedInputs.reduce((maxIndex, utxo) => {
|
|
7825
7897
|
if (utxo.amount === BigInt(0) || utxo.index === void 0 || utxo.index < 0) {
|
|
7826
7898
|
return maxIndex;
|
|
@@ -7837,7 +7909,7 @@ async function swapUtxo(params, options) {
|
|
|
7837
7909
|
merkleState = await readMerkleTreeState(connection, pdas.merkleTree, forceRefresh, relayUrl, useChainRootForProof, swapPoolMint);
|
|
7838
7910
|
}
|
|
7839
7911
|
const relaySyncTargetIndex = merkleState && merkleState.nextIndex > 0 ? Math.max(requiredRelayIndex, merkleState.nextIndex - 1) : requiredRelayIndex;
|
|
7840
|
-
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree)) {
|
|
7912
|
+
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree) && !hasCachedTree) {
|
|
7841
7913
|
if (!_relayMerkleFallbackNotifiedMints.has(relayMintKey)) {
|
|
7842
7914
|
onProgress?.(`Using on-chain proof mode for ${relayMintKey} in this environment.`);
|
|
7843
7915
|
_relayMerkleFallbackNotifiedMints.add(relayMintKey);
|
package/dist/index.d.cts
CHANGED
|
@@ -2843,7 +2843,10 @@ interface TransactOptions {
|
|
|
2843
2843
|
relayerFee?: bigint;
|
|
2844
2844
|
/** Relayer address for fee payment */
|
|
2845
2845
|
relayer?: PublicKey;
|
|
2846
|
-
/**
|
|
2846
|
+
/**
|
|
2847
|
+
* Relay URL override.
|
|
2848
|
+
* Defaults to `https://api.cloak.ag` when omitted.
|
|
2849
|
+
*/
|
|
2847
2850
|
relayUrl?: string;
|
|
2848
2851
|
/** Keypair of the depositor (signs the deposit transaction) - for programmatic use */
|
|
2849
2852
|
depositorKeypair?: Keypair;
|
package/dist/index.d.ts
CHANGED
|
@@ -2843,7 +2843,10 @@ interface TransactOptions {
|
|
|
2843
2843
|
relayerFee?: bigint;
|
|
2844
2844
|
/** Relayer address for fee payment */
|
|
2845
2845
|
relayer?: PublicKey;
|
|
2846
|
-
/**
|
|
2846
|
+
/**
|
|
2847
|
+
* Relay URL override.
|
|
2848
|
+
* Defaults to `https://api.cloak.ag` when omitted.
|
|
2849
|
+
*/
|
|
2847
2850
|
relayUrl?: string;
|
|
2848
2851
|
/** Keypair of the depositor (signs the deposit transaction) - for programmatic use */
|
|
2849
2852
|
depositorKeypair?: Keypair;
|
package/dist/index.js
CHANGED
|
@@ -1401,6 +1401,22 @@ var ErrorPatterns = [
|
|
|
1401
1401
|
recoverable: true
|
|
1402
1402
|
}
|
|
1403
1403
|
},
|
|
1404
|
+
{
|
|
1405
|
+
patterns: [
|
|
1406
|
+
"Swap refunded",
|
|
1407
|
+
"swap refunded",
|
|
1408
|
+
"funds refunded as SOL",
|
|
1409
|
+
"funds were refunded",
|
|
1410
|
+
"Swap timed out and funds were refunded"
|
|
1411
|
+
],
|
|
1412
|
+
result: {
|
|
1413
|
+
title: "Swap Refunded",
|
|
1414
|
+
message: "No swap route was available. Your funds have been refunded as SOL to your wallet.",
|
|
1415
|
+
category: "service",
|
|
1416
|
+
suggestion: "Check your wallet balance \u2014 the SOL should already be there (minus the protocol fee). Try again with a different token or amount.",
|
|
1417
|
+
recoverable: true
|
|
1418
|
+
}
|
|
1419
|
+
},
|
|
1404
1420
|
{
|
|
1405
1421
|
patterns: [
|
|
1406
1422
|
"Failed to get quote",
|
|
@@ -2156,8 +2172,8 @@ var IS_REACT_NATIVE = typeof navigator !== "undefined" && navigator.product ===
|
|
|
2156
2172
|
var IS_BROWSER = IS_REACT_NATIVE || typeof window !== "undefined" || typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
|
|
2157
2173
|
var DEFAULT_CIRCUITS_URL = "https://cloak-circuits.s3.us-east-1.amazonaws.com/circuits/0.1.0";
|
|
2158
2174
|
var SKIP_CIRCUIT_VERIFY_ENV = typeof process !== "undefined" && process.env && process.env.CLOAK_SKIP_CIRCUIT_INTEGRITY_CHECK === "1";
|
|
2159
|
-
function isUrl(
|
|
2160
|
-
return
|
|
2175
|
+
function isUrl(path) {
|
|
2176
|
+
return path.startsWith("http://") || path.startsWith("https://");
|
|
2161
2177
|
}
|
|
2162
2178
|
function resolveCircuitsUrl(circuitsPath2) {
|
|
2163
2179
|
if (circuitsPath2.trim() !== "" && circuitsPath2.trim() !== DEFAULT_CIRCUITS_URL) {
|
|
@@ -2621,7 +2637,7 @@ function createSetLoadedAccountsDataSizeLimitInstruction(bytes) {
|
|
|
2621
2637
|
data
|
|
2622
2638
|
});
|
|
2623
2639
|
}
|
|
2624
|
-
var CLOAK_PROGRAM_ID = new PublicKey4("
|
|
2640
|
+
var CLOAK_PROGRAM_ID = new PublicKey4("zh1eLd6rSphLejbFfJEneUwzHRfMKxgzrgkfwA6qRkW");
|
|
2625
2641
|
var CLOAK_API_URL = "https://api.cloak.ag";
|
|
2626
2642
|
var CloakSDK = class {
|
|
2627
2643
|
/**
|
|
@@ -5113,56 +5129,39 @@ function chainNoteFromBase64(base64) {
|
|
|
5113
5129
|
// src/core/transact.ts
|
|
5114
5130
|
import { buildPoseidon as buildPoseidon3 } from "circomlibjs";
|
|
5115
5131
|
import nacl4 from "tweetnacl";
|
|
5116
|
-
|
|
5117
|
-
import { createHash } from "crypto";
|
|
5118
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
5119
|
-
import { tmpdir } from "os";
|
|
5132
|
+
var IS_BROWSER2 = typeof window !== "undefined" || typeof globalThis.document !== "undefined";
|
|
5120
5133
|
var DEFAULT_TRANSACTION_CIRCUITS_URL = "https://cloak-circuits.s3.us-east-1.amazonaws.com/circuits/0.1.0";
|
|
5134
|
+
var DEFAULT_CLOAK_RELAY_URL = "https://api.cloak.ag";
|
|
5121
5135
|
function resolveDefaultTransactionCircuitsPath() {
|
|
5122
5136
|
return DEFAULT_TRANSACTION_CIRCUITS_URL;
|
|
5123
5137
|
}
|
|
5124
5138
|
var circuitsPath = resolveDefaultTransactionCircuitsPath();
|
|
5125
|
-
function isHttpCircuitsPath(p) {
|
|
5126
|
-
return p.startsWith("https://") || p.startsWith("http://");
|
|
5127
|
-
}
|
|
5128
5139
|
var _remoteTxCircuitsCache = null;
|
|
5129
5140
|
async function resolveTransactionCircuitFiles() {
|
|
5130
5141
|
const base = circuitsPath;
|
|
5131
|
-
const wasmRel = path.join("transaction_js", "transaction.wasm");
|
|
5132
|
-
const zkeyRel = "transaction_final.zkey";
|
|
5133
|
-
if (!isHttpCircuitsPath(base)) {
|
|
5134
|
-
const root = base;
|
|
5135
|
-
return {
|
|
5136
|
-
wasmPath: path.join(root, wasmRel),
|
|
5137
|
-
zkeyPath: path.join(root, zkeyRel)
|
|
5138
|
-
};
|
|
5139
|
-
}
|
|
5140
5142
|
const baseNorm = base.endsWith("/") ? base : `${base}/`;
|
|
5143
|
+
const wasmUrl = `${baseNorm}transaction_js/transaction.wasm`;
|
|
5144
|
+
const zkeyUrl = `${baseNorm}transaction_final.zkey`;
|
|
5145
|
+
if (IS_BROWSER2) {
|
|
5146
|
+
return { wasmPath: wasmUrl, zkeyPath: zkeyUrl };
|
|
5147
|
+
}
|
|
5141
5148
|
if (_remoteTxCircuitsCache?.base === baseNorm) {
|
|
5142
|
-
|
|
5143
|
-
return {
|
|
5144
|
-
wasmPath: path.join(dir2, "transaction.wasm"),
|
|
5145
|
-
zkeyPath: path.join(dir2, "transaction_final.zkey")
|
|
5146
|
-
};
|
|
5149
|
+
return _remoteTxCircuitsCache.artifacts;
|
|
5147
5150
|
}
|
|
5148
|
-
const
|
|
5149
|
-
const zkeyUrl = new URL(zkeyRel, baseNorm).toString();
|
|
5150
|
-
const subdir = `cloak-tx-circuits-${createHash("sha256").update(baseNorm).digest("hex").slice(0, 16)}`;
|
|
5151
|
-
const dir = path.join(tmpdir(), subdir);
|
|
5152
|
-
await mkdir(dir, { recursive: true });
|
|
5153
|
-
const wasmPath = path.join(dir, "transaction.wasm");
|
|
5154
|
-
const zkeyPath = path.join(dir, "transaction_final.zkey");
|
|
5155
|
-
const download = async (url, dest) => {
|
|
5151
|
+
const fetchAsBuffer = async (url) => {
|
|
5156
5152
|
const res = await fetch(url);
|
|
5157
5153
|
if (!res.ok) {
|
|
5158
5154
|
throw new Error(`Failed to fetch circuit artifact ${url}: ${res.status} ${res.statusText}`);
|
|
5159
5155
|
}
|
|
5160
|
-
|
|
5156
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
5161
5157
|
};
|
|
5162
|
-
await
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5158
|
+
const [wasmData, zkeyData] = await Promise.all([
|
|
5159
|
+
fetchAsBuffer(wasmUrl),
|
|
5160
|
+
fetchAsBuffer(zkeyUrl)
|
|
5161
|
+
]);
|
|
5162
|
+
const artifacts = { wasmPath: wasmData, zkeyPath: zkeyData };
|
|
5163
|
+
_remoteTxCircuitsCache = { base: baseNorm, artifacts };
|
|
5164
|
+
return artifacts;
|
|
5166
5165
|
}
|
|
5167
5166
|
var _transactPaddingSaltCounter = 0;
|
|
5168
5167
|
var _registeredViewingKeys = /* @__PURE__ */ new Set();
|
|
@@ -5256,6 +5255,12 @@ function deriveRelayUrlFromRiskQuoteUrl(riskQuoteUrl) {
|
|
|
5256
5255
|
}
|
|
5257
5256
|
return void 0;
|
|
5258
5257
|
}
|
|
5258
|
+
function resolveRelayUrl(relayUrl) {
|
|
5259
|
+
const trimmed = relayUrl?.trim();
|
|
5260
|
+
if (trimmed === "") return void 0;
|
|
5261
|
+
if (trimmed) return trimmed.replace(/\/$/, "");
|
|
5262
|
+
return DEFAULT_CLOAK_RELAY_URL;
|
|
5263
|
+
}
|
|
5259
5264
|
async function resolveAddressLookupTableAccounts(connection, relayUrl, altAddressesFromOptions, provided, onProgress) {
|
|
5260
5265
|
if (provided && provided.length > 0) {
|
|
5261
5266
|
return provided;
|
|
@@ -5353,9 +5358,8 @@ async function resolveChainNoteNk(options) {
|
|
|
5353
5358
|
}
|
|
5354
5359
|
return null;
|
|
5355
5360
|
}
|
|
5356
|
-
function shouldDefaultUseUniqueNullifiers(
|
|
5357
|
-
|
|
5358
|
-
return endpoint.includes("127.0.0.1") || endpoint.includes("localhost") || endpoint.includes("0.0.0.0");
|
|
5361
|
+
function shouldDefaultUseUniqueNullifiers(_connection) {
|
|
5362
|
+
return true;
|
|
5359
5363
|
}
|
|
5360
5364
|
function toHex(bytes) {
|
|
5361
5365
|
return Buffer.from(bytes).toString("hex");
|
|
@@ -5364,7 +5368,7 @@ async function ensureViewingKeyRegistered(options, onProgress, fallbackNk) {
|
|
|
5364
5368
|
if (options.enforceViewingKeyRegistration === false) {
|
|
5365
5369
|
return;
|
|
5366
5370
|
}
|
|
5367
|
-
const relayUrl = options.relayUrl
|
|
5371
|
+
const relayUrl = resolveRelayUrl(options.relayUrl);
|
|
5368
5372
|
if (!relayUrl) {
|
|
5369
5373
|
throw new Error("Viewing key registration is mandatory: relayUrl is required.");
|
|
5370
5374
|
}
|
|
@@ -5435,12 +5439,12 @@ async function ensureViewingKeyRegistered(options, onProgress, fallbackNk) {
|
|
|
5435
5439
|
}
|
|
5436
5440
|
async function generateTransactionProof(inputs, onProgress) {
|
|
5437
5441
|
onProgress?.(10);
|
|
5438
|
-
const { wasmPath, zkeyPath } = await resolveTransactionCircuitFiles();
|
|
5442
|
+
const { wasmPath: wasmInput, zkeyPath: zkeyInput } = await resolveTransactionCircuitFiles();
|
|
5439
5443
|
onProgress?.(30);
|
|
5440
5444
|
const { proof, publicSignals } = await snarkjs2.groth16.fullProve(
|
|
5441
5445
|
inputs,
|
|
5442
|
-
|
|
5443
|
-
|
|
5446
|
+
wasmInput,
|
|
5447
|
+
zkeyInput
|
|
5444
5448
|
);
|
|
5445
5449
|
onProgress?.(100);
|
|
5446
5450
|
return { proof, publicSignals };
|
|
@@ -5563,21 +5567,26 @@ function buildTransactInstruction(programId, payer, poolPDA, treasuryPDA, merkle
|
|
|
5563
5567
|
{ pubkey: SystemProgram2.programId, isSigner: false, isWritable: false }
|
|
5564
5568
|
// 6. system_program
|
|
5565
5569
|
];
|
|
5566
|
-
if (recipient) {
|
|
5567
|
-
accounts.push({ pubkey: recipient, isSigner: false, isWritable: true });
|
|
5568
|
-
if (enableRiskCheck) {
|
|
5569
|
-
accounts.push({ pubkey: SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
5570
|
-
}
|
|
5571
|
-
} else if (enableRiskCheck) {
|
|
5572
|
-
const instructionsSysvar = SYSVAR_INSTRUCTIONS_PUBKEY;
|
|
5573
|
-
accounts.push({ pubkey: instructionsSysvar, isSigner: false, isWritable: false });
|
|
5574
|
-
}
|
|
5575
5570
|
if (splAccounts) {
|
|
5576
5571
|
accounts.push({ pubkey: splAccounts.vaultAuthority, isSigner: false, isWritable: false });
|
|
5577
5572
|
accounts.push({ pubkey: splAccounts.poolVaultAta, isSigner: false, isWritable: true });
|
|
5578
5573
|
accounts.push({ pubkey: splAccounts.tokenProgram, isSigner: false, isWritable: false });
|
|
5579
5574
|
if (splAccounts.payerAta) {
|
|
5575
|
+
if (enableRiskCheck) {
|
|
5576
|
+
accounts.push({ pubkey: SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
5577
|
+
}
|
|
5580
5578
|
accounts.push({ pubkey: splAccounts.payerAta, isSigner: false, isWritable: true });
|
|
5579
|
+
} else if (enableRiskCheck && !recipient) {
|
|
5580
|
+
accounts.push({ pubkey: SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
5581
|
+
}
|
|
5582
|
+
} else {
|
|
5583
|
+
if (recipient) {
|
|
5584
|
+
accounts.push({ pubkey: recipient, isSigner: false, isWritable: true });
|
|
5585
|
+
if (enableRiskCheck) {
|
|
5586
|
+
accounts.push({ pubkey: SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
5587
|
+
}
|
|
5588
|
+
} else if (enableRiskCheck) {
|
|
5589
|
+
accounts.push({ pubkey: SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false });
|
|
5581
5590
|
}
|
|
5582
5591
|
}
|
|
5583
5592
|
return new TransactionInstruction3({
|
|
@@ -5693,13 +5702,7 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
5693
5702
|
let riskQuoteIx = null;
|
|
5694
5703
|
const isDeposit = recipient === void 0;
|
|
5695
5704
|
const isSplPool = !mint.equals(NATIVE_SOL_MINT);
|
|
5696
|
-
const
|
|
5697
|
-
const riskCheckEnabled = !isSplPool && riskCheckRequested;
|
|
5698
|
-
if (isSplPool && riskCheckRequested) {
|
|
5699
|
-
onProgress?.(
|
|
5700
|
-
"Skipping risk quote for SPL direct transaction path (not consumed by on-chain SPL transact handler)."
|
|
5701
|
-
);
|
|
5702
|
-
}
|
|
5705
|
+
const riskCheckEnabled = true;
|
|
5703
5706
|
if (isDeposit && riskCheckEnabled && !getRiskQuoteInstruction && !riskQuoteUrl && rangeApiKey) {
|
|
5704
5707
|
onProgress?.("Fetching risk quote from Switchboard (SDK-internal)...");
|
|
5705
5708
|
const result = await fetchRiskQuoteIx(connection, depositor.publicKey, rangeApiKey);
|
|
@@ -5769,11 +5772,12 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
5769
5772
|
proofBytes,
|
|
5770
5773
|
publicInputsBytes,
|
|
5771
5774
|
recipient,
|
|
5772
|
-
isDeposit && riskCheckEnabled,
|
|
5775
|
+
(isDeposit || !recipient) && riskCheckEnabled,
|
|
5773
5776
|
encryptedNoteBytes,
|
|
5774
5777
|
splAccounts
|
|
5775
5778
|
);
|
|
5776
|
-
|
|
5779
|
+
const isSend = !recipient && publicAmount === BigInt(0);
|
|
5780
|
+
if ((isDeposit || isSend) && riskCheckEnabled && !riskQuoteIx) {
|
|
5777
5781
|
if (getRiskQuoteInstruction) {
|
|
5778
5782
|
onProgress?.("Fetching risk quote (custom)...");
|
|
5779
5783
|
riskQuoteIx = await getRiskQuoteInstruction(depositor.publicKey);
|
|
@@ -6237,7 +6241,7 @@ async function transact(params, options) {
|
|
|
6237
6241
|
onProofProgress,
|
|
6238
6242
|
relayerFee = BigInt(0),
|
|
6239
6243
|
relayer,
|
|
6240
|
-
relayUrl,
|
|
6244
|
+
relayUrl: relayUrlOverride,
|
|
6241
6245
|
depositorKeypair,
|
|
6242
6246
|
signTransaction: signTransaction2,
|
|
6243
6247
|
depositorPublicKey,
|
|
@@ -6258,6 +6262,7 @@ async function transact(params, options) {
|
|
|
6258
6262
|
enforceViewingKeyRegistration = true,
|
|
6259
6263
|
useChainRootForProof = true
|
|
6260
6264
|
} = options;
|
|
6265
|
+
const relayUrl = resolveRelayUrl(relayUrlOverride);
|
|
6261
6266
|
const useUniqueNullifiersEffective = useUniqueNullifiers ?? shouldDefaultUseUniqueNullifiers(connection);
|
|
6262
6267
|
void enforceViewingKeyRegistration;
|
|
6263
6268
|
const disableAutoRiskQuoteDerive = typeof process !== "undefined" && !!process.env && (process.env.CLOAK_DISABLE_RELAY_RISK_QUOTE_AUTO_DERIVE === "1" || process.env.CLOAK_DISABLE_RELAY_RISK_QUOTE_AUTO_DERIVE === "true");
|
|
@@ -6314,6 +6319,7 @@ async function transact(params, options) {
|
|
|
6314
6319
|
const needsTreeForProof = paddedInputs.some(
|
|
6315
6320
|
(utxo) => utxo.amount > BigInt(0) && utxo.index !== void 0
|
|
6316
6321
|
);
|
|
6322
|
+
const hasCachedTree = !!cachedMerkleTree && cachedMerkleTree.length > 0;
|
|
6317
6323
|
let merkleTree = cachedMerkleTree ?? null;
|
|
6318
6324
|
let treeState = null;
|
|
6319
6325
|
const chainIndexingEnabled = options.useChainForMerkle === true || typeof process !== "undefined" && !!process.env && (process.env.CLOAK_BUILD_TREE_FROM_CHAIN === "true" || process.env.CLOAK_BUILD_TREE_FROM_CHAIN === "1");
|
|
@@ -6337,7 +6343,7 @@ async function transact(params, options) {
|
|
|
6337
6343
|
treeState = await readMerkleTreeState(connection, pdas.merkleTree, forceRefresh, relayUrl, useChainRootForProof, mint);
|
|
6338
6344
|
}
|
|
6339
6345
|
const relaySyncTargetIndex = treeState && treeState.nextIndex > 0 ? Math.max(requiredRelayIndex, treeState.nextIndex - 1) : requiredRelayIndex;
|
|
6340
|
-
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree)) {
|
|
6346
|
+
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree) && !hasCachedTree) {
|
|
6341
6347
|
if (!_relayMerkleFallbackNotifiedMints.has(relayMintKey)) {
|
|
6342
6348
|
onProgress?.(`Using on-chain proof mode for ${relayMintKey} in this environment.`);
|
|
6343
6349
|
_relayMerkleFallbackNotifiedMints.add(relayMintKey);
|
|
@@ -7149,14 +7155,40 @@ async function transact(params, options) {
|
|
|
7149
7155
|
resultTree = merkleTree;
|
|
7150
7156
|
}
|
|
7151
7157
|
} else {
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
+
if (relayUrl) {
|
|
7159
|
+
try {
|
|
7160
|
+
const maxIdx = Math.max(...commitmentIndices);
|
|
7161
|
+
if (maxIdx >= 0) {
|
|
7162
|
+
const postTree = await buildMerkleTreeFromRelay(relayUrl, {
|
|
7163
|
+
mint,
|
|
7164
|
+
sync: true,
|
|
7165
|
+
repair: true,
|
|
7166
|
+
timeoutMs: 8e3,
|
|
7167
|
+
maxRetries: 0,
|
|
7168
|
+
waitForIndex: maxIdx
|
|
7169
|
+
});
|
|
7170
|
+
if (postTree && postTree.length > 0) {
|
|
7171
|
+
const treeLenBefore = postTree.length;
|
|
7172
|
+
const toInsert = outputCommitments.filter((_, i) => commitmentIndices[i] >= treeLenBefore);
|
|
7173
|
+
if (toInsert.length > 0) {
|
|
7174
|
+
postTree.bulkInsert(toInsert);
|
|
7175
|
+
}
|
|
7176
|
+
resultTree = postTree;
|
|
7177
|
+
}
|
|
7178
|
+
}
|
|
7179
|
+
} catch {
|
|
7180
|
+
}
|
|
7181
|
+
}
|
|
7182
|
+
if (!resultTree) {
|
|
7183
|
+
try {
|
|
7184
|
+
const indexedCommitments = outputCommitments.map((c, i) => ({ c, idx: commitmentIndices[i], amount: paddedOutputs[i]?.amount ?? BigInt(0) })).filter((x) => x.idx >= 0 && x.amount > BigInt(0)).sort((a, b) => a.idx - b.idx);
|
|
7185
|
+
const isContiguousFromZero = indexedCommitments.length > 0 && indexedCommitments.every((x, i) => x.idx === i);
|
|
7186
|
+
if (isContiguousFromZero) {
|
|
7187
|
+
const leaves = indexedCommitments.map((x) => x.c);
|
|
7188
|
+
resultTree = await MerkleTree.create(32, leaves);
|
|
7189
|
+
}
|
|
7190
|
+
} catch {
|
|
7158
7191
|
}
|
|
7159
|
-
} catch {
|
|
7160
7192
|
}
|
|
7161
7193
|
}
|
|
7162
7194
|
return {
|
|
@@ -7208,9 +7240,37 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
7208
7240
|
if (inputSum < withdrawAmount) {
|
|
7209
7241
|
throw new Error(`Insufficient funds: have ${inputSum}, need ${withdrawAmount}`);
|
|
7210
7242
|
}
|
|
7211
|
-
const change = inputSum - withdrawAmount;
|
|
7212
7243
|
const myKeypair = inputUtxos[0].keypair;
|
|
7213
7244
|
const mint = inputUtxos[0].mintAddress;
|
|
7245
|
+
let utxos = [...inputUtxos];
|
|
7246
|
+
let cachedTree = options.cachedMerkleTree;
|
|
7247
|
+
while (utxos.length > 2) {
|
|
7248
|
+
options.onProgress?.(`Consolidating notes (${utxos.length} remaining)...`);
|
|
7249
|
+
utxos.sort((a, b) => a.amount > b.amount ? 1 : a.amount < b.amount ? -1 : 0);
|
|
7250
|
+
const [small1, small2, ...rest] = utxos;
|
|
7251
|
+
const mergedAmount = small1.amount + small2.amount;
|
|
7252
|
+
const mergedOutput = await createUtxo(mergedAmount, myKeypair, mint);
|
|
7253
|
+
const mergeResult = await transact(
|
|
7254
|
+
{
|
|
7255
|
+
inputUtxos: [small1, small2],
|
|
7256
|
+
outputUtxos: [mergedOutput],
|
|
7257
|
+
externalAmount: BigInt(0)
|
|
7258
|
+
// Shield-to-shield, no external movement
|
|
7259
|
+
},
|
|
7260
|
+
{
|
|
7261
|
+
...options,
|
|
7262
|
+
cachedMerkleTree: cachedTree
|
|
7263
|
+
}
|
|
7264
|
+
);
|
|
7265
|
+
cachedTree = mergeResult.merkleTree;
|
|
7266
|
+
const consolidatedUtxo = mergeResult.outputUtxos?.[0] ?? mergedOutput;
|
|
7267
|
+
if (mergeResult.commitmentIndices?.[0] >= 0) {
|
|
7268
|
+
consolidatedUtxo.index = mergeResult.commitmentIndices[0];
|
|
7269
|
+
}
|
|
7270
|
+
utxos = [consolidatedUtxo, ...rest];
|
|
7271
|
+
}
|
|
7272
|
+
const finalInputSum = sumUtxoAmounts(utxos);
|
|
7273
|
+
const change = finalInputSum - withdrawAmount;
|
|
7214
7274
|
const outputUtxos = [];
|
|
7215
7275
|
if (change > BigInt(0)) {
|
|
7216
7276
|
const changeUtxo = await createUtxo(change, myKeypair, mint);
|
|
@@ -7218,13 +7278,15 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
7218
7278
|
}
|
|
7219
7279
|
return transact(
|
|
7220
7280
|
{
|
|
7221
|
-
inputUtxos,
|
|
7281
|
+
inputUtxos: utxos,
|
|
7222
7282
|
outputUtxos,
|
|
7223
7283
|
recipient,
|
|
7224
7284
|
externalAmount: -withdrawAmount
|
|
7225
|
-
// Negative = withdraw
|
|
7226
7285
|
},
|
|
7227
|
-
|
|
7286
|
+
{
|
|
7287
|
+
...options,
|
|
7288
|
+
cachedMerkleTree: cachedTree
|
|
7289
|
+
}
|
|
7228
7290
|
);
|
|
7229
7291
|
}
|
|
7230
7292
|
async function fullWithdraw(inputUtxos, recipient, options) {
|
|
@@ -7252,6 +7314,10 @@ async function waitForSwapCompletion(relayUrl, requestId, onProgress, maxAttempt
|
|
|
7252
7314
|
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "likely refunded after timeout";
|
|
7253
7315
|
throw new Error(`Swap execution cancelled: ${detail}`);
|
|
7254
7316
|
}
|
|
7317
|
+
if (status === "refunded") {
|
|
7318
|
+
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "Swap route unavailable \u2014 funds refunded as SOL to your wallet";
|
|
7319
|
+
throw new Error(`Swap refunded: ${detail}`);
|
|
7320
|
+
}
|
|
7255
7321
|
if (swapPhase && swapPhase !== lastSwapPhase) {
|
|
7256
7322
|
lastSwapPhase = swapPhase;
|
|
7257
7323
|
if (swapPhase === "waiting_timeout") {
|
|
@@ -7264,7 +7330,7 @@ async function waitForSwapCompletion(relayUrl, requestId, onProgress, maxAttempt
|
|
|
7264
7330
|
}
|
|
7265
7331
|
} catch (e) {
|
|
7266
7332
|
const msg = e.message ?? "";
|
|
7267
|
-
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled")) {
|
|
7333
|
+
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.includes("Swap refunded") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled") || msg.toLowerCase().includes("refunded")) {
|
|
7268
7334
|
throw e;
|
|
7269
7335
|
}
|
|
7270
7336
|
}
|
|
@@ -7283,10 +7349,14 @@ async function waitForSwapCompletion(relayUrl, requestId, onProgress, maxAttempt
|
|
|
7283
7349
|
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "likely refunded after timeout";
|
|
7284
7350
|
throw new Error(`Swap execution cancelled: ${detail}`);
|
|
7285
7351
|
}
|
|
7352
|
+
if (status === "refunded") {
|
|
7353
|
+
const detail = typeof json.data.error === "string" && json.data.error.length > 0 ? json.data.error : "Swap route unavailable \u2014 funds refunded as SOL to your wallet";
|
|
7354
|
+
throw new Error(`Swap refunded: ${detail}`);
|
|
7355
|
+
}
|
|
7286
7356
|
}
|
|
7287
7357
|
} catch (e) {
|
|
7288
7358
|
const msg = e.message ?? "";
|
|
7289
|
-
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled")) {
|
|
7359
|
+
if (msg.includes("Swap execution failed") || msg.includes("Swap execution cancelled") || msg.includes("Swap refunded") || msg.startsWith("Swap failed") || msg.toLowerCase().includes("cancelled") || msg.toLowerCase().includes("refunded")) {
|
|
7290
7360
|
throw e;
|
|
7291
7361
|
}
|
|
7292
7362
|
}
|
|
@@ -7311,7 +7381,7 @@ async function swapUtxo(params, options) {
|
|
|
7311
7381
|
useChainForMerkle,
|
|
7312
7382
|
relayerFee = BigInt(0),
|
|
7313
7383
|
relayer,
|
|
7314
|
-
relayUrl,
|
|
7384
|
+
relayUrl: relayUrlOverride,
|
|
7315
7385
|
riskQuoteUrl,
|
|
7316
7386
|
maxRootRetries = 40,
|
|
7317
7387
|
// Increased to handle prolonged relay sync recovery under high concurrency
|
|
@@ -7320,6 +7390,7 @@ async function swapUtxo(params, options) {
|
|
|
7320
7390
|
useUniqueNullifiers,
|
|
7321
7391
|
useChainRootForProof = true
|
|
7322
7392
|
} = options;
|
|
7393
|
+
const relayUrl = resolveRelayUrl(relayUrlOverride);
|
|
7323
7394
|
const useUniqueNullifiersEffective = useUniqueNullifiers ?? shouldDefaultUseUniqueNullifiers(connection);
|
|
7324
7395
|
if (inputUtxos.length === 0) {
|
|
7325
7396
|
throw new Error("At least one input UTXO required");
|
|
@@ -7374,6 +7445,7 @@ async function swapUtxo(params, options) {
|
|
|
7374
7445
|
const useRelayMerkleByDefault = shouldUseRelayMerkleByDefault(connection);
|
|
7375
7446
|
const relayMintKey = swapPoolMint.toBase58();
|
|
7376
7447
|
let relayTreeDisabledForMint = _relayMerkleDisabledMints.has(relayMintKey) || !useRelayMerkleByDefault;
|
|
7448
|
+
const hasCachedTree = !!cachedMerkleTree && cachedMerkleTree.length > 0;
|
|
7377
7449
|
const requiredRelayIndex = paddedInputs.reduce((maxIndex, utxo) => {
|
|
7378
7450
|
if (utxo.amount === BigInt(0) || utxo.index === void 0 || utxo.index < 0) {
|
|
7379
7451
|
return maxIndex;
|
|
@@ -7390,7 +7462,7 @@ async function swapUtxo(params, options) {
|
|
|
7390
7462
|
merkleState = await readMerkleTreeState(connection, pdas.merkleTree, forceRefresh, relayUrl, useChainRootForProof, swapPoolMint);
|
|
7391
7463
|
}
|
|
7392
7464
|
const relaySyncTargetIndex = merkleState && merkleState.nextIndex > 0 ? Math.max(requiredRelayIndex, merkleState.nextIndex - 1) : requiredRelayIndex;
|
|
7393
|
-
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree)) {
|
|
7465
|
+
if (needsTreeForProof && relayTreeDisabledForMint && relayUrl && !forceChainIndexing && (forceRefresh || !merkleTree) && !hasCachedTree) {
|
|
7394
7466
|
if (!_relayMerkleFallbackNotifiedMints.has(relayMintKey)) {
|
|
7395
7467
|
onProgress?.(`Using on-chain proof mode for ${relayMintKey} in this environment.`);
|
|
7396
7468
|
_relayMerkleFallbackNotifiedMints.add(relayMintKey);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloak.dev/sdk",
|
|
3
3
|
"description": "TypeScript SDK for Cloak",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",
|
|
22
22
|
"test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
23
23
|
"test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
|
|
24
|
+
"prepare": "npm run build",
|
|
24
25
|
"prepublishOnly": "npm run build",
|
|
25
26
|
"example:fast-send": "tsx examples/fast-send.ts",
|
|
26
27
|
"example:fast-usdc-send": "tsx examples/fast-usdc-send.ts",
|