Skip to content

useBalance Hook

The useBalance hook fetches and watches an address balance on a given chain, pairing live USD conversion.

Import

import { useBalance } from "@scaffold-ui/hooks";

Usage

const {
  displayUsdMode,
  toggleDisplayUsdMode,
  formattedBalance,
  balanceInUsd,
  balance,
  isBalanceLoading,
  isBalanceError,
  isNativeCurrencyPriceLoading,
  isNativeCurrencyPriceError,
  isLoading,
  isError,
} = useBalance({
  address: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
  chain: mainnet,
  defaultUsdMode: true,
});

Parameters

ParameterTypeDefaultDescription
addressAddress (optional)-The address to watch. When omitted, the hook returns zeroed balance values.
chainChain-The viem chain configuration used for fetching balances and USD prices.
defaultUsdModeboolean (optional)falseIf true and price data is available, show USD values by default.

Return Values

PropertyTypeDescription
displayUsdModebooleanWhether the display is currently set to USD.
toggleDisplayUsdMode() => voidToggle between native and USD display (only active when price data exists).
formattedBalancenumberNative balance normalized with formatEther.
balanceInUsdnumberUSD value derived from formattedBalance * nativeCurrencyPrice.
balanceGetBalanceReturnType | undefinedRaw wagmi balance payload containing value, decimals, and symbol.
isBalanceLoadingbooleanLoading state for the balance fetch.
isBalanceErrorbooleanError state for the balance fetch.
isNativeCurrencyPriceLoadingbooleanLoading state for fetching the native currency price.
isNativeCurrencyPriceErrorbooleanError state for fetching the native currency price.
isLoadingbooleanCombined loading state: balance data or price is still loading.
isErrorbooleanCombined error state: balance data or price failed to load.

Live Examples

Basic Usage

Display a live balance with an inline USD toggle.

Balance: 0 ETH

import React from "react";
import { useBalance } from "@scaffold-ui/hooks";
import { mainnet } from "viem/chains";
 
function BalanceWithToggle() {
  const address = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045";
  const {
    formattedBalance,
    balanceInUsd,
    displayUsdMode,
    toggleDisplayUsdMode,
    isLoading,
  } = useBalance({
    address,
    chain: mainnet,
  });
 
  return (
    <div>
      <p>
        Balance: {displayUsdMode ? `${balanceInUsd.toLocaleString()}` : `${formattedBalance.toLocaleString()} ETH`}
      </p>
      <button onClick={toggleDisplayUsdMode} disabled={isLoading}>
        Toggle USD / ETH
      </button>
    </div>
  );
}

Loading and Error States

Handle asynchronous fetch states while keeping the toggle experience consistent.

Fetching balance…

import React, { useState } from "react";
import { useBalance } from "@scaffold-ui/hooks";
import { mainnet } from "viem/chains";
 
function BalanceWithLoadingStates() {
  const [isValidAddress, setIsValidAddress] = useState(true);
  const validAddress = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045";
  const brokenAddress = "0x";
  const {
    formattedBalance,
    balanceInUsd,
    displayUsdMode,
    toggleDisplayUsdMode,
    isLoading,
    isError,
  } = useBalance({
    address: isValidAddress ? validAddress : brokenAddress,
    chain: mainnet,
    defaultUsdMode: true,
  });
 
  if (isLoading) return <p>Fetching balance…</p>;
  if (isError) return (
    <div>
        <p style={{ color: "red" }}>Could not fetch balance</p>
        <button
            style={{ display: "block", padding: "8px", background: "#dae8ff", borderRadius: "4px", marginTop: "4px", border: "none", cursor: "pointer", color: "#000" }}
            onClick={() => setIsValidAddress((v) => !v)}
        >
            Fetch balance of the valid address
        </button>
    </div>
  );
 
  return (
    <div>
      <p>
        Balance: {displayUsdMode ? `${balanceInUsd.toLocaleString()}` : `${formattedBalance.toLocaleString()} ETH`}
      </p>
      <button onClick={toggleDisplayUsdMode}>Toggle USD / ETH</button>
      <button
        style={{ display: "block", padding: "8px", background: "#dae8ff", borderRadius: "4px", marginTop: "4px", border: "none", cursor: "pointer", color: "#000" }}
        onClick={() => setIsValidAddress((v) => !v)}
      >
        Try to fetch balance of the broken address
      </button>
    </div>
  );
}