@energy8platform/platform-core 0.16.0 → 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.
- package/README.md +35 -5
- package/dist/dev-bridge.cjs.js +223 -23
- package/dist/dev-bridge.cjs.js.map +1 -1
- package/dist/dev-bridge.d.ts +42 -1
- package/dist/dev-bridge.esm.js +223 -23
- package/dist/dev-bridge.esm.js.map +1 -1
- package/dist/index.cjs.js +223 -23
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.esm.js +223 -23
- package/dist/index.esm.js.map +1 -1
- package/dist/lua.cjs.js +89 -7
- package/dist/lua.cjs.js.map +1 -1
- package/dist/lua.d.ts +16 -3
- package/dist/lua.esm.js +89 -7
- package/dist/lua.esm.js.map +1 -1
- package/dist/simulation.d.ts +6 -0
- package/package.json +1 -1
- package/src/dev-bridge/DevBridge.ts +247 -26
- package/src/lua/LuaEngine.ts +88 -5
- package/src/lua/SessionManager.ts +23 -1
- package/src/lua/types.ts +6 -0
package/dist/dev-bridge.esm.js
CHANGED
|
@@ -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,24 +177,83 @@ class DevBridge {
|
|
|
117
177
|
this.delayedSend('INIT', initData, id);
|
|
118
178
|
}
|
|
119
179
|
handlePlayRequest(payload, id) {
|
|
120
|
-
const { action, bet,
|
|
180
|
+
const { action, bet, params } = payload;
|
|
121
181
|
this._roundCounter++;
|
|
122
182
|
if (this._useLuaServer) {
|
|
123
|
-
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
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
|
+
}
|
|
224
|
+
// Compute the debit amount for this action — mirrors the platform's
|
|
225
|
+
// server-side rules so Buy Bonus / Ante Bet actions debit the right
|
|
226
|
+
// multiple of bet instead of just the base bet.
|
|
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
|
+
}
|
|
235
|
+
this._balance -= debit;
|
|
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 })
|
|
127
243
|
.then((result) => {
|
|
244
|
+
this._lastPlayResult = result;
|
|
245
|
+
this.updateSessionState(result);
|
|
128
246
|
this._bridge?.send('PLAY_RESULT', result, id);
|
|
129
247
|
})
|
|
130
248
|
.catch((err) => {
|
|
131
249
|
console.error('[DevBridge] Lua server error:', err);
|
|
132
|
-
this._balance +=
|
|
133
|
-
this.
|
|
250
|
+
this._balance += debit;
|
|
251
|
+
this.sendError(id, 'ENGINE_ERROR', err?.message ?? 'lua execution failed');
|
|
134
252
|
});
|
|
135
253
|
}
|
|
136
254
|
else {
|
|
137
255
|
// Fallback to onPlay callback
|
|
256
|
+
const { roundId } = payload;
|
|
138
257
|
const customResult = this._config.onPlay({ action, bet, roundId, params });
|
|
139
258
|
const totalWin = customResult.totalWin ?? (Math.random() > 0.6 ? bet * (1 + Math.random() * 10) : 0);
|
|
140
259
|
this._balance += totalWin;
|
|
@@ -151,9 +270,95 @@ class DevBridge {
|
|
|
151
270
|
currency: this._config.currency,
|
|
152
271
|
gameId: this._config.gameConfig?.id ?? 'dev-game',
|
|
153
272
|
};
|
|
273
|
+
this._lastPlayResult = result;
|
|
154
274
|
this.delayedSend('PLAY_RESULT', result, id);
|
|
155
275
|
}
|
|
156
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
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Compute the wallet debit for a play request, mirroring the platform's
|
|
305
|
+
* server-side ActionDefinition.DebitAmount:
|
|
306
|
+
* - debit: 'bet' → bet (× ante_bet.cost_multiplier when params.ante_bet=true)
|
|
307
|
+
* - debit: 'buy_bonus_cost' → bet × buy_bonus.modes[mode].cost_multiplier
|
|
308
|
+
* - debit: 'ante_bet_cost' → bet × ante_bet.cost_multiplier
|
|
309
|
+
* - anything else (incl. 'none', '', missing action) → 0
|
|
310
|
+
*
|
|
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.
|
|
314
|
+
*
|
|
315
|
+
* Note: in the platform protocol the client sends the *base* bet only
|
|
316
|
+
* (`PlayParams.bet`); the cost multiplier lives in the GameDefinition.
|
|
317
|
+
* Session continuations must be invoked with the triggering bet — LuaEngine
|
|
318
|
+
* pulls the active session's bet from the persisted session state.
|
|
319
|
+
*/
|
|
320
|
+
computeDebit(action, bet, params) {
|
|
321
|
+
const def = this._config.gameDefinition;
|
|
322
|
+
const actionDef = def?.actions?.[action];
|
|
323
|
+
if (!def || !actionDef) {
|
|
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;
|
|
327
|
+
}
|
|
328
|
+
switch (actionDef.debit) {
|
|
329
|
+
case 'buy_bonus_cost': {
|
|
330
|
+
const modeName = actionDef.buy_bonus_mode;
|
|
331
|
+
const mode = modeName ? def.buy_bonus?.modes?.[modeName] : undefined;
|
|
332
|
+
if (!mode) {
|
|
333
|
+
console.warn(`[DevBridge] Action "${action}" has debit: "buy_bonus_cost" but no matching buy_bonus mode (${modeName ?? '<unset>'}). Falling back to base bet.`);
|
|
334
|
+
return bet;
|
|
335
|
+
}
|
|
336
|
+
return bet * mode.cost_multiplier;
|
|
337
|
+
}
|
|
338
|
+
case 'ante_bet_cost': {
|
|
339
|
+
const multiplier = def.ante_bet?.cost_multiplier;
|
|
340
|
+
if (typeof multiplier !== 'number') {
|
|
341
|
+
console.warn(`[DevBridge] Action "${action}" has debit: "ante_bet_cost" but no ante_bet.cost_multiplier defined. Falling back to base bet.`);
|
|
342
|
+
return bet;
|
|
343
|
+
}
|
|
344
|
+
return bet * multiplier;
|
|
345
|
+
}
|
|
346
|
+
case 'bet': {
|
|
347
|
+
// The platform also debits ante_bet pricing on regular `bet` actions
|
|
348
|
+
// when the client signals it via params.ante_bet. Mirror that here.
|
|
349
|
+
if (params && params['ante_bet'] === true) {
|
|
350
|
+
const multiplier = def.ante_bet?.cost_multiplier;
|
|
351
|
+
if (typeof multiplier === 'number') {
|
|
352
|
+
return bet * multiplier;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return bet;
|
|
356
|
+
}
|
|
357
|
+
default:
|
|
358
|
+
// 'none', '', or any unrecognized debit mode → 0 (server default).
|
|
359
|
+
return 0;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
157
362
|
async executeLuaOnServer(params) {
|
|
158
363
|
const response = await fetch('/__lua-play', {
|
|
159
364
|
method: 'POST',
|
|
@@ -180,21 +385,9 @@ class DevBridge {
|
|
|
180
385
|
data: luaResult.data,
|
|
181
386
|
nextActions: luaResult.nextActions,
|
|
182
387
|
session: luaResult.session,
|
|
183
|
-
creditPending
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
gameId: this._config.gameConfig?.id ?? 'dev-game',
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
buildFallbackResult(action, bet, roundId) {
|
|
190
|
-
return {
|
|
191
|
-
roundId: roundId ?? `dev-round-${this._roundCounter}`,
|
|
192
|
-
action,
|
|
193
|
-
balanceAfter: this._balance,
|
|
194
|
-
totalWin: 0,
|
|
195
|
-
data: { error: 'Lua execution failed' },
|
|
196
|
-
nextActions: ['spin'],
|
|
197
|
-
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.
|
|
198
391
|
creditPending: false,
|
|
199
392
|
bonusFreeSpin: null,
|
|
200
393
|
currency: this._config.currency,
|
|
@@ -210,7 +403,14 @@ class DevBridge {
|
|
|
210
403
|
this.delayedSend('BALANCE_UPDATE', { balance: this._balance }, id);
|
|
211
404
|
}
|
|
212
405
|
handleGetState(id) {
|
|
213
|
-
|
|
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);
|
|
214
414
|
}
|
|
215
415
|
handleOpenDeposit() {
|
|
216
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,24 +179,83 @@ class DevBridge {
|
|
|
119
179
|
this.delayedSend('INIT', initData, id);
|
|
120
180
|
}
|
|
121
181
|
handlePlayRequest(payload, id) {
|
|
122
|
-
const { action, bet,
|
|
182
|
+
const { action, bet, params } = payload;
|
|
123
183
|
this._roundCounter++;
|
|
124
184
|
if (this._useLuaServer) {
|
|
125
|
-
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
|
|
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
|
+
}
|
|
226
|
+
// Compute the debit amount for this action — mirrors the platform's
|
|
227
|
+
// server-side rules so Buy Bonus / Ante Bet actions debit the right
|
|
228
|
+
// multiple of bet instead of just the base bet.
|
|
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
|
+
}
|
|
237
|
+
this._balance -= debit;
|
|
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 })
|
|
129
245
|
.then((result) => {
|
|
246
|
+
this._lastPlayResult = result;
|
|
247
|
+
this.updateSessionState(result);
|
|
130
248
|
this._bridge?.send('PLAY_RESULT', result, id);
|
|
131
249
|
})
|
|
132
250
|
.catch((err) => {
|
|
133
251
|
console.error('[DevBridge] Lua server error:', err);
|
|
134
|
-
this._balance +=
|
|
135
|
-
this.
|
|
252
|
+
this._balance += debit;
|
|
253
|
+
this.sendError(id, 'ENGINE_ERROR', err?.message ?? 'lua execution failed');
|
|
136
254
|
});
|
|
137
255
|
}
|
|
138
256
|
else {
|
|
139
257
|
// Fallback to onPlay callback
|
|
258
|
+
const { roundId } = payload;
|
|
140
259
|
const customResult = this._config.onPlay({ action, bet, roundId, params });
|
|
141
260
|
const totalWin = customResult.totalWin ?? (Math.random() > 0.6 ? bet * (1 + Math.random() * 10) : 0);
|
|
142
261
|
this._balance += totalWin;
|
|
@@ -153,9 +272,95 @@ class DevBridge {
|
|
|
153
272
|
currency: this._config.currency,
|
|
154
273
|
gameId: this._config.gameConfig?.id ?? 'dev-game',
|
|
155
274
|
};
|
|
275
|
+
this._lastPlayResult = result;
|
|
156
276
|
this.delayedSend('PLAY_RESULT', result, id);
|
|
157
277
|
}
|
|
158
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
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Compute the wallet debit for a play request, mirroring the platform's
|
|
307
|
+
* server-side ActionDefinition.DebitAmount:
|
|
308
|
+
* - debit: 'bet' → bet (× ante_bet.cost_multiplier when params.ante_bet=true)
|
|
309
|
+
* - debit: 'buy_bonus_cost' → bet × buy_bonus.modes[mode].cost_multiplier
|
|
310
|
+
* - debit: 'ante_bet_cost' → bet × ante_bet.cost_multiplier
|
|
311
|
+
* - anything else (incl. 'none', '', missing action) → 0
|
|
312
|
+
*
|
|
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.
|
|
316
|
+
*
|
|
317
|
+
* Note: in the platform protocol the client sends the *base* bet only
|
|
318
|
+
* (`PlayParams.bet`); the cost multiplier lives in the GameDefinition.
|
|
319
|
+
* Session continuations must be invoked with the triggering bet — LuaEngine
|
|
320
|
+
* pulls the active session's bet from the persisted session state.
|
|
321
|
+
*/
|
|
322
|
+
computeDebit(action, bet, params) {
|
|
323
|
+
const def = this._config.gameDefinition;
|
|
324
|
+
const actionDef = def?.actions?.[action];
|
|
325
|
+
if (!def || !actionDef) {
|
|
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;
|
|
329
|
+
}
|
|
330
|
+
switch (actionDef.debit) {
|
|
331
|
+
case 'buy_bonus_cost': {
|
|
332
|
+
const modeName = actionDef.buy_bonus_mode;
|
|
333
|
+
const mode = modeName ? def.buy_bonus?.modes?.[modeName] : undefined;
|
|
334
|
+
if (!mode) {
|
|
335
|
+
console.warn(`[DevBridge] Action "${action}" has debit: "buy_bonus_cost" but no matching buy_bonus mode (${modeName ?? '<unset>'}). Falling back to base bet.`);
|
|
336
|
+
return bet;
|
|
337
|
+
}
|
|
338
|
+
return bet * mode.cost_multiplier;
|
|
339
|
+
}
|
|
340
|
+
case 'ante_bet_cost': {
|
|
341
|
+
const multiplier = def.ante_bet?.cost_multiplier;
|
|
342
|
+
if (typeof multiplier !== 'number') {
|
|
343
|
+
console.warn(`[DevBridge] Action "${action}" has debit: "ante_bet_cost" but no ante_bet.cost_multiplier defined. Falling back to base bet.`);
|
|
344
|
+
return bet;
|
|
345
|
+
}
|
|
346
|
+
return bet * multiplier;
|
|
347
|
+
}
|
|
348
|
+
case 'bet': {
|
|
349
|
+
// The platform also debits ante_bet pricing on regular `bet` actions
|
|
350
|
+
// when the client signals it via params.ante_bet. Mirror that here.
|
|
351
|
+
if (params && params['ante_bet'] === true) {
|
|
352
|
+
const multiplier = def.ante_bet?.cost_multiplier;
|
|
353
|
+
if (typeof multiplier === 'number') {
|
|
354
|
+
return bet * multiplier;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return bet;
|
|
358
|
+
}
|
|
359
|
+
default:
|
|
360
|
+
// 'none', '', or any unrecognized debit mode → 0 (server default).
|
|
361
|
+
return 0;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
159
364
|
async executeLuaOnServer(params) {
|
|
160
365
|
const response = await fetch('/__lua-play', {
|
|
161
366
|
method: 'POST',
|
|
@@ -182,21 +387,9 @@ class DevBridge {
|
|
|
182
387
|
data: luaResult.data,
|
|
183
388
|
nextActions: luaResult.nextActions,
|
|
184
389
|
session: luaResult.session,
|
|
185
|
-
creditPending
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
gameId: this._config.gameConfig?.id ?? 'dev-game',
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
buildFallbackResult(action, bet, roundId) {
|
|
192
|
-
return {
|
|
193
|
-
roundId: roundId ?? `dev-round-${this._roundCounter}`,
|
|
194
|
-
action,
|
|
195
|
-
balanceAfter: this._balance,
|
|
196
|
-
totalWin: 0,
|
|
197
|
-
data: { error: 'Lua execution failed' },
|
|
198
|
-
nextActions: ['spin'],
|
|
199
|
-
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.
|
|
200
393
|
creditPending: false,
|
|
201
394
|
bonusFreeSpin: null,
|
|
202
395
|
currency: this._config.currency,
|
|
@@ -212,7 +405,14 @@ class DevBridge {
|
|
|
212
405
|
this.delayedSend('BALANCE_UPDATE', { balance: this._balance }, id);
|
|
213
406
|
}
|
|
214
407
|
handleGetState(id) {
|
|
215
|
-
|
|
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);
|
|
216
416
|
}
|
|
217
417
|
handleOpenDeposit() {
|
|
218
418
|
if (this._config.debug) {
|