Розробка мобільного додатка для P2P-обміну криптовалюти
P2P-біржа — це не просто дошка оголошень з цінами. Це система, в якій гроші та крипта мають переходити з рук в руки з мінімальним довір'ям між сторонами. Ключовий механізм — escrow: криптовалюта продавця блокується на смарт-контракті або кастодіальному кошельку до підтвердження отримання фіатних грошей. Якщо цю логіку реалізувати недбайливо — або продавець втратить крипту без оплати, або покупець заплатить та не отримає нічого.
Escrow: смарт-контракт vs кастодіальний сервіс
На вибір два підходи:
Смарт-контракт escrow (некастодіальний). Продавець депонує крипту в контракт через approve() + deposit(). Покупник переводить фіат будь-яким способом → натискає "підтвердити отримання" → контракт викликає release() та відправляє крипту покупцю. Якщо спір — арбітражний адрес може викликати resolveDispute(winner).
// Спрощена логіка escrow на EVM-сумісній цепи
contract P2PEscrow {
enum Status { ACTIVE, RELEASED, REFUNDED, DISPUTED }
struct Trade {
address seller;
address buyer;
address token;
uint256 amount;
Status status;
}
mapping(uint256 => Trade) public trades;
address public arbiter;
function deposit(uint256 tradeId, address buyer, address token, uint256 amount) external {
IERC20(token).transferFrom(msg.sender, address(this), amount);
trades[tradeId] = Trade(msg.sender, buyer, token, amount, Status.ACTIVE);
}
function release(uint256 tradeId) external {
Trade storage t = trades[tradeId];
require(msg.sender == t.seller, "Only seller");
require(t.status == Status.ACTIVE);
t.status = Status.RELEASED;
IERC20(t.token).transfer(t.buyer, t.amount);
}
function dispute(uint256 tradeId) external {
Trade storage t = trades[tradeId];
require(msg.sender == t.buyer || msg.sender == t.seller);
t.status = Status.DISPUTED;
}
function resolveDispute(uint256 tradeId, address winner) external {
require(msg.sender == arbiter);
Trade storage t = trades[tradeId];
require(t.status == Status.DISPUTED);
IERC20(t.token).transfer(winner, t.amount);
}
}
Переваги — децентралізований, користувачі самі контролюють гаманці. Недоліки — газ на кожну операцію, складність для новачків.
Кастодіальний escrow. Сервер зберігає крипту на hot wallet. Швидше, без газу, простіший UX. Потребує високих стандартів безпеки: HSM для приватних ключів, мультисигнатурні гаманці (Gnosis Safe), розділення cold/hot wallet.
Мобільний клієнт: архітектура та Web3
На iOS — web3.swift або кастомна інтеграція через URLSession до JSON-RPC. На Android — web3j. Для гаманця користувача — WalletConnect v2 (Sign SDK): дозволяє підключити MetaMask, Trust Wallet, Rainbow та відправляти транзакції через deep link без зберігання ключів у додатку.
// Підключення через WalletConnect v2 на iOS
import WalletConnectSign
class WalletService {
func connect() async throws {
let methods: Set<String> = ["eth_sendTransaction", "personal_sign"]
let chains = [Blockchain("eip155:1")!] // Ethereum mainnet
let namespaces: [String: ProposalNamespace] = [
"eip155": ProposalNamespace(
chains: chains,
methods: methods,
events: ["chainChanged", "accountsChanged"]
)
]
let uri = try await Sign.instance.connect(requiredNamespaces: namespaces)
// Відкриваємо Deep Link до гаманця або показуємо QR
await UIApplication.shared.open(uri.deepLink)
}
}
Лента ордерів та real-time оновлення
Список ордерів на купівлю/продаж має оновлюватися в реальному часі — WebSocket від сервера. Новий ордер, зміна ціни, закриття сделки — все через push по ws://. На клієнті URLSessionWebSocketTask (iOS) або OkHttp WebSocket (Android).
Фільтрація ордерів: валюта, спосіб оплати (банківський переказ, наличні), діапазон суми, рейтинг продавця. Рейтингова система — обов'язковий елемент P2P. Без неї площадка не набирає довіру. Зберігаємо історію сделок та відгуки, рейтинг рахуємо на сервері.
Верифікація користувачів (KYC)
Регуляторні вимоги для P2P-площадок: хоча б базовий KYC (фото паспорта + selfie). На iOS — VisionKit документ-сканер, на Android — ML Kit Document Scanner. Перевірку документів передаємо на Sum Sub, Veriff або Jumio через їхній мобільний SDK — немає сенсу реалізовувати liveness detection самостійно.
Ліміти за замовчуванням для неверифікованих користувачів, підняття ліміту після KYC — стандартна схема.
Чат між трейдерами
Вбудований чат між покупцем та продавцем у межах сделки — критична функція. Без нього неможливо розв'язати спірні ситуації. Реалізуємо через Firebase Realtime Database або Stream Chat SDK — останній дає готовий UI для iOS/Android, економить 2–3 дні розробки. Сповіщення шифруємо end-to-end через libsignal якщо потрібна додаткова приватність.
Підтвердження оплати фіату — скриншот з банку, завантажений у чат. Зберігається у Firebase Storage або S3 з presigned URL.
Безпека
Rate limiting на ендпоїнтах публікації ордерів — без нього конкуренти зальють ринок мусорними ордерами. Anti-scam перевірки: новий аккаунт не може одразу публікувати великі ордера. 2FA через TOTP (Google Authenticator) — обов'язково для виводу коштів. Біометрична аутентифікація через LocalAuthentication (iOS) / BiometricPrompt (Android) для підтвердження сделок.
Етапи роботи
| Етап | Терміни |
|---|---|
| Проектування: escrow-механізм, архітектура | 1 тиждень |
| Смарт-контракт + аудит (опціонально) | 1–2 тижні |
| Серверна частина (API, ордербук, escrow) | 2–3 тижні |
| Мобільний клієнт iOS + Android | 3–4 тижні |
| KYC-інтеграція, чат | 1 тиждень |
| Тестування, testnet/mainnet деплой | 1 тиждень |
Всього: 8–12 тижнів залежно від типу escrow та набору функцій. Вартість розраховується індивідуально після аналізу вимог.







