@hizi.io/engine-sdk 0.1.9

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.
Files changed (64) hide show
  1. package/README.md +212 -0
  2. package/lib/api.d.ts +198 -0
  3. package/lib/api.js +352 -0
  4. package/lib/constants.d.ts +44 -0
  5. package/lib/constants.js +56 -0
  6. package/lib/index.d.ts +7 -0
  7. package/lib/index.js +37 -0
  8. package/lib/network.d.ts +9 -0
  9. package/lib/network.js +63 -0
  10. package/lib/types/balance.d.ts +20 -0
  11. package/lib/types/balance.js +2 -0
  12. package/lib/types/blackjack.d.ts +163 -0
  13. package/lib/types/blackjack.js +22 -0
  14. package/lib/types/buyFeatureOption.d.ts +11 -0
  15. package/lib/types/buyFeatureOption.js +2 -0
  16. package/lib/types/collectOptions.d.ts +8 -0
  17. package/lib/types/collectOptions.js +2 -0
  18. package/lib/types/crash.d.ts +223 -0
  19. package/lib/types/crash.js +80 -0
  20. package/lib/types/freePlayInfo.d.ts +11 -0
  21. package/lib/types/freePlayInfo.js +2 -0
  22. package/lib/types/gameResult.d.ts +48 -0
  23. package/lib/types/gameResult.js +2 -0
  24. package/lib/types/gameRoundInfo.d.ts +19 -0
  25. package/lib/types/gameRoundInfo.js +2 -0
  26. package/lib/types/gameSettings.d.ts +133 -0
  27. package/lib/types/gameSettings.js +16 -0
  28. package/lib/types/gameState.d.ts +20 -0
  29. package/lib/types/gameState.js +2 -0
  30. package/lib/types/index.d.ts +32 -0
  31. package/lib/types/index.js +22 -0
  32. package/lib/types/keno.d.ts +34 -0
  33. package/lib/types/keno.js +18 -0
  34. package/lib/types/loadConfigConfig.d.ts +42 -0
  35. package/lib/types/loadConfigConfig.js +2 -0
  36. package/lib/types/loginOptions.d.ts +7 -0
  37. package/lib/types/loginOptions.js +2 -0
  38. package/lib/types/mines.d.ts +26 -0
  39. package/lib/types/mines.js +19 -0
  40. package/lib/types/network.d.ts +24 -0
  41. package/lib/types/network.js +2 -0
  42. package/lib/types/pfVerifyOptions.d.ts +48 -0
  43. package/lib/types/pfVerifyOptions.js +2 -0
  44. package/lib/types/placeBetOptions.d.ts +16 -0
  45. package/lib/types/placeBetOptions.js +2 -0
  46. package/lib/types/progressionCounter.d.ts +65 -0
  47. package/lib/types/progressionCounter.js +2 -0
  48. package/lib/types/replies.d.ts +107 -0
  49. package/lib/types/replies.js +2 -0
  50. package/lib/types/roulette.d.ts +53 -0
  51. package/lib/types/roulette.js +11 -0
  52. package/lib/types/scenarioInfo.d.ts +12 -0
  53. package/lib/types/scenarioInfo.js +2 -0
  54. package/lib/types/sessionOptions.d.ts +7 -0
  55. package/lib/types/sessionOptions.js +2 -0
  56. package/lib/types/spinAward.d.ts +31 -0
  57. package/lib/types/spinAward.js +12 -0
  58. package/lib/types/spinInfo.d.ts +9 -0
  59. package/lib/types/spinInfo.js +2 -0
  60. package/lib/types/tokenData.d.ts +7 -0
  61. package/lib/types/tokenData.js +2 -0
  62. package/lib/websocket.d.ts +27 -0
  63. package/lib/websocket.js +186 -0
  64. package/package.json +19 -0
