WinUpGo
Поиск
CASWINO
SKYSLOTS
BRAMA
TETHERPAY
777 FREE SPINS + 300%
Криптовалютное казино Крипто-казино Torrent Gear – ваш универсальный торрент-поиск! Torrent Gear

Баланс и кошельки: архитектура multi-wallet

1) Зачем multi-wallet и какие цели

Одна запись «баланс = число» не покрывает реальность iGaming. Нужны отдельные кошельки/субсчета: реальные деньги (cash), бонусные средства, вэйджер-пул, фриспины, комп-поинты, иногда — валютные кошельки (EUR/USD/BRL).

Цели архитектуры:
  • Точность денег (double-entry, аудируемость).
  • Политики списания (например, сначала бонус/вэйджер, потом cash).
  • Скорость (p95 API ≤ 250–400 мс, ставка/сеттлмент в реальном времени).
  • Безопасность и комплаенс (KYC/AML, лимиты ответственной игры, регуляторы).
  • Масштаб: пики → десятки тысяч операций/сек, миллиарды постингов/месяц.

2) Модель данных: «Ledger + Subwallets»

Минимальные сущности

Account: игрок/бренд/маркет.

Wallet: `{type: CASHBONUSWAGERFSPOINTS, currency, status}`.
LedgerEntry (двойная запись): `debit_account`, `credit_account`, `amount`, `currency`, `operation_id`, `category`, `created_at`.
Posting: атомарная бизнес-операция, объединяет 2+ LedgerEntry.
Hold/Reservation: временная блокировка средств под ставку/вывод.
Policy: правила приоритета списания/зачисления.
FXRate: курс/точность/правила округления.
Limit: дневные/месячные/ответственная игра.

Пример таблиц (упрощённо)

sql
-- Балансовые счета для double-entry (включая служебные)
accounts(id, owner_user_id, type, currency, status,...)

-- Проводка (двойная запись, ссылка на бизнес-операцию)
ledger_entries(id, posting_id, debit_account_id, credit_account_id,        amount_minor, currency, category, operation_id, created_at)

-- Холды (резервы)
holds(id, account_id, amount_minor, currency, reason, expires_at, state,    operation_id, created_at)

-- Политики списания (приоритеты)
spend_policies(id, market, wallet_priority jsonb, updated_at)

-- Кросс-валютные курсы fx_rates(ccy_from, ccy_to, rate, precision, valid_from)

Правило: истина живет в журнале проводок (`ledger_entries`). Текущий баланс — либо агрегат (материализованный снэпшот), либо вычисляется из журнала (дорого, но единственно верно).


3) Типы кошельков и их поведение

КошелёкДля чегоМожно пополнитьМожно списатьСпециальные правила
CASHРеальные деньгиPSP/ручные начисления/возвратыСтавки, покупки, выводВлияет на AML/KYC; транзакции попадают в бухучёт
BONUSБонусные деньгиПромо/кампанииСтавки (по правилам)Не выводится напрямую, конвертируется в Cash при выполнении вэйджера
WAGERУчёт «замороженных» бонусовАвто из бонуса при ставкеСписания в пользу провайдера игрПравило освобождения при settle/отмене
FS (FreeSpins)Пакеты вращенийКампанииПогашение в слотахДенежный эквивалент фиксируется по T&C
POINTSЛояльность/компыАктивностьМагазин/статусыНе деньги; не попадает в отчёты AML

4) Политики списания и порядок приоритета

Чётко формализуйте алгоритм источника средств: Пример (слоты/казино):

1. Сначала списывать из WAGER (если активен вэйджер).

2. Затем из BONUS, пока не исчерпан.

3. Остаток — из CASH.

Пример (спорт):

1. Сначала CASH (регулятор/налог).

2. Затем BONUS (freebet), переводя в WAGER.

Сохраняйте в Postings «решение политики» как атрибут, чтобы саппорт и аудит видели «почему так списали».


5) Жизненный цикл денег и операций

Депозит

1. `POST /wallet/deposit` → создаём pending запись (inbox колбэка PSP).

2. Вебхук PSP (подпись HMAC, идемпотентность по `operation_id`) → credit CASH, category=`DEPOSIT`.

3. Публикуем событие `wallet_updated`.

Ставка

1. `POST /bet/place` → создаём hold (резерв) на счёте источника (CASH/BONUS/WAGER).

