Skip to main content

Obtener Balances

const balances = await pan.wallet.getBalances('pan_wallet_abc123');

console.log('Total USD:', balances.totalValueUsd);
console.log('Address:', balances.address);

Estructura de Respuesta

interface WalletBalances {
  walletId: string;
  address: string;
  chains: ChainBalance[];
  totalValueUsd?: number;
}

interface ChainBalance {
  chain: string;
  tokens: TokenBalance[];
}

interface TokenBalance {
  asset: string;            // Simbolo (USDC, WETH)
  balance: string;          // En unidades minimas
  balanceFormatted: string; // Con decimales
  decimals: number;
  valueUsd?: number;
}
Estructura de datos: Los balances se organizan por chain en un array chains, donde cada chain contiene sus tokens.

Iterar Balances

const balances = await pan.wallet.getBalances(walletId);

for (const chainBalance of balances.chains) {
  console.log(`\n${chainBalance.chain}:`);
  for (const token of chainBalance.tokens) {
    if (parseFloat(token.balanceFormatted) > 0) {
      console.log(`  ${token.balanceFormatted} ${token.asset} ($${token.valueUsd || 0})`);
    }
  }
}

Helpers Utiles

Total de un Asset

function getAssetTotal(balances: WalletBalances, asset: string): number {
  let total = 0;

  for (const chainBalance of balances.chains) {
    const token = chainBalance.tokens.find(t => t.asset === asset);
    if (token) {
      total += parseFloat(token.balanceFormatted);
    }
  }

  return total;
}

const totalUsdc = getAssetTotal(balances, 'USDC');

Balances por Asset

function getBalancesByAsset(balances: WalletBalances): Record<string, {
  total: number;
  totalUsd: number;
  chains: { chain: string; amount: number; usd: number }[];
}> {
  const result: Record<string, any> = {};

  for (const chainBalance of balances.chains) {
    for (const token of chainBalance.tokens) {
      if (!result[token.asset]) {
        result[token.asset] = { total: 0, totalUsd: 0, chains: [] };
      }

      const amount = parseFloat(token.balanceFormatted);
      result[token.asset].total += amount;
      result[token.asset].totalUsd += token.valueUsd || 0;
      result[token.asset].chains.push({
        chain: chainBalance.chain,
        amount,
        usd: token.valueUsd || 0
      });
    }
  }

  return result;
}

Verificar Fondos

function hasFunds(balances: WalletBalances, asset: string, required: number): boolean {
  return getAssetTotal(balances, asset) >= required;
}

if (!hasFunds(balances, 'USDC', 1000)) {
  throw new Error('Fondos insuficientes');
}

Hook de React

import { useState, useEffect, useCallback } from 'react';
import { usePan } from './usePan';
import type { Balances } from '@pan/sdk';

interface UseBalancesOptions {
  autoRefresh?: boolean;
  refreshInterval?: number;
}

export function useBalances(walletId: string, options: UseBalancesOptions = {}) {
  const { autoRefresh = false, refreshInterval = 30000 } = options;
  const pan = usePan();

  const [balances, setBalances] = useState<Balances | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  const fetch = useCallback(async () => {
    try {
      const data = await pan.wallet.getBalances(walletId);
      setBalances(data);
      setError(null);
    } catch (err) {
      setError(err);
    } finally {
      setLoading(false);
    }
  }, [pan, walletId]);

  useEffect(() => {
    fetch();
  }, [fetch]);

  useEffect(() => {
    if (!autoRefresh) return;

    const timer = setInterval(fetch, refreshInterval);
    return () => clearInterval(timer);
  }, [autoRefresh, refreshInterval, fetch]);

  const getTotal = (symbol: string) => {
    if (!balances) return 0;
    return getAssetTotal(balances, symbol);
  };

  return {
    balances,
    loading,
    error,
    refresh: fetch,
    getTotal,
    totalUsd: balances?.totalValueUsd || 0
  };
}
// Uso
function BalanceDisplay({ walletId }) {
  const { balances, loading, totalUsd, getTotal, refresh } = useBalances(walletId, {
    autoRefresh: true,
    refreshInterval: 60000
  });

  if (loading) return <div>Cargando...</div>;

  return (
    <div>
      <h3>Total: ${totalUsd.toFixed(2)}</h3>
      <p>USDC: {getTotal('USDC').toFixed(2)}</p>
      <button onClick={refresh}>Actualizar</button>
    </div>
  );
}