package/lib/api.js ADDED
@@ -0,0 +1,352 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.login = login;
4
+ exports.loadConfig = loadConfig;
5
+ exports.placeBet = placeBet;
6
+ exports.collect = collect;
7
+ exports.pfVerify = pfVerify;
8
+ exports.refresh = refresh;
9
+ exports.reportAnimationEnd = reportAnimationEnd;
10
+ exports.updateBalance = updateBalance;
11
+ exports.getFreePlaysRemaining = getFreePlaysRemaining;
12
+ exports.getFreePlayStake = getFreePlayStake;
13
+ const constants_js_1 = require("./constants.js");
14
+ const network_js_1 = require("./network.js");
15
+ /** Parse an error response from login/refresh endpoints. */
16
+ function parseErrorResponse(data, statusText) {
17
+ return {
18
+ success: false,
19
+ error: {
20
+ code: String(data?.errorId ?? data?.code ?? constants_js_1.API_RETURNCODES.UNEXPECTED),
21
+ message: (data?.errorText ?? data?.message ?? statusText),
22
+ ...(data?.passThroughData !== undefined && data?.passThroughData !== 'undefined' ? { passThroughData: data.passThroughData } : {}),
23
+ },
24
+ };
25
+ }
26
+ /** Parse a connect reply (used by both login and refresh). */
27
+ function parseConnectReply(data) {
28
+ return {
29
+ token: data.token,
30
+ backendURL: (data.backendUrl ?? data.backendURL),
31
+ refreshURL: (data.refreshUrl ?? data.refreshURL),
32
+ logoutURL: (data.logoutUrl ?? data.logoutURL),
33
+ webSocketURL: (data.webSocketUrl ?? data.webSocketURL),
34
+ balance: data.balance,
35
+ gameSettings: data.gameSettings,
36
+ tokenData: data.tokenData,
37
+ freePlaysAvailable: data.freePlaysAvailable,
38
+ };
39
+ }
40
+ /**
41
+ * Exchange a launch token for a session token.
42
+ *
43
+ * The `loginURL` and `launchToken` are provided as URL query parameters
44
+ * when the game is launched by the operator.
45
+ *
46
+ * @param options - Login credentials from the launch URL.
47
+ * @param options.loginURL - The operator-provided login endpoint URL.
48
+ * @param options.launchToken - Short-lived token from the launch URL query string.
49
+ * @returns A session token, backend URL, and platform settings on success.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const response = await login({ loginURL, launchToken });
54
+ * if (response.success) {
55
+ * const { token, backendURL } = response.result;
56
+ * }
57
+ * ```
58
+ */
59
+ async function login(options) {
60
+ try {
61
+ const url = new URL(options.loginURL);
62
+ url.searchParams.set('token', options.launchToken);
63
+ const response = await fetch(url.href, {
64
+ method: 'GET',
65
+ headers: { Accept: 'application/json' },
66
+ signal: AbortSignal.timeout(constants_js_1.defaultNetworkTimeout),
67
+ });
68
+ const data = await response.json();
69
+ if (!response.ok) {
70
+ return parseErrorResponse(data, response.statusText);
71
+ }
72
+ return { success: true, result: parseConnectReply(data) };
73
+ }
74
+ catch (error) {
75
+ return {
76
+ success: false,
77
+ error: {
78
+ code: String(constants_js_1.API_RETURNCODES.NETWORKERROR),
79
+ message: error instanceof Error ? error.message : 'Network error',
80
+ },
81
+ };
82
+ }
83
+ }
84
+ /**
85
+ * Load the game configuration including available stakes, RTP, and buy features.
86
+ *
87
+ * Call this once after {@link login} to retrieve the game's configuration before
88
+ * placing any bets. If a previous round was interrupted, the response includes
89
+ * `gameResult` and `amountToCollect` for resumption.
90
+ *
91
+ * @param options - Session credentials from the login response.
92
+ * @param options.backendURL - Backend URL from the login response.
93
+ * @param options.token - Session token.
94
+ * @returns Game configuration, balance, and any in-progress round data.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const response = await loadConfig({ backendURL, token });
99
+ * if (response.success) {
100
+ * const { stakes, rtp, buyFeatures } = response.result.config;
101
+ * }
102
+ * ```
103
+ */
104
+ async function loadConfig(options) {
105
+ return (0, network_js_1.request)(options.backendURL, {
106
+ op: 'loadConfig',
107
+ token: options.token,
108
+ });
109
+ }
110
+ /**
111
+ * Place a bet and receive a game result, or continue an in-progress round.
112
+ *
113
+ * - **New spin** — pass the desired `stake` amount.
114
+ * - **Continue round** — omit `stake` when `engineData.inProgress` is `true`.
115
+ * - **Buy feature** — pass `featureToBuy` to enter a bonus directly (engine computes the price).
116
+ * - **Player choice** — pass `playerChoiceIndex` when `engineData.playerChoice` is set.
117
+ *
118
+ * @param options - Bet parameters.
119
+ * @param options.backendURL - Backend URL from the login response.
120
+ * @param options.token - Session token.
121
+ * @param options.stake - Stake amount in minor currency units. Required for the first call of a game round.
122
+ * @param options.featureToBuy - Buy-feature ID (e.g. `'freespin'`).
123
+ * @param options.playerChoiceIndex - Index of the selected option when `engineData.playerChoice` is set.
124
+ * @param options.useTicket - Set `true` to consume a free play ticket.
125
+ * @param options.useTicketFeatureType - Feature type of the free play ticket.
126
+ * @param options.additionalData - Additional game-specific parameters.
127
+ * @returns The game result including scenario data, engine state, and cumulative win.
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * // New spin
132
+ * const response = await placeBet({ backendURL, token, stake });
133
+ *
134
+ * // Buy feature
135
+ * const response = await placeBet({ backendURL, token, stake, featureToBuy: 'freespin' });
136
+ *
137
+ * // Continue round
138
+ * const response = await placeBet({ backendURL, token });
139
+ * ```
140
+ */
141
+ async function placeBet(options) {
142
+ const { backendURL, token, stake, useTicket, useTicketFeatureType, featureToBuy, playerChoiceIndex, additionalData } = options;
143
+ const body = {
144
+ ...additionalData,
145
+ op: 'placeBet',
146
+ token,
147
+ };
148
+ if (stake !== undefined)
149
+ body.stake = stake;
150
+ if (useTicket !== undefined)
151
+ body.useTicket = useTicket;
152
+ if (useTicketFeatureType !== undefined)
153
+ body.useTicketFeatureType = useTicketFeatureType;
154
+ if (featureToBuy !== undefined)
155
+ body.featureToBuy = featureToBuy;
156
+ if (playerChoiceIndex !== undefined)
157
+ body.playerChoiceIndex = playerChoiceIndex;
158
+ return (0, network_js_1.request)(backendURL, body);
159
+ }
160
+ /**
161
+ * Collect winnings after a completed round.
162
+ *
163
+ * Only available for games with wager features (`config.wagerFeatures` is present).
164
+ * Games without wager features auto-end the round and credit winnings automatically.
165
+ *
166
+ * @param options - Session credentials and optional partial amount.
167
+ * @param options.backendURL - Backend URL from the login response.
168
+ * @param options.token - Session token.
169
+ * @param options.amount - Amount to collect. Omit to collect the full available amount.
170
+ * @returns The credited amount and updated balance.
171
+ * @throws When called on a game without wager features, or when no winnings are available.
172
+ *
173
+ * @example
174
+ * ```ts
175
+ * if (gameResult.engineData.canCollect) {
176
+ * const response = await collect({ backendURL, token });
177
+ * }
178
+ * ```
179
+ */
180
+ async function collect(options) {
181
+ const body = {
182
+ ...options.additionalData,
183
+ op: 'collect',
184
+ token: options.token,
185
+ };
186
+ if (options.amount !== undefined)
187
+ body.collectAmount = options.amount;
188
+ return (0, network_js_1.request)(options.backendURL, body);
189
+ }
190
+ /**
191
+ * Re-run a past round against its revealed PF seeds and get back the
192
+ * engine's offline replay — the per-call RNG audit (`rngData`) and the
193
+ * per-step game outcomes (`steps`) — so the caller can diff them against
194
+ * what they recorded live.
195
+ *
196
+ * Only meaningful for rounds played with `config.rng === 'pf'`. The
197
+ * endpoint never touches the wallet, progression counters, or operator
198
+ * caps; it's pure compute.
199
+ *
200
+ * Two checks make up a passing verification:
201
+ *
202
+ * 1. **Audit replay** — `reply.rngData` matches the live `pf.rngData`
203
+ * element-wise. A swapped server seed would yield different draws, so
204
+ * this transitively proves the revealed seed is the one committed to.
205
+ * 2. **Result replay** — `reply.steps[i].scenario` / `totalWin` match the
206
+ * live round at each step. The terminal step is `steps[steps.length - 1]`.
207
+ *
208
+ * @param options - Verify parameters; see {@link IPfVerifyOptions}.
209
+ * @param options.backendURL - Backend URL from the login response.
210
+ * @param options.token - Session token (used to resolve the game config).
211
+ * @param options.serverSeed - Revealed server seed from the round's `pf` block.
212
+ * @param options.clientSeed - Client seed bound to the round.
213
+ * @param options.startNonce - Defaults to `0`. Set when the round opened mid-PF-session.
214
+ * @param options.stake - Stake the round opened with (required by games that need it to settle).
215
+ * @param options.featureToBuy - Buy-feature id the round opened on, if any.
216
+ * @param options.initialData - Mirror the round's opening payload (blackjack side bets, …).
217
+ * @param options.bets - Roulette / crash opening bets.
218
+ * @param options.playerNumbers - Keno picks, if the player chose their own.
219
+ * @param options.actions - Continuation actions in order; shape per game (see {@link IPfVerifyAction}).
220
+ *
221
+ * @example
222
+ * ```ts
223
+ * // Verify a one-shot roulette round.
224
+ * const reply = await pfVerify({
225
+ * backendURL, token,
226
+ * serverSeed: pf.revealedServerSeed,
227
+ * clientSeed: pf.clientSeed,
228
+ * stake: 200,
229
+ * bets: [{ type: 'straight', selection: 17, stake: 100 }, { type: 'red', stake: 100 }],
230
+ * });
231
+ * if (reply.success) {
232
+ * const rngOk = deepEqual(reply.result.rngData, pf.rngData);
233
+ * const pocketOk = (reply.result.steps[0].scenario as { pocket: number }).pocket === liveScenario.pocket;
234
+ * }
235
+ * ```
236
+ */
237
+ async function pfVerify(options) {
238
+ const { backendURL, token, serverSeed, clientSeed, startNonce, stake, featureToBuy, initialData, bets, playerNumbers, actions } = options;
239
+ const body = { op: 'pfVerify', token, serverSeed, clientSeed };
240
+ // Engine defaults startNonce to 0 when omitted; only spend bytes when non-zero.
241
+ if (startNonce !== undefined && startNonce > 0)
242
+ body.startNonce = startNonce;
243
+ if (stake !== undefined)
244
+ body.stake = stake;
245
+ if (featureToBuy !== undefined)
246
+ body.featureToBuy = featureToBuy;
247
+ if (initialData !== undefined)
248
+ body.initialData = initialData;
249
+ if (bets !== undefined)
250
+ body.bets = bets;
251
+ if (playerNumbers !== undefined)
252
+ body.playerNumbers = playerNumbers;
253
+ if (actions !== undefined)
254
+ body.actions = actions;
255
+ return (0, network_js_1.request)(backendURL, body);
256
+ }
257
+ /**
258
+ * Refresh the session token when it expires.
259
+ *
260
+ * Call this when API requests start returning `SESSIONINVALID` or `NOTLOGGEDON`
261
+ * errors. The new session token and URLs are returned in the response.
262
+ *
263
+ * @param refreshURL - The refresh endpoint URL from the {@link login} response (`result.refreshURL`).
264
+ * @returns A new session token and updated platform info.
265
+ *
266
+ * @example
267
+ * ```ts
268
+ * const response = await refresh(refreshURL);
269
+ * if (response.success) {
270
+ * token = response.result.token;
271
+ * }
272
+ * ```
273
+ */
274
+ async function refresh(refreshURL) {
275
+ try {
276
+ const response = await fetch(refreshURL, {
277
+ method: 'GET',
278
+ headers: { 'Content-Type': 'application/json' },
279
+ signal: AbortSignal.timeout(constants_js_1.defaultNetworkTimeout),
280
+ });
281
+ const data = await response.json();
282
+ if (!response.ok) {
283
+ return parseErrorResponse(data, response.statusText);
284
+ }
285
+ return { success: true, result: parseConnectReply(data) };
286
+ }
287
+ catch (error) {
288
+ return {
289
+ success: false,
290
+ error: {
291
+ code: String(constants_js_1.API_RETURNCODES.NETWORKERROR),
292
+ message: error instanceof Error ? error.message : 'Network error',
293
+ },
294
+ };
295
+ }
296
+ }
297
+ /**
298
+ * Report that the game animation has finished playing.
299
+ *
300
+ * Only needed when `gameSettings.reportAnimationEnd` is `true` (set by the operator).
301
+ * Call this after your spin/win animation completes.
302
+ *
303
+ * @param options - Session credentials.
304
+ * @param options.backendURL - Backend URL from the login response.
305
+ * @param options.token - Session token.
306
+ */
307
+ async function reportAnimationEnd(options) {
308
+ return (0, network_js_1.request)(options.backendURL, {
309
+ op: 'reportAnimationEnd',
310
+ token: options.token,
311
+ });
312
+ }
313
+ /**
314
+ * Request an updated balance from the server.
315
+ *
316
+ * Use this to refresh the displayed balance outside of the normal
317
+ * `placeBet`/`collect` flow (e.g. after an external deposit).
318
+ *
319
+ * @param options - Session credentials.
320
+ * @param options.backendURL - Backend URL from the login response.
321
+ * @param options.token - Session token.
322
+ * @returns The player's current balance.
323
+ */
324
+ async function updateBalance(options) {
325
+ return (0, network_js_1.request)(options.backendURL, {
326
+ op: 'updateBalance',
327
+ token: options.token,
328
+ });
329
+ }
330
+ // ---- Helper Functions ----
331
+ /**
332
+ * Get the total number of free plays remaining.
333
+ *
334
+ * @param freePlaysAvailable - The `freePlaysAvailable` array from a `loadConfig` or `placeBet` response.
335
+ * @returns Total free play count across all entries, or `0` if none available.
336
+ */
337
+ function getFreePlaysRemaining(freePlaysAvailable) {
338
+ if (!freePlaysAvailable)
339
+ return 0;
340
+ return freePlaysAvailable.reduce((total, fp) => total + fp.count, 0);
341
+ }
342
+ /**
343
+ * Get the stake amount for available free plays.
344
+ *
345
+ * @param freePlaysAvailable - The `freePlaysAvailable` array from a `loadConfig` or `placeBet` response.
346
+ * @returns The first free play's stake amount, or `undefined` if none available.
347
+ */
348
+ function getFreePlayStake(freePlaysAvailable) {
349
+ if (!freePlaysAvailable || freePlaysAvailable.length === 0)
350
+ return undefined;
351
+ return freePlaysAvailable[0].stake;
352
+ }
@@ -0,0 +1,44 @@
1
+ /** Error codes returned by the Hizi RGS platform. */
2
+ export declare enum API_RETURNCODES {
3
+ SUCCESS = 0,
4
+ PLAYERNOTFOUND = 1,
5
+ PLAYERBLOCKED = 2,
6
+ BALANCETOOLOW = 10,
7
+ BETLIMITREACHED = 11,
8
+ GAMEROUNDALREADYSTARTED = 12,
9
+ GAMEROUNDNOTACTIVE = 13,
10
+ GAMEROUNDNOTFOUND = 14,
11
+ GAMEROUNDNOTSTARTED = 15,
12
+ TRANSACTIONCOUNTWRONG = 16,
13
+ GAMEROUNDPLAYERMISMATCH = 17,
14
+ CURRENCYINVALID = 18,
15
+ INVALIDPARAMETER = 19,
16
+ TRANSACTIONAFTEREND = 20,
17
+ GAMEROUNDISLOCKED = 21,
18
+ GAMEROUNDISCLOSING = 22,
19
+ SPINNOTAVAILABLE = 23,
20
+ COOLOFFPERIODACTIVE = 25,
21
+ NOTLOGGEDON = 29,
22
+ RESPONSIBLEGAMINGLIMITREACHED = 30,
23
+ RESPONSIBLESGAMINGSESSIONEXPIRED = 31,
24
+ PLAYERNOAUTHENTICATED = 32,
25
+ GENERICBETERROR = 34,
26
+ GENERICWINERROR = 35,
27
+ OPERATIONBEINGPROCESSED = 36,
28
+ REALITYCHECK = 38,
29
+ SIGNATUREWRONG = 1001,
30
+ PARAMETERMISSING = 1004,
31
+ GAMECODENOTFOUND = 1006,
32
+ SESSIONINVALID = 1008,
33
+ RNGFAILURE = 1009,
34
+ NETWORKERROR = 1010,
35
+ RATELIMITEXCEEDED = 1300,
36
+ UNEXPECTED = -1
37
+ }
38
+ /**
39
+ * Error codes that can be retried (e.g. balance too low, rate limit, network error).
40
+ * Use this to decide whether to show a retry option or a fatal error screen.
41
+ */
42
+ export declare const recoverableErrorCodes: string[];
43
+ /** Default timeout for HTTP and WebSocket requests, in milliseconds. */
44
+ export declare const defaultNetworkTimeout = 30000;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultNetworkTimeout = exports.recoverableErrorCodes = exports.API_RETURNCODES = void 0;
4
+ /** Error codes returned by the Hizi RGS platform. */
5
+ var API_RETURNCODES;
6
+ (function (API_RETURNCODES) {
7
+ API_RETURNCODES[API_RETURNCODES["SUCCESS"] = 0] = "SUCCESS";
8
+ API_RETURNCODES[API_RETURNCODES["PLAYERNOTFOUND"] = 1] = "PLAYERNOTFOUND";
9
+ API_RETURNCODES[API_RETURNCODES["PLAYERBLOCKED"] = 2] = "PLAYERBLOCKED";
10
+ API_RETURNCODES[API_RETURNCODES["BALANCETOOLOW"] = 10] = "BALANCETOOLOW";
11
+ API_RETURNCODES[API_RETURNCODES["BETLIMITREACHED"] = 11] = "BETLIMITREACHED";
12
+ API_RETURNCODES[API_RETURNCODES["GAMEROUNDALREADYSTARTED"] = 12] = "GAMEROUNDALREADYSTARTED";
13
+ API_RETURNCODES[API_RETURNCODES["GAMEROUNDNOTACTIVE"] = 13] = "GAMEROUNDNOTACTIVE";
14
+ API_RETURNCODES[API_RETURNCODES["GAMEROUNDNOTFOUND"] = 14] = "GAMEROUNDNOTFOUND";
15
+ API_RETURNCODES[API_RETURNCODES["GAMEROUNDNOTSTARTED"] = 15] = "GAMEROUNDNOTSTARTED";
16
+ API_RETURNCODES[API_RETURNCODES["TRANSACTIONCOUNTWRONG"] = 16] = "TRANSACTIONCOUNTWRONG";
17
+ API_RETURNCODES[API_RETURNCODES["GAMEROUNDPLAYERMISMATCH"] = 17] = "GAMEROUNDPLAYERMISMATCH";
18
+ API_RETURNCODES[API_RETURNCODES["CURRENCYINVALID"] = 18] = "CURRENCYINVALID";
19
+ API_RETURNCODES[API_RETURNCODES["INVALIDPARAMETER"] = 19] = "INVALIDPARAMETER";
20
+ API_RETURNCODES[API_RETURNCODES["TRANSACTIONAFTEREND"] = 20] = "TRANSACTIONAFTEREND";
21
+ API_RETURNCODES[API_RETURNCODES["GAMEROUNDISLOCKED"] = 21] = "GAMEROUNDISLOCKED";
22
+ API_RETURNCODES[API_RETURNCODES["GAMEROUNDISCLOSING"] = 22] = "GAMEROUNDISCLOSING";
23
+ API_RETURNCODES[API_RETURNCODES["SPINNOTAVAILABLE"] = 23] = "SPINNOTAVAILABLE";
24
+ API_RETURNCODES[API_RETURNCODES["COOLOFFPERIODACTIVE"] = 25] = "COOLOFFPERIODACTIVE";
25
+ API_RETURNCODES[API_RETURNCODES["NOTLOGGEDON"] = 29] = "NOTLOGGEDON";
26
+ API_RETURNCODES[API_RETURNCODES["RESPONSIBLEGAMINGLIMITREACHED"] = 30] = "RESPONSIBLEGAMINGLIMITREACHED";
27
+ API_RETURNCODES[API_RETURNCODES["RESPONSIBLESGAMINGSESSIONEXPIRED"] = 31] = "RESPONSIBLESGAMINGSESSIONEXPIRED";
28
+ API_RETURNCODES[API_RETURNCODES["PLAYERNOAUTHENTICATED"] = 32] = "PLAYERNOAUTHENTICATED";
29
+ API_RETURNCODES[API_RETURNCODES["GENERICBETERROR"] = 34] = "GENERICBETERROR";
30
+ API_RETURNCODES[API_RETURNCODES["GENERICWINERROR"] = 35] = "GENERICWINERROR";
31
+ API_RETURNCODES[API_RETURNCODES["OPERATIONBEINGPROCESSED"] = 36] = "OPERATIONBEINGPROCESSED";
32
+ API_RETURNCODES[API_RETURNCODES["REALITYCHECK"] = 38] = "REALITYCHECK";
33
+ API_RETURNCODES[API_RETURNCODES["SIGNATUREWRONG"] = 1001] = "SIGNATUREWRONG";
34
+ API_RETURNCODES[API_RETURNCODES["PARAMETERMISSING"] = 1004] = "PARAMETERMISSING";
35
+ API_RETURNCODES[API_RETURNCODES["GAMECODENOTFOUND"] = 1006] = "GAMECODENOTFOUND";
36
+ API_RETURNCODES[API_RETURNCODES["SESSIONINVALID"] = 1008] = "SESSIONINVALID";
37
+ API_RETURNCODES[API_RETURNCODES["RNGFAILURE"] = 1009] = "RNGFAILURE";
38
+ API_RETURNCODES[API_RETURNCODES["NETWORKERROR"] = 1010] = "NETWORKERROR";
39
+ API_RETURNCODES[API_RETURNCODES["RATELIMITEXCEEDED"] = 1300] = "RATELIMITEXCEEDED";
40
+ API_RETURNCODES[API_RETURNCODES["UNEXPECTED"] = -1] = "UNEXPECTED";
41
+ })(API_RETURNCODES || (exports.API_RETURNCODES = API_RETURNCODES = {}));
42
+ /**
43
+ * Error codes that can be retried (e.g. balance too low, rate limit, network error).
44
+ * Use this to decide whether to show a retry option or a fatal error screen.
45
+ */
46
+ exports.recoverableErrorCodes = [
47
+ API_RETURNCODES.BALANCETOOLOW,
48
+ API_RETURNCODES.BETLIMITREACHED,
49
+ API_RETURNCODES.NETWORKERROR,
50
+ API_RETURNCODES.RATELIMITEXCEEDED,
51
+ API_RETURNCODES.GENERICBETERROR,
52
+ API_RETURNCODES.RNGFAILURE,
53
+ API_RETURNCODES.OPERATIONBEINGPROCESSED,
54
+ ].map(String);
55
+ /** Default timeout for HTTP and WebSocket requests, in milliseconds. */
56
+ exports.defaultNetworkTimeout = 30000;
package/lib/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { login, loadConfig, placeBet, collect, pfVerify, refresh, reportAnimationEnd, updateBalance, getFreePlaysRemaining, getFreePlayStake } from './api.js';
2
+ export { enableWebSockets } from './websocket.js';
3
+ export type { WebSocketHandler } from './websocket.js';
4
+ export type { TNetworkResponse, TNetworkSuccess, TNetworkError, IErrorResponse, IBalanceEntry, IBalanceReply, IGameSettings, ITokenData, IGameState, IGameRoundInfo, IFreePlayInfo, IScenarioInfo, ISpinInfo, TPlayerChoiceFeatureAward, TPlayerChoiceCashAward, TPlayerChoiceAward, IGameResult, IBuyFeatureOption, ILoadConfigConfig, IProgressionCounterConfig, IProgressionEvent, TRandomChoiceAward, TRandomChoiceFeatureAward, TRandomChoiceCashAward, TProgressionAwarded, IConnectReply, ILoadConfigReply, IPlaceBetReply, ICollectReply, ISessionOptions, ILoginOptions, IPlaceBetOptions, ICollectOptions, IPfVerifyOptions, IPfVerifyAction, IPfVerifyReply, IRngDataEntry, TRouletteBetType, TRouletteBetSelection, TRouletteEvenMoneyBetType, IRouletteBet, IRouletteBetSettlement, IRouletteScenario, TBlackjackRank, TBlackjackSuit, IBlackjackCard, TBlackjackAction, TBlackjackActionKind, IBlackjackSideBets, IBlackjackInitialBet, IBlackjackChoice, IBlackjackHand, IBlackjackDealer, IBlackjackPerfectPairsBet, IBlackjackTwentyOnePlusThreeBet, IBlackjackInsuranceBet, IBlackjackScenario, ICrashBetRequest, ICrashBet, ICrashScenario, ICrashLoadConfig, TCrashEventName, ICrashRoundStartedPayload, ICrashRoundTickPayload, ICrashBetCashedOutPayload, ICrashRoundEndedPayload, ICrashBalanceUpdatedPayload, TCrashEvent, TMinesTile, IMinesScenario, IKenoScenario, } from './types/index.js';
5
+ export { rouletteAdditionalData, blackjackInitialData, blackjackActionData, CRASH_EVENTS, crashPlaceBetData, crashCollectData, minesPickData, kenoPickData, } from './types/index.js';
6
+ export { isCashChoice, isFeatureChoice } from './types/index.js';
7
+ export { API_RETURNCODES, recoverableErrorCodes, defaultNetworkTimeout } from './constants.js';
package/lib/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultNetworkTimeout = exports.recoverableErrorCodes = exports.API_RETURNCODES = exports.isFeatureChoice = exports.isCashChoice = exports.kenoPickData = exports.minesPickData = exports.crashCollectData = exports.crashPlaceBetData = exports.CRASH_EVENTS = exports.blackjackActionData = exports.blackjackInitialData = exports.rouletteAdditionalData = exports.enableWebSockets = exports.getFreePlayStake = exports.getFreePlaysRemaining = exports.updateBalance = exports.reportAnimationEnd = exports.refresh = exports.pfVerify = exports.collect = exports.placeBet = exports.loadConfig = exports.login = void 0;
4
+ // API functions
5
+ var api_js_1 = require("./api.js");
6
+ Object.defineProperty(exports, "login", { enumerable: true, get: function () { return api_js_1.login; } });
7
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return api_js_1.loadConfig; } });
8
+ Object.defineProperty(exports, "placeBet", { enumerable: true, get: function () { return api_js_1.placeBet; } });
9
+ Object.defineProperty(exports, "collect", { enumerable: true, get: function () { return api_js_1.collect; } });
10
+ Object.defineProperty(exports, "pfVerify", { enumerable: true, get: function () { return api_js_1.pfVerify; } });
11
+ Object.defineProperty(exports, "refresh", { enumerable: true, get: function () { return api_js_1.refresh; } });
12
+ Object.defineProperty(exports, "reportAnimationEnd", { enumerable: true, get: function () { return api_js_1.reportAnimationEnd; } });
13
+ Object.defineProperty(exports, "updateBalance", { enumerable: true, get: function () { return api_js_1.updateBalance; } });
14
+ Object.defineProperty(exports, "getFreePlaysRemaining", { enumerable: true, get: function () { return api_js_1.getFreePlaysRemaining; } });
15
+ Object.defineProperty(exports, "getFreePlayStake", { enumerable: true, get: function () { return api_js_1.getFreePlayStake; } });
16
+ // WebSocket
17
+ var websocket_js_1 = require("./websocket.js");
18
+ Object.defineProperty(exports, "enableWebSockets", { enumerable: true, get: function () { return websocket_js_1.enableWebSockets; } });
19
+ // Game-specific helpers
20
+ var index_js_1 = require("./types/index.js");
21
+ Object.defineProperty(exports, "rouletteAdditionalData", { enumerable: true, get: function () { return index_js_1.rouletteAdditionalData; } });
22
+ Object.defineProperty(exports, "blackjackInitialData", { enumerable: true, get: function () { return index_js_1.blackjackInitialData; } });
23
+ Object.defineProperty(exports, "blackjackActionData", { enumerable: true, get: function () { return index_js_1.blackjackActionData; } });
24
+ Object.defineProperty(exports, "CRASH_EVENTS", { enumerable: true, get: function () { return index_js_1.CRASH_EVENTS; } });
25
+ Object.defineProperty(exports, "crashPlaceBetData", { enumerable: true, get: function () { return index_js_1.crashPlaceBetData; } });
26
+ Object.defineProperty(exports, "crashCollectData", { enumerable: true, get: function () { return index_js_1.crashCollectData; } });
27
+ Object.defineProperty(exports, "minesPickData", { enumerable: true, get: function () { return index_js_1.minesPickData; } });
28
+ Object.defineProperty(exports, "kenoPickData", { enumerable: true, get: function () { return index_js_1.kenoPickData; } });
29
+ // Type guards
30
+ var index_js_2 = require("./types/index.js");
31
+ Object.defineProperty(exports, "isCashChoice", { enumerable: true, get: function () { return index_js_2.isCashChoice; } });
32
+ Object.defineProperty(exports, "isFeatureChoice", { enumerable: true, get: function () { return index_js_2.isFeatureChoice; } });
33
+ // Constants
34
+ var constants_js_1 = require("./constants.js");
35
+ Object.defineProperty(exports, "API_RETURNCODES", { enumerable: true, get: function () { return constants_js_1.API_RETURNCODES; } });
36
+ Object.defineProperty(exports, "recoverableErrorCodes", { enumerable: true, get: function () { return constants_js_1.recoverableErrorCodes; } });
37
+ Object.defineProperty(exports, "defaultNetworkTimeout", { enumerable: true, get: function () { return constants_js_1.defaultNetworkTimeout; } });
@@ -0,0 +1,9 @@
1
+ import type { TNetworkResponse } from './types/index.js';
2
+ declare let wsTransport: {
3
+ send: <T>(body: Record<string, unknown>) => Promise<TNetworkResponse<T>>;
4
+ isConnected: () => boolean;
5
+ } | null;
6
+ export declare function setWsTransport(transport: typeof wsTransport): void;
7
+ export declare function getWsTransport(): typeof wsTransport;
8
+ export declare function request<T>(url: string, body: Record<string, unknown>): Promise<TNetworkResponse<T>>;
9
+ export {};
package/lib/network.js ADDED
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setWsTransport = setWsTransport;
4
+ exports.getWsTransport = getWsTransport;
5
+ exports.request = request;
6
+ const constants_js_1 = require("./constants.js");
7
+ let wsTransport = null;
8
+ function setWsTransport(transport) {
9
+ wsTransport = transport;
10
+ }
11
+ function getWsTransport() {
12
+ return wsTransport;
13
+ }
14
+ async function request(url, body) {
15
+ if (wsTransport?.isConnected()) {
16
+ return wsTransport.send(body);
17
+ }
18
+ return httpRequest(url, body);
19
+ }
20
+ function decodeBase64Utf8(value) {
21
+ try {
22
+ const binary = atob(value);
23
+ const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
24
+ return new TextDecoder('utf-8').decode(bytes);
25
+ }
26
+ catch {
27
+ return value;
28
+ }
29
+ }
30
+ async function httpRequest(url, body) {
31
+ try {
32
+ const response = await fetch(url, {
33
+ method: 'POST',
34
+ headers: { 'Content-Type': 'application/json' },
35
+ body: JSON.stringify(body),
36
+ signal: AbortSignal.timeout(constants_js_1.defaultNetworkTimeout),
37
+ });
38
+ const data = await response.json();
39
+ if (!response.ok) {
40
+ const errorMsgBase64 = response.headers.get('x-h-error-msg-base64');
41
+ const headerMsg = errorMsgBase64 ? decodeBase64Utf8(errorMsgBase64) : response.headers.get('x-h-error-msg');
42
+ const headerId = response.headers.get('x-h-error-id');
43
+ const error = {
44
+ code: String(headerId ?? data?.errorId ?? data?.code ?? constants_js_1.API_RETURNCODES.UNEXPECTED),
45
+ message: headerMsg ?? data?.errorText ?? data?.message ?? response.statusText,
46
+ };
47
+ if (data?.passThroughData !== undefined && data?.passThroughData !== 'undefined') {
48
+ error.passThroughData = data.passThroughData;
49
+ }
50
+ return { success: false, error };
51
+ }
52
+ return { success: true, result: data };
53
+ }
54
+ catch (error) {
55
+ return {
56
+ success: false,
57
+ error: {
58
+ code: String(constants_js_1.API_RETURNCODES.NETWORKERROR),
59
+ message: error instanceof Error ? error.message : 'Network error',
60
+ },
61
+ };
62
+ }
63
+ }
@@ -0,0 +1,20 @@
1
+ /** A single balance bucket (e.g. real money, bonus, free-play credit). */
2
+ export interface IBalanceEntry {
3
+ /** Balance type identifier (e.g. "real", "bonus"). */
4
+ type: string;
5
+ /** ISO 4217 currency code. */
6
+ currency: string;
7
+ /** Balance amount in minor currency units. */
8
+ amount: number;
9
+ }
10
+ /** Player balance breakdown, returned in most API responses. */
11
+ export interface IBalanceReply {
12
+ /** Sum of all balance buckets. */
13
+ totalBalance: number;
14
+ /** Balance mode identifier (operator-specific). */
15
+ mode: string;
16
+ /** ISO 4217 currency code. */
17
+ currency: string;
18
+ /** Individual balance buckets. */
19
+ balances: IBalanceEntry[];
20
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });