A Raydium transaction can contain several instructions and routed swap legs. Parsing the first byte that looks like a swap is not enough: first resolve the instruction's program ID, then decode the layout for that exact Raydium program.
This guide covers the AMM v4 exact-input instruction body. CLMM and CPMM require their own layouts and program IDs.
Start with a filtered transaction stream
Use the Yellowstone setup and set PROGRAM_ID to the AMM v4 program from the official Raydium addresses. Keep that address in configuration and verify it when updating the decoder.
Build the effective account-key list from static keys followed by loaded writable and loaded readonly addresses. Resolve programIdIndex against that list. Apply the decoder only when the resolved program equals the AMM v4 program.
Decode the exact-input instruction body
This standalone function accepts instruction bytes after program validation. Save it as decode.mts and run it with node --import tsx decode.mts after installing tsx.
import assert from 'node:assert/strict';
function decodeAmmV4SwapBaseIn(data: Uint8Array) {
const bytes = Buffer.from(data);
if (bytes.length !== 17 || bytes[0] !== 9) return null;
return {
amountInRaw: bytes.readBigUInt64LE(1).toString(),
minimumAmountOutRaw: bytes.readBigUInt64LE(9).toString(),
};
}
const fixture = Buffer.alloc(17);
fixture[0] = 9;
fixture.writeBigUInt64LE(1_000_000n, 1);
fixture.writeBigUInt64LE(950_000n, 9);
assert.deepEqual(decodeAmmV4SwapBaseIn(fixture), {
amountInRaw: '1000000', minimumAmountOutRaw: '950000',
});
assert.equal(decodeAmmV4SwapBaseIn(Buffer.alloc(3)), null);
The fixture checks byte offsets and truncation behavior. It is synthetic, not a recorded on-chain transaction, and does not establish program coverage.
Minimum output is not executed output
The instruction contains a slippage constraint. It does not tell you the amount actually received. Recover executed amounts from the relevant token transfers, program events, or carefully attributed balance deltas.
A transaction-wide balance delta can combine multiple swaps, fees, transfers, and account closures. It is not automatically the fill for one instruction. Retain instruction position and inner-instruction context while attributing execution.
Walk inner instructions and preserve multiple legs
Aggregators often call AMM programs through CPI. Visit both top-level and inner instructions, validate each program, and keep all matching legs. Returning after the first match loses activity.
Store signature, slot, instruction path, pool, input mint, output mint, and raw amounts. Determine buy or sell relative to the mint your screen represents. A swap's direction is not an absolute property independent of token scope.
Know when to use normalized trades
If your application needs a trade tape rather than protocol research, the normalized trade stream avoids maintaining several Raydium parsers. Keep raw decoding when you need instruction semantics, custom attribution, or independent verification.
FAQ
Does this function parse all Raydium swaps?
No. It handles the AMM v4 exact-input body only, after program validation.
Why preserve raw amounts as strings?
Token integers can exceed JavaScript safe integer precision. Convert for display only with known mint decimals.
Can one transaction contain multiple swaps?
Yes. Preserve instruction-level identity and inspect inner instructions.
References
Companion project
The companion example contains a fuller project layout. Check the companion dependencies and bundled program layouts against the versions described here before use. Keep credentials in a local environment file, never in a shared browser workspace.