Platform adapter
One interface — PlatformAdapter — covers everything
upstream of the RGS: session lifecycle, money movement, free-round
promo free-rounds, and platform events. How it talks to the operator (one
WS, three microservices, REST + polling) is the integrator's call.
Interface
interface PlatformAdapter {
connect(): Promise<void>;
disconnect(): void;
readonly isHealthy: boolean;
readonly diagnostics: Record<string, unknown>;
openSession(sessionId, connectionId): Promise<SessionInfo>;
settleSimple(req): Promise<RoundReceipt>; // simple round = 1 RPC
openComplex(req): Promise<RoundReceipt>; // complex = 2 RPCs
updateComplex?(req): Promise<void>; // optional audit, no money
closeComplex(req): Promise<RoundReceipt>;
onEvent(handler: (e: PlatformEvent) => void): void;
} Money flow
| Round shape | Wallet calls | Where |
|---|---|---|
| simple (slot spin) | settleSimple(bet, win) | once per SPIN_REQUEST |
| complex (Mines, Road) | openComplex(bet) | at OPEN_REQUEST |
| complex (Mines, Road) | closeComplex(win) | at CLOSE_REQUEST |
| complex — STEP | none | STEP is pure in-process |
Two transactions per round, no exceptions. Mid-round
step calls never touch the wallet. If you need an
audit trail for in-flight state, implement the optional
updateComplex — the orchestrator calls it
fire-and-forget after each step; failures are logged, never
surfaced to the player.
SessionInfo
{
sessionId, currency,
currencyDecimals, // 2 = EUR/USD, 0 = JPY, 8 = BTC. Adapter sources it.
balance, // integer minor units (× 10^currencyDecimals)
allowedBets: number[], // integer minor units
defaultBetIndex,
promo?: PromoFreeRounds,
openRound?: OpenRoundResume, // round in flight from a prior connection
carry?: string, // math's cross-round opaque blob (you stored it)
nextMode?: string, // math's hint, you stored it
mathVersion?: string, // version that produced carry — discard on mismatch
}
The adapter is the source of truth for cross-round state.
RGS stores nothing durable: it asks openSession for
carry / nextMode / mathVersion
and threads them into the next round's math.play or
math.open.
Settle requests
SettleSimple = {
sessionId, bet, betIndex, priceMultiplier, win, multiplier, type,
roundState, // this round's final math state, also the carry
nextMode?, mathVersion?, promoId?, idempotencyKey?,
}
OpenComplex = {
sessionId, bet, betIndex, priceMultiplier,
initialState, // math's opening state blob
mathVersion?, promoId?, idempotencyKey?,
}
CloseComplex = {
sessionId, roundId,
finalState, // THIS round's final math state
carry?, // NEXT round's seed — adapter stores for return on openSession
nextMode?, mathVersion?,
win, multiplier, type, idempotencyKey?,
}
RoundReceipt = { roundId, balance, promo?: { remaining } } Event stream
The adapter pushes platform-originating events into the
orchestrator via the handler installed by onEvent.
type PlatformEvent =
| { type: "balanceChanged", sessionId, balance, reason }
| { type: "sessionClosed", sessionId, reason }
| { type: "promoGranted", sessionId, promo }
| { type: "autocloseRequested", sessionId, roundId?, reason }; autocloseRequested is the wallet's way to tell RGS
to settle an in-flight complex round (e.g. session-end policy,
compliance trigger). RGS-side autoclose is never timer-driven —
always external.
Numerics & idempotency
All currency amounts are integers in the currency's
minimal unit. The unit is scaled by
SessionInfo.currencyDecimals: USD/EUR 1.00 → 100 when
decimals = 2, BTC 0.00000001 → 1 when decimals = 8, JPY 100 →
100 when decimals = 0. Adapters facing platforms that expect
decimal strings or floats convert at the boundary with
toWireAmount / fromWireAmount from
@open-rgs/adapter-kit — pick an explicit
RoundingMode (default half_even,
banker's rounding).
Every state-changing wallet RPC carries an
idempotencyKey (default: uuid-v4, 5 min TTL). Forward
it to the wallet if upstream supports dedupe; otherwise ignore it.
Configure via createServer({ idempotency }).
Authoring resources
@open-rgs/adapter-kit— helpers for WS / HTTP RPC, error mapping, diagnostics@open-rgs/adapter-test-kit— conformance suite (run live or fixtures)@open-rgs/platform-mock— in-memory dev/test wallet with promo + autoclose helpers- specs/12 — adapter cookbook