@open-slot-ui/core 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1255,6 +1255,11 @@ declare class OpenUI {
1255
1255
  };
1256
1256
  /** Minimum round duration (ms) from jurisdiction — stored for the GAME to enforce. */
1257
1257
  minimumRoundDuration: number;
1258
+ /** Buy-feature confirm threshold, as a multiple of the base bet. A play (buy or
1259
+ * bet-mode activation) that costs STRICTLY MORE than this must show a confirm step
1260
+ * — Stake requires that bet modes above 2× never activate on a single click. `0`
1261
+ * (the default) = off. Set via `spec.buyFeature.confirmAboveCost` or a jurisdiction. */
1262
+ confirmBuyAboveCost: number;
1258
1263
  private sessionNet;
1259
1264
  private prevVolumes;
1260
1265
  /** The frozen UISpec `createUI` built this from, if any — authored = run = tested. */
@@ -1363,6 +1368,10 @@ declare class OpenUI {
1363
1368
  /** Read-back: did the applied jurisdiction disable this feature? (real guard, not
1364
1369
  * just a hide — `confirmBuy`/autoplay entry points consult this). */
1365
1370
  isDisabled(feature: 'autoplay' | 'buyFeature' | 'turbo' | 'fullscreen' | 'slamstop' | 'spacebar'): boolean;
1371
+ /** True when a buy / bet-mode activation of `cost`× the base bet must be confirmed
1372
+ * before it commits (Stake: no one-click activation above `confirmBuyAboveCost`×).
1373
+ * Always false when the threshold is 0/unset or `cost` isn't a finite number. */
1374
+ shouldConfirmBuy(cost: number): boolean;
1366
1375
  /**
1367
1376
  * Start a reality-check reminder (RTS 13). Every `everyMinutes` (WALL-CLOCK, so a
1368
1377
  * backgrounded tab can't cheat it) it emits a `realityCheck` event, stops autoplay,
@@ -1403,6 +1412,11 @@ interface JurisdictionConfig {
1403
1412
  displaySessionTimer?: boolean;
1404
1413
  /** Minimum ms a round must take — stored on the HUD for the GAME to enforce. */
1405
1414
  minimumRoundDuration?: number;
1415
+ /** Buy-feature confirm threshold (× base bet). A play costing more than this must
1416
+ * be confirmed before it commits — Stake requires that bet modes above 2× never
1417
+ * activate on a single click, so a Stake preset sets this to `2`. Not part of the
1418
+ * wallet schema; a convenience so a jurisdiction can require the confirm step. */
1419
+ confirmBuyAboveCost?: number;
1406
1420
  }
1407
1421
  /**
1408
1422
  * Apply a Stake Engine `jurisdiction` config to a live HUD — the whole switchboard
@@ -1679,6 +1693,15 @@ interface UISpec {
1679
1693
  name?: string;
1680
1694
  version?: string;
1681
1695
  };
1696
+ /** Buy-feature / bet-mode confirmation. `confirmAboveCost` (× base bet) makes any
1697
+ * play costing MORE than that require a confirm step before it commits — Stake
1698
+ * requires bet modes above 2× to never activate on a single click, so set `2`.
1699
+ * The game routes a purchase/activation through `hud.requestBuyFeature(...)`, which
1700
+ * shows the confirm popup itself when the cost exceeds the threshold. A jurisdiction
1701
+ * can set the same threshold (`JurisdictionConfig.confirmBuyAboveCost`). */
1702
+ buyFeature?: {
1703
+ confirmAboveCost?: number;
1704
+ };
1682
1705
  /** Reality-check reminder (RTS 13): open-ui runs a wall-clock timer, emits a
1683
1706
  * `realityCheck` event, stops autoplay, and (unless `showModal:false`) shows an
1684
1707
  * acknowledge modal. You supply only the cadence + text. `title`/`message` are
@@ -1895,8 +1918,9 @@ interface CurrencyInfo {
1895
1918
  /**
1896
1919
  * The Stake Engine supported-currency matrix (symbol · decimals · placement), 1:1 with
1897
1920
  * the platform's `CurrencyMeta`. Symbol placement: prefix by default, SUFFIX for the
1898
- * few that render after the amount (DKK/PLN/VND/CLP/ARS/PEN). Crypto is included for
1899
- * completeness (8-dp with a symbol) so high-precision balances also format right.
1921
+ * few that render after the amount (DKK/NOK/PLN/VND/CLP/ARS/PEN). Decimals follow the
1922
+ * ISO minor units 0 for JPY/KRW/IDR/VND/CLP, 3 for the KWD/JOD/BHD dinars (1000 fils),
1923
+ * 2 otherwise. Crypto is included (8-dp) so high-precision balances also format right.
1900
1924
  */