2. При подтверждении ставки → перевод hold → debit источника, credit служебного «расчетного» счёта провайдера.

3. При отмене — release hold.

Сеттлмент (результат)

Выигрыш: debit «расчетного» счёта провайдера → credit CASH или WAGER→BONUS→CASH по политике.

Проигрыш: закрываем проводкой «расход» провайдера → без кредитов игроку.

1. Проверка KYC/AML, лимиты ответственной игры.

2. Hold на сумму вывода.

3. Успех PSP → финальная debit CASH → credit счёт «выплаты».

4. Отказ PSP → release hold.


6) Идемпотентность и exactly-once «по смыслу»

Везде `operation_id` (UUID/улучшенный ULID) с уникальным индексом. Повторный запрос → статус прошлой операции.

Вебхуки PSP/провайдера игр: Inbox-таблица с dedupe по `event_id+signature`. Обработка — идемпотентный воркер (Outbox-паттерн).

Idempotency-Key на HTTP для клиента; TTL хранить ≥ 24–72 ч.


7) Резервы и холды (holds)

Холд — не списание, а «заморозка» доступного остатка.

Правила:
  • Срок жизни холда: seconds→minutes (ставка) или часы (вывод).
  • Холд может быть частично или полностью погашен (partial settle).
  • При expire — автоматический release и событие.
  • Храните связь `hold_id` ↔ `bet_id/withdraw_id`.

8) Валюты, FX и округления

Денежные суммы — в минорных единицах (cents), тип — целое.

Округления банковские (round half to even) либо по T&C.

FX: `CASH(EUR)` ↔ `CASH(USD)` лучше разделять кошельки. Конверсию делать как отдельную операцию:
  • `debit EUR, credit FX_EURUSD` и `debit FX_EURUSD, credit USD` — прозрачно для аудита.
  • Запрещено автоматом «дотягивать» курс при споре; все правила — в политике FX.

9) Ответственная игра и лимиты

Deposit/Bet/Loss/Session лимиты (день/неделя/месяц), «cooling-off», self-exclusion.

Реализуются как pre-check перед hold/debit.

Логи отказов — в отдельный аудит-журнал, доступны саппорту и регулятору.


10) Антифрод-сигналы вокруг кошелька

Кластеры устройств/ASN, частые депозиты малой суммы → крупные выводы, отмывочные паттерны.

Velocity-лимиты на `deposit/withdraw` по BIN/стране/устройству.

Блок-листы для получателей (кошельки/ IBAN), список «мулов».

События кошелька → в feature store скоринга (логин/депозит/ставка).


11) Консистентность и производительность

Истина vs кэш

Истина — в ledger. Для API «получить баланс» — держите материализованный снэпшот (`user_id+wallet_type → balance_minor, version`).

Писать: транзакция в БД → инвалидировать кэш.

В «тяжёлых» флоу (live) уместно short-TTL 1–5 с + обязательная проверка истины перед выводом/крупной ставкой.

Скалирование

Шардирование по `user_id` (модуль/ранжирование), отдельные шард-пулы под CASH vs BONUS.

Горячие ключи (VIP/боты) — request coalescing по `user_id`.

Асинхронные агрегации (скомпонуйте `posting` → «снапшот-апдейтер» в фоне).


12) API-контракты (псевдо)

Баланс

http
GET /v1/wallets?types=CASH,BONUS
→ 200 {"wallets":[
{"type":"CASH","currency":"EUR","available":12050,"hold":500,"version":1942},  {"type":"BONUS","currency":"EUR","available":3000,"wager_req":15000}
]}

Ставка (с холдом)

http
POST /v1/bets/place
{"bet_id":"b_123","amount":500,"currency":"EUR","source_policy":"casino_default", "idempotency_key":"ik_abc"}
→ 201 {"status":"HELD","hold_id":"h_789","expires_in":30}

Сеттлмент

http
POST /v1/bets/settle
{"bet_id":"b_123","result":"WIN","payout":1250}
→ 200 {"status":"SETTLED","cash_delta":+1250}
http
POST /v1/withdrawals
{"withdraw_id":"w_456","amount":10000,"currency":"EUR","method":"sepa", "idempotency_key":"ik_def"}
→ 202 {"state":"PENDING","next_check_sec":2,"status_url":"/v1/withdrawals/w_456"}

