---
title: EVM with EIP-6963 and EIP-1193
category: how-to
---

# EVM with EIP-6963 and EIP-1193

This guide shows how to connect to Ledger Wallet Provider from an EVM dApp and sign messages or transactions through [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) discovery and the [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) provider API.

Ledger Wallet Provider registers an EIP-1193 provider when you call `initializeLedgerProvider` with the EVM factory **and** Ethereum is enabled in your partner dApp configuration (`dAppIdentifier`).

> **Note:** Complete [Get started](../get-started) first so `initializeLedgerProvider` runs in the browser (use a dynamic import in SSR frameworks). Install `@ledgerhq/ledger-wallet-provider-evm`, pass `createEvmBlockchainProvider`, and confirm with Ledger that Ethereum is enabled for your dApp. Then follow this page for EIP-6963 discovery and signing.

## Prerequisites

```bash
npm install @ledgerhq/ledger-wallet-provider @ledgerhq/ledger-wallet-provider-evm
```

Initialize once at application startup (see [Get started](../get-started) and [Configuration](../configuration)):

```ts
import { initializeLedgerProvider } from '@ledgerhq/ledger-wallet-provider'
import { createEvmBlockchainProvider } from '@ledgerhq/ledger-wallet-provider-evm'
import '@ledgerhq/ledger-wallet-provider/styles.css'

const cleanup = initializeLedgerProvider({
  dAppIdentifier: 'my-dapp',
  apiKey: 'your-api-key',
  blockchainProviderFactories: [
    { family: 'ethereum', create: createEvmBlockchainProvider },
  ],
})

// Call cleanup() when your app unmounts to unregister the EVM provider too.
```

## Supported methods

After connection, use `provider.request({ method, params })`. Methods handled locally by Ledger include:

| Method                                       | Purpose                                            |
| -------------------------------------------- | -------------------------------------------------- |
| `eth_requestAccounts`                        | Open the Ledger UI and return the selected address |
| `eth_accounts`                               | Return the currently selected account              |
| `eth_chainId`                                | Return the current chain ID (hex)                  |
| `personal_sign` / `eth_sign`                 | Sign a message                                     |
| `eth_signTypedData` / `eth_signTypedData_v4` | Sign EIP-712 typed data                            |
| `eth_signTransaction`                        | Sign a transaction without broadcasting            |
| `eth_sendTransaction`                        | Sign and broadcast a transaction                   |
| `wallet_switchEthereumChain`                 | Switch to a supported chain ID                     |

Read methods such as `eth_call` and `eth_getBalance` are forwarded to the node RPC. See [API reference](../api-reference) for the full list, events, and error codes.

## Discover and connect

Listen for EIP-6963 announcements, then request accounts:

```ts
import type { EIP6963ProviderDetail } from '@ledgerhq/ledger-wallet-provider-evm'

let provider: EIP6963ProviderDetail['provider'] | undefined

window.addEventListener('eip6963:announceProvider', ((event: CustomEvent<EIP6963ProviderDetail>) => {
  const { provider: announced, info } = event.detail
  if (info.name.toLowerCase().includes('ledger')) {
    provider = announced
  }
}) as EventListener)

window.dispatchEvent(new Event('eip6963:requestProvider'))

if (!provider) {
  throw new Error('Ledger EVM provider not found. Call initializeLedgerProvider first.')
}

const accounts = await provider.request({
  method: 'eth_requestAccounts',
  params: [],
}) as string[]

const account = accounts[0]
```

> **Note:** **Registration:** A family is registered only when you pass its factory **and** it is enabled in your dApp config. EVM factory + Ethereum enabled → EIP-6963 / EIP-1193. Solana factory + Solana enabled → Wallet Standard. Both → both surfaces from the same `initializeLedgerProvider` call. Account pickers are filtered by the requesting family (`eth_requestAccounts` only lists EVM-compatible accounts).

## Sign a message

```ts
const signature = await provider.request({
  method: 'personal_sign',
  params: ['Hello from my EVM dApp', account],
})
```

For EIP-712 typed data, use `eth_signTypedData_v4` with your typed-data payload. Signing opens the Ledger Wallet Provider UI so the user can confirm on their device.

## Sign a transaction

```ts
const signedTx = await provider.request({
  method: 'eth_signTransaction',
  params: [
    {
      from: account,
      to: '0x…',
      value: '0x0',
      // gas, data, chainId, …
    },
  ],
})

// `signedTx` is the signed raw transaction (you broadcast yourself if needed)
```

## Sign and send a transaction

```ts
const txHash = await provider.request({
  method: 'eth_sendTransaction',
  params: [
    {
      from: account,
      to: '0x…',
      value: '0x0',
    },
  ],
})
```

## Switch chain

```ts
await provider.request({
  method: 'wallet_switchEthereumChain',
  params: [{ chainId: '0x1' }], // Ethereum mainnet
})
```

## Cleanup

Call the function returned by `initializeLedgerProvider` when your application unmounts. Cleanup removes the Ledger UI and unregisters any providers that were registered for your partner configuration.

```ts
const cleanup = initializeLedgerProvider({ /* options */ })

// Later:
cleanup()
```

## Troubleshooting

**The `eip6963:announceProvider` event never fires.**
Confirm `initializeLedgerProvider` ran in the browser before dispatching `eip6963:requestProvider`, that you passed `createEvmBlockchainProvider`, and that Ethereum is enabled for your `dAppIdentifier`. On unsupported platforms (no Web HID / Web Bluetooth), initialization is a no-op and no provider is registered — see [Requirements](../requirements).

**`request()` rejects with error code `4100` ("Unauthorized").**
Call `eth_requestAccounts` first, or the user disconnected. Request accounts again to reopen the Ledger UI.

**`request()` rejects with error code `-32603` and message "Ledger Provider is busy".**
Blocking requests (connect / sign) are handled one at a time. Wait for the current Ledger UI flow to finish before starting another.

## See also

- [Get started](../get-started) — install family packages and pass `blockchainProviderFactories`
- [Solana](./solana) — Wallet Standard connect and signing
- [Configuration](../configuration) — init options
- [API reference](../api-reference) — full EIP-1193 methods, events, and errors
- [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) / [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963)
