spotClearinghouseState - HyperCore Info Endpoint
Get spot trading account state and token balances for any user on Hyperliquid, including available and held balances.
Get spot trading account state and token balances for a user on Hyperliquid.
Why Hyperliquid? Build on the trading-focused EVM and HyperCore ecosystem built for onchain perpetuals and market data with HyperCore market structure, sub-second finality, and direct access to trading-focused data services.
Authenticate HyperCore Info requests by sending your Dwellir API key in the x-api-key header to https://api-hyperliquid-mainnet-info.n.dwellir.com/info.
When to Use This Endpoint
The spotClearinghouseState endpoint is essential for spot traders, portfolio managers, and trading platforms who need to:
- Track Token Balances — Monitor available and held balances across all tokens
- Portfolio Management — Calculate total portfolio value across spot holdings
- Trading Validation — Verify sufficient balance before placing spot orders
- Liquidity Management — Track which funds are locked in open orders
Common Use Cases
1. Check Available Balance
Calculate available balance for a specific token:
async function getAvailableBalance(userAddress, token) {
const state = await getSpotClearinghouseState(userAddress);
const balance = state.balances.find(b => b.coin === token);
if (!balance) {
return {
token: token,
available: 0,
total: 0,
hold: 0,
exists: false
};
}
const total = parseFloat(balance.total);
const hold = parseFloat(balance.hold);
const available = total - hold;
return {
token: token,
available: available,
total: total,
hold: hold,
exists: true
};
}
// Usage
const usdcBalance = await getAvailableBalance(
'0x63E8c7C149556D5f34F833419A287bb9Ef81487f',
'USDC'
);
if (usdcBalance.available < 1000) {
console.log('Insufficient USDC balance for trade');
}2. Portfolio Value Calculator
Calculate total portfolio value in USD:
async function calculatePortfolioValue(userAddress, prices) {
const state = await getSpotClearinghouseState(userAddress);
let totalValue = 0;
const holdings = [];
state.balances.forEach(balance => {
const total = parseFloat(balance.total);
if (total === 0) return;
const price = prices[balance.coin] || 0;
const value = total * price;
totalValue += value;
holdings.push({
token: balance.coin,
amount: total,
price: price,
value: value,
percentage: 0 // Will calculate after
});
});
// Calculate percentages
holdings.forEach(h => {
h.percentage = (h.value / totalValue) * 100;
});
// Sort by value
holdings.sort((a, b) => b.value - a.value);
return {
totalValue: totalValue,
holdings: holdings,
tokenCount: holdings.length
};
}
// Usage with example prices
const prices = { USDC: 1, ETH: 2500, BTC: 45000 };
const portfolio = await calculatePortfolioValue(
'0x63E8c7C149556D5f34F833419A287bb9Ef81487f',
prices
);
console.log(`Total Portfolio Value: $${portfolio.totalValue.toFixed(2)}`);
portfolio.holdings.forEach(h => {
console.log(`${h.token}: $${h.value.toFixed(2)} (${h.percentage.toFixed(1)}%)`);
});3. Validate Trade Feasibility
Check if user has sufficient balance for a trade:
async function canExecuteTrade(userAddress, token, requiredAmount) {
const balance = await getAvailableBalance(userAddress, token);
if (!balance.exists) {
return {
canTrade: false,
reason: `No ${token} balance found`,
available: 0,
required: requiredAmount
};
}
if (balance.available < requiredAmount) {
return {
canTrade: false,
reason: 'Insufficient balance',
available: balance.available,
required: requiredAmount,
shortfall: requiredAmount - balance.available
};
}
return {
canTrade: true,
available: balance.available,
required: requiredAmount,
remaining: balance.available - requiredAmount
};
}
// Usage
const tradeCheck = await canExecuteTrade(
'0x63E8c7C149556D5f34F833419A287bb9Ef81487f',
'USDC',
1000
);
if (!tradeCheck.canTrade) {
console.error(`Cannot trade: ${tradeCheck.reason}`);
console.error(`Required: ${tradeCheck.required}, Available: ${tradeCheck.available}`);
}4. Monitor Locked Balances
Track which tokens have funds locked in orders:
async function getLockedBalances(userAddress) {
const state = await getSpotClearinghouseState(userAddress);
const lockedBalances = state.balances
.filter(b => parseFloat(b.hold) > 0)
.map(b => ({
token: b.coin,
total: parseFloat(b.total),
hold: parseFloat(b.hold),
available: parseFloat(b.total) - parseFloat(b.hold),
percentLocked: (parseFloat(b.hold) / parseFloat(b.total)) * 100
}));
return lockedBalances;
}
// Usage
const locked = await getLockedBalances('0x63E8c7C149556D5f34F833419A287bb9Ef81487f');
console.log(`${locked.length} tokens with locked funds:\n`);
locked.forEach(l => {
console.log(`${l.token}:`);
console.log(` Locked: ${l.hold} (${l.percentLocked.toFixed(1)}%)`);
console.log(` Available: ${l.available}`);
});5. Balance Summary Report
Generate a comprehensive balance report:
async function getBalanceSummary(userAddress) {
const state = await getSpotClearinghouseState(userAddress);
console.log('\n=== Spot Balance Summary ===\n');
const nonZeroBalances = state.balances.filter(b => parseFloat(b.total) > 0);
const lockedBalances = state.balances.filter(b => parseFloat(b.hold) > 0);
console.log(`Total Tokens: ${nonZeroBalances.length}`);
console.log(`Tokens with Orders: ${lockedBalances.length}\n`);
console.log('Balances:');
nonZeroBalances.forEach(balance => {
const total = parseFloat(balance.total);
const hold = parseFloat(balance.hold);
const available = total - hold;
console.log(`\n${balance.coin}:`);
console.log(` Total: ${balance.total}`);
console.log(` Available: ${available.toFixed(8)}`);
if (hold > 0) {
console.log(` On Hold: ${balance.hold} ⚠️`);
}
});
}Best Practices
- Poll responsibly — Don't poll more frequently than needed (every 5-10 seconds for active trading)
- Handle zero balances — Token may exist with zero balance
- Check available balance — Always calculate
total - holdbefore placing orders - Validate addresses — Ensure user addresses are valid Ethereum addresses
- Cache when appropriate — Cache balance data briefly to reduce API calls
Related Endpoints
- clearinghouseState — Get perpetual account state
- openOrders — See which orders are holding funds
- spotMeta — Get spot trading asset metadata
- userFees — Get user fee rates for trading
Access real-time Hyperliquid spot balances with Dwellir's HyperCore Info Endpoint. Get your API key →
perpDexs
Get all perpetual DEXs deployed on Hyperliquid. Query deployer details, listed assets, open interest caps, funding multipliers, fee configuration, and sub-deployer permissions.
spotMeta
Get comprehensive spot trading asset metadata including token information, decimal precision, and trading pair details for Hyperliquid's spot markets.