@energy8platform/platform-core 0.16.1 → 0.16.2

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.
@@ -1,5 +1,56 @@
1
1
  import { Bridge } from '@energy8platform/game-sdk';
2
2
 
3
+ /** Default session TTL when GameDefinition.session_ttl is omitted (24h). */
4
+ const DEFAULT_SESSION_TTL_MS = 24 * 60 * 60 * 1000;
5
+ /**
6
+ * Parse a Go-style duration string ("24h", "5ms", "30s", "10m") into
7
+ * milliseconds. Mirrors GameDefinition.SessionTTLDuration on the server.
8
+ */
9
+ function parseSessionTtl(ttl) {
10
+ if (!ttl)
11
+ return DEFAULT_SESSION_TTL_MS;
12
+ const m = ttl.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)$/);
13
+ if (!m)
14
+ return DEFAULT_SESSION_TTL_MS;
15
+ const n = parseFloat(m[1]);
16
+ switch (m[2]) {
17
+ case 'ms': return n;
18
+ case 's': return n * 1000;
19
+ case 'm': return n * 60 * 1000;
20
+ case 'h': return n * 60 * 60 * 1000;
21
+ default: return DEFAULT_SESSION_TTL_MS;
22
+ }
23
+ }
24
+ /**
25
+ * Validate a bet against the game's bet_levels config — mirrors the server's
26
+ * validateBet. Levels-list takes priority over min/max range.
27
+ */
28
+ function isBetAllowed(bet, levels) {
29
+ if (!levels)
30
+ return true;
31
+ if (Array.isArray(levels)) {
32
+ return levels.includes(bet);
33
+ }
34
+ if (levels.levels && levels.levels.length > 0) {
35
+ return levels.levels.includes(bet);
36
+ }
37
+ if (levels.min !== undefined && bet < levels.min)
38
+ return false;
39
+ if (levels.max !== undefined && bet > levels.max)
40
+ return false;
41
+ return true;
42
+ }
43
+ /**
44
+ * Generate a server-style UUID for a fresh round. Falls back to a counter
45
+ * suffix if `crypto.randomUUID` isn't available (very old runtimes).
46
+ */
47
+ function generateRoundId() {
48
+ const c = globalThis.crypto;
49
+ if (c && typeof c.randomUUID === 'function')
50
+ return c.randomUUID();
51
+ // Minimal fallback — not crypto-strong, but keeps the wire shape sane.
52
+ return 'dev-' + Math.random().toString(16).slice(2) + '-' + Date.now().toString(16);
53
+ }
3
54
  const DEFAULT_CONFIG = {
4
55
  balance: 10000,
5
56
  currency: 'USD',
@@ -48,10 +99,19 @@ class DevBridge {
48
99
  _roundCounter = 0;
49
100
  _bridge = null;
50
101
  _useLuaServer;
102
+ /** Last PlayResult sent — mirrors what `GET /games/{id}/session` returns. */
103
+ _lastPlayResult = null;
104
+ /** Active session round id; non-null while a session is in progress. */
105
+ _activeRoundId = null;
106
+ /** Wall-clock expiry timestamp for the active session. */
107
+ _sessionExpiresAt = null;
108
+ /** Pre-parsed session TTL from gameDefinition.session_ttl. */
109
+ _sessionTtlMs;
51
110
  constructor(config = {}) {
52
111
  this._config = { ...DEFAULT_CONFIG, ...config };
53
112
  this._balance = this._config.balance;
54
113
  this._useLuaServer = !!(this._config.luaScript && this._config.gameDefinition);
114
+ this._sessionTtlMs = parseSessionTtl(this._config.gameDefinition?.session_ttl);
55
115
  }
56
116
  /** Current mock balance */
57
117
  get balance() {
@@ -117,26 +177,83 @@ class DevBridge {
117
177
  this.delayedSend('INIT', initData, id);
118
178
  }
119
179
  handlePlayRequest(payload, id) {
120
- const { action, bet, roundId, params } = payload;
180
+ const { action, bet, params } = payload;
121
181
  this._roundCounter++;
122
182
  if (this._useLuaServer) {
183
+ const def = this._config.gameDefinition;
184
+ // Mirror the server's INVALID_INPUT short-circuit: an unknown action
185
+ // is rejected before any wallet movement, with no PLAY_RESULT.
186
+ const actionDef = def.actions?.[action];
187
+ if (!actionDef) {
188
+ this.sendError(id, 'INVALID_INPUT', `unknown action "${action}"`);
189
+ return;
190
+ }
191
+ // Bet validation — server returns 400 INVALID_AMOUNT before the
192
+ // engine. We mirror that so games can't silently accept bad bets.
193
+ if (!isBetAllowed(bet, def.bet_levels)) {
194
+ this.sendError(id, 'INVALID_AMOUNT', `bet ${bet} is not in allowed bet_levels`);
195
+ return;
196
+ }
197
+ // Session-state guards (server: 409 ACTIVE_SESSION_EXISTS / 404 NoActiveSession / 410 ExpiredSession).
198
+ const sessionExpired = this._activeRoundId !== null &&
199
+ this._sessionExpiresAt !== null &&
200
+ Date.now() > this._sessionExpiresAt;
201
+ if (actionDef.requires_session) {
202
+ if (sessionExpired) {
203
+ this.clearSessionState();
204
+ this.sendError(id, 'SESSION_EXPIRED', 'game session has expired');
205
+ return;
206
+ }
207
+ if (this._activeRoundId === null) {
208
+ this.sendError(id, 'NO_ACTIVE_SESSION', `action "${action}" requires an active session`);
209
+ return;
210
+ }
211
+ }
212
+ else {
213
+ // Non-session action over an active (non-expired) session — server's
214
+ // acquireSession would fail with ACTIVE_SESSION_EXISTS.
215
+ if (this._activeRoundId !== null && !sessionExpired) {
216
+ this.sendError(id, 'ACTIVE_SESSION_EXISTS', 'an active game session already exists');
217
+ return;
218
+ }
219
+ if (sessionExpired) {
220
+ // Drop stale session state so a fresh non-session action can proceed.
221
+ this.clearSessionState();
222
+ }
223
+ }
123
224
  // Compute the debit amount for this action — mirrors the platform's
124
225
  // server-side rules so Buy Bonus / Ante Bet actions debit the right
125
226
  // multiple of bet instead of just the base bet.
126
227
  const debit = this.computeDebit(action, bet, params);
228
+ // Server returns 402 INSUFFICIENT_FUNDS before the wallet is touched
229
+ // and never reaches the engine. DevBridge must do the same so the
230
+ // SDK's play() rejects with the right SDKError code.
231
+ if (debit > this._balance) {
232
+ this.sendError(id, 'INSUFFICIENT_FUNDS', `insufficient funds (need ${debit}, have ${this._balance})`);
233
+ return;
234
+ }
127
235
  this._balance -= debit;
128
- this.executeLuaOnServer({ action, bet, roundId, params })
236
+ // Round id rules mirror server's playRound:
237
+ // non-session → fresh UUID, client-supplied id is ignored
238
+ // session-based → reuse the active session's round id
239
+ const serverRoundId = actionDef.requires_session
240
+ ? this._activeRoundId
241
+ : generateRoundId();
242
+ this.executeLuaOnServer({ action, bet, roundId: serverRoundId, params })
129
243
  .then((result) => {
244
+ this._lastPlayResult = result;
245
+ this.updateSessionState(result);
130
246
  this._bridge?.send('PLAY_RESULT', result, id);
131
247
  })
132
248
  .catch((err) => {
133
249
  console.error('[DevBridge] Lua server error:', err);
134
250
  this._balance += debit;
135
- this._bridge?.send('PLAY_RESULT', this.buildFallbackResult(action, bet, roundId), id);
251
+ this.sendError(id, 'ENGINE_ERROR', err?.message ?? 'lua execution failed');
136
252
  });
137
253
  }
138
254
  else {
139
255
  // Fallback to onPlay callback
256
+ const { roundId } = payload;
140
257
  const customResult = this._config.onPlay({ action, bet, roundId, params });
141
258
  const totalWin = customResult.totalWin ?? (Math.random() > 0.6 ? bet * (1 + Math.random() * 10) : 0);
142
259
  this._balance += totalWin;
@@ -153,40 +270,62 @@ class DevBridge {
153
270
  currency: this._config.currency,
154
271
  gameId: this._config.gameConfig?.id ?? 'dev-game',
155
272
  };
273
+ this._lastPlayResult = result;
156
274
  this.delayedSend('PLAY_RESULT', result, id);
157
275
  }
158
276
  }
277
+ /** Send a PLAY_ERROR correlated to the original PLAY_REQUEST id. */
278
+ sendError(id, code, message) {
279
+ this._bridge?.send('PLAY_ERROR', { code, message }, id);
280
+ }
281
+ /**
282
+ * Refresh tracked session state from the latest PlayResult.
283
+ * - new/ongoing session → remember roundId + (re)set expiry
284
+ * - completed/no session → clear tracking
285
+ */
286
+ updateSessionState(result) {
287
+ const session = result.session;
288
+ if (session && !session.completed) {
289
+ if (this._activeRoundId === null) {
290
+ this._activeRoundId = result.roundId;
291
+ this._sessionExpiresAt = Date.now() + this._sessionTtlMs;
292
+ }
293
+ }
294
+ else {
295
+ this.clearSessionState();
296
+ }
297
+ }
298
+ /** Drop active-session tracking (called on completion or expiry sweep). */
299
+ clearSessionState() {
300
+ this._activeRoundId = null;
301
+ this._sessionExpiresAt = null;
302
+ }
159
303
  /**
160
304
  * Compute the wallet debit for a play request, mirroring the platform's
161
- * server-side rules:
162
- * - debit: 'bet' → bet
305
+ * server-side ActionDefinition.DebitAmount:
306
+ * - debit: 'bet' → bet (× ante_bet.cost_multiplier when params.ante_bet=true)
163
307
  * - debit: 'buy_bonus_cost' → bet × buy_bonus.modes[mode].cost_multiplier
164
308
  * - debit: 'ante_bet_cost' → bet × ante_bet.cost_multiplier
165
- * - debit: 'none' 0 (session continuations, e.g. free spins)
309
+ * - anything else (incl. 'none', '', missing action) → 0
166
310
  *
167
- * Without a gameDefinition (or when the action is unknown), falls back to
168
- * `bet` and warns. This is the dev-mode behavior the previous
169
- * implementation always used for every action kept here as a safe
170
- * default so existing setups don't silently change semantics.
311
+ * The empty/missing default returns 0 to match the server's
312
+ * `decimal.Zero` fallback important for table-game continuations
313
+ * (e.g. blackjack `hit`/`stand`) where the action exists with no debit.
171
314
  *
172
315
  * Note: in the platform protocol the client sends the *base* bet only
173
316
  * (`PlayParams.bet`); the cost multiplier lives in the GameDefinition.
174
- * Session continuations (free_spin, feature_spin) must be invoked with
175
- * `bet: 0` — LuaEngine pulls the active session's bet from the persisted
176
- * session state.
317
+ * Session continuations must be invoked with the triggering bet — LuaEngine
318
+ * pulls the active session's bet from the persisted session state.
177
319
  */
178
320
  computeDebit(action, bet, params) {
179
321
  const def = this._config.gameDefinition;
180
322
  const actionDef = def?.actions?.[action];
181
323
  if (!def || !actionDef) {
182
- if (this._config.debug) {
183
- console.warn(`[DevBridge] Unknown action "${action}" debiting base bet as fallback.`);
184
- }
185
- return bet;
324
+ // Server short-circuits unknown actions before computing debit;
325
+ // returning 0 here keeps semantics aligned if the guard is ever bypassed.
326
+ return 0;
186
327
  }
187
328
  switch (actionDef.debit) {
188
- case 'none':
189
- return 0;
190
329
  case 'buy_bonus_cost': {
191
330
  const modeName = actionDef.buy_bonus_mode;
192
331
  const mode = modeName ? def.buy_bonus?.modes?.[modeName] : undefined;
@@ -204,8 +343,7 @@ class DevBridge {
204
343
  }
205
344
  return bet * multiplier;
206
345
  }
207
- case 'bet':
208
- default: {
346
+ case 'bet': {
209
347
  // The platform also debits ante_bet pricing on regular `bet` actions
210
348
  // when the client signals it via params.ante_bet. Mirror that here.
211
349
  if (params && params['ante_bet'] === true) {
@@ -216,6 +354,9 @@ class DevBridge {
216
354
  }
217
355
  return bet;
218
356
  }
357
+ default:
358
+ // 'none', '', or any unrecognized debit mode → 0 (server default).
359
+ return 0;
219
360
  }
220
361
  }
221
362
  async executeLuaOnServer(params) {
@@ -244,21 +385,9 @@ class DevBridge {
244
385
  data: luaResult.data,
245
386
  nextActions: luaResult.nextActions,
246
387
  session: luaResult.session,
247
- creditPending: !shouldCredit,
248
- bonusFreeSpin: null,
249
- currency: this._config.currency,
250
- gameId: this._config.gameConfig?.id ?? 'dev-game',
251
- };
252
- }
253
- buildFallbackResult(action, bet, roundId) {
254
- return {
255
- roundId: roundId ?? `dev-round-${this._roundCounter}`,
256
- action,
257
- balanceAfter: this._balance,
258
- totalWin: 0,
259
- data: { error: 'Lua execution failed' },
260
- nextActions: ['spin'],
261
- session: null,
388
+ // creditPending=true on the wire means "wallet credit failed, queued
389
+ // for retry" — not "credit deferred until session completes". DevBridge
390
+ // never simulates credit failures, so this is always false.
262
391
  creditPending: false,
263
392
  bonusFreeSpin: null,
264
393
  currency: this._config.currency,
@@ -274,7 +403,14 @@ class DevBridge {
274
403
  this.delayedSend('BALANCE_UPDATE', { balance: this._balance }, id);
275
404
  }
276
405
  handleGetState(id) {
277
- this.delayedSend('STATE_RESPONSE', { session: this._config.session ?? null }, id);
406
+ // Mirror the platform's GET /games/{id}/session: the response wraps the
407
+ // last PlayResult-shaped snapshot, which the SDK reads back as
408
+ // `payload.session.session` (SessionData) and `payload.session.balanceAfter`.
409
+ // Only surface it while a session is active and not yet completed —
410
+ // matches GameUseCase.GetActiveSession.
411
+ const last = this._lastPlayResult;
412
+ const session = last && last.session && !last.session.completed ? last : null;
413
+ this.delayedSend('STATE_RESPONSE', { session }, id);
278
414
  }
279
415
  handleOpenDeposit() {
280
416
  if (this._config.debug) {
@@ -1 +1 @@
1
- {"version":3,"file":"dev-bridge.esm.js","sources":["../src/dev-bridge/DevBridge.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev-bridge.esm.js","sources":["../src/dev-bridge/DevBridge.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
package/dist/index.cjs.js CHANGED
@@ -2,6 +2,57 @@
2
2
 
3
3
  var gameSdk = require('@energy8platform/game-sdk');
4
4
 
5
+ /** Default session TTL when GameDefinition.session_ttl is omitted (24h). */
6
+ const DEFAULT_SESSION_TTL_MS = 24 * 60 * 60 * 1000;
7
+ /**
8
+ * Parse a Go-style duration string ("24h", "5ms", "30s", "10m") into
9
+ * milliseconds. Mirrors GameDefinition.SessionTTLDuration on the server.
10
+ */
11
+ function parseSessionTtl(ttl) {
12
+ if (!ttl)
13
+ return DEFAULT_SESSION_TTL_MS;
14
+ const m = ttl.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)$/);
15
+ if (!m)
16
+ return DEFAULT_SESSION_TTL_MS;
17
+ const n = parseFloat(m[1]);
18
+ switch (m[2]) {
19
+ case 'ms': return n;
20
+ case 's': return n * 1000;
21
+ case 'm': return n * 60 * 1000;
22
+ case 'h': return n * 60 * 60 * 1000;
23
+ default: return DEFAULT_SESSION_TTL_MS;
24
+ }
25
+ }
26
+ /**
27
+ * Validate a bet against the game's bet_levels config — mirrors the server's
28
+ * validateBet. Levels-list takes priority over min/max range.
29
+ */
30
+ function isBetAllowed(bet, levels) {
31
+ if (!levels)
32
+ return true;
33
+ if (Array.isArray(levels)) {
34
+ return levels.includes(bet);
35
+ }
36
+ if (levels.levels && levels.levels.length > 0) {
37
+ return levels.levels.includes(bet);
38
+ }
39
+ if (levels.min !== undefined && bet < levels.min)
40
+ return false;
41
+ if (levels.max !== undefined && bet > levels.max)
42
+ return false;
43
+ return true;
44
+ }
45
+ /**
46
+ * Generate a server-style UUID for a fresh round. Falls back to a counter
47
+ * suffix if `crypto.randomUUID` isn't available (very old runtimes).
48
+ */
49
+ function generateRoundId() {
50
+ const c = globalThis.crypto;
51
+ if (c && typeof c.randomUUID === 'function')
52
+ return c.randomUUID();
53
+ // Minimal fallback — not crypto-strong, but keeps the wire shape sane.
54
+ return 'dev-' + Math.random().toString(16).slice(2) + '-' + Date.now().toString(16);
55
+ }
5
56
  const DEFAULT_CONFIG = {
6
57
  balance: 10000,
7
58
  currency: 'USD',
@@ -50,10 +101,19 @@ class DevBridge {
50
101
  _roundCounter = 0;
51
102
  _bridge = null;
52
103
  _useLuaServer;
104
+ /** Last PlayResult sent — mirrors what `GET /games/{id}/session` returns. */
105
+ _lastPlayResult = null;
106
+ /** Active session round id; non-null while a session is in progress. */
107
+ _activeRoundId = null;
108
+ /** Wall-clock expiry timestamp for the active session. */
109
+ _sessionExpiresAt = null;
110
+ /** Pre-parsed session TTL from gameDefinition.session_ttl. */
111
+ _sessionTtlMs;
53
112
  constructor(config = {}) {
54
113
  this._config = { ...DEFAULT_CONFIG, ...config };
55
114
  this._balance = this._config.balance;
56
115
  this._useLuaServer = !!(this._config.luaScript && this._config.gameDefinition);
116
+ this._sessionTtlMs = parseSessionTtl(this._config.gameDefinition?.session_ttl);
57
117
  }
58
118
  /** Current mock balance */
59
119
  get balance() {
@@ -119,26 +179,83 @@ class DevBridge {
119
179
  this.delayedSend('INIT', initData, id);
120
180
  }
121
181
  handlePlayRequest(payload, id) {
122
- const { action, bet, roundId, params } = payload;
182
+ const { action, bet, params } = payload;
123
183
  this._roundCounter++;
124
184
  if (this._useLuaServer) {
185
+ const def = this._config.gameDefinition;
186
+ // Mirror the server's INVALID_INPUT short-circuit: an unknown action
187
+ // is rejected before any wallet movement, with no PLAY_RESULT.
188
+ const actionDef = def.actions?.[action];
189
+ if (!actionDef) {
190
+ this.sendError(id, 'INVALID_INPUT', `unknown action "${action}"`);
191
+ return;
192
+ }
193
+ // Bet validation — server returns 400 INVALID_AMOUNT before the
194
+ // engine. We mirror that so games can't silently accept bad bets.
195
+ if (!isBetAllowed(bet, def.bet_levels)) {
196
+ this.sendError(id, 'INVALID_AMOUNT', `bet ${bet} is not in allowed bet_levels`);
197
+ return;
198
+ }
199
+ // Session-state guards (server: 409 ACTIVE_SESSION_EXISTS / 404 NoActiveSession / 410 ExpiredSession).
200
+ const sessionExpired = this._activeRoundId !== null &&
201
+ this._sessionExpiresAt !== null &&
202
+ Date.now() > this._sessionExpiresAt;
203
+ if (actionDef.requires_session) {
204
+ if (sessionExpired) {
205
+ this.clearSessionState();
206
+ this.sendError(id, 'SESSION_EXPIRED', 'game session has expired');
207
+ return;
208
+ }
209
+ if (this._activeRoundId === null) {
210
+ this.sendError(id, 'NO_ACTIVE_SESSION', `action "${action}" requires an active session`);
211
+ return;
212
+ }
213
+ }
214
+ else {
215
+ // Non-session action over an active (non-expired) session — server's
216
+ // acquireSession would fail with ACTIVE_SESSION_EXISTS.
217
+ if (this._activeRoundId !== null && !sessionExpired) {
218
+ this.sendError(id, 'ACTIVE_SESSION_EXISTS', 'an active game session already exists');
219
+ return;
220
+ }
221
+ if (sessionExpired) {
222
+ // Drop stale session state so a fresh non-session action can proceed.
223
+ this.clearSessionState();
224
+ }
225
+ }
125
226
  // Compute the debit amount for this action — mirrors the platform's
126
227
  // server-side rules so Buy Bonus / Ante Bet actions debit the right
127
228
  // multiple of bet instead of just the base bet.
128
229
  const debit = this.computeDebit(action, bet, params);
230
+ // Server returns 402 INSUFFICIENT_FUNDS before the wallet is touched
231
+ // and never reaches the engine. DevBridge must do the same so the
232
+ // SDK's play() rejects with the right SDKError code.
233
+ if (debit > this._balance) {
234
+ this.sendError(id, 'INSUFFICIENT_FUNDS', `insufficient funds (need ${debit}, have ${this._balance})`);
235
+ return;
236
+ }
129
237
  this._balance -= debit;
130
- this.executeLuaOnServer({ action, bet, roundId, params })
238
+ // Round id rules mirror server's playRound:
239
+ // non-session → fresh UUID, client-supplied id is ignored
240
+ // session-based → reuse the active session's round id
241
+ const serverRoundId = actionDef.requires_session
242
+ ? this._activeRoundId
243
+ : generateRoundId();
244
+ this.executeLuaOnServer({ action, bet, roundId: serverRoundId, params })
131
245
  .then((result) => {
246
+ this._lastPlayResult = result;
247
+ this.updateSessionState(result);
132
248
  this._bridge?.send('PLAY_RESULT', result, id);
133
249
  })
134
250
  .catch((err) => {
135
251
  console.error('[DevBridge] Lua server error:', err);
136
252
  this._balance += debit;
137
- this._bridge?.send('PLAY_RESULT', this.buildFallbackResult(action, bet, roundId), id);
253
+ this.sendError(id, 'ENGINE_ERROR', err?.message ?? 'lua execution failed');
138
254
  });
139
255
  }
140
256
  else {
141
257
  // Fallback to onPlay callback
258
+ const { roundId } = payload;
142
259
  const customResult = this._config.onPlay({ action, bet, roundId, params });
143
260
  const totalWin = customResult.totalWin ?? (Math.random() > 0.6 ? bet * (1 + Math.random() * 10) : 0);
144
261
  this._balance += totalWin;
@@ -155,40 +272,62 @@ class DevBridge {
155
272
  currency: this._config.currency,
156
273
  gameId: this._config.gameConfig?.id ?? 'dev-game',
157
274
  };
275
+ this._lastPlayResult = result;
158
276
  this.delayedSend('PLAY_RESULT', result, id);
159
277
  }
160
278
  }
279
+ /** Send a PLAY_ERROR correlated to the original PLAY_REQUEST id. */
280
+ sendError(id, code, message) {
281
+ this._bridge?.send('PLAY_ERROR', { code, message }, id);
282
+ }
283
+ /**
284
+ * Refresh tracked session state from the latest PlayResult.
285
+ * - new/ongoing session → remember roundId + (re)set expiry
286
+ * - completed/no session → clear tracking
287
+ */
288
+ updateSessionState(result) {
289
+ const session = result.session;
290
+ if (session && !session.completed) {
291
+ if (this._activeRoundId === null) {
292
+ this._activeRoundId = result.roundId;
293
+ this._sessionExpiresAt = Date.now() + this._sessionTtlMs;
294
+ }
295
+ }
296
+ else {
297
+ this.clearSessionState();
298
+ }
299
+ }
300
+ /** Drop active-session tracking (called on completion or expiry sweep). */
301
+ clearSessionState() {
302
+ this._activeRoundId = null;
303
+ this._sessionExpiresAt = null;
304
+ }
161
305
  /**
162
306
  * Compute the wallet debit for a play request, mirroring the platform's
163
- * server-side rules:
164
- * - debit: 'bet' → bet
307
+ * server-side ActionDefinition.DebitAmount:
308
+ * - debit: 'bet' → bet (× ante_bet.cost_multiplier when params.ante_bet=true)
165
309
  * - debit: 'buy_bonus_cost' → bet × buy_bonus.modes[mode].cost_multiplier
166
310
  * - debit: 'ante_bet_cost' → bet × ante_bet.cost_multiplier
167
- * - debit: 'none' 0 (session continuations, e.g. free spins)
311
+ * - anything else (incl. 'none', '', missing action) → 0
168
312
  *
169
- * Without a gameDefinition (or when the action is unknown), falls back to
170
- * `bet` and warns. This is the dev-mode behavior the previous
171
- * implementation always used for every action kept here as a safe
172
- * default so existing setups don't silently change semantics.
313
+ * The empty/missing default returns 0 to match the server's
314
+ * `decimal.Zero` fallback important for table-game continuations
315
+ * (e.g. blackjack `hit`/`stand`) where the action exists with no debit.
173
316
  *
174
317
  * Note: in the platform protocol the client sends the *base* bet only
175
318
  * (`PlayParams.bet`); the cost multiplier lives in the GameDefinition.
176
- * Session continuations (free_spin, feature_spin) must be invoked with
177
- * `bet: 0` — LuaEngine pulls the active session's bet from the persisted
178
- * session state.
319
+ * Session continuations must be invoked with the triggering bet — LuaEngine
320
+ * pulls the active session's bet from the persisted session state.
179
321
  */
180
322
  computeDebit(action, bet, params) {
181
323
  const def = this._config.gameDefinition;
182
324
  const actionDef = def?.actions?.[action];
183
325
  if (!def || !actionDef) {
184
- if (this._config.debug) {
185
- console.warn(`[DevBridge] Unknown action "${action}" debiting base bet as fallback.`);
186
- }
187
- return bet;
326
+ // Server short-circuits unknown actions before computing debit;
327
+ // returning 0 here keeps semantics aligned if the guard is ever bypassed.
328
+ return 0;
188
329
  }
189
330
  switch (actionDef.debit) {
190
- case 'none':
191
- return 0;
192
331
  case 'buy_bonus_cost': {
193
332
  const modeName = actionDef.buy_bonus_mode;
194
333
  const mode = modeName ? def.buy_bonus?.modes?.[modeName] : undefined;
@@ -206,8 +345,7 @@ class DevBridge {
206
345
  }
207
346
  return bet * multiplier;
208
347
  }
209
- case 'bet':
210
- default: {
348
+ case 'bet': {
211
349
  // The platform also debits ante_bet pricing on regular `bet` actions
212
350
  // when the client signals it via params.ante_bet. Mirror that here.
213
351
  if (params && params['ante_bet'] === true) {
@@ -218,6 +356,9 @@ class DevBridge {
218
356
  }
219
357
  return bet;
220
358
  }
359
+ default:
360
+ // 'none', '', or any unrecognized debit mode → 0 (server default).
361
+ return 0;
221
362
  }
222
363
  }
223
364
  async executeLuaOnServer(params) {
@@ -246,21 +387,9 @@ class DevBridge {
246
387
  data: luaResult.data,
247
388
  nextActions: luaResult.nextActions,
248
389
  session: luaResult.session,
249
- creditPending: !shouldCredit,
250
- bonusFreeSpin: null,
251
- currency: this._config.currency,
252
- gameId: this._config.gameConfig?.id ?? 'dev-game',
253
- };
254
- }
255
- buildFallbackResult(action, bet, roundId) {
256
- return {
257
- roundId: roundId ?? `dev-round-${this._roundCounter}`,
258
- action,
259
- balanceAfter: this._balance,
260
- totalWin: 0,
261
- data: { error: 'Lua execution failed' },
262
- nextActions: ['spin'],
263
- session: null,
390
+ // creditPending=true on the wire means "wallet credit failed, queued
391
+ // for retry" — not "credit deferred until session completes". DevBridge
392
+ // never simulates credit failures, so this is always false.
264
393
  creditPending: false,
265
394
  bonusFreeSpin: null,
266
395
  currency: this._config.currency,
@@ -276,7 +405,14 @@ class DevBridge {
276
405
  this.delayedSend('BALANCE_UPDATE', { balance: this._balance }, id);
277
406
  }
278
407
  handleGetState(id) {
279
- this.delayedSend('STATE_RESPONSE', { session: this._config.session ?? null }, id);
408
+ // Mirror the platform's GET /games/{id}/session: the response wraps the
409
+ // last PlayResult-shaped snapshot, which the SDK reads back as
410
+ // `payload.session.session` (SessionData) and `payload.session.balanceAfter`.
411
+ // Only surface it while a session is active and not yet completed —
412
+ // matches GameUseCase.GetActiveSession.
413
+ const last = this._lastPlayResult;
414
+ const session = last && last.session && !last.session.completed ? last : null;
415
+ this.delayedSend('STATE_RESPONSE', { session }, id);
280
416
  }
281
417
  handleOpenDeposit() {
282
418
  if (this._config.debug) {