Yellowstone (Geyser) gRPC gives you raw Solana transactions about as fast as a node sees them. That part is easy to set up. The hard part comes after: turning a raw transaction into "this wallet bought this token on this pool for this much."
We run a decoder like this across 12 DEX venues. Here is the list of problems we had to solve, so you can budget for them if you build your own.
1. One decoder per program
Every venue logs trades differently. Some use Anchor emit_cpi events, some print their trades to the program logs, and sometimes the only reliable source is the balance changes. Twelve venues means twelve decoders, and any of them can break when the program is upgraded and the event layout changes.
2. Inner instructions
A lot of volume arrives through routers and aggregators, so the actual swap is an inner instruction, not a top-level one. If you only look at top-level instructions you will miss a large share of trades. We also record the outer program (we call it via) so you can tell routed flow from direct flow.
3. Duplicate events
Some programs emit two events for one swap. Meteora DLMM, for example, emits a current event plus a legacy twin. If you count both, your volume is doubled. You need to pick one.
4. Truncated logs
The runtime truncates long logs, so on busy transactions the event you are looking for can simply be missing. For the venues that report trades in their logs, our fallback is to rebuild the trade from the user's own token transfers inside the swap (or from the pool's balance changes) and flag the result as derived, so consumers know it was reconstructed.
5. Base vs quote orientation
Pools list their two tokens in arbitrary order. If you don't normalize, "buy" and "price" mean opposite things on different pools. We orient every pool the same way: the first of USDC, USDT or SOL present is the quote token. After that, is_buy and price mean the same thing on every venue.
6. Token-2022 extensions
Transfer-fee extensions change what a user actually receives, and other mint extensions (permanent delegate, transfer hook and so on) matter for risk. You need to read the mint account, not just the transaction, and cache it.
7. Big integers
Raw token amounts regularly exceed JavaScript's safe integer range (2^53). Send them as strings with the decimals alongside, or your JS consumers will silently lose precision.
8. Reconnects and gaps
gRPC streams drop. When you reconnect you need to know what you missed. We put a sequence number on every event so a client can resume from where it left off, and send an explicit gap message when something could not be replayed. Without that, a reconnect silently loses trades.
What the output looks like
After all of that, a PumpSwap trade and a Raydium CLMM trade come out in the same flat shape. Trimmed example:
{
"kind": "swap",
"venue": "pumpswap",
"commitment": "processed",
"slot": 454291681,
"via": "DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH",
"pool": "6tv1HzMFM93HHPZds7kyWZFuUEgVAnNkAgT1d5Dg7Gw5",
"user": "jMrze5nuUXTTWraMGWDnqzLED5JWvQygLByH86hpwJ1",
"base_mint": "7XSrFStYppauv9dvrPBqMXqJarQJo4QFSDsUp7Dmpump",
"quote_mint": "So11111111111111111111111111111111111111112",
"is_buy": true,
"base_amount": "328124895560",
"quote_amount": "210414078",
"base_decimals": 6,
"quote_decimals": 9,
"price": 6.412621561094693e-07,
"derived": false
}
When to just parse raw gRPC yourself
Building this yourself is the right call if:
- you need programs a decoded feed doesn't cover, or non-DEX activity
- you need the full transaction or account data, not just the decoded event
- you need confirmed or finalized commitment (ours, for example, publishes at processed, before confirmation)
- you already run Yellowstone and have decoders you trust
If you mostly want DEX trades, launches, migrations and pool events across many venues, and you'd rather not maintain decoders every time a program upgrades, a decoded feed is less work. For reference, the full multi-venue stream we see is about 480 messages per second (about 0.65 MB/s), so server-side filtering by venue, mint, pool or wallet matters.
We build sol-feed, a decoded Solana DEX WebSocket feed, which is where this list comes from. The original guide, with a Python client example, is here. Market data only.
Top comments (0)