1901
1925
  declare const CURRENCY_TABLE: Readonly<Record<string, CurrencyInfo>>;
1902
1926
  /** True if `code` is a Stake social/sweepstakes coin (displayed "GC"/"SC"). */
package/dist/index.d.ts CHANGED
@@ -1255,6 +1255,11 @@ declare class OpenUI {
1255
1255
  };
1256
1256
  /** Minimum round duration (ms) from jurisdiction — stored for the GAME to enforce. */
1257
1257
  minimumRoundDuration: number;
1258
+ /** Buy-feature confirm threshold, as a multiple of the base bet. A play (buy or
1259
+ * bet-mode activation) that costs STRICTLY MORE than this must show a confirm step
1260
+ * — Stake requires that bet modes above 2× never activate on a single click. `0`
1261
+ * (the default) = off. Set via `spec.buyFeature.confirmAboveCost` or a jurisdiction. */
1262
+ confirmBuyAboveCost: number;
1258
1263
  private sessionNet;
1259
1264
  private prevVolumes;
1260
1265
  /** The frozen UISpec `createUI` built this from, if any — authored = run = tested. */
@@ -1363,6 +1368,10 @@ declare class OpenUI {
1363
1368
  /** Read-back: did the applied jurisdiction disable this feature? (real guard, not
1364
1369
  * just a hide — `confirmBuy`/autoplay entry points consult this). */
1365
1370
  isDisabled(feature: 'autoplay' | 'buyFeature' | 'turbo' | 'fullscreen' | 'slamstop' | 'spacebar'): boolean;
1371
+ /** True when a buy / bet-mode activation of `cost`× the base bet must be confirmed
1372
+ * before it commits (Stake: no one-click activation above `confirmBuyAboveCost`×).
1373
+ * Always false when the threshold is 0/unset or `cost` isn't a finite number. */
1374
+ shouldConfirmBuy(cost: number): boolean;
1366
1375
  /**
1367
1376
  * Start a reality-check reminder (RTS 13). Every `everyMinutes` (WALL-CLOCK, so a
1368
1377
  * backgrounded tab can't cheat it) it emits a `realityCheck` event, stops autoplay,
@@ -1403,6 +1412,11 @@ interface JurisdictionConfig {
1403
1412
  displaySessionTimer?: boolean;
1404
1413
  /** Minimum ms a round must take — stored on the HUD for the GAME to enforce. */
1405
1414
  minimumRoundDuration?: number;
1415
+ /** Buy-feature confirm threshold (× base bet). A play costing more than this must
1416
+ * be confirmed before it commits — Stake requires that bet modes above 2× never
1417
+ * activate on a single click, so a Stake preset sets this to `2`. Not part of the
1418
+ * wallet schema; a convenience so a jurisdiction can require the confirm step. */
1419
+ confirmBuyAboveCost?: number;
1406
1420
  }
1407
1421
  /**
1408
1422
  * Apply a Stake Engine `jurisdiction` config to a live HUD — the whole switchboard
@@ -1679,6 +1693,15 @@ interface UISpec {
1679
1693
  name?: string;
1680
1694
  version?: string;
1681
1695
  };
1696
+ /** Buy-feature / bet-mode confirmation. `confirmAboveCost` (× base bet) makes any
1697
+ * play costing MORE than that require a confirm step before it commits — Stake
1698
+ * requires bet modes above 2× to never activate on a single click, so set `2`.
1699
+ * The game routes a purchase/activation through `hud.requestBuyFeature(...)`, which
1700
+ * shows the confirm popup itself when the cost exceeds the threshold. A jurisdiction
1701
+ * can set the same threshold (`JurisdictionConfig.confirmBuyAboveCost`). */
1702
+ buyFeature?: {
1703
+ confirmAboveCost?: number;
1704
+ };
1682
1705
  /** Reality-check reminder (RTS 13): open-ui runs a wall-clock timer, emits a
1683
1706
  * `realityCheck` event, stops autoplay, and (unless `showModal:false`) shows an
1684
1707
  * acknowledge modal. You supply only the cadence + text. `title`/`message` are
@@ -1895,8 +1918,9 @@ interface CurrencyInfo {
1895
1918
  /**
1896
1919
  * The Stake Engine supported-currency matrix (symbol · decimals · placement), 1:1 with
1897
1920
  * the platform's `CurrencyMeta`. Symbol placement: prefix by default, SUFFIX for the
1898
- * few that render after the amount (DKK/PLN/VND/CLP/ARS/PEN). Crypto is included for
1899
- * completeness (8-dp with a symbol) so high-precision balances also format right.
1921
+ * few that render after the amount (DKK/NOK/PLN/VND/CLP/ARS/PEN). Decimals follow the
1922
+ * ISO minor units 0 for JPY/KRW/IDR/VND/CLP, 3 for the KWD/JOD/BHD dinars (1000 fils),
1923
+ * 2 otherwise. Crypto is included (8-dp) so high-precision balances also format right.
1900
1924
  */
