Skip to content
PokerEnginePro
Ledger & wallets

Every chip, counted.
Twice, by construction.

Double-entry, idempotent and reconciled every night, with multi-balance wallets and a social casino built in. Every movement leaves one account and reaches another, every command happens once, and the books are checked every night.

11.3M

ledger entries reconciled in 28 s

about 990,000 accounts, no drift

8

round trips to settle a hand

plus the commit, whatever the table size — down from 39 for a six-handed hand

11 ms

to publish 500 hand events

as one batch to the broker, against 7,687 ms one at a time

0

chip-conservation violations

every hand, every run — checked after every state transition

The books

Double-entry, exactly once.
A retry never pays twice.

Money is an integer number of minor units with its currency — never a float, never a guess. Every entry names where the money came from and where it went, so the books balance by construction.

01

Double-entry, to the chip

Every chip movement is a balanced ledger entry; money is always integer minor units with its currency.

02

Exactly once

Every command is idempotent and every debit is overdraft-proof, so a retry never pays twice.

03

Play money and real money never meet

Real money, free play chips and purchased play chips live on one ledger as different currencies, so a play chip can never become a real one.

Every command, once

  1. 01

    A key with every command

    The table, the gateway or the back office sends each command with an idempotency key.

  2. 02

    The key is claimed

    The key is inserted under a unique index. If it is already there, the first answer stands and nothing moves again.

  3. 03

    Debits that cannot overdraw

    A debit is a conditional update that never takes a balance below zero — however many spends race for it.

  4. 04

    Written whole, or not at all

    The entries and the new balances are written and committed in the command's one transaction.

LedgerEntry · the accounting model
/// <summary>
/// One movement of money, append-only. The amount leaves <see cref="DebitAccountId"/> and arrives at
/// <see cref="CreditAccountId"/>; both sides are always recorded, so every entry balances by construction.
/// </summary>
public sealed class LedgerEntry
{
    /// <summary>Unique per tenant: a repeated call with the same key is a no-op, not a second movement.</summary>
    public string IdempotencyKey { get; set; } = string.Empty;

    public LedgerEntryType Type { get; set; }

    public string Currency { get; set; } = string.Empty;

    /// <summary>Where the money came from.</summary>
    public long DebitAccountId { get; set; }

    /// <summary>Where the money went.</summary>
    public long CreditAccountId { get; set; }

    /// <summary>Always positive, in the currency's minor units.</summary>
    public long Amount { get; set; }
    // …
The ledger entry, excerpted from the platform's accounting model.

Settlement

Settled in one transaction.
In eight round trips.

A hand settles in one transaction, in a fixed eight database round trips — not forty.

Settlement is the step every table waits on between hands. Done the obvious way — a guarded update per account per movement — it costs a round trip to the database for every chip that moves, and the wait grows with the table.

Ours locks every stack and escrow at the table in a fixed order, checks in code that every loser has the chips they lost, and writes everything in one save. A short loser refuses the whole settlement and nothing is kept. Because buy-ins and cash-outs lock in the same order, a rebuy and a settlement at the same table queue — they never deadlock.

8

round trips to settle a hand

0

chip-conservation violations

A hand's money, from buy-in to cash-outA buy-in moves chips from the player's wallet, most restricted balance first, into a table escrow account, one per seat. At settlement, in one transaction, the losers pay from their escrow into the hand's own pot account, the winners are paid from the pot back to their escrow, the rake goes to one of sixteen house rake shards, and the hand's events are written to the outbox, which publishes them to Kafka at least once. The pot ends at zero. A cash-out returns each part of the escrow to the balance it came from. Every night the reconciliation checks that every pot is at zero, every stack matches its escrow and the books sum to zero.Player walletmost restricted firstone transactionTable escrowone account per seatHand potnets to zeroHouse rake1 of 16 shardsOutboxsame transactionBuyInCashOut · to sourcelosers pay inwinners paidrakeKafkaat least oncepublishNightly reconciliationpots at zero · stacks = escrowbooks sum to zerosolid: a balanced ledger entrydashed: events, checks
After the ledger’s own design: one transaction per settled hand.

The eight round trips, whatever the table size

  1. 01

    Claim the key

    Insert the hand's idempotency key — a repeated settlement is answered Duplicate, and nothing moves twice.

  2. 02

    Lock in order

    Lock every seat's stack, then every seat's escrow, in player order — the order buy-ins and cash-outs use.

  3. 03

    Read the stacks

    One query for every seat's stack at the table.

  4. 04

    Read the accounts

    One query for the escrow, pot and rake-shard accounts.

  5. 05

    Create what is new

    The hand's pot account — rarely a winner's escrow or a rake shard.

  6. 06

    Mark the hand

    Mark the hand settled without reading it first.

  7. 07

    Write once

    One save: every ledger entry, every stack and escrow balance.

  8. 08

    Rake last

    Add the rake to the house's rake shard atomically, last — the one row other tables share is held only until the commit.

Per hand

Every hand balances on its own

Each hand gets its own pot account: losers pay in, winners and the rake are paid out, and it ends at zero — the check an auditor makes.

Per hand

House accounts that never queue

Each house account is sixteen rows, so busy tables never wait on one another to pay the rake — and still one account in the books.

Per hand

Rake per player

Each hand's rake is split over the seats that paid into the pot and recorded per player; the shares add up to what the ledger took.

Wallets

One wallet, many balances.
In the right order.

Cash, bonus, free and purchased play money, and tournament tickets — spent most-restricted first, cashed out to source.
  • Chips at a table sit in an escrow account of their own; a cash-out returns each part to the balance it was bought from.
  • Entries, rebuys and add-ons are paid before they count, once per key; prizes are paid in one transaction that must empty the pool.
  • Satellites pay tickets — a wallet asset with an expiry — into the target event.
A buy-in spends, in order

Real money

