web3icons

What makes a good wallet icon

Where wallet icons appear, from connect modals to extension toolbars and home screens, what makes one hold up, and which files wallet teams should ship.

6 min read

A wallet's icon spends most of its life in places the wallet team doesn't design. It sits in a row of eight other wallets in some dApp's connect modal, at 16 px in a crowded browser toolbar, on a phone home screen masked into whatever shape the operating system likes, and inside a data URI that the wallet's own extension hands to the websites its user visits.

So a good wallet icon is mostly about surviving those contexts. This guide walks through each one and lists the files a wallet team should publish so that dApps and designers don't have to improvise.

Where wallet icons show up

Context Typical size Who controls the container Background
dApp connect modal 28 to 48 px The dApp Light or dark, unknown in advance
Browser extension toolbar 16 px, rendered at 2x on dense screens The browser The browser theme, light or dark
Phone home screen Set by the OS The operating system, which applies its own mask Your icon's own background
EIP-6963 provider list Whatever the dApp chooses The dApp Light or dark
Docs, blog posts, partner pages 24 to 128 px Whoever writes the page Anything

Two things stand out. The icon is almost always shown inside someone else's container, cropped, masked or placed on a background you didn't choose. And it lands on both light and dark surfaces, often within the same product.

The app icon is the identity

People install a wallet as an app or an extension, and they see its app icon every day: on their home screen, in their toolbar, in their app switcher. That rounded square, with the mark on the brand's own background, is what they recognize. When a dApp lists wallets, the most useful thing it can show is that same picture.

This is why wallets, unlike tokens, are usually shown as rounded squares. A dApp that clips every wallet into a circle, or shows only the bare mark, makes users work a little harder to match it to the app on their phone. Circle or square? covers mixing wallet squares with round token icons.

For the wallet team, that means the square app icon is the primary asset, not an afterthought for the app store. Design it first, and derive everything else from it.

What makes the icon hold up

Keep the mark in the center. Phone operating systems mask app icons into their own shapes, Android launchers can choose between several, and dApps may round the corners further or clip to a circle. Anything near the corners or edges will be cut somewhere, so treat the outer band as background only. Apple's and Android's design guidelines give the exact safe areas; check the current versions when you export.

Give the square icon its own background. A full-bleed background color makes the icon look the same on a white modal, a dark modal and a gray toolbar. A transparent app icon looks different in every one of those places and may disappear in some.

Design for 16 px. The toolbar is the harshest test: 16 by 16 CSS pixels next to a dozen other extensions. One bold shape, two or three colors, no text, no thin outlines, no subtle gradients. If the icon only works at 64 px, it doesn't work.

Be distinguishable from the neighbors. A connect modal is a lineup. Shields, keys, wallets and coins are common motifs, and blue is a common color. Put your icon in a mock modal next to the wallets your users are likely to have installed and check that it's identifiable at a glance by shape alone, not only by its name label.

Use the same mark everywhere. The extension toolbar, the mobile app, the EIP-6963 announcement and the press kit should show the same picture, so someone connecting from a dApp recognizes the icon they clicked in their toolbar a minute ago. Keep seasonal and campaign variants out of the provider info.

The EIP-6963 icon

EIP-6963 lets several injected wallets coexist in one browser. Each wallet announces itself with a provider info object containing a uuid, a name, an icon and an rdns identifier. The icon is a data URI: the image travels inside a string, with no network request. For an extension wallet, this is often the icon a dApp puts in its wallet list, so it deserves the same care as the app icon.

// provider is your EIP-1193 provider object
const info = Object.freeze({
  uuid: crypto.randomUUID(),
  name: 'Example Wallet',
  icon: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...',
  rdns: 'com.example.wallet',
})

function announce() {
  window.dispatchEvent(
    new CustomEvent('eip6963:announceProvider', {
      detail: Object.freeze({ info, provider }),
    }),
  )
}

window.addEventListener('eip6963:requestProvider', announce)
announce()

Use the square app icon here, with its background, because you don't know what the dApp's modal looks like. The EIP asks for a square image with a minimum resolution, so read the current text before exporting. An optimized SVG is usually best: sharp at any size, and a simple icon fits in a few kilobytes. Check that it has a viewBox, no scripts or external references, and no live text.

To produce the string from a file:

echo "data:image/svg+xml;base64,$(base64 -w0 wallet-icon.svg)"

The -w0 flag turns off line wrapping in GNU base64; macOS base64 doesn't wrap by default, so leave the flag out there.

If you build the dApp side

The icon comes from whatever extension the user installed, so treat it as untrusted input. Render it with an <img> element, where SVG scripts don't run, and never inject it as inline markup. Check that it is an image data URI before using it:

type ProviderInfo = { uuid: string; name: string; icon: string; rdns: string }

export function WalletOption({ info }: { info: ProviderInfo }) {
  const icon = info.icon.startsWith('data:image/') ? info.icon : undefined

  return (
    <button type="button">
      {icon && <img src={icon} alt="" width={32} height={32} />}
      <span>{info.name}</span>
    </button>
  )
}

The wallet's name is visible text inside the button, so the image gets an empty alt and the button's accessible name is the wallet name. More on that in making wallet connection modals accessible, and on untrusted SVG in Is SVG safe?.

What a wallet team should publish

dApp developers and designers need your icon in forms you can't predict, and without the right file they may resort to screenshots. A small, clearly labeled kit prevents that:

Asset Format Used for
Square app icon, full-bleed background SVG, plus PNG at 1024 px Connect modals, docs, partner pages, app stores
Mark only, transparent background SVG, light and dark versions Interfaces that supply their own container
Single-color mark SVG Monochrome UIs, print, watermarks
Extension toolbar icons PNG at the sizes your target browsers ask for The manifest; Chrome's documentation lists 16, 32, 48 and 128 px
EIP-6963 icon Optimized SVG as a data URI The provider announcement
Name and spelling Plain text Labels, so nobody writes "Examplewallet"

Put it all on one press page with a single download, state which uses are fine, and keep file names descriptive (example-wallet-app-icon.svg, not logo-final-2.svg). Press kits and brand guidelines covers what else that page should include.

To see how wallet marks and their background versions compare side by side, browse the wallets in the icon library; MetaMask, Phantom and Rainbow are a good place to start.

More in Icon design

All guides