← Protocols
EIP-6963 — Multi Injected Provider Discovery
Standard / EIP·EVM

EIP-6963 — Multi Injected Provider Discovery

01Description

Final interface EIP that fixes the `window.ethereum` clobber problem by replacing the singleton injection with an event-based discovery protocol. Wallets dispatch `eip6963:announceProvider` and dapps dispatch `eip6963:requestProvider`, exchanging UUID-tagged provider details so users can pick from any installed wallet.

02Best for
  • 01supporting multiple injected wallets simultaneously
  • 02wallet selector UIs
  • 03avoiding window.ethereum overwrites
  • 04RDNS-keyed wallet identification
  • 05modern Connect flows
03Install
  • pnpm add mipd
  • pnpm add wagmi
  • pnpm add viem
05Prompt snippet
On the dapp side, listen for `window.addEventListener('eip6963:announceProvider', (e) => collect(e.detail))` BEFORE dispatching `window.dispatchEvent(new Event('eip6963:requestProvider'))` — order matters because wallets re-announce on request. Each `event.detail` is an `EIP6963ProviderDetail` with `info: { uuid, name, icon, rdns }` and `provider: EIP1193Provider`. Use `rdns` (reverse-DNS, e.g. `io.metamask`) as the stable identity key, never `name`. Persist the user's chosen `rdns` and re-resolve the provider on each load. Use `mipd` (Multi-Injected Provider Discovery) for a typed store, or wagmi's `injected({ target: { id: rdns } })` connector. Keep the listener attached for the page lifetime so late-injecting wallets (extension popups, deferred frames) still register.
06Gotchas
  • `window.ethereum` is unreliable under EIP-6963 — last-injected wallet wins and shadows others; never read it directly when 6963 announcements are available.
  • Listener-before-dispatch ordering: dispatching `requestProvider` before adding the `announceProvider` listener loses every announcement; always attach the listener first, then dispatch.
  • Duplicate announcements happen on every `requestProvider` — dedupe by `info.uuid` (per-page-load identity) or `info.rdns` (cross-load identity); not deduping renders the same wallet 3–5 times in your selector.
  • `rdns` is the only stable cross-session identifier — `uuid` regenerates per page load and `name` can collide (multiple 'MetaMask' forks); persist `rdns` for reconnection.
  • Some wallets (older Rabby, Trust) announce a provider but still inject `window.ethereum` — if you fall back to the singleton when 6963 yields zero providers, you'll double-count the same wallet.
  • Provider detail is meant to be frozen (`Object.freeze`) — mutating `event.detail.provider` breaks isolation between wallets and is forbidden by the spec.
07Alternatives