Create, transfer, query, and melt Spore Protocol NFTs on CKB. Spore stores all NFT content on-chain inside CKB cells — no external storage required.
Spore Protocol is CKB’s native NFT standard. Unlike most NFT systems, Spore stores all content — images, text, binary data — directly inside CKB cells. There is no IPFS link or external server that can go offline. Burning (melting) a Spore releases the stored CKB capacity back to the owner.
Use createSpore() to mint a new NFT. Pass a SporeDataView that describes the content type and raw content bytes.
import { ccc, createSpore } from "@ckb-ccc/spore";const { tx, id } = await createSpore({ signer, data: { contentType: "text/plain", content: new TextEncoder().encode("Hello, Spore!"), },});// Complete capacity inputs and pay the network feeawait tx.completeInputsByCapacity(signer);await tx.completeFeeBy(signer);const txHash = await signer.sendTransaction(tx);console.log("Spore ID:", id);console.log("Transaction hash:", txHash);
createSpore() returns:
tx — a transaction skeleton with the Spore output and required cell deps. You must call completeInputsByCapacity(signer) and completeFeeBy(signer) before broadcasting.
id — the unique spore ID (a hex string) that identifies this NFT permanently on-chain.
When a Spore includes a clusterId, CCC must prove that the signer has permission to add a Spore to the cluster. The clusterMode parameter controls how this is done.
lockProxy (recommended)
Adds a cell that shares the same lock as the cluster cell to both inputs and outputs. Suitable for public clusters where membership is proved by controlling the right lock script.
clusterCell
Puts the cluster cell itself into the transaction inputs and outputs. Use this for private clusters where you own the cluster cell directly.
skip
Does not add any cluster-related inputs or outputs. Use only when you have already handled the cluster logic manually, or for testing.
If clusterId is set in the Spore data and clusterMode is not provided, createSpore() throws an error. Always specify a clusterMode when using clusters.
findSpores() searches by lock script and optional cluster ID. Use it when you want to query spores for an arbitrary address rather than the connected signer.