Інтеграція бота з Raydium SDK (Solana)
Solana AMM працює принципово інакше, ніж Uniswap на EVM. На Ethereum swap — це один виклик контракту. На Solana — набір інструкцій всередину транзакції, кожна взаємодіє з конкретними account-ами. Якщо при інтеграції з Raydium SDK передати неправильний account (неправильний pool state PDA або token vault) — транзакція мовчки реверсується з кодом 0x1 без чіткого повідомлення. Це першає, з чим стикаються при самостійній інтеграції.
Специфіка Raydium AMM v4 та CLMM
Raydium підтримує два пули: AMM v4 (аналог Uniswap v2, constant product) та CLMM (concentrated liquidity, аналог Uniswap v3). Для торгового бота це різні SDK-шляхи та різна структура account-ів.
AMM v4 swap потребує передачи ~10 account-ів: pool state, token vaults обох активів, authority PDA, user token accounts. Усі адреси деривуються через findProgramAddressSync з правильними seeds — це не задокументовано явно, потрібно дивитися в source код SDK або reverse-інженерити існуючі транзакції через Solana Explorer.
CLMM додатково потребує tick array accounts — сегментів ціного діапазону. Якщо поточна ціна на границі тика, потрібно передати сусідні tick arrays, інакше транзакція провалиться. Raydium CLMM SDK v2 обробляє це автоматично через PoolUtils.computeAmountOut, але тільки якщо правильно ініціалізувати 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 — це ті самі tick arrays, які потрібно передати в інструкцію. Пропустити цей крок = гарантований revert.
Проблеми з latency та приоритетними комісіями
На Solana немає газової аукції як на EVM. Замість цього — compute unit price (priority fee). Транзакція з setComputeUnitPrice(microLamports) отримує пріоритет у черзі валідатора. Без priority fee у період високої нагрузки (новий meme-токен, торгівля на відкритті ринку) транзакція може зависнути на 5-10 секунд або взагалі не попасти в блок.
Оптимальна стратегія — динамічний розрахунок priority fee на основі 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),
});
Ще один момент — preflight checks. По замовчуванню sendTransaction прогоняє симуляцію перед відправленням. Для скоростного бота це лишні ~100ms. Якщо впевнені в коректності після власної симуляції — skipPreflight: true та commitment: 'processed' для швидкого підтвердження.
Архітектура бота
Стек: TypeScript, @raydium-io/raydium-sdk-v2, @solana/web3.js, Redis для стану.
Структура:
- WebSocket підписка на
programSubscribeпотрібного AMM program ID — детектимо нові пули - Парсинг account data через
PoolInfoLayoutдля отримання поточних резервів та ціни - Розрахунок swap через SDK, оцінка slippage та price impact
- Формування транзакції з приоритетними fees + versioned transaction (v0) для address lookup tables
- Відправлення на кілька RPC одночасно для резервування
Versioned transactions (v0) важливі: Raydium CLMM swap генерує ~20+ account-ів, стандартна legacy транзакція має лімith 35 account-ів. Address Lookup Tables дозволяють стиснути адреси та вмістити все в одну транзакцію.
Часові орієнтири
Базова інтеграція з AMM v4 Raydium (покупка/продаж по фіксованій парі) — 3-4 дні. Повнофункціональний бот з CLMM поддержкою, динамічним priority fee та мультипул моніторингом — 1-2 тижні. Вартість розраховується індивідуально.







