> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ckbccc.com/llms.txt - append ".md" to any page URL for its Markdown source.
> Use this file to discover all available pages before exploring further.

---
# @ckb-ccc/xverse
URL: https://docs.ckbccc.com/en/docs/packages/wallet-integrations/xverse
Source: https://raw.githubusercontent.com/ckb-devrel/ccc/refs/heads/dev/packages/docs/content/docs/packages/wallet-integrations/xverse.mdx
> Connect Xverse and SATS Connect compatible wallets to CKB — Bitcoin signing through a unified Signer interface.




`@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)` reads from `window.btc_providers`. Xverse and providers supporting the WBIP network methods get separate Mainnet, Testnet4, Signet, and Regtest entries; legacy providers retain a single `BTC` entry.

<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;Create fixed-network signers&#x22;]
    Create --> Result[&#x22;BTC / BTC Testnet4 / Signet / Regtest&#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()`               | Requests permissions and switches to the selected network                     |
| `disconnect()`            | Clears the cached address                                                     |
| `isConnected()`           | Checks the selected network, then reads the payment address without prompting |
| `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
    opt Fixed-network signer
        Signer->>Wallet: wallet_getNetwork
        Wallet->>Signer: current network
        alt Network differs from selected network
            Signer->>Wallet: wallet_changeNetwork({name: selectedNetwork})
            Wallet->>Signer: switched
            Signer->>Signer: Clear cached address
        end
    end
    App->>Signer: getBtcAccount()
    Signer->>Wallet: getAddresses({purposes: [Payment]})
    Wallet->>Signer: addresses[0]
    Signer->>Signer: Cache address
    Signer->>App: address.address"
/>

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