We work with different teams to index their data so institutions, devs, or users can access it. One of the advantages of the Cosmos SDK ecosystem is that every chain built on top of it inherits the same underlying data model — blocks, transactions, messages, and events are emitted with a consistent shape across the entire ecosystem. That means we can expose the same three tables for every Cosmos SDK chain we index, and the queries you write against one chain work, with minimal changes, against any of the others.
Here’s a list of the chains currently supported under Numia SQL.
Onboarding new chains
We onboard new Cosmos SDK chains continuously. If the chain you need isn’t listed below — or if you need to index your own chain or protocol — reach out at support@numia.xyz or through our website and we’ll scope the integration with you.
Available chains
Cosmos Hub
cosmoshub_4
Osmosis
osmosis_1
Stride
stride_1
Injective
injective_1
Sei
pacific_1
dYdX
dydx_mainnet_1
Celestia
celestia
Noble
noble_1

Secret Network
secret_4
Akash
akashnet_2

Xion
xion_mainnet_1
Mantra
mantra_1
Interwoven
interwoven_1
Zigchain
zigchain_1
Babylon
bbn_1
Echelon
echelon_1
Yominet
yominet_1
What’s in each chain’s database
Inside every database above, we expose the same three tables. One raw table is fed directly by the ingestion pipeline; two source tables are derived from it through ClickHouse materialized views and stay within seconds of chain tip.
raw_block_resultsOne row per block — the raw payload returned by the chain’s RPC.
src_eventsOne row per event — begin-block, transaction, end-block, and finalize-block events normalized into a single shape.
src_messagesOne row per message inside every transaction, with the full message body kept as JSON.
Parsed tables on request
The three tables above keep payloads as raw JSON so they cover every message and event type a chain emits — including ones we’ve never seen. If you need decoded, column-per-field tables for specific message types or modules (e.g. bank.MsgSend, staking.MsgDelegate, IBC transfers, DEX trades), reach out at support@numia.xyz and we’ll build them for you.
What’s in a Cosmos SDK block?
Before diving into columns, it helps to have a mental model of what each row in these tables actually represents. A Cosmos SDK block is a small hierarchy:
Blocks
A block is the unit of consensus. Cosmos chains use the CometBFT (formerly Tendermint BFT) consensus algorithm to commit blocks, each containing a header, a set of transactions, and the side-effects produced by executing them. Every block has a unique, monotonically increasing block_height per chain, and a block_timestamp derived from the consensus round that produced it. In our schema, raw_block_results stores one row per block — the unmodified payload returned by the chain’s RPC, including header, transactions, and execution results.
Transactions
A transaction is a signed user instruction that asks the chain to perform one or more actions. A block contains zero or more transactions, ordered by their position inside the block (transaction_index). Each transaction has a hash, a list of messages, gas accounting, and an execution result (success or failure with a code/log). Transactions don’t get their own dedicated table — they’re embedded inside raw_block_results.transactions (decoded) and raw_block_results.tx_results (execution outcomes), and are surfaced one-row-per-message in src_messages.
Messages
Messages (Msgs) are the actual actions inside a transaction. A MsgSend transfers tokens; a MsgDelegate stakes with a validator; a custom module message might mint an NFT or open a CLOB position. A single transaction can carry multiple messages, executed atomically. src_messages stores one row per message, with the message body kept as JSON in the message column and the protobuf type URL (e.g. /cosmos.bank.v1beta1.MsgSend) in message_type, so the same table holds every message type a chain emits without per-module schema work.
Events
Events are the granular, machine-readable side-effects emitted while a block is being processed. They have a type (e.g. transfer, withdraw_rewards, ibc_transfer) and a list of attributes — key/value pairs that describe the action in detail. Events come from three places in the block lifecycle:
- Begin-block events — emitted before any transactions run (e.g. epoch rollovers, reward distributions).
- Per-transaction events — emitted while executing each message inside a transaction.
- End-block / finalize-block events — emitted after transactions run (e.g. validator set changes, slashing).
src_events stores one row per event across all three sources, normalized onto a single block_section_index axis (see Section indexing) so you can query begin/tx/end events with the same shape.
How it all fits together
raw_block_resultsOne row per block. Fields that feed the derived tables:
transactionsbegin_block_eventstx_results[*].eventsend_block_eventsfinalize_block_events
src_messagesFed by transactions — one row per message inside every tx.
src_eventsFed by the four event arrays — one row per event, normalized across begin / tx / end / finalize.
The rest of this page is the column-level reference for those three tables.
raw_block_results
The unparsed block payload as returned by the chain’s RPC. This is the source of truth — everything else is derived from it.
| Column | Type | Notes |
|---|---|---|
chain_id | String | e.g. cosmoshub-4 |
block_height PK | UInt64 | Unique per chain |
block_timestamp | DateTime64(9) | Nanosecond precision |
hash | String | Block hash |
header | String | Raw JSON header |
data | String | Raw JSON data field (contains txs) |
last_commit | String | Raw JSON last-commit payload |
tx_results | String | Raw JSON array of per-tx results |
begin_block_events | String | Raw JSON events (legacy BeginBlock) |
end_block_events | String | Raw JSON events (legacy EndBlock) |
finalize_block_events | String | Raw JSON events (ABCI 2.x FinalizeBlock) |
validator_updates | String? | Raw JSON |
consensus_param_updates | String? | Raw JSON |
transactions | String | Decoded transactions, JSON array (default '[]') |
ingestion_timestamp | DateTime64 | Used by ReplacingMergeTree to dedupe re-ingestions |
src_events
One row per event emitted in the block, regardless of where it came from (begin-block, transaction, end-block, finalize-block). Built from raw_block_results via a materialized view that flattens each event section with ARRAY JOIN.
| Column | Type | Notes |
|---|---|---|
chain_id | String | — |
block_height PK | UInt64 | — |
block_timestamp | DateTime | — |
block_section_index PK | UInt8 | 0 = block_begin, 1 = transactions_results, 2 = block_end, 3 = block_finalize |
block_section | String | Human-readable section name (matches the index above) |
transaction_index PK | String | Zero-based tx index; empty for non-tx events |
transaction_hash | String | Hex hash; for non-tx events: 'This event was not emitted due to a transaction' |
message_index PK | String | From the msg_index event attribute when present |
event_raw_index PK | String | Position of the event inside its source array |
event_msg_index | String | Per-message ordinal of the event |
event_type_index | String | Per-(message, event_type) ordinal — useful for picking the Nth transfer, etc. |
event_type | String | e.g. transfer, withdraw_rewards, ibc_transfer |
event_attributes | String | Raw JSON array of {key, value, index?} |
processed_at | DateTime | Used by ReplacingMergeTree |
ingestion_timestamp | DateTime64 | Inherited from the raw row |
Section indexing
ABCI 1.x chains emit events through begin_block_events / end_block_events, while ABCI 2.x chains emit through finalize_block_events. We normalize both worlds onto the same block_section_index axis:
block_section_index | block_section | Source |
|---|---|---|
0 | block_begin | begin_block_events, or finalize_block_events with mode = 'BeginBlock' |
1 | transactions_results | Per-tx events inside tx_results[*].events |
2 | block_end | end_block_events, or finalize_block_events with mode = 'EndBlock' |
3 | block_finalize | finalize_block_events not tagged as Begin/End |
src_messages
One row per message inside every transaction in the block. Built from raw_block_results.transactions via a materialized view.
| Column | Type | Notes |
|---|---|---|
chain_id | String | — |
block_height PK | UInt64 | — |
block_timestamp | DateTime | — |
transaction_index PK | String | Zero-based tx index within the block |
transaction_hash | String | — |
message_index PK | String | Zero-based message index within the tx |
message_type | String | e.g. /cosmos.bank.v1beta1.MsgSend |
message | String | Raw JSON body of the message |
processed_at | DateTime | Used by ReplacingMergeTree |
ingestion_timestamp | DateTime64 | Inherited from the raw row |
Querying tips
- Always include a
block_heightpredicate (orblock_timestampresolved through it) to take advantage of the partition key. - For tables with
ReplacingMergeTree, appendFINALonly when you need the deduplicated view at query time — otherwise let background merges handle it. - Use
JSON_VALUE(message, '$.from_address')orJSONExtractString(message, 'from_address')to drill intosrc_messages.messagewithout re-materializing columns.