@cloak.dev/sdk 0.1.1 → 0.1.3
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 +102 -13
- package/dist/index.cjs +56 -38
- package/dist/index.js +56 -38
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @cloak.
|
|
1
|
+
# @cloak.dev/sdk
|
|
2
2
|
|
|
3
3
|
TypeScript SDK for the Cloak Protocol - Private transactions on Solana using zero-knowledge proofs.
|
|
4
4
|
|
|
@@ -14,11 +14,11 @@ TypeScript SDK for the Cloak Protocol - Private transactions on Solana using zer
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npm install @cloak.
|
|
17
|
+
npm install @cloak.dev/sdk @solana/web3.js
|
|
18
18
|
# or
|
|
19
|
-
yarn add @cloak.
|
|
19
|
+
yarn add @cloak.dev/sdk @solana/web3.js
|
|
20
20
|
# or
|
|
21
|
-
pnpm add @cloak.
|
|
21
|
+
pnpm add @cloak.dev/sdk @solana/web3.js
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
**Note**: For swap functionality, you'll also need `@solana/spl-token`:
|
|
@@ -28,12 +28,101 @@ npm install @solana/spl-token
|
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### SDK Defaults (Recommended)
|
|
32
32
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
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:
|
|
121
|
+
|
|
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
|
|
|
@@ -66,7 +155,7 @@ npm run test:examples
|
|
|
66
155
|
### Node.js (with Keypair)
|
|
67
156
|
|
|
68
157
|
```typescript
|
|
69
|
-
import { CloakSDK } from "@cloak.
|
|
158
|
+
import { CloakSDK } from "@cloak.dev/sdk";
|
|
70
159
|
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
|
71
160
|
|
|
72
161
|
// Initialize connection and keypair
|
|
@@ -96,7 +185,7 @@ console.log("Withdrawn! TX:", withdrawResult.signature);
|
|
|
96
185
|
### React/Next.js (with Wallet Adapter)
|
|
97
186
|
|
|
98
187
|
```typescript
|
|
99
|
-
import { CloakSDK } from "@cloak.
|
|
188
|
+
import { CloakSDK } from "@cloak.dev/sdk";
|
|
100
189
|
import { useWallet, useConnection } from "@solana/wallet-adapter-react";
|
|
101
190
|
import { PublicKey } from "@solana/web3.js";
|
|
102
191
|
|
|
@@ -181,7 +270,7 @@ const result = await sdk.swap(connection, note, recipientPublicKey, {
|
|
|
181
270
|
Use `getDistributableAmount()` to calculate the amount after fees:
|
|
182
271
|
|
|
183
272
|
```typescript
|
|
184
|
-
import { getDistributableAmount } from "@cloak.
|
|
273
|
+
import { getDistributableAmount } from "@cloak.dev/sdk";
|
|
185
274
|
|
|
186
275
|
const deposited = 100_000_000; // 0.1 SOL
|
|
187
276
|
const afterFees = getDistributableAmount(deposited); // ~94,700,000 lamports
|
|
@@ -245,7 +334,7 @@ sequenceDiagram
|
|
|
245
334
|
## Error Handling
|
|
246
335
|
|
|
247
336
|
```typescript
|
|
248
|
-
import { CloakError } from "@cloak.
|
|
337
|
+
import { CloakError } from "@cloak.dev/sdk";
|
|
249
338
|
|
|
250
339
|
try {
|
|
251
340
|
await sdk.withdraw(connection, note, recipient);
|
package/dist/index.cjs
CHANGED
|
@@ -6083,6 +6083,7 @@ function collectLookupCandidatesFromInstructions(instructions, payer, existingAl
|
|
|
6083
6083
|
}
|
|
6084
6084
|
async function createEphemeralALT(connection, depositor, onProgress, additionalAddresses = []) {
|
|
6085
6085
|
const MAX_ALT_ADDRESSES = 20;
|
|
6086
|
+
const MAX_ALT_CREATE_RETRIES = 3;
|
|
6086
6087
|
const altAddresses = dedupePubkeys([
|
|
6087
6088
|
...getCommonALTAddresses(),
|
|
6088
6089
|
...additionalAddresses
|
|
@@ -6093,46 +6094,59 @@ async function createEphemeralALT(connection, depositor, onProgress, additionalA
|
|
|
6093
6094
|
`ALT address set truncated (${addressesForCreate.length}/${altAddresses.length}); packet savings may be limited.`
|
|
6094
6095
|
);
|
|
6095
6096
|
}
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6097
|
+
for (let altAttempt = 0; altAttempt < MAX_ALT_CREATE_RETRIES; altAttempt++) {
|
|
6098
|
+
try {
|
|
6099
|
+
const slot = await connection.getSlot("finalized");
|
|
6100
|
+
const [createIx, altAddress] = import_web37.AddressLookupTableProgram.createLookupTable({
|
|
6101
|
+
authority: depositor.publicKey,
|
|
6102
|
+
payer: depositor.publicKey,
|
|
6103
|
+
recentSlot: slot
|
|
6104
|
+
});
|
|
6105
|
+
const extendIx = import_web37.AddressLookupTableProgram.extendLookupTable({
|
|
6106
|
+
payer: depositor.publicKey,
|
|
6107
|
+
authority: depositor.publicKey,
|
|
6108
|
+
lookupTable: altAddress,
|
|
6109
|
+
addresses: addressesForCreate
|
|
6110
|
+
});
|
|
6111
|
+
const tx = new import_web37.Transaction().add(createIx).add(extendIx);
|
|
6112
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
6113
|
+
tx.recentBlockhash = blockhash;
|
|
6114
|
+
tx.feePayer = depositor.publicKey;
|
|
6115
|
+
if (depositor.keypair) {
|
|
6116
|
+
await (0, import_web37.sendAndConfirmTransaction)(connection, tx, [depositor.keypair], { commitment: "confirmed" });
|
|
6117
|
+
} else if (depositor.signTransaction) {
|
|
6118
|
+
const signedTx = await depositor.signTransaction(tx);
|
|
6119
|
+
const sig = await connection.sendRawTransaction(signedTx.serialize());
|
|
6120
|
+
const latestBH = await connection.getLatestBlockhash();
|
|
6121
|
+
await connection.confirmTransaction({ signature: sig, blockhash: latestBH.blockhash, lastValidBlockHeight: latestBH.lastValidBlockHeight }, "confirmed");
|
|
6122
|
+
} else {
|
|
6123
|
+
throw new Error("Cannot create ALT: no signing method provided");
|
|
6124
|
+
}
|
|
6125
|
+
for (let i = 0; i < 30; i++) {
|
|
6126
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
6127
|
+
const result = await connection.getAddressLookupTable(altAddress);
|
|
6128
|
+
if (result.value && result.value.isActive()) {
|
|
6129
|
+
onProgress?.(`ALT created and active: ${altAddress.toBase58()}`);
|
|
6130
|
+
return [result.value];
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
const finalResult = await connection.getAddressLookupTable(altAddress);
|
|
6134
|
+
if (finalResult.value) {
|
|
6135
|
+
onProgress?.("ALT created (activation pending)");
|
|
6136
|
+
return [finalResult.value];
|
|
6137
|
+
}
|
|
6138
|
+
throw new Error("Failed to create ALT: not active after 15 seconds");
|
|
6139
|
+
} catch (err) {
|
|
6140
|
+
const msg = err?.message ?? String(err);
|
|
6141
|
+
if (msg.includes("not a recent slot") && altAttempt < MAX_ALT_CREATE_RETRIES - 1) {
|
|
6142
|
+
onProgress?.(`ALT creation failed (stale slot), retrying (${altAttempt + 2}/${MAX_ALT_CREATE_RETRIES})...`);
|
|
6143
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
6144
|
+
continue;
|
|
6145
|
+
}
|
|
6146
|
+
throw err;
|
|
6128
6147
|
}
|
|
6129
6148
|
}
|
|
6130
|
-
|
|
6131
|
-
if (finalResult.value) {
|
|
6132
|
-
onProgress?.("ALT created (activation pending)");
|
|
6133
|
-
return [finalResult.value];
|
|
6134
|
-
}
|
|
6135
|
-
throw new Error("Failed to create ALT: not active after 15 seconds");
|
|
6149
|
+
throw new Error(`Failed to create ALT after ${MAX_ALT_CREATE_RETRIES} retries`);
|
|
6136
6150
|
}
|
|
6137
6151
|
async function submitTransactionDirect(connection, programId, depositor, proofBytes, publicInputsBytes, nullifiers, mint, recipient, riskOracleQueue, riskQuoteUrl, getRiskQuoteInstruction, onProgress, addressLookupTableAccounts, rangeApiKey, encryptedNoteBytes, relayUrl, altAddresses) {
|
|
6138
6152
|
onProgress?.("Building transaction...");
|
|
@@ -6163,6 +6177,10 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6163
6177
|
onProgress?.("Creating address lookup table (chain notes require v0 tx to fit)...");
|
|
6164
6178
|
addressLookupTableAccounts = await createEphemeralALT(connection, depositor, onProgress);
|
|
6165
6179
|
}
|
|
6180
|
+
if (isDeposit && isSplPool && (!addressLookupTableAccounts || addressLookupTableAccounts.length === 0)) {
|
|
6181
|
+
onProgress?.("Creating address lookup table (SPL deposit requires v0 tx)...");
|
|
6182
|
+
addressLookupTableAccounts = await createEphemeralALT(connection, depositor, onProgress);
|
|
6183
|
+
}
|
|
6166
6184
|
const publicAmountBytes = publicInputsBytes.slice(32, 40);
|
|
6167
6185
|
const publicAmountBuffer = Buffer.from(publicAmountBytes);
|
|
6168
6186
|
const publicAmount = publicAmountBuffer.readBigInt64LE(0);
|
package/dist/index.js
CHANGED
|
@@ -5636,6 +5636,7 @@ function collectLookupCandidatesFromInstructions(instructions, payer, existingAl
|
|
|
5636
5636
|
}
|
|
5637
5637
|
async function createEphemeralALT(connection, depositor, onProgress, additionalAddresses = []) {
|
|
5638
5638
|
const MAX_ALT_ADDRESSES = 20;
|
|
5639
|
+
const MAX_ALT_CREATE_RETRIES = 3;
|
|
5639
5640
|
const altAddresses = dedupePubkeys([
|
|
5640
5641
|
...getCommonALTAddresses(),
|
|
5641
5642
|
...additionalAddresses
|
|
@@ -5646,46 +5647,59 @@ async function createEphemeralALT(connection, depositor, onProgress, additionalA
|
|
|
5646
5647
|
`ALT address set truncated (${addressesForCreate.length}/${altAddresses.length}); packet savings may be limited.`
|
|
5647
5648
|
);
|
|
5648
5649
|
}
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5650
|
+
for (let altAttempt = 0; altAttempt < MAX_ALT_CREATE_RETRIES; altAttempt++) {
|
|
5651
|
+
try {
|
|
5652
|
+
const slot = await connection.getSlot("finalized");
|
|
5653
|
+
const [createIx, altAddress] = AddressLookupTableProgram.createLookupTable({
|
|
5654
|
+
authority: depositor.publicKey,
|
|
5655
|
+
payer: depositor.publicKey,
|
|
5656
|
+
recentSlot: slot
|
|
5657
|
+
});
|
|
5658
|
+
const extendIx = AddressLookupTableProgram.extendLookupTable({
|
|
5659
|
+
payer: depositor.publicKey,
|
|
5660
|
+
authority: depositor.publicKey,
|
|
5661
|
+
lookupTable: altAddress,
|
|
5662
|
+
addresses: addressesForCreate
|
|
5663
|
+
});
|
|
5664
|
+
const tx = new Transaction3().add(createIx).add(extendIx);
|
|
5665
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
5666
|
+
tx.recentBlockhash = blockhash;
|
|
5667
|
+
tx.feePayer = depositor.publicKey;
|
|
5668
|
+
if (depositor.keypair) {
|
|
5669
|
+
await sendAndConfirmTransaction(connection, tx, [depositor.keypair], { commitment: "confirmed" });
|
|
5670
|
+
} else if (depositor.signTransaction) {
|
|
5671
|
+
const signedTx = await depositor.signTransaction(tx);
|
|
5672
|
+
const sig = await connection.sendRawTransaction(signedTx.serialize());
|
|
5673
|
+
const latestBH = await connection.getLatestBlockhash();
|
|
5674
|
+
await connection.confirmTransaction({ signature: sig, blockhash: latestBH.blockhash, lastValidBlockHeight: latestBH.lastValidBlockHeight }, "confirmed");
|
|
5675
|
+
} else {
|
|
5676
|
+
throw new Error("Cannot create ALT: no signing method provided");
|
|
5677
|
+
}
|
|
5678
|
+
for (let i = 0; i < 30; i++) {
|
|
5679
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
5680
|
+
const result = await connection.getAddressLookupTable(altAddress);
|
|
5681
|
+
if (result.value && result.value.isActive()) {
|
|
5682
|
+
onProgress?.(`ALT created and active: ${altAddress.toBase58()}`);
|
|
5683
|
+
return [result.value];
|
|
5684
|
+
}
|
|
5685
|
+
}
|
|
5686
|
+
const finalResult = await connection.getAddressLookupTable(altAddress);
|
|
5687
|
+
if (finalResult.value) {
|
|
5688
|
+
onProgress?.("ALT created (activation pending)");
|
|
5689
|
+
return [finalResult.value];
|
|
5690
|
+
}
|
|
5691
|
+
throw new Error("Failed to create ALT: not active after 15 seconds");
|
|
5692
|
+
} catch (err) {
|
|
5693
|
+
const msg = err?.message ?? String(err);
|
|
5694
|
+
if (msg.includes("not a recent slot") && altAttempt < MAX_ALT_CREATE_RETRIES - 1) {
|
|
5695
|
+
onProgress?.(`ALT creation failed (stale slot), retrying (${altAttempt + 2}/${MAX_ALT_CREATE_RETRIES})...`);
|
|
5696
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
5697
|
+
continue;
|
|
5698
|
+
}
|
|
5699
|
+
throw err;
|
|
5681
5700
|
}
|
|
5682
5701
|
}
|
|
5683
|
-
|
|
5684
|
-
if (finalResult.value) {
|
|
5685
|
-
onProgress?.("ALT created (activation pending)");
|
|
5686
|
-
return [finalResult.value];
|
|
5687
|
-
}
|
|
5688
|
-
throw new Error("Failed to create ALT: not active after 15 seconds");
|
|
5702
|
+
throw new Error(`Failed to create ALT after ${MAX_ALT_CREATE_RETRIES} retries`);
|
|
5689
5703
|
}
|
|
5690
5704
|
async function submitTransactionDirect(connection, programId, depositor, proofBytes, publicInputsBytes, nullifiers, mint, recipient, riskOracleQueue, riskQuoteUrl, getRiskQuoteInstruction, onProgress, addressLookupTableAccounts, rangeApiKey, encryptedNoteBytes, relayUrl, altAddresses) {
|
|
5691
5705
|
onProgress?.("Building transaction...");
|
|
@@ -5716,6 +5730,10 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
5716
5730
|
onProgress?.("Creating address lookup table (chain notes require v0 tx to fit)...");
|
|
5717
5731
|
addressLookupTableAccounts = await createEphemeralALT(connection, depositor, onProgress);
|
|
5718
5732
|
}
|
|
5733
|
+
if (isDeposit && isSplPool && (!addressLookupTableAccounts || addressLookupTableAccounts.length === 0)) {
|
|
5734
|
+
onProgress?.("Creating address lookup table (SPL deposit requires v0 tx)...");
|
|
5735
|
+
addressLookupTableAccounts = await createEphemeralALT(connection, depositor, onProgress);
|
|
5736
|
+
}
|
|
5719
5737
|
const publicAmountBytes = publicInputsBytes.slice(32, 40);
|
|
5720
5738
|
const publicAmountBuffer = Buffer.from(publicAmountBytes);
|
|
5721
5739
|
const publicAmount = publicAmountBuffer.readBigInt64LE(0);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloak.dev/sdk",
|
|
3
|
-
"description": "TypeScript SDK
|
|
4
|
-
"version": "0.1.
|
|
3
|
+
"description": "Shield, send, and swap on Solana privately — TypeScript SDK with UTXO-based zero-knowledge transactions",
|
|
4
|
+
"version": "0.1.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|