



`@ckb-ccc/eip6963` exposes any [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) compatible browser wallet (MetaMask, Rabby, OKX EVM, etc.) as a CCC `Signer`. It signs CKB transactions via `personal_sign` EVM signatures and derives CKB addresses from the user's Ethereum account.

<Callout type="info">
  If you're using `@ckb-ccc/connector-react` or `@ckb-ccc/ccc`, EIP-6963 wallets are already included — no separate installation needed.
</Callout>

## Installation [#installation]

<PackageBadges pkg="@ckb-ccc/eip6963" />

<Tabs items="['npm', 'yarn', 'pnpm']">
  <Tab value="npm">
    ```bash
    npm install @ckb-ccc/eip6963
    ```
  </Tab>

  <Tab value="yarn">
    ```bash
    yarn add @ckb-ccc/eip6963
    ```
  </Tab>

  <Tab value="pnpm">
    ```bash
    pnpm add @ckb-ccc/eip6963
    ```
  </Tab>
</Tabs>

**Dependencies:**

| Package         | Description                                              |
| --------------- | -------------------------------------------------------- |
| `@ckb-ccc/core` | Base types — `Signer`, `Client`, `Transaction`, and more |

## Architecture [#architecture]

Unlike other wallet packages that detect a single global provider, `@ckb-ccc/eip6963` uses the EIP-6963 **multi-injected provider discovery** standard. This means it can discover and create signers for *all* EVM wallets installed in the browser simultaneously.

<Mermaid
  chart="graph TB
    subgraph &#x22;EIP-6963 Package&#x22;
        SF[&#x22;SignerFactory&#x22;]
        S[&#x22;Signer (extends SignerEvm)&#x22;]
    end

    subgraph &#x22;Discovery&#x22;
        E6963[&#x22;eip6963:announceProvider events&#x22;]
        Legacy[&#x22;window.ethereum (fallback)&#x22;]
    end

    subgraph &#x22;Wallets&#x22;
        MM[&#x22;MetaMask&#x22;]
        RB[&#x22;Rabby&#x22;]
        OKX[&#x22;OKX EVM&#x22;]
        Other[&#x22;Any EIP-6963 wallet&#x22;]
    end

    SF -->|&#x22;listens&#x22;| E6963
    SF -->|&#x22;fallback&#x22;| Legacy
    E6963 --- MM
    E6963 --- RB
    E6963 --- OKX
    E6963 --- Other
    SF -->|&#x22;creates&#x22;| S
    S --> Core[&#x22;@ckb-ccc/core (SignerEvm)&#x22;]"
/>

### Entry point: `SignerFactory` [#entry-point-signerfactory]

`SignerFactory` is the main entry point. It listens for `eip6963:announceProvider` events and creates a `Signer` for each unique wallet discovered:

<Mermaid
  chart="graph TD
    Start[&#x22;new SignerFactory(client)&#x22;] --> Sub[&#x22;subscribeSigners(callback)&#x22;]
    Sub --> Listen[&#x22;Listen eip6963:announceProvider&#x22;]
    Sub --> Request[&#x22;Dispatch eip6963:requestProvider&#x22;]
    Sub --> Fallback[&#x22;Check window.ethereum&#x22;]

    Listen -->|&#x22;New provider&#x22;| Dedup[&#x22;UUID already seen?&#x22;]
    Dedup -->|&#x22;No&#x22;| Create[&#x22;new Signer(client, provider)&#x22;]
    Dedup -->|&#x22;Yes&#x22;| Skip[&#x22;Skip&#x22;]
    Create --> CB[&#x22;callback(signer, detail)&#x22;]
    Fallback -->|&#x22;exists&#x22;| Create2[&#x22;new Signer(client, ethereum)&#x22;]
    Create2 --> CB"
/>

## The `Signer` class [#the-signer-class]

`Signer` extends `ccc.SignerEvm` and adapts any EIP-1193 compatible provider to CKB signing.

### Key methods [#key-methods]

| Method                    | Description                                                 |
| ------------------------- | ----------------------------------------------------------- |
| `connect()`               | Calls `eth_requestAccounts` to prompt wallet connection     |
| `isConnected()`           | Checks if `eth_accounts` returns any account                |
| `getEvmAccount()`         | Returns the first EVM address from the provider             |
| `signMessageRaw(message)` | Signs via `personal_sign` — used for CKB witness generation |
| `onReplaced(listener)`    | Fires on `accountsChanged` or `disconnect` events           |

### Signing flow [#signing-flow]

CKB transactions are signed by deriving a CKB address from the EVM account and using `personal_sign` to produce a witness signature:

<Mermaid
  chart="sequenceDiagram
    participant App as Application
    participant Signer as EVM Signer
    participant Wallet as EVM Wallet (e.g. MetaMask)

    App->>Signer: sendTransaction(tx)
    Signer->>Signer: prepareTransaction(tx)
    Note over Signer: Add CellDeps, prepare witnesses
    Signer->>Wallet: personal_sign(message, account)
    Wallet->>Signer: signature (65 bytes)
    Signer->>Signer: Pack signature into witness
    Signer->>App: txHash"
/>

## Account change detection [#account-change-detection]

`Signer` implements `onReplaced()` to handle account or wallet disconnection:

* Listens for `"accountsChanged"` — user switched account in wallet
* Listens for `"disconnect"` — wallet disconnected

When either fires, the application callback is invoked and the listener is automatically cleaned up.

## Provider interface (EIP-1193) [#provider-interface-eip-1193]

The package uses a minimal subset of the EIP-1193 provider interface:

| Method                | Purpose                                  |
| --------------------- | ---------------------------------------- |
| `eth_requestAccounts` | Prompt user to connect                   |
| `eth_accounts`        | Get connected accounts (no prompt)       |
| `personal_sign`       | Sign a message with the selected account |

## Integration pattern [#integration-pattern]

`@ckb-ccc/eip6963` follows the same integration contract as other wallet packages in CCC:

* **Factory class** — `SignerFactory` discovers wallets and creates signers dynamically.
* **Provider detection** — uses EIP-6963 events with `window.ethereum` fallback.
* **Deduplication** — tracks provider UUIDs to avoid duplicate signers.
* **Graceful degradation** — if no EVM wallets are installed, no signers are created.

This means `SignersController` can dynamically discover all EVM wallets without any configuration.


---

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