Obtener Balances
Copy
const balances = await pan.wallet.getBalances('pan_wallet_abc123');
console.log('Total USD:', balances.totalValueUsd);
console.log('Address:', balances.address);
Estructura de Respuesta
Copy
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
Copy
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
Copy
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
Copy
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
Copy
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
Copy
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
};
}
Copy
// 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>
);
}
