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.

Balance Management

This guide covers querying and managing token balances in the Privacy Boost SDK.

Understanding Balances

Privacy Boost tracks two types of balances:
Balance TypeDescription
ShieldedPrivate balance in the privacy pool
WalletPublic balance in your connected wallet

Get Single Token Balance

const tokenAddress = '0x...';
const balance = await sdk.vault.getBalance(tokenAddress);

console.log('Shielded:', balance.shielded);
console.log('Wallet:', balance.wallet);
// Returns: TokenBalance { tokenAddress, shielded, wallet, symbol?, decimals? }

Get All Balances

const balances = await sdk.vault.getAllBalances();

for (const balance of balances) {
  console.log(`Token: ${balance.tokenAddress}`);
  console.log(`  Symbol: ${balance.symbol}`);
  console.log(`  Shielded: ${balance.shielded}`);
  console.log(`  Wallet: ${balance.wallet}`);
  console.log(`  Decimals: ${balance.decimals}`);
}

Balance Type

interface TokenBalance {
  tokenAddress: Hex;    // Token contract address
  shielded: bigint;     // Private balance
  wallet: bigint;       // Wallet balance
  symbol?: string;      // Token symbol (e.g., "USDC")
  decimals?: number;    // Token decimals (e.g., 18)
}

Refreshing Balances

Balances are cached locally. Refresh to get the latest:
// Refresh a specific token
await sdk.vault.refreshBalance('0x...token-address');

// Refresh all tracked balances
await sdk.vault.refreshBalances();

Token Metadata

Get information about a token:
const token = await sdk.vault.getToken('0x...token-address');

console.log('Name:', token.name);        // "USD Coin"
console.log('Symbol:', token.symbol);    // "USDC"
console.log('Decimals:', token.decimals); // 6

Token Metadata Type

interface TokenMetadata {
  address: Hex;
  symbol: string;
  decimals: number;
  name: string;
}

Supported Tokens

Get list of all supported tokens:
const tokens = await sdk.vault.getSupportedTokens();

for (const token of tokens) {
  console.log(`${token.symbol} (${token.address})`);
}

Formatting Amounts

parseAmount and formatAmount are standalone utilities exported from the SDK package.

Parse Human-Readable to BigInt

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

// Parse "1.5" using a token's decimals
const usdc = parseAmount('1.5', 6);
// Returns: 1500000n

const weth = parseAmount('1.5', 18);
// Returns: 1500000000000000000n

Format BigInt to Human-Readable

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

const formatted = formatAmount(1500000n, 6);
// Returns: "1.5"

const ethFormatted = formatAmount(1500000000000000000n, 18);
// Returns: "1.5"

Native ETH

Native ETH is represented by the zero address:
const ETH_ADDRESS = '0x0000000000000000000000000000000000000000';

// Check if token is native ETH
import { isNativeEth } from '@sunnyside-io/privacy-boost';

if (isNativeEth(tokenAddress)) {
  console.log('This is native ETH');
}

UI Example

import { useState, useEffect } from 'react';

function BalanceList() {
  const [balances, setBalances] = useState<TokenBalance[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function loadBalances() {
      setLoading(true);
      await sdk.vault.refreshBalances();
      const allBalances = await sdk.vault.getAllBalances();
      setBalances(allBalances);
      setLoading(false);
    }
    loadBalances();
  }, []);

  const formatBalance = (amount: bigint, decimals: number) => {
    return formatAmount(amount, decimals);
  };

  if (loading) return <div>Loading balances...</div>;

  return (
    <table>
      <thead>
        <tr>
          <th>Token</th>
          <th>Shielded</th>
          <th>Wallet</th>
        </tr>
      </thead>
      <tbody>
        {balances.map((balance) => (
          <tr key={balance.tokenAddress}>
            <td>{balance.symbol}</td>
            <td>{formatBalance(balance.shielded, balance.decimals || 18)}</td>
            <td>{formatBalance(balance.wallet, balance.decimals || 18)}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

Balance Polling

Keep balances updated with polling:
function useBalancePolling(intervalMs = 30000) {
  const [balances, setBalances] = useState<TokenBalance[]>([]);

  useEffect(() => {
    async function sync() {
      await sdk.vault.refreshBalances();
      setBalances(await sdk.vault.getAllBalances());
    }

    sync(); // Initial sync

    const interval = setInterval(sync, intervalMs);
    return () => clearInterval(interval);
  }, [intervalMs]);

  return balances;
}

Balance Calculations

Total Portfolio Value

async function getTotalValue(prices: Record<string, number>) {
  const balances = await sdk.vault.getAllBalances();

  let total = 0;
  for (const balance of balances) {
    const price = prices[balance.tokenAddress.toLowerCase()] || 0;
    const amount = Number(balance.shielded) / 10 ** (balance.decimals || 18);
    total += amount * price;
  }

  return total;
}

Check Sufficient Balance

async function hasSufficientBalance(
  tokenAddress: Hex,
  requiredAmount: bigint
): Promise<boolean> {
  const balance = await sdk.vault.getBalance(tokenAddress);
  return balance.shielded >= requiredAmount;
}

Error Handling

try {
  const balance = await sdk.vault.getBalance(tokenAddress);
} catch (error) {
  switch (error.code) {
    case 'TOKEN_NOT_FOUND':
      console.log('Token not supported');
      break;
    case 'SYNC_FAILED':
      console.log('Failed to sync balance');
      break;
    default:
      console.log('Balance error:', error.message);
  }
}

Best Practices

1. Cache Token Metadata

const tokenCache = new Map<string, TokenMetadata>();

async function getTokenCached(address: string) {
  const key = address.toLowerCase();
  if (!tokenCache.has(key)) {
    const metadata = await sdk.vault.getToken(address);
    tokenCache.set(key, metadata);
  }
  return tokenCache.get(key)!;
}

2. Handle Zero Balances

function formatBalance(balance: TokenBalance): string {
  if (balance.shielded === 0n && balance.wallet === 0n) {
    return '0';
  }
  return formatAmount(balance.shielded, balance.decimals || 18);
}

3. Refresh After Operations

async function depositWithRefresh(params: DepositParams) {
  const result = await sdk.vault.shield(params);

  // Refresh balance after deposit
  await sdk.vault.refreshBalance(params.tokenAddress);

  return result;
}

Next Steps