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.
- 01supporting multiple injected wallets simultaneously
- 02wallet selector UIs
- 03avoiding window.ethereum overwrites
- 04RDNS-keyed wallet identification
- 05modern Connect flows
- pnpm add mipd
- pnpm add wagmi
- pnpm add viem
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.
- ⚑`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.