SP slotplate
How-to

Swap the network transport

Replace the mock with your RGS client in one file.

slotplate ships with MockNetworkManager (random grids, 300ms latency). Real games talk to an RGS over WebSocket or HTTPS.

The interface

export interface NetworkManager {
  spin(req: SpinRequest): Promise<SpinResponse>;
}

That's it. Write your own class, register it in composition.ts:

container.register<NetworkManager>(
  'network',
  () => new RgsNetworkManager(config.rgsUrl, config.sessionToken),
);

Nothing else in the codebase knows about the transport. Phases call network.spin(...); the return type is the same. No other change needed.

What goes in the real implementation

  • Session handshake / authentication. Usually a one-time call on app boot; store the token in infrastructure, not in a MobX store.
  • Request/response logging for support tickets. Log correlation IDs so you can trace a spin end-to-end.
  • Retry on transient errors. Finite retries with backoff. Throw loud after N attempts — do not silently return an empty response.
  • Schema validation. Don't trust the payload shape. Parse it (Zod, io-ts, hand-rolled) at the boundary and throw if malformed.

What does NOT go here

  • Game rules. The server enforces them; the client doesn't recompute.
  • UI state. NetworkManager is infrastructure — it doesn't touch UIStore.
  • Paytable caching. If you need the paytable on the client (for tooltips), serve it as a separate endpoint.

Testing

Phase tests use a mock NetworkManager via vi.fn() — see tests/flow/SpinPhase.test.ts. For integration with the real server, use a dev seed if your RGS supports it. Otherwise, mock at the NetworkManager boundary only — don't mock deeper.