Интеграция с 1inch API
Написать самостоятельный роутинг по DEX — это недели работы: нужно агрегировать ликвидность Uniswap v2/v3, Curve, Balancer, SushiSwap, находить оптимальный путь через graph algorithm, учитывать gas cost каждого hop. 1inch решает эту задачу через Aggregation Protocol, который сплитует swap между несколькими источниками ликвидности. Интеграция занимает дни, а не недели — если сделать её правильно.
Где интеграция обычно ломается
Устаревший quote и slippage при исполнении
GET /v6.0/1/quote возвращает toAmount — ожидаемое количество токенов на выходе. Между моментом получения quote и исполнением транзакции проходит время. На волатильном рынке за 10-30 секунд цена может сдвинуться на 0.5-2%.
Если передавать в POST /v6.0/1/swap параметр slippage=1 (1%), при реальном движении рынка на 1.5% транзакция зареверсируется — пользователь заплатил газ и ничего не получил. Правильно: динамически устанавливать slippage на основе волатильности пары, 0.5% для stable-пар, 1-3% для волатильных.
Ещё одна проблема: toAmount из /quote не совпадает с toAmount из /swap. Это нормально — /swap строит финальный calldata с учётом текущего состояния пулов. Показывать пользователю цифру из /quote, а подписывать транзакцию с /swap — правильная практика.
Approve и permit: два паттерна
1inch Aggregation Router v6 принимает tokens через стандартный ERC-20.approve. Но для лучшего UX поддерживается также permit (EIP-2612) — gasless approve через подпись. Если токен реализует EIP-2612 (DAI, USDC на Ethereum, большинство современных ERC-20), нужно использовать /approve/transaction endpoint только как fallback.
Проверка поддержки permit: вызвать token.nonces(address) — если не reverting, permit поддерживается.
Второй тип approve — 1inch Permit2 (аналог Uniswap Permit2). Если пользователь уже дал approve в Permit2 для другого протокола, повторный approve не нужен. Это улучшает UX при частых свопах.
Как мы интегрируем 1inch
Структура запросов
Базовый флоу для swap виджета:
-
GET /v6.0/{chainId}/tokens— кешируем список поддерживаемых токенов (раз в час достаточно) -
GET /v6.0/{chainId}/quote?src=...&dst=...&amount=...— получаем quote, показываем пользователю -
GET /v6.0/{chainId}/approve/allowance?tokenAddress=...&walletAddress=...— проверяем текущий allowance - Если allowance < amount:
GET /v6.0/{chainId}/approve/transaction→ подписываем approve -
POST /v6.0/{chainId}/swap→ получаем calldata, отправляем транзакцию
Для мультичейн поддержки используем chainId в URL. 1inch поддерживает Ethereum (1), Polygon (137), Arbitrum (42161), Optimism (10), BSC (56), Avalanche (43114), Base (8453).
Обработка ошибок API
1inch v6 возвращает HTTP 400 с JSON body при любой ошибке бизнес-логики. Типичные коды:
-
"Cannot estimate"— недостаточно ликвидности для запрошенной суммы -
"Insufficient liquidity"— то же, явно -
"fromTokenAddress cannot be equal to toTokenAddress"— UI баг - Код 429 — rate limit. Free tier: 1 RPS, Growth: 10 RPS, Enterprise: без ограничений
Rate limiting нужно обрабатывать через exponential backoff, не слать запросы повторно немедленно.
Fusion mode vs Classic
1inch Fusion (v5+) — orderbook-based execution через resolvers. Пользователь подписывает order off-chain (gasless), resolver исполняет транзакцию и платит gas. Пользователь платит через slippage. Это лучший UX, но требует интеграции через @1inch/fusion-sdk, не через REST API.
Для простой интеграции (swap виджет, агрегатор в dApp) — Classic mode через REST API. Для продвинутого UX с gasless transactions — Fusion.
Проверка calldata
Перед отправкой транзакции пользователем — всегда симулировать через eth_call. Это позволяет поймать revert до трат газа. В wagmi/viem:
const { data } = await publicClient.call({
account: userAddress,
to: swapData.tx.to,
data: swapData.tx.data,
value: BigInt(swapData.tx.value),
});
Если call reverting — показываем пользователю ошибку, не транзакцию.
Стек интеграции
viem + wagmi для TypeScript/React приложений — нативная поддержка TypeScript, tree-shaking, хорошая интеграция с WalletConnect и MetaMask. Альтернатива — ethers.js v6 для Node.js бэкенда.
Для кеширования quote данных — React Query с staleTime: 10_000 (10 секунд). Более старый quote не показываем, запрашиваем заново.
Процесс работы
Анализ требований (0.5 дня). Какие чейны, какие токены, Classic или Fusion, нужен ли собственный UI или embed виджет.
Разработка (2-3 дня). API слой с типизацией, React хуки для quote/swap flow, обработка allowance, error handling.
Тестирование (0.5-1 день). Тесты на testnet (1inch поддерживает Sepolia). Проверка edge cases: нет ликвидности, insufficient balance, expired quote.
Ориентиры по срокам
Базовая интеграция swap функциональности в существующий dApp: 2-3 дня. Полноценный swap виджет с мультичейн поддержкой, историей транзакций и Fusion mode: 1-1.5 недели.







