AILEENA MACHINA

Reference · 2026.05.29

Reading Solana — From Data Structure to API Call

Everything on Solana is an account. Every API call is, underneath, a way of reading one. Here's the whole map — six layers of on-chain data and the exact call that pulls each one back — plus the handful of rules that explain why the API looks the way it does.

Solana · RPC · API · DAS · Helius

▸ Narrated reading · 2026.05.29

Reading Solana — From Data Structure to API Call

Press play for a narrated reading — English-accent female where available.

0:00
0:00

Once you internalize one idea, the entire Solana RPC API stops looking like a grab-bag of method names and starts looking like a map. The idea: everything on Solana lives in an account — a flat blob of bytes with an owner — and every API method is just a different lens for reading those accounts. Balances, tokens, NFTs, validator stake, the block that wrapped your transaction: all of it is account data, sometimes raw, sometimes indexed, sometimes parsed for you off-chain. This is the layer-by-layer mapping, from the data structure on the chain to the call that reads it.

The Account Layer

An account is the atom. It holds lamports (the smallest unit of SOL), a data blob, and an owner (the program allowed to write to it). Reading state, at bottom, is reading an account.

On-chain structureAPI methodWhat comes back
Account { lamports, data, owner }getAccountInfolamports, data (base64), owner, executable
Many accounts at oncegetMultipleAccountssame fields, as an array
Every account a program ownsgetProgramAccountsaccount list, with filters
Token mint accountgetAccountInfo → parse MintLayoutsupply, decimals, mintAuthority
Token account (ATA)getTokenAccountsByOwneramount, mint, owner
Balance only (lamports)getBalancelamports (u64)

Notice that the mint account and the token account both come back through plain account reads — you just have to know the byte layout to decode them. An ATA, by the way, is an associated token account: the one deterministic address that holds a given wallet's balance of a given token.

The Transaction Layer

A transaction is a bundle of signatures plus a message. Once it lands, the chain also attaches meta — the receipt, with balance snapshots, logs, and any nested calls. That meta is where most of the useful information actually lives.

On-chain structureAPI methodNotes
Transaction { signatures, message }getTransactionthe full transaction, meta included
Many transactionsgetTransactionsup to 1,000 at a time
An address's historygetSignaturesForAddresssignatures + slot only, nothing parsed
meta.pre/postBalancesgetTransaction → metaSOL balance change, aligned by accountKeys index
meta.pre/postTokenBalancesgetTransaction → metaSPL token balance change
meta.innerInstructionsgetTransaction → metathe nested CPI calls (one program invoking another)
meta.logMessagesgetTransaction → metaprogram log output — where you parse events from

The catch with the raw API: it hands you bytes and logs, not meaning. To know that a transaction was a swap, you have to read the logs and the inner instructions yourself. That's the gap Helius — an RPC provider that indexes and parses on its own servers — fills with an enhanced layer that does the interpretation for you.

Raw structureHelius enhanced APIWhat it adds
raw instructions + logsgetTransactions (Enhanced)auto-parsed type (SWAP, NFT_SALE…), tokenTransfers, nativeTransfers
signature listgetTransactionsForAddresspagination, type filter, source filter

The Block and Slot Layer

A slot is a 400ms time bucket (the target); a block is what fills one when the scheduled leader produces it. This layer is how you move between "what time is it on the chain" and "what happened in that window."

On-chain structureAPI methodNotes
Block { parentSlot, transactions[], rewards[] }getBlockthe full block, every transaction in it
Current slotgetSlotlatest confirmed slot
Slot → timestampgetBlockTimeUnix timestamp
Block heightgetBlockHeightcurrent height
Recent blockhash (replay guard)getLatestBlockhashblockhash + lastValidBlockHeight

The Token Layer

