@clovnet/casino-sdk 1.0.0

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.
@@ -0,0 +1,2167 @@
1
+ import { j as WebSocketImpl, a as ConnectionState, d as RealtimeChannel, C as ChannelEventMap, U as Unsubscribe, e as RealtimeError } from './contract-DtFe4bRy.cjs';
2
+
3
+ /**
4
+ * Plugin-actions (ext) transport contract — mirrored verbatim from the runtime's
5
+ * frozen plugin-actions wire contract (see `docs/CASINO_SDK_EXT_BUILD_PROMPT.md` §2,
6
+ * built in the runtime repo from `PLUGIN_ACTIONS_RUNTIME_BUILD_PROMPT.md`).
7
+ *
8
+ * Discovery endpoints:
9
+ *
10
+ * ```
11
+ * GET /api/ext/_catalog → ExtCatalog (ETag + Cache-Control: max-age=60)
12
+ * GET /api/ext/_catalog/:pluginKey → ExtCatalogPlugin (404 if plugin not enabled for tenant)
13
+ * ```
14
+ *
15
+ * Action calls are plain HTTP to `PluginActionDescriptor.path` over the SDK's
16
+ * standard transport. Plugin payloads are opaque to the SDK — no minor-unit money
17
+ * conversion happens on `ext` responses; consult each plugin's docs for its shapes.
18
+ *
19
+ * This file also hosts the typed-client machinery ({@link ExtRegistry} and friends)
20
+ * used by generated `@cwe-plugins/<key>-client` packages. It is types-only so the
21
+ * error model can reference {@link ExtPluginClient} without import cycles.
22
+ */
23
+ interface ExtCatalog {
24
+ catalogVersion: 1;
25
+ tenantId: string;
26
+ plugins: ExtCatalogPlugin[];
27
+ }
28
+ interface ExtCatalogPlugin {
29
+ pluginKey: string;
30
+ /** Installed plugin semver. */
31
+ version: string;
32
+ title: string;
33
+ actions: PluginActionDescriptor[];
34
+ /** Realtime channels the plugin may publish, e.g. `["ext.cashback"]`. */
35
+ channels: string[];
36
+ /** Optional widget descriptors. */
37
+ frontend?: PluginFrontendDecl;
38
+ }
39
+ interface PluginActionDescriptor {
40
+ key: string;
41
+ title: string;
42
+ description?: string;
43
+ kind: "query" | "mutation";
44
+ /** Mutation requires an `Idempotency-Key` header (auto-generated if absent). */
45
+ idempotent?: boolean;
46
+ deprecated?: string;
47
+ method: "GET" | "POST" | "PUT" | "DELETE";
48
+ /** Absolute, e.g. `"/api/ext/cashback/claim"`. */
49
+ path: string;
50
+ /** `"player"` ⇒ session cookie required (the SDK handles this as usual). */
51
+ auth: "public" | "player";
52
+ /** JSON Schema draft-07 for params/query/body. */
53
+ input?: unknown;
54
+ /** JSON Schema, when declared. */
55
+ output?: unknown;
56
+ /** Plugin event types this action may cause. */
57
+ emits?: string[];
58
+ }
59
+ interface PluginFrontendDecl {
60
+ widgets?: Array<{
61
+ key: string;
62
+ title: string;
63
+ slot: "lobby" | "account" | "cashier" | "game-sidebar";
64
+ /** A `kind: "query"` action key. */
65
+ dataAction: string;
66
+ /** Mutation action keys. */
67
+ actions?: string[];
68
+ }>;
69
+ }
70
+ /** HTTP methods a plugin action may declare. */
71
+ type ExtMethod = "GET" | "POST" | "PUT" | "DELETE";
72
+ interface ExtCallOpts {
73
+ /** Use this idempotency key instead of an auto-generated one. */
74
+ idempotencyKey?: string;
75
+ /** Abort signal. */
76
+ signal?: AbortSignal;
77
+ }
78
+ /** Init for the {@link ExtPluginClient.request} escape hatch. */
79
+ interface ExtRequestInit extends ExtCallOpts {
80
+ /** Query params; `undefined`/`null` are dropped, arrays repeat the key. */
81
+ query?: Record<string, unknown>;
82
+ /** JSON body (plugins validate `.strict()` — send exactly the declared keys). */
83
+ body?: unknown;
84
+ }
85
+ /**
86
+ * Lazy per-plugin handle returned by `sdk.ext(pluginKey)`. Nothing is fetched
87
+ * until `call()`/`request()` is used.
88
+ */
89
+ interface ExtPluginClient {
90
+ /** The plugin this handle targets. */
91
+ readonly pluginKey: string;
92
+ /**
93
+ * Call a catalog-declared action. Resolves the action descriptor from the
94
+ * (cached) catalog, routes `input` per the action's method, and auto-generates
95
+ * an `Idempotency-Key` for idempotent mutations.
96
+ */
97
+ call<TResult = unknown>(actionKey: string, input?: unknown, opts?: ExtCallOpts): Promise<TResult>;
98
+ /**
99
+ * Escape hatch for declared routes not in the catalog (same transport, no
100
+ * descriptor lookup). `path` is relative to the plugin mount:
101
+ * `request("GET", "/games/starburst")` → `GET /api/ext/<pluginKey>/games/starburst`.
102
+ */
103
+ request<TResult = unknown>(method: ExtMethod, path: string, init?: ExtRequestInit): Promise<TResult>;
104
+ }
105
+ /**
106
+ * Per-action shape a generated client declares: `input` (omit for none) and
107
+ * `output` (omit for `unknown`).
108
+ */
109
+ interface ExtActionShape {
110
+ input?: unknown;
111
+ output?: unknown;
112
+ }
113
+ /**
114
+ * Augmentation point for generated plugin clients. Empty by default; a generated
115
+ * package adds its plugin under its key:
116
+ *
117
+ * ```ts
118
+ * declare module "@clovnet/casino-sdk" {
119
+ * interface ExtRegistry {
120
+ * cashback: {
121
+ * getSummary: { output: CashbackSummary };
122
+ * claim: { input: { periodId: string }; output: ClaimResult };
123
+ * };
124
+ * }
125
+ * }
126
+ * ```
127
+ *
128
+ * With that in scope, `sdk.ext("cashback")` returns a {@link TypedExtPluginClient}
129
+ * whose `call()` narrows action keys, input, and result. Unregistered plugin keys
130
+ * keep the loosely-typed {@link ExtPluginClient}.
131
+ */
132
+ interface ExtRegistry {
133
+ }
134
+ /** The declared input type of an action shape (`undefined` when it takes none; an optional `input?:` admits `undefined`). */
135
+ type ExtActionInput<S> = "input" extends keyof S ? S extends {
136
+ input?: infer I;
137
+ } ? {} extends Pick<S, "input" & keyof S> ? I | undefined : I : never : undefined;
138
+ /** The declared output type of an action shape (`unknown` when undeclared). */
139
+ type ExtActionOutput<S> = "output" extends keyof S ? S extends {
140
+ output?: infer O;
141
+ } ? O : never : unknown;
142
+ /** `call()` argument tuple for an action shape: input is optional only when it may be omitted. */
143
+ type ExtCallArgs<S> = [ExtActionInput<S>] extends [undefined] ? [input?: undefined, opts?: ExtCallOpts] : undefined extends ExtActionInput<S> ? [input?: ExtActionInput<S>, opts?: ExtCallOpts] : [input: ExtActionInput<S>, opts?: ExtCallOpts];
144
+ /**
145
+ * The narrowed handle `sdk.ext(pluginKey)` returns when `pluginKey` is registered
146
+ * in {@link ExtRegistry}. Transport is identical to {@link ExtPluginClient} — this
147
+ * is typing only.
148
+ */
149
+ interface TypedExtPluginClient<A> {
150
+ readonly pluginKey: string;
151
+ call<K extends keyof A & string>(actionKey: K, ...args: ExtCallArgs<A[K]>): Promise<ExtActionOutput<A[K]>>;
152
+ request<TResult = unknown>(method: ExtMethod, path: string, init?: ExtRequestInit): Promise<TResult>;
153
+ }
154
+
155
+ /**
156
+ * Error model.
157
+ *
158
+ * The runtime returns a single envelope shape on failure:
159
+ *
160
+ * ```json
161
+ * { "error": { "code": "INSUFFICIENT_FUNDS", "message": "...", "details": { } } }
162
+ * ```
163
+ *
164
+ * `mapEnvelope` turns that (plus the HTTP status) into a typed {@link CasinoSdkError}
165
+ * subclass so app code can `instanceof`-branch instead of string-matching codes.
166
+ */
167
+
168
+ /** The runtime's `AppError` envelope, as seen on the wire. */
169
+ interface AppErrorEnvelope {
170
+ error: {
171
+ code: string;
172
+ message: string;
173
+ details?: unknown;
174
+ };
175
+ }
176
+ /** Type guard for the runtime error envelope. */
177
+ declare function isAppErrorEnvelope(value: unknown): value is AppErrorEnvelope;
178
+ /**
179
+ * Base class for every error the SDK throws. Carries the stable machine-readable
180
+ * `code`, the HTTP `status` (0 for transport/client-side failures), and the
181
+ * runtime's `details` payload when present.
182
+ */
183
+ declare class CasinoSdkError extends Error {
184
+ readonly code: string;
185
+ readonly status: number;
186
+ readonly details?: unknown;
187
+ constructor(code: string, message: string, status?: number, details?: unknown);
188
+ }
189
+ /** 401 — session missing/invalid/expired. Often triggers an auto-refresh + retry. */
190
+ declare class AuthError extends CasinoSdkError {
191
+ }
192
+ /**
193
+ * 403 — authenticated but not allowed. This includes CSRF double-submit failures:
194
+ * the runtime throws them as a plain `FORBIDDEN` (see `packages/core/src/csrf.ts`
195
+ * in the runtime), so there is deliberately no separate CSRF error class here.
196
+ */
197
+ declare class ForbiddenError extends CasinoSdkError {
198
+ }
199
+ /** 400 — request failed validation. `details.issues` lists the per-field problems. */
200
+ declare class ValidationError extends CasinoSdkError {
201
+ }
202
+ /** 404 — resource not found. */
203
+ declare class NotFoundError extends CasinoSdkError {
204
+ }
205
+ /** 409 — conflict or invalid state transition. */
206
+ declare class ConflictError extends CasinoSdkError {
207
+ }
208
+ /** 422 — wallet balance too low for the requested debit (`INSUFFICIENT_FUNDS`). */
209
+ declare class InsufficientFundsError extends CasinoSdkError {
210
+ }
211
+ /**
212
+ * 422 — the request was semantically rejected and no more-specific domain code
213
+ * matched. The neutral fallback for unknown 422s: a future non-money 422 must not
214
+ * `instanceof`-match app branches written for insufficient funds.
215
+ */
216
+ declare class UnprocessableError extends CasinoSdkError {
217
+ }
218
+ /**
219
+ * 422 — a cashier gate plugin denied the operation (`DEPOSIT_DENIED`,
220
+ * `WITHDRAWAL_DENIED`, `DEPOSIT_LIMIT_EXCEEDED`, `WITHDRAWAL_LIMIT_EXCEEDED`).
221
+ * `details.pluginId` names the deciding plugin.
222
+ */
223
+ declare class OperationDeniedError extends CasinoSdkError {
224
+ }
225
+ /**
226
+ * 429 — rate limited. On verification-request cooldowns `details.resendIn`
227
+ * gives the seconds to wait before retrying.
228
+ */
229
+ declare class RateLimitError extends CasinoSdkError {
230
+ }
231
+ /**
232
+ * 409 `FLOW_DELEGATED` — this tenant delegates the flow (signup/deposit/
233
+ * withdrawal/KYC) to a plugin; drive the plugin's actions via `sdk.ext`
234
+ * instead. `details: { flow, pluginKey }`.
235
+ */
236
+ declare class FlowDelegatedError extends ConflictError {
237
+ /** The plugin that owns the delegated flow (from `details.pluginKey`). */
238
+ readonly pluginKey: string;
239
+ /** The delegated flow kind (from `details.flow`), e.g. `"deposit"`. */
240
+ readonly flow: string | undefined;
241
+ /**
242
+ * Set (best-effort, by the SDK) when the ext catalog shows an action named
243
+ * after the flow — `sdk.ext(pluginKey).call(continueWith.actionKey, …)` is
244
+ * then the way to continue. Left `undefined` when the catalog lookup fails;
245
+ * the original error is never masked.
246
+ */
247
+ continueWith?: {
248
+ actionKey: string;
249
+ };
250
+ constructor(code: string, message: string, status?: number, details?: unknown);
251
+ /** Sugar for `sdk.ext(this.pluginKey)` — the plugin client to continue the flow with. */
252
+ resolve(sdk: {
253
+ ext: (pluginKey: string) => ExtPluginClient;
254
+ }): ExtPluginClient;
255
+ }
256
+ /**
257
+ * 409 `RG_BLOCKED` — a responsible-gaming state blocks the operation.
258
+ * `details: { reason: "cool_off" | "self_excluded", until: string | null }`.
259
+ */
260
+ declare class RgBlockedError extends CasinoSdkError {
261
+ }
262
+ /**
263
+ * 409 `LIMIT_EXCEEDED` — a responsible-gaming limit blocks the operation.
264
+ * `details: { kind, period, remainingMinor, resetsAt }`.
265
+ */
266
+ declare class LimitExceededError extends CasinoSdkError {
267
+ }
268
+ /** 5xx — the runtime failed internally. */
269
+ declare class ServerError extends CasinoSdkError {
270
+ }
271
+ /** No HTTP response (DNS/offline/abort/CORS). `status` is 0. */
272
+ declare class NetworkError extends CasinoSdkError {
273
+ }
274
+ /**
275
+ * A capability the SDK exposes for surface-completeness, but the runtime does not
276
+ * implement yet. See the roadmap in `docs/SDK_BIBLE.md`.
277
+ */
278
+ declare class NotImplementedError extends CasinoSdkError {
279
+ constructor(message: string);
280
+ }
281
+ /**
282
+ * The plugin is not installed/enabled for this tenant — either a 404 from an
283
+ * `/api/ext/*` route (the runtime makes disabled and not-installed
284
+ * indistinguishable) or the plugin is absent from a fresh catalog (then thrown
285
+ * client-side with `status` 0 and code `PLUGIN_NOT_ENABLED`, no network call).
286
+ */
287
+ declare class PluginNotEnabledError extends NotFoundError {
288
+ readonly pluginKey: string;
289
+ constructor(pluginKey: string, options?: {
290
+ code?: string;
291
+ message?: string;
292
+ status?: number;
293
+ details?: unknown;
294
+ });
295
+ }
296
+ /**
297
+ * The action key is not among the plugin's catalog descriptors. Thrown
298
+ * client-side (status 0) without a network call when the catalog is fresh.
299
+ */
300
+ declare class PluginActionNotFoundError extends NotFoundError {
301
+ readonly pluginKey: string;
302
+ readonly actionKey: string;
303
+ constructor(pluginKey: string, actionKey: string);
304
+ }
305
+ /**
306
+ * The plugin handler timed out or crashed — a 504 from an `/api/ext/*` route or
307
+ * the envelope code `PLUGIN_ROUTE_ERROR` (also the legacy `PLUGIN_ROUTE_TIMEOUT`).
308
+ */
309
+ declare class PluginUnavailableError extends ServerError {
310
+ }
311
+ /**
312
+ * A generated plugin client's expected major version does not match the
313
+ * installed plugin's version in the catalog. Thrown client-side by
314
+ * `assertPluginVersion` (status 0).
315
+ */
316
+ declare class PluginVersionMismatchError extends ConflictError {
317
+ readonly pluginKey: string;
318
+ readonly expectedRange: string;
319
+ readonly actualVersion: string;
320
+ constructor(pluginKey: string, expectedRange: string, actualVersion: string);
321
+ }
322
+
323
+ /** Minimal cookie store used when no browser cookie jar exists. */
324
+ declare class CookieJar {
325
+ private readonly store;
326
+ /** Read a cookie value by name, or undefined. */
327
+ get(name: string): string | undefined;
328
+ /** Serialize all cookies into a `Cookie` request-header value. */
329
+ header(): string | undefined;
330
+ /** Clear the jar (e.g. on logout). */
331
+ clear(): void;
332
+ /**
333
+ * Ingest `set-cookie` header(s) from a response. Only the `name=value` pair is
334
+ * retained (attributes like Path/HttpOnly are ignored — this jar is a dev/SSR
335
+ * convenience, not a spec-complete cookie store). A `Max-Age<=0` or an `Expires`
336
+ * in the past deletes the cookie; `Max-Age` wins when both are present.
337
+ */
338
+ ingest(setCookie: string | string[] | null | undefined): void;
339
+ }
340
+
341
+ /**
342
+ * Client configuration.
343
+ */
344
+
345
+ /** A `fetch`-compatible function. Defaults to the platform global. */
346
+ type FetchLike = typeof fetch;
347
+ /** Cookie names the runtime sets. Stable; surfaced for advanced use. */
348
+ declare const COOKIE: {
349
+ readonly access: "cwe_access_token";
350
+ readonly refresh: "cwe_refresh_token";
351
+ readonly csrf: "cwe_csrf";
352
+ };
353
+ /** Header names the SDK sends. */
354
+ declare const HEADER: {
355
+ readonly tenant: "x-tenant-id";
356
+ readonly brand: "x-brand-id";
357
+ readonly region: "x-region";
358
+ readonly csrf: "x-csrf-token";
359
+ readonly idempotency: "idempotency-key";
360
+ };
361
+ interface CasinoClientConfig {
362
+ /** Base URL of the runtime HTTP API, e.g. `https://api.staging.example`. */
363
+ baseUrl: string;
364
+ /**
365
+ * WebSocket URL of the realtime gateway, e.g. `wss://api.staging.example/realtime`.
366
+ * Optional — only needed if you use `sdk.realtime`. Defaults to `baseUrl` with
367
+ * the protocol swapped to ws(s) and `/realtime` appended.
368
+ */
369
+ wsUrl?: string;
370
+ /**
371
+ * Tenant id sent as `x-tenant-id` on every request — as *declared intent*,
372
+ * not as the selector. Since the runtime's H1 trusted tenant resolution, the
373
+ * tenant is determined by the request host (`baseUrl`'s origin → the
374
+ * runtime's trusted host→tenant map, else its env base); an untrusted
375
+ * `x-tenant-id` is ignored. The header is only honored when a trusted
376
+ * internal proxy forwards it with `x-internal-tenant-token`. Point `baseUrl`
377
+ * at the correct brand host; multi-brand apps need one client per brand
378
+ * base URL.
379
+ */
380
+ tenantId: string;
381
+ /** Optional brand id sent as `x-brand-id`. */
382
+ brandId?: string;
383
+ /** Optional region sent as `x-region`. */
384
+ region?: string;
385
+ /** Default fiat currency for wallet/cashier/launch calls (ISO 4217). Default `EUR`. */
386
+ defaultCurrency?: string;
387
+ /** Injected fetch (Node < 18, tests, custom agents). Defaults to global `fetch`. */
388
+ fetch?: FetchLike;
389
+ /**
390
+ * Called when a request fails auth even after one refresh attempt. Use it to
391
+ * route the user to login / clear app state. Receives the originating error.
392
+ */
393
+ onAuthError?: (error: CasinoSdkError) => void;
394
+ /**
395
+ * Disable the automatic 401 → refresh → retry behavior (default enabled).
396
+ * Turn off if you manage refresh yourself.
397
+ */
398
+ autoRefresh?: boolean;
399
+ /**
400
+ * Node/SSR only: the cookie jar this client reads and writes (the browser manages
401
+ * its own cookies). Defaults to a fresh private jar. On a server that handles many
402
+ * users, never share one jar (or one module-scope client) across requests — use
403
+ * `client.withCookies(new CookieJar())` per incoming request instead.
404
+ */
405
+ cookieJar?: CookieJar;
406
+ /**
407
+ * Default per-request timeout in milliseconds — a black-holed request rejects
408
+ * with `NetworkError` (code `NETWORK_TIMEOUT`) instead of hanging forever, so
409
+ * `deposit()`/`withdraw()`/`login()` always settle. Default 30 000; `0` disables.
410
+ * Calls that legitimately run long expose a per-call override — e.g.
411
+ * `kyc.uploadDocument(input, { timeoutMs })` for large files on slow uplinks.
412
+ */
413
+ timeoutMs?: number;
414
+ }
415
+ /** Internal, fully-resolved config with defaults applied. */
416
+ interface ResolvedConfig extends Required<Omit<CasinoClientConfig, "brandId" | "region" | "onAuthError" | "cookieJar">> {
417
+ brandId: string | undefined;
418
+ region: string | undefined;
419
+ onAuthError: ((error: CasinoSdkError) => void) | undefined;
420
+ cookieJar: CookieJar | undefined;
421
+ }
422
+
423
+ /**
424
+ * The isomorphic HTTP layer every module calls through.
425
+ *
426
+ * Responsibilities (so modules and app code never deal with them):
427
+ * - inject `x-tenant-id` (+ optional brand/region) from config — declared intent
428
+ * only: the runtime resolves the tenant from the request host (H1) and ignores
429
+ * untrusted `x-tenant-*` headers,
430
+ * - `credentials: "include"` for the cookie session; in Node, replay/ingest a
431
+ * {@link CookieJar},
432
+ * - double-submit CSRF: read `cwe_csrf`, send `x-csrf-token` on mutations,
433
+ * - auto idempotency keys for money ops (body field + header),
434
+ * - decode the `AppError` envelope into a typed {@link CasinoSdkError},
435
+ * - on 401, attempt a single refresh + retry, then fire `onAuthError` — the refresh
436
+ * is single-flight across concurrent 401s and never refreshes itself,
437
+ * - apply the default request timeout (`timeoutMs`, 30s) → `NETWORK_TIMEOUT`.
438
+ */
439
+
440
+ type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
441
+ interface RequestOptions {
442
+ /** Query params; `undefined`/`null` are dropped, arrays repeat the key. */
443
+ query?: Record<string, string | number | boolean | undefined | null | readonly string[]>;
444
+ /**
445
+ * Request body. A plain value is JSON-encoded; a `FormData` is sent as
446
+ * multipart (content-type left to fetch so the boundary is set) — used by
447
+ * KYC document uploads.
448
+ */
449
+ body?: unknown;
450
+ /**
451
+ * Mark this a money operation: the SDK injects an idempotency key into both the
452
+ * body (`idempotencyKey`) and the `idempotency-key` header.
453
+ */
454
+ idempotent?: boolean;
455
+ /** Provide your own idempotency key instead of an auto-generated one. */
456
+ idempotencyKey?: string;
457
+ /**
458
+ * With `idempotent`, send the key as the `idempotency-key` header only and leave
459
+ * the body untouched. Plugin ext routes validate bodies `.strict()` and read the
460
+ * key from the header, so an injected body field would be rejected.
461
+ */
462
+ idempotencyHeaderOnly?: boolean;
463
+ /** Force-enable/disable the CSRF header (defaults: on for mutations). */
464
+ csrf?: boolean;
465
+ /** Extra request headers, merged after the SDK's own (advanced; e.g. `if-none-match`). */
466
+ headers?: Record<string, string>;
467
+ /** Abort signal. */
468
+ signal?: AbortSignal;
469
+ /** Per-request timeout in ms, overriding `config.timeoutMs` (`0` disables). */
470
+ timeoutMs?: number;
471
+ /** Internal: prevents infinite refresh recursion. */
472
+ _isRetry?: boolean;
473
+ /**
474
+ * Internal: this request must never enter the 401 → refresh → retry path, and a
475
+ * 401 on it does not fire `onAuthError` itself. Set on the refresh POST: when
476
+ * refresh 401s (fully logged out), the *originating* request reports the auth
477
+ * failure exactly once instead of the refresh request recursing into itself.
478
+ */
479
+ _noRefresh?: boolean;
480
+ /**
481
+ * Internal: skip the error enricher for this request. Set on the ext catalog
482
+ * reads the enricher itself performs, so an erroring catalog can never
483
+ * re-enter its own error path.
484
+ */
485
+ _noEnrich?: boolean;
486
+ }
487
+ /** Result of a {@link HttpClient.conditionalGet} (ETag revalidation). */
488
+ interface ConditionalGetResult<T> {
489
+ /** True when the server answered `304 Not Modified` — keep your cached copy. */
490
+ notModified: boolean;
491
+ /** The parsed body (present on 2xx, absent on 304). */
492
+ data?: T;
493
+ /** The response `ETag`, to send back as `etag` on the next call. */
494
+ etag?: string;
495
+ /** Parsed `Cache-Control: max-age=N`, in seconds. */
496
+ maxAgeSeconds?: number;
497
+ }
498
+ declare class HttpClient {
499
+ private readonly config;
500
+ readonly jar: CookieJar;
501
+ private refresh;
502
+ private refreshInflight;
503
+ private enrich;
504
+ constructor(config: ResolvedConfig);
505
+ /** Wired by the client after the auth module exists (avoids a circular import). */
506
+ setRefreshHandler(fn: () => Promise<void>): void;
507
+ /**
508
+ * Wired by the client: a best-effort pass over every decoded error before it is
509
+ * thrown (e.g. populating `FlowDelegatedError.continueWith` from the ext
510
+ * catalog). Whatever it does or throws, the original error is what propagates.
511
+ */
512
+ setErrorEnricher(fn: (error: CasinoSdkError) => Promise<void> | void): void;
513
+ get<T>(path: string, options?: Omit<RequestOptions, "body">): Promise<T>;
514
+ post<T>(path: string, options?: RequestOptions): Promise<T>;
515
+ put<T>(path: string, options?: RequestOptions): Promise<T>;
516
+ patch<T>(path: string, options?: RequestOptions): Promise<T>;
517
+ delete<T>(path: string, options?: RequestOptions): Promise<T>;
518
+ request<T>(method: Method, path: string, options?: RequestOptions): Promise<T>;
519
+ /**
520
+ * GET with ETag revalidation: sends `If-None-Match` when `etag` is given and
521
+ * treats `304 Not Modified` as success (empty `data`). Used for endpoints that
522
+ * declare HTTP caching, e.g. the ext plugin catalog.
523
+ */
524
+ conditionalGet<T>(path: string, options?: {
525
+ etag?: string;
526
+ signal?: AbortSignal;
527
+ _noEnrich?: boolean;
528
+ }): Promise<ConditionalGetResult<T>>;
529
+ /** The shared pipeline: headers, CSRF, idempotency, cookies, fetch, 401→refresh→retry. */
530
+ private performFetch;
531
+ /**
532
+ * Run the wired refresh handler with single-flight dedupe (same pattern as the
533
+ * ext catalog): concurrent 401s all await ONE in-flight `POST /auth/player/refresh`.
534
+ * With rotating refresh tokens, parallel refreshes would present an already-rotated
535
+ * token and get the whole session revoked.
536
+ */
537
+ private runRefresh;
538
+ private parseBody;
539
+ private toError;
540
+ private buildUrl;
541
+ }
542
+
543
+ /**
544
+ * Money.
545
+ *
546
+ * The runtime keeps money to **4 decimal places** (`@cwe/shared/money.ts`, `SCALE=4`).
547
+ * Three encodings appear on the wire and the SDK reconciles them to ONE:
548
+ *
549
+ * - REST **responses** carry 4-dp **decimal strings** — `"12.5000"`.
550
+ * - REST **request bodies** take plain JSON **numbers** in major units — `12.5`
551
+ * (the runtime's Zod schemas are `z.number()`; it normalizes to 4-dp internally).
552
+ * - Realtime carries the same value as a **scale-4 integer** — `125000`.
553
+ *
554
+ * The SDK's public surface always uses {@link MinorUnits} (the scale-4 integer),
555
+ * matching `docs/realtime-sdk-contract.ts`. Convert at the REST boundary with
556
+ * {@link decimalToMinor} (read) / {@link minorToAmount} (write), and display with
557
+ * {@link formatMoney}. Never do money math beyond display.
558
+ */
559
+ /** Integer minor units at scale 4 (i.e. major × 10_000). `125000` ⇒ `12.5000`. */
560
+ type MinorUnits = number;
561
+ /** Decimal places the runtime stores. Do not change without the runtime changing. */
562
+ declare const MONEY_SCALE = 4;
563
+ /**
564
+ * Convert a runtime decimal string (or number) to scale-4 minor units.
565
+ * `"12.5000"` ⇒ `125000`. Throws on non-numeric input.
566
+ */
567
+ declare function decimalToMinor(value: string | number): MinorUnits;
568
+ /**
569
+ * Parse a runtime **minor-unit integer string** (`"1000000"` ⇒ `1000000`) — the
570
+ * encoding the player history surfaces (`/player/cashier/*`, `/player/bets`,
571
+ * `/player/game-sessions`, `/player/limits`) use, unlike the 4-dp decimal
572
+ * strings elsewhere (use {@link decimalToMinor} for those).
573
+ *
574
+ * Strict by design: only canonical digit strings (`/^-?\d+$/`) within the safe
575
+ * integer range are accepted. A 4-dp decimal that happens to be integral
576
+ * (`"50.0000"`) is a WRONG-SURFACE value — accepting it would misread €50.00 as
577
+ * 50 minor units (a 10 000× error) — and an over-`MAX_SAFE_INTEGER` string would
578
+ * silently lose minor units. Both throw so contract drift is loud.
579
+ */
580
+ declare function minorStringToMinor(value: string): MinorUnits;
581
+ /**
582
+ * Convert scale-4 minor units to the plain major-unit **number** the runtime's
583
+ * write schemas expect (`amount: z.number()`). `125000` ⇒ `12.5`. Safe for the
584
+ * 4-dp range: a scale-4 integer divided by 10⁴ round-trips exactly through JSON.
585
+ */
586
+ declare function minorToAmount(minor: MinorUnits): number;
587
+ /**
588
+ * Convert scale-4 minor units back to a canonical 4-dp decimal string
589
+ * (`125000` ⇒ `"12.5000"`) — the format REST **responses** use. Kept public for
590
+ * symmetry/display; note the runtime's write paths take numbers, not strings
591
+ * (use {@link minorToAmount} there).
592
+ */
593
+ declare function minorToDecimal(minor: MinorUnits): string;
594
+ /**
595
+ * Format minor units for display in the currency's natural precision.
596
+ * `formatMoney(125000, "EUR")` ⇒ `"€12.50"` (en locale). Uses `Intl.NumberFormat`;
597
+ * pass `locale` to localize, or `{ minimumFractionDigits }` to show all 4 dp.
598
+ */
599
+ declare function formatMoney(minor: MinorUnits, currency: string, options?: {
600
+ locale?: string;
601
+ minimumFractionDigits?: number;
602
+ maximumFractionDigits?: number;
603
+ }): string;
604
+
605
+ /**
606
+ * Transport types — the player-facing HTTP contract, hand-authored from the
607
+ * runtime route files + Zod schemas (the "manual fallback" of contract sync;
608
+ * see `docs/SDK_BIBLE.md` → Versioning for the swagger follow-up).
609
+ *
610
+ * Money fields that the runtime serializes as 4-dp decimal strings are typed as
611
+ * `MinorUnits` here because the SDK converts them at the transport boundary
612
+ * (`src/modules/*`), so app code only ever sees scale-4 integers.
613
+ *
614
+ * Targets runtime API: see `RUNTIME_API_VERSION` in `src/index.ts`.
615
+ */
616
+
617
+ type PlayerStatus = "active" | "suspended" | "closed" | "pending_verification" | "self_excluded";
618
+ /** Shared pagination block on the new player-facing history endpoints. */
619
+ interface PageInfo {
620
+ limit: number;
621
+ offset: number;
622
+ /** Total rows for the player, across all pages. */
623
+ total: number;
624
+ /** True when `offset + returned < total`. */
625
+ hasMore: boolean;
626
+ }
627
+ interface Player {
628
+ id: string;
629
+ tenantId: string;
630
+ externalId: string | null;
631
+ username: string | null;
632
+ email: string | null;
633
+ phone: string | null;
634
+ status: PlayerStatus;
635
+ createdAt: string;
636
+ updatedAt: string;
637
+ }
638
+ interface PlayerProfile {
639
+ firstName?: string | null;
640
+ lastName?: string | null;
641
+ birthDate?: string | null;
642
+ gender?: string | null;
643
+ country?: string | null;
644
+ city?: string | null;
645
+ address?: string | null;
646
+ language?: string | null;
647
+ currency?: string | null;
648
+ timezone?: string | null;
649
+ avatarUrl?: string | null;
650
+ }
651
+ /** Three wallet buckets, all in scale-4 minor units. */
652
+ interface WalletBuckets {
653
+ cash: MinorUnits;
654
+ bonus: MinorUnits;
655
+ locked: MinorUnits;
656
+ }
657
+ interface Paginated<T> {
658
+ rows: T[];
659
+ total: number;
660
+ limit: number;
661
+ offset: number;
662
+ }
663
+ /**
664
+ * Attribution hints carried from the affiliate click chain into signup. Optional
665
+ * and best-effort — signup never fails on them — but they can only be captured
666
+ * here: a click chain not carried at signup is unrecoverable. `clickId` is the
667
+ * value returned by {@link TrackClickResult} (persist it client-side after
668
+ * `affiliate.trackClick` and pass it through here).
669
+ */
670
+ interface SignupAttribution {
671
+ /** The `clickId` from `affiliate.trackClick` — the click → registration join key. */
672
+ clickId?: string;
673
+ /** Affiliate public tracking code, when the `clickId` was not captured. */
674
+ affiliateCode?: string;
675
+ deviceFingerprint?: string;
676
+ }
677
+ interface SignupInput {
678
+ email: string;
679
+ password: string;
680
+ username?: string;
681
+ profile?: {
682
+ firstName?: string;
683
+ lastName?: string;
684
+ country?: string;
685
+ currency?: string;
686
+ language?: string;
687
+ };
688
+ /** Affiliate attribution captured at click time; see {@link SignupAttribution}. */
689
+ attribution?: SignupAttribution;
690
+ }
691
+ interface LoginInput {
692
+ email: string;
693
+ password: string;
694
+ }
695
+ /** Response of signup/login/refresh/social-callback. Cookies are set by the runtime. */
696
+ interface AuthSession {
697
+ player: Player;
698
+ csrfToken: string;
699
+ }
700
+ interface MeResponse {
701
+ player: Player;
702
+ profile: PlayerProfile | null;
703
+ }
704
+ type SocialProvider = "google" | "discord" | "apple" | "telegram" | "facebook" | "twitter" | "github" | "custom";
705
+ interface SocialAccount {
706
+ id: string;
707
+ tenantId: string;
708
+ playerId: string;
709
+ provider: string;
710
+ providerUserId: string;
711
+ providerEmail?: string | null;
712
+ providerUsername?: string | null;
713
+ providerAvatarUrl?: string | null;
714
+ /** Raw provider profile payload as stored by the runtime. */
715
+ providerData?: unknown;
716
+ linkedAt: string;
717
+ }
718
+ /**
719
+ * Player-facing view of a login session — the "your devices" surface. Omits the
720
+ * refresh-token hash and rotation linkage (server-internal). Dates are ISO strings
721
+ * on the wire.
722
+ */
723
+ interface SafeSession {
724
+ id: string;
725
+ /** True for the session this request is authenticated with ("this device"). */
726
+ current: boolean;
727
+ /** Not revoked and not expired. */
728
+ active: boolean;
729
+ device: {
730
+ type: string | null;
731
+ os: string | null;
732
+ browser: string | null;
733
+ model: string | null;
734
+ /** Human label, e.g. "Chrome on macOS". */
735
+ label: string;
736
+ };
737
+ location: {
738
+ city: string | null;
739
+ region: string | null;
740
+ country: string | null;
741
+ };
742
+ ip: string | null;
743
+ createdAt: string;
744
+ /** Refreshed on token rotation (throttled server-side); null for old sessions. */
745
+ lastSeenAt: string | null;
746
+ expiresAt: string;
747
+ revokedAt: string | null;
748
+ }
749
+ interface SessionHistoryQuery {
750
+ /** Page size, 1–100. Runtime default 50. */
751
+ limit?: number;
752
+ /** Runtime default 0. */
753
+ offset?: number;
754
+ }
755
+ /** One page of session history (`GET /auth/player/sessions/history`). */
756
+ interface SessionHistoryPage {
757
+ sessions: SafeSession[];
758
+ pagination: {
759
+ limit: number;
760
+ offset: number;
761
+ /** Total sessions for the player, across all pages. */
762
+ total: number;
763
+ /** True when `offset + returned < total`. */
764
+ hasMore: boolean;
765
+ };
766
+ }
767
+ /**
768
+ * One login attempt (`GET /auth/player/login-history`). `failReason` values
769
+ * observed from the runtime: `invalid_credentials`, `account_inactive`,
770
+ * `account_locked`; null on success.
771
+ */
772
+ interface LoginAttempt {
773
+ id: string;
774
+ at: string;
775
+ ip: string | null;
776
+ device: {
777
+ type: string | null;
778
+ os: string | null;
779
+ browser: string | null;
780
+ label: string;
781
+ };
782
+ location: {
783
+ country: string | null;
784
+ city: string | null;
785
+ };
786
+ method: "password" | "social" | "refresh";
787
+ success: boolean;
788
+ failReason: string | null;
789
+ }
790
+ interface LoginHistoryPage {
791
+ attempts: LoginAttempt[];
792
+ pagination: PageInfo;
793
+ }
794
+ /**
795
+ * `200` of email/phone verification request. `expiresIn` is the credential TTL
796
+ * in seconds; `resendIn` is the cooldown before another request is accepted
797
+ * (a premature retry returns 429 `RATE_LIMITED` with `details.resendIn`).
798
+ */
799
+ interface VerificationRequestResult {
800
+ success: true;
801
+ expiresIn: number;
802
+ resendIn: number;
803
+ }
804
+ /**
805
+ * The full profile row as `GET /player/profile` serializes it (unlike the
806
+ * partial {@link PlayerProfile} on `/auth/player/me`, every field is present,
807
+ * nullable). `birthDate` is a `YYYY-MM-DD` string.
808
+ */
809
+ interface PlayerProfileRecord {
810
+ playerId: string;
811
+ tenantId: string;
812
+ firstName: string | null;
813
+ lastName: string | null;
814
+ birthDate: string | null;
815
+ gender: string | null;
816
+ country: string | null;
817
+ city: string | null;
818
+ address: string | null;
819
+ language: string | null;
820
+ currency: string | null;
821
+ timezone: string | null;
822
+ avatarUrl: string | null;
823
+ createdAt: string;
824
+ updatedAt: string;
825
+ }
826
+ interface ProfileResponse {
827
+ /** Null until the player has a profile row. */
828
+ profile: PlayerProfileRecord | null;
829
+ /**
830
+ * Identity fields locked after KYC approval (`firstName`/`lastName`/
831
+ * `birthDate`/`country`); patching them fails 409 `PROFILE_FIELD_LOCKED`.
832
+ */
833
+ lockedFields: string[];
834
+ }
835
+ /**
836
+ * Body of `PATCH /player/profile`. All fields optional, at least one required;
837
+ * `null` clears a field. Identity fields are rejected after KYC approval.
838
+ */
839
+ interface UpdateProfileInput {
840
+ firstName?: string | null;
841
+ lastName?: string | null;
842
+ /** `YYYY-MM-DD`. */
843
+ birthDate?: string | null;
844
+ gender?: string | null;
845
+ /** ISO 3166-1 alpha-2. */
846
+ country?: string | null;
847
+ city?: string | null;
848
+ address?: string | null;
849
+ language?: string | null;
850
+ timezone?: string | null;
851
+ avatarUrl?: string | null;
852
+ }
853
+ interface UpdateProfileResult {
854
+ profile: PlayerProfileRecord;
855
+ /** Keys whose value actually changed (may be empty for a no-op patch). */
856
+ changedFields: string[];
857
+ }
858
+ type OddsFormat = "decimal" | "fractional" | "american";
859
+ interface PlayerPreferences {
860
+ language: string | null;
861
+ timezone: string | null;
862
+ displayCurrency: string | null;
863
+ oddsFormat: string | null;
864
+ marketing: {
865
+ email: boolean;
866
+ sms: boolean;
867
+ push: boolean;
868
+ };
869
+ /** Reality-check interval in minutes (5–240); null = disabled. */
870
+ realityCheckMinutes: number | null;
871
+ }
872
+ /** Body of `PUT /player/preferences` — all optional, at least one required. */
873
+ interface SetPreferencesInput {
874
+ language?: string;
875
+ timezone?: string;
876
+ /** ISO 4217. */
877
+ displayCurrency?: string;
878
+ oddsFormat?: OddsFormat;
879
+ marketing?: {
880
+ email?: boolean;
881
+ sms?: boolean;
882
+ push?: boolean;
883
+ };
884
+ /** 5–240 minutes, or null to disable the reality check. */
885
+ realityCheckMinutes?: number | null;
886
+ }
887
+ /** One append-only consent-trail entry. Keys today: `marketing.{email,sms,push}`. */
888
+ interface ConsentEntry {
889
+ consentKey: string;
890
+ granted: boolean;
891
+ at: string;
892
+ source: string;
893
+ }
894
+ interface ConsentsPage {
895
+ consents: ConsentEntry[];
896
+ pagination: PageInfo;
897
+ }
898
+ /**
899
+ * GDPR export request state. `POST /player/account/export` answers `202` with
900
+ * `status: "pending"`; `GET /player/account/export` returns the latest request,
901
+ * or the bare `{ status: "none" }` when none was ever requested. The download
902
+ * link is delivered out-of-band, not through these endpoints.
903
+ */
904
+ type DataExportStatus = {
905
+ status: "none";
906
+ } | {
907
+ id: string;
908
+ status: "pending" | "processing" | "completed" | "failed";
909
+ requestedAt: string;
910
+ finishedAt: string | null;
911
+ expiresAt: string | null;
912
+ };
913
+ type LimitKind = "deposit" | "loss" | "wager" | "session_time";
914
+ /** UTC windows; `week` starts ISO Monday 00:00 UTC. */
915
+ type LimitPeriod = "day" | "week" | "month";
916
+ /**
917
+ * One active limit (`GET /player/limits`). `value` is scale-4 minor units for
918
+ * the money kinds (`deposit`/`loss`/`wager`) and **whole minutes** for
919
+ * `session_time`. Ratchet semantics: a new limit or a decrease applies
920
+ * immediately (`pending: null`); an increase or removal is stored in `pending`
921
+ * and applied at `pending.activeAt` (24h cooldown).
922
+ */
923
+ interface PlayerLimit {
924
+ kind: LimitKind;
925
+ period: LimitPeriod;
926
+ value: MinorUnits;
927
+ currency: string | null;
928
+ activeFrom: string;
929
+ pending: {
930
+ /** The value that will apply (null for a pending removal). */
931
+ value: MinorUnits | null;
932
+ removal: boolean;
933
+ activeAt: string;
934
+ } | null;
935
+ }
936
+ /**
937
+ * One entry of `PUT /player/limits`. `value` in scale-4 minor units (minutes
938
+ * for `session_time`); `null` requests removal of the existing limit.
939
+ */
940
+ interface SetLimitInput {
941
+ kind: LimitKind;
942
+ period: LimitPeriod;
943
+ value: MinorUnits | null;
944
+ /** ISO 4217, for money kinds. */
945
+ currency?: string;
946
+ }
947
+ /** Cool-off blocks gameplay + deposits (login/withdrawal stay); extend-only. */
948
+ type CoolOffPeriod = "24h" | "48h" | "7d" | "30d";
949
+ /** Self-exclusion is irreversible player-side; `permanent` has no end date. */
950
+ type SelfExclusionPeriod = "6m" | "1y" | "5y" | "permanent";
951
+ type KycTrigger = "manual" | "signup" | "deposit_total_threshold" | "withdrawal_amount_threshold" | "withdrawal_total_threshold" | "risk_flag";
952
+ type KycRequestStatus = "draft" | "submitted" | "in_review" | "approved" | "rejected" | "needs_more";
953
+ type KycDocumentStatus = "uploaded" | "in_review" | "approved" | "rejected";
954
+ type PlayerKycStatus = "none" | "pending" | "approved" | "rejected" | "expired";
955
+ /** `GET /player/kyc/status`. */
956
+ interface KycStatusResponse {
957
+ /** Verification level 0–3. */
958
+ level: number;
959
+ status: PlayerKycStatus;
960
+ approvedAt: string | null;
961
+ emailVerified: boolean;
962
+ phoneVerified: boolean;
963
+ gates: {
964
+ withdrawal: {
965
+ requiredLevel: number;
966
+ met: boolean;
967
+ };
968
+ };
969
+ }
970
+ /** Latest upload for a checklist item (metadata only — players cannot download). */
971
+ interface KycItemDocument {
972
+ id: string;
973
+ status: KycDocumentStatus;
974
+ fileName: string;
975
+ uploadedAt: string;
976
+ rejectionReason: string | null;
977
+ }
978
+ interface KycChecklistItem {
979
+ /** e.g. `passport`, `id_front`, `proof_of_address`, `selfie`. */
980
+ documentTypeKey: string;
981
+ title: string;
982
+ required: boolean;
983
+ sort: number;
984
+ source: "set" | "needs_more" | "plugin";
985
+ document: KycItemDocument | null;
986
+ }
987
+ /** One open KYC request (`GET /player/kyc/requirements`). */
988
+ interface KycRequest {
989
+ id: string;
990
+ trigger: KycTrigger;
991
+ status: KycRequestStatus;
992
+ targetLevel: number | null;
993
+ createdAt: string;
994
+ items: KycChecklistItem[];
995
+ }
996
+ interface KycHistoryEntry {
997
+ id: string;
998
+ trigger: KycTrigger;
999
+ status: KycRequestStatus;
1000
+ targetLevel: number | null;
1001
+ decisionReasonCode: string | null;
1002
+ createdAt: string;
1003
+ reviewedAt: string | null;
1004
+ }
1005
+ interface KycHistoryPage {
1006
+ requests: KycHistoryEntry[];
1007
+ pagination: PageInfo;
1008
+ }
1009
+ /**
1010
+ * A KYC document upload. Accepted content: JPEG/PNG/PDF, sniffed server-side
1011
+ * from magic bytes (the declared content-type is ignored); 25 MB transport cap,
1012
+ * per-type cap (default 10 MB) enforced at 422 `KYC_DOCUMENT_INVALID`.
1013
+ */
1014
+ interface KycUploadInput {
1015
+ /** Attach to an open request (`draft`/`needs_more`); omit for a proactive upload. */
1016
+ requestId?: string;
1017
+ documentTypeKey: string;
1018
+ /** The file content. In Node pass a `Blob`/`File` (both global on Node ≥20). */
1019
+ file: Blob;
1020
+ /** Filename sent in the multipart part; defaults to `File.name` or `document`. */
1021
+ fileName?: string;
1022
+ /** `YYYY-MM-DD`; required for document types with `requiresExpiryDate` (e.g. passport). */
1023
+ expiryDate?: string;
1024
+ }
1025
+ /** `201` of a KYC document upload. */
1026
+ interface KycUploadResult {
1027
+ documentId: string;
1028
+ status: "uploaded";
1029
+ }
1030
+ interface DepositInput {
1031
+ /** Defaults to the authenticated player. */
1032
+ playerId?: string;
1033
+ /** Amount in scale-4 minor units. */
1034
+ amount: MinorUnits;
1035
+ /** Defaults to the client/profile currency. */
1036
+ currency?: string;
1037
+ providerKey?: string;
1038
+ methodKey?: string;
1039
+ instrumentId?: string;
1040
+ /** FX snapshot currency (ISO 4217) for base-currency analytics. */
1041
+ baseCurrency?: string;
1042
+ returnUrl?: string;
1043
+ /** Auto-generated if omitted. */
1044
+ idempotencyKey?: string;
1045
+ metadata?: Record<string, unknown>;
1046
+ }
1047
+ type DepositTxStatus = "initiated" | "pending_provider" | "authorized" | "captured" | "completed" | "failed" | "refunded" | "chargeback";
1048
+ interface DepositResult {
1049
+ depositId: string;
1050
+ status: DepositTxStatus;
1051
+ providerKey?: string;
1052
+ sourceTxId?: string;
1053
+ /** PSP redirect/3DS/QR instruction; provider-specific. Render or follow as told. */
1054
+ nextAction?: unknown;
1055
+ walletTransactionId?: string;
1056
+ balances?: WalletBuckets;
1057
+ idempotent: boolean;
1058
+ /** Present when a gate plugin requires a step-up (e.g. KYC) before the deposit proceeds. */
1059
+ challenge?: {
1060
+ challenge: string;
1061
+ reason?: string;
1062
+ };
1063
+ }
1064
+ interface WithdrawalInput {
1065
+ playerId?: string;
1066
+ amount: MinorUnits;
1067
+ currency?: string;
1068
+ providerKey?: string;
1069
+ methodKey?: string;
1070
+ instrumentId?: string;
1071
+ /** FX snapshot currency (ISO 4217) for base-currency analytics. */
1072
+ baseCurrency?: string;
1073
+ idempotencyKey?: string;
1074
+ metadata?: Record<string, unknown>;
1075
+ }
1076
+ type WithdrawalTxStatus = "requested" | "pending_review" | "approved" | "processing" | "paid" | "rejected" | "failed" | "cancelled";
1077
+ interface WithdrawalResult {
1078
+ withdrawalId: string;
1079
+ status: WithdrawalTxStatus;
1080
+ reviewVerdict?: string;
1081
+ providerKey?: string;
1082
+ sourceTxId?: string;
1083
+ balances?: WalletBuckets;
1084
+ idempotent: boolean;
1085
+ }
1086
+ /** Shared filter block on the cashier/gaming history endpoints. */
1087
+ interface HistoryRangeQuery {
1088
+ /** ISO date(-time) or `Date`. */
1089
+ from?: string | Date;
1090
+ to?: string | Date;
1091
+ /** 1–100, runtime default 50. */
1092
+ limit?: number;
1093
+ offset?: number;
1094
+ }
1095
+ interface DepositHistoryQuery extends HistoryRangeQuery {
1096
+ status?: DepositTxStatus;
1097
+ providerKey?: string;
1098
+ }
1099
+ /** One deposit (`GET /player/cashier/deposits`), amounts in minor units. */
1100
+ interface DepositSummary {
1101
+ id: string;
1102
+ amount: MinorUnits;
1103
+ currency: string;
1104
+ status: DepositTxStatus;
1105
+ providerKey: string;
1106
+ methodKey: string | null;
1107
+ isFirstDeposit: boolean;
1108
+ createdAt: string;
1109
+ updatedAt: string;
1110
+ }
1111
+ /** `GET /player/cashier/deposits/:id`. */
1112
+ interface DepositDetail extends DepositSummary {
1113
+ walletTransactionId: string | null;
1114
+ failureReason: string | null;
1115
+ /** Only non-null while the deposit is `initiated`/`pending_provider`. */
1116
+ nextAction: unknown | null;
1117
+ }
1118
+ interface DepositHistoryPage {
1119
+ deposits: DepositSummary[];
1120
+ pagination: PageInfo;
1121
+ }
1122
+ interface WithdrawalHistoryQuery extends HistoryRangeQuery {
1123
+ status?: WithdrawalTxStatus;
1124
+ }
1125
+ /** One withdrawal (`GET /player/cashier/withdrawals`), amounts in minor units. */
1126
+ interface WithdrawalSummary {
1127
+ id: string;
1128
+ amount: MinorUnits;
1129
+ currency: string;
1130
+ status: WithdrawalTxStatus;
1131
+ providerKey: string | null;
1132
+ methodKey: string | null;
1133
+ reviewVerdict: string | null;
1134
+ createdAt: string;
1135
+ updatedAt: string;
1136
+ }
1137
+ /** `GET /player/cashier/withdrawals/:id`. */
1138
+ interface WithdrawalDetail extends WithdrawalSummary {
1139
+ failureReason: string | null;
1140
+ /** Wallet transaction ids of the reserve/settle/release legs. */
1141
+ walletTransactionIds: {
1142
+ reserve: string | null;
1143
+ settle: string | null;
1144
+ release: string | null;
1145
+ };
1146
+ }
1147
+ interface WithdrawalHistoryPage {
1148
+ withdrawals: WithdrawalSummary[];
1149
+ pagination: PageInfo;
1150
+ }
1151
+ /**
1152
+ * A payment method available to the player (`GET /player/cashier/methods`),
1153
+ * sorted by `sort` ascending. `limits` are converted to minor units.
1154
+ */
1155
+ interface PaymentMethod {
1156
+ methodKey: string;
1157
+ providerKey: string;
1158
+ title: string;
1159
+ kind: "card" | "bank" | "ewallet" | "crypto" | "voucher";
1160
+ direction: "deposit" | "withdrawal" | "both";
1161
+ limits: {
1162
+ min: MinorUnits;
1163
+ max: MinorUnits;
1164
+ currency: string;
1165
+ };
1166
+ /** Present when the method is gated behind a KYC level. */
1167
+ requiresKycLevel?: number;
1168
+ /** Extra inputs the method needs (e.g. IBAN); render as a form. */
1169
+ fields?: Array<{
1170
+ key: string;
1171
+ label: string;
1172
+ type: "text" | "number" | "select";
1173
+ required?: boolean;
1174
+ options?: string[];
1175
+ }>;
1176
+ sort: number;
1177
+ }
1178
+ interface BalanceResponse {
1179
+ playerId: string;
1180
+ currency: string;
1181
+ cash: MinorUnits;
1182
+ bonus: MinorUnits;
1183
+ locked: MinorUnits;
1184
+ total: MinorUnits;
1185
+ /** `closed` is terminal; `frozen` is reversible. See the runtime wallet state machine. */
1186
+ status: "active" | "frozen" | "closed";
1187
+ walletId: string | null;
1188
+ }
1189
+ type TransactionType = "credit" | "debit" | "deposit" | "withdrawal" | "bet" | "win" | "bonus" | "rollback" | "transfer" | "adjustment";
1190
+ type TransactionStatus = "pending" | "processing" | "completed" | "failed" | "cancelled" | "reversed";
1191
+ interface WalletTransaction {
1192
+ id: string;
1193
+ walletId: string;
1194
+ playerId: string;
1195
+ externalTransactionId: string | null;
1196
+ type: TransactionType;
1197
+ amount: MinorUnits;
1198
+ currency: string;
1199
+ source: string;
1200
+ gameId: string | null;
1201
+ /** The replay-guard key the write was made with. */
1202
+ idempotencyKey: string;
1203
+ metadata: Record<string, unknown> | null;
1204
+ status: TransactionStatus;
1205
+ createdAt: string;
1206
+ updatedAt: string;
1207
+ }
1208
+ interface TransactionsQuery {
1209
+ playerId?: string;
1210
+ walletId?: string;
1211
+ type?: TransactionType;
1212
+ status?: TransactionStatus;
1213
+ currency?: string;
1214
+ limit?: number;
1215
+ offset?: number;
1216
+ }
1217
+ /** The three wallet buckets a ledger leg can move. */
1218
+ type WalletBucketName = "cash" | "bonus" | "locked";
1219
+ /**
1220
+ * One append-only ledger leg (`GET /wallet/ledger`) — a single bucket movement
1221
+ * with its before/after balance snapshot. Amounts in scale-4 minor units.
1222
+ */
1223
+ interface LedgerEntry {
1224
+ id: string;
1225
+ walletId: string;
1226
+ transactionId: string;
1227
+ playerId: string;
1228
+ walletType: WalletBucketName;
1229
+ direction: "credit" | "debit";
1230
+ amount: MinorUnits;
1231
+ currency: string;
1232
+ balanceBefore: MinorUnits;
1233
+ balanceAfter: MinorUnits;
1234
+ createdAt: string;
1235
+ }
1236
+ interface LedgerQuery {
1237
+ playerId?: string;
1238
+ walletId?: string;
1239
+ walletType?: WalletBucketName;
1240
+ transactionId?: string;
1241
+ limit?: number;
1242
+ offset?: number;
1243
+ }
1244
+ interface GameFeatures {
1245
+ hasDemo?: boolean;
1246
+ isVirtual?: boolean;
1247
+ bonusBuy?: boolean;
1248
+ megaways?: boolean;
1249
+ [key: string]: unknown;
1250
+ }
1251
+ interface Game {
1252
+ id: string;
1253
+ slug: string | null;
1254
+ title: string | null;
1255
+ name?: unknown;
1256
+ providerId: string;
1257
+ launchCode: string | null;
1258
+ imageUrl: string | null;
1259
+ rtp: string | null;
1260
+ minBet: string | null;
1261
+ maxBet: string | null;
1262
+ featured: boolean;
1263
+ features: GameFeatures;
1264
+ }
1265
+ interface GamePage {
1266
+ games: Game[];
1267
+ page: {
1268
+ limit: number;
1269
+ offset: number;
1270
+ count: number;
1271
+ };
1272
+ }
1273
+ interface CategoryNode {
1274
+ id: string;
1275
+ slug: string;
1276
+ title: string | null;
1277
+ kind: string;
1278
+ sort: number;
1279
+ children: CategoryNode[];
1280
+ }
1281
+ interface Provider {
1282
+ id: string;
1283
+ externalId: string;
1284
+ name: string;
1285
+ alias: string | null;
1286
+ logoUrl: string | null;
1287
+ logoPath: string | null;
1288
+ weight: number;
1289
+ parentProviderId: string | null;
1290
+ }
1291
+ interface GeoQuery {
1292
+ country?: string;
1293
+ /** Sub-national code, e.g. `"CA-QC"`. */
1294
+ subdivision?: string;
1295
+ currency?: string;
1296
+ locale?: string;
1297
+ device?: string;
1298
+ }
1299
+ interface LobbyQuery extends GeoQuery {
1300
+ limit?: number;
1301
+ offset?: number;
1302
+ }
1303
+ interface SearchQuery extends LobbyQuery {
1304
+ q?: string;
1305
+ /** Provider id, name, or alias; expands to its sub-providers server-side. */
1306
+ provider?: string;
1307
+ /** Category id or slug (e.g. `"slots"`); includes the category subtree. */
1308
+ category?: string;
1309
+ hasDemo?: boolean;
1310
+ isVirtual?: boolean;
1311
+ bonusBuy?: boolean;
1312
+ megaways?: boolean;
1313
+ }
1314
+ /**
1315
+ * @deprecated Input for the removed SlotServ aggregation route (`POST
1316
+ * /plugins/slotserv/launch`); `games.launch()` is a stub now. The live launch
1317
+ * path — `games.providerSession()` — takes `playerId`/`currency` options only.
1318
+ */
1319
+ interface LaunchInput {
1320
+ playerId?: string;
1321
+ currency?: string;
1322
+ device?: string;
1323
+ locale?: string;
1324
+ mode?: "real" | "demo";
1325
+ country?: string;
1326
+ }
1327
+ /** Response of `POST /providers/:provider/session`. */
1328
+ interface LaunchResult {
1329
+ provider: string;
1330
+ /** The game session id. */
1331
+ sessionId: string;
1332
+ /** Fully-formed URL to render in the game iframe. */
1333
+ launchUrl: string;
1334
+ }
1335
+ type BetStatus = "placed" | "settled" | "rolled_back";
1336
+ interface BetsQuery extends HistoryRangeQuery {
1337
+ gameId?: string;
1338
+ providerKey?: string;
1339
+ status?: BetStatus;
1340
+ }
1341
+ /** One bet (`GET /player/bets`), amounts in minor units. */
1342
+ interface Bet {
1343
+ betId: string;
1344
+ roundId: string;
1345
+ gameId: string | null;
1346
+ gameTitle: string | null;
1347
+ providerKey: string;
1348
+ betAmount: MinorUnits;
1349
+ /** Null until settled. */
1350
+ winAmount: MinorUnits | null;
1351
+ currency: string;
1352
+ status: BetStatus;
1353
+ placedAt: string;
1354
+ settledAt: string | null;
1355
+ }
1356
+ /** `GET /player/bets/:betId` — the bet plus its round-linked wallet transactions. */
1357
+ interface BetDetail extends Bet {
1358
+ walletTransactions: Array<{
1359
+ id: string;
1360
+ type: string;
1361
+ }>;
1362
+ }
1363
+ interface BetsPage {
1364
+ bets: Bet[];
1365
+ pagination: PageInfo;
1366
+ }
1367
+ /** One game session (`GET /player/game-sessions`), totals in minor units. */
1368
+ interface GameSession {
1369
+ id: string;
1370
+ providerKey: string;
1371
+ gameId: string | null;
1372
+ currency: string | null;
1373
+ status: "active" | "ended";
1374
+ betCount: number;
1375
+ betTotal: MinorUnits;
1376
+ winTotal: MinorUnits;
1377
+ startedAt: string;
1378
+ lastActivityAt: string | null;
1379
+ endedAt: string | null;
1380
+ }
1381
+ interface GameSessionsPage {
1382
+ sessions: GameSession[];
1383
+ pagination: PageInfo;
1384
+ }
1385
+ /** Up to five free-form sub-tracking ids an affiliate appends to their link. */
1386
+ interface AffiliateSubIds {
1387
+ subId1?: string;
1388
+ subId2?: string;
1389
+ subId3?: string;
1390
+ subId4?: string;
1391
+ subId5?: string;
1392
+ }
1393
+ /** Standard UTM parameters captured from the landing URL. */
1394
+ interface UtmParams {
1395
+ source?: string;
1396
+ medium?: string;
1397
+ campaign?: string;
1398
+ term?: string;
1399
+ content?: string;
1400
+ }
1401
+ /**
1402
+ * Body of `POST /affiliate/track/click`. The runtime validates `.strict()` —
1403
+ * unknown keys are rejected — and captures `ip`/`user-agent` server-side.
1404
+ * `referrer` falls back to the `Referer` header when omitted.
1405
+ */
1406
+ interface TrackClickInput {
1407
+ /** The affiliate's public tracking code from the landing link (required). */
1408
+ affiliateCode: string;
1409
+ campaignId?: string;
1410
+ creativeId?: string;
1411
+ subIds?: AffiliateSubIds;
1412
+ /** Google Ads click id. */
1413
+ gclid?: string;
1414
+ /** Meta click id. */
1415
+ fbclid?: string;
1416
+ /** TikTok click id. */
1417
+ ttclid?: string;
1418
+ /** Microsoft Ads click id. */
1419
+ msclkid?: string;
1420
+ utm?: UtmParams;
1421
+ landingPage?: string;
1422
+ referrer?: string;
1423
+ deviceFingerprint?: string;
1424
+ }
1425
+ /**
1426
+ * `201` response of the click capture. Store `clickId` client-side
1427
+ * (cookie/localStorage) and pass it through signup — it is the
1428
+ * click → registration join key.
1429
+ */
1430
+ interface TrackClickResult {
1431
+ clickId: string;
1432
+ }
1433
+
1434
+ /**
1435
+ * `sdk.affiliate` — affiliate click tracking.
1436
+ *
1437
+ * Maps to the runtime's one public affiliate endpoint, `POST /affiliate/track/click`.
1438
+ * Call it on the landing page; anything not captured at click time (gclid/fbclid/…)
1439
+ * is unrecoverable. The endpoint is rate-limited per IP (`RateLimitError` on 429).
1440
+ */
1441
+
1442
+ declare class AffiliateModule {
1443
+ private readonly http;
1444
+ constructor(http: HttpClient);
1445
+ /**
1446
+ * Record an affiliate click. Returns the `clickId` join key — persist it
1447
+ * (cookie/localStorage) and carry it into signup so the registration can be
1448
+ * attributed to the click.
1449
+ */
1450
+ trackClick(input: TrackClickInput): Promise<TrackClickResult>;
1451
+ }
1452
+
1453
+ /**
1454
+ * Session state held client-side.
1455
+ *
1456
+ * Several runtime endpoints need the player's id and/or currency that the SDK can
1457
+ * supply automatically once the player has authenticated:
1458
+ *
1459
+ * - cashier `deposits`/`withdrawals` take `playerId` in the body,
1460
+ * - `GET /wallet/balance` and `/wallet/transactions` take `playerId` + `currency`,
1461
+ * - provider game sessions (`providerSession`) take `playerId` + `currency`.
1462
+ *
1463
+ * Auth responses (`signup`/`login`/`me`) populate this cache so callers don't have
1464
+ * to thread `playerId` through every call. Every method still accepts an explicit
1465
+ * override.
1466
+ */
1467
+
1468
+ interface SessionSnapshot {
1469
+ player: Player | null;
1470
+ profile: PlayerProfile | null;
1471
+ /** Default currency: profile currency, else the client's configured default. */
1472
+ currency: string;
1473
+ }
1474
+ declare class Session {
1475
+ private player;
1476
+ private profile;
1477
+ private readonly fallbackCurrency;
1478
+ constructor(fallbackCurrency: string);
1479
+ setPlayer(player: Player | null, profile?: PlayerProfile | null): void;
1480
+ clear(): void;
1481
+ get playerId(): string | undefined;
1482
+ /** Resolve a playerId, preferring an explicit override; throws if neither exists. */
1483
+ requirePlayerId(override?: string): string;
1484
+ /** Resolve a currency: override → profile → configured default. */
1485
+ resolveCurrency(override?: string): string;
1486
+ snapshot(): SessionSnapshot;
1487
+ }
1488
+
1489
+ /**
1490
+ * `sdk.auth` — signup, login, logout, refresh, me, social OAuth, and sessions
1491
+ * ("your devices").
1492
+ *
1493
+ * Maps to the runtime's `/auth/player/*` routes. Auth is cookie-based: the runtime
1494
+ * sets `cwe_access_token` / `cwe_refresh_token` (HttpOnly) and `cwe_csrf` (readable);
1495
+ * the SDK's HTTP layer carries the session and CSRF automatically. After a
1496
+ * successful auth call the {@link Session} cache is populated so wallet/cashier/launch
1497
+ * calls can auto-fill `playerId` + `currency`.
1498
+ */
1499
+
1500
+ interface SocialStartOptions {
1501
+ /**
1502
+ * Where the runtime should send the player back after the provider flow.
1503
+ * Use `https:` URLs only — a non-https `redirectUri` (or worse, a scheme like
1504
+ * `javascript:`) must never reach a browser navigation. The runtime validates
1505
+ * it against the tenant's allowlist; keep your allowlist https-only too.
1506
+ */
1507
+ redirectUri?: string;
1508
+ }
1509
+ declare class AuthModule {
1510
+ private readonly http;
1511
+ private readonly session;
1512
+ private readonly baseUrl;
1513
+ constructor(http: HttpClient, session: Session, baseUrl: string);
1514
+ /** Create an account and start a session. */
1515
+ signup(input: SignupInput): Promise<AuthSession>;
1516
+ /** Log in with email + password and start a session. */
1517
+ login(input: LoginInput): Promise<AuthSession>;
1518
+ /** End the session and clear the cached player. */
1519
+ logout(): Promise<void>;
1520
+ /**
1521
+ * Rotate the session using the refresh cookie. Called automatically by the HTTP
1522
+ * layer on a 401; you rarely call it directly.
1523
+ *
1524
+ * The request is marked `_noRefresh`: a 401 here (fully logged out) must throw
1525
+ * immediately instead of re-entering the 401 → refresh path it is part of.
1526
+ */
1527
+ refresh(): Promise<AuthSession>;
1528
+ /** Current player + profile. Refreshes the session cache (incl. default currency). */
1529
+ me(): Promise<MeResponse>;
1530
+ readonly social: {
1531
+ /**
1532
+ * Build the URL that begins a social login. Send the browser here (full
1533
+ * navigation, not fetch) so the runtime can redirect to the provider.
1534
+ */
1535
+ startUrl: (provider: SocialProvider, options?: SocialStartOptions) => string;
1536
+ /**
1537
+ * Complete the OAuth callback (provider → your app) by exchanging `code`+`state`.
1538
+ * Use this if your app handles the callback route itself; otherwise the runtime
1539
+ * handles `/auth/player/social/:provider/callback` directly.
1540
+ */
1541
+ callback: (provider: SocialProvider, params: {
1542
+ code?: string;
1543
+ state?: string;
1544
+ hash?: string;
1545
+ }) => Promise<AuthSession>;
1546
+ /** Link a social account to the logged-in player. */
1547
+ link: (provider: SocialProvider, code: string) => Promise<{
1548
+ account: SocialAccount;
1549
+ }>;
1550
+ /** Unlink a previously-linked social account. */
1551
+ unlink: (provider: SocialProvider, socialAccountId: string) => Promise<{
1552
+ success: true;
1553
+ }>;
1554
+ };
1555
+ /**
1556
+ * Session management — the "your devices" surface. The runtime scopes every call
1557
+ * to the authenticated player (the id comes from the verified principal, never a
1558
+ * path), so a player can only see and revoke their own sessions.
1559
+ */
1560
+ readonly sessions: {
1561
+ /** Active sessions — the player's currently signed-in devices. */
1562
+ list: () => Promise<SafeSession[]>;
1563
+ /**
1564
+ * Full session history — active plus revoked/expired, newest first. Paginated:
1565
+ * `limit` 1–100 (default 50), `offset` ≥ 0; `pagination.hasMore` says whether
1566
+ * another page exists.
1567
+ */
1568
+ history: (query?: SessionHistoryQuery) => Promise<SessionHistoryPage>;
1569
+ /** Disconnect (revoke) one of the player's own sessions. */
1570
+ revoke: (sessionId: string) => Promise<{
1571
+ success: true;
1572
+ }>;
1573
+ /**
1574
+ * Revoke every session. By default the current one survives ("sign out
1575
+ * everywhere else"); pass `{ exceptCurrent: false }` to revoke this device
1576
+ * too (the runtime then also clears the auth cookies).
1577
+ */
1578
+ revokeAll: (options?: {
1579
+ exceptCurrent?: boolean;
1580
+ }) => Promise<{
1581
+ revoked: number;
1582
+ }>;
1583
+ };
1584
+ /**
1585
+ * Login history (successful and failed attempts, newest first). Paginated:
1586
+ * `limit` 1–100 (default 50), `offset` ≥ 0.
1587
+ */
1588
+ loginHistory(query?: SessionHistoryQuery): Promise<LoginHistoryPage>;
1589
+ /** Password management. The reset flow is anonymous; `change` needs a session. */
1590
+ readonly password: {
1591
+ /**
1592
+ * Change the password (requires the current one). The runtime revokes every
1593
+ * OTHER session; this one survives. Rate-limited 10/h per player.
1594
+ */
1595
+ change: (input: {
1596
+ currentPassword: string;
1597
+ newPassword: string;
1598
+ }) => Promise<{
1599
+ success: true;
1600
+ }>;
1601
+ /**
1602
+ * Request a password-reset email. Always resolves `{ success: true }`
1603
+ * (anti-enumeration) — even for unknown emails or while rate-limited.
1604
+ */
1605
+ requestReset: (email: string) => Promise<{
1606
+ success: true;
1607
+ }>;
1608
+ /**
1609
+ * Complete a reset with the emailed token. Revokes ALL sessions — the
1610
+ * player must log in again.
1611
+ */
1612
+ confirmReset: (input: {
1613
+ token: string;
1614
+ newPassword: string;
1615
+ }) => Promise<{
1616
+ success: true;
1617
+ }>;
1618
+ };
1619
+ /**
1620
+ * Email/phone verification. `request` sends the token/OTP (429 with
1621
+ * `details.resendIn` inside the cooldown); `confirm` verifies it.
1622
+ */
1623
+ readonly verification: {
1624
+ email: {
1625
+ request: () => Promise<VerificationRequestResult>;
1626
+ /** Confirm with the emailed link `token` XOR the 6-digit `code` (code needs a session). */
1627
+ confirm: (input: {
1628
+ token?: string;
1629
+ code?: string;
1630
+ }) => Promise<{
1631
+ verified: true;
1632
+ }>;
1633
+ };
1634
+ phone: {
1635
+ /** Pass `phone` to verify a NEW number (applied on confirm). */
1636
+ request: (phone?: string) => Promise<VerificationRequestResult>;
1637
+ confirm: (code: string) => Promise<{
1638
+ verified: true;
1639
+ }>;
1640
+ };
1641
+ };
1642
+ }
1643
+
1644
+ /**
1645
+ * `sdk.cashier` — deposits & withdrawals.
1646
+ *
1647
+ * Maps to `POST /cashier/deposits` and `POST /cashier/withdrawals`. These are money
1648
+ * operations: the HTTP layer auto-generates an idempotency key (body + header), and
1649
+ * the SDK auto-fills `playerId` + `currency` from the session. Amounts are passed in
1650
+ * minor units and converted to the plain major-unit number the runtime's write
1651
+ * schemas require; any `balances` in the response (4-dp decimal strings) are
1652
+ * converted back to minor units.
1653
+ */
1654
+
1655
+ declare class CashierModule {
1656
+ private readonly http;
1657
+ private readonly session;
1658
+ constructor(http: HttpClient, session: Session);
1659
+ /**
1660
+ * Initiate a deposit. Follow `result.nextAction` for any PSP redirect/3DS step;
1661
+ * a `result.challenge` means a gate plugin requires a step-up (e.g. KYC) first.
1662
+ */
1663
+ deposit(input: DepositInput): Promise<DepositResult>;
1664
+ /** Request a withdrawal. May land in `pending_review` depending on risk rules. */
1665
+ withdraw(input: WithdrawalInput): Promise<WithdrawalResult>;
1666
+ /**
1667
+ * The payment methods available to the player (`GET /player/cashier/methods`),
1668
+ * sorted for display; `limits` in minor units. Cached 60s server-side.
1669
+ */
1670
+ listMethods(options?: {
1671
+ currency?: string;
1672
+ }): Promise<PaymentMethod[]>;
1673
+ /** Deposit history, newest first, amounts in minor units. */
1674
+ deposits(query?: DepositHistoryQuery): Promise<DepositHistoryPage>;
1675
+ /**
1676
+ * One deposit with its wallet linkage and any pending `nextAction`
1677
+ * (`GET /player/cashier/deposits/:id`). Realtime `wallet.deposit` remains the
1678
+ * push channel; this is the authoritative re-read.
1679
+ */
1680
+ depositStatus(depositId: string): Promise<DepositDetail>;
1681
+ /** Withdrawal history, newest first, amounts in minor units. */
1682
+ withdrawals(query?: WithdrawalHistoryQuery): Promise<WithdrawalHistoryPage>;
1683
+ /** One withdrawal with its reserve/settle/release wallet-transaction legs. */
1684
+ withdrawalStatus(withdrawalId: string): Promise<WithdrawalDetail>;
1685
+ /**
1686
+ * Cancel a withdrawal that hasn't been picked up yet (`requested`/
1687
+ * `pending_review` only — anything later is a `ConflictError` with code
1688
+ * `INVALID_WITHDRAWAL_STATE`). Releases the reserved funds; idempotent
1689
+ * (a replay returns `idempotent: true` without balances).
1690
+ */
1691
+ cancelWithdrawal(withdrawalId: string): Promise<WithdrawalResult>;
1692
+ }
1693
+
1694
+ /**
1695
+ * `sdk.wallet` — balance buckets, transaction history, and the append-only ledger.
1696
+ *
1697
+ * Maps to `GET /wallet/balance`, `GET /wallet/transactions`, and `GET /wallet/ledger`.
1698
+ * All take the player's id (auto-filled from the session); balance also takes a
1699
+ * currency (defaults to the profile/config currency). All money is converted to
1700
+ * scale-4 minor units here.
1701
+ */
1702
+
1703
+ declare class WalletModule {
1704
+ private readonly http;
1705
+ private readonly session;
1706
+ constructor(http: HttpClient, session: Session);
1707
+ /** Current balance across the cash/bonus/locked buckets, in minor units. */
1708
+ getBalance(options?: {
1709
+ playerId?: string;
1710
+ currency?: string;
1711
+ }): Promise<BalanceResponse>;
1712
+ /** Paginated transaction history (newest first), amounts in minor units. */
1713
+ transactions(query?: TransactionsQuery): Promise<Paginated<WalletTransaction>>;
1714
+ /**
1715
+ * Paginated append-only ledger (newest first) — one row per bucket movement,
1716
+ * with before/after balance snapshots, amounts in minor units. Filter by
1717
+ * `transactionId` to see the legs of a single transaction.
1718
+ */
1719
+ ledger(query?: LedgerQuery): Promise<Paginated<LedgerEntry>>;
1720
+ /**
1721
+ * Fetch a single transaction by id.
1722
+ *
1723
+ * @remarks Not available to players yet — the runtime route
1724
+ * `GET /wallet/transactions/:id` requires staff permission. Tracked on the
1725
+ * roadmap; use {@link transactions} to page history in the meantime.
1726
+ */
1727
+ getTransaction(_id: string): Promise<WalletTransaction>;
1728
+ }
1729
+
1730
+ /**
1731
+ * `sdk.catalog` — lobby, search, categories tree, providers, game detail,
1732
+ * suggested, and trending. All endpoints are public and geo/currency-aware via
1733
+ * query params (`country`, `currency`, `locale`, `device`).
1734
+ *
1735
+ * Maps to the runtime's `/catalog/*` routes.
1736
+ */
1737
+
1738
+ declare class CatalogModule {
1739
+ private readonly http;
1740
+ constructor(http: HttpClient);
1741
+ /** The default lobby, filtered by geo/currency/device. */
1742
+ lobby(query?: LobbyQuery): Promise<GamePage>;
1743
+ /** Search/filter games by text, provider, category, and feature flags. */
1744
+ searchGames(query?: SearchQuery): Promise<GamePage>;
1745
+ /** Trending games over a window (`"all"` by default), most popular first. */
1746
+ trending(query?: GeoQuery & {
1747
+ window?: string;
1748
+ limit?: number;
1749
+ }): Promise<Game[]>;
1750
+ /** The localized category tree (recursive `children`). */
1751
+ categories(options?: {
1752
+ locale?: string;
1753
+ }): Promise<CategoryNode[]>;
1754
+ /** All enabled providers for this brand/region. */
1755
+ providers(query?: GeoQuery): Promise<Provider[]>;
1756
+ /** A single game by internal id or slug. */
1757
+ game(idOrSlug: string, query?: GeoQuery): Promise<Game>;
1758
+ /**
1759
+ * Games suggested alongside the given game. Takes the internal game **id** only
1760
+ * (an unknown id — including a slug — yields an empty list, not a 404).
1761
+ */
1762
+ suggested(gameId: string, query?: GeoQuery & {
1763
+ limit?: number;
1764
+ }): Promise<Game[]>;
1765
+ }
1766
+
1767
+ /**
1768
+ * `sdk.ext` — plugin actions: player-facing features that tenant-enabled plugins
1769
+ * expose on the casino API.
1770
+ *
1771
+ * ```ts
1772
+ * // Discovery
1773
+ * const catalog = await sdk.ext.catalog();
1774
+ * const cashback = await sdk.ext.plugin("cashback");
1775
+ *
1776
+ * // Generic — works for any enabled plugin, no build-time knowledge:
1777
+ * const summary = await sdk.ext("cashback").call("getSummary");
1778
+ * await sdk.ext("cashback").call("claim", { periodId });
1779
+ *
1780
+ * // Typed — when the plugin's generated client package is installed, the
1781
+ * // ExtRegistry augmentation narrows call() keys/input/result (see types/ext.ts).
1782
+ * ```
1783
+ *
1784
+ * `call()` resolves the action descriptor from the cached catalog
1785
+ * (`GET /api/ext/_catalog`, ETag-revalidated, `Cache-Control: max-age` honored),
1786
+ * routes input per the action's method (GET/DELETE ⇒ query, POST/PUT ⇒ JSON body,
1787
+ * `:name` path params substituted from matching top-level input keys), and
1788
+ * auto-generates an `Idempotency-Key` for idempotent mutations. The key travels
1789
+ * as a header only — plugin bodies validate `.strict()`.
1790
+ *
1791
+ * Dev-mode only: input is best-effort checked against the action's JSON schema
1792
+ * (`console.warn`, never a client-side throw — the server's Zod is
1793
+ * authoritative), and `deprecated` actions warn once per action per client.
1794
+ *
1795
+ * Money note: plugin payloads are opaque to the SDK, so no minor-unit conversion
1796
+ * happens here — consult the plugin's own docs for its money shapes.
1797
+ */
1798
+
1799
+ interface ExtCatalogOptions {
1800
+ /** Bypass the cache and refetch unconditionally. */
1801
+ force?: boolean;
1802
+ }
1803
+ /**
1804
+ * The `sdk.ext` surface: callable for a per-plugin handle, plus catalog
1805
+ * discovery. Fully lazy — nothing is fetched until an action is called or the
1806
+ * catalog is requested, and a broken catalog endpoint never affects non-ext SDK
1807
+ * usage.
1808
+ */
1809
+ interface ExtModule {
1810
+ /** Typed handle — `pluginKey` is registered in {@link ExtRegistry} (generated client installed). */
1811
+ <K extends keyof ExtRegistry & string>(pluginKey: K): TypedExtPluginClient<ExtRegistry[K]>;
1812
+ /** Generic handle for any enabled plugin; no build-time knowledge needed. */
1813
+ (pluginKey: string): ExtPluginClient;
1814
+ /**
1815
+ * The tenant's plugin catalog. Cached in-memory per `Cache-Control: max-age`
1816
+ * (default 60s) and revalidated via ETag once stale; `{ force: true }`
1817
+ * refetches unconditionally. Concurrent callers share one in-flight fetch.
1818
+ */
1819
+ catalog(opts?: ExtCatalogOptions): Promise<ExtCatalog>;
1820
+ /**
1821
+ * One plugin's catalog entry, straight from
1822
+ * `GET /api/ext/_catalog/:pluginKey`. Rejects with
1823
+ * {@link PluginNotEnabledError} when the plugin is not enabled (404).
1824
+ */
1825
+ plugin(pluginKey: string): Promise<ExtCatalogPlugin>;
1826
+ }
1827
+ /**
1828
+ * Runtime guard for generated plugin clients: throws
1829
+ * {@link PluginVersionMismatchError} when the installed plugin's **major**
1830
+ * version differs from the expected range's major. `expectedRange` accepts the
1831
+ * common single-major forms a generator emits: `"1"`, `"1.x"`, `"1.2.3"`,
1832
+ * `"^1.2.3"`, `"~1.2"`, `"=1.0.0"`, `"v1"`.
1833
+ */
1834
+ declare function assertPluginVersion(catalogEntry: ExtCatalogPlugin, expectedRange: string): void;
1835
+
1836
+ /**
1837
+ * `sdk.games` — launch a game session.
1838
+ *
1839
+ * `providerSession` maps to the generic `POST /providers/:provider/session` and
1840
+ * returns a fully-formed `launchUrl` to render in the game iframe plus a
1841
+ * `sessionId`. Provider adapters are registered per tenant in the runtime
1842
+ * (built-in `"fake"` for dev, or plugin-contributed adapters). The SDK never
1843
+ * sees provider secrets; all money flows server-side through the provider →
1844
+ * wallet (and pushes back over the realtime `wallet.balance` channel).
1845
+ *
1846
+ * `launch` is a stub: the runtime removed its route (`POST
1847
+ * /plugins/slotserv/launch`) together with the baked-in SlotServ plugin
1848
+ * (runtime `16d4e5d`); it throws `NotImplementedError` until an aggregation
1849
+ * plugin ships a launch surface again.
1850
+ */
1851
+
1852
+ /**
1853
+ * Assert a game `launchUrl` is safe to render in an iframe: `https:` only
1854
+ * (`http:` tolerated for loopback hosts so local dev runtimes keep working).
1855
+ * `javascript:`, `data:`, and every other scheme are rejected — a compromised or
1856
+ * misconfigured provider must not be able to hand the frontend a script URL.
1857
+ *
1858
+ * The SDK applies this to every launch result; it is exported so app code can
1859
+ * re-validate URLs it stored or received elsewhere. Also render the iframe with
1860
+ * `sandbox="allow-scripts allow-same-origin allow-forms"` (see the games guide).
1861
+ *
1862
+ * @returns the URL, unchanged, for fluent use.
1863
+ * @throws ValidationError (`LAUNCH_URL_INVALID`, status 0) when the URL is unsafe.
1864
+ */
1865
+ declare function assertLaunchUrl(url: string): string;
1866
+ declare class GamesModule {
1867
+ private readonly http;
1868
+ private readonly session;
1869
+ constructor(http: HttpClient, session: Session);
1870
+ /**
1871
+ * @deprecated The runtime removed the SlotServ aggregation route
1872
+ * (`POST /plugins/slotserv/launch`) along with its baked-in plugins
1873
+ * (runtime `16d4e5d`, 2026-07-10) — this now always throws
1874
+ * {@link NotImplementedError}. Launch through a tenant-registered provider
1875
+ * adapter instead: {@link providerSession}. It returns the same
1876
+ * `{ launchUrl, sessionId }` shape.
1877
+ */
1878
+ launch(gameId: string, _input?: LaunchInput): Promise<LaunchResult>;
1879
+ /**
1880
+ * Open a game session with a specific provider adapter via the generic
1881
+ * `POST /providers/:provider/session` route (provider-agnostic counterpart of
1882
+ * {@link launch}). Currency defaults from the session.
1883
+ */
1884
+ providerSession(provider: string, gameId: string, options?: {
1885
+ playerId?: string;
1886
+ currency?: string;
1887
+ }): Promise<LaunchResult>;
1888
+ /** Bet history (`GET /player/bets`), newest first, amounts in minor units. */
1889
+ bets(query?: BetsQuery): Promise<BetsPage>;
1890
+ /** One bet plus its round-linked wallet transactions (`GET /player/bets/:betId`). */
1891
+ bet(betId: string): Promise<BetDetail>;
1892
+ /** Game-session history with per-session bet/win totals in minor units. */
1893
+ gameSessions(query?: {
1894
+ from?: string | Date;
1895
+ to?: string | Date;
1896
+ limit?: number;
1897
+ offset?: number;
1898
+ }): Promise<GameSessionsPage>;
1899
+ }
1900
+
1901
+ /**
1902
+ * `sdk.kyc` — the player-side KYC surface (`/player/kyc/*`).
1903
+ *
1904
+ * Flow: {@link status} says where the player stands and whether the withdrawal
1905
+ * gate is met; {@link requirements} lists the open requests with their document
1906
+ * checklists; {@link uploadDocument} sends files (multipart; JPEG/PNG/PDF,
1907
+ * sniffed server-side); {@link submit} hands a completed request to review.
1908
+ * Players can never download their documents — item `document` objects are
1909
+ * metadata only. Live status pushes arrive on the realtime `player` channel
1910
+ * (`kyc_status_changed` / `kyc_documents_requested`).
1911
+ *
1912
+ * If the tenant delegates the KYC flow to a plugin, mutations throw
1913
+ * {@link FlowDelegatedError} — drive the plugin's `/api/ext` routes via
1914
+ * `sdk.ext` instead.
1915
+ */
1916
+
1917
+ declare class KycModule {
1918
+ private readonly http;
1919
+ constructor(http: HttpClient);
1920
+ /** Verification level, per-gate requirements, and email/phone verification flags. */
1921
+ status(): Promise<KycStatusResponse>;
1922
+ /** Open KYC requests (draft/submitted/in_review/needs_more) with their checklists. */
1923
+ requirements(): Promise<KycRequest[]>;
1924
+ /** All requests, newest first. `limit` 1–100 (default 50). */
1925
+ history(query?: {
1926
+ limit?: number;
1927
+ offset?: number;
1928
+ }): Promise<KycHistoryPage>;
1929
+ /**
1930
+ * Upload a document. With `requestId` it attaches to that request (which must
1931
+ * be `draft`/`needs_more`); without, it is a proactive re-verification
1932
+ * upload. Rejections are `ValidationError` with code `KYC_DOCUMENT_INVALID`
1933
+ * (format/size/expiry — see `details`).
1934
+ *
1935
+ * Large files on slow uplinks can outlive the client's default request
1936
+ * timeout (30s) — raise or disable it per call via `options.timeoutMs`
1937
+ * (`0` disables).
1938
+ */
1939
+ uploadDocument(input: KycUploadInput, options?: {
1940
+ timeoutMs?: number;
1941
+ signal?: AbortSignal;
1942
+ }): Promise<KycUploadResult>;
1943
+ /**
1944
+ * Submit a request for review. Every `required` checklist item needs an
1945
+ * uploaded/approved document first — otherwise `ValidationError` with
1946
+ * `details.missing` listing the absent `documentTypeKey`s.
1947
+ */
1948
+ submit(requestId: string): Promise<{
1949
+ status: "submitted";
1950
+ }>;
1951
+ }
1952
+
1953
+ /**
1954
+ * `sdk.player` — profile, preferences, consents, responsible-gaming limits, and
1955
+ * account lifecycle (close / GDPR export).
1956
+ *
1957
+ * Maps to the runtime's `/player/*` account surface. Responsible-gaming limit
1958
+ * values ride the wire as scale-4 minor-unit integer *strings* (minutes for
1959
+ * `session_time`); the SDK converts them to `MinorUnits` numbers at the
1960
+ * boundary. KYC lives at `sdk.kyc`.
1961
+ */
1962
+
1963
+ declare class PlayerModule {
1964
+ private readonly http;
1965
+ private readonly auth;
1966
+ constructor(http: HttpClient, auth: AuthModule);
1967
+ /** The logged-in player's identity + profile (via `/auth/player/me`). */
1968
+ getProfile(): Promise<MeResponse>;
1969
+ /**
1970
+ * The full profile row plus which identity fields are KYC-locked
1971
+ * (`GET /player/profile`). `profile` is null until one exists.
1972
+ */
1973
+ profile(): Promise<ProfileResponse>;
1974
+ /**
1975
+ * Patch the profile (`PATCH /player/profile`). At least one field; `null`
1976
+ * clears. Identity fields (`firstName`/`lastName`/`birthDate`/`country`)
1977
+ * throw `ConflictError` (`PROFILE_FIELD_LOCKED`) after KYC approval.
1978
+ */
1979
+ updateProfile(patch: UpdateProfileInput): Promise<UpdateProfileResult>;
1980
+ /** Preferences (locale, display currency, marketing consents, reality check). */
1981
+ getPreferences(): Promise<PlayerPreferences>;
1982
+ /**
1983
+ * Update preferences (`PUT /player/preferences`, partial — at least one
1984
+ * field). Marketing changes are recorded on the consent trail; set
1985
+ * `realityCheckMinutes: null` to disable the reality check.
1986
+ */
1987
+ setPreferences(patch: SetPreferencesInput): Promise<PlayerPreferences>;
1988
+ /** The append-only marketing-consent trail, newest first. */
1989
+ consents(query?: {
1990
+ limit?: number;
1991
+ offset?: number;
1992
+ }): Promise<ConsentsPage>;
1993
+ /**
1994
+ * Active responsible-gaming limits, values in minor units (minutes for
1995
+ * `session_time`). `pending` carries a ratcheted increase/removal and when it
1996
+ * applies.
1997
+ */
1998
+ getLimits(): Promise<PlayerLimit[]>;
1999
+ /**
2000
+ * Set/remove limits (`PUT /player/limits`). `value` in minor units (minutes
2001
+ * for `session_time`); `null` removes. New limits and decreases apply
2002
+ * immediately; increases/removals apply after the 24h ratchet cooldown
2003
+ * (returned in `pending`).
2004
+ */
2005
+ setLimits(limits: SetLimitInput[]): Promise<PlayerLimit[]>;
2006
+ /** Responsible-gaming actions beyond limits. */
2007
+ readonly rg: {
2008
+ /**
2009
+ * Start a cooling-off period (blocks gameplay + deposits; login and
2010
+ * withdrawals stay). Extend-only — a shorter period than the active one is
2011
+ * a `ConflictError`.
2012
+ */
2013
+ coolOff: (period: CoolOffPeriod) => Promise<{
2014
+ success: true;
2015
+ until: string;
2016
+ }>;
2017
+ /**
2018
+ * Self-exclude. Irreversible player-side; revokes every session (including
2019
+ * this one). `until` is null for `"permanent"`.
2020
+ */
2021
+ selfExclude: (period: SelfExclusionPeriod) => Promise<{
2022
+ success: true;
2023
+ until: string | null;
2024
+ }>;
2025
+ /** Acknowledge a reality-check prompt (audit trail only). */
2026
+ acknowledgeRealityCheck: (gameSessionId?: string) => Promise<{
2027
+ success: true;
2028
+ }>;
2029
+ };
2030
+ /** Presence signals. */
2031
+ readonly presence: {
2032
+ /**
2033
+ * Tell the runtime this player is still here (`POST
2034
+ * /player/presence/heartbeat`, 204). Any authenticated request already
2035
+ * refreshes presence server-side — call this only for clients that idle
2036
+ * while "in play" (e.g. a game iframe generates provider callbacks, not
2037
+ * player API traffic). Best-effort on the server: a storage blip never
2038
+ * fails the request; presence decays via TTL and heals on the next call.
2039
+ */
2040
+ heartbeat: () => Promise<void>;
2041
+ };
2042
+ /** Account lifecycle. */
2043
+ readonly account: {
2044
+ /**
2045
+ * Close the account (idempotent). Requires zero balances and no pending
2046
+ * withdrawal — otherwise `ConflictError` with code `BALANCE_REMAINING` or
2047
+ * `WITHDRAWAL_PENDING`. Revokes every session.
2048
+ */
2049
+ close: (reason?: string) => Promise<{
2050
+ success: true;
2051
+ }>;
2052
+ /**
2053
+ * Request a GDPR data export (202; one active at a time — a second request
2054
+ * while pending/processing is a `ConflictError`). The download link is
2055
+ * delivered out-of-band.
2056
+ */
2057
+ requestDataExport: () => Promise<DataExportStatus>;
2058
+ /** Latest export request, or `{ status: "none" }` if never requested. */
2059
+ dataExportStatus: () => Promise<DataExportStatus>;
2060
+ };
2061
+ }
2062
+
2063
+ /**
2064
+ * `sdk.realtime` — the realtime gateway, pre-wired with the ticket handshake.
2065
+ *
2066
+ * Flow: `POST /realtime/ticket` (cookie-authenticated, via the HTTP layer) →
2067
+ * `{ ticket }` → open the WS → send `{ type: "auth", token }`. In the browser the
2068
+ * same-site HttpOnly cookie can authenticate the upgrade directly; the ticket path
2069
+ * is used everywhere for portability and to survive access-token expiry.
2070
+ *
2071
+ * This is a thin delegate over the standalone {@link createRealtimeClient} so it
2072
+ * shares the SDK's session/config and you don't pass `url`/`getAuthCredential`.
2073
+ */
2074
+
2075
+ /** Realtime options you can pass to `createCasinoClient({ realtime })`. */
2076
+ interface RealtimeOptions {
2077
+ /** Reconcile missed state after every (re)connect; the SDK calls this for you. */
2078
+ resync?: (ctx: {
2079
+ since?: string;
2080
+ }) => Promise<void>;
2081
+ backoff?: {
2082
+ baseMs?: number;
2083
+ maxMs?: number;
2084
+ factor?: number;
2085
+ };
2086
+ heartbeatMs?: number;
2087
+ dedupeWindow?: number;
2088
+ /** Node only: pass `ws` (`import WebSocket from "ws"`). */
2089
+ WebSocketImpl?: WebSocketImpl;
2090
+ }
2091
+ declare class RealtimeModule {
2092
+ private readonly http;
2093
+ private readonly wsUrl;
2094
+ private readonly options;
2095
+ private client;
2096
+ constructor(http: HttpClient, wsUrl: string, options?: RealtimeOptions);
2097
+ /** Fetch a single-use socket ticket from the gateway. */
2098
+ ticket(): Promise<{
2099
+ ticket: string;
2100
+ expiresIn: number;
2101
+ }>;
2102
+ private ensure;
2103
+ get state(): ConnectionState;
2104
+ /** Open the socket and authenticate. Call once after login. */
2105
+ connect(): Promise<void>;
2106
+ /** Close intentionally (call on logout). Stops auto-reconnect. */
2107
+ disconnect(): Promise<void>;
2108
+ /** Subscribe to a channel with a typed handler. Returns an unsubscribe fn. */
2109
+ on<C extends RealtimeChannel>(channel: C, handler: (event: ChannelEventMap[C]) => void): Unsubscribe;
2110
+ subscribe(channels: readonly RealtimeChannel[]): Promise<void>;
2111
+ unsubscribe(channels: readonly RealtimeChannel[]): Promise<void>;
2112
+ withSubscription<T>(channels: readonly RealtimeChannel[], scope: () => Promise<T>): Promise<T>;
2113
+ activeChannels(): readonly RealtimeChannel[];
2114
+ onStateChange(handler: (state: ConnectionState) => void): Unsubscribe;
2115
+ onError(handler: (error: RealtimeError) => void): Unsubscribe;
2116
+ }
2117
+
2118
+ /**
2119
+ * `createCasinoClient` — the framework-agnostic entry point.
2120
+ *
2121
+ * Composes the HTTP layer + session cache + every module into one object:
2122
+ * `{ auth, cashier, wallet, catalog, games, player, realtime, ... }`. Construct it
2123
+ * once and share it (e.g. via the React `CasinoProvider`).
2124
+ */
2125
+
2126
+ interface CreateCasinoClientConfig extends CasinoClientConfig {
2127
+ /** Options for `sdk.realtime` (resync hook, backoff, Node WebSocket, …). */
2128
+ realtime?: RealtimeOptions;
2129
+ }
2130
+ interface CasinoClient {
2131
+ readonly affiliate: AffiliateModule;
2132
+ readonly auth: AuthModule;
2133
+ readonly cashier: CashierModule;
2134
+ readonly wallet: WalletModule;
2135
+ readonly catalog: CatalogModule;
2136
+ /**
2137
+ * Plugin actions: `sdk.ext(pluginKey).call(actionKey, input)` plus catalog
2138
+ * discovery (`sdk.ext.catalog()` / `sdk.ext.plugin(key)`).
2139
+ */
2140
+ readonly ext: ExtModule;
2141
+ readonly games: GamesModule;
2142
+ /** Player-side KYC: status, requirements, document upload, submit. */
2143
+ readonly kyc: KycModule;
2144
+ readonly player: PlayerModule;
2145
+ readonly realtime: RealtimeModule;
2146
+ /** A snapshot of the cached player/profile/currency (no network call). */
2147
+ getSession(): SessionSnapshot;
2148
+ /**
2149
+ * A fully isolated scope of this client bound to `jar`: same configuration, fresh
2150
+ * HTTP pipeline, fresh session cache — nothing (cookies, CSRF, cached player) is
2151
+ * shared with this client or any other scope.
2152
+ *
2153
+ * THE way to use the SDK server-side (Next.js route handlers, RSC, API routes):
2154
+ * a module-scope client is safe in the browser (one user per tab) but on a server
2155
+ * it is shared across every user's requests, so its jar would replay user A's
2156
+ * auth cookies on user B's request. Create one scope per incoming request:
2157
+ *
2158
+ * ```ts
2159
+ * const scoped = client.withCookies(new CookieJar());
2160
+ * await scoped.auth.login(credentials); // cookies stay inside this scope
2161
+ * ```
2162
+ */
2163
+ withCookies(jar: CookieJar): CasinoClient;
2164
+ }
2165
+ declare function createCasinoClient(config: CreateCasinoClientConfig): CasinoClient;
2166
+
2167
+ export { InsufficientFundsError as $, type AffiliateSubIds as A, type BalanceResponse as B, COOKIE as C, type DataExportStatus as D, type ExtActionInput as E, type ExtActionShape as F, type ExtCallArgs as G, type ExtCallOpts as H, type ExtCatalog as I, type ExtCatalogOptions as J, type ExtCatalogPlugin as K, type ExtMethod as L, type ExtModule as M, type ExtPluginClient as N, type ExtRegistry as O, type ExtRequestInit as P, type FetchLike as Q, FlowDelegatedError as R, ForbiddenError as S, type Game as T, type GameFeatures as U, type GamePage as V, type GameSession as W, type GameSessionsPage as X, type GeoQuery as Y, HEADER as Z, type HistoryRangeQuery as _, type AppErrorEnvelope as a, type SocialProvider as a$, type KycChecklistItem as a0, type KycDocumentStatus as a1, type KycHistoryEntry as a2, type KycHistoryPage as a3, type KycItemDocument as a4, type KycRequest as a5, type KycRequestStatus as a6, type KycStatusResponse as a7, type KycTrigger as a8, type KycUploadInput as a9, type PlayerPreferences as aA, type PlayerProfile as aB, type PlayerProfileRecord as aC, type PlayerStatus as aD, type PluginActionDescriptor as aE, PluginActionNotFoundError as aF, type PluginFrontendDecl as aG, PluginNotEnabledError as aH, PluginUnavailableError as aI, PluginVersionMismatchError as aJ, type ProfileResponse as aK, type Provider as aL, RateLimitError as aM, type RealtimeOptions as aN, RgBlockedError as aO, type SafeSession as aP, type SearchQuery as aQ, type SelfExclusionPeriod as aR, ServerError as aS, type SessionHistoryPage as aT, type SessionHistoryQuery as aU, type SessionSnapshot as aV, type SetLimitInput as aW, type SetPreferencesInput as aX, type SignupAttribution as aY, type SignupInput as aZ, type SocialAccount as a_, type KycUploadResult as aa, type LaunchInput as ab, type LaunchResult as ac, type LedgerEntry as ad, type LedgerQuery as ae, LimitExceededError as af, type LimitKind as ag, type LimitPeriod as ah, type LobbyQuery as ai, type LoginAttempt as aj, type LoginHistoryPage as ak, type LoginInput as al, MONEY_SCALE as am, type MeResponse as an, type MinorUnits as ao, NetworkError as ap, NotFoundError as aq, NotImplementedError as ar, type OddsFormat as as, OperationDeniedError as at, type PageInfo as au, type Paginated as av, type PaymentMethod as aw, type Player as ax, type PlayerKycStatus as ay, type PlayerLimit as az, AuthError as b, type SocialStartOptions as b0, type TrackClickInput as b1, type TrackClickResult as b2, type TransactionStatus as b3, type TransactionType as b4, type TransactionsQuery as b5, type TypedExtPluginClient as b6, UnprocessableError as b7, type UpdateProfileInput as b8, type UpdateProfileResult as b9, type UtmParams as ba, ValidationError as bb, type VerificationRequestResult as bc, type WalletBucketName as bd, type WalletBuckets as be, type WalletTransaction as bf, type WithdrawalDetail as bg, type WithdrawalHistoryPage as bh, type WithdrawalHistoryQuery as bi, type WithdrawalInput as bj, type WithdrawalResult as bk, type WithdrawalSummary as bl, type WithdrawalTxStatus as bm, assertLaunchUrl as bn, assertPluginVersion as bo, createCasinoClient as bp, decimalToMinor as bq, formatMoney as br, isAppErrorEnvelope as bs, minorStringToMinor as bt, minorToAmount as bu, minorToDecimal as bv, type AuthSession as c, type Bet as d, type BetDetail as e, type BetStatus as f, type BetsPage as g, type BetsQuery as h, type CasinoClient as i, type CasinoClientConfig as j, CasinoSdkError as k, type CategoryNode as l, ConflictError as m, type ConsentEntry as n, type ConsentsPage as o, CookieJar as p, type CoolOffPeriod as q, type CreateCasinoClientConfig as r, type DepositDetail as s, type DepositHistoryPage as t, type DepositHistoryQuery as u, type DepositInput as v, type DepositResult as w, type DepositSummary as x, type DepositTxStatus as y, type ExtActionOutput as z };