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

# Connect Wallet

> Add multi-wallet support to your React app using the CCC connector. Supports MetaMask, JoyID, UniSat, OKX, UTXO Global, and Nostr in a single integration.

CCC ships a ready-made React connector that surfaces a wallet picker UI supporting wallets from EVM, BTC, Nostr, and native CKB ecosystems — all through a single `<ccc.Provider>` wrapper.

## Supported wallets

<CardGroup cols={3}>
  <Card title="MetaMask" icon="ethereum">
    EVM-based signing via MetaMask and other EVM-compatible wallets.
  </Card>

  <Card title="JoyID" icon="fingerprint">
    Passkey-based CKB wallet — no seed phrase required.
  </Card>

  <Card title="UniSat" icon="bitcoin-sign">
    BTC wallet with CKB support via the UniSat extension.
  </Card>

  <Card title="OKX" icon="wallet">
    OKX wallet supporting BTC, EVM, and CKB signers.
  </Card>

  <Card title="UTXO Global" icon="globe">
    UTXO-based multi-chain wallet with CKB integration.
  </Card>

  <Card title="Nostr" icon="key">
    Sign with a Nostr key pair for decentralized identity.
  </Card>
</CardGroup>

## Steps

<Steps>
  <Step title="Install the package">
    Add `@ckb-ccc/connector-react` to your project.

    <Tabs>
      <Tab title="npm">
        ```bash theme={null}
        npm install @ckb-ccc/connector-react
        ```
      </Tab>

      <Tab title="yarn">
        ```bash theme={null}
        yarn add @ckb-ccc/connector-react
        ```
      </Tab>

      <Tab title="pnpm">
        ```bash theme={null}
        pnpm add @ckb-ccc/connector-react
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Wrap your app in the Provider">
    Import `ccc` from the connector package and wrap your application root with `<ccc.Provider>`. The `Provider` injects the connector UI and context that all child components can access.

    ```tsx app.tsx theme={null}
    import { ccc } from "@ckb-ccc/connector-react";

    export function App() {
      return (
        <ccc.Provider>
          <YourApp />
        </ccc.Provider>
      );
    }
    ```

    <Tip>
      If you are using Next.js with the App Router, add `"use client"` at the top of any file that renders `<ccc.Provider>` or uses the CCC hooks, because they rely on React context and browser APIs.
    </Tip>

    ### Provider props

    | Prop                | Type                                       | Description                                                                                                          |
    | ------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
    | `name`              | `string`                                   | App name shown in the wallet picker.                                                                                 |
    | `icon`              | `string`                                   | App icon URL shown in the wallet picker.                                                                             |
    | `defaultClient`     | `ccc.Client`                               | Override the default CKB client (defaults to testnet).                                                               |
    | `clientOptions`     | `{ name, icon, client }[]`                 | List of network options for the user to switch between.                                                              |
    | `preferredNetworks` | `ccc.NetworkPreference[]`                  | Networks to prefer for each signer type; the connector prompts the wallet to switch if it is on a different network. |
    | `signerFilter`      | `(signerInfo, wallet) => Promise<boolean>` | Filter which signers appear in the picker.                                                                           |

    ```tsx app.tsx theme={null}
    import { ccc } from "@ckb-ccc/connector-react";

    const mainnetClient = new ccc.ClientPublicMainnet();
    const testnetClient = new ccc.ClientPublicTestnet();

    export function App() {
      return (
        <ccc.Provider
          name="My CKB App"
          icon="https://example.com/icon.png"
          defaultClient={testnetClient}
          clientOptions={[
            { name: "Mainnet", client: mainnetClient },
            { name: "Testnet", client: testnetClient },
          ]}
        >
          <YourApp />
        </ccc.Provider>
      );
    }
    ```
  </Step>

  <Step title="Read wallet state with useCcc()">
    Call `useCcc()` inside any component that is a descendant of `<ccc.Provider>`. It returns the current connection state and actions.

    ```tsx wallet-button.tsx theme={null}
    import { ccc } from "@ckb-ccc/connector-react";

    export function WalletButton() {
      const { open, disconnect, wallet, signerInfo } = ccc.useCcc();

      if (signerInfo) {
        return (
          <div>
            <p>Connected: {wallet?.name}</p>
            <button onClick={disconnect}>Disconnect</button>
          </div>
        );
      }

      return <button onClick={open}>Connect Wallet</button>;
    }
    ```

    ### Return values

    | Value        | Type                           | Description                                        |
    | ------------ | ------------------------------ | -------------------------------------------------- |
    | `open`       | `() => void`                   | Opens the wallet picker modal.                     |
    | `close`      | `() => void`                   | Closes the wallet picker modal.                    |
    | `disconnect` | `() => void`                   | Disconnects the current wallet.                    |
    | `wallet`     | `ccc.Wallet \| undefined`      | The currently connected wallet (name and icon).    |
    | `signerInfo` | `ccc.SignerInfo \| undefined`  | The active signer with name and `signer` instance. |
    | `client`     | `ccc.Client`                   | The active CKB client.                             |
    | `isOpen`     | `boolean`                      | Whether the wallet picker modal is open.           |
    | `setClient`  | `(client: ccc.Client) => void` | Switch the active client programmatically.         |

    <Warning>
      `useCcc()` throws if the component is rendered outside of `<ccc.Provider>`. Make sure the Provider wraps your entire component tree before using the hook.
    </Warning>
  </Step>

  <Step title="Get the signer with useSigner()">
    Use the `useSigner()` shorthand when you only need the `Signer` object to build and send transactions.

    ```tsx transfer-button.tsx theme={null}
    import { ccc } from "@ckb-ccc/connector-react";

    export function TransferButton() {
      const signer = ccc.useSigner();

      async function handleSend() {
        if (!signer) return;
        const address = await signer.getRecommendedAddress();
        console.log("My address:", address);
      }

      return (
        <button onClick={handleSend} disabled={!signer}>
          Get Address
        </button>
      );
    }
    ```

    `useSigner()` returns `undefined` when no wallet is connected, so always check before using it.
  </Step>
</Steps>

## Filter signers

Use `signerFilter` to restrict which wallets appear in the picker. The function receives a `ccc.SignerInfo` and the parent `ccc.Wallet`, and must return a promise that resolves to `true` to include the signer or `false` to hide it.

```tsx app.tsx theme={null}
import { ccc } from "@ckb-ccc/connector-react";

export function App() {
  return (
    <ccc.Provider
      signerFilter={async (signerInfo, wallet) => {
        // Show only CKB-type signers
        return signerInfo.signer.type === ccc.SignerType.CKB;
      }}
    >
      <YourApp />
    </ccc.Provider>
  );
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="Send CKB" icon="paper-plane" href="/guides/send-ckb">
    Build and broadcast a CKB transfer with the signer you just connected.
  </Card>

  <Card title="Sign Message" icon="pen" href="/guides/sign-message">
    Request a signed message from the connected wallet.
  </Card>
</CardGroup>
