Freelance · white-label iGaming platform
Money flows that stay honest when settlement is asynchronous.
A client that builds white-label casino products hired me as lead full-stack developer to deliver a working demo of their platform. The hard part was how value got in and out. The main funding method depended on an external service and on a player finishing a hand-off that might never happen.
- Lead full-stack developer
- 2025
- Deployed client demo
What I owned
- Deposit and withdrawal flows
- Ledger and refund rules
- Real-time status over WebSockets
- Multi-currency cashier
- Authentication and currency migration
Context
A demo with the whole stack in scope.
The client builds white-label casino products for operators and needed a deployable demo to show them. I led the full-stack work: the SolidJS interface, Node and Express services, the MySQL data model, real-time events, authentication and every transaction flow. The engagement ended when the demo was delivered and running, so this page describes what was built and how, not how it fared under production traffic.
Part of the brief was a migration. The platform had grown up around a third-party game economy and its item trading. I moved it to a first-party token currency with credential-based authentication and retired the legacy payment and trading subsystems that depended on the old model, which left a single ledger behind every balance change.
The problem
A deposit that could not finish inside one request.
For the platform’s primary non-crypto funding method, a player had to meet an automated in-game agent and complete the hand-off there. A single deposit therefore crossed three things: our database, an external HTTP service that controlled the agent, and a human who might take a minute or walk away. The original design leaned on webhooks and long-held requests, which meant guessing at timeouts and leaving the interface unsure what had happened.
I restructured it as two phases. The API acknowledges the request immediately and records it as pending, so the player sees an honest state straight away. Settlement then runs asynchronously against the external service. When it resolves, the ledger is updated and the outcome is pushed to the client over a WebSocket. The cashier updates without polling, and nothing holds a connection open for the length of a human decision.
- 01Player requests a deposit
- 02API records it as pending and acknowledges
- 03Settlement runs against the external service
- 04Ledger is updated in a transaction
- 05Client receives the outcome over WebSocket
Money semantics
Deposits and withdrawals needed different rules.
A deposit credits the player’s balance only after external confirmation; until then the ledger does not change. A withdrawal debits optimistically inside a database transaction, because the player must not be able to spend the same balance twice while settlement is in flight. If settlement then fails in a way the system can classify, a compensating entry refunds the balance. The refund is a new ledger row, not an edit, so the history shows exactly what happened.
Failures the system could not classify stayed pending rather than being refunded, since refunding value that may already have transferred is the worse mistake. Those cases are meant for a person to resolve. Before any request reaches settlement it passes authentication, validation, balance checks and a per-user concurrency guard, so two simultaneous withdrawals cannot both pass the same balance check.
Product
One cashier across currencies.
The visible product was the cashier. It converts amounts between the platform token and several currencies with denomination-specific precision, shows fees and minimums before a player commits, handles QR and address flows for crypto deposits, lets a player cancel a withdrawal while it is still pending, and links settled transfers to their explorers. The transaction history is paginated with its filters kept in the URL, so a support conversation can share an exact view.
The server stays authoritative for rates and limits. The client submits the token amount and the backend recomputes the transfer at its current rate, so the conversion a player saw on a stale screen never sets the price.
Before production
What I would harden before real money at scale.
A demo is allowed to make choices a production system is not. These are the ones I flagged to the client at hand-over.
- Make in-flight settlement state durable, so it survives a restart and works across more than one server instance.
- Add idempotency keys to settlement calls, and a formal reconciliation queue for the pending cases that need a person.
- Put automated integration tests around the ledger invariants and every compensation path.
- Commission an independent security review before the platform handles production funds.
Stack
SolidJS · Node.js · Express · Socket.IO · MySQL · REST · WebSockets