Solana NFT & Compressed cNFT Tracking: Why a Wallet Read Isn't Enough (2026)
Solana NFT & Compressed cNFT Tracking: Why a Wallet Read Isn't Enough (2026)
Reviewed by Wag3s Editorial Team — verified against the Solana state-compression model, the Metaplex Bubblegum cNFT standard, and the indexer-retrieval requirement · Last reviewed May 2026
Solana NFT & Compressed cNFT Tracking: Why a Wallet Read Isn't Enough
What is unique about Solana NFT tracking is that the cheapest and most common Solana NFTs, compressed NFTs, are not stored in a wallet's accounts at all: their data is hashed into a Concurrent Merkle Tree with only the root on-chain, reachable only through an indexer. Read the accounts and stop, and you silently under-report the portfolio. This guide is the cNFT model and the discovery split it forces, one spoke of the broader multi-wallet aggregation problem on Solana.
Why cNFTs need a different discovery path
- A cNFT uses state compression: data is hashed into a Concurrent Merkle Tree, with only the root on-chain and updates in the ledger.
- The Metaplex Bubblegum program powers cNFTs (mint, transfer and update go through Bubblegum).
- A cNFT is not in a normal Solana account, so a plain account scan misses it.
- Discovery needs an indexer (e.g. Metaplex Read API implementers), not a token-account read.
- Two discovery paths are required: direct account reads for uncompressed Metaplex NFTs plus indexer queries for cNFTs.
- Tax is jurisdiction-specific: track the mechanics, confirm tax separately.
What compression actually does
A compressed NFT uses Solana state compression: the NFT data is hashed into a Concurrent Merkle Tree, and only the tree's root is stored on-chain (in a single account), with updates recorded in the Solana ledger. This makes minting drastically cheaper than an uncompressed Metaplex NFT. The Metaplex Bubblegum program is the smart contract powering cNFTs, and mint, transfer and update instructions all go through Bubblegum. The ownership concept is unchanged; the storage and retrieval are not.
Cost comparison: uncompressed vs compressed
The cost difference explains why cNFTs are now dominant for high-volume mints (gaming items, loyalty tokens, large PFP collections):
- Uncompressed Metaplex NFT: ~0.012 SOL per mint (account rent for metadata + mint accounts).
- Compressed cNFT: ~0.000005 SOL per mint at scale (shared tree storage amortised across thousands of NFTs).
At 100,000-NFT collection scale, the cost difference is roughly 1,200 SOL vs 0.5 SOL for the tree. This means major gaming projects and high-volume drops almost exclusively use cNFTs — making cNFT coverage critical for any complete Solana NFT portfolio.
Why a wallet read misses cNFTs
This is the crux. A cNFT is not stored in a traditional Solana account. Its metadata lives off the normal account model, in the ledger, verifiable against the Merkle root. So a plain account scan will not surface it. Enumerating a wallet's cNFTs requires an indexing service, such as those implementing the Metaplex Read API. A tracker that only reads accounts, the correct method for SPL token accounts, misses every compressed NFT. That is a silent completeness failure, not a visible error.
Two discovery paths, one portfolio
| NFT type | Discovery |
|---|---|
| Uncompressed Metaplex NFT | Direct on-chain account read |
| Compressed NFT (cNFT) | Indexer query against the Merkle tree |
A complete Solana NFT portfolio must cover both. Treating all Solana NFTs as one discovery model leaves a gap, and because cNFTs are often minted at scale, the gap can be large. This is the Solana-NFT analogue of the aggregation completeness problem.
Compression doesn't make it less real
A cNFT is still an asset held by a wallet, verifiable against the on-chain Merkle root. The practical difference is discovery and proof (indexer plus Merkle proof), not whether it counts. It should be tracked and valued like any other NFT (see NFT portfolio valuation); the discovery method is the only structural change.
Verifying cNFT ownership with a Merkle proof
To prove ownership of a cNFT without trusting only an indexer, the tracker can request a Merkle proof from the indexer and verify it against the on-chain tree root:
- Fetch the asset proof from the indexer:
GET /getAssetProof?id={assetId}(Metaplex Read API). - The response includes
root,proof(array of sibling hashes),leaf(hash of the asset data), andnode_index. - Recompute the root: hash the leaf with each proof element in sequence.
- Compare the computed root to the value stored in the on-chain tree account (
getConcurrentMerkleTreeAccountSizedata). - If they match, the ownership claim is cryptographically verified, not just indexer-attested.
Step-by-step: how to track Solana NFTs including cNFTs
- Discover uncompressed NFTs via account reads. Call
getTokenAccountsByOwneron the Solana RPC, filtering forprogramId = TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA(Token Program). Filter results for mint decimals = 0 and supply = 1 (NFT criteria). Then fetch the Metaplex metadata account for each mint. - Discover compressed NFTs via the Metaplex Read API. Call
getAssetsByOwner(ownerAddress, {interface: "V1_NFT"})or the equivalent DAS (Digital Asset Standard) endpoint on an indexer such as Helius, Triton, or the Metaplex hosted API. This returns cNFTs where the indexer has indexed the Bubblegum tree. - Merge the two result sets. De-duplicate by asset ID (each NFT has a unique ID regardless of compression). The combined list is the complete Solana NFT inventory for the address.
- For each cNFT, record the tree address and leaf index. These are needed to construct Merkle proofs for ownership verification and transfer transactions.
- Track transfer history. For uncompressed NFTs, monitor
Transferevents on the SPL Token Program. For cNFTs, monitorTransferinstructions on the Bubblegum program (bgUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY) filtered by the owner address as theleafOwner. - Compute acquisition cost. For mint transactions, the cost is the SOL paid (mint price + transaction fee). For secondary purchases (OpenSea, Magic Eden, Tensor), read the sale amount from the marketplace instruction data.
- Apply the jurisdiction cost-basis method for disposals; confirm NFT characterisation with an adviser.
Common errors and how to fix them
Error 1 — Querying only SPL Token Program accounts for NFTs. This finds uncompressed NFTs but returns nothing for cNFTs, silently dropping the compressed portion of the portfolio. Fix: always run both the account-scan path and the indexer-query path and merge results.
Error 2 — Trusting a single indexer for complete cNFT coverage. Indexers may have partial coverage of Merkle trees, especially for recently minted collections or very large trees. Relying on one indexer risks missing NFTs. Fix: use multiple indexer sources and cross-reference; flag discrepancies for manual review.
Error 3 — Recording cNFT mint cost as zero. Because cNFT minting is very cheap, trackers may default to a zero or negligible cost basis. For NFTs minted via a paid collection mint (where the user pays a mint price), the actual acquisition cost can be significant. Fix: parse the marketplace or minting contract instruction to extract the exact SOL (or token) amount paid.
Error 4 — Missing cNFT transfers in the transaction history. Bubblegum transfers are not SPL Token transfers — they are Bubblegum program instructions. A tracker monitoring only SPL Token Transfer events will miss every cNFT transfer. Fix: monitor Bubblegum program instructions (setDecompress, transfer, burn) separately from SPL Token events.
Tax is jurisdiction-specific
Whether a cNFT disposal is taxable, and how, is jurisdiction-specific and must not be assumed, the same as any NFT (see NFT cost basis and disposal). The compression and indexer mechanics are the tracking layer; the tax characterisation is separate and adviser-confirmed.
Practical guidance
- Use two discovery paths: account reads for uncompressed NFTs, an indexer for cNFTs.
- Require an indexer (Metaplex Read API class); a wallet scan alone is incomplete.
- Reconcile cNFTs against the Merkle root for proof of holding.
- Value cNFTs like any NFT, since compression changes discovery, not the asset.
- Confirm tax treatment of cNFT disposals per jurisdiction.
- Treat missing cNFT coverage as a completeness failure, not a minor gap.
Choosing a tool for Solana NFTs
Koinly and Zerion both support Solana NFTs, but compression is where coverage quietly fails. Before you trust a Solana NFT figure, confirm the tool:
- runs both discovery paths, the SPL token account scan for uncompressed NFTs and a DAS / Metaplex Read API indexer query (
getAssetsByOwner) for cNFTs; - monitors Bubblegum program instructions for cNFT transfers, not just SPL Token
Transferevents, which never fire for cNFTs; - can verify a holding against the on-chain Merkle root rather than trusting a single indexer, and ideally cross-references more than one indexer;
- parses the actual mint or marketplace price for cNFT cost basis instead of defaulting a paid mint to zero.
Account-only discovery silently drops the compressed portion of the portfolio, which is often the largest.
How Wag3s handles it
Wag3s Folio discovers both uncompressed Metaplex NFTs (account reads) and compressed cNFTs (indexer against the Merkle tree), reconciles cNFTs to the on-chain root, values them like any NFT, and surfaces the result for the jurisdiction-specific tax characterisation. See the Folio product page.
Further reading
- Solana Portfolio Tracking
- Bitcoin Ordinals Portfolio Tracking
- NFT Portfolio Valuation
- NFT Cost Basis and Disposal Tracking
- Cross-Chain NFT Portfolio
- Multi-Chain Portfolio Aggregation Beyond EVM
Sources
- Solana state compression — NFT data hashed into a Concurrent Merkle Tree; only the root stored on-chain; updates in the ledger
- Metaplex Bubblegum program powers compressed NFTs; cNFTs are not in a traditional Solana account and require an indexer (Metaplex Read API class) to retrieve
- Two discovery paths: direct account reads (uncompressed Metaplex NFTs) vs indexer queries (compressed NFTs)
Bitcoin Ordinals Portfolio Tracking: Sats, Inscriptions, and the UTXO Trap (2026)
A Bitcoin Ordinal is not an ERC-721 — it is content inscribed on a specific satoshi, moving through Bitcoin UTXOs first-in-first-out. There is no contract or tokenId, and an inscribed sat can be spent as a fee by accident. Why Ordinals tracking is a UTXO and sat-control problem, not a token-balance one.
NFT Portfolio Valuation: There Is No Single True Price (2026)
Floor price, last sale, trait-based value, and a model estimate all give different numbers for the same NFT — and the floor is often fake. Why a portfolio must pick and disclose a valuation basis, treat illiquidity honestly, and never value a specific NFT at the collection floor.
Every chain, integration, and competitor mentioned in this article gets its own page — coverage detail, comparison signals, and the audit trail your finance team needs.
- Chain
Solana
SPL tokens, native stake, Jupiter, Metaplex NFTs.
View page - Chain
Ethereum
ERC-20, DeFi, gas, restaking — the largest ecosystem.
View page - Integration
NetSuite integration
Mid-market and enterprise crypto subledger.
View page - Integration
QuickBooks integration
SMB GL with daily JE sync.
View page - Integration
Safe integration
DAO and corporate multi-sig accounting.
View page - Compare
Wag3s vs Cryptio
Side-by-side enterprise subledger comparison.
View page