Разработка торгового бота для DEX на Solana (Jupiter, Raydium)
Solana обрабатывает теоретически 65 000 TPS при confirmation time 400ms. На практике для торгового бота это означает: конкурентное преимущество существует, но только если вы правильно работаете с приоритетными комиссиями и понимаете механику Solana transaction scheduling. Большинство ботов проигрывают не из-за плохого алгоритма, а из-за того что транзакции попадают в конец очереди из-за неправильно рассчитанного priority fee.
Solana transaction model: чем отличается от EVM
В Ethereum gas price определяет приоритет. В Solana — комбинация compute units и priority fee:
- Compute units (CU) — аналог gas, лимит вычислительных ресурсов для транзакции. Максимум 1.4M CU на транзакцию.
- Priority fee — дополнительная плата в lamports за каждый compute unit сверх базовой комиссии.
Обязательные инструкции для конкурентного бота:
import { ComputeBudgetProgram } from "@solana/web3.js";
// Устанавливаем лимит CU (важно: не больше чем нужно)
const setComputeLimit = ComputeBudgetProgram.setComputeUnitLimit({
units: 200_000, // обычно для swap достаточно 100k-200k
});
// Устанавливаем priority fee
const setPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 100_000, // 0.1 lamport per CU = 0.02 SOL на 200k CU
});
transaction.add(setComputeLimit, setPriorityFee, ...swapInstructions);
Неправильно рассчитанный лимит CU в меньшую сторону → транзакция fails с exceeded compute budget. В большую сторону → переплата и снижение приоритета (validators оптимизируют throughput по fee/CU ratio).
Динамический расчёт priority fee: используем getRecentPrioritizationFees RPC метод, который возвращает последние fee уровни для аккаунтов, задействованных в транзакции. Берём 75-90 percentile для высокого приоритета.
Jupiter: агрегация маршрутов
Jupiter — de-facto стандартный агрегатор ликвидности на Solana. Агрегирует Raydium, Orca, Meteora, Lifinity и ещё 20+ DEX/AMM. API v6 — самая актуальная версия.
Quote API
const quote = await fetch(`https://quote-api.jup.ag/v6/quote?` + new URLSearchParams({
inputMint: "So11111111111111111111111111111111111111112", // SOL
outputMint: USDC_MINT,
amount: "1000000000", // 1 SOL в lamports
slippageBps: "50", // 0.5%
onlyDirectRoutes: "false",
maxAccounts: "64", // ограничение аккаунтов в транзакции
}));
const quoteData = await quote.json();
// quoteData.outAmount — ожидаемый вывод в USDC
// quoteData.priceImpactPct — price impact в процентах
maxAccounts: 64 — критический параметр. Solana транзакция ограничена 64 уникальными аккаунтами. Сложный маршрут через 4-5 протоколов может превысить лимит → TooManyAccounts ошибка. Ограничение уменьшает оптимальность маршрута, но гарантирует исполнимость.
Swap execution
После получения quote — исполнение через Swap API:
const swapResponse = await fetch("https://quote-api.jup.ag/v6/swap", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
quoteResponse: quoteData,
userPublicKey: wallet.publicKey.toString(),
wrapAndUnwrapSol: true,
dynamicComputeUnitLimit: true, // автоматический расчёт CU
prioritizationFeeLamports: "auto", // автоматический priority fee
}),
});
const { swapTransaction } = await swapResponse.json();
// Десериализуем, подписываем, отправляем
const tx = VersionedTransaction.deserialize(Buffer.from(swapTransaction, "base64"));
tx.sign([wallet]);
const txid = await connection.sendRawTransaction(tx.serialize(), {
skipPreflight: false,
maxRetries: 3,
});
dynamicComputeUnitLimit: true — Jupiter автоматически симулирует транзакцию и устанавливает правильный CU лимит. Рекомендуем для production.
Raydium: прямая интеграция
Jupiter работает поверх Raydium, но для latency-sensitive операций прямая интеграция с Raydium CLMM (Concentrated Liquidity Market Maker) быстрее.
Raydium SDK v2:
import { Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2";
import { PublicKey } from "@solana/web3.js";
const raydium = await Raydium.load({
owner: wallet,
connection,
disableFeatureCheck: true,
});
// Получаем информацию о пуле
const poolInfo = await raydium.clmm.getPoolInfoFromRpc(POOL_ID);
// Строим swap транзакцию
const { transaction } = await raydium.clmm.swap({
poolInfo,
ownerInfo: { useSOLBalance: true },
inputMint: new PublicKey(INPUT_MINT),
amountIn: new BN(amount),
amountOutMin: new BN(minAmountOut),
observationId: poolInfo.observationId,
txVersion: TxVersion.V0, // Versioned transactions
});
Versioned Transactions (V0) с Address Lookup Tables — обязательны для complex multi-hop swaps. Позволяют включать больше аккаунтов через ALT сжатие.
Latency оптимизация
Для конкурентного бота latency измеряется не в секундах — в миллисекундах:
Jito bundling. Jito — MEV-инфраструктура на Solana. Bundle из нескольких транзакций отправляется напрямую к Jito block engine, минуя стандартный gossip. Преимущество: atomic исполнение нескольких транзакций в одном блоке, первый слот в блоке.
import { searcherClient } from "jito-ts/dist/sdk/block-engine/searcher";
const client = searcherClient(JITO_BLOCK_ENGINE_URL, keypair);
const bundle = new Bundle([tx1, tx2], 5); // max 5 transactions
await client.sendBundle(bundle);
Jito взимает tip — минимум 1000 lamports per bundle, реально при конкурентных условиях 10 000 - 100 000+ lamports.
Geyser plugin / yellowstone. Для real-time мониторинга on-chain данных (изменение пулов, новые транзакции) — Solana Geyser plugin через Yellowstone gRPC. Латентность 5-20ms vs 200-500ms через стандартный RPC polling.
Географическое расположение. Серверы нод кластера Solana сконцентрированы в определённых датацентрах. Размещение бота близко к validator nodes — Amsterdam, Frankfurt для Европы, Ashburn для США — снижает network latency на 10-50ms.
Мониторинг и управление рисками
Transaction confirmation tracking: confirmTransaction через WebSocket subscription намного быстрее чем polling. Статусы: processed → confirmed → finalized.
Failed transaction handling: При ошибке BlockhashNotFound (устаревший blockhash) — автоматически fetch новый blockhash и retry. При SlippageToleranceExceeded — пересчёт quote и retry с актуальными данными.
Capital management: Отдельный keypair для каждой торговой стратегии. Никогда не держим весь баланс в hot wallet. Hardware wallet или KMS для long-term storage.
Сравнение подходов: Jupiter API vs прямая интеграция
| Параметр | Jupiter API | Прямая интеграция (Raydium SDK) |
|---|---|---|
| Оптимальность маршрута | Высокая (20+ DEX) | Ниже (один протокол) |
| Latency quote | ~100-200ms | ~20-50ms (on-chain) |
| Maintenance | Минимальный | Обновления SDK |
| Сложность | Низкая | Высокая |
| Кастомизация | Ограниченная | Полная |
Для большинства ботов Jupiter API — правильный выбор: лучшие цены, меньше кода. Прямая интеграция с Raydium — только если нужна sub-50ms latency или специфичное взаимодействие с пулами (LP management, concentrated liquidity range orders).
Процесс разработки
Аналитика (2-3 дня). Определение стратегии, выбор Jupiter API vs прямая интеграция, определение требований к latency и объёму.
Разработка core бота (1-2 недели). WebSocket мониторинг, quote engine, execution с priority fees, Jito bundling (если нужно).
Risk management и мониторинг (3-5 дней). Slippage защита, failed tx handling, Telegram алерты, метрики.
Оптимизация (3-5 дней). Профилирование latency, оптимизация CU usage, тюнинг priority fees под реальный трафик.
Ориентиры по срокам
Базовый бот с Jupiter API и автоматическим priority fee — 1 неделя. Конкурентный бот с Jito bundling, Geyser мониторингом и кастомными стратегиями — 2-3 недели. Стоимость рассчитывается индивидуально.