1901
1925
  declare const CURRENCY_TABLE: Readonly<Record<string, CurrencyInfo>>;
1902
1926
  /** True if `code` is a Stake social/sweepstakes coin (displayed "GC"/"SC"). */
package/dist/index.js CHANGED
@@ -1247,6 +1247,9 @@ function validateSpec(spec) {
1247
1247
  if (spec.realityCheck != null && !(typeof spec.realityCheck.everyMinutes === "number" && spec.realityCheck.everyMinutes > 0)) {
1248
1248
  add("error", "realityCheck.everyMinutes", "bad-interval", "realityCheck.everyMinutes must be a number > 0");
1249
1249
  }
1250
+ if (spec.buyFeature?.confirmAboveCost != null && !(typeof spec.buyFeature.confirmAboveCost === "number" && Number.isFinite(spec.buyFeature.confirmAboveCost) && spec.buyFeature.confirmAboveCost >= 0)) {
1251
+ add("error", "buyFeature.confirmAboveCost", "bad-threshold", "buyFeature.confirmAboveCost must be a finite number >= 0");
1252
+ }
1250
1253
  if (spec.controls) {
1251
1254
  for (const [id, ov] of Object.entries(spec.controls)) {
1252
1255
  checkLayout(ov.layout?.anchor, `controls.${id}.layout.anchor`);
@@ -1399,6 +1402,9 @@ function applyJurisdiction(ui, jur) {
1399
1402
  if (typeof jur.minimumRoundDuration === "number" && Number.isFinite(jur.minimumRoundDuration)) {
1400
1403
  ui.minimumRoundDuration = Math.max(0, jur.minimumRoundDuration);
1401
1404
  }
1405
+ if (typeof jur.confirmBuyAboveCost === "number" && Number.isFinite(jur.confirmBuyAboveCost)) {
1406
+ ui.confirmBuyAboveCost = Math.max(0, jur.confirmBuyAboveCost);
1407
+ }
1402
1408
  }
1403
1409
 
1404
1410
  // src/notice.ts
@@ -1456,6 +1462,8 @@ var openuiDefaults = {
1456
1462
  "openui.replay": "Replay",
1457
1463
  "openui.buyFeature.title": "Buy feature",
1458
1464
  "openui.buyFeature.message": "Buy this feature now?",
1465
+ // Confirm step for a higher-cost play — {{name}} / {{price}} are interpolated.
1466
+ "openui.buyFeature.confirm": "Buy {{name}} for {{price}}?",
1459
1467
  "openui.freeSpins": "FS",
1460
1468
  // reality check (RTS 13) — {{minutes}} is interpolated by open-ui's scheduler
1461
1469
  "openui.realityCheck.title": "Reality check",
@@ -1491,6 +1499,7 @@ var openuiSocialDefaults = {
1491
1499
  "openui.err.insufficient.title": "Insufficient balance",
1492
1500
  "openui.buyFeature.title": "Play bonus",
1493
1501
  "openui.buyFeature.message": "Play this bonus now?",
1502
+ "openui.buyFeature.confirm": "Play {{name}} for {{price}}?",
1494
1503
  "openui.err.insufficient.message": "You don't have enough balance for this play.",
1495
1504
  "openui.err.limit.message": "A play limit has been reached. Please try again later."
1496
1505
  };
@@ -1553,8 +1562,18 @@ var CURRENCY_TABLE = Object.freeze({
1553
1562
  MXN: { symbol: "MX$", decimals: 2 },
1554
1563
  TRY: { symbol: "\u20BA", decimals: 2 },
1555
1564
  GBP: { symbol: "\xA3", decimals: 2 },
1565
+ NGN: { symbol: "\u20A6", decimals: 2 },
1566
+ TWD: { symbol: "NT$", decimals: 2 },
1567
+ SGD: { symbol: "SG$", decimals: 2 },
1568
+ MYR: { symbol: "RM", decimals: 2 },
1569
+ CRC: { symbol: "\u20A1", decimals: 2 },
1570
+ // three-decimal dinars (1 unit = 1000 fils) — the >2-decimal path must format these
1571
+ KWD: { symbol: "KD", decimals: 3 },
1572
+ JOD: { symbol: "JD", decimals: 3 },
1573
+ BHD: { symbol: "BD", decimals: 3 },
1556
1574
  // ── fiat — symbol AFTER the amount ───────────────────────────────────────────
1557
1575
  DKK: { symbol: "kr", decimals: 2, symbolAfter: true },
1576
+ NOK: { symbol: "kr", decimals: 2, symbolAfter: true },
1558
1577
  PLN: { symbol: "z\u0142", decimals: 2, symbolAfter: true },
1559
1578
  VND: { symbol: "\u20AB", decimals: 0, symbolAfter: true },
1560
1579
  CLP: { symbol: "CLP", decimals: 0, symbolAfter: true },
@@ -1671,6 +1690,11 @@ var OpenUI = class {
1671
1690
  gameInfo = {};
1672
1691
  /** Minimum round duration (ms) from jurisdiction — stored for the GAME to enforce. */
1673
1692
  minimumRoundDuration = 0;
1693
+ /** Buy-feature confirm threshold, as a multiple of the base bet. A play (buy or
1694
+ * bet-mode activation) that costs STRICTLY MORE than this must show a confirm step
1695
+ * — Stake requires that bet modes above 2× never activate on a single click. `0`
1696
+ * (the default) = off. Set via `spec.buyFeature.confirmAboveCost` or a jurisdiction. */
1697
+ confirmBuyAboveCost = 0;
1674
1698
  sessionNet = 0;
1675
1699
  prevVolumes = null;
1676
1700
  /** The frozen UISpec `createUI` built this from, if any — authored = run = tested. */
@@ -2020,6 +2044,13 @@ var OpenUI = class {
2020
2044
  const j = this.jurisdiction;
2021
2045
  return feature === "autoplay" && !!j.disabledAutoplay || feature === "buyFeature" && !!j.disabledBuyFeature || feature === "turbo" && !!j.disabledTurbo || feature === "fullscreen" && !!j.disabledFullscreen || feature === "slamstop" && !!j.disabledSlamstop || feature === "spacebar" && !!j.disabledSpacebar;
2022
2046
  }
2047
+ /** True when a buy / bet-mode activation of `cost`× the base bet must be confirmed
2048
+ * before it commits (Stake: no one-click activation above `confirmBuyAboveCost`×).
2049
+ * Always false when the threshold is 0/unset or `cost` isn't a finite number. */
2050
+ shouldConfirmBuy(cost) {
2051
+ const t = this.confirmBuyAboveCost;
2052
+ return t > 0 && Number.isFinite(cost) && cost > t;
2053
+ }
2023
2054
  /**
2024
2055
  * Start a reality-check reminder (RTS 13). Every `everyMinutes` (WALL-CLOCK, so a
2025
2056
  * backgrounded tab can't cheat it) it emits a `realityCheck` event, stops autoplay,
@@ -2353,6 +2384,9 @@ function createUI(spec = {}, hooks = {}) {
2353
2384
  }
2354
2385
  }
2355
2386
  }
2387
+ if (spec.buyFeature?.confirmAboveCost != null && Number.isFinite(spec.buyFeature.confirmAboveCost)) {
2388
+ ui.confirmBuyAboveCost = Math.max(0, spec.buyFeature.confirmAboveCost);
2389
+ }
2356
2390
  if (spec.jurisdiction) ui.applyJurisdiction(spec.jurisdiction);
2357
2391
  const portraitControls = {};
2358
2392
  for (const [id, layout] of Object.entries(portraitDefaultLayouts)) {