# @umbra-privacy/sdk

TypeScript SDK for the Umbra privacy protocol on Solana. Provides encrypted balances, anonymous transfers via an on-chain mixer, and full compliance tooling.

## Installation

```bash
pnpm add @umbra-privacy/sdk
```

## Quick Start

```typescript
import {
  getInMemorySigner,
  getUmbraClient,
  getUserRegistrationFunction,
  getPublicBalanceToEncryptedBalanceDirectDepositorFunction,
  getEncryptedBalanceToPublicBalanceDirectWithdrawerFunction,
} from "@umbra-privacy/sdk";

// 1. Create a signer (use a wallet adapter in production)
const signer = await getInMemorySigner();

// 2. Create the Umbra client
const client = await getUmbraClient({
  signer,
  network: "mainnet",
  rpcUrl: "https://api.mainnet-beta.solana.com",
  rpcSubscriptionsUrl: "wss://api.mainnet-beta.solana.com",
  indexerApiEndpoint: "https://indexer.umbraprivacy.com",
});

// 3. Register (idempotent — safe to call even if already registered)
const register = getUserRegistrationFunction({ client });
await register({ confidential: true, anonymous: true });

// 4. Deposit tokens into an encrypted balance
const deposit = getPublicBalanceToEncryptedBalanceDirectDepositorFunction({ client });
const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
await deposit(signer.address, USDC, 1_000_000n);

// 5. Withdraw back to public wallet
const withdraw = getEncryptedBalanceToPublicBalanceDirectWithdrawerFunction({ client });
await withdraw(signer.address, USDC, 1_000_000n);
```

## Features

- **Encrypted Balances** — Deposit SPL / Token-2022 tokens into on-chain encrypted accounts. Withdraw back to a public wallet at any time.
- **Anonymous Transfers (Mixer)** — Create UTXOs in an Indexed Merkle Tree. Recipients claim with a Groth16 ZK proof, breaking any on-chain link to the sender.
- **Compliance** — Master viewing key hierarchy and X25519 compliance grants for authorized auditors.
- **Branded Types** — Runtime-validated `U64`, `U128`, `U256`, `Address`, `X25519PublicKey`, and other branded types prevent accidental misuse of cryptographic values.
- **Dual Module Format** — Ships ESM and CommonJS bundles with full TypeScript declarations.

## Entry Points

The SDK provides granular subpath exports to keep bundle sizes small:

- `@umbra-privacy/sdk` — Client construction, service factories, cryptographic operations
- `@umbra-privacy/sdk/crypto` — Rescue cipher, Poseidon hash, AES, key derivation, Fiat-Shamir challenges
- `@umbra-privacy/sdk/pda` — Program Derived Address derivation for all Umbra and Arcium accounts
- `@umbra-privacy/sdk/solana` — RPC providers, signers, transaction forwarding
- `@umbra-privacy/sdk/math` — BN254 and Curve25519 field arithmetic
- `@umbra-privacy/sdk/types` — Branded types and assertion functions (`assertU64`, `assertAddress`, etc.)
- `@umbra-privacy/sdk/interfaces` — Function type signatures for all factory functions and dependencies
- `@umbra-privacy/sdk/constants` — Network configs, program IDs, domain separators
- `@umbra-privacy/sdk/errors` — Error classes, stage enums, and type guards

## Service Factory Pattern

Every SDK operation follows the same two-step pattern:

```typescript
// Step 1: Build the function once (captures client config and optional dependency overrides)
const operation = getOperationFunction({ client }, optionalDeps);

// Step 2: Call it at runtime (can be called many times with different args)
const result = await operation(/* runtime arguments */);
```

The optional `deps` argument accepts injectable overrides for RPC providers, key generators, and ZK provers — useful for unit testing or custom infrastructure.

## Available Services

### Token Flow (Source → Destination → Action)

- **Direct Deposit** — `getPublicBalanceToEncryptedBalanceDirectDepositorFunction` — Move tokens from public wallet into encrypted balance
- **Direct Withdraw** — `getEncryptedBalanceToPublicBalanceDirectWithdrawerFunction` — Move tokens from encrypted balance to public wallet

### UTXO Creation (Stealth Pool Deposits)