  1. 1Bonus

    locked until wagering releases it

  2. 2Cash

    withdrawable

Play money

  1. 1Free chips

    daily chips, rewarded ads, grants

  2. 2Purchased chips

    bought in the chip store

Tickets

  1. 1Ticket

    its target event only, once

A cash-out returns each part of a stack to the balance it was bought from — split by largest remainder, so not a chip is lost to rounding.

Checked every night

Reconciled, published, never lost.

The balances are a convenience; the entries are the truth. Every night one server re-derives the books from them — and anything that could not settle waits in plain sight until someone settles it.

The nightly reconciliation

  1. 1

    Starts from the last run's checkpoints and reads only the entries written since.

  2. 2

    Every wallet, escrow and house account: checkpoint plus new entries must equal the stored balance.

  3. 3

    Every pot created since the last run nets to zero.

  4. 4

    The books sum to zero, and every table stack matches its escrow.

  5. 5

    Anything off is confirmed from scratch, from every entry the account ever had, and shown on the back office's Ledger page.

11.3M

ledger entries reconciled in 28 s

about 990,000 accounts, no drift

Reconciled every night

Incremental nightly reconciliation with a record of every run: 11.3 million entries across 990,000 accounts in 28 seconds, no drift.

The archive waits for the books

A month of history leaves the live database only after a clean reconciliation that started after the month ended.

The outbox, not a hope

Hand events are written in the hand's own transaction and published to Kafka at least once.

Nothing lost, nothing hidden

Anything that cannot settle goes to a dead-letter queue to be retried or, with a second approver, dismissed.

Social casino

A social casino, built in.
Play money that behaves like money.

A chip store, a seven-day daily-chip ladder, daily missions, a bankrupt top-up and rewarded ads with a daily cap.

01

A chip store that survives a crash

Entitlement checked, attempt recorded, provider charged, then chips credited — a crash in between leaves a recoverable row, never an unexplained payment.

02

Daily chips and missions

Daily chips on a seven-day ladder, three daily missions and a once-a-day bankrupt top-up — each claimed once, with no counter to drift.

03

Rewarded ads

Rewarded views pay play chips only, up to a daily cap, and only for impressions the ad provider confirms it served.

04

The store follows the market

Switches in the back office turn the store, rewards and ads on or off; the player client offers only what the server says it may.

Grant play chips

Batch grants with per-player results, a ceiling staff can tune, and an audit row per batch.

The back office

Play money and real money

Play money. Real money.
One ledger, never mixed.

Play money runs in every market that is not closed; real money only in the markets an operator assigns a real-money rule pack to, in EUR, GBP, USD and CAD and, in the African packs, NGN, KES and GHS.

Payments arrive and leave through the house's payment-gateway account, so a deposit is just another balanced entry — reconciled every night like everything else, with play money kept apart as a currency of its own.

Deposits and withdrawals

Cards, e-wallets, prepaid and pay by bank through the providers' hosted pages and fields, so card data never touches the platform; withdrawals go back the way the money came, and large ones need a second approver.

Stablecoin deposits and withdrawals

USDT and USDC on Ethereum and USDT on Tron, through institutional custody and crypto processing, in the markets that allow crypto.

In-app purchases

Apple and Google purchases in the mobile app are verified on the server — Apple's signed transactions against Apple's certificate chain, Google's through the Play API — and credited once, to the account that started them. Store refunds and chargebacks take the chips back.

Crypto

Crypto, in stablecoins.
Screened, final, kept in fiat.

USDT and USDC on Ethereum and USDT on Tron, through institutional custody and crypto processing, in the markets that allow crypto.

A player withdraws in the asset, and on the network, they deposited with. Every address is screened, every deposit is converted and recorded as it is credited, and the tables only ever see the operator's own currency.

Assets and networks

  • USDT logoEthereum logoUSDT on EthereumERC-20 · 12 confirmations
  • USDC logoEthereum logoUSDC on EthereumERC-20 · 12 confirmations
  • USDT logoTron logoUSDT on TronTRC-20 · 20 confirmations

Market by market

Crypto is a rule of each market's pack: on in Curaçao, allowed in Malta but off until the operator turns it on, and never in Great Britain, the US states or Ontario.

  • CuraçaoCuraçaoOn
  • MaltaMaltaOff by default
  • Great BritainGreat BritainNever
  • US statesUS statesNever
  • OntarioOntarioNever

The controls

  • Every address screened

    Every confirmed deposit and every withdrawal address is screened on chain: high risk holds the money and raises an AML alert, severe needs a second approver, and a screening that cannot be made is never read as no risk.

  • Final before it counts

    A deposit is credited after 12 confirmations on Ethereum and 20 on Tron.

  • Addresses checked

    Withdrawal addresses are checked by EIP-55 on Ethereum — an address typed in one case confirmed by the player in its checksum form — and Base58Check on Tron, the platform's own addresses are refused, and every address is stored encrypted.

  • Closed loop

    A player withdraws only in an asset, and on a network, they have deposited with — and no more than they have deposited there, net.

  • One flat network fee

    The player pays a flat fee per network, shown in the quote; the operator absorbs the real cost.

  • The ledger stays in fiat

    Crypto is converted as it arrives, with the rate, its source and the time recorded and the amount rounded down — so the books never hold a coin.

  • Held for a person, never lost

    A deposit in the wrong asset, to an address never issued, that cannot be attributed, too small, from a market without crypto, refused by the identity or safer-gambling checks, or high risk waits for a person to decide. Money on chain never expires.

Follow a hand's money.
From the buy-in to the books.

A live walkthrough of the ledger, the wallets and the nightly reconciliation — with the measurements behind every number on this page.