> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Token balances & display

> Show a wallet's native balance and its token holdings — with prices, market values, and spam filtering.

## Prerequisites

Before this page: create and initialize a Dynamic client (see [Creating a Dynamic client](/docs/javascript/reference/client/create-dynamic-client), [Initializing the Dynamic client](/docs/javascript/reference/client/initialize-dynamic-client)), have a connected wallet to read from (see [Connecting external wallets](/docs/javascript/building-ui/connecting-external-wallets)), and know which wallet you'll show balances for (see [Connected wallets management](/docs/javascript/building-ui/connected-wallets-management)).

## What you'll build

Two views most apps need:

* **Native balance** — how much of the chain's native asset (ETH, SOL, …) the wallet holds.
* **Token list** — every token the wallet holds, optionally with USD prices and market values, and with spam tokens filtered out.

Both read from a `WalletAccount` that your app supplies — the wallet it's currently acting on.

## Native balance

`getNativeBalance` returns `{ balance }` where `balance` is a human-readable string (or `null` while it's unavailable).

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"system"}
    import {
      getNativeBalance,
      type WalletAccount,
    } from '@dynamic-labs-sdk/client';

    async function renderNativeBalance(
      element: HTMLElement,
      walletAccount: WalletAccount,
    ) {
      const { balance } = await getNativeBalance({ walletAccount });
      element.textContent = balance ?? 'Unavailable';
    }
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { type WalletAccount } from '@dynamic-labs-sdk/client';
    import { useGetNativeBalance } from '@dynamic-labs-sdk/react-hooks';

    function NativeBalance({ walletAccount }: { walletAccount: WalletAccount }) {
      const { data, isLoading } = useGetNativeBalance({ walletAccount });

      if (isLoading) return <span>Loading…</span>;
      return <span>{data?.balance ?? 'Unavailable'}</span>;
    }
    ```

    The query refetches automatically when the wallet's network changes, so the balance stays in sync.
  </Tab>
</Tabs>

## Token holdings

`getTokenBalances` returns one `TokenBalance` per token, with `symbol`, `name`, `logoURI`, `decimals`, a human-readable `balance`, and (when you opt in) `price` and `marketValue`. Pass `includePrices` for USD figures and `filterSpamTokens` to drop junk tokens.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"system"}
    import {
      getTokenBalances,
      type WalletAccount,
    } from '@dynamic-labs-sdk/client';

    async function renderTokens(
      list: HTMLUListElement,
      walletAccount: WalletAccount,
    ) {
      const tokens = await getTokenBalances({
        walletAccount,
        includePrices: true,
        filterSpamTokens: true,
      });

      list.replaceChildren();
      for (const token of tokens) {
        const item = document.createElement('li');

        const icon = document.createElement('img');
        icon.src = token.logoURI;
        icon.alt = '';
        icon.width = 20;

        const value =
          token.marketValue !== undefined ? ` · $${token.marketValue.toFixed(2)}` : '';
        item.append(
          icon,
          document.createTextNode(`${token.balance} ${token.symbol}${value}`),
        );
        list.append(item);
      }
    }
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { type WalletAccount } from '@dynamic-labs-sdk/client';
    import { useGetTokenBalances } from '@dynamic-labs-sdk/react-hooks';

    function TokenList({ walletAccount }: { walletAccount: WalletAccount }) {
      const { data: tokens = [], isLoading } = useGetTokenBalances({
        walletAccount,
        includePrices: true,
        filterSpamTokens: true,
      });

      if (isLoading) return <p>Loading balances…</p>;

      return (
        <ul>
          {tokens.map((token) => (
            <li key={`${token.networkId}-${token.address}`}>
              <img src={token.logoURI} alt="" width={20} />
              <span>{token.balance} {token.symbol}</span>
              {token.marketValue !== undefined ? (
                <span>${token.marketValue.toFixed(2)}</span>
              ) : null}
            </li>
          ))}
        </ul>
      );
    }
    ```
  </Tab>
</Tabs>

<Note>
  `balance` is already scaled by the token's `decimals` for display. When you need the exact integer amount (for a transfer, say), use `rawBalanceString` — it preserves full precision that a JavaScript number can lose.
</Note>

## Options worth knowing

| Option             | Effect                                                            |
| ------------------ | ----------------------------------------------------------------- |
| `includePrices`    | Adds `price` and `marketValue` (USD) to each token.               |
| `filterSpamTokens` | Drops tokens flagged as spam — recommended for user-facing lists. |
| `includeNative`    | Includes the native asset as an entry in the token list.          |
| `networkIds`       | Fetch balances across several networks at once (multichain).      |
| `forceRefresh`     | Bypass any cached result and refetch.                             |

<Tip>
  For a portfolio across chains, pass `networkIds` (or use `getMultichainTokenBalances`) instead of calling per network — one request returns every network's holdings.
</Tip>

## Handling errors

| Situation           | What to do                                                                                                      |
| ------------------- | --------------------------------------------------------------------------------------------------------------- |
| `balance` is `null` | Treat as "unavailable" and show a placeholder; the fetch may still be resolving or the network RPC may be down. |
| Request rejects     | Keep the last known balances and offer a retry rather than clearing the UI.                                     |
| Empty token list    | The wallet holds nothing on the queried network(s) — show an empty state.                                       |

## See also

* [Connected wallets management](/docs/javascript/building-ui/connected-wallets-management) — pick which wallet to show balances for
* Transaction confirmation & simulation — spend the balance you display
* Network switching & validation — balances are per network
