Інтеграція API Binance у мобільні крипто-додатки
REST та WebSocket не є взаємозамінюваними. Binance надає обидва транспорти, і більшість помилок при інтеграції виникають тому, що команди намагаються підписатися на рынкові дані через REST замість WebSocket Streams, або навпаки — намагаються виставити ордер через wss://stream.binance.com:9443.
Розберемо обидва сценарії по-чесному.
REST API: лімітиґ, підпис і типові краші на мобілі
Binance REST API версії 3 (/api/v3/) використовує HMAC-SHA256 для підпису приватних endpoints. Підпис формується з рядка queryString + body, до якої додається timestamp та опціональний recvWindow. Типова помилка — {"code":-1021,"msg":"Timestamp for this request is outside of the recvWindow."} — виникає не через криву підпис, а тому що системні години на Android-пристрої відхилились від серверного часу на 2–3 секунди. На iOS це рідкість, на Android бюджетних пристроїв — норма.
Правильне рішення: не hardcode recvWindow=5000, а синхронізувати локальний час з /api/v3/time при кожному холодному старті додатка й зберегти serverTimeOffset в пам'яті.
Лімітиґ вагові, не запросні. Кожний endpoint має weight — /api/v3/depth?limit=1000 коштує 50 одиниць, тоді як /api/v3/ticker/price — 1. Хвилинний лімітґ — 6000 одиниць. Мобільний додаток з агресивним поллингом стаканів на 5 пар улітає в бан (HTTP 429) за 30 секунд. Реалізуйте WeightBudget-менеджер: чергу запитів з пріоритетами, дебаунс на ручне оновлення й миттєвий переїхідь на WebSocket при перевищенні 80% квоти.
WebSocket Streams: життєвий цикл з'єднання на мобілі
wss://stream.binance.com:9443/ws/<streamName> — окремий хост, без авторизації для публічних стрімів. Для приватних (ордери, баланс) потрібен listenKey, який отримують через POST /api/v3/userDataStream та продовжують кожні 30 хвилин через PUT /api/v3/userDataStream.
Проблема мобіля: фоновий режим. На iOS додаток іде в background, сокет закривається з кодом 1001 (going away). При повертанні на foreground потрібно:
- Перевірити, чи не вийшов строк
listenKey(TTL — 60 хвилин з моменту останньогоPUT) - Якщо вийшов — отримати новий, переподписатися
- Відновити всі публічні стрімиа
На Android агресивний Doze Mode перерває TCP-сокет раніше, ніж WebSocket встигне відправити ping. OkHttp з pingInterval(20, TimeUnit.SECONDS) справляється, але лише якщо WakeLock утримується на рівні WorkManager.
Для Flutter використовуйте web_socket_channel з кастомним ReconnectingWebSocketChannel — wrapper з exponential backoff (старт 1 с, максимум 30 с) та журналом пропущених подій для reconciliation при переподключенні.
Підпис ордерів: що не так з більшістю реалізацій
Критична деталь: параметри в query string та в body вважаються разом. Якщо POST /api/v3/order відправляється з тілом symbol=BTCUSDT&side=BUY&...×tamp=..., то підпис формується з усієї цієї рядка цілком — без знака ?. Типова помилка — підписувати лише body або лише query, отримати {"code":-1022,"msg":"Signature for this request is not valid."} й шукати баг в алгоритмі хешування.
Ще один нюанс: порядок параметрів важливий лише для підпису, але не для виконання — Binance приймає їх у будь-якому порядку, але HMAC чутливий до порядку конкатенації.
Як будуємо інтеграцію
Архітектура: Clean Architecture з окремим BinanceDataSource (network layer), TradeRepository (бізнес-логіка) та ViewModel-слоєм для UI.
Для REST: Retrofit 2 + OkHttpClient з інтерцептором підпису та інтерцептором синхронізації часу. Перехоплюємо 429 та 418 (IP-бан) — при 418 показуємо користувачу таймер до разбану (заголовок Retry-After).
Для WebSocket: окремий BinanceStreamManager — Singleton в DI-контейнері (Hilt), управляє пулом стрімів, дедублікує підписки (якщо два екрани хочуть btcusdt@trade — один сокет, два observer'и через SharedFlow).
Тестування: Binance Testnet (testnet.binance.vision) з окремим ключем. MockWebServer у unit-тестах для перевірки підпису без мережі.
Оцінка й терміни
Вартість інтеграції залежить від обсягу функціональності: лише маркет-дані (без торгівлі) — один рахунок, повноцінний трейдинг з управлінням ордерами й портфелем — зовсім інший. Перед оцінкою уточніть вимоги: які endpoints потрібні, Spot + Futures + Margin, чи є існуючий бекенд-прокси або все з мобільного.
Базова інтеграція (маркет-дані + один тип торгівлі) — від 2 до 4 тижнів. Повний торговий терміна з кількома типами ордерів, стаканом, історією й аналітикою — від 6 до 12 тижнів залежно від платформи (нативна iOS/Android vs Flutter).







