BigBlocks Docs
Components/Wallet

WalletOverview

Display comprehensive wallet information including balance, recent transactions, and quick actions.

Display comprehensive wallet information including balance, recent transactions, and quick actions. A complete wallet dashboard component with BSV/USD conversion and interactive elements.

View WalletOverview examples →

Installation

npm install bigblocks

Usage

import { WalletOverview } from 'bigblocks';

export default function WalletPage() {
  return (
    <WalletOverview
      balance={{
        confirmed: 150000000, // 1.5 BSV in satoshis
        unconfirmed: 0,
        total: 150000000
      }}
      onSend={() => console.log('Send clicked')}
      onReceive={() => console.log('Receive clicked')}
    />
  );
}

Props

PropTypeDefaultDescription
balanceBSVBalance-Wallet balance information
showValuesbooleantrueShow balance values
currency'BSV' | 'USD''BSV'Display currency
exchangeRatenumber-BSV/USD exchange rate
previousBalancenumber-Previous balance for change calculation
loadingbooleanfalseShow loading state
onSend() => void-Send button callback
onReceive() => void-Receive button callback
onBuy() => void-Buy BSV button callback
onSettings() => void-Settings button callback
classNamestring-Additional CSS classes

BSVBalance Interface

interface BSVBalance {
  confirmed: number;      // Confirmed satoshis
  unconfirmed: number;    // Pending satoshis
  total: number;          // Total satoshis
}

Features

  • Balance Display: Confirmed, pending, and total amounts
  • Currency Conversion: BSV ⟷ USD with live exchange rates
  • Balance Change: Visual indicators for balance changes
  • Quick Actions: Send, Receive, Buy, and Settings buttons
  • Loading States: Skeleton loading while fetching data
  • Responsive Design: Mobile-optimized layout
  • Privacy Mode: Toggle balance visibility

Examples

Basic Wallet Overview

<WalletOverview
  balance={{
    confirmed: 100000000, // 1.0 BSV
    unconfirmed: 0,
    total: 100000000
  }}
  onSend={() => setShowSendModal(true)}
  onReceive={() => setShowReceiveModal(true)}
/>

With USD Display

<WalletOverview
  balance={{
    confirmed: 150000000, // 1.5 BSV
    unconfirmed: 0,
    total: 150000000
  }}
  currency="USD"
  exchangeRate={50.25} // $50.25 per BSV
  onSend={handleSend}
  onBuy={handleBuy}
/>

With Pending Balance

<WalletOverview
  balance={{
    confirmed: 100000000,  // 1.0 BSV confirmed
    unconfirmed: 50000000, // 0.5 BSV pending
    total: 150000000       // 1.5 BSV total
  }}
  previousBalance={100000000} // Show +0.5 BSV change
  onReceive={handleReceive}
/>

Loading State

<WalletOverview
  loading={true}
  onSend={handleSend}
  onReceive={handleReceive}
/>

Compact Version

import { CompactWalletOverview } from 'bigblocks';

<CompactWalletOverview
  balance={{
    confirmed: 75000000,
    unconfirmed: 0,
    total: 75000000
  }}
  currency="USD"
  exchangeRate={48.50}
/>

Complete Dashboard

function WalletDashboard() {
  const [balance, setBalance] = useState(null);
  const [loading, setLoading] = useState(true);
  const [currency, setCurrency] = useState('BSV');
  const [showValues, setShowValues] = useState(true);

  useEffect(() => {
    fetchWalletBalance().then(setBalance).finally(() => setLoading(false));
  }, []);

  return (
    <div className="wallet-dashboard">
      <div className="header">
        <h1>My Wallet</h1>
        <div className="controls">
          <button onClick={() => setCurrency(currency === 'BSV' ? 'USD' : 'BSV')}>
            Switch to {currency === 'BSV' ? 'USD' : 'BSV'}
          </button>
          <button onClick={() => setShowValues(!showValues)}>
            {showValues ? 'Hide' : 'Show'} Values
          </button>
        </div>
      </div>
      
      <WalletOverview
        balance={balance}
        loading={loading}
        currency={currency}
        showValues={showValues}
        exchangeRate={50.0}
        onSend={() => router.push('/send')}
        onReceive={() => router.push('/receive')}
        onBuy={() => router.push('/buy')}
        onSettings={() => router.push('/settings')}
        className="main-wallet"
      />
    </div>
  );
}

Multi-Wallet View

function MultiWalletView() {
  const wallets = [
    { id: 'main', name: 'Main Wallet', balance: { confirmed: 200000000, unconfirmed: 0, total: 200000000 } },
    { id: 'savings', name: 'Savings', balance: { confirmed: 500000000, unconfirmed: 0, total: 500000000 } },
    { id: 'business', name: 'Business', balance: { confirmed: 100000000, unconfirmed: 25000000, total: 125000000 } }
  ];

  return (
    <div className="multi-wallet">
      {wallets.map(wallet => (
        <div key={wallet.id} className="wallet-card">
          <h3>{wallet.name}</h3>
          <WalletOverview
            balance={wallet.balance}
            currency="BSV"
            onSend={() => handleSend(wallet.id)}
            onReceive={() => handleReceive(wallet.id)}
            className="compact"
          />
        </div>
      ))}
    </div>
  );
}

With Real-time Updates

function LiveWalletOverview() {
  const [balance, setBalance] = useState(null);
  const [exchangeRate, setExchangeRate] = useState(50.0);

  // WebSocket for real-time balance updates
  useEffect(() => {
    const ws = new WebSocket('/api/wallet/stream');
    
    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      if (data.type === 'balance_updated') {
        setBalance(data.balance);
      } else if (data.type === 'exchange_rate_updated') {
        setExchangeRate(data.rate);
      }
    };

    return () => ws.close();
  }, []);

  return (
    <WalletOverview
      balance={balance}
      exchangeRate={exchangeRate}
      currency="USD"
      onSend={handleSend}
      onReceive={handleReceive}
    />
  );
}

