



`@ckb-ccc/xverse` integrates [Xverse Wallet](https://www.xverse.app/) and any [SATS Connect](https://docs.xverse.app/sats-connect) compatible Bitcoin wallet into CCC. It provides a `SignerBtc` implementation using the SATS Connect RPC protocol, supporting multi-wallet discovery via `window.btc_providers`.

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

## Installation [#installation]

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

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

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

  <Tab value="pnpm">
    ```bash
    pnpm add @ckb-ccc/xverse
    ```
  </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/xverse` uses the `window.btc_providers` array to discover multiple SATS Connect wallets simultaneously.

<Mermaid
  chart="graph TB
    subgraph &#x22;Xverse Package&#x22;
        GXS[&#x22;getXverseSigners(client)&#x22;]
        S[&#x22;Signer (extends SignerBtc)&#x22;]
    end

    subgraph &#x22;Discovery&#x22;
        BTP[&#x22;window.btc_providers[]&#x22;]
    end

    subgraph &#x22;Wallets&#x22;
        XV[&#x22;Xverse&#x22;]
        Other[&#x22;Any SATS Connect wallet&#x22;]
    end

    GXS -->|&#x22;reads&#x22;| BTP
    BTP --- XV
    BTP --- Other
    GXS -->|&#x22;creates per provider&#x22;| S
    S --> Core[&#x22;@ckb-ccc/core (SignerBtc)&#x22;]"
/>

### Entry point: `getXverseSigners` [#entry-point-getxversesigners]

`getXverseSigners(client, preferredNetworks?)` reads from `window.btc_providers` and returns a `{ wallet, signerInfo }[]` array — one entry per discovered wallet:

<Mermaid
  chart="graph TD
    Start[&#x22;getXverseSigners(client)&#x22;] --> Check[&#x22;window.btc_providers exists?&#x22;]
    Check -->|No| Empty[&#x22;return []&#x22;]
    Check -->|Yes| Iter[&#x22;For each provider in btc_providers&#x22;]
    Iter --> Create[&#x22;new Signer(client, getProviderById(provider.id))&#x22;]
    Create --> Result[&#x22;{ wallet: {name, icon}, signerInfo: {name: 'BTC', signer} }&#x22;]"
/>

Each provider entry includes wallet metadata (`name`, `icon`) allowing `SignersController` to display distinct wallet entries.

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

`Signer` extends `ccc.SignerBtc` and uses the SATS Connect RPC protocol for all wallet interactions.

### Key methods [#key-methods]

| Method                    | Description                                                |
| ------------------------- | ---------------------------------------------------------- |
| `connect()`               | Calls `wallet_requestPermissions` if not already connected |
| `disconnect()`            | Clears the cached address                                  |
| `isConnected()`           | Attempts `getBalance` — returns `true` on success          |
| `getBtcAccount()`         | Returns the payment address via `getAddresses`             |
| `getBtcPublicKey()`       | Returns the public key from the payment address            |
| `signMessageRaw(message)` | Signs via `signMessage` with ECDSA protocol                |
| `onReplaced(listener)`    | Fires on `accountChange` or `networkChange` events         |

### Connection and address caching [#connection-and-address-caching]

The signer caches the resolved address to avoid redundant RPC calls. The cache is invalidated on `disconnect()`:

<Mermaid
  chart="sequenceDiagram
    participant App as Application
    participant Signer as Xverse Signer
    participant Wallet as Xverse Extension

    App->>Signer: connect()
    Signer->>Signer: isConnected()?
    alt Not connected
        Signer->>Wallet: wallet_requestPermissions
        Wallet->>Signer: granted
    end
    App->>Signer: getBtcAccount()
    Signer->>Wallet: getAddresses({purposes: [Payment]})
    Wallet->>Signer: addresses[0]
    Signer->>Signer: Cache address
    Signer->>App: address.address"
/>

### Network preferences [#network-preferences]

| CKB Network     | Default BTC Network |
| --------------- | ------------------- |
| Mainnet (`ckb`) | `btc`               |
| Testnet (`ckt`) | `btcTestnet`        |

### Signing flow [#signing-flow]

<Mermaid
  chart="sequenceDiagram
    participant App as Application
    participant Signer as Xverse Signer
    participant Wallet as Xverse Extension

    App->>Signer: sendTransaction(tx)
    Signer->>Signer: prepareTransaction(tx)
    Note over Signer: Add CellDeps, prepare witnesses
    Signer->>Wallet: signMessage({message, address, protocol: ECDSA})
    Wallet->>Signer: {signature}
    Signer->>Signer: Pack signature into witness
    Signer->>App: txHash"
/>

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

`Signer` implements `onReplaced()` via the SATS Connect event API:

* Listens for `"accountChange"` — user switched BTC account
* Listens for `"networkChange"` — user switched BTC network

Returns cleanup functions from `provider.addListener()` for proper teardown.

## SATS Connect RPC methods [#sats-connect-rpc-methods]

| Method                      | Description                                                 |
| --------------------------- | ----------------------------------------------------------- |
| `wallet_requestPermissions` | Request wallet connection permissions                       |
| `getAddresses`              | Get addresses filtered by purpose (Payment, Ordinals, etc.) |
| `getBalance`                | Get wallet balance (used for connection check)              |
| `signMessage`               | Sign a message with ECDSA or BIP-322                        |

## Integration pattern [#integration-pattern]

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

* **Factory function** — `getXverseSigners` returns `{ wallet, signerInfo }[]` for multi-wallet support.
* **Provider detection** — reads `window.btc_providers` array.
* **Multi-wallet discovery** — creates separate signer entries per provider with distinct wallet names and icons.
* **Graceful degradation** — returns an empty array when no SATS Connect wallets are available.


---

> ## 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.
