# UltraGames — Backend & Provider Integration Guide

This is a **front-end prototype**. All data is mock/simulated behind clearly named seams.
Everything below tells your AI harness exactly where to swap mock logic for real API/socket calls.

## Files
- `UltraGames-Desktop.dc.html` — desktop app (single Design Component)
- `UltraGames.dc.html` — mobile app (single Design Component)

Each file has **one `class Component`** with the logic. UI reads values from `renderVals()`.
The **same seam names exist in both files** — wire both. State that must survive reload is
persisted to `localStorage` under the key **`ultragames_state`** (see `_persistKeys`).

---

## 1. Config — add this block first
There is no central config yet. Create one object at the top of each `renderVals()` (or a shared
`config.js` imported by both) and replace the hard-coded values it feeds:

```js
const CONFIG = {
  apiBase:     'https://api.yourbackend.com',   // REST base
  wsUrl:       'wss://socket.yourbackend.com',  // live wins + chat
  gameLaunch:  'https://games.yourbackend.com', // provider aggregator launch endpoint
  sportsbook:  'https://odds.yourbackend.com',  // odds feed / bet placement
  authTokenKey:'ug_token',                      // where you store the session JWT
};
```

---

## 2. Auth / session
**Where:** `doRegister`, `doLogin` in `renderVals()`; state `loggedIn`, `pname`, `pemail`.
- `doLogin` currently sets `loggedIn:true` locally. Replace with `POST {apiBase}/auth/login`,
  store the returned token at `CONFIG.authTokenKey`, then set `loggedIn`, `pname`, `pemail` from the response.
- `doRegister` validates (username ≥3, valid email, password ≥6, 18+ checkbox) then locally
  credits a $100 signup bonus. Replace the local credit with `POST {apiBase}/auth/register`;
  apply the real bonus from the server response to `bal`.
- **Logout:** search `loggedIn:false` (the menu "Log out" handler) — clear the token there too.
- On app load, `componentDidMount` should validate an existing token and hydrate the session.

## 3. Balance / wallet (single source of truth)
**Where:** state `bal`; methods `bump(delta, extra)`, `persist(patch)`, `fmtBal()`; saved by `_savePersist()`.
- `bal` is the one balance every action reads/writes. Replace `bump()` with an optimistic update
  that also calls `POST {apiBase}/wallet/adjust` (or refetch `GET {apiBase}/wallet/balance`).
- **Deposit:** `doDeposit` — wire to your PSP; credit on confirmed webhook, not on click.
- **Withdraw:** `doWithdraw` (validation: min $20, ≤ balance, address length ≥20) — wire to
  `POST {apiBase}/wallet/withdraw`. Multi-currency data is `COINMETA` / `coinBalances`.
- **Swap / Vault / Tip:** `swapDo`, `vaultDeposit`, `vaultWithdraw`, `tipSend` — each has a clear handler.
- **Deposit address/QR:** `ADDRS`, `depCoin`, `depNet`, `networks` — replace static addresses with
  a per-request address from `POST {apiBase}/wallet/deposit-address`.
- **Transactions:** `txs` array (mock). Replace with `GET {apiBase}/wallet/transactions`.
  Statuses supported by the UI: Completed, Pending, Failed, Expired, Credited.

## 4. Game catalog + launch (provider aggregator)
**Where:** `CATALOG` (game list), `mkGame`, `row()`; launch handlers `playReal`, `playDemo`;
screen `game-launch`; the `<iframe src="{{ gameUrl }}">`.
- Replace `CATALOG` with `GET {apiBase}/games` (fields used: name `n`, provider `p`, image index `i`, category `c`).
- `gameUrl` is `'about:blank'`. Set it to the provider's launch URL:
  `GET {gameLaunch}/launch?game=<id>&mode=<real|demo>&token=<jwt>` and put the returned URL into `gameUrl`.
- `playReal` / `playDemo` set `gameMode` to `'real'` / `'demo'` — pass that mode to the launch call.
- **In-house bet demo:** `doSpin()` fakes an outcome and moves `bal` (real) or `demoBal` (demo).
  For real provider games the iframe owns outcomes; bind the provider's postMessage/webhook to update `bal`.