SPL tokens (Solana's token standard) are themselves just accounts, but they're common enough that the API gives them shortcuts so you don't have to decode layouts by hand.

On-chain structureAPI methodNotes
Mint accountgetTokenSupplyuiAmount, decimals, amount
All token accounts a wallet holdsgetTokenAccountsByOwnerfilter by programId or mint
Every holder of a mintgetProgramAccounts + filterscans all Token Program accounts — slow
Token balance (one account)getTokenAccountBalanceuiAmount, decimals
Token balance (many)getTokenAccountsByOwnerreturned in one batch

NFTs and compressed assets are the exception. A compressed NFT (a cNFT) doesn't get its own token account at all — it lives as a leaf in a Merkle tree to save rent (the SOL deposit that keeps an account alive) — so the normal token calls can't see it. For those you need the DAS API (Digital Asset Standard), a separate indexed layer built for exactly this.

Asset typeDAS methodNotes
One NFT / assetgetAssetmetadata, ownership, compression proof
All NFTs a wallet holdsgetAssetsByOwnerpaginated, with sortBy
All NFTs in a collectiongetAssetsByGroupgroupKey = collection
Compressed-NFT Merkle proofgetAssetProofverify a leaf on-chain
Search assetssearchAssetsfilter by owner / creator / mint and more

The Validator and Stake Layer

Who's producing blocks, who's delegated to them, and when the next handoff happens — all of it is readable, because validators and stake are (you guessed it) just accounts owned by the vote and stake programs.

On-chain structureAPI methodNotes
All validator vote accountsgetVoteAccountscurrent (active) + delinquent (offline)
Epoch infogetEpochInfoepoch, slotIndex, slotsInEpoch, absoluteSlot
Epoch schedulegetEpochScheduleslotsPerEpoch, warmup config (how fast newly activated stake ramps up)
Stake accountgetProgramAccounts → Stake Programdelegation, activationEpoch
Leader schedulegetLeaderScheduleslot → validator mapping
Block production statsgetBlockProductionproduced / skipped per validator

The Network State Layer

The last layer is the chain's vital signs — throughput, fees, supply, who's online. This is what you read when you're tuning a transaction or building a dashboard, not chasing a specific account.

On-chain structureAPI methodNotes
Network TPS / performancegetRecentPerformanceSamplestx count + duration per sample window
Network feegetFeeForMessagecost for a specific message
Priority fee estimategetPriorityFeeEstimate (Helius)suggested microLamports, by percentile
SupplygetSupplytotal, circulating, nonCirculating
Cluster node listgetClusterNodesIP / version of every gossip node

The Whole Map

Stacked up, the layers and where the off-chain indexers (Helius, DAS) bolt on look like this:

Solana on-chain state
  │
  ├── Account layer       getAccountInfo / getProgramAccounts
  ├── Transaction layer   getTransaction / getSignaturesForAddress ──► Helius enhanced
  │                                                                     (type, tokenTransfers, nativeTransfers)
  ├── Block layer         getBlock / getSlot / getBlockTime
  ├── Token layer         getTokenAccountsByOwner / getTokenSupply ───► DAS layer
  │                                                                     (getAsset / getAssetsByOwner / searchAssets)
  ├── Validator layer     getVoteAccounts / getEpochInfo
  └── Network layer       getRecentPerformanceSamples / getFeeForMessage

The Rules That Explain the Shape

Six patterns fall out of the map. Learn these and you can usually guess the right method before you look it up.

RuleWhat it means
Account = data containerAll state lives in accounts. Every read is, underneath, reading an account.
Program = stateless logicgetAccountInfo(programId) returns bytecode, never state.
Index vs real-timegetSignaturesForAddress reads history from an index; getAccountInfo reads current state from a live RPC.
Balance changes need a diffpre/postBalances are snapshots — the change is post − pre, and you compute it yourself.
Compressed assets go through DASA cNFT has no normal token account, so only the DAS API can find it.
Enhanced parsing is off-chainHelius's type / tokenTransfers are indexed off-chain — not raw on-chain fields.

That last rule is the one people trip on most. The chain stores bytes and emits logs; it never tells you "this was a swap." Any time a field reads like a human sentence — a transaction type, a clean list of token transfers — something off-chain parsed it for you. Useful, but it's an interpretation layer, not ground truth. When you need ground truth, drop back down to the raw account and decode it yourself.

← Back to Archive
← dispatch