Terrain by Tim WijnhovenTerrain by Tim Wijnhoven

Terrain

Tim Wijnhoven

Tim Wijnhoven

Built from the messy parts up

Most people building in crypto slap a UI on top of someone else's API and call it a day. Fair enough. We went the other way and built the machinery underneath it.
Terrain turns raw Solana and Raydium-style market activity into something humans can actually use: price charts, wallet history, transaction feeds, trader rankings, live token updates, the lot. Under the hood that meant parsing ugly blockchain data, figuring out what actually happened, storing the important bits, and pushing it back out in realtime.
Three parts, one system: a Rust parser engine, a TypeScript backend, and a frontend that makes all that chain chaos readable.
RawHuman
Raw transactionParser trace / RPC meta
Slot281,991,842Block246,889,104Compute109,773 / 200k CUFee0.0000175 SOL
Instruction tracedepth · 2
IXDProgramInstructionResult
001ComputeBudget1111set_compute_unit_limit200,000 CU
011ComputeBudget1111set_compute_unit_price12,500 μ-lamports
021ATokenGPvbdGVxr1b2hvcreate_idempotentsuccess
031675kPX9MHTjS2zt1qfrraydium_amm::swap_base_ininvoke
03.12TokenkegQfeZyiNwAJbtransfer_checked100.387 SOL
03.2211111111111111111111transfer0.000005 SOL
03.32TokenkegQfeZyiNwAJbtransfer_checked270.90 USDC
03.42TokenkegQfeZyiNwAJbsync_nativesuccess
041JUP6LkbZbjS1jKKwapdrouteexact_in
Program logs8 / 31
01Program 675kPX9M invoke [1]
02Program log: Instruction: SwapBaseIn
03Program TokenkegQ invoke [2]
04Program log: amount_in=100387000000
05Program log: minimum_out=269440000
06Program TokenkegQ consumed 4645 of 174128 CU
07Program 675kPX9M consumed 92118 of 190400 CU
08Program 675kPX9M success
Account diffs4 / 17
#03 signer / writable7xKXt…9QmB
−100.387 SOL
#07 pool vault A6UeJg…vL2d
+100.387 SOL
#08 pool vault B8FqWj…3HnA
−270.90 USDC
#12 owner ATA4nPzV…wK7c
+270.90 USDC
signature 5Kp9aAV7…Ym4rpreTokenBalances[7] → postTokenBalances[7]err: nullfinalized
Terrain recapSuccess
What happened?
This wallet added liquidity, received two assets and redeemed rewards about five minutes ago.
Added liquidity100.387 SOLLido pool
Redeemed rewards2 assets$270.90 USD
01 / Understand the action
What just happened?

A transaction that reads like a story.

Start with one wallet action. Terrain groups the movements, names what happened and keeps the underlying detail close at hand.
Next questionNow zoom out: what does this action mean for the asset?
02 / Add market context
What does it mean now?

The useful view, assembled from the noise.

Terrain connects that activity to balances, liquidity, holders and live price context, so the transaction becomes part of a market rather than an isolated event.
Next questionWith the market visible, ask who holds the power.
03 / Reveal the structure
Where is the risk?

See concentration before it becomes risk.

Holder distribution and trader performance reveal whether activity is broad, concentrated or being driven by a small group.
Next questionThen carry that understanding into a market comparison.
04 / Compare the options
Where should I look next?

Six markets. One glance.

The same product language now makes liquidity, volume and performance comparable across markets without losing the evidence underneath.
The outcomeOne trail: from a single action to an informed market decision.
Because raw chaindata looks likenonsense unlessyou do the work.

Terrain Parser

Blockchains don't hand you neat little labels like "swap", "transfer", or "this wallet dumped the token and left." They hand you a pile of low-level state changes and basically wish you good luck.
So we built a Rust parser that takes raw Solana transactions and turns them into stuff you can actually use: swaps, prices, balances, live updates.
It does more than just index chain data. It figures out what happened, who likely did it, and feeds the rest of the system from there.
The part where raw blockchain data stops being gibberish.
This was proper systems work: Rust crates, worker pools, batching, retries, caches, Docker, AWS, Kafka, WebSockets. Less "look I made an app," more "we built the engine room too."
Pipeline walkthrough

Data pipeline from chain transaction to live client update.

Slow it down
Playback
1124 tx / 4.6s
One pipeline pass from raw transaction intake to live client output. Low-power mode is active, so ambient motion and dot density are reduced.
3s1124 tx
Each wave shows one pass moving through the pipeline.
RawParserActionsPricingEventOutputs
batch1124 transactionssynced burst
95% complete
Batch completion
1070 / 1124 tx completed
01completed
Encoded tx + status meta

Raw txstream

Solana RPC and Kafka payloads arrive as noisy transaction data.
InputKafka raw topic
decode payload
Outputtransaction + meta
slotblockTimemeta.err
02completed
block_parser

CtTransactionparser

A shared Rust engine normalizes signer, UBO, fees, token deltas, and inner instructions.
Inputtransaction + meta
normalize semantics
OutputCtTransaction
signerubotoken deltas
03completed
CtAction

Actionreconstruction

Low-level value changes resolve into swaps, transfers, and wallet-aware events.
InputValueChange[]
group deltas
Outputswap / transfer
combineinferlabel
04processing
PriceItem

Pool-awarepricing

Raydium pool context, SOL reference price, and pool metadata produce market prices.
Inputpool id + SOL/USD
derive market price
OutputPriceItem
PoolMetaMoka cacheprice_usd
05queued
TokenUpdate

