@ckb-ccc/connector-react
React connector with Provider component and hooks for CKB wallet integration.
@ckb-ccc/connector-react is the recommended integration layer for React and Next.js applications. It provides a context Provider, a useCcc hook that exposes the full connector state, and a useSigner hook that returns the active signer whenever a wallet is connected.
Installation
npm install @ckb-ccc/connector-reactyarn add @ckb-ccc/connector-reactpnpm add @ckb-ccc/connector-reactQuick start
Place Provider at the root of your application (above any component that
needs wallet access).
import { ccc } from "@ckb-ccc/connector-react";
export default function App({ children }) {
return (
<ccc.Provider>
{children}
</ccc.Provider>
);
}Call useCcc() inside any descendant component to open the wallet picker
and read the connected wallet state.
import { ccc } from "@ckb-ccc/connector-react";
export function ConnectButton() {
const { open, wallet, signerInfo } = ccc.useCcc();
return (
<div>
<button onClick={open}>
{wallet ? `Connected: ${wallet.name}` : "Connect Wallet"}
</button>
{signerInfo && <Address />}
</div>
);
}
function Address() {
const { signerInfo } = ccc.useCcc();
const [address, setAddress] = React.useState("");
React.useEffect(() => {
signerInfo?.signer.getRecommendedAddress().then(setAddress);
}, [signerInfo]);
return <p>{address}</p>;
}Provider props
<ccc.Provider
hideMark={false}
name="My App"
icon="https://example.com/icon.png"
signerFilter={async (signerInfo, wallet) => true}
defaultClient={new ccc.ClientPublicTestnet()}
clientOptions={[
{ name: "Testnet", client: new ccc.ClientPublicTestnet() },
{ name: "Mainnet", client: new ccc.ClientPublicMainnet() },
]}
preferredNetworks={[{ addressPrefix: "ckb", signerType: ccc.SignerType.BTC, network: "btc" }]}
>
{children}
</ccc.Provider>| Prop | Type | Description |
|---|---|---|
children | ReactNode | Your application tree |
connectorProps | HTMLAttributes<{}>? | Additional props to pass to the connector element |
hideMark | boolean? | Hide the "Powered by CCC" mark in the connector UI |
name | string? | App name shown in the wallet picker |
icon | string? | App icon URL shown in the wallet picker |
signerFilter | (signerInfo, wallet) => Promise<boolean> | Filter which wallet/signer combinations appear |
signersController | ccc.SignersController? | Custom signers controller (advanced) |
defaultClient | ccc.Client? | The initial network client |
clientOptions | { icon?, client, name }[]? | Network options to display in the connector |
preferredNetworks | ccc.NetworkPreference[]? | Networks to prefer when a wallet supports multiple |
useCcc() hook
const {
isOpen, // boolean — whether the wallet picker modal is open
open, // () => void — open the wallet picker
close, // () => void — close the wallet picker
disconnect, // () => void — disconnect the current wallet
setClient, // (client: ccc.Client) => void — switch network
client, // ccc.Client — current network client
wallet, // ccc.Wallet | undefined — connected wallet
signerInfo, // ccc.SignerInfo | undefined — connected signer
} = ccc.useCcc();The hook throws if called outside a <ccc.Provider> tree.
Full example
"use client"; // Required for Next.js App Router
import { ccc } from "@ckb-ccc/connector-react";
import { useState, useEffect } from "react";
function Layout({ children }: { children: React.ReactNode }) {
return (
<ccc.Provider
name="My CKB App"
defaultClient={new ccc.ClientPublicTestnet()}
>
<Header />
{children}
</ccc.Provider>
);
}
function Header() {
const { open, disconnect, wallet, signerInfo, client } = ccc.useCcc();
const [address, setAddress] = useState("");
useEffect(() => {
if (!signerInfo) {
setAddress("");
return;
}
signerInfo.signer.getRecommendedAddress().then(setAddress);
}, [signerInfo]);
return (
<header>
{wallet ? (
<>
<span>{address}</span>
<button onClick={disconnect}>Disconnect</button>
</>
) : (
<button onClick={open}>Connect</button>
)}
</header>
);
}Filtering wallets
Use signerFilter to show only specific wallet types:
import { ccc } from "@ckb-ccc/connector-react";
// Show only CKB-native wallets
<ccc.Provider
signerFilter={async (signerInfo, wallet) => {
return signerInfo.signer.type === ccc.SignerType.CKB;
}}
>
{children}
</ccc.Provider>Next.js (App Router)
CCC's connector uses React context and browser APIs, so it only works on the client side. Add "use client" to any file that imports from @ckb-ccc/connector-react or renders <ccc.Provider>.
"use client";
import { ccc } from "@ckb-ccc/connector-react";Forgetting "use client" in Next.js App Router will cause a runtime error:
TypeError: (0, react....createContext) is not a function.