State Compression Basics
8 examples to get you started with state compression and cNFTs - 6 basic and 2 intermediate.
Prerequisites
npm install @solana/kit@7.0.0 @metaplex-foundation/mpl-bubblegum @metaplex-foundation/mpl-account-compressionDAS-enabled RPC required for proof reads. SPL Account Compression program: cmtDvXnzBMY46rZyrBGX7p7r4Xc78DGpXEC5rVjrvAf.
Basic Examples
1. Why Compression Exists
Full NFT mint accounts cost rent per item. Compression amortizes cost across millions of leaves.
// Full NFT: ~several accounts per item
// cNFT: one tree account + leaf hash updates per mint- Game inventories and POAPs drove adoption
- On-chain root proves integrity; leaves updated with proofs
- Trade-off: reliance on indexer for proof data
Related: Cost & Trade-offs
2. Concurrent Merkle Tree
Concurrent Merkle Trees allow multiple updates per slot without serializing entire tree rewrites.
const TREE_PROGRAM = "cmtDvXnzBMY46rZyrBGX7p7r4Xc78DGpXEC5rVjrvAf";
// Tree account stores root, canopy, and change log- Tree capacity chosen at creation (power of 2 depth)
- Canopy caches upper proof nodes on-chain to shrink proof size
- Deeper trees support more assets but cost more rent upfront
Related: How Compression Works
3. Bubblegum Program
Bubblegum mints and transfers compressed NFTs into trees.
const BUBBLEGUM_PROGRAM = "BGUMAp9Gq7iN3nEkgqX1FbwwdBonfLCEEgxoj36SYPk";- Metaplex metadata schema in compressed format
- Collection and creator fields supported
- Primary program for mass NFT drops in 2026
Related: Compressed NFTs (Bubblegum)
4. Read cNFT via DAS
Wallets do not decode merkle leaves manually.
const asset = await dasRpc("getAsset", { id: "CNFT_ASSET_ID" });
console.log(asset.compression?.leaf_id, asset.compression?.tree);compressionobject on DAS asset responseinterfaceoftenCompressedNft- Standard RPC
getAccountInfoon asset id is not sufficient
Related: Reading Compressed Assets (DAS)
5. Fetch Proof for Transfers
Transfers need merkle proof path from DAS.
const proof = await dasRpc("getAssetProof", { id: "CNFT_ASSET_ID" });
console.log(proof.root, proof.proof.length);- Proof length depends on tree depth minus canopy
- Stale proof fails transaction - refresh before send
- Store
rootused at build time for debugging failures
Related: Transferring cNFTs
6. Tree Authority and Delegates
Tree creator controls minting; delegates can be granted for custodial mint services.
# Tree created with tree authority signer
# Bubblegum mint CPIs update leaf under authority rules- Compromised tree authority can corrupt tree state
- Use multisig for production tree authority
- Document delegate permissions if using hosted mint APIs
Related: Compressed NFTs (Bubblegum)
Intermediate Examples
7. Mint 10k cNFTs (Outline)
// 1. createTree (depth/maxBufferSize/canopy per capacity plan)
// 2. mintV1 in loop or batch transactions
// 3. monitor leaf index via DAS getAssetsByGroup- Batch mints across multiple transactions to avoid size limits
- Priority fees during competitive mint windows
- Indexer lag means delayed gallery after mint
Related: Compression Best Practices
8. When Not to Use Compression
| Use cNFT | Use Core / Token Metadata |
|---|---|
| 10k+ similar items | 1/1 fine art |
| Low per-item cost priority | Maximum wallet simplicity |
| DAS-backed read stack | Heavy on-chain program composability per NFT |
- On-chain programs cannot treat cNFT as simple SPL account
- Composability requires proof-aware instructions
Related: NFT Basics on Solana
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.