Skip to main content
A Client is your connection to the CKB network. It wraps the CKB JSON-RPC, handles request caching, and exposes higher-level helpers for finding cells and transactions. Every other CCC abstraction — signers, transactions, addresses — depends on a client to talk to the chain.

Instantiate a client

CCC ships two ready-to-use implementations that connect to the public RPC endpoints:
import { ccc } from "@ckb-ccc/ccc";

const client = new ccc.ClientPublicMainnet();
Both classes automatically prefer a WebSocket transport when the environment supports it, and fall back to HTTPS otherwise. Pass a url option to point at your own node:
const client = new ccc.ClientPublicMainnet({ url: "https://my-node.example.com/" });
ClientPublicMainnet uses the address prefix ckb; ClientPublicTestnet uses ckt.

Query chain state

Tip block

const tipBlockNumber = await client.getTip();
console.log(tipBlockNumber); // e.g. 14000000n

Blocks and headers

const block = await client.getBlockByNumber(14000000n);
const alsoBlock = await client.getBlockByHash("0xabc...");

const header = await client.getHeaderByNumber(14000000n);
Both methods return undefined when the block does not exist, and cache confirmed results automatically.

Fee rate

// Median fee rate over the last N blocks (defaults to a recent window)
const feeRate = await client.getFeeRate();

// With a custom block range
const feeRate24h = await client.getFeeRate(100n);

// Cap the fee rate so you never overpay
const cappedFeeRate = await client.getFeeRate(undefined, { maxFeeRate: 2000n });

Find cells

Use findCells to iterate over live cells that match a search key. It merges cached cells with on-chain results so you never miss a freshly sent cell:
const lock = { codeHash: "0x...", hashType: "type", args: "0x..." };

for await (const cell of client.findCells({ script: lock, scriptType: "lock", scriptSearchMode: "exact", withData: true })) {
  console.log(cell.cellOutput.capacity);
}
Two convenience wrappers cover the most common cases:
// All cells locked by a specific lock script
for await (const cell of client.findCellsByLock(lock)) { ... }

// All cells with a specific type script
for await (const cell of client.findCellsByType(typeScript)) { ... }

Find transactions

findTransactions returns an async generator of transaction records for any lock or type script:
for await (const tx of client.findTransactionsByLock(lock)) {
  console.log(tx.txHash, tx.blockNumber);
}
Pass groupByTransaction: true to receive one record per transaction instead of one record per input/output:
for await (const grouped of client.findTransactionsByLock(lock, undefined, true)) {
  console.log(grouped.txHash);
}

Send a transaction

After you build and sign a transaction, submit it with sendTransaction:
const txHash = await client.sendTransaction(signedTx);
console.log("sent:", txHash);
sendTransaction validates the fee rate against a configurable maximum before broadcasting.

Wait for confirmation

// Wait up to 60 s with at least 1 confirmation
const response = await client.waitTransaction(txHash, 1, 60_000);

KnownScript

The KnownScript enum lets you reference well-known on-chain scripts by name instead of hard-coding code hashes. Call client.getKnownScript() to retrieve the deployment info (code hash, hash type, and cell deps) for any entry:
const info = await client.getKnownScript(ccc.KnownScript.Secp256k1Blake160);
console.log(info.codeHash);
Available entries:
Enum valueDescription
NervosDaoNervos DAO deposit/withdraw script
Secp256k1Blake160Standard single-sig lock
Secp256k1MultisigStandard multisig lock
AnyoneCanPayAnyone-can-pay lock
TypeIdType ID script
XUdtxUDT fungible token type
JoyIdJoyID passkey lock
OmniLockOmniLock (EVM / BTC compatible)
NostrLockNostr event lock
COTACoTA NFT type
UniqueTypeUnique cell type
TimeLockTime-locked cells
Script availability varies by network. Calling getKnownScript for a script that is not deployed on the current network throws an error.