@stakeplate/core 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/audio.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as SfxBus, c as createGameAudio, d as bindInputSounds, f as MixerGroup, i as MusicBus, l as InputSoundMap, m as bindMixerToHud, n as GameAudio, o as SoundEntry, p as MixerLike, r as GameAudioOptions, s as bindAudioToHud, t as BusName, u as InputSoundOptions } from "./index-BIcsWHW3.js";
1
+ import { a as SfxBus, c as createGameAudio, d as bindInputSounds, f as MixerGroup, i as MusicBus, l as InputSoundMap, m as bindMixerToHud, n as GameAudio, o as SoundEntry, p as MixerLike, r as GameAudioOptions, s as bindAudioToHud, t as BusName, u as InputSoundOptions } from "./index-BHNLK36s.js";
2
2
  export { BusName, GameAudio, GameAudioOptions, type InputSoundMap, type InputSoundOptions, type MixerGroup, type MixerLike, MusicBus, SfxBus, SoundEntry, bindAudioToHud, bindInputSounds, bindMixerToHud, createGameAudio };
@@ -1,5 +1,5 @@
1
1
  import { m as Round } from "./protocol-C1KamF3t.js";
2
- import { t as NetworkManager } from "./network-CBxKQzeb.js";
2
+ import { t as NetworkManager } from "./network-BIbVvWge.js";
3
3
  import { n as RootStore } from "./index-BBlN97RY.js";
4
4
  import { a as Ticker, t as HudPort } from "./hud-port-DNfotn4U.js";
5
5
  import { BootedHud } from "@open-slot-ui/pixi";
@@ -362,4 +362,4 @@ declare function bindAudioToHud(audio: GameAudio, hud: BootedHud, opts?: {
362
362
  }): () => void;
363
363
  //#endregion
364
364
  export { TurboClock as A, ModeConfig as C, RoundInfo as D, InterpretBook as E, roundInfo as O, GameConfig as S, GameRound as T, FSM as _, SfxBus as a, PhaseContext as b, createGameAudio as c, bindInputSounds as d, MixerGroup as f, AudioValue as g, AudioPort as h, MusicBus as i, TurboState as j, DEFAULT_TURBO_SPEEDS as k, InputSoundMap as l, bindMixerToHud as m, GameAudio as n, SoundEntry as o, MixerLike as p, GameAudioOptions as r, bindAudioToHud as s, BusName as t, InputSoundOptions as u, LoaderPort as v, modeCostOf as w, SpinStartView as x, Phase as y };
365
- //# sourceMappingURL=index-BIcsWHW3.d.ts.map
365
+ //# sourceMappingURL=index-BHNLK36s.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { a as Balance, c as JurisdictionConfig, d as ReplayParams, f as RgsConfig, h as roundEvents, i as BOOK_AMOUNT_MULTIPLIER, l as PlayRequest, m as Round, n as AuthenticateRequest, o as EndRoundRequest, p as RgsError, r as AuthenticateResponse, s as EndRoundResponse, t as API_AMOUNT_MULTIPLIER, u as PlayResponse } from "./protocol-C1KamF3t.js";
2
- import { a as MockOptions, c as RuntimeConfig, d as urlParam, i as MockNetworkManager, l as isStakeLaunch, n as PlayArgs, o as ScriptedRound, r as createNetwork, s as ReplayLaunch, t as NetworkManager, u as readRuntime } from "./network-CBxKQzeb.js";
2
+ import { a as MockOptions, c as RuntimeConfig, d as urlParam, i as MockNetworkManager, l as isStakeLaunch, n as PlayArgs, o as ScriptedRound, r as createNetwork, s as ReplayLaunch, t as NetworkManager, u as readRuntime } from "./network-BIbVvWge.js";
3
3
  import { i as UiStore, n as RootStore, r as SessionStore, t as BalanceStore } from "./index-BBlN97RY.js";
4
4
  import { a as Ticker, i as RealTicker, n as ReplayInfo, r as InstantTicker, t as HudPort } from "./hud-port-DNfotn4U.js";
