Skip to main content

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:', balance);
// Returns: bigint (e.g., 1000000000000000000n)

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)
}

Syncing Balances

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

// Sync all balances
await sdk.vault.syncAllBalances();

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

Parse Human-Readable to BigInt

// Parse "1.5" to bigint for a token
const amount = await sdk.vault.parseAmount('0x...usdc', '1.5');
// Returns: 1500000n (for 6 decimal token)

const ethAmount = await sdk.vault.parseAmount('0x...weth', '1.5');
// Returns: 1500000000000000000n (for 18 decimal token)

Format BigInt to Human-Readable

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

const ethFormatted = sdk.vault.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 '@testinprod-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.syncAllBalances();
      const allBalances = await sdk.vault.getAllBalances();
      setBalances(allBalances);
      setLoading(false);
    }
    loadBalances();
  }, []);

  const formatBalance = (amount: bigint, decimals: number) => {
    return sdk.vault.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.syncAllBalances();
      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 >= 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 sdk.vault.formatAmount(balance.shielded, balance.decimals || 18);
}

3. Refresh After Operations

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

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

  return result;
}

Next Steps