@cloak.dev/sdk 0.1.6 → 0.1.8

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 CHANGED
@@ -4,12 +4,12 @@ TypeScript SDK for the Cloak Protocol - Private transactions on Solana using zer
4
4
 
5
5
  ## Features
6
6
 
7
- - 🔒 **Private Transfers**: Shield, send, and reclaim SOL or SPL tokens via the UTXO model and zero-knowledge proofs
8
- - 🔁 **Shield-to-shield**: Move funds privately between UTXOs (`transfer`) without ever de-shielding
9
- - 💱 **Token Swaps**: Swap shielded SOL for SPL tokens via Jupiter (`swapUtxo`) — SOL → USDC, BRZ, etc.
10
- - 🔐 **Type-Safe**: Full TypeScript types; the `getConfig()` snapshot is structurally narrower than the constructor input so secrets cannot be re-exposed by accident
11
- - 🌐 **Cross-Platform**: Browser (wallet adapter) and Node.js (`Keypair`) modes
12
- - ⚡ **Functional API**: `transact` / `transfer` / `partialWithdraw` / `fullWithdraw` / `swapUtxo` — pass connection + program + relay + signer per call
7
+ - 🔒 **Private Transfers**: Send SOL privately using zero-knowledge proofs
8
+ - 👥 **Multi-Recipient**: Support for 1-5 recipients in a single transaction
9
+ - 💱 **Token Swaps**: Swap SOL for SPL tokens privately (SOL → USDC, etc.)
10
+ - 🔐 **Type-Safe**: Full TypeScript support with comprehensive types
11
+ - 🌐 **Cross-Platform**: Works in browser (React, Next.js) and Node.js
12
+ - ⚡ **Simple API**: Easy-to-use high-level client with wallet adapter support
13
13
 
14
14
  ## Installation
15
15
 
@@ -155,215 +155,146 @@ npm run test:examples
155
155
  ### Node.js (with Keypair)
156
156
 
157
157
  ```typescript
158
- import {
159
- CLOAK_PROGRAM_ID,
160
- NATIVE_SOL_MINT,
161
- createUtxo,
162
- createZeroUtxo,
163
- fullWithdraw,
164
- generateUtxoKeypair,
165
- transact,
166
- } from "@cloak.dev/sdk";
158
+ import { CloakSDK } from "@cloak.dev/sdk";
167
159
  import { Connection, Keypair, PublicKey } from "@solana/web3.js";
168
160
 
169
- const connection = new Connection("https://api.mainnet-beta.solana.com");
170
- const signer = Keypair.fromSecretKey(/* your secret key */);
161
+ // Initialize connection and keypair
162
+ const connection = new Connection("https://api.devnet.solana.com");
163
+ const keypair = Keypair.fromSecretKey(/* your secret key */);
171
164
 
172
- // Generate a UTXO keypair (owner of the shielded balance)
173
- const owner = await generateUtxoKeypair();
174
-
175
- // Build a 0.01 SOL output UTXO and shield it
176
- const amountLamports = 10_000_000n;
177
- const output = await createUtxo(amountLamports, owner, NATIVE_SOL_MINT);
165
+ // Initialize SDK
166
+ const sdk = new CloakSDK({
167
+ keypairBytes: keypair.secretKey,
168
+ network: "devnet",
169
+ });
178
170
 
179
- const deposited = await transact(
180
- {
181
- inputUtxos: [await createZeroUtxo(NATIVE_SOL_MINT), await createZeroUtxo(NATIVE_SOL_MINT)],
182
- outputUtxos: [output, await createZeroUtxo(NATIVE_SOL_MINT)],
183
- externalAmount: amountLamports, // positive = deposit
184
- depositor: signer.publicKey,
185
- },
186
- {
187
- connection,
188
- programId: CLOAK_PROGRAM_ID,
189
- relayUrl: "https://api.cloak.ag",
190
- depositorKeypair: signer,
191
- },
192
- );
193
- console.log("Deposit signature:", deposited.signature);
171
+ // Deposit SOL into the privacy pool
172
+ const depositResult = await sdk.deposit(connection, 100_000_000); // 0.1 SOL
173
+ console.log("Deposited! Leaf index:", depositResult.leafIndex);
194
174
 
195
- // Reclaim the full balance to a public address
196
- const recipient = new PublicKey("RECIPIENT_ADDRESS");
197
- const withdrawn = await fullWithdraw(deposited.outputUtxos, recipient, {
175
+ // Withdraw to a recipient
176
+ const withdrawResult = await sdk.withdraw(
198
177
  connection,
199
- programId: CLOAK_PROGRAM_ID,
200
- relayUrl: "https://api.cloak.ag",
201
- depositorKeypair: signer,
202
- cachedMerkleTree: deposited.merkleTree,
203
- });
204
- console.log("Withdraw signature:", withdrawn.signature);
178
+ depositResult.note,
179
+ new PublicKey("RECIPIENT_ADDRESS"),
180
+ { withdrawAll: true }
181
+ );
182
+ console.log("Withdrawn! TX:", withdrawResult.signature);
205
183
  ```
