Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ckb-devrel/ccc/llms.txt

Use this file to discover all available pages before exploring further.

CCC supports wallets from multiple chain ecosystems — EVM, BTC, CKB, Nostr, and Doge — through a unified connector interface. You can drop in the pre-built connector UI or build your own using SignersController directly.

Installation

npm install @ckb-ccc/connector-react

React Integration

Wrap your application with ccc.Provider to make wallet state available throughout your component tree.
If you are using React Server Components, add "use client" at the top of any file that uses ccc.Provider. CCC’s UI components only run on the client side.
"use client";

import { ccc } from "@ckb-ccc/connector-react";

export default function App({ children }: { children: React.ReactNode }) {
  return (
    <ccc.Provider name="My App" icon="https://example.com/icon.png">
      {children}
    </ccc.Provider>
  );
}

Provider Props

PropTypeDescription
childrenReactNodeChild components
hideMarkbooleanHide the CCC watermark
namestringYour app name displayed in the connector
iconstringYour app icon URL displayed in the connector
signerFilter(signerInfo: ccc.SignerInfo, wallet: ccc.Wallet) => Promise<boolean>Filter which wallets/signers are shown
signersControllerccc.SignersControllerCustom signers controller instance
defaultClientccc.ClientDefault CKB client (testnet or mainnet)
clientOptions{ icon?: string; client: ccc.Client; name: string }[]Network switching options shown in the connector
preferredNetworksccc.NetworkPreference[]Preferred networks per signer type

useCcc() Hook

The useCcc hook returns all wallet state and control functions. It must be called from a component inside ccc.Provider.
"use client";

import { ccc } from "@ckb-ccc/connector-react";

export function ConnectButton() {
  const { isOpen, open, close, disconnect, setClient, client, wallet, signerInfo } =
    ccc.useCcc();

  return (
    <div>
      {signerInfo ? (
        <button onClick={disconnect}>Disconnect {wallet?.name}</button>
      ) : (
        <button onClick={open}>Connect Wallet</button>
      )}
    </div>
  );
}
Return valueTypeDescription
isOpenbooleanWhether the connector modal is currently open
open() => voidOpen the connector modal
close() => voidClose the connector modal
disconnect() => voidDisconnect the current wallet
setClient(client: ccc.Client) => voidSwitch to a different CKB client
clientccc.ClientCurrent CKB client (defaults to ClientPublicTestnet)
walletccc.Wallet | undefinedCurrently connected wallet (name, icon)
signerInfoccc.SignerInfo | undefinedCurrent signer info (name, signer)

useSigner() Hook

For quick access to the active signer instance, use useSigner:
"use client";

import { ccc } from "@ckb-ccc/connector-react";

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

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

  return (
    <button onClick={handleClick} disabled={!signer}>
      Get Address
    </button>
  );
}
useSigner() returns ccc.Signer | undefined. It is undefined when no wallet is connected.

Filtering Wallets

Use signerFilter on ccc.Provider to restrict which wallets appear. Return true to include a wallet or false to hide it.
<ccc.Provider
  signerFilter={async (signerInfo, wallet) => {
    // Only show CKB-native wallets
    return signerInfo.signer.type === ccc.SignerType.CKB;
  }}
>
  {children}
</ccc.Provider>

Preferred Networks

Use preferredNetworks to specify which network each wallet type should connect to. Wallets will attempt to switch automatically when a mismatch is detected.
<ccc.Provider
  preferredNetworks={[
    {
      addressPrefix: "ckb",
      signerType: ccc.SignerType.BTC,
      network: "btc",
    },
  ]}
>
  {children}
</ccc.Provider>
The NetworkPreference type:
type NetworkPreference = {
  addressPrefix: string; // "ckb" for mainnet, "ckt" for testnet
  signerType: SignerType;
  network: string;
  // BTC network values: "btc" | "btcTestnet" | "btcTestnet4" | "btcSignet" | "fractalBtc"
};

Custom UI with SignersController

To build your own wallet selection UI without the built-in modal, use SignersController directly. It discovers all available wallet extensions and returns them as a list of WalletWithSigners.
import { ccc } from "@ckb-ccc/ccc";

const controller = new ccc.SignersController();
let wallets: ccc.WalletWithSigners[] | undefined;

// Fetch all available signers
await controller.refresh(client, (w) => (wallets = w));
if (!wallets) {
  throw new Error("Unexpected not wallets");
}
wallets.forEach((wallet) => {
  console.log(
    wallet.name,
    wallet.signers.map(({ name }) => name),
  );
});

const signer = wallets[0].signers[0].signer;

// Connect signer
await signer.connect();
console.log("Connected");

// Sign message as test
const signature = await signer.signMessage("Hello world");
console.log(signature);

Direct Signer Instantiation

For applications that target a specific wallet without any selection UI:
import { ccc } from "@ckb-ccc/ccc";

// Provide your app name and icon to JoyID
const signer = new ccc.JoyId.CkbSigner(client, "CCC", "https://fav.farm/🇨");

// Connect signer
await signer.connect();
console.log("Connected");

// Sign an empty transaction as test
const signature = await signer.signTransaction({});
console.log(signature);

Supported Wallet Integrations

WalletSigner Type
JoyIDCKB
OKXBTC / EVM
UniSatBTC
UTXO GlobalBTC
XverseBTC
MetaMask / EIP-6963EVM
Nostr (NIP-07)Nostr
REIEVM
All imports use the ccc namespace:
import { ccc } from "@ckb-ccc/connector-react"; // React apps
import { ccc } from "@ckb-ccc/ccc";             // Custom UI / Node.js

Build docs developers (and LLMs) love