Skip to main content

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 '@testinprod-io/privacy-boost';

const sdk = await PrivacyBoost.create({
  appId: 'your-app-id',
  indexerUrl: 'https://test-api.privacy-boost.sunnyside.io/indexer',
  wethContract: '0x4200000000000000000000000000000000000006',
});

Configuration Options

OptionTypeRequiredDescription
appIdstringYesApplication identifier
indexerUrlstringYesIndexer service endpoint
chainIdnumberNoEVM chain ID (auto-discovered from indexer)
shieldContractstringNoShield contract address (auto-discovered from indexer)
wethContractstringNoWETH 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(typedData: string) {
    const accounts = await window.ethereum.request({ method: 'eth_accounts' });
    return window.ethereum.request({ method: 'eth_signTypedData_v4', params: [accounts[0], typedData] });
  },
  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).
// Get balance for a specific token
const tokenAddress = '0x...';
const balance = await sdk.vault.getBalance(tokenAddress);
console.log('Shielded balance:', balance);

// Get all balances
const allBalances = await sdk.vault.getAllBalances();
for (const b of allBalances) {
  console.log(`${b.symbol}: ${b.shielded} (shielded), ${b.wallet} (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 tx:', result.txHash);
The recipient will see the tokens in their shielded balance after the transaction confirms.

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',
  onProgress: ({ step, message }) => {
    console.log(`${step}: ${message}`);
  },
});

console.log('Withdraw tx:', result.txHash);

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 indexerUrl is required; rest is auto-discovered)
const arbitrum = sdk.chain({ indexerUrl: 'https://arb.example.com' });

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

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

const arbBalance = await arbitrum.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.