reserves_a / reserves_b, the volume comes from differencing reserves between snapshots.
Dexploit doesn’t do that. We process every swap event from the Yellowstone gRPC stream as it arrives, normalize it across protocols (Pump.fun, PumpSwap, Raydium, Meteora), and aggregate the events into bars.
Why this matters for you
Building from events instead of state changes a few things you can rely on:- Volume is exact.
volume_solandvolume_tokenon each candle are the sum of actual swap amounts within the bar. - Trade counts are real.
trade_count,buy_count,sell_count, andunique_tradersare direct counts. State-snapshot APIs can’t produce these. - No phantom bars. When a pool has zero trades during a 1-minute interval, that interval has no bar. We don’t carry-forward the previous close.
- Bar boundaries are clean. 1-minute bars start at
:00. RPC drops or block-time jitter don’t shift them.
What’s in a candle
base_mint is always wrapped SOL — prices are quoted in SOL.
Both
volume_sol and volume_token are integers in base units, despite the names:volume_solis lamports — divide by1e9to get SOL (12340000000→12.34 SOL).volume_tokenis the token’s base units — divide by10 ** quote_decimalsfor the human-readable amount.
Comparison with the account-update model
| Account-update model | Swap-event model (Dexploit) | |
|---|---|---|
| Source | Poll pool reserves | Yellowstone swap stream |
| Volume accuracy | Approximate (delta of reserves) | Exact (sum of swap amounts) |
| Empty bars | Carries forward last close | Skipped (no trades = no bar) |
| Trade count | Not available | Per bar |
| Late RPC blocks | Bars shift / duplicate | Bars stay aligned |
Getting the data
GET /api/v1/candles for a time range, GET /api/v1/candles/latest for the most-recent N bars. Both require pair_address, not token mint.
For real-time bars and ticks, subscribe over WebSocket.
