Skip to main content
EIP-6963 enables dapps to discover multiple wallet providers and wallets to announce themselves without conflicts.

Overview

Traditional wallet injection (window.ethereum) creates conflicts when multiple wallets are installed. EIP-6963 solves this by:
  • Dapps: Subscribe to wallet announcements, discover all available wallets
  • Wallets: Announce themselves with metadata (name, icon, identifier)

Dapp Usage

Subscribe to Announcements

import * as EIP6963 from '@voltaire/provider/eip6963';

const unsubscribe = EIP6963.subscribe((providers) => {
  console.log(`Found ${providers.length} wallets`);

  for (const { info, provider } of providers) {
    console.log(`- ${info.name} (${info.rdns})`);
  }
});

// Cleanup when done
unsubscribe();
The listener is called immediately with current providers, then again whenever new providers announce.

Find Specific Provider

import * as EIP6963 from '@voltaire/provider/eip6963';

// Start discovery
const unsubscribe = EIP6963.subscribe(() => {});

// Find MetaMask by reverse DNS
const metamask = EIP6963.findProvider({ rdns: 'io.metamask' });

if (metamask) {
  const accounts = await metamask.provider.request({
    method: 'eth_requestAccounts'
  });
  console.log('Connected:', accounts[0]);
}

unsubscribe();

Get Current Providers

import * as EIP6963 from '@voltaire/provider/eip6963';

// Start discovery
const unsubscribe = EIP6963.subscribe(() => {});

// Get snapshot of all providers
const providers = EIP6963.getProviders();
console.log(providers.map(p => p.info.name));

unsubscribe();

Wallet Usage

For wallet developers: announce your provider to dapps.
import * as EIP6963 from '@voltaire/provider/eip6963';

const unsubscribe = EIP6963.announce({
  info: {
    uuid: crypto.randomUUID(),
    name: "My Wallet",
    icon: "data:image/svg+xml;base64,PHN2Zy...",
    rdns: "com.mywallet"
  },
  provider: myEIP1193Provider
});

// On extension unload
unsubscribe();
The wallet automatically re-announces when dapps request providers.

Types

ProviderInfo

Wallet metadata:
type ProviderInfo = Readonly<{
  uuid: string;   // UUIDv4 unique to session
  name: string;   // Human-readable name
  icon: string;   // Data URI (>=96x96px)
  rdns: string;   // Reverse DNS (e.g., "io.metamask")
}>;

ProviderDetail

Complete announcement:
type ProviderDetail = Readonly<{
  info: ProviderInfo;
  provider: EIP1193Provider;
}>;

Constructors

Create validated, frozen objects:
import * as EIP6963 from '@voltaire/provider/eip6963';

const info = EIP6963.ProviderInfo({
  uuid: "350670db-19fa-4704-a166-e52e178b59d2",
  name: "Example Wallet",
  icon: "data:image/svg+xml;base64,PHN2Zy...",
  rdns: "com.example.wallet"
});

console.log(Object.isFrozen(info)); // true

Environment Detection

EIP-6963 only works in browsers. Use getPlatform() to check:
import * as EIP6963 from '@voltaire/provider/eip6963';

const platform = EIP6963.getPlatform();
// 'browser' | 'node' | 'bun' | 'worker' | 'unknown'

if (platform === 'browser') {
  // Safe to use EIP-6963
}

Error Handling

All errors extend EIP6963Error:
import * as EIP6963 from '@voltaire/provider/eip6963';

try {
  EIP6963.subscribe(() => {});
} catch (error) {
  if (error instanceof EIP6963.UnsupportedEnvironmentError) {
    console.log(`Not supported: ${error.platform}`);
  }
}

Error Types

ErrorCodeWhen
UnsupportedEnvironmentErrorUNSUPPORTED_ENVIRONMENTNot in browser
InvalidUuidErrorINVALID_UUIDUUID not v4 format
InvalidRdnsErrorINVALID_RDNSRDNS not valid format
InvalidIconErrorINVALID_ICONIcon not data URI
InvalidProviderErrorINVALID_PROVIDERNo request() method
MissingFieldErrorMISSING_FIELDRequired field missing
InvalidArgumentErrorINVALID_ARGUMENTBad function argument

Security

Icon XSS Prevention: Always render wallet icons via <img src={icon}> elements. Never inject icon content directly into the DOM, as malicious SVG icons could contain scripts.

Common RDNS Values

WalletRDNS
MetaMaskio.metamask
Coinbase Walletcom.coinbase.wallet
Rainbowme.rainbow
Trust Walletcom.trustwallet.app
Rabbyio.rabby

API Reference

Dapp Functions

FunctionDescription
subscribe(listener)Subscribe to announcements, returns unsubscribe
getProviders()Get current providers snapshot
findProvider({ rdns })Find provider by RDNS

Wallet Functions

FunctionDescription
announce({ info, provider })Announce provider, returns unsubscribe

Utilities

FunctionDescription
getPlatform()Detect runtime environment
ProviderInfo(input)Create validated ProviderInfo
ProviderDetail(input)Create validated ProviderDetail

See Also