How to Build a Live Solana Candlestick Chart with GetBlock Solana Market Data
A step-by-step guide to streaming OHLCV candles from GetBlock Solana Market Data and rendering a live SOL/USDC chart that updates as trades land.
Every price chart starts the same way: you need candles, and Solana does not hand you any. What the chain gives you is raw transactions across dozens of DEX programs, each with its own instruction layout. To draw a single one-minute candle, you have to subscribe to blocks, decode swaps from Raydium, Orca, Meteora, and the rest, normalize them into a common trade shape, group those trades into time buckets, and keep the whole pipeline correct while slots keep arriving. That is weeks of work before you render a single wick.
GetBlock Solana Market Data does that aggregation for you and streams the finished candles over WebSocket, complete with a backfill so your chart is populated the moment it opens.
In this guide, you'll build a live SOL/USDC candlestick chart that backfills the last hour on startup and then updates in real time as trades land.
What you'll build
A createCandleStream(options, onSeries) function that:
Opens a WebSocket to the Solana Market Data stream and subscribes to the
ohlcvtopic.Seeds the chart with the last 60 one-minute candles from the
hydratebackfill.Upserts rows by their stable
id, so the candle that is still open is revised in place.Removes rows that arrive in
deletesas they fall out of the window.Emits a time-sorted candle array that the browser chart redraws whenever it changes.
How it works
The candle for the window still in progress is sent repeatedly under the same id as more trades land. Key your state by id and overwrite. If you append every message to an array instead, one minute of trading becomes dozens of duplicate candles and the chart marches sideways with a flat price.
Prerequisites
Node.js 20+ — the examples use the built-in global
WebSocket, so no client library is needed.A Solana Market Data API key with the product activated on it.
Basic JavaScript knowledge.
Project Setup
Wire it together and run
The entry point starts the server, starts the stream, and pipes one into the other.
Start it:
Then open http://localhost:8080
The live URL page looks like this:

The terminal prints the candle currently being built:
Read that output closely, because it shows the whole model working:
The timestamp stays at
12:26:00— these are all the same candle, revised.The high climbs
104.33 → 104.46 → 104.48as bigger trades land in the window.The count stays at 60 —
hydrateholds the set size, so an old candle is evicted for each new one.
Understanding the response
Each row in inserts, updates, and deletes is one candle. These are the fields the chart uses, plus the ones worth knowing about.
id
number
Stable identifier for the candle. The key for your local state — the open candle keeps it while it changes.
window_start
string
Start of the candle's period. Use this as the chart's time axis.
window_end
string
End of the candle's period.
window_duration
string
Period as an ISO 8601 duration — a 1m window comes back as PT1M.
open
string
First price traded in the window, in the quote token.
high
string
Highest price traded in the window.
low
string
Lowest price traded in the window.
close
string
Latest price traded — still moving while the window is open.
open_usd
string
Same as open, converted to USD. high_usd, low_usd, close_usd follow the same pattern.
base_volume
string
Volume traded, denominated in the base token.
quote_volume
string
Volume traded, denominated in the quote token.
volume_usd
string
Volume traded, expressed in USD.
data_points
string
How many trades went into the candle. A low count means a thin, less reliable candle.
base / quote
string
Mint addresses of the pair, useful when one socket carries several markets.
Troubleshooting
Socket closes instantly with code 1006 and no reason
The key is rejected during the handshake, and browsers can't surface the 401
Check GETBLOCK_API_KEY is set and that Solana Market Data is activated on that key.
Chart fills with duplicate candles marching sideways
Appending each message instead of upserting by id
Key your state by row.id and overwrite, as candles.js does.
Cannot read properties of undefined (reading 'result')
Treating the subscription acknowledgement as a candle notification
Return early when typeof msg.result === 'string'.
Value is null or a blank chart from setData
Series not sorted by time, or duplicate timestamps
Sort ascending by time and keep one row per id.
window must be one of 1s, 10s, 30s, 1m, …
An unsupported window such as 7m
Use a listed value.
hydrate must be an integer from 1 to 100
hydrate outside the allowed range
Pass a value between 1 and 100.
base must be a base58-encoded 32-byte Solana public key
A malformed or truncated mint address
Copy the full base58 mint for both base and quote.
Flooded with candles for pairs you didn't ask for
base and quote were omitted, subscribing you to every market
Always set both mints.
Candle count never grows beyond hydrate
Not a bug — hydrate is the size of the retained set, not just a backfill
Raise hydrate (max 100), or keep evicted candles in your own store.
Conclusion
You built a live Solana price chart by subscribing to the ohlcv topic on GetBlock Solana Market Data, reconciling the inserts, updates, and deletes change sets into a Map keyed by each candle's stable id, and relaying the sorted series to a browser that redraws it on every change. The same reconciliation pattern works for every other topic in the product — swap ohlcv for trades, vwap, or volume and only the row's shape changes.
Resources
Last updated
Was this helpful?