WinUpGo
Search
CASWINO
SKYSLOTS
BRAMA
TETHERPAY
777 FREE SPINS + 300%
Cryptocurrency casino Crypto Casino Torrent Gear is your all-purpose torrent search! Torrent Gear

Balance and wallets: multi-wallet architecture

1) Why multi-wallet and what goals

One "balance = number" entry does not cover the reality of iGaming. Separate wallets/subaccounts are needed: real money (cash), bonus funds, wager pool, freespins, computer points, sometimes currency wallets (EUR/USD/BRL).

The objectives of the architecture are:
  • Money accuracy (double-entry, auditability).
  • Write-off policies (for example, first bonus/vager, then cash).
  • Speed ​ ​ (p95 API ≤ 250-400 ms, bet/settlement in real time).
  • Safety and compliance (KYC/AML, responsible play limits, regulators).
  • Scale: peaks → tens of thousands of operations/sec, billions of posts/month.

2) Data model: "Ledger + Subwallets"

Minimal entities

Account: player/brand/market.

Wallet: `{type: CASHBONUSWAGERFSPOINTS, currency, status}`.
LedgerEntry (двойная запись): `debit_account`, `credit_account`, `amount`, `currency`, `operation_id`, `category`, `created_at`.
Posting: atomic business operation, combines 2 + LedgerEntry.
Hold/Reservation: temporary blocking of funds for bet/withdrawal.
Policy: write-off/credit priority rules.
FXRate: course/precision/rounding rules.
Limit: day/month/responsible game.

Example of tables (simplified)

sql
-- Balance sheet accounts for double-entry (including business)
accounts(id, owner_user_id, type, currency, status,...)

-- Posting (double entry, reference to business transaction)
ledger_entries(id, posting_id, debit_account_id, credit_account_id,        amount_minor, currency, category, operation_id, created_at)

-- Holds (reserves)
holds(id, account_id, amount_minor, currency, reason, expires_at, state,    operation_id, created_at)

-- Write-off policies (priorities)
spend_policies(id, market, wallet_priority jsonb, updated_at)

-- Cross exchange rates fx_rates (ccy_from, ccy_to, rate, precision, valid_from)

Rule: The truth lives in the transaction journal ('ledger _ entries'). The current balance is either an aggregate (materialized snapshot), or is calculated from a journal (expensive, but only true).


3) Types of wallets and their behavior

PurseFor whatCan top upCan be written offSpecial rules
CASHReal moneyPSP/manual accruals/returnsBids, purchases, withdrawalsAffects AML/KYC; transactions are recorded
BONUSBonus moneyPromo/CampaignsRates (by rules)Not directly displayed, converted to Cash when the vager is executed
WAGERAccounting for "frozen" bonusesAuto from bet bonusWrite-offs in favor of the game providerSettle/Cancel Release Rule
FS (FreeSpins)Rotation packagesCampaignsRepayment in slotsCash equivalent is fixed at T&C
POINTSLoyalty/compsActivityShop/statusesNot money; not included in AML reports

4) Write-off policies and priority order

Clearly formalize the algorithm for the source of funds: Example (slots/casinos):

1. First, write off from WAGER (if the wager is active).

2. Then from BONUS until exhausted.

3. The remainder is from CASH.

Example (sports):

1. First CASH (regulator/tax).

2. Then BONUS (freebet), translating to WAGER.

Save the "policy decision" as an attribute in Postings so that the support and audit see "why they wrote it off."


5) The life cycle of money and operations

Deposit

1. 'POST/wallet/deposit' → create a pending entry (inbox of the PSP sausage).

2. Webhook PSP (HMAC signature, idempotency by 'operation _ id') → credit CASH, category = 'DEPOSIT'.

3. We publish the 'wallet _ updated' event.

Rate

1. 'POST/bet/place' → create a hold (reserve) on the source account (CASH/BONUS/WAGER).

2. When confirming the rate, the transfer of the hold → debit source, credit of the service "settlement" account of the provider is →.

3. Upon cancellation - release hold.

Settlement (result)

Gain: debit of the "settlement" account of the provider → credit CASH or policy WAGER→BONUS→CASH.

Loss: close the provider's "expense" with a transaction → without credits to the player.

1. KYC/AML check, responsible play limits.

2. Hold on the withdrawal amount.

3. The success of the PSP → the final debit CASH → credit account "payment."

4. PSP → release hold failed.


6) Idempotence and exactly-once "within meaning"

Everywhere'operation _ id '(UUID/enhanced ULID) with a unique index. Re-request → status of past transaction.

PSP/game provider webhooks: Inbox table with dedupe by 'event _ id + signature'. Processing - idempotent worker (Outbox pattern).

Idempotency-Key on HTTP for the client; Store TTL ≥ 24-72 hours.


7) Reserves and holds

Hold is not a write-off, but a "freeze" of the available balance.

Rules:
  • Hold life: seconds→minutes (rate) or hours (output).
  • The hold can be partially or completely extinguished (partial settle).
  • When expire - automatic release and event.
  • Keep the 'hold _ id' ↔ 'bet _ id/withdraw _ id' relationship.

