Documentation Index
Fetch the complete documentation index at: https://hedgeem-api.qeetoto.com/llms.txt
Use this file to discover all available pages before exploring further.
F102 — Two-Balance Wallet System
| |
|---|
| Phase | 5 — Platform |
| Jira | HEDGE-187 |
| Status | TypeScript ✅ · UMA ⬜ · V7 ⬜ |
Business Rule
Every registered player holds two separate balances:
| Balance | Location | Description |
|---|
| Account balance | wallets.balance (Supabase) | Money held by the platform. Shown in the lobby header and cashier page. Persists across sessions. |
| Seat balance | game_table_state.seat_balance | Chips in front of the player at a specific table. Exists only while seated. |
Flow:
- Player sits at a table → buy-in amount deducted from account, credited as seat chips
- Player tops up during a session → amount deducted from account, added to seat chips
- Player presses Back to Lobby → all remaining seat chips automatically credited back to account
- If player loses all chips mid-session → can top up from account without leaving the table
Welcome balance: New players receive a £1,000 welcome balance on first login (Google OAuth).
Technical Design
Database
-- Account balance — persists across sessions
public.wallets.balance bigint -- pence, non-negative
public.wallets.welcome_balance_granted boolean -- prevents double-crediting
-- Seat balance — per (table, player) while in a game
public.game_table_state.seat_balance bigint -- pence, non-negative
API endpoints
| Endpoint | Effect on balances |
|---|
GET /api/players/:playerId | Returns accountBalance from wallets.balance. Auto-creates wallet with £1,000 on first login. |
POST /api/tables/:id/sit | Deducts buyInAmount from wallet. Sets seat_balance. Returns NACK if wallet insufficient. |
POST /api/tables/:id/topup | Deducts amount from wallet. Adds to seat_balance. Returns NACK if wallet insufficient. Response always includes newAccountBalance. |
POST /api/tables/:id/leave | Credits seat_balance → wallet. Resets game state to STATUS_START. Idempotent — safe if seat is already empty. |
Client integration (game-shell.html)
The compliance bar’s Lobby button is intercepted:
click → POST /api/tables/:tableId/leave (auth'd only)
→ update localStorage session.balance = newAccountBalance * 100
→ navigate to /lobby.html
The tableId is extracted from the game iframe URL (?tableId=N). If the player is anonymous or no tableId is present, navigation proceeds immediately without calling leave.
localStorage session shape
{
"playerId": "uuid",
"displayName": "Simon",
"balance": 100000,
"access_token": "...",
"role": "BASIC_USER"
}
balance is stored in pence (integer). £1,000 = 100000. Updated after leave and after fetchPlayerProfile().
Acceptance Criteria
| # | Criterion | Test |
|---|
| AC1 | After OAuth login, lobby header shows account balance from server | GET /api/players/:id returns accountBalance: 1000.00 for new user |
| AC2 | Sitting at a table deducts buy-in from account balance | wallets.balance reduced by buyInAmount * 100 after /sit |
| AC3 | Sitting with more than available balance returns NACK | /sit with buyInAmount > wallet → { acknowledgement: "NACK" } |
| AC4 | Pressing Lobby button calls leave before navigating | game-shell.html network log shows POST /leave |
| AC5 | Account balance updated in localStorage after leave | localStorage.hedgeem_session.balance reflects newAccountBalance * 100 |
| AC6 | Lobby header balance refreshes after return from game | renderHeader() reads updated session on load |
| AC7 | Top-up deducts from account and adds to seat | wallets.balance -= amount; seat_balance += amount |
| AC8 | Top-up with insufficient wallet returns NACK | /topup with amount > wallet → { acknowledgement: "NACK" } |
| AC9 | New player receives £1,000 welcome balance | First GET /api/players/:id → accountBalance: 1000.00 |
| AC10 | Leave with empty seat returns creditsReturned: 0 | /leave when seat_balance = 0 → { creditsReturned: 0 } |
Version Parity
| Version | Status | Notes |
|---|
| TypeScript (v6) | ✅ | Full implementation: server endpoints + game-shell leave hook (HEDGE-187) |
| JavaScript (v4) | N/A | No server integration; standalone client only |
| UMA (v5) | ⬜ | Not implemented |
| V7 (Horse Racing) | ⬜ | Not implemented |
POST /api/tables/{tableId}/sit — buy in to a table
POST /api/tables/{tableId}/leave — cash out chips back to wallet
POST /api/tables/{tableId}/topup — top up chips during a session
GET /api/players/{playerId} — read account balance
- F016 — Credits wallet — in-game chip balance display
- HEDGE-187 · HEDGE-190 (lobby / cashier page)