Інтеграція крипто-казино з провайдерами ігор
Крипто-казино технічно складніше звичайного online casino з однієї причини: транзакції необоротні й публічно верифіковані. Якщо класичне казино може откатити виплату "по технічним причинам", крипто-казино не може. Якщо смарт-контракт виплатив неправильну суму — це вже on-chain. Тому інтеграція з ігровими провайдерами повинна бути спроектована з врахуванням цих реалій.
Архітектура інтеграції: де казино зустрічається з провайдером
Типові ігрові провайдери
Більшість великих провайдерів (Pragmatic Play, Evolution, Hacksaw, BGaming, Spinomenal) надають Seamless wallet інтеграцію або Transfer wallet інтеграцію:
Seamless wallet — провайдер звертається до вашого API за кожною ставкою й виплатою в реальному часі. Ваш сервер авторизує дебет/кредит миттєво. Latency критична: провайдер очікує ответ < 1–2 секунди.
Transfer wallet — у гравця два баланси: ваш основний й тимчасовий у провайдера. Гравець сам робить transfer перед грою й виводить після. Простіше технічно, гірший UX.
Для крипто-казино seamless wallet створює challenge: провайдер очікує миттєвий ответ, а крипто-транзакції не миттєві. Рішення — off-chain баланс у вашій БД, синхронізований з on-chain коштами.
Двохрівневий баланс
On-chain: користувач тримає USDC у смарт-контракті казино
↕ депозит / вивід
Off-chain: ваша БД зберігає "ігровий баланс" (миттєві оновлення)
↕ seamless API вызови
Провайдер гри: робить bet/win вызови до вашого API
Депозит: користувач відправляє USDC у контракт → ваш сервіс детектує on-chain подію → зачисляє на off-chain баланс → користувач може грати.
Вивід: користувач запитує вивід → ви резервуєте суму → ініціюєте on-chain withdrawal з контракту → при підтвердженні помічаєте як виконаний.
Seamless Wallet API: що повинен реалізувати ваш бекенд
Провайдер звертається до ваших ендпоінтів. Стандартний набір:
POST /wallet/balance — отримати баланс гравця
POST /wallet/debit — списати ставку
POST /wallet/credit — зачислити виграш
POST /wallet/rollback — откат транзакції (при помилці провайдера)
POST /wallet/check — перевірка статусу транзакції
Ключові вимоги до реалізації:
Ідемпотентність — провайдер може надіслати один і той же запит кілька разів (retry при timeout). Кожен debit/credit має унікальний transactionId. Якщо вже оброблений — повернути той же результат без повторного застосування:
async function processDebit(req: DebitRequest): Promise<DebitResponse> {
// Перевірка ідемпотентності
const existing = await db.transactions.findByProviderTxId(req.transactionId);
if (existing) {
return { balance: existing.balanceAfter, transactionId: req.transactionId };
}
return await db.transaction(async (trx) => {
const user = await trx.users.lockForUpdate(req.userId);
if (user.balance < req.amount) {
throw new InsufficientFundsError();
}
const newBalance = user.balance - req.amount;
await trx.users.updateBalance(req.userId, newBalance);
await trx.transactions.create({
providerTxId: req.transactionId,
userId: req.userId,
type: "debit",
amount: req.amount,
balanceAfter: newBalance,
});
return { balance: newBalance, transactionId: req.transactionId };
});
}
Атомарність — баланс й запис транзакції оновлюються в одній БД транзакції. SELECT FOR UPDATE щоб уникнути race conditions при паралельних запитах.
Rollback — провайдер вызывает rollback якщо на їх стороні виникла помилка після debit. Ви повинні відновити баланс. Rollback може прийти через години після оригінальної транзакції.
On-chain контракт казино
Базова структура
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
contract CasinoVault is AccessControl, ReentrancyGuard, Pausable {
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
IERC20 public immutable token;
// Резерви для виплат (завжди повинно бути достатньо)
uint256 public playerFundsReserve;
event Deposit(address indexed player, uint256 amount);
event Withdrawal(address indexed player, uint256 amount);
function deposit(uint256 amount) external nonReentrant whenNotPaused {
token.transferFrom(msg.sender, address(this), amount);
playerFundsReserve += amount;
emit Deposit(msg.sender, amount);
}
// Тільки оператор ініціює вивід (після off-chain авторизації)
function withdraw(
address player,
uint256 amount,
bytes calldata signature // EIP-712 підпис від авторизуючого сервера
) external nonReentrant whenNotPaused {
_verifyWithdrawalSignature(player, amount, signature);
require(playerFundsReserve >= amount, "Insufficient reserves");
playerFundsReserve -= amount;
token.transfer(player, amount);
emit Withdrawal(player, amount);
}
}
Provably fair механіка
Для on-chain ігор (не провайдерських, а власних) доказуємо честність важлива. Класичний підхід — commit-reveal:
- Сервер публікує
commitment = keccak256(serverSeed)перед раундом - Гравець робить ставку з
clientSeed - Після ставки сервер reveals
serverSeed - Результат =
keccak256(serverSeed + clientSeed + nonce)— верифіковано будь-ким
Для on-chain VRF — Chainlink VRF v2. Запит випадковості коштує LINK, ответ приходить в окремій транзакції (~1–3 хв). Підходить для jackpot й рідких событіїв, не для real-time слотів.
Безпека й compliance
Обмеження й лімити
uint256 public maxDailyWithdrawal = 100_000 * 1e6; // 100k USDC
mapping(address => uint256) public dailyWithdrawn;
mapping(address => uint256) public lastWithdrawalDay;
modifier checkDailyLimit(address player, uint256 amount) {
uint256 today = block.timestamp / 1 days;
if (lastWithdrawalDay[player] < today) {
dailyWithdrawn[player] = 0;
lastWithdrawalDay[player] = today;
}
require(dailyWithdrawn[player] + amount <= maxDailyWithdrawal, "Daily limit exceeded");
dailyWithdrawn[player] += amount;
_;
}
KYC/AML інтеграція
Незважаючи на Web3, більшість юрисдикцій вимагає KYC при виводі вище певних сум. Chainalysis або Elliptic для on-chain AML screening — перевірка вхідних депозитів на приналежність до санкціонованих адрес або міксерів.
Workflow: wallet screening при першому депозиті → manual review якщо risk score > поріг → block withdrawal якщо confirmed high-risk.
Моніторинг та операційна робота
Баланс резервів: контракт завжди повинен мати достатньо коштів для покриття всіх off-chain балансів гравців. Автоматичний моніторинг: якщо playerFundsReserve < sum(all player balances) * 1.05 — alert.
Аномалії виплат: незвичайно великий виграш, підозрілий паттерн ставок (ідеальне використання rollback), масові виводи — тригери для manual review.
Провайдер uptime: якщо провайдер недоступний — потрібен graceful degradation, не 500 помилки у користувача. Circuit breaker: після N помилок — тимчасово відключити провайдера, показати "гра на техобслуговуванні".
Срок разработки MVP інтеграції з одним провайдером: 6–10 тижнів з урахуванням тестування на staging окружінні провайдера.