- `getPublicBalanceToSelfClaimableUtxoCreatorFunction` — Shield your own public tokens into the mixer
- `getEncryptedBalanceToSelfClaimableUtxoCreatorFunction` — Shield your own encrypted tokens into the mixer
- `getPublicBalanceToReceiverClaimableUtxoCreatorFunction` — Send public tokens to a receiver via the mixer
- `getEncryptedBalanceToReceiverClaimableUtxoCreatorFunction` — Send encrypted tokens to a receiver via the mixer

### UTXO Scanning & Claiming

- `getClaimableUtxoScannerFunction` — Scan Merkle trees for UTXOs addressed to your keys
- `getSelfClaimableUtxoToEncryptedBalanceClaimerFunction` — Claim your own UTXO into encrypted balance
- `getSelfClaimableUtxoToPublicBalanceClaimerFunction` — Claim your own UTXO into public wallet
- `getReceiverClaimableUtxoToEncryptedBalanceClaimerFunction` — Claim a received UTXO into encrypted balance

### User Account Management

- `getUserRegistrationFunction` — Account init, X25519 key registration, anonymous usage setup
- `getUserEncryptionKeyRotatorFunction` — Rotate user account X25519 encryption key
- `getMasterViewingKeyRotatorFunction` — Rotate master viewing key
- `getUserEntropySeedRotatorFunction` — Rotate user-level entropy seed
- `getTokenEntropySeedRotatorFunction` — Rotate per-token entropy seed
- `getStagedSolRecovererFunction` — Recover SOL stuck from failed MPC callbacks
- `getStagedSplRecovererFunction` — Recover SPL tokens stuck from failed MPC callbacks

### Query

- `getUserAccountQuerierFunction` — Read user account state
- `getEncryptedBalanceQuerierFunction` — Read and decrypt encrypted token balance

### Conversion

- `getNetworkEncryptionToSharedEncryptionConverterFunction` — Convert from network-only to shared encryption mode
- `getMintEncryptionKeyRotatorFunction` — Rotate per-mint encryption key

### Compliance

- `getComplianceGrantIssuerFunction` — Authorize an auditor to view encrypted data
- `getComplianceGrantRevokerFunction` — Revoke auditor access
- `getSharedCiphertextReencryptorForUserGrantFunction` — Re-encrypt shared balance for a user-granted auditor
- `getNetworkCiphertextReencryptorForNetworkGrantFunction` — Re-encrypt network balance for a network-granted auditor
- `getSharedCiphertextReencryptorForNetworkGrantFunction` — Re-encrypt shared balance for a network-granted auditor

## PDA Derivation

All Program Derived Address functions use the `find*Pda` convention:

```typescript
import {
  findEncryptedTokenAccountPda,
  findStealthPoolPda,
  findNullifierSetPdas,
} from "@umbra-privacy/sdk/pda";

const tokenAccountPda = await findEncryptedTokenAccountPda(userAddress, mintAddress, programId);
const stealthPoolPda = await findStealthPoolPda(treeIndex, programId);
const nullifierPdas = await findNullifierSetPdas(treeIndex, programId);
```

## Cryptography

```typescript
import {
  getRescueEncryptorFromPrivateKey,
  getRescueDecryptorFromPrivateKey,
  getPoseidonHasher,
  getMasterViewingKeyDeriver,
} from "@umbra-privacy/sdk/crypto";

// Rescue cipher encryption
const encryptor = getRescueEncryptorFromPrivateKey(privateKey);
const { ciphertexts, nonce } = await encryptor([plaintext]);

// Poseidon hashing
const hasher = getPoseidonHasher();
const hash = hasher([input1, input2]);

// Key derivation
const deriveMvk = getMasterViewingKeyDeriver({ client });
const masterViewingKey = await deriveMvk();
```

## ZK Provers

UTXO creation and claim operations require a Groth16 prover. Install the companion package for browser-based proving:

```bash
pnpm add @umbra-privacy/web-zk-prover
```

```typescript
import { getCreateReceiverClaimableUtxoFromPublicBalanceProver } from "@umbra-privacy/web-zk-prover";

const zkProver = getCreateReceiverClaimableUtxoFromPublicBalanceProver();
const createUtxo = getPublicBalanceToReceiverClaimableUtxoCreatorFunction(
  { client },
  { zkProver },
);
```

## Requirements

- Node.js 18+
- Solana RPC endpoint

## Documentation

Full documentation at [docs.umbraprivacy.com](https://docs.umbraprivacy.com).

## License

MIT
