quicknode-cascade
Stream blockchain data at scale. Plugin-based framework powered by QuickNode Cascade — an edge-cached block archive served from 300+ global PoPs with sub-50ms latency.
Start with Solana. More chains coming soon.
Install
Quick Start
use ;
;
That's it. The runner fetches blocks in parallel, extracts structured data, and calls your plugin hooks. You bring your own database, your own schema, your own logic.
CascadeRunner
Builder-pattern runner that handles all parallel fetching, retries, cursor management, and plugin lifecycle.
Chain Selection
use CascadeRunner;
// Solana mainnet
solana_mainnet
// Solana devnet
solana_devnet
// Any chain by name — maps to https://{chain}-cascade.quiknode.io
chain
Authentication
solana_mainnet
.auth_token
The token is sent as Authorization: Bearer <token> on every request.
Running Modes
// Backfill a slot range
.backfill
// Follow the chain tip in real-time
.live
// Follow from a specific slot
.live_from
Full Configuration
solana_mainnet
.auth_token // JWT for Cascade API
.backfill // slot range to backfill
.concurrency // parallel workers (default: 10)
.encoding // "json" (structured) or raw modes
.cursor_file // resume support (default: cursor.json)
.tip_buffer // slots behind tip for live mode
.source_url // override Cascade endpoint
.with_plugin // register N plugins
.with_plugin // each sees all events
.run // blocks until done or SIGTERM
Plugin Trait (Solana)
All hooks have default no-op implementations. Override only what you need. Plugin errors are logged but never halt the pipeline.
For convenience, import everything with:
use *;
Data Types
Every data type carries extracted fields plus the original raw JSON for custom parsing:
| Type | Key Fields |
|---|---|
BlockData |
slot, blockhash, parent_slot, block_time, block_height, transaction_count, raw |
TransactionData |
slot, tx_index, signature, success, fee, compute_units, is_vote, pre/post_balances, log_messages, raw |
TokenTransferData |
slot, tx_index, signature, mint, owner, pre_amount, post_amount, decimals |
AccountActivityData |
slot, tx_index, signature, account, pre/post_balance, balance_change, is_signer, is_fee_payer |
Event Order per Slot
1. fetch_block(slot) — parallel, retry-forever
2. extract structured data — BlockData, TransactionData[], etc.
3. on_block(&block_data) — for each plugin
4. for each transaction:
on_transaction(&tx) — for each plugin
for each token balance change:
on_token_transfer(&transfer) — for each plugin
for each account touched:
on_account_activity(&activity) — for each plugin
5. advance cursor
Built-in Plugins
| Plugin | Description |
|---|---|
plugins::StdoutPlugin |
Prints block JSON to stdout (1 line per block) |
plugins::NdjsonPlugin |
Writes per-type NDJSON files (blocks, transactions, token_transfers, account_activity) |
Reliability
Every fetch retries forever. Plugin errors are logged, never fatal. The cursor saves after every batch.
| Failure | Behavior |
|---|---|
| Network error / timeout / HTTP 5xx | Retry forever with exponential backoff |
| HTTP 429 (rate limit) | Wait 5s, retry forever |
| Solana-skipped slot (-32004, -32007) | on_skipped_slot() called, cursor advances |
| Plugin hook error | Logged, pipeline continues |
Plugin on_load error |
Fatal (fail fast at startup) |
| Shutdown (SIGTERM / Ctrl-C) | on_exit() called for all plugins, cursor saved |
| Crash (SIGKILL) | Cursor may be up to 1 batch stale, replay is safe |
Resume
The cursor file (cursor.json) tracks progress. On restart, the runner reads it and skips already-processed slots. Atomic writes (tmp + rename) prevent corruption.
Multi-Chain Design
The crate is designed for multi-chain support. Solana types live under the solana module:
use ;
When new chains are added (Ethereum, etc.), they'll have their own modules with chain-specific plugin traits and data types:
// Future: use quicknode_cascade::ethereum::{Plugin, BlockData, TraceData};
The CascadeRunner::chain() method already maps any chain name to its Cascade endpoint.
License
Apache-2.0