5
- import { A as TurboClock, C as ModeConfig, D as RoundInfo, E as InterpretBook, O as roundInfo, S as GameConfig, T as GameRound, _ as FSM, b as PhaseContext, g as AudioValue, h as AudioPort, j as TurboState, k as DEFAULT_TURBO_SPEEDS, l as InputSoundMap, o as SoundEntry, r as GameAudioOptions, v as LoaderPort, w as modeCostOf, x as SpinStartView, y as Phase } from "./index-BIcsWHW3.js";
5
+ import { A as TurboClock, C as ModeConfig, D as RoundInfo, E as InterpretBook, O as roundInfo, S as GameConfig, T as GameRound, _ as FSM, b as PhaseContext, g as AudioValue, h as AudioPort, j as TurboState, k as DEFAULT_TURBO_SPEEDS, l as InputSoundMap, o as SoundEntry, r as GameAudioOptions, v as LoaderPort, w as modeCostOf, x as SpinStartView, y as Phase } from "./index-BHNLK36s.js";
6
6
  import { StakeNetworkManager, StakeNetworkOptions } from "./rgs.js";
7
7
  import { BootedHud } from "@open-slot-ui/pixi";
8
8
  import { CurrencySpec } from "@open-slot-ui/core";
@@ -138,22 +138,16 @@ interface NetworkManager {
138
138
  dispose?(): void;
139
139
  }
140
140
  /**
141
- * Pick the transport from the launch runtime:
141
+ * Pick the transport from the launch runtime.
142
142
  *
143
- * - a supplied `mock` instance, or `?mock=true` → the in-process mock RGS (no backend)
144
- * - a real `rgs_url` was provided → the REAL Stake RGS. This INCLUDES a
145
- * `?demo=true` fun-play launch: a Stake demo session still authenticates + plays
146
- * against `rgs_url`, so `demo` must NOT force the mock.
147
- * - `?demo=true` with NO host → the mock (bare local click-around)
148
- * - otherwise → the real transport at the default
149
- * (local emulator) host
150
- *
151
- * This is the key fix over the old `demo → mock`: Stake's own local-redirect dev tool opens
152
- * `…?rgs_url=rgsd.stake-engine.com&sessionID=…&demo=true`. Under the old rule that demo
153
- * session was hijacked by the in-process mock and never reached the RGS; now it authorizes
154
- * on Stake, pulls the real balance/config, and spins/buys with real requests.
143
+ * The in-process mock RGS is used ONLY when EXPLICITLY forced (a supplied `mock` instance, or
144
+ * `?mock=true`). EVERYTHING else talks to the REAL Stake RGS via `stakeTransport` — including a
145
+ * `?demo=true` fun-play launch (a Stake demo wallet still authenticates + plays against the RGS)
146
+ * and a launch with no `rgs_url` (which then targets the default/local-emulator host and surfaces
147
+ * a real boot error if it is unreachable). A game must NEVER silently fall back to fake data:
148
+ * `demo` used to force the mock, which hijacked Stake fun-play sessions into showing mock rounds.
155
149
  */
156
150
  declare function createNetwork(runtime: RuntimeConfig, mock?: MockNetworkManager): NetworkManager;
157
151
  //#endregion
158
152
  export { MockOptions as a, RuntimeConfig as c, urlParam as d, MockNetworkManager as i, isStakeLaunch as l, PlayArgs as n, ScriptedRound as o, createNetwork as r, ReplayLaunch as s, NetworkManager as t, readRuntime as u };
