Guide to Streaming and Retrieving cNFT Events
1. Understanding cNFTs and Their Event Lifecycle
On Solana, Compressed NFTs (cNFTs) differ from traditional NFTs in a crucial way:
Traditional NFTs each have their own mint address and token account.
Compressed NFTs store data within a Merkle tree managed by the related cNFT program. This single on-chain account holds the Merkle tree root, and each NFT is represented as a leaf in that tree.
Key Points:
A cNFT mint adds a new leaf.
A cNFT transfer updates the ownership data in the existing leaf.
A cNFT burn removes or invalidates the leaf from the tree.
Because cNFTs lack typical token accounts, standard Solana NFT tracking methods (e.g., “watch the mint address” or “subscribe to a token account”) won’t work. Instead, you focus on program instructions or the Merkle tree account.
2. Why Stream cNFT Events?
Imagine building a marketplace, wallet, or analytics dashboard around cNFTs. You need to know:
When new cNFTs are minted.
Which cNFTs are transferred to or from a user.
Whether a cNFT was burned.
Receiving these updates in real time helps you keep your interface or data layer in perfect sync with on-chain state. Combined with historical lookups, you gain a complete timeline of cNFT activity, from the moment it was created to its current status.
3. Real-Time Streaming Methods
Helius offers three major ways to stream cNFT events. Below is a recap of each approach.
3.1 WebSockets (Standard & Enhanced)
Persistent connection: You subscribe to accounts or programs, and Solana pushes updates.
Enhanced WebSocket with advanced filters (
accountInclude
,accountRequired
, etc.).Reduces parsing overhead because you only receive transactions relevant to your addresses.
3.2 Webhooks
Webhooks let Helius notify your server via HTTP POST whenever an on-chain event occurs. Ideal if you don’t want a persistent connection.
Specify addresses to watch (Merkle tree address, user wallet, etc.).
Receive transaction data on your server endpoint; parse for cNFT instructions.
Creating a Webhook (API Example):
3.3 gRPC (Yellowstone)
gRPC is the most flexible and high-performance streaming solution, available on Dedicated Nodes.
Advanced filtering (memcmp, owners, accounts, etc.).
Enterprise-level throughput for large-scale apps.
Example (TypeScript with reconnection logic shortened):
4. Retrieving Historical cNFT Data
Real-time feeds are great for capturing future events. But what if you need the past—the entire lifetime of a cNFT or all transactions that impacted a Merkle tree or wallet?
In this section, we’ll explore two primary methods for historical lookups:
Helius’ Parsed Transaction API
Normal Solana RPC Calls:
getSignaturesForAddress
+getParsedTransaction
orgetTransaction
4.1 Helius’ Parsed Transaction API
Helius offers an Enriched or Parsed Transaction API. It automatically decodes NFT, SPL, and Swap transactions into a human-readable format. This saves you from manually parsing raw data.
4.1.1 Single or Batched Transactions (/v0/transactions
)
Endpoint:
Mainnet:
https://api.helius.xyz/v0/transactions?api-key=<YOUR_API_KEY>
Devnet:
https://api-devnet.helius.xyz/v0/transactions?api-key=<YOUR_API_KEY>
You send up to 100 transaction signatures in the request body, and Helius returns an array of parsed transactions.
Example:
Within each parsed transaction, you may find a compressed
object under events
, indicating a cNFT mint, transfer, or burn:
4.1.2 Parsed Transaction History by Address (/v0/addresses/{address}/transactions
)
If you want parsed transactions for a specific address—say a Merkle tree or user wallet—you can call:
Mainnet:
https://api.helius.xyz/v0/addresses/{address}/transactions?api-key=<YOUR_API_KEY>
Devnet:
https://api-devnet.helius.xyz/v0/addresses/{address}/transactions?api-key=<YOUR_API_KEY>
Example:
4.2 Normal Methods: getSignaturesForAddress
+ getParsedTransaction
/ getTransaction
getSignaturesForAddress
+ getParsedTransaction
/ getTransaction
If you prefer the traditional Solana approach or want maximum control, you can call Solana’s native RPC methods:
getSignaturesForAddress
: Returns an array of transaction signatures involving the given address (e.g., the Merkle tree or user’s wallet).getParsedTransaction
: Returns a Solana-parsed JSON for a given signature.getTransaction
: Returns the raw binary-encoded transaction, which you can parse using an external library (e.g., Blockbuster) if you need specialized cNFT decoding.
4.2.1 getSignaturesForAddress
This is a pagination-friendly method. You can pass before
or until
to walk backward or forward through transaction history.
Example:
4.2.2 getParsedTransaction
or getTransaction
Once you have the signatures, retrieve each transaction’s details:
Look for instructions referencing the cNFT program or the Merkle tree. If you use getTransaction
instead, you’ll get raw data (e.g., base64), which you’d decode with a specialized parser.
5. Putting It All Together
Stream cNFT Events
Pick a method: WebSockets, Webhooks, or gRPC.
Filter for the cNFT program or a Merkle tree address.
Parse instructions in real time to track mints, transfers, and burns.
Retrieve Historical Data
Helius Parsed Transaction API: The easiest way to get a human-readable breakdown of cNFT actions.
Normal RPC:
getSignaturesForAddress
+getParsedTransaction
(orgetTransaction
+ manual parsing) for maximum flexibility or if you already rely on standard Solana RPC calls.
Build a Complete Timeline
Merge future (real-time) events with past (historical) data.
If your streaming solution ever goes down, fill gaps by pulling recent transaction signatures for your Merkle tree or user address.
6. Next Steps and Best Practices
Leverage Helius: The Parsed Transaction API is particularly handy if you want cNFT events (mints, transfers, burns) in a straightforward JSON format.
Pagination: For addresses with a lot of activity, you may need to iterate with
before
oruntil
to get older data.Verification: For extra security, you can verify Merkle proofs to confirm a cNFT leaf is valid under the on-chain root.
Indexing: If you’re building a large-scale solution, consider storing parsed cNFT events in your own database for quick queries.
Performance: For high-volume streaming, a Dedicated Node + gRPC approach offers top performance and advanced filters.
Happy building!
Last updated
Was this helpful?