Enterprise Wallet

function EnterpriseWallet() {
  const [walletData, setWalletData] = useState(null);
  const [permissions, setPermissions] = useState({});

  return (
    <div className="enterprise-wallet">
      <WalletOverview
        balance={walletData?.balance}
        currency="USD"
        exchangeRate={walletData?.exchangeRate}
        onSend={permissions.canSend ? handleSend : undefined}
        onReceive={handleReceive}
        onBuy={permissions.canBuy ? handleBuy : undefined}
        onSettings={permissions.isAdmin ? handleSettings : undefined}
        className="enterprise-style"
      />
      
      {!permissions.canSend && (
        <div className="permission-notice">
          Contact administrator for send permissions
        </div>
      )}
    </div>
  );
}

Required Context

The component requires the following providers:

import { 
  BitcoinAuthProvider, 
  BitcoinQueryProvider 
} from 'bigblocks';

function App() {
  return (
    <BitcoinAuthProvider>
      <BitcoinQueryProvider>
        <WalletOverview
          balance={balance}
          onSend={handleSend}
          onReceive={handleReceive}
        />
      </BitcoinQueryProvider>
    </BitcoinAuthProvider>
  );
}

API Integration

Required Backend Endpoints

The component expects these API endpoints:

1. Get Wallet Balance

GET /api/wallet/balance

Response:
{
  confirmed: number;      // Confirmed satoshis
  unconfirmed: number;    // Pending satoshis
  total: number;          // Total satoshis
  bsv: {
    confirmed: string;    // BSV amount "1.50000000"
    unconfirmed: string;
    total: string;
  };
  usd?: {
    confirmed: string;    // USD value "$75.00"
    unconfirmed: string;
    total: string;
    rate: number;         // Exchange rate
  };
  lastUpdated: number;    // Timestamp
}

2. Get Exchange Rate

GET /api/wallet/exchange-rate?currency=USD

Response:
{
  currency: 'USD';
  rate: number;           // BSV price in USD
  timestamp: number;
  change24h: number;      // 24h change percentage
  source: string;         // Rate provider
}

3. Real-time Updates

// WebSocket connection
WS /api/wallet/stream

Events:
- balance_updated: { balance: BSVBalance }
- exchange_rate_updated: { rate: number, currency: string }
- transaction_received: { amount: number, txid: string }

Authentication Headers

For authenticated requests:

headers: {
  'X-Auth-Token': '<BSM signature>',
  'Content-Type': 'application/json'
}

Currency Conversion

BSV ⟷ USD Conversion

function CurrencyConverter() {
  const [amount, setAmount] = useState(1.0);
  const [fromCurrency, setFromCurrency] = useState('BSV');
  const exchangeRate = 50.25; // $50.25 per BSV

  const convertedAmount = fromCurrency === 'BSV' 
    ? amount * exchangeRate 
    : amount / exchangeRate;

  return (
    <div className="converter">
      <WalletOverview
        balance={{
          confirmed: amount * 100000000, // Convert BSV to satoshis
          unconfirmed: 0,
          total: amount * 100000000
        }}
        currency={fromCurrency === 'BSV' ? 'USD' : 'BSV'}
        exchangeRate={exchangeRate}
      />
      
      <div className="conversion-info">
        {amount} {fromCurrency} = {convertedAmount.toFixed(8)} {fromCurrency === 'BSV' ? 'USD' : 'BSV'}
      </div>
    </div>
  );
}

Privacy Features

Balance Visibility Toggle

function PrivateWallet() {
  const [showBalance, setShowBalance] = useState(false);

  return (
    <div className="private-wallet">
      <div className="privacy-controls">
        <button onClick={() => setShowBalance(!showBalance)}>
          {showBalance ? '👁️ Hide' : '👁️‍🗨️ Show'} Balance
        </button>
      </div>
      
      <WalletOverview
        balance={balance}
        showValues={showBalance}
        onSend={handleSend}
        onReceive={handleReceive}
      />
    </div>
  );
}

Styling Customization

Custom Themes

// Dark theme
<WalletOverview
  balance={balance}
  className="bg-gray-900 text-white border-gray-700"
  onSend={handleSend}
/>

// Colorful theme
<WalletOverview
  balance={balance}
  className="bg-gradient-to-r from-purple-500 to-pink-500 text-white"
  onSend={handleSend}
/>

// Minimal theme
<WalletOverview
  balance={balance}
  className="border-none shadow-none bg-transparent"
  onSend={handleSend}
/>

Performance Considerations

  • Balance Caching: Cache balance data for 30 seconds
  • Exchange Rate: Update rates every 5 minutes
  • Debounced Updates: Prevent excessive API calls
  • Skeleton Loading: Show placeholders while loading

Error Handling

Common Error Scenarios

function RobustWalletOverview() {
  const [balance, setBalance] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchBalance()
      .then(setBalance)
      .catch(setError)
      .finally(() => setLoading(false));
  }, []);

  if (error) {
    return (
      <div className="wallet-error">
        <p>Failed to load wallet: {error.message}</p>
        <button onClick={() => window.location.reload()}>
          Retry
        </button>
      </div>
    );
  }

  return (
    <WalletOverview
      balance={balance}
      loading={loading}
      onSend={handleSend}
      onReceive={handleReceive}
    />
  );
}