159
- //# sourceMappingURL=network-CBxKQzeb.d.ts.map
153
+ //# sourceMappingURL=network-BIbVvWge.d.ts.map
package/dist/rgs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as Balance, c as JurisdictionConfig, d as ReplayParams, f as RgsConfig, h as roundEvents, i as BOOK_AMOUNT_MULTIPLIER, l as PlayRequest, m as Round, n as AuthenticateRequest, o as EndRoundRequest, p as RgsError, r as AuthenticateResponse, s as EndRoundResponse, t as API_AMOUNT_MULTIPLIER, u as PlayResponse } from "./protocol-C1KamF3t.js";
2
- import { a as MockOptions, c as RuntimeConfig, d as urlParam, i as MockNetworkManager, l as isStakeLaunch, n as PlayArgs, o as ScriptedRound, r as createNetwork, s as ReplayLaunch, t as NetworkManager, u as readRuntime } from "./network-CBxKQzeb.js";
2
+ import { a as MockOptions, c as RuntimeConfig, d as urlParam, i as MockNetworkManager, l as isStakeLaunch, n as PlayArgs, o as ScriptedRound, r as createNetwork, s as ReplayLaunch, t as NetworkManager, u as readRuntime } from "./network-BIbVvWge.js";
3
3
  //#region src/rgs/StakeNetworkManager.d.ts
