Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

TokenBalance

Token balance display with auto-formatting, fiat conversion, and polling. Supports native tokens (ETH, MATIC) and ERC-20 tokens.

Bundle: 4.6 kB JS (gzip) + 2.1 kB CSS (gzip).

Import

import { TokenBalance } from '@txkit/react'

Usage

<TokenBalance />

Shows the connected wallet's native token balance with USD equivalent.

For ERC-20 tokens, pass the contract address:

<TokenBalance token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" />

Props

PropTypeDefault
classNamestring-
children(data: TokenBalanceRenderData) => ReactNode-
variant'inline' | 'row''inline'
token`0x${string}`-
namestring-
iconstring-
address`0x${string}`Connected wallet
chainIdnumberCurrent chain
fiatCurrencystring'USD'
pricenumber-
refetchIntervalnumberpollingInterval from config
formatOptionsTokenBalanceFormatOptionsSee Formatting
labelsPartial<TokenBalanceLabels>See Labels
showFiatbooleantrue
showIconbooleantrue
showSymbolbooleantrue
onBalanceChange(balance: bigint, prevBalance: bigint | undefined) => void-
onError(error: Error) => void-
  • variant - inline is the default compact display (icon, balance, symbol on one line). row switches to a token-list layout with name on the first line and balance + fiat on the second - meant for portfolio tables.

  • name - Token display name shown only in variant="row" (e.g. "USD Coin"). The symbol is auto-resolved from the contract.

  • token - ERC-20 contract address. When omitted, shows the native token (ETH, MATIC, etc.).

  • icon - Token icon URL. Displayed as a 20px circle before the balance.

  • address - Override whose balance to show. Defaults to the connected wallet.

  • price - Manual USD price override. Skips the DeFiLlama price fetch.

  • children - Render function for full UI control. Receives TokenBalanceRenderData.

States

StateShowsBehavior
loadingSkeleton pulse animationFetching balance from RPC
readyFormatted balance + fiatAuto-refetches on refetchInterval
zero0 with dimmed styleBalance is exactly 0n - not an error, fiat hidden by default
error"Failed to load" textCalls onError if provided

The data-state attribute on the root element exposes the current state for custom styling ([data-state="loading"], [data-state="ready"], [data-state="error"]). The data-zero attribute is set on the ready state when balance is zero.

Examples

ERC-20 Token

<TokenBalance token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" />

Row Variant (Portfolio Tables)

Switches from inline (icon + balance + symbol on one line) to a stacked layout suitable for token lists or portfolio rows. The first line shows name, the second line shows balance + fiat.

<TokenBalance
  variant="row"
  token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
  name="USD Coin"
  icon="https://assets.coingecko.com/coins/images/6319/small/usdc.png"
/>

For multi-token portfolio displays:

<div role="list">
  <TokenBalance variant="row" name="Ether" />
  <TokenBalance variant="row" token={USDC} name="USD Coin" />
  <TokenBalance variant="row" token={WBTC} name="Wrapped Bitcoin" />
</div>

With Icon

<TokenBalance
  token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
  icon="https://assets.coingecko.com/coins/images/6319/small/usdc.png"
/>

Custom Fiat Currency

<TokenBalance fiatCurrency="EUR" />

Forex rates are fetched automatically. Supported currencies: any ISO 4217 code (EUR, GBP, JPY, etc.).

Manual Price Override

<TokenBalance token="0x..." price={1.0} />

Useful for stablecoins or tokens not listed on DeFiLlama.

Hide Parts

<TokenBalance showFiat={false} />
<TokenBalance showIcon={false} showSymbol={false} />

Custom Render

<TokenBalance token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48">
  {({ formatted, symbol, fiatFormatted, isLoading }) => (
    isLoading
      ? <span>Loading...</span>
      : <span>{formatted} {symbol} ({fiatFormatted})</span>
  )}
</TokenBalance>