## 5. Sportsbook
**Where:** `MATCHES` (fixtures/odds), `mMatches`/`matches`, `slip` (bet slip), `placeBet`,
`sbMode` (real/demo), `slipMode` (single/parlay), `totalOddsNum`, `payoutNum`.
- Replace `MATCHES` with a live odds feed: `GET {sportsbook}/events` (or subscribe over WS for in-play).
  Fields used per match: `league`, `home`, `away`, `time`, `live`, `o` (array of `[label, decimalOdds]`).
- `placeBet` computes settle locally. Replace with `POST {sportsbook}/bets` `{selections, stake, mode}`;
  reflect accepted/rejected + settled result back into `bal` (real) or `sbDemoBal` (demo).
- Odds can update live — push new odds into `MATCHES` from the socket to re-render the slip.

## 6. Live wins feed + chat (WebSocket)
**Where:** `_startLiveFeed()`, `_pushWin()`, state `liveFeed` (ticker) and `chatMsgs` (chat).
- `_startLiveFeed` uses a `setInterval` **placeholder**. There is a marked comment:
  `/* swap for a real WebSocket: ws.onmessage = e => this._pushWin(JSON.parse(e.data)) */`
- Open `new WebSocket(CONFIG.wsUrl)` in `componentDidMount`; on message call `_pushWin(payload)`
  with `{user, game, gi (image index), amt, ts}`. Close it in `componentWillUnmount` (already clears the interval).
- **Chat send:** `sendChatMsg()` appends locally — also emit the message over the socket.

## 7. Bonuses / rewards
**Where:** `rewards` / `rwDef` (rakeback, daily, weekly, level-up), `claimAll`, per-item `onClaim`,
promo redeem `redeemPromo` (currently only `ULTRA100` works).
- Replace claim handlers with `POST {apiBase}/rewards/claim`; credit returned amount via `bump()`.
- `redeemPromo` → `POST {apiBase}/promo/redeem`; apply server-validated bonus + wagering requirement.

## 8. KYC / verification
**Where:** `kycTiers`, `pickFile()` (opens device file/photo picker), `docUploads`, `uploads` state.
- `pickFile` stores file name/size locally. Replace with a real upload to
  `POST {apiBase}/kyc/documents` (multipart) and reflect review status from the server.
- Tiers: email/phone, identity doc, proof of address, source of funds.

## 9. Responsible gaming
**Where:** `limits` (deposit/loss/wager inputs), `saveLimits`, `openCooloff`/`openExclude` (duration picker), `rgLimits` state.
- Wire `saveLimits` and the cool-off/self-exclusion confirm to `POST {apiBase}/rg/limits` — these must be enforced server-side.

## 10. Profile / security
**Where:** profile fields `pname`/`pemail`/`pphone` + `saveProfile`; security screen `loginHistory`,
`sessionTimer`, `toggle2fa` (2FA-on-withdrawal), `logoutAll`; change-password / 2FA / sessions modals.
- Replace `loginHistory` (mock) with `GET {apiBase}/account/sessions`; wire `logoutAll` to revoke tokens.
- Enforce the 2FA-on-withdrawal flag server-side; the UI toggle is `twofaWd` in state.

---

## Integration checklist
- [ ] Add `CONFIG`; store/read session token
- [ ] `auth/register`, `auth/login`, logout, token hydrate on load
- [ ] `wallet/balance` + `bump()` → server; deposit webhook, withdraw endpoint
- [ ] `GET /games` → `CATALOG`; provider launch URL → `gameUrl`; outcome callback → `bal`
- [ ] Odds feed → `MATCHES`; `POST /bets` → `placeBet` settle
- [ ] WebSocket → `_pushWin` (ticker + chat); chat send emits
- [ ] `rewards/claim`, `promo/redeem`
- [ ] `kyc/documents` upload; `rg/limits`; `account/sessions`
- [ ] Do all of the above in **both** `UltraGames-Desktop.dc.html` and `UltraGames.dc.html`

## Notes for the harness
- Both apps are single self-contained `.dc.html` files; logic lives in `class Component`, UI in the template. `renderVals()` returns every value/handler the template binds to — that is your integration surface.
- Persisted keys (localStorage `ultragames_state`): see `_persistKeys()`. Keep server state authoritative; treat localStorage as cache.
- No build step or framework beyond the DC runtime (`support.js`). Icons are Phosphor; fonts are Afacad / Chakra Petch / Montserrat.
- Mock arrays to replace: `CATALOG`, `MATCHES`, `txs`, `loginHistory`, `promos`, `rewards`/`rwDef`, `COINMETA`, live-feed seed in `_pushWin`.
