> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloak.ag/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Minimal mainnet setup with SOL send plus full and partial withdrawals

Use this page when you want the smallest possible end-to-end Cloak integration.

This snippet covers:

* shielded SOL deposit
* full withdrawal (send)
* partial withdrawal (keep change private)

```typescript theme={null}
import {
  CLOAK_PROGRAM_ID,
  NATIVE_SOL_MINT,
  createUtxo,
  createZeroUtxo,
  fullWithdraw,
  generateUtxoKeypair,
  partialWithdraw,
  transact,
} from "@cloak.dev/sdk";
import { Connection, Keypair } from "@solana/web3.js";

const connection = new Connection(
  "https://api.mainnet-beta.solana.com",
  "confirmed",
);
const signer = Keypair.fromSecretKey(/* Uint8Array secret key */);

const amount = 1_000_000_000n; // 1 SOL
const owner = await generateUtxoKeypair();
const depositOutput = await createUtxo(amount, owner, NATIVE_SOL_MINT);

const deposited = await transact(
  {
    inputUtxos: [await createZeroUtxo(NATIVE_SOL_MINT)],
    outputUtxos: [depositOutput],
    externalAmount: amount,
    depositor: signer.publicKey,
  },
  {
    connection,
    programId: CLOAK_PROGRAM_ID,
    depositorKeypair: signer,
    walletPublicKey: signer.publicKey,
  },
);

const recipient = Keypair.generate().publicKey;

// Full withdrawal: sends all spendable value externally.
await fullWithdraw(deposited.outputUtxos, recipient, {
  connection,
  programId: CLOAK_PROGRAM_ID,
  depositorKeypair: signer,
  walletPublicKey: signer.publicKey,
  cachedMerkleTree: deposited.merkleTree,
});

// OR partial withdrawal: withdraw a portion, keep private change in shielded state.
// await partialWithdraw(deposited.outputUtxos, recipient, 200_000_000n, {
//   connection,
//   programId: CLOAK_PROGRAM_ID,
//   depositorKeypair: signer,
//   walletPublicKey: signer.publicKey,
//   cachedMerkleTree: deposited.merkleTree,
// });
```

## One-file CLI contract (recommended for one-shot scripts)

For minimal script generation, keep this exact interface:

* file: `send-sol-private.ts`
* command: `npx tsx send-sol-private.ts <recipientPubkey> <lamports>`
* env vars: `SOLANA_RPC_URL`, `KEYPAIR_PATH`

Guardrails:

* keep tx amounts as `bigint`
* use `KEYPAIR_PATH` (file-based keypair), not raw private key env vars
* do not parse SOL decimals with float math (`parseFloat`, `AMOUNT_SOL`)
* read recipient/amount from `process.argv` (`<recipientPubkey> <lamports>`), not `RECIPIENT_ADDRESS`/`SEND_LAMPORTS` env vars
* keep `programId` fixed to `CLOAK_PROGRAM_ID` internally
* rely on SDK stale-root retries for standard flows
* call `process.exit(0)` on success and `process.exit(1)` on failure

## Mainnet smoke test (keypair bytes)

Use this when you want a first real send with explicit runtime values.

```bash theme={null}
export SOLANA_RPC_URL="https://api.mainnet-beta.solana.com"

# Must be an absolute path. Do not rely on `~` expansion inside env files.
export KEYPAIR_PATH="/Users/you/.config/solana/id.json"
```

Sanity-check before running:

```bash theme={null}
solana-keygen pubkey "$KEYPAIR_PATH"
solana balance "$(solana-keygen pubkey "$KEYPAIR_PATH")" --url "$SOLANA_RPC_URL"
```

Run your script entrypoint that wraps the snippet above:

```bash theme={null}
npx tsx send.ts "<recipient-wallet-pubkey>" "50000000"
```

## Funding and net amount

For SOL withdraw/send paths:

* `gross = abs(externalAmount)`
* `fee = 5_000_000 + floor(gross * 3 / 1000)`
* `net = gross - fee`

Worked example (`gross = 50_000_000`, i.e. `0.05 SOL`):

* fee = `5_150_000` lamports (`0.00515 SOL`)
* net = `44_850_000` lamports (`0.04485 SOL`)

Recommended first-run sender balance for this smoke test: `0.07 SOL` or higher.

Next: [Code Examples](/sdk/examples)