Balance Change Callback

<TokenBalance
  onBalanceChange={(balance, prev) => {
    if (prev !== undefined && balance > prev) {
      console.log('Received tokens!')
    }
  }}
/>

Multiple Tokens

Multiple TokenBalance components with the same parameters share a single RPC call via TanStack Query deduplication:

<TokenBalance token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" />
{/* Same token - no extra RPC call */}
<TokenBalance token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" />

Specific Address

<TokenBalance address="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" />

Render Data

When using the children render function, you receive a TokenBalanceRenderData object:

FieldTypeDescription
iconstring | undefinedToken icon URL (passed via icon prop)
balancebigint | undefinedRaw balance in smallest unit (wei)
decimalsnumber | undefinedToken decimals (18 for ETH, 6 for USDC)
symbolstring | undefinedToken symbol (ETH, USDC)
formattedstring | undefinedHuman-readable balance with progressive scaling
integerPartstring | undefinedInteger part of formatted balance (e.g. "1,234")
fractionPartstring | undefinedFractional part including dot (e.g. ".5678")
isZerobooleanTrue when balance is exactly 0n
fiatValuenumber | undefinedFiat equivalent as raw number
fiatFormattedstring | undefinedFiat with currency symbol (e.g. "$1,234.57")
isLoadingbooleanTrue while fetching
isErrorbooleanTrue if fetch failed
errorError | nullError object if failed
refetch() => voidManually trigger refetch

integerPart and fractionPart exist so custom renderers can typeset the fraction at a smaller size or muted color (the default UI does this).

Formatting

TokenBalance uses progressive decimal scaling based on the amount:

RangeDecimalsExample
0 - 951.23456
10 - 99442.1234
100 - 9993500.123
1,000 - 9,99922,500.12
10,000+suffix42.5k, 1.2m, 3.4b

Dust Threshold

Amounts below 0.0001 display as < 0.0001. Override via formatOptions:

<TokenBalance formatOptions={{ dustThreshold: 0.001 }} />

Locale

Number formatting follows the browser locale by default. Override:

<TokenBalance formatOptions={{ locale: 'de-DE' }} />

Hooks

useTokenBalance

Headless hook for single token balance.

import { useTokenBalance } from '@txkit/react'
 
const { balance, decimals, symbol, formatted, isLoading, refetch } = useTokenBalance({
  token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
})
OptionTypeDescription
token`0x${string}`ERC-20 address. Omit for native token.
address`0x${string}`Wallet address. Default: connected wallet.
chainIdnumberChain ID. Default: current chain.
refetchIntervalnumberPolling interval in ms.
enabledbooleanDisable fetching. Default: true.

useTokenBalances

Batch hook for multiple tokens. Optimizes ERC-20 calls into a single multicall request.

import { useTokenBalances } from '@txkit/react'
 
const balances = useTokenBalances({
  tokens: [ 'native', '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' ],
})
 
balances.forEach(({ symbol, formatted }) => {
  console.log(`${symbol}: ${formatted}`)
})

useTokenPrice

Hook for token price in fiat. Uses DeFiLlama API with automatic forex conversion.

import { useTokenPrice } from '@txkit/react'
 
const { price, isLoading } = useTokenPrice({
  chainId: 1,
  token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  fiatCurrency: 'EUR',
})

Labels

Override UI text by passing a partial TokenBalanceLabels object:

<TokenBalance labels={{ loading: 'Fetching...', error: 'Unavailable' }} />

All Label Keys

KeyDefault
loading'Loading...'
error'Failed to load'

Accessibility

TokenBalance includes built-in screen reader support:

  • role="status" and aria-live="polite" - announces balance updates without interrupting
  • aria-atomic="true" - reads the full balance on each update
  • aria-busy - set to true while loading
  • Hidden status text provides a full sentence for screen readers (e.g. "Balance: 1.5 ETH, $3,200.00")