8) Currencies, FX and rounding

Monetary amounts - in minor units (cents), type - integer.

Bank rounding (round half to even) or by T & C.

FX: 'CASH (EUR)' ↔ 'CASH (USD)' it is better to divide wallets. Convert as a separate operation:
  • 'debit EUR, credit FX_EURUSD' and'debit FX_EURUSD, credit USD '- transparent to audit.
  • It is forbidden to automatically "reach" the course in a dispute; all rules are in FX policy.

9) Responsible play and limits

Deposit/Bet/Loss/Session limits (day/week/month), cooling-off, self-exclusion.

Implemented as pre-check before hold/debit.

Failure logs - in a separate audit log, available to the support and regulator.


10) Anti-fraud signals around the wallet

Device clusters/ASNs, frequent small deposits → large withdrawals, washing patterns.

Velocity limits on 'deposit/within' by BIN/country/device.

Block lists for recipients (wallets/IBAN), list of "mules."

Wallet events → in the scoring feature store (login/deposit/rate).


11) Consistency and performance

True vs cache

The truth is in the ledger. For the "get balance" API, keep the materialized snapshot ('user _ id + wallet _ type → balance_minor, version').

Write: a transaction in the database → invalidate the cache.

In "heavy" flow (live), short-TTL 1-5 s + mandatory truth check before withdrawal/large bet is appropriate.

Scalding

Sharding by 'user _ id' (module/ranking), separate shard pools for CASH vs BONUS.

Hot keys (VIP/bots) - request coalescing by 'user _ id'.

Asynchronous aggregations (compose 'posting' → "snapshot-update" in the background).


12) API contracts (pseudo)

Balance

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}
]}

Bet (with hold)

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}

Settlement

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) Examples of postings (double-entry)

Deposit €100 (PSP fee €1, commis. account - separate)


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

Debit: User. CASH (EUR) 100 (fee shift)
Credit: PSP_Fees(EUR)          100

Bet €5 from BONUS (transfer to WAGER)


Debit: User. BONUS(EUR)       500
Credit: User. WAGER (EUR) 500 (move to wager)
Debit: User. WAGER(EUR)       500
Credit: Provider. Settlement (EUR) 500 (rate written off)

Win €12. 5 → in CASH


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

Hold write-off (realization via HOLD service account)


Debit: User. CASH(EUR)       500
Credit: User. HOLD (EUR) 500 (created by hold)
-- at settle
Debit: User. HOLD(EUR)       500
Credit: Provider. Settlement(EUR)   500
-- on cancellation
Debit: User. HOLD(EUR)       500
Credit: User. CASH(EUR)         500

14) Audit, immutability and compliance

WORM/immunity for log (object storage/WAL archive).

Access meta-logs: who read/changed the limits, who made manual adjustments (only through "adjustment-posting" with justification).

GDPR/regulators: storage of transactions for 5-10 years (by jurisdiction), transparency of settlements for the player (history of write-offs/wager).


15) Fault tolerance and DR

Multi-AZ mandatory; DR-region for wallet: sync replication in the zone, async - to the region; PITR is enabled.

Promote standby - only manually by checklist (exclude split-brain).

Restore check weekly (test-restore), reconciliation of the amount of control reports.


16) Wallet observability

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`.

Alerts: PSP success drop in the market, 'hold _ expired _ rate' growth, game provider out of sync (no confirmations> N min).


17) Testing and quality control

Contract tests with PSP/game providers (webhooks/signatures).

Property-based tests of money: sum of debits = = sum of credits in each Posting.

Fuzz/chaos: PSP/provider delays, webhook repeats, network flappies.

Load: burst bets (60-120 s), soaks (4-8 h), control 'queue _ lag' and p99.


18) Production readiness checklist

  • Double ledger entry, all operations via Posting with 'operation _ id'.
  • Clear spend-policies and priority order (persists with posting).
  • Holds with TTL/partial settle/expiry, communication with bet/withdraw.
  • Inbox/Outbox, HMAC webhooks, idempotency at all borders.
  • Individual CASH/BONUS/WAGER/FS/POINTS wallets; split by currencies.
  • FX and minor rounding; conversion - a separate operation.
  • Responsible play limits to hold/debit; failure audit.
  • Read cache (short TTL) + required truth check before critical actions.
  • PITR/backups/DR scripts; manual promote, regular DR exercises.
  • Dashboards/alerts SLI + technical; WORM logs and access logs.
  • Load/chaos tests; reconciliation reports with PSP/providers.

Resume Summary

The multi-wallet architecture is not "many balance numbers," but a financial system with a double entry, spending policies, reservation and a transparent trail for auditing and players. Keep the truth in the log, use holds and idempotence, separate wallets and currencies, automate reconciliation and DR. This way the wallet will be fast for UX, accurate for money and resistant to peak loads and regulatory checks.

× Search by games
Enter at least 3 characters to start the search.