4
4
  interface StakeNetworkOptions {
5
5
  rgsUrl: string;
package/dist/rgs.js CHANGED
@@ -117,26 +117,18 @@ var StakeNetworkManager = class {
117
117
  //#endregion
118
118
  //#region src/rgs/network.ts
119
119
  /**
120
- * Pick the transport from the launch runtime:
120
+ * Pick the transport from the launch runtime.
121
121
  *
122
- * - a supplied `mock` instance, or `?mock=true` → the in-process mock RGS (no backend)
123
- * - a real `rgs_url` was provided → the REAL Stake RGS. This INCLUDES a
124
- * `?demo=true` fun-play launch: a Stake demo session still authenticates + plays
125
- * against `rgs_url`, so `demo` must NOT force the mock.
126
- * - `?demo=true` with NO host → the mock (bare local click-around)
127
- * - otherwise → the real transport at the default
128
- * (local emulator) host
129
- *
130
- * This is the key fix over the old `demo → mock`: Stake's own local-redirect dev tool opens
131
- * `…?rgs_url=rgsd.stake-engine.com&sessionID=…&demo=true`. Under the old rule that demo
132
- * session was hijacked by the in-process mock and never reached the RGS; now it authorizes
133
- * on Stake, pulls the real balance/config, and spins/buys with real requests.
122
+ * The in-process mock RGS is used ONLY when EXPLICITLY forced (a supplied `mock` instance, or
123
+ * `?mock=true`). EVERYTHING else talks to the REAL Stake RGS via `stakeTransport` — including a
124
+ * `?demo=true` fun-play launch (a Stake demo wallet still authenticates + plays against the RGS)
125
+ * and a launch with no `rgs_url` (which then targets the default/local-emulator host and surfaces
126
+ * a real boot error if it is unreachable). A game must NEVER silently fall back to fake data:
127
+ * `demo` used to force the mock, which hijacked Stake fun-play sessions into showing mock rounds.
134
128
  */
135
129
  function createNetwork(runtime, mock) {
136
130
  if (mock) return mock;
137
131
  if (runtime.mock) return new MockNetworkManager();
138
- if (runtime.rgsUrlProvided) return stakeTransport(runtime);
139
- if (runtime.demo) return new MockNetworkManager();
140
132
  return stakeTransport(runtime);
141
133
  }
142
134
  function stakeTransport(runtime) {
package/dist/rgs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"rgs.js","names":[],"sources":["../src/rgs/runtime.ts","../src/rgs/StakeNetworkManager.ts","../src/rgs/network.ts"],"sourcesContent":["/**\n * Stake launch parameters (mirrors `StakeEngine/web-sdk`\n * `packages/state-shared/src/stateUrl`): sessionID, rgs_url, lang, currency, device,\n * social, demo — plus the REPLAY set: replay, amount, game, version, mode, event.\n * `lang` is REQUIRED by `/wallet/authenticate` (its absence 400s the RGS).\n */\n\nexport interface ReplayLaunch {\n /** `?replay=true` — launch into replay (fetch + play back a recorded round). */\n active: boolean;\n amount: number;\n game: string;\n version: string;\n mode: string;\n event: string;\n}\n\nexport interface RuntimeConfig {\n rgsUrl: string;\n /**\n * True when a real `rgs_url`/`rgsUrl` launch param was present (vs falling back to the\n * local default). A provided host means \"talk to it\" — this is what tells the transport\n * picker to use the REAL Stake RGS, even for a `demo` fun-play launch. Set it in\n * `overrides` to force the real transport when you supply `rgsUrl` programmatically.\n */\n rgsUrlProvided: boolean;\n sessionId: string;\n /** BCP-47-ish language for `/wallet/authenticate` + the HUD locale ('br' → 'pt'). */\n language: string;\n /** `?currency=` — currency code (used for replay, where there's no wallet to read it). */\n currency: string;\n /** `?social=true` — force Stake US social/sweepstakes wording. */\n social: boolean;\n /** `?device=` — Stake's viewport hint ('' | 'desktop' | 'mobile' | a small popout). */\n device: string;\n /**\n * `?demo=true` — Stake FUN-PLAY: a demo (non-cash) wallet on the REAL RGS. This is NOT a\n * \"use a fake backend\" switch — Stake's own local-redirect dev tool launches\n * `…?rgs_url=rgsd.stake-engine.com&sessionID=…&demo=true`, and that session still\n * authenticates + plays against the real RGS. To run the in-process mock, use `?mock=true`.\n */\n demo: boolean;\n /**\n * `?mock=true` — force the built-in in-process mock RGS (no backend). For pure client dev\n * without a real session; distinct from Stake's `demo` fun-play. Overrides `rgs_url`.\n */\n mock: boolean;\n replay: ReplayLaunch;\n}\n\ntype ParamSource = (name: string) => string | undefined;\n\n/** Read a URL param from `window.location.search` (undefined off-DOM). */\nexport function urlParam(name: string): string | undefined {\n if (typeof window === 'undefined') return undefined;\n return new URLSearchParams(window.location.search).get(name) ?? undefined;\n}\n\n/**\n * Parse the Stake launch params into a {@link RuntimeConfig}. Pass `overrides` (or a\n * custom `param` reader) for tests/embedding; otherwise reads the page URL. `rgsUrl`\n * defaults to a local emulator so `pnpm dev` works out of the box.\n */\nexport function readRuntime(opts: { param?: ParamSource; overrides?: Partial<RuntimeConfig>; defaultRgsUrl?: string } = {}): RuntimeConfig {\n const param = opts.param ?? urlParam;\n const rawLang = param('lang');\n const language = rawLang === 'br' ? 'pt' : rawLang || 'en';\n const rgsUrlParam = param('rgs_url') ?? param('rgsUrl');\n const base: RuntimeConfig = {\n rgsUrl: rgsUrlParam ?? opts.defaultRgsUrl ?? 'http://localhost:4758',\n rgsUrlProvided: rgsUrlParam != null,\n sessionId: param('sessionID') ?? param('sessionId') ?? 'dev',\n language,\n currency: param('currency') ?? 'USD',\n social: param('social') === 'true',\n device: param('device') ?? '',\n demo: param('demo') === 'true',\n mock: param('mock') === 'true',\n replay: {\n active: param('replay') === 'true',\n amount: Number(param('amount')) || 0,\n game: param('game') ?? '',\n version: param('version') ?? '',\n mode: param('mode') ?? '',\n event: param('event') ?? '',\n },\n };\n return { ...base, ...opts.overrides, replay: { ...base.replay, ...opts.overrides?.replay } };\n}\n\n/**\n * True when the game was launched by the Stake platform — i.e. a real `rgs_url` was provided\n * (the dev dashboard's \"local redirect\", or a live launch) and the in-process mock wasn't\n * forced with `?mock=true`. This holds for `demo=true` fun-play launches too: they still run\n * against the real RGS.\n *\n * A game gates its local dev mock on `!isStakeLaunch()` — so bare `pnpm dev` uses the mock,\n * while a Stake launch auto-connects to the real RGS with the launch `sessionID`, no code edit.\n */\nexport function isStakeLaunch(runtime: RuntimeConfig = readRuntime()): boolean {\n return runtime.rgsUrlProvided && !runtime.mock;\n}\n","// StakeNetworkManager — the ONLY thing that speaks the Stake RGS wire. Thin: it\n// returns RAW protocol shapes; the engine (SpinPhase/boot) owns the end-round settle\n// + active-round resume. Money: RGS = API units (×1e6); the game's book = BOOK units.\n\nimport {\n API_AMOUNT_MULTIPLIER,\n type AuthenticateResponse,\n type EndRoundResponse,\n type PlayResponse,\n type ReplayParams,\n type Round,\n} from './protocol';\nimport type { NetworkManager, PlayArgs } from './network';\n\nexport interface StakeNetworkOptions {\n rgsUrl: string;\n sessionId: string;\n /** REQUIRED — `/wallet/authenticate` 400s without it. */\n language: string;\n}\n\nexport class StakeNetworkManager implements NetworkManager {\n private readonly base: string;\n /** Currency learned at authenticate; sent on every `/wallet/play`. */\n private currency = 'USD';\n\n constructor(private readonly opts: StakeNetworkOptions) {\n this.base = /^https?:\\/\\//.test(opts.rgsUrl) ? opts.rgsUrl : `https://${opts.rgsUrl}`;\n }\n\n async authenticate(): Promise<AuthenticateResponse> {\n const res = await this.post<AuthenticateResponse>('/wallet/authenticate', {\n sessionID: this.opts.sessionId,\n language: this.opts.language,\n });\n this.currency = res.balance.currency;\n return res;\n }\n\n async play(args: PlayArgs): Promise<PlayResponse> {\n return this.post<PlayResponse>('/wallet/play', {\n sessionID: this.opts.sessionId,\n currency: args.currency ?? this.currency,\n amount: Math.round(args.bet * API_AMOUNT_MULTIPLIER),\n mode: args.mode,\n });\n }\n\n async endRound(): Promise<EndRoundResponse> {\n return this.post<EndRoundResponse>('/wallet/end-round', { sessionID: this.opts.sessionId });\n }\n\n async replay(p: ReplayParams): Promise<Round> {\n const path = `/bet/replay/${encodeURIComponent(p.game)}/${encodeURIComponent(p.version)}/${encodeURIComponent(p.mode)}/${encodeURIComponent(p.event)}`;\n const res = await this.get<Record<string, unknown>>(path);\n // The RGS may return `{ round }` or the round object directly.\n return (res.round ?? res) as Round;\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const res = await fetch(this.base + path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[StakeNetworkManager] ${path} -> ${res.status} ${text}`);\n }\n return (await res.json()) as T;\n }\n\n private async get<T>(path: string): Promise<T> {\n const res = await fetch(this.base + path, { method: 'GET', headers: { accept: 'application/json' } });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[StakeNetworkManager] ${path} -> ${res.status} ${text}`);\n }\n return (await res.json()) as T;\n }\n}\n","// The transport seam. Adapters return RAW protocol shapes; the engine applies the\n// game's `interpretBook` and owns the round lifecycle (settle / resume).\n\nimport type { AuthenticateResponse, EndRoundResponse, PlayResponse, ReplayParams, Round } from './protocol';\nimport type { RuntimeConfig } from './runtime';\nimport { StakeNetworkManager } from './StakeNetworkManager';\nimport { MockNetworkManager } from './MockNetworkManager';\n\nexport interface PlayArgs {\n /** Base bet in MAJOR units (the transport converts to API units). */\n bet: number;\n /** Mode key — base / a boost / a bonus buy. The platform applies its cost. */\n mode: string;\n /** Currency code; defaults to the one learned at authenticate. */\n currency?: string;\n}\n\nexport interface NetworkManager {\n authenticate(): Promise<AuthenticateResponse>;\n play(args: PlayArgs): Promise<PlayResponse>;\n endRound(): Promise<EndRoundResponse>;\n /** Optional — fetch a recorded round for read-only replay. */\n replay?(params: ReplayParams): Promise<Round>;\n dispose?(): void;\n}\n\n/**\n * Pick the transport from the launch runtime:\n *\n * - a supplied `mock` instance, or `?mock=true` → the in-process mock RGS (no backend)\n * - a real `rgs_url` was provided → the REAL Stake RGS. This INCLUDES a\n * `?demo=true` fun-play launch: a Stake demo session still authenticates + plays\n * against `rgs_url`, so `demo` must NOT force the mock.\n * - `?demo=true` with NO host → the mock (bare local click-around)\n * - otherwise → the real transport at the default\n * (local emulator) host\n *\n * This is the key fix over the old `demo → mock`: Stake's own local-redirect dev tool opens\n * `…?rgs_url=rgsd.stake-engine.com&sessionID=…&demo=true`. Under the old rule that demo\n * session was hijacked by the in-process mock and never reached the RGS; now it authorizes\n * on Stake, pulls the real balance/config, and spins/buys with real requests.\n */\nexport function createNetwork(runtime: RuntimeConfig, mock?: MockNetworkManager): NetworkManager {\n if (mock) return mock;\n if (runtime.mock) return new MockNetworkManager();\n if (runtime.rgsUrlProvided) return stakeTransport(runtime);\n if (runtime.demo) return new MockNetworkManager();\n return stakeTransport(runtime);\n}\n\nfunction stakeTransport(runtime: RuntimeConfig): StakeNetworkManager {\n return new StakeNetworkManager({\n rgsUrl: runtime.rgsUrl,\n sessionId: runtime.sessionId,\n language: runtime.language,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"rgs.js","names":[],"sources":["../src/rgs/runtime.ts","../src/rgs/StakeNetworkManager.ts","../src/rgs/network.ts"],"sourcesContent":["/**\n * Stake launch parameters (mirrors `StakeEngine/web-sdk`\n * `packages/state-shared/src/stateUrl`): sessionID, rgs_url, lang, currency, device,\n * social, demo — plus the REPLAY set: replay, amount, game, version, mode, event.\n * `lang` is REQUIRED by `/wallet/authenticate` (its absence 400s the RGS).\n */\n\nexport interface ReplayLaunch {\n /** `?replay=true` — launch into replay (fetch + play back a recorded round). */\n active: boolean;\n amount: number;\n game: string;\n version: string;\n mode: string;\n event: string;\n}\n\nexport interface RuntimeConfig {\n rgsUrl: string;\n /**\n * True when a real `rgs_url`/`rgsUrl` launch param was present (vs falling back to the\n * local default). A provided host means \"talk to it\" — this is what tells the transport\n * picker to use the REAL Stake RGS, even for a `demo` fun-play launch. Set it in\n * `overrides` to force the real transport when you supply `rgsUrl` programmatically.\n */\n rgsUrlProvided: boolean;\n sessionId: string;\n /** BCP-47-ish language for `/wallet/authenticate` + the HUD locale ('br' → 'pt'). */\n language: string;\n /** `?currency=` — currency code (used for replay, where there's no wallet to read it). */\n currency: string;\n /** `?social=true` — force Stake US social/sweepstakes wording. */\n social: boolean;\n /** `?device=` — Stake's viewport hint ('' | 'desktop' | 'mobile' | a small popout). */\n device: string;\n /**\n * `?demo=true` — Stake FUN-PLAY: a demo (non-cash) wallet on the REAL RGS. This is NOT a\n * \"use a fake backend\" switch — Stake's own local-redirect dev tool launches\n * `…?rgs_url=rgsd.stake-engine.com&sessionID=…&demo=true`, and that session still\n * authenticates + plays against the real RGS. To run the in-process mock, use `?mock=true`.\n */\n demo: boolean;\n /**\n * `?mock=true` — force the built-in in-process mock RGS (no backend). For pure client dev\n * without a real session; distinct from Stake's `demo` fun-play. Overrides `rgs_url`.\n */\n mock: boolean;\n replay: ReplayLaunch;\n}\n\ntype ParamSource = (name: string) => string | undefined;\n\n/** Read a URL param from `window.location.search` (undefined off-DOM). */\nexport function urlParam(name: string): string | undefined {\n if (typeof window === 'undefined') return undefined;\n return new URLSearchParams(window.location.search).get(name) ?? undefined;\n}\n\n/**\n * Parse the Stake launch params into a {@link RuntimeConfig}. Pass `overrides` (or a\n * custom `param` reader) for tests/embedding; otherwise reads the page URL. `rgsUrl`\n * defaults to a local emulator so `pnpm dev` works out of the box.\n */\nexport function readRuntime(opts: { param?: ParamSource; overrides?: Partial<RuntimeConfig>; defaultRgsUrl?: string } = {}): RuntimeConfig {\n const param = opts.param ?? urlParam;\n const rawLang = param('lang');\n const language = rawLang === 'br' ? 'pt' : rawLang || 'en';\n const rgsUrlParam = param('rgs_url') ?? param('rgsUrl');\n const base: RuntimeConfig = {\n rgsUrl: rgsUrlParam ?? opts.defaultRgsUrl ?? 'http://localhost:4758',\n rgsUrlProvided: rgsUrlParam != null,\n sessionId: param('sessionID') ?? param('sessionId') ?? 'dev',\n language,\n currency: param('currency') ?? 'USD',\n social: param('social') === 'true',\n device: param('device') ?? '',\n demo: param('demo') === 'true',\n mock: param('mock') === 'true',\n replay: {\n active: param('replay') === 'true',\n amount: Number(param('amount')) || 0,\n game: param('game') ?? '',\n version: param('version') ?? '',\n mode: param('mode') ?? '',\n event: param('event') ?? '',\n },\n };\n return { ...base, ...opts.overrides, replay: { ...base.replay, ...opts.overrides?.replay } };\n}\n\n/**\n * True when the game was launched by the Stake platform — i.e. a real `rgs_url` was provided\n * (the dev dashboard's \"local redirect\", or a live launch) and the in-process mock wasn't\n * forced with `?mock=true`. This holds for `demo=true` fun-play launches too: they still run\n * against the real RGS.\n *\n * A game gates its local dev mock on `!isStakeLaunch()` — so bare `pnpm dev` uses the mock,\n * while a Stake launch auto-connects to the real RGS with the launch `sessionID`, no code edit.\n */\nexport function isStakeLaunch(runtime: RuntimeConfig = readRuntime()): boolean {\n return runtime.rgsUrlProvided && !runtime.mock;\n}\n","// StakeNetworkManager — the ONLY thing that speaks the Stake RGS wire. Thin: it\n// returns RAW protocol shapes; the engine (SpinPhase/boot) owns the end-round settle\n// + active-round resume. Money: RGS = API units (×1e6); the game's book = BOOK units.\n\nimport {\n API_AMOUNT_MULTIPLIER,\n type AuthenticateResponse,\n type EndRoundResponse,\n type PlayResponse,\n type ReplayParams,\n type Round,\n} from './protocol';\nimport type { NetworkManager, PlayArgs } from './network';\n\nexport interface StakeNetworkOptions {\n rgsUrl: string;\n sessionId: string;\n /** REQUIRED — `/wallet/authenticate` 400s without it. */\n language: string;\n}\n\nexport class StakeNetworkManager implements NetworkManager {\n private readonly base: string;\n /** Currency learned at authenticate; sent on every `/wallet/play`. */\n private currency = 'USD';\n\n constructor(private readonly opts: StakeNetworkOptions) {\n this.base = /^https?:\\/\\//.test(opts.rgsUrl) ? opts.rgsUrl : `https://${opts.rgsUrl}`;\n }\n\n async authenticate(): Promise<AuthenticateResponse> {\n const res = await this.post<AuthenticateResponse>('/wallet/authenticate', {\n sessionID: this.opts.sessionId,\n language: this.opts.language,\n });\n this.currency = res.balance.currency;\n return res;\n }\n\n async play(args: PlayArgs): Promise<PlayResponse> {\n return this.post<PlayResponse>('/wallet/play', {\n sessionID: this.opts.sessionId,\n currency: args.currency ?? this.currency,\n amount: Math.round(args.bet * API_AMOUNT_MULTIPLIER),\n mode: args.mode,\n });\n }\n\n async endRound(): Promise<EndRoundResponse> {\n return this.post<EndRoundResponse>('/wallet/end-round', { sessionID: this.opts.sessionId });\n }\n\n async replay(p: ReplayParams): Promise<Round> {\n const path = `/bet/replay/${encodeURIComponent(p.game)}/${encodeURIComponent(p.version)}/${encodeURIComponent(p.mode)}/${encodeURIComponent(p.event)}`;\n const res = await this.get<Record<string, unknown>>(path);\n // The RGS may return `{ round }` or the round object directly.\n return (res.round ?? res) as Round;\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const res = await fetch(this.base + path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[StakeNetworkManager] ${path} -> ${res.status} ${text}`);\n }\n return (await res.json()) as T;\n }\n\n private async get<T>(path: string): Promise<T> {\n const res = await fetch(this.base + path, { method: 'GET', headers: { accept: 'application/json' } });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`[StakeNetworkManager] ${path} -> ${res.status} ${text}`);\n }\n return (await res.json()) as T;\n }\n}\n","// The transport seam. Adapters return RAW protocol shapes; the engine applies the\n// game's `interpretBook` and owns the round lifecycle (settle / resume).\n\nimport type { AuthenticateResponse, EndRoundResponse, PlayResponse, ReplayParams, Round } from './protocol';\nimport type { RuntimeConfig } from './runtime';\nimport { StakeNetworkManager } from './StakeNetworkManager';\nimport { MockNetworkManager } from './MockNetworkManager';\n\nexport interface PlayArgs {\n /** Base bet in MAJOR units (the transport converts to API units). */\n bet: number;\n /** Mode key — base / a boost / a bonus buy. The platform applies its cost. */\n mode: string;\n /** Currency code; defaults to the one learned at authenticate. */\n currency?: string;\n}\n\nexport interface NetworkManager {\n authenticate(): Promise<AuthenticateResponse>;\n play(args: PlayArgs): Promise<PlayResponse>;\n endRound(): Promise<EndRoundResponse>;\n /** Optional — fetch a recorded round for read-only replay. */\n replay?(params: ReplayParams): Promise<Round>;\n dispose?(): void;\n}\n\n/**\n * Pick the transport from the launch runtime.\n *\n * The in-process mock RGS is used ONLY when EXPLICITLY forced (a supplied `mock` instance, or\n * `?mock=true`). EVERYTHING else talks to the REAL Stake RGS via `stakeTransport` — including a\n * `?demo=true` fun-play launch (a Stake demo wallet still authenticates + plays against the RGS)\n * and a launch with no `rgs_url` (which then targets the default/local-emulator host and surfaces\n * a real boot error if it is unreachable). A game must NEVER silently fall back to fake data:\n * `demo` used to force the mock, which hijacked Stake fun-play sessions into showing mock rounds.\n */\nexport function createNetwork(runtime: RuntimeConfig, mock?: MockNetworkManager): NetworkManager {\n if (mock) return mock;\n if (runtime.mock) return new MockNetworkManager(); // ?mock=true — explicit local-dev only\n return stakeTransport(runtime); // real RGS (rgs_url when provided, else the default host)\n}\n\nfunction stakeTransport(runtime: RuntimeConfig): StakeNetworkManager {\n return new StakeNetworkManager({\n rgsUrl: runtime.rgsUrl,\n sessionId: runtime.sessionId,\n language: runtime.language,\n });\n}\n"],"mappings":"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"}
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as MockOptions, i as MockNetworkManager, o as ScriptedRound } from "./network-CBxKQzeb.js";
1
+ import { a as MockOptions, i as MockNetworkManager, o as ScriptedRound } from "./network-BIbVvWge.js";
2
2
  import { r as InstantTicker, t as HudPort } from "./hud-port-DNfotn4U.js";
3
3
  //#region src/testing/index.d.ts
4
4
  /** A recording no-op HudPort — inspect `.calls` in tests. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stakeplate/core",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Batteries-included Stake Engine game core — RGS transport, boot, round FSM, HUD binding, audio, i18n and a compliant rules builder. Bring a scene, a Present phase and a pure interpretBook; the core does the rest.",
5
5
  "keywords": [
6
6
  "stake",