206
184
 
207
185
  ### React/Next.js (with Wallet Adapter)
208
186
 
209
187
  ```typescript
210
- import {
211
- CLOAK_PROGRAM_ID,
212
- NATIVE_SOL_MINT,
213
- createUtxo,
214
- createZeroUtxo,
215
- generateUtxoKeypair,
216
- transact,
217
- } from "@cloak.dev/sdk";
218
- import { useConnection, useWallet } from "@solana/wallet-adapter-react";
219
- import { useCallback } from "react";
188
+ import { CloakSDK } from "@cloak.dev/sdk";
189
+ import { useWallet, useConnection } from "@solana/wallet-adapter-react";
190
+ import { PublicKey } from "@solana/web3.js";
220
191
 
221
- export function DepositButton() {
192
+ function PrivateTransfer() {
193
+ const { publicKey, signTransaction, sendTransaction } = useWallet();
222
194
  const { connection } = useConnection();
223
- const wallet = useWallet();
224
195
 
225
- const onClick = useCallback(async () => {
226
- if (!wallet.publicKey || !wallet.signTransaction) return;
227
-
228
- const owner = await generateUtxoKeypair();
229
- const amount = 10_000_000n; // 0.01 SOL — SDK-enforced minimum
230
- const output = await createUtxo(amount, owner, NATIVE_SOL_MINT);
231
-
232
- const result = await transact(
233
- {
234
- inputUtxos: [await createZeroUtxo(NATIVE_SOL_MINT), await createZeroUtxo(NATIVE_SOL_MINT)],
235
- outputUtxos: [output, await createZeroUtxo(NATIVE_SOL_MINT)],
236
- externalAmount: amount,
237
- depositor: wallet.publicKey,
238
- },
239
- {
240
- connection,
241
- programId: CLOAK_PROGRAM_ID,
242
- relayUrl: "https://api.cloak.ag",
243
- wallet: {
244
- publicKey: wallet.publicKey,
245
- signTransaction: wallet.signTransaction,
246
- },
196
+ // Initialize SDK with wallet adapter
197
+ const sdk = useMemo(() => {
198
+ if (!publicKey) return null;
199
+ return new CloakSDK({
200
+ network: "devnet",
201
+ wallet: {
202
+ publicKey,
203
+ signTransaction: (tx) => signTransaction!(tx),
204
+ sendTransaction: (tx, conn, opts) => sendTransaction(tx, conn, opts),
247
205
  },
248
- );
249
- console.log("Deposited:", result.signature);
250
- }, [connection, wallet]);
206
+ });
207
+ }, [publicKey, signTransaction, sendTransaction]);
251
208
 
252
- return <button onClick={onClick}>Deposit 0.01 SOL</button>;
209
+ const handleDeposit = async () => {
210
+ const result = await sdk.deposit(connection, 100_000_000);
211
+ console.log("Deposited!", result.signature);
212
+ };
213
+
214
+ return <button onClick={handleDeposit}>Deposit 0.1 SOL</button>;
253
215
  }
254
216
  ```
255
217
 
256
- The `CloakSDK` class is kept as a thin config + read-only chain helper
257
- (`getPublicKey`, `getCurrentRoot`, `getMerkleProof`, `getTransactionStatus`,
258
- `importWalletKeys`, `exportWalletKeys`, `getConfig`). All transaction-emitting
259
- calls use the standalone helpers above.
218
+ ## Core Methods
260
219
 
