Indexing on Solana
HyperIndex indexes Solana programs at the instruction level. You select the programs and instructions you care about, HyperIndex decodes them (arguments and accounts) using your Anchor IDL or an inline schema, and writes the results to Postgres with an auto-generated GraphQL API. Inner instructions (CPIs), token balances and balance changes, transaction metadata and program logs are all available.
It is powered by HyperSync for Solana, the same high-performance data engine behind EVM indexing, so historical backfills are fast and you never touch an RPC node for the bulk of indexing.
Solana support is in beta: the core instruction-indexing path is stable
enough to build on, though the program/instruction config surface (the
chain-level experimental key) may still evolve as we round it out. Building
on Solana? Say hello on Discord. We'd love your
input on what to prioritize next.
Two ways to index Solana
| Approach | API | Data source | Use it for |
|---|---|---|---|
| Instruction handlers | indexer.onInstruction | HyperSync | The main path: decode and index program instructions (swaps, deposits, mints, transfers…), including inner/CPI instructions, with token balance changes. |
| Slot handlers | indexer.onSlot | RPC (via the Effect API) | Per-slot orchestration, time-series snapshots, or pulling extra data from RPC on a schedule. |
Most indexers use instruction handlers. Slot handlers are for cases where you need to run logic on a slot cadence rather than react to a specific instruction. For raw, low-level data you can also query HyperSync for Solana directly.
Quickstart
pnpx envio init
Choose Solana when prompted, then pick a starter template (a Metaplex NFT instruction indexer, or a minimal slot handler). See Getting Started for the full walkthrough.
Data endpoint and history
Every Solana chain must name its HyperSync endpoint explicitly under
experimental.hypersync_config.url - it is a required field, with no default
applied when it is missing. Each endpoint serves history back to its own floor
slot, and that floor moves forward over time, so pick both the endpoint and
start_block deliberately. See
choosing an endpoint
for the current endpoints and the silent-skip failure mode to avoid.
Mental model: coming from EVM?
If you've used HyperIndex on EVM, the shift is mostly vocabulary:
| EVM | Solana |
|---|---|
| Contract + ABI | Program + IDL |
Event (onEvent) | Instruction (onInstruction) |
event.params | instruction.params?.args (optional: decoding can fail) |
| Topic0 / event signature | Instruction discriminator |
Block (onBlock) | Slot (onSlot) |
Hex addresses 0x… | Base58 addresses |
start_block = block number | start_block = slot number |
See EVM vs Solana for the full picture.
What's supported today
- Instruction indexing via
indexer.onInstruction: match by program + discriminator. - IDL-aware decoding: point at a standard Anchor IDL (legacy or 0.30+) and HyperIndex derives the argument and account layout. The
discriminatoris always read fromconfig.yaml, never from the IDL. No IDL? Declare an inline schema. - Inner instructions (CPIs): decoded the same way as top-level ones, with a full instruction-address path so you can reconstruct the call tree.
- Token balances & balance changes: pre/post SPL Token (and Token-2022) balances per transaction, so you get the net token movement without indexing every transfer. See token balances.
- Transaction metadata & logs: fee payer, fee, compute units, success, the transaction signature, and per-instruction program logs (opt-in via field selection).
- Slot handlers via
indexer.onSlot+ the Effect API for RPC enrichment. - Local dev + GraphQL + Envio Cloud: the same workflow and hosting as EVM.
What is not supported yet
These are gaps in the built-in instruction-handler surface, not hard limits: for most of them you can still pull the data yourself by calling out to RPC from a handler with the Effect API, you just don't get it as a struct field for free.
- Native SOL balance fields on handlers. Pre/post token balances are surfaced today; native SOL (lamport) balances aren't yet a handler field-selection toggle, though you can get them via HyperSync directly, or by reading the account over RPC in a handler with the Effect API.
- Account-change subscriptions. There is no
onAccount/program-account handler.instruction.accountsandparams.accountsgive you the account references (pubkeys) an instruction touched, not their state; for actual state, per-transaction token balances (viatoken_balance_fields) cover the token case, and the Effect API covers everything else by reading it over RPC yourself. - A separate log handler. Logs are a field on the instruction event, not their own handler.
- No-code contract import. Solana has no
contract-importflow, so you configure programs/instructions by hand. (IDLs are wired up inconfig.yaml, not auto-imported.) - ReScript. Solana indexers are TypeScript only. Codegen emits no ReScript for
ecosystem: svm, andenvio initsilently picks TypeScript if you ask for ReScript. - Per-field selection on
token_balance_fields/log_fields. Those two toggles accepttrueonly.transaction_fieldsandblock_fieldsdo take field name lists.
If the piece you need is on this list, tell us on Discord: there's a good chance we can sequence the work to unblock you, or point you at a HyperSync-direct path that gets the data today.
In this section
- Getting Started: scaffold and run your first Solana indexer.
- Configuration: the
config.yamlreference forecosystem: svm. - Instruction Handlers:
onInstruction, the instruction object, token balances, CPIs, testing. - Decoding & IDLs: discriminators, Anchor IDLs, inline schemas, supported types.
- Slot Handlers:
onSlotand RPC enrichment. - EVM vs Solana: every difference in one place.