web3icons

Empty states in wallets and dashboards

What an empty balance, empty activity feed or empty NFT tab should explain and offer, how to tell empty from loading, and how to avoid dead ends.

5 min read

Every new wallet starts empty, and so does every portfolio dashboard on its first visit. Empty screens are where newcomers form their first impression and where experienced users wonder whether something broke. A screen that says only "No tokens" answers neither group: it doesn't say why, and it doesn't say what to do.

A good empty state does three things. It confirms the screen is working, explains what will appear there, and offers the action that fills it. This guide covers the different kinds of empty, the common screens in wallets and dashboards, and wording that avoids dead ends.

First, make sure it's actually empty

The most damaging empty state is a false one. "You have no tokens" shown while balances are still loading, or after an RPC request quietly failed, tells someone their funds are gone. Model loading, failure and empty as three separate states, and only show the empty message when you know the answer is zero:

type Load<T> =
  | { status: 'loading' }
  | { status: 'error'; retry: () => void }
  | { status: 'ready'; data: T }

function Balances({ state }: { state: Load<Token[]> }) {
  if (state.status === 'loading') return <BalanceSkeleton rows={4} />
  if (state.status === 'error') {
    return (
      <p>
        We couldn't load balances right now. Your funds are not affected.{' '}
        <button type="button" onClick={state.retry}>Try again</button>
      </p>
    )
  }
  if (state.data.length === 0) return <EmptyBalances />
  return <TokenList tokens={state.data} />
}

The error message carries one important phrase: "Your funds are not affected." When a balance view fails, that's the first thing people worry about.

Kinds of empty

Not all empty screens mean the same thing, and the copy should differ:

Kind Example What to say
First use New wallet, no balance What will appear and how to start
Nothing here, on this network Funds exist on another chain Where the funds are, how to see them
Nothing matches Search or filter returns no results The query, and how to clear it
Everything hidden Only spam tokens, all hidden How many are hidden and where
Not yet indexed A transaction just confirmed, activity not updated That it can take a moment, with an explorer link

The second row is easy to miss. A wallet or dashboard showing one network can look empty while the person holds funds elsewhere. If you can check other networks, say so: "No balance on Base. You have funds on Ethereum and Arbitrum One." with a button to switch view. If you can't check, at least name the network being shown: "Showing balances on Base."

Empty balance

For a new wallet, the empty balance screen is effectively the start of onboarding. Offer the actions that get funds in, in order of how people usually do it:

Your wallet is empty

Add crypto to get started. You can receive it from another wallet or exchange, or buy it here.

Receive · Buy

"Receive" should lead to the address with a QR code, the network name and logo, and a note to send on that network only. Keep any illustration small. A large graphic pushes the actions below the fold on phones and adds nothing the text doesn't say. If you use an icon, a single mono glyph in a muted color fits better than a colorful scene.

For a dashboard that watches an address read-only, the action is different: there's nothing to buy, so offer to watch another address or to connect a wallet.

No activity

An empty activity feed should say what will appear there, so people know where to look later:

No activity yet. Your sends, swaps and receipts will appear here.

If the person just completed a transaction and the feed hasn't caught up, which can happen when activity comes from an indexer, don't show the plain empty message. Show the pending or recent transaction you already know about from your own state, and add "Can take a moment to appear" with a link to the block explorer.

No NFTs

The NFT tab has its own version of the problem. Some people don't know what NFTs are, and many wallets receive spam NFTs that should stay hidden by default. Two adjustments help:

  • If nothing is held at all, a one-line explanation is enough: "NFTs you own will appear here." Don't push people toward buying them.
  • If items exist but are all hidden as possible spam, say so with a count: "3 items hidden as possible spam. Show hidden." An empty screen that's secretly hiding things feels like a bug when the person finds out.

The difference between collection images and token logos also matters on this tab; see NFT images vs token logos.

No search results

When a filter or search returns nothing, repeat what they searched for and give a way out:

No tokens match "arbb". Check the spelling, or paste a contract address to search by address.

Clear search

For a token search, "paste a contract address" is a useful hint, because it leads to the import flow for tokens that aren't listed. For a filter, show which filters are active and a single button to reset them all.

Writing the copy

A few patterns cover most empty states:

Instead of Write
No data No activity yet. Your sends, swaps and receipts will appear here.
0 tokens No balance on Base. Funds on other networks aren't shown here.
Nothing found No tokens match "arbb".
Error We couldn't load balances. Your funds are not affected. Try again.

Keep it to one or two sentences and one primary action. Use the same wording for the same situation everywhere in the product. And avoid jokes in empty financial screens: a playful message on an empty wallet can read as mocking to someone who thinks their funds are missing.

Empty states overlap heavily with first-run experience, which onboarding people who are new to crypto covers, and with multichain display, covered in designing for many chains.

More in Web3 UX

All guides