Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.privacyboost.io/llms.txt

Use this file to discover all available pages before exploring further.

Getting Started

This guide walks through the core integration flow: initialize the SDK, authenticate a wallet, and perform your first private transactions.
For a minimal copy-paste example, see the TypeScript Quickstart. This guide explains each step in detail.

Prerequisites

Step 1: Initialize the SDK

import { PrivacyBoost } from '@sunnyside-io/privacy-boost';

const sdk = await PrivacyBoost.create({
  appId: 'your-app-id',
  serverUrl: 'https://test-api.privacyboost.io',
  wethContractAddress: '0x4200000000000000000000000000000000000006',
});

Configuration Options

OptionTypeRequiredDescription
appIdstringYesApplication identifier
serverUrlstringYesPrivacy Boost server endpoint
chainIdnumberNoEVM chain ID (auto-discovered from server)
shieldContractAddressstringNoShield contract address (auto-discovered from server)
wethContractAddressstringNoWETH contract for ETH handling

Step 2: Authenticate

Connect a wallet and authenticate in a single call:

Using Browser Wallet (MetaMask, etc.)

// Create a wallet adapter that wraps window.ethereum
const adapter = {
  async connect() {
    const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
    const chainId = await window.ethereum.request({ method: 'eth_chainId' });
    return { address: accounts[0], chainId: parseInt(chainId, 16) };
  },
  async disconnect() {},
  async signMessage(message: string) {
    const accounts = await window.ethereum.request({ method: 'eth_accounts' });
    return window.ethereum.request({ method: 'personal_sign', params: [message, accounts[0]] });
  },
  async signTypedData(typedDataJson: string) {
    const accounts = await window.ethereum.request({ method: 'eth_accounts' });
    return window.ethereum.request({ method: 'eth_signTypedData_v4', params: [accounts[0], typedDataJson] });
  },
  async sendTransaction(tx: unknown) {
    return window.ethereum.request({ method: 'eth_sendTransaction', params: [tx] });
  },
  async getAddress() {
    const accounts = await window.ethereum.request({ method: 'eth_accounts' });
    return accounts[0];
  },
  async getChainId() {
    const chainId = await window.ethereum.request({ method: 'eth_chainId' });
    return parseInt(chainId, 16);
  },
};

// Authenticate — connects wallet, derives keys, and authenticates with server
const result = await sdk.auth.authenticate(adapter);

if (result.status === 'authenticated') {
  console.log('Privacy Address:', result.privacyAddress);
  console.log('MPK:', result.mpk);
} else if (result.status === 'credentialRequired') {
  // Prompt user for credential, then submit
  const loginResult = await result.submit(credential);
}
When does credentialRequired fire? credentialRequired only fires when persistence with pin or password unlock is configured. For the simple case (no persistence), authenticate() always returns authenticated directly.
Using React? The React SDK provides createWalletAdapter() and authenticateWithWalletAdapter() which handle this for you. See the React Getting Started guide.

Authentication State

// Check authentication status
console.log('Authenticated:', sdk.auth.isAuthenticated());
console.log('Privacy Address:', sdk.auth.getPrivacyAddress());

Step 3: Check Balance

Each token has two balances: a shielded balance (tokens inside the private pool, only visible to you) and a wallet balance (your public on-chain balance). Both are returned together in a TokenBalance object.
// Get balance for a specific token
const tokenAddress = '0x...';
const balance = await sdk.vault.getBalance(tokenAddress);
console.log('Shielded:', balance.shieldedBalance);
console.log('Wallet:', balance.walletBalance);

// Get all balances
const allBalances = await sdk.vault.getAllBalances();
for (const b of allBalances) {
  console.log(`${b.symbol}: ${b.shieldedBalance} (shielded), ${b.walletBalance} (wallet)`);
}

Step 4: Deposit Tokens

Move tokens from your public wallet into the shielded pool. Once deposited, your balance is private — only you can see it.
const result = await sdk.vault.shield({
  tokenAddress: '0x...',
  amount: 1000000000000000000n, // 1 token (18 decimals)
  onProgress: ({ step, message }) => {
    console.log(`${step}: ${message}`);
  },
});

console.log('Deposit tx:', result.txHash);
console.log('Commitment:', result.commitment);

Deposit Steps

The deposit operation goes through several steps:
  1. wrapping - If depositing ETH, wrap to WETH
  2. approving - Approve token spending
  3. shielding - Execute the deposit transaction
  4. registering - Register the deposit with the indexer
  5. compliance - Wait for compliance check

Step 5: Send Private Transfer

Send tokens privately to another user’s privacy address. The recipient shares their privacy address with you (similar to sharing a bank account number). No on-chain observer can see the sender, recipient, or amount.
const result = await sdk.vault.send({
  to: '0x04...recipient-privacy-address',
  tokenAddress: '0x...',
  amount: 500000000000000000n, // 0.5 tokens
});

console.log('Transfer requestId:', result.requestId);
The recipient will see the tokens in their shielded balance after the transaction confirms.
For send() and unshield(), the returned txHash is a local placeholder until the canonical on-chain hash is available. Track status by requestId (e.g. sdk.vault.getTransferStatus(requestId) / sdk.vault.getUnshieldStatus(requestId)). For shield(), txHash is the real on-chain hash because the wallet signs and submits it directly.

Step 6: Withdraw Tokens

Move tokens out of the shielded pool to any public Ethereum address. This is how you “cash out” back to a regular wallet.
const result = await sdk.vault.unshield({
  tokenAddress: '0x...',
  amount: 250000000000000000n, // 0.25 tokens
  recipientAddress: '0x...any-public-address',
  // Optional: when the token is WETH, automatically unwrap to native ETH
  // after the unshield lands. Requires `wethContractAddress` to be set.
  unwrapWeth: false,
  onProgress: ({ step, message }) => {
    console.log(`${step}: ${message}`);
  },
});

console.log('Withdraw requestId:', result.requestId);

Step 7: Multi-Chain (Optional)

To operate on additional blockchains, create chain clients from the same SDK instance. Each chain client shares your identity but has independent auth, balances, and transactions:
// Create a chain client (only serverUrl is required; rest is auto-discovered)
const ethereum = sdk.forChain({ serverUrl: 'https://eth.example.com' });

// Authenticate on the new chain
await ethereum.authenticate(adapter);

// Use it just like the primary SDK
await ethereum.vault.shield({
  tokenAddress: '0x...token-on-ethereum',
  amount: 1000000000000000000n,
});

const ethBalance = await ethereum.vault.getBalance('0x...');
See the Multi-Chain guide for patterns like parallel operations and cross-chain balance aggregation.

What’s Next

You’ve completed the core flow: init → auth → balance → deposit → send → withdraw. Here’s where to go from here:

Deposits

Deposit tokens into the shielded pool

Withdrawals

Withdraw tokens from the shielded pool

Private Transfers

Send tokens privately between users

Error Handling

Error codes and retry patterns

Multi-Chain

Operate across multiple blockchains

API Reference

Complete method signatures and type definitions
For cross-platform concepts (key management, auth methods, error codes), see the Setup section.