| name | midnight-indexer:indexer-data-model |
| description | This skill should be used when the user asks about the indexer data model, what the indexer indexes, indexer schema, contract actions, unshielded UTXOs, ledger events, DUST generation, Decentralized Unshielded Staking Token, SPO data, blocks table, transactions table, zswap events, indexer database, or the contract action lifecycle. Covers "what tables does the indexer have", "indexer entity relationships", and "what data does the indexer store". |
| version | 0.1.0 |
Indexer Data Model
The Midnight indexer extracts and stores on-chain data into a relational database, making it queryable through the GraphQL API. This skill covers what gets indexed, the database schema, and the relationships between entities.
What Gets Indexed
The indexer processes every finalized block and extracts nine categories of data:
- Blocks — Hash, height, timestamp, author, parent hash, protocol version
- Transactions — Regular and System variants with hashes, identifiers, raw content, and Merkle tree roots
- Contract actions — Deploy, Call, and Update events with contract address, state, zswap state, and entry point
- Contract balances — Unshielded token balances per contract action
- Unshielded UTXOs — Creation and spending tracking, owner addresses, token types, DUST registration status
- Ledger events — Zswap events (inputs/outputs) and DUST events (initial UTXOs, dtime updates, spend processing, parameter changes)
- DUST generation — cNIGHT registrations from Cardano, generation rate and capacity tracking
- System parameters — D-parameter history (stored in the
system_parameters_d table) and Terms & Conditions history (stored in the system_parameters_terms_and_conditions table)
- SPO data — Identities, committee membership, epoch performance, stake distribution, pool metadata
Database Schema
The tables below are grouped by purpose. For the complete catalog — every table, all columns and types, primary keys, indexes, the full foreign-key map, and the Postgres-vs-SQLite divergences — see references/database-schema.md.
Core Tables
| Table | Purpose |
|---|
blocks | Block metadata — hash, height, timestamp, block author |
transactions | Transaction records — variant (Regular/System), hash, raw bytes |
regular_transactions | Extended data for regular transactions — result, Merkle root, fees |
Contract Tables
| Table | Purpose |
|---|
contract_actions | Deploy, Call, and Update events — contract address, state snapshot |
contract_balances | Token balances associated with each contract action |
Token and UTXO Tables
| Table | Purpose |
|---|
unshielded_utxos | UTXO lifecycle tracking — creation, spending, owner address, token type |
ledger_events | Zswap events (inputs/outputs) and DUST events |
dust_generation_info | NIGHT UTXO tracking for DUST generation |
cnight_registrations | Cardano stake key to Midnight address mappings |
Wallet Tables
| Table | Purpose |
|---|
wallets | Wallet sessions with encrypted viewing keys |
relevant_transactions | Wallet-to-transaction association for shielded scanning |
When a wallet connects via the connect mutation, its viewing key is encrypted using APP__INFRA__SECRET and stored in the wallets table. The wallet-indexer then scans each new block, attempting to decrypt transaction outputs with the viewing key. Transactions that decrypt successfully are "relevant" to that wallet and inserted into relevant_transactions, a many-to-many join table linking wallets to transactions. This join table enables the shieldedTransactions subscription to stream only the transactions a specific wallet can view.
Governance and SPO Tables
| Table | Purpose |
|---|
system_parameters_d | D-parameter history (governance) |
system_parameters_terms_and_conditions | Terms & Conditions history (governance) |
epochs | Epoch boundary records |
spo_identity | Stake pool operator identity records |
committee_membership | SPO committee membership tracking |
Entity Relationships
blocks
└── transactions (1:N)
├── regular_transactions (1:1, for Regular variant)
├── contract_actions (1:N)
│ └── contract_balances (1:N)
├── unshielded_utxos (1:N)
└── ledger_events (1:N)
├── zswap events (inputs/outputs)
└── dust events
wallets
└── relevant_transactions (N:M with transactions)
Contract Action Types
The indexer records three independent kinds of contract action as they occur. They are peer variants, not stages of a fixed sequence: a contract begins with a Deploy, and any number of Call and Update actions can follow in whatever order they happen on-chain. Update is contract maintenance (new verifier keys / state) — it is not a mandatory terminal step that closes out a contract.
Deploy Call Update
│ │ │
▼ ▼ ▼
Initial Entry New verifier
state point keys / state
exec
| Action | Description |
|---|
| Deploy | Contract is deployed to the network with initial state and verifier keys |
| Call | Contract entry point is invoked, state is updated |
| Update | Contract verifier keys or operations are updated (contract maintenance) |
Each action records:
- The contract address
- The resulting contract state
- The resulting zswap state
- The parent transaction
- Any unshielded token balances
Transaction Variants
| Variant | Description |
|---|
| Regular | User-submitted transactions with ZK proofs, contract calls, and token operations |
| System | Protocol-generated transactions (epoch boundaries, parameter updates) |
Regular transactions include additional fields:
result — SUCCESS, PARTIAL_SUCCESS, or FAILURE
merkle_root — Commitment tree root at time of transaction
fees — Paid and estimated fees
Unshielded UTXO Tracking
The indexer tracks the full lifecycle of unshielded UTXOs:
Created (in contract action)
│
├── Owner address recorded
├── Token type recorded
├── DUST registration status tracked
│
▼
Spent (in later transaction)
│
└── Spending transaction recorded
DUST Generation Data
The indexer tracks DUST (Decentralized Unshielded Staking Token) generation:
- cNIGHT registrations — Cardano stake keys mapped to Midnight addresses
- Generation rate — How quickly DUST accrues
- Capacity — Maximum DUST that can be generated
- Initial UTXOs, dtime updates, spend processing, parameter changes — All tracked as DUST ledger events
Deep dive: references/dust-and-spo-data.md — the cNIGHT→DUST pipeline (registrations, QDO fields, the dtime decay model, generation-tree indexes) and the full SPO data model (identity, committee, epochs, Blockfrost stake refresh).
References
| Name | Description | When used |
|---|
references/database-schema.md | Complete table catalog from the migrations — every column, PK, index, the foreign-key map, and Postgres-vs-SQLite differences | When writing queries against the schema or reasoning about entity relationships |
references/dust-and-spo-data.md | DUST-generation and SPO subsystem deep-dive: cNIGHT registrations, QDO/dtime model, generation-tree indexes, SPO identity/committee/epoch/stake flow | When working with DUST generation data or SPO/stake indexing |
Cross-References
compact-core:compact-tokens — Token types and shielded/unshielded semantics
compact-core:compact-transaction-model — Transaction structure and execution phases
core-concepts:data-models — UTXO model fundamentals and ledger structure
midnight-indexer:indexer-graphql-api — Querying indexed data via GraphQL