Enrichedevent

Structured token updates leave the ingest worker with token and pool headers.
InputPriceItem
batch + publish
OutputTokenUpdate
headersroundinglz4
06queued
PRICE_UPDATE

Productoutputs

Postgres receives analytics while subscribed clients receive live price updates.
InputTokenUpdate
fan out
OutputDB + token room
token_prices_newJOIN_ROOMPRICE_UPDATE

Terrain Backend

The API nobody sees first, but everything depends on.

Once the parser did its job, this service turned the data into actual product features. Token charts. Transaction history. Wallet views. Trader leaderboards. The sort of stuff users click around in without thinking too much about how annoying it is to make.
The interesting part here is that it doesn't just dump chain data back at the frontend and walk away. It calculates things like realized P/L, ROI, bought vs sold volume, unrealized exposure, trader rankings, filtered history, and wallet-level views. Basically: raw blockchain activity in, readable trading intelligence out.
Also included: versioned APIs, request tracing, Sentry, mock endpoints for frontend work, Docker, Fly, AWS. The boring grown-up stuff that keeps things alive.
Built in Node, TypeScript and Postgres, the backend combines precomputed analytics, cached transaction records, live Solana RPC enrichment, and parser-service fallbacks. Which is a fancy way of saying: it does whatever it needs to do to return something useful, fast.
The part where raw blockchain data stops being gibberish.
superhuge
Terrain note

Terrain Frontend

Because raw chain data looks like nonsense unless you do the work.

Most blockchain explorers feel like they were designed by and for people who enjoy suffering. Huge tables, mystery labels, JSON vibes, good luck out there.
No big deal.
Terrain took a more useful route. Search-first, fast to navigate, and built around the idea that users want to jump straight to a wallet, transaction, token or protocol without getting lost in some overcomplicated menu.
Once there, the UI translates blockchain movement into something readable: who sent what, who received what, what got swapped, what changed, and why it matters.
It also pulls in protocol views, wallet filters, transaction drill-downs, live token pricing, websocket updates, and client-side chart transformations.
Domain model

A few stable models make the product readable.

CtTransaction

hash
signer
ubo
block_number
token_changes

TokenUpdate

signature
token_address
pool_address
price_usd
amount_usd

BalanceUpdate

signature
token_address
owner
balance_post
datetime
Terrain does not push raw chain payloads straight into the UI. It shapes them into stable transaction, token, and balance models that the rest of the product can actually build on.
That modeling layer is what makes live pricing, holder changes, wallet views, and feed updates feel coherent instead of improvised.

One stack, not a facade

Terrain is a Solana block explorer stack built from the messy parts up: parser, backend, frontend, and the operational glue that makes the whole thing feel fast instead of fragile.

What it actually took

So in short, Rust workspace, multi-crate parser core, CtTransaction, Solana transaction/meta payloads, instruction-vector walks, inner-instruction traversal, signer and UBO heuristics, fee surfaces, owner-level token balance deltas, token-account-level diffs, Raydium AMM pool extraction, pool-id resolution, quote/base price math, SOL/USD anchoring, Kafka consumers, Kafka republish, async channels, worker pools, batched processing, Postgres persistence, price-update listeners, holder-ingest signature pagination, historical replay, parser-debugger flows, Moka cache hits, connection pools, exponential backoff, Axum listeners, WebSocket fan-out, Socket.IO token rooms, multi-stage Docker, env-driven config, AWS CDK, ECS services, Fargate tasks, ALB wiring, snapshot diffing, and just enough distributed-systems trauma to keep it honest.
Your way through the machineryStart at Solana. Every stop adds one useful thing: evidence, meaning, continuity, context, then clarity.
01
slot 218,447,921programId 675kPX9MHTjS2zt1q...innerInstructions[3] transfer_checkedpostTokenBalances[7] 270900000
SolanaAdds Evidence

The raw chain

RPC payloads, inner instructions, account changes and noisy metadata arrive first. In plain English: plenty of evidence, no useful answer yet.
02
SWAP
Wallet
5mbK…BSow
Sent
−100.387 SOL
Received
+270.90 USDC
Rust parserAdds Meaning

Transaction semantics

The Rust parser identifies signers, token deltas, swaps, transfers, pools and prices. This is where the system works out what actually happened.
03
parsed.txprice.enrichedroom.broadcast
Event streamAdds Continuity

One enriched signal

Kafka joins parsed activity with persistence and live enrichment, then publishes one dependable event downstream. This keeps the answer moving without falling apart.
04
P/L+$22.37
ROI+12.3%
Wallet rank#184
Live price$0.0084
API + analyticsAdds Context

Product-ready intelligence

Cached records, history and live prices become profit and loss (P/L), return on investment (ROI), rankings and wallet-level intelligence. This is where chain activity becomes product intelligence.
05
InterfaceAdds Clarity

One readable product surface

The complexity finally resolves into search, wallet intelligence, transaction explanations and live markets. The user gets the useful bit, not the plumbing.
That is Terrain in one line: serious infrastructure, sharp product thinking, and an interface that never asks the user to care how hard any of it was.
The useful bit

All that machinery, so the product can feel simple.

Like this project

Posted Oct 10, 2026

Solana block-explorer stack: Rust parser, TypeScript backend and frontend that turn raw blockchain transactions into readable market and wallet intelligence.

Likes

0

Views

0