13) Примеры проводок (double-entry)

Депозит €100 (PSP fee €1, коммис. счёт — отдельный)


Debit: PSP_Settlements(EUR)   10000
Credit: User.CASH(EUR)         10000

Debit: User.CASH(EUR)       100 (fee перекладываем)
Credit: PSP_Fees(EUR)          100

Ставка €5 из BONUS (перевод в WAGER)


Debit: User.BONUS(EUR)       500
Credit: User.WAGER(EUR)         500  (перемещение в «вэйджер»)
Debit: User.WAGER(EUR)       500
Credit: Provider.Settlement(EUR)    500  (ставка списана)

Выигрыш €12.5 → в CASH


Debit: Provider.Settlement(EUR)  1250
Credit: User.CASH(EUR)         1250

Холдовое списание (реализация через служебный счёт HOLD)


Debit: User.CASH(EUR)       500
Credit: User.HOLD(EUR)         500  (создан hold)
-- при settle
Debit: User.HOLD(EUR)       500
Credit: Provider.Settlement(EUR)   500
-- при отмене
Debit: User.HOLD(EUR)       500
Credit: User.CASH(EUR)         500

14) Аудит, неизменяемость и соответствие

WORM/immutability для журнала (объектное хранилище/архив WAL).

Метажурналы доступа: кто читал/менял лимиты, кто делал ручные корректировки (только через «adjustment-posting» с обоснованием).

GDPR/регуляторы: хранение транзакций 5–10 лет (по юрисдикции), прозрачность расчётов для игрока (история списаний/вэйджера).


15) Отказоустойчивость и DR

Multi-AZ обязательно; DR-регион для кошелька: sync-репликация в зоне, async — в регион; PITR включён.

Promote standby — только вручную по чек-листу (исключить split-brain).

Восстановление проверять еженедельно (test-restore), сверка суммы по контрольным отчётам.


16) Наблюдаемость кошелька

SLI: `deposit_success_ratio`, `withdraw_success_ratio`, `bet_hold_latency_p95`, `settlement_latency_p95`.

Тех: `ledger_postings_rate`, `db_connections_saturation`, `queue_lag_seconds`, `hold_expired_rate`.

Алерты: падение success PSP по рынку, рост `hold_expired_rate`, рассинхрон провайдера игр (нет подтверждений > N мин).


17) Тестирование и контроль качества

Контрактные тесты с PSP/игровыми провайдерами (вебхуки/подписи).

Property-based тесты денег: сумма дебетов == сумма кредитов в каждой Posting.

Fuzz/chaos: задержки PSP/провайдера, повторы вебхуков, сетевые флаппи.

Нагрузочные: burst ставок (60–120 с), soaks (4–8 ч), контроль `queue_lag` и p99.


18) Чек-лист продакшен-готовности

  • Двойная запись ledger, все операции через Posting с `operation_id`.
  • Чёткие spend-policies и порядок приоритета (персистится вместе с постингом).
  • Холды с TTL/partial settle/expiry, связь с bet/withdraw.
  • Inbox/Outbox, HMAC-вебхуки, идемпотентность на всех границах.
  • Отдельные кошельки CASH/BONUS/WAGER/FS/POINTS; разделение по валютам.
  • FX и округления в минорных единицах; конверсия — отдельной операцией.
  • Лимиты ответственной игры до hold/debit; аудит отказов.
  • Кэш для чтений (короткий TTL) + обязательная проверка истины перед критичными действиями.
  • PITR/бэкапы/DR-скрипты; ручной promote, регулярные DR-учения.
  • Дашборды/алерты SLI + технические; логи WORM и метажурналы доступа.
  • Нагрузочные/хаос-тесты; отчёты reconciliation с PSP/провайдерами.

Резюме

Архитектура multi-wallet — это не «много чисел баланса», а финансовая система с двойной записью, политиками расходования, резервацией и прозрачным следом для аудита и игроков. Держите истину в журнале, используйте холды и идемпотентность, разделяйте кошельки и валюты, автоматизируйте reconciliation и DR. Так кошелёк будет быстрым для UX, точным для денег и устойчивым под пиковые нагрузки и регуляторные проверки.

× Поиск по играм
Введите минимум 3 символа, чтобы начать поиск.