Raydium SDK bot integration (Solana)
Solana AMM works fundamentally differently than Uniswap on EVM. On Ethereum, swap is one contract call. On Solana it's a set of instructions within a transaction, each interacting with specific accounts. If you pass an incorrect account during Raydium SDK integration (wrong pool state PDA or token vault) — transaction silently reverts with code 0x1 without clear message. This is the first issue encountered during self-integration.
Specifics of Raydium AMM v4 and CLMM
Raydium supports two pools: AMM v4 (similar to Uniswap v2, constant product) and CLMM (concentrated liquidity, similar to Uniswap v3). For trading bot these are different SDK paths and different account structures.
AMM v4 swap requires passing ~10 accounts: pool state, token vaults for both assets, authority PDA, user token accounts. All addresses are derived via findProgramAddressSync with correct seeds — this isn't documented explicitly, you need to look at SDK source code or reverse-engineer existing transactions via Solana Explorer.
CLMM additionally requires tick array accounts — price range segments. If current price is on tick boundary, you must pass neighboring tick arrays, otherwise transaction fails. Raydium CLMM SDK v2 handles this automatically via PoolUtils.computeAmountOut, but only if you correctly initialize PoolInfoLayout.
import { CLMM, PoolUtils } from '@raydium-io/raydium-sdk-v2';
const poolInfo = await CLMM.getPoolInfoFromRpc({
connection,
poolId: new PublicKey(POOL_ID),
});
const { amountOut, remainingAccounts } = PoolUtils.computeAmountOut({
poolInfo,
tickArrayCache,
baseMint: new PublicKey(INPUT_MINT),
epochInfo: await connection.getEpochInfo(),
amountIn: new BN(swapAmount),
slippage: 0.005,
});
remainingAccounts — these are the tick arrays that must be passed in the instruction. Missing this step = guaranteed revert.
Latency issues and priority fees
Solana has no gas auction like EVM. Instead — compute unit price (priority fee). Transaction with setComputeUnitPrice(microLamports) gets priority in validator queue. Without priority fee during high load periods (new meme token, market open trading) transaction may hang 5-10 seconds or not make it into block.
Optimal strategy — dynamic priority fee calculation based on recent fee statistics:
const recentFees = await connection.getRecentPrioritizationFees({
lockedWritableAccounts: [poolStatePubkey, userTokenAccount],
});
const p75Fee = recentFees
.map(f => f.prioritizationFee)
.sort((a, b) => a - b)[Math.floor(recentFees.length * 0.75)];
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: Math.max(p75Fee * 1.2, MIN_PRIORITY_FEE),
});
Another point — preflight checks. By default sendTransaction runs simulation before sending. For high-speed bot this is extra ~100ms. If you're confident in correctness after your own simulation — skipPreflight: true and commitment: 'processed' for fast confirmation.
Bot architecture
Stack: TypeScript, @raydium-io/raydium-sdk-v2, @solana/web3.js, Redis for state.
Structure:
- WebSocket subscription to
programSubscribeof target AMM program ID — detect new pools - Parse account data via
PoolInfoLayoutto get current reserves and price - Calculate swap via SDK, estimate slippage and price impact
- Form transaction with priority fees + versioned transaction (v0) for address lookup tables
- Send to multiple RPCs simultaneously for redundancy
Versioned transactions (v0) are important: Raydium CLMM swap generates ~20+ accounts, standard legacy transaction has 35 account limit. Address Lookup Tables let you compress addresses and fit everything in one transaction.
Timeline estimates
Basic AMM v4 Raydium integration (buy/sell at fixed pair) — 3-4 days. Full-fledged bot with CLMM support, dynamic priority fee and multi-pool monitoring — 1-2 weeks. Cost calculated individually.







