> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# EIP-6963: Multi Injected Provider Discovery

> Discover multiple wallet providers and allow wallets to announce themselves

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

```typescript theme={null}
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

```typescript theme={null}
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

```typescript theme={null}
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.

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
type ProviderDetail = Readonly<{
  info: ProviderInfo;
  provider: EIP1193Provider;
}>;
```

## Constructors

Create validated, frozen objects:

```typescript theme={null}
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:

```typescript theme={null}
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`:

```typescript theme={null}
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

| Error                         | Code                      | When                   |
| ----------------------------- | ------------------------- | ---------------------- |
| `UnsupportedEnvironmentError` | `UNSUPPORTED_ENVIRONMENT` | Not in browser         |
| `InvalidUuidError`            | `INVALID_UUID`            | UUID not v4 format     |
| `InvalidRdnsError`            | `INVALID_RDNS`            | RDNS not valid format  |
| `InvalidIconError`            | `INVALID_ICON`            | Icon not data URI      |
| `InvalidProviderError`        | `INVALID_PROVIDER`        | No request() method    |
| `MissingFieldError`           | `MISSING_FIELD`           | Required field missing |
| `InvalidArgumentError`        | `INVALID_ARGUMENT`        | Bad function argument  |

## Security

<Warning>
  **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.
</Warning>

## Common RDNS Values

| Wallet          | RDNS                  |
| --------------- | --------------------- |
| MetaMask        | `io.metamask`         |
| Coinbase Wallet | `com.coinbase.wallet` |
| Rainbow         | `me.rainbow`          |
| Trust Wallet    | `com.trustwallet.app` |
| Rabby           | `io.rabby`            |

## API Reference

### Dapp Functions

| Function                 | Description                                     |
| ------------------------ | ----------------------------------------------- |
| `subscribe(listener)`    | Subscribe to announcements, returns unsubscribe |
| `getProviders()`         | Get current providers snapshot                  |
| `findProvider({ rdns })` | Find provider by RDNS                           |

### Wallet Functions

| Function                       | Description                            |
| ------------------------------ | -------------------------------------- |
| `announce({ info, provider })` | Announce provider, returns unsubscribe |

### Utilities

| Function                | Description                     |
| ----------------------- | ------------------------------- |
| `getPlatform()`         | Detect runtime environment      |
| `ProviderInfo(input)`   | Create validated ProviderInfo   |
| `ProviderDetail(input)` | Create validated ProviderDetail |

## See Also

* [EIP-6963 Specification](https://eips.ethereum.org/EIPS/eip-6963)
* [EIP-1193 Provider](/jsonrpc-provider/index)