261
- ## Core Functions
220
+ ### Deposit
262
221
 
263
- ### Deposit (`transact` with positive `externalAmount`)
222
+ Deposit SOL into the privacy pool:
264
223
 
265
224
  ```typescript
266
- const result = await transact(
267
- {
268
- inputUtxos: [await createZeroUtxo(), await createZeroUtxo()],
269
- outputUtxos: [outputUtxo, await createZeroUtxo()],
270
- externalAmount: 10_000_000n, // positive = deposit
271
- depositor: signer.publicKey,
272
- },
273
- { connection, programId: CLOAK_PROGRAM_ID, relayUrl: "https://api.cloak.ag", depositorKeypair: signer },
274
- );
275
- console.log("Leaf index:", result.commitmentIndices[0]);
276
- console.log("Output UTXO:", result.outputUtxos[0]);
225
+ const result = await sdk.deposit(connection, 100_000_000); // 0.1 SOL
226
+ // Save the note securely - you need it to withdraw!
227
+ console.log(result.note);
277
228
  ```
278
229
 
279
230
  ### Withdraw
280
231
 
281
- ```typescript
282
- import { fullWithdraw, partialWithdraw } from "@cloak.dev/sdk";
232
+ Withdraw to a single recipient:
283
233
 
284
- // Reclaim everything in one or more input UTXOs to a public address.
285
- const result = await fullWithdraw(myUtxos, recipientPublicKey, {
286
- connection,
287
- programId: CLOAK_PROGRAM_ID,
288
- relayUrl: "https://api.cloak.ag",
289
- depositorKeypair: signer,
290
- });
291
-
292
- // Or withdraw a portion and keep the change shielded.
293
- const partial = await partialWithdraw(myUtxos, recipientPublicKey, 5_000_000n, {
234
+ ```typescript
235
+ const result = await sdk.withdraw(
294
236
  connection,
295
- programId: CLOAK_PROGRAM_ID,
296
- relayUrl: "https://api.cloak.ag",
297
- depositorKeypair: signer,
298
- });
237
+ note,
238
+ recipientPublicKey,
239
+ { withdrawAll: true }
240
+ );
299
241
  ```
300
242
 
301
- ### Shield-to-shield Transfer
243
+ ### Send to Multiple Recipients
302
244
 
303
- ```typescript
304
- import { transfer } from "@cloak.dev/sdk";
245
+ Send to up to 5 recipients:
305
246
 
306
- const result = await transfer(myUtxos, recipientUtxoPublicKey, amountLamports, {
307
- connection,
308
- programId: CLOAK_PROGRAM_ID,
309
- relayUrl: "https://api.cloak.ag",
310
- depositorKeypair: signer,
311
- });
247
+ ```typescript
248
+ const result = await sdk.send(connection, note, [
249
+ { recipient: addr1, amount: 50_000_000 },
250
+ { recipient: addr2, amount: 47_000_000 },
251
+ ]);
312
252
  ```
313
253
 
314
- ### Swap (SOL → SPL token)
254
+ ### Swap
255
+
256
+ Swap SOL for SPL tokens:
315
257
 
316
258
  ```typescript
317
- import { swapUtxo } from "@cloak.dev/sdk";
318
-
319
- const result = await swapUtxo(
320
- {
321
- inputUtxos: myUtxos,
322
- swapAmount: 10_000_000n,
323
- outputMint: new PublicKey("TOKEN_MINT_ADDRESS"),
324
- recipientAta: recipientTokenAccount,
325
- minOutputAmount: 1_000_000n,
326
- },
327
- {
328
- connection,
329
- programId: CLOAK_PROGRAM_ID,
330
- relayUrl: "https://api.cloak.ag",
331
- depositorKeypair: signer,
332
- },
333
- );
259
+ const result = await sdk.swap(connection, note, recipientPublicKey, {
260
+ outputMint: "TOKEN_MINT_ADDRESS",
261
+ minOutputAmount: 1000000,
262
+ });
334
263
  ```
335
264
 
336
265
  ## Fee Structure
337
266
 
338
- - **Fixed Fee**: 0.005 SOL (5,000,000 lamports) on withdraw
339
- - **Variable Fee**: 0.3% of withdrawn amount
267
+ - **Fixed Fee**: 0.005 SOL (5,000,000 lamports)
268
+ - **Variable Fee**: 0.3% of deposit amount
340
269
 
341
- Use `getDistributableAmount()` to calculate the amount a recipient receives after fees:
270
+ Use `getDistributableAmount()` to calculate the amount after fees:
342
271
 
343
272
  ```typescript
344
273
  import { getDistributableAmount } from "@cloak.dev/sdk";
345
274
 
346
- const withdrawing = 100_000_000; // 0.1 SOL
347
- const recipientReceives = getDistributableAmount(withdrawing); // ~94,700,000 lamports
275
+ const deposited = 100_000_000; // 0.1 SOL
276
+ const afterFees = getDistributableAmount(deposited); // ~94,700,000 lamports
348
277
  ```
349
278
 
350
- ## UTXOs
279
+ ## Notes
351
280
 
352
- A **UTXO** is a cryptographic commitment over `(amount, ownerPubkey, blinding, mintAddress)`. Each `transact` call consumes up to 2 input UTXOs and produces up to 2 outputs:
281
+ A **Cloak Note** is a cryptographic commitment representing a private amount of SOL:
353
282
 
354
283
  ```typescript
355
- interface Utxo {
356
- amount: bigint; // lamports for SOL, token units for SPL
357
- keypair: UtxoKeypair; // { privateKey, publicKey } — bigints
358
- blinding: bigint; // randomness
359
- mintAddress: PublicKey; // NATIVE_SOL_MINT for SOL
360
- index?: number; // leaf index in the Merkle tree (set after the UTXO is in-tree)
361
- commitment?: bigint;
362
- nullifier?: bigint;
284
+ interface CloakNote {
285
+ version: string;
286
+ amount: number; // Amount in lamports
287
+ commitment: string; // Commitment hash
288
+ sk_spend: string; // Spending key (keep secret!)
289
+ r: string; // Randomness
290
+ timestamp: number;
291
+ network: Network;
292
+ leafIndex?: number; // Set after deposit
293
+ depositSignature?: string;
363
294
  }
364
295
  ```
365
296
 
366
- **⚠️ Important**: persist the spend `privateKey`, `blinding`, `amount`, `index`, and `mintAddress` for every output UTXO — those are the only inputs you need to spend it later. The SDK ships `LocalStorageAdapter` for browser wallet keys; UTXO persistence is the consumer's responsibility (see `lib/utxo-manager.ts` patterns in cloak-ag/web for a reference implementation).
297
+ **⚠️ Important**: Save your notes securely! Without the note, you cannot withdraw your funds.
367
298
 
368
299
  ## Compliance Chain Scanning
369
300
 
@@ -403,31 +334,13 @@ sequenceDiagram
403
334
  ## Error Handling
404
335
 
405
336
  ```typescript
406
- import {
407
- CloakError,
408
- UtxoAlreadySpentError,
409
- RootNotFoundError,
410
- classifyRelayError,
411
- fullWithdraw,
412
- CLOAK_PROGRAM_ID,
413
- } from "@cloak.dev/sdk";
337
+ import { CloakError } from "@cloak.dev/sdk";
414
338
 
415
339
  try {
416
- await fullWithdraw(myUtxos, recipient, {
417
- connection,
418
- programId: CLOAK_PROGRAM_ID,
419
- relayUrl: "https://api.cloak.ag",
420
- depositorKeypair: signer,
421
- });
340
+ await sdk.withdraw(connection, note, recipient);
422
341
  } catch (error) {
423
- if (error instanceof UtxoAlreadySpentError) {
424
- // Drop the spent UTXO from local storage; the structured error
425
- // carries which nullifiers collided.
426
- console.log("Spent nullifiers:", error.nullifiers);
427
- } else if (error instanceof RootNotFoundError) {
428
- // Relay/chain root mismatch; retry against a fresh tree.
429
- } else if (error instanceof CloakError) {
430
- console.log("Category:", error.category); // 'wallet' | 'network' | 'prover' | 'relay' | 'validation' | 'environment' | 'service' | 'indexer'
342
+ if (error instanceof CloakError) {
343
+ console.log("Category:", error.category); // 'wallet', 'network', 'prover', etc.
431
344
  console.log("Retryable:", error.retryable);
432
345
  }
433
346
  }