@series-inc/venus-sdk 3.0.4 → 3.1.0-beta.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.
Files changed (39) hide show
  1. package/README.md +324 -123
  2. package/dist/{AdsApi-CNGRf6j0.d.mts → AdsApi-meVfUcZy.d.mts} +37 -25
  3. package/dist/{AdsApi-CNGRf6j0.d.ts → AdsApi-meVfUcZy.d.ts} +37 -25
  4. package/dist/chunk-2PDL7CQK.mjs +26 -0
  5. package/dist/chunk-2PDL7CQK.mjs.map +1 -0
  6. package/dist/{chunk-PXWCNWJ6.mjs → chunk-EMVTVSGL.mjs} +421 -109
  7. package/dist/chunk-EMVTVSGL.mjs.map +1 -0
  8. package/dist/chunk-IZLOB7DV.mjs +343 -0
  9. package/dist/chunk-IZLOB7DV.mjs.map +1 -0
  10. package/dist/{chunk-W7IPHM67.mjs → chunk-QABXMFND.mjs} +3 -26
  11. package/dist/chunk-QABXMFND.mjs.map +1 -0
  12. package/dist/core-5JLON75E.mjs +4 -0
  13. package/dist/{core-R3FHW62G.mjs.map → core-5JLON75E.mjs.map} +1 -1
  14. package/dist/index.cjs +768 -105
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.mts +140 -25
  17. package/dist/index.d.ts +140 -25
  18. package/dist/index.mjs +5 -3
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/venus-api/index.cjs +452 -101
  21. package/dist/venus-api/index.cjs.map +1 -1
  22. package/dist/venus-api/index.d.mts +2 -2
  23. package/dist/venus-api/index.d.ts +2 -2
  24. package/dist/venus-api/index.mjs +46 -3
  25. package/dist/venus-api/index.mjs.map +1 -1
  26. package/dist/vite/index.cjs +534 -0
  27. package/dist/vite/index.cjs.map +1 -0
  28. package/dist/vite/index.mjs +527 -0
  29. package/dist/vite/index.mjs.map +1 -0
  30. package/dist/webview/index.cjs +346 -0
  31. package/dist/webview/index.cjs.map +1 -0
  32. package/dist/webview/index.d.mts +17 -0
  33. package/dist/webview/index.d.ts +17 -0
  34. package/dist/webview/index.mjs +4 -0
  35. package/dist/webview/index.mjs.map +1 -0
  36. package/package.json +19 -1
  37. package/dist/chunk-PXWCNWJ6.mjs.map +0 -1
  38. package/dist/chunk-W7IPHM67.mjs.map +0 -1
  39. package/dist/core-R3FHW62G.mjs +0 -3
@@ -1,4 +1,5 @@
1
- import { __esm, __export, __publicField, createMockDelay, MOCK_DELAYS, isWebPlatform, __toCommonJS } from './chunk-W7IPHM67.mjs';
1
+ import { createMockDelay, MOCK_DELAYS, isWebPlatform } from './chunk-QABXMFND.mjs';
2
+ import { __esm, __export, __publicField, __toCommonJS } from './chunk-2PDL7CQK.mjs';
2
3
 
3
4
  // src/rooms/VenusRoom.ts
4
5
  var VenusRoom;
@@ -306,11 +307,11 @@ var VenusMessageId = /* @__PURE__ */ ((VenusMessageId2) => {
306
307
  VenusMessageId2["H5_SIMULATION_GET_AVAILABLE_ITEMS"] = "H5_SIMULATION_GET_AVAILABLE_ITEMS";
307
308
  VenusMessageId2["H5_SIMULATION_VALIDATE_ASSIGNMENT"] = "H5_SIMULATION_VALIDATE_ASSIGNMENT";
308
309
  VenusMessageId2["H5_SIMULATION_BATCH_OPERATIONS"] = "H5_SIMULATION_BATCH_OPERATIONS";
309
- VenusMessageId2["H5_LEADERBOARD_START_RUN"] = "H5_LEADERBOARD_START_RUN";
310
+ VenusMessageId2["H5_LEADERBOARD_CREATE_SCORE_TOKEN"] = "H5_LEADERBOARD_CREATE_SCORE_TOKEN";
310
311
  VenusMessageId2["H5_LEADERBOARD_SUBMIT_SCORE"] = "H5_LEADERBOARD_SUBMIT_SCORE";
311
- VenusMessageId2["H5_LEADERBOARD_GET"] = "H5_LEADERBOARD_GET";
312
- VenusMessageId2["H5_LEADERBOARD_GET_HIGHLIGHT"] = "H5_LEADERBOARD_GET_HIGHLIGHT";
313
- VenusMessageId2["H5_LEADERBOARD_GET_PLAYER_STATS"] = "H5_LEADERBOARD_GET_PLAYER_STATS";
312
+ VenusMessageId2["H5_LEADERBOARD_GET_PAGED_SCORES"] = "H5_LEADERBOARD_GET_PAGED_SCORES";
313
+ VenusMessageId2["H5_LEADERBOARD_GET_PODIUM_SCORES"] = "H5_LEADERBOARD_GET_PODIUM_SCORES";
314
+ VenusMessageId2["H5_LEADERBOARD_GET_MY_RANK"] = "H5_LEADERBOARD_GET_MY_RANK";
314
315
  VenusMessageId2["H5_ROOM_CREATE"] = "H5_ROOM_CREATE";
315
316
  VenusMessageId2["H5_ROOM_JOIN"] = "H5_ROOM_JOIN";
316
317
  VenusMessageId2["H5_ROOM_JOIN_OR_CREATE"] = "H5_ROOM_JOIN_OR_CREATE";
@@ -3326,9 +3327,11 @@ function isPacificDaylightTime(date) {
3326
3327
 
3327
3328
  // src/time/HostTimeApi.ts
3328
3329
  var HostTimeApi = class {
3329
- constructor(rpcClient) {
3330
+ constructor(rpcClient, venusApi) {
3330
3331
  __publicField(this, "rpcClient");
3332
+ __publicField(this, "venusApi");
3331
3333
  this.rpcClient = rpcClient;
3334
+ this.venusApi = venusApi;
3332
3335
  }
3333
3336
  async requestTimeAsync() {
3334
3337
  const response = await this.rpcClient.call(
@@ -3338,13 +3341,7 @@ var HostTimeApi = class {
3338
3341
  return response;
3339
3342
  }
3340
3343
  formatTime(timestamp, options) {
3341
- let locale = "en-US";
3342
- const windowVenus = window.venus;
3343
- if (windowVenus._config.locale) {
3344
- locale = windowVenus._config.locale;
3345
- } else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
3346
- locale = windowVenus._config.environment.browserInfo.language;
3347
- }
3344
+ const locale = this.venusApi.getLocale();
3348
3345
  const date = new Date(timestamp);
3349
3346
  const dateTimeOptions = {
3350
3347
  dateStyle: options.dateStyle || "medium",
@@ -3356,13 +3353,7 @@ var HostTimeApi = class {
3356
3353
  }
3357
3354
  formatNumber(value, options) {
3358
3355
  try {
3359
- let locale = "en-US";
3360
- const windowVenus = window.venus;
3361
- if (windowVenus._config.locale) {
3362
- locale = windowVenus._config.locale;
3363
- } else if (windowVenus._config.environment && windowVenus._config.environment.browserInfo && windowVenus._config.environment.browserInfo.language) {
3364
- locale = windowVenus._config.environment.browserInfo.language;
3365
- }
3356
+ const locale = this.venusApi.getLocale();
3366
3357
  const numberOptions = {
3367
3358
  style: options?.style || "decimal",
3368
3359
  minimumFractionDigits: options?.minimumFractionDigits || 0,
@@ -3425,7 +3416,7 @@ var MockTimeApi = class {
3425
3416
  this.venusApi = venusApi;
3426
3417
  }
3427
3418
  formatNumber(value, options) {
3428
- const locale = this.getLocale();
3419
+ const locale = this.venusApi.getLocale();
3429
3420
  const numberOptions = {
3430
3421
  style: options?.style || "decimal",
3431
3422
  minimumFractionDigits: options?.minimumFractionDigits || 0,
@@ -3436,7 +3427,7 @@ var MockTimeApi = class {
3436
3427
  return value.toLocaleString(locale, numberOptions);
3437
3428
  }
3438
3429
  formatTime(timestamp, options) {
3439
- const locale = this.getLocale();
3430
+ const locale = this.venusApi.getLocale();
3440
3431
  const date = new Date(timestamp);
3441
3432
  const dateTimeOptions = {
3442
3433
  dateStyle: options.dateStyle || "medium",
@@ -3516,16 +3507,6 @@ var MockTimeApi = class {
3516
3507
  });
3517
3508
  return timeInfo;
3518
3509
  }
3519
- getLocale() {
3520
- const venusApi = this.venusApi;
3521
- let locale = "en-US";
3522
- if (venusApi._mock.user && venusApi._mock.user.locale) {
3523
- locale = venusApi._mock.user.locale;
3524
- } else if (venusApi._mock.environment && venusApi._mock.environment.browserInfo.language) {
3525
- locale = venusApi._mock.environment.browserInfo.language;
3526
- }
3527
- return locale;
3528
- }
3529
3510
  };
3530
3511
 
3531
3512
  // src/time/index.ts
@@ -3545,7 +3526,176 @@ function initializeTime(venusApi, host) {
3545
3526
  }
3546
3527
 
3547
3528
  // src/version.ts
3548
- var SDK_VERSION = "3.0.4";
3529
+ var SDK_VERSION = "3.1.0-beta.0";
3530
+
3531
+ // src/shared-assets/embeddedLibrariesManifest.ts
3532
+ var DEFAULT_SHARED_LIB_CDN_BASE = "https://venus-static-01293ak.web.app/libs";
3533
+ var EMBEDDED_LIBRARIES = [
3534
+ {
3535
+ libraryKey: "phaser@3.90.0",
3536
+ assetKey: "library:phaser@3.90.0",
3537
+ packageName: "phaser",
3538
+ version: "3.90.0",
3539
+ globalVar: "Phaser",
3540
+ cdnPath: "phaser/3.90.0/phaser.min.js",
3541
+ moduleSpecifiers: [{ match: "exact", value: "phaser" }],
3542
+ loadStage: 0,
3543
+ enabled: true
3544
+ },
3545
+ {
3546
+ libraryKey: "react@18.3.1",
3547
+ assetKey: "library:react@18.3.1",
3548
+ packageName: "react",
3549
+ version: "18.3.1",
3550
+ globalVar: "React",
3551
+ cdnPath: "react/18.3.1/react.production.min.js",
3552
+ moduleSpecifiers: [
3553
+ { match: "exact", value: "react", behavior: "namespace" },
3554
+ { match: "exact", value: "react/jsx-runtime", behavior: "react-jsx-runtime" },
3555
+ {
3556
+ match: "exact",
3557
+ value: "react/jsx-dev-runtime",
3558
+ behavior: "react-jsx-dev-runtime"
3559
+ }
3560
+ ],
3561
+ loadStage: 0,
3562
+ // Must load before ReactDOM
3563
+ enabled: true
3564
+ },
3565
+ {
3566
+ libraryKey: "react-dom@18.3.1",
3567
+ assetKey: "library:react-dom@18.3.1",
3568
+ packageName: "react-dom",
3569
+ version: "18.3.1",
3570
+ globalVar: "ReactDOM",
3571
+ cdnPath: "react-dom/18.3.1/react-dom.production.min.js",
3572
+ moduleSpecifiers: [
3573
+ { match: "exact", value: "react-dom", behavior: "namespace" },
3574
+ { match: "exact", value: "react-dom/client", behavior: "namespace" }
3575
+ ],
3576
+ loadStage: 1,
3577
+ // Depends on React (stage 0)
3578
+ enabled: true
3579
+ },
3580
+ {
3581
+ libraryKey: "three@0.170.0",
3582
+ assetKey: "library:three@0.170.0",
3583
+ packageName: "three",
3584
+ version: "0.170.0",
3585
+ globalVar: "THREE",
3586
+ cdnPath: "three/r170/three.min.js",
3587
+ moduleSpecifiers: [
3588
+ { match: "exact", value: "three", behavior: "namespace" },
3589
+ { match: "prefix", value: "three/examples/jsm/", behavior: "namespace" }
3590
+ ],
3591
+ loadStage: 0,
3592
+ enabled: true
3593
+ },
3594
+ {
3595
+ libraryKey: "matter-js@0.19.0",
3596
+ assetKey: "library:matter-js@0.19.0",
3597
+ packageName: "matter-js",
3598
+ version: "0.19.0",
3599
+ globalVar: "Matter",
3600
+ cdnPath: "matter-js/0.19.0/matter.min.js",
3601
+ moduleSpecifiers: [{ match: "exact", value: "matter-js" }],
3602
+ loadStage: 0,
3603
+ enabled: true
3604
+ },
3605
+ {
3606
+ libraryKey: "inkjs@2.2.0",
3607
+ assetKey: "library:inkjs@2.2.0",
3608
+ packageName: "inkjs",
3609
+ version: "2.2.0",
3610
+ globalVar: "inkjs",
3611
+ cdnPath: "inkjs/2.2.0/ink.min.js",
3612
+ moduleSpecifiers: [{ match: "exact", value: "inkjs" }],
3613
+ loadStage: 0,
3614
+ enabled: true
3615
+ },
3616
+ {
3617
+ libraryKey: "zustand@5.0.3",
3618
+ assetKey: "library:zustand@5.0.3",
3619
+ packageName: "zustand",
3620
+ version: "5.0.3",
3621
+ globalVar: "zustand",
3622
+ cdnPath: "zustand/5.0.3/zustand.min.js",
3623
+ moduleSpecifiers: [
3624
+ { match: "exact", value: "zustand" },
3625
+ { match: "exact", value: "zustand/middleware" }
3626
+ ],
3627
+ loadStage: 0,
3628
+ enabled: true
3629
+ },
3630
+ {
3631
+ libraryKey: "ammo.js@2024.11",
3632
+ assetKey: "library:ammo.js@2024.11",
3633
+ packageName: "ammo.js",
3634
+ version: "2024.11",
3635
+ globalVar: "Ammo",
3636
+ cdnPath: "ammo/2024.11/ammo.js",
3637
+ moduleSpecifiers: [
3638
+ { match: "exact", value: "ammo.js" },
3639
+ { match: "exact", value: "ammo.js/builds/ammo.wasm.js" }
3640
+ ],
3641
+ loadStage: 0,
3642
+ enabled: false
3643
+ // Not ready yet - WASM loading needs additional work
3644
+ }
3645
+ ];
3646
+ var EMBEDDED_LIBRARY_BY_KEY = EMBEDDED_LIBRARIES.reduce(
3647
+ (acc, lib) => {
3648
+ acc[lib.libraryKey] = lib;
3649
+ return acc;
3650
+ },
3651
+ {}
3652
+ );
3653
+ var MODULE_TO_LIBRARY_SPECIFIERS = EMBEDDED_LIBRARIES.filter(
3654
+ (lib) => lib.enabled
3655
+ ).flatMap(
3656
+ (lib) => lib.moduleSpecifiers.map((specifier) => ({
3657
+ ...specifier,
3658
+ libraryKey: lib.libraryKey
3659
+ }))
3660
+ );
3661
+ function getLibraryDefinition(libraryKey) {
3662
+ const definition = EMBEDDED_LIBRARY_BY_KEY[libraryKey];
3663
+ if (!definition) {
3664
+ const availableKeys = Object.keys(EMBEDDED_LIBRARY_BY_KEY).join(", ");
3665
+ throw new Error(
3666
+ `Unsupported embedded library: ${libraryKey}. Available libraries: ${availableKeys}`
3667
+ );
3668
+ }
3669
+ return definition;
3670
+ }
3671
+
3672
+ // src/shared-assets/base64Utils.ts
3673
+ function base64ToArrayBuffer(base64) {
3674
+ const binaryString = atob(base64);
3675
+ const len = binaryString.length;
3676
+ const bytes = new Uint8Array(len);
3677
+ for (let i = 0; i < len; i++) {
3678
+ bytes[i] = binaryString.charCodeAt(i);
3679
+ }
3680
+ return bytes.buffer;
3681
+ }
3682
+ function base64ToUtf8(base64) {
3683
+ if (typeof TextDecoder !== "undefined") {
3684
+ const decoder = new TextDecoder("utf-8");
3685
+ const buffer = base64ToArrayBuffer(base64);
3686
+ return decoder.decode(new Uint8Array(buffer));
3687
+ }
3688
+ if (typeof globalThis !== "undefined" && typeof globalThis.Buffer !== "undefined") {
3689
+ const BufferCtor = globalThis.Buffer;
3690
+ return BufferCtor.from(base64, "base64").toString("utf-8");
3691
+ }
3692
+ const binaryString = atob(base64);
3693
+ let result = "";
3694
+ for (let i = 0; i < binaryString.length; i++) {
3695
+ result += String.fromCharCode(binaryString.charCodeAt(i));
3696
+ }
3697
+ return decodeURIComponent(escape(result));
3698
+ }
3549
3699
 
3550
3700
  // src/shared-assets/consts.ts
3551
3701
  var BurgerTimeAssetsCdnPath = "burger-time/Core.stow";
@@ -3589,16 +3739,33 @@ var RpcSharedAssetsApi = class {
3589
3739
  }
3590
3740
  }
3591
3741
  }
3592
- };
3593
- function base64ToArrayBuffer(base64) {
3594
- const binaryString = atob(base64);
3595
- const len = binaryString.length;
3596
- const bytes = new Uint8Array(len);
3597
- for (let i = 0; i < len; i++) {
3598
- bytes[i] = binaryString.charCodeAt(i);
3742
+ async loadLibraryCode(libraryKey) {
3743
+ const definition = getLibraryDefinition(libraryKey);
3744
+ try {
3745
+ const response = await this.rpcClient.callT("H5_LOAD_EMBEDDED_ASSET" /* H5_LOAD_EMBEDDED_ASSET */, {
3746
+ assetKey: definition.assetKey
3747
+ });
3748
+ return base64ToUtf8(response.base64Data);
3749
+ } catch (err) {
3750
+ console.error(
3751
+ `[Venus Libraries] Failed to load ${libraryKey} from host via RPC:`,
3752
+ err
3753
+ );
3754
+ console.warn(
3755
+ `[Venus Libraries] Falling back to CDN for ${libraryKey}. This may indicate an asset packaging issue.`
3756
+ );
3757
+ try {
3758
+ const cdnUrl = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
3759
+ const response = await this.venusApi.cdn.fetchFromCdn(cdnUrl);
3760
+ return await response.text();
3761
+ } catch (cdnError) {
3762
+ throw new Error(
3763
+ `Failed to load embedded library ${libraryKey}: RPC failed, CDN fallback failed: ${cdnError.message}`
3764
+ );
3765
+ }
3766
+ }
3599
3767
  }
3600
- return bytes.buffer;
3601
- }
3768
+ };
3602
3769
 
3603
3770
  // src/shared-assets/MockSharedAssetsApi.ts
3604
3771
  var MockSharedAssetsApi = class {
@@ -3614,49 +3781,114 @@ var MockSharedAssetsApi = class {
3614
3781
  const blob = await this.venusApi.cdn.fetchBlob(CharacterAssetsCdnPath);
3615
3782
  return await blob.arrayBuffer();
3616
3783
  }
3784
+ async loadLibraryCode(libraryKey) {
3785
+ const definition = getLibraryDefinition(libraryKey);
3786
+ const url = this.venusApi.cdn.resolveSharedLibUrl(definition.cdnPath);
3787
+ const response = await this.venusApi.cdn.fetchFromCdn(url);
3788
+ return await response.text();
3789
+ }
3617
3790
  };
3618
3791
 
3792
+ // src/leaderboard/utils.ts
3793
+ var HASH_ALGORITHM_WEB_CRYPTO = "SHA-256";
3794
+ var HASH_ALGORITHM_NODE = "sha256";
3795
+ async function computeScoreHash(score, duration, token, sealingNonce, sealingSecret) {
3796
+ const payload = `score:${score}|duration:${duration}|token:${token}`;
3797
+ const fullPayload = `${payload}|nonce:${sealingNonce}`;
3798
+ const encoder = new TextEncoder();
3799
+ const keyData = encoder.encode(sealingSecret);
3800
+ const messageData = encoder.encode(fullPayload);
3801
+ const cryptoKey = await crypto.subtle.importKey(
3802
+ "raw",
3803
+ keyData,
3804
+ { name: "HMAC", hash: HASH_ALGORITHM_WEB_CRYPTO },
3805
+ false,
3806
+ ["sign"]
3807
+ );
3808
+ const signature = await crypto.subtle.sign("HMAC", cryptoKey, messageData);
3809
+ return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
3810
+ }
3811
+
3619
3812
  // src/leaderboard/RpcLeaderboardApi.ts
3620
3813
  var RpcLeaderboardApi = class {
3621
3814
  constructor(rpcClient) {
3622
3815
  __publicField(this, "rpcClient");
3816
+ /** Cache of score tokens for automatic hash computation */
3817
+ __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
3623
3818
  this.rpcClient = rpcClient;
3624
3819
  }
3625
- startRun(mode) {
3626
- return this.rpcClient.call(
3627
- "H5_LEADERBOARD_START_RUN" /* H5_LEADERBOARD_START_RUN */,
3820
+ /**
3821
+ * Create a score token for submitting a score.
3822
+ * Token is cached for automatic hash computation if score sealing is enabled.
3823
+ *
3824
+ * @param mode - Optional game mode
3825
+ * @returns Score token with sealing data if enabled
3826
+ */
3827
+ async createScoreToken(mode) {
3828
+ const token = await this.rpcClient.call(
3829
+ "H5_LEADERBOARD_CREATE_SCORE_TOKEN" /* H5_LEADERBOARD_CREATE_SCORE_TOKEN */,
3628
3830
  mode ? { mode } : {}
3629
3831
  );
3832
+ this.tokenCache.set(token.token, token);
3833
+ return token;
3630
3834
  }
3631
- submitScore(sessionId, score, durationSec, options) {
3835
+ /**
3836
+ * Submit a score to the leaderboard.
3837
+ * Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
3838
+ *
3839
+ * @param params - Score submission parameters
3840
+ * @returns Submission result with acceptance status and rank
3841
+ * @throws Error if token not found in cache
3842
+ */
3843
+ async submitScore(params) {
3844
+ let hash;
3845
+ if (params.token) {
3846
+ const cachedToken = this.tokenCache.get(params.token);
3847
+ if (!cachedToken) {
3848
+ throw new Error(
3849
+ "Invalid token: not found in cache. Did you call createScoreToken() first?"
3850
+ );
3851
+ }
3852
+ if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
3853
+ hash = await computeScoreHash(
3854
+ params.score,
3855
+ params.duration,
3856
+ params.token,
3857
+ cachedToken.sealingNonce,
3858
+ cachedToken.sealingSecret
3859
+ );
3860
+ }
3861
+ this.tokenCache.delete(params.token);
3862
+ }
3632
3863
  return this.rpcClient.call(
3633
3864
  "H5_LEADERBOARD_SUBMIT_SCORE" /* H5_LEADERBOARD_SUBMIT_SCORE */,
3634
3865
  {
3635
- sessionId,
3636
- score,
3637
- durationSec,
3638
- mode: options?.mode,
3639
- telemetry: options?.telemetry,
3640
- metadata: options?.metadata,
3641
- hash: options?.hash
3866
+ token: params.token,
3867
+ score: params.score,
3868
+ duration: params.duration,
3869
+ mode: params.mode,
3870
+ telemetry: params.telemetry,
3871
+ metadata: params.metadata,
3872
+ hash
3873
+ // undefined if no sealing, computed if sealing enabled
3642
3874
  }
3643
3875
  );
3644
3876
  }
3645
- getLeaderboard(options) {
3877
+ getPagedScores(options) {
3646
3878
  return this.rpcClient.call(
3647
- "H5_LEADERBOARD_GET" /* H5_LEADERBOARD_GET */,
3879
+ "H5_LEADERBOARD_GET_PAGED_SCORES" /* H5_LEADERBOARD_GET_PAGED_SCORES */,
3648
3880
  options ?? {}
3649
3881
  );
3650
3882
  }
3651
- getPlayerStats(options) {
3883
+ getMyRank(options) {
3652
3884
  return this.rpcClient.call(
3653
- "H5_LEADERBOARD_GET_PLAYER_STATS" /* H5_LEADERBOARD_GET_PLAYER_STATS */,
3885
+ "H5_LEADERBOARD_GET_MY_RANK" /* H5_LEADERBOARD_GET_MY_RANK */,
3654
3886
  options ?? {}
3655
3887
  );
3656
3888
  }
3657
- getLeaderboardHighlight(options) {
3889
+ getPodiumScores(options) {
3658
3890
  return this.rpcClient.call(
3659
- "H5_LEADERBOARD_GET_HIGHLIGHT" /* H5_LEADERBOARD_GET_HIGHLIGHT */,
3891
+ "H5_LEADERBOARD_GET_PODIUM_SCORES" /* H5_LEADERBOARD_GET_PODIUM_SCORES */,
3660
3892
  options ?? {}
3661
3893
  );
3662
3894
  }
@@ -3665,17 +3897,31 @@ var RpcLeaderboardApi = class {
3665
3897
  // src/leaderboard/MockLeaderboardApi.ts
3666
3898
  var MockLeaderboardApi = class {
3667
3899
  constructor(options) {
3668
- __publicField(this, "sessions", /* @__PURE__ */ new Map());
3900
+ __publicField(this, "tokens", /* @__PURE__ */ new Map());
3901
+ /** Cache of score tokens for automatic hash computation */
3902
+ __publicField(this, "tokenCache", /* @__PURE__ */ new Map());
3669
3903
  __publicField(this, "entriesByMode", /* @__PURE__ */ new Map());
3670
- __publicField(this, "sessionCounter", 0);
3671
- __publicField(this, "requiresHash", false);
3672
- if (options?.requiresHash) {
3673
- this.requiresHash = true;
3904
+ __publicField(this, "tokenCounter", 0);
3905
+ __publicField(this, "enableScoreSealing", false);
3906
+ __publicField(this, "scoreSealingSecret", "mock-leaderboard-secret-key");
3907
+ if (options?.enableScoreSealing) {
3908
+ this.enableScoreSealing = true;
3909
+ }
3910
+ if (options?.scoreSealingSecret) {
3911
+ this.scoreSealingSecret = options.scoreSealingSecret;
3674
3912
  }
3675
3913
  }
3914
+ /**
3915
+ * Configure mock leaderboard settings
3916
+ *
3917
+ * @param options - Configuration options
3918
+ */
3676
3919
  configure(options) {
3677
- if (typeof options.requiresHash === "boolean") {
3678
- this.requiresHash = options.requiresHash;
3920
+ if (typeof options.enableScoreSealing === "boolean") {
3921
+ this.enableScoreSealing = options.enableScoreSealing;
3922
+ }
3923
+ if (options.scoreSealingSecret) {
3924
+ this.scoreSealingSecret = options.scoreSealingSecret;
3679
3925
  }
3680
3926
  }
3681
3927
  generateNonce() {
@@ -3692,83 +3938,149 @@ var MockLeaderboardApi = class {
3692
3938
  }
3693
3939
  return this.entriesByMode.get(key);
3694
3940
  }
3695
- async startRun(mode) {
3696
- const sessionId = `mock_session_${++this.sessionCounter}`;
3941
+ /**
3942
+ * Create a mock score token for testing.
3943
+ * Token is cached for automatic hash computation if score sealing is enabled.
3944
+ *
3945
+ * @param mode - Optional game mode
3946
+ * @returns Score token with sealing data if enabled
3947
+ */
3948
+ async createScoreToken(mode) {
3949
+ const token = `mock_token_${++this.tokenCounter}`;
3697
3950
  const startTime = Date.now();
3698
3951
  const expiresAt = startTime + 36e5;
3699
3952
  const resolvedMode = mode || "default";
3700
- const hashNonce = this.requiresHash ? this.generateNonce() : null;
3701
- this.sessions.set(sessionId, {
3702
- id: sessionId,
3953
+ const sealingNonce = this.enableScoreSealing ? this.generateNonce() : null;
3954
+ const sealingSecret = this.enableScoreSealing ? this.scoreSealingSecret : null;
3955
+ this.tokens.set(token, {
3956
+ id: token,
3703
3957
  expiresAt,
3704
3958
  mode: resolvedMode,
3705
- hashNonce,
3959
+ sealingNonce,
3706
3960
  used: false
3707
3961
  });
3708
- return {
3709
- sessionId,
3962
+ const result = {
3963
+ token,
3710
3964
  startTime,
3711
3965
  expiresAt,
3712
- hashNonce,
3966
+ sealingNonce,
3967
+ sealingSecret,
3713
3968
  mode: resolvedMode
3714
3969
  };
3970
+ this.tokenCache.set(token, result);
3971
+ return result;
3715
3972
  }
3716
- async submitScore(sessionId, score, durationSec, options) {
3717
- const session = this.sessions.get(sessionId);
3718
- if (!session) {
3719
- throw new Error("Invalid leaderboard session");
3973
+ /**
3974
+ * Submit a mock score to the leaderboard.
3975
+ * Automatically computes hash if score sealing is enabled and token was created via createScoreToken().
3976
+ *
3977
+ * @param params - Score submission parameters
3978
+ * @returns Submission result with acceptance status and rank
3979
+ * @throws Error if token not found in cache or validation fails
3980
+ */
3981
+ async submitScore(params) {
3982
+ let hash;
3983
+ if (params.token) {
3984
+ const cachedToken = this.tokenCache.get(params.token);
3985
+ if (!cachedToken) {
3986
+ throw new Error(
3987
+ "Invalid token: not found in cache. Did you call createScoreToken() first?"
3988
+ );
3989
+ }
3990
+ if (cachedToken.sealingNonce && cachedToken.sealingSecret) {
3991
+ hash = await computeScoreHash(
3992
+ params.score,
3993
+ params.duration,
3994
+ params.token,
3995
+ cachedToken.sealingNonce,
3996
+ cachedToken.sealingSecret
3997
+ );
3998
+ }
3720
3999
  }
3721
- if (session.expiresAt < Date.now()) {
3722
- throw new Error("Invalid or expired leaderboard session");
4000
+ if (!params.token) {
4001
+ const mode = params.mode || "default";
4002
+ const submittedAt2 = Date.now();
4003
+ const entry2 = {
4004
+ profileId: `mock_profile`,
4005
+ username: "Mock Player",
4006
+ avatarUrl: null,
4007
+ score: params.score,
4008
+ duration: params.duration,
4009
+ submittedAt: submittedAt2,
4010
+ token: "simple-mode",
4011
+ rank: null,
4012
+ zScore: null,
4013
+ isAnomaly: false,
4014
+ trustScore: 50,
4015
+ metadata: params.metadata ?? null,
4016
+ isSeed: false
4017
+ };
4018
+ const modeEntries2 = this.getEntriesForMode(mode);
4019
+ modeEntries2.push(entry2);
4020
+ modeEntries2.sort((a, b) => {
4021
+ if (b.score !== a.score) return b.score - a.score;
4022
+ return a.submittedAt - b.submittedAt;
4023
+ });
4024
+ modeEntries2.forEach((e, index) => {
4025
+ modeEntries2[index] = { ...e, rank: index + 1 };
4026
+ });
4027
+ const inserted2 = modeEntries2.find((e) => e.submittedAt === submittedAt2);
4028
+ return {
4029
+ accepted: true,
4030
+ rank: inserted2?.rank ?? null
4031
+ };
4032
+ }
4033
+ const scoreToken = this.tokens.get(params.token);
4034
+ if (!scoreToken) {
4035
+ throw new Error("Invalid score token");
4036
+ }
4037
+ if (scoreToken.expiresAt < Date.now()) {
4038
+ throw new Error("Invalid or expired score token");
3723
4039
  }
3724
- if (session.used) {
3725
- throw new Error("Leaderboard session already used");
4040
+ if (scoreToken.used) {
4041
+ throw new Error("Score token already used");
3726
4042
  }
3727
- if (options?.mode && options.mode !== session.mode) {
3728
- throw new Error("Submission mode does not match session mode");
4043
+ if (params.mode && params.mode !== scoreToken.mode) {
4044
+ throw new Error("Submission mode does not match token mode");
3729
4045
  }
3730
- if (session.hashNonce && !options?.hash) {
3731
- throw new Error("Score hash is required for sealed leaderboard submissions");
4046
+ if (scoreToken.sealingNonce && !hash) {
4047
+ throw new Error("Score hash required when score sealing is enabled");
3732
4048
  }
3733
4049
  const submittedAt = Date.now();
3734
4050
  const entry = {
3735
4051
  profileId: `mock_profile`,
3736
4052
  username: "Mock Player",
3737
4053
  avatarUrl: null,
3738
- score,
3739
- durationSec,
4054
+ score: params.score,
4055
+ duration: params.duration,
3740
4056
  submittedAt,
3741
- sessionId,
4057
+ token: params.token,
3742
4058
  rank: null,
3743
4059
  zScore: null,
3744
4060
  isAnomaly: false,
3745
4061
  trustScore: 50,
3746
- metadata: options?.metadata ?? null,
4062
+ metadata: params.metadata ?? null,
3747
4063
  isSeed: false
3748
4064
  };
3749
- const modeEntries = this.getEntriesForMode(session.mode);
4065
+ const modeEntries = this.getEntriesForMode(scoreToken.mode);
3750
4066
  modeEntries.push(entry);
3751
4067
  modeEntries.sort((a, b) => {
3752
- if (b.score !== a.score) {
3753
- return b.score - a.score;
3754
- }
4068
+ if (b.score !== a.score) return b.score - a.score;
3755
4069
  return a.submittedAt - b.submittedAt;
3756
4070
  });
3757
4071
  modeEntries.forEach((e, index) => {
3758
- modeEntries[index] = {
3759
- ...e,
3760
- rank: index + 1
3761
- };
4072
+ modeEntries[index] = { ...e, rank: index + 1 };
3762
4073
  });
3763
- session.used = true;
3764
- session.hashNonce = null;
3765
- const inserted = modeEntries.find((e) => e.sessionId === sessionId && e.submittedAt === submittedAt);
4074
+ scoreToken.used = true;
4075
+ scoreToken.sealingNonce = null;
4076
+ this.tokenCache.delete(params.token);
4077
+ const inserted = modeEntries.find((e) => e.token === params.token && e.submittedAt === submittedAt);
3766
4078
  return {
3767
4079
  accepted: true,
3768
4080
  rank: inserted?.rank ?? null
3769
4081
  };
3770
4082
  }
3771
- async getLeaderboard(options) {
4083
+ async getPagedScores(options) {
3772
4084
  const limit = options?.limit ?? 10;
3773
4085
  const mode = options?.mode ?? "default";
3774
4086
  const modeEntries = [...this.getEntriesForMode(mode)];
@@ -3784,7 +4096,7 @@ var MockLeaderboardApi = class {
3784
4096
  periodInstance: options?.period ?? "alltime"
3785
4097
  };
3786
4098
  }
3787
- async getPlayerStats(_options) {
4099
+ async getMyRank(_options) {
3788
4100
  const mode = _options?.mode ?? "default";
3789
4101
  const modeEntries = this.getEntriesForMode(mode);
3790
4102
  const playerEntry = modeEntries[0] ?? null;
@@ -3797,7 +4109,7 @@ var MockLeaderboardApi = class {
3797
4109
  periodInstance: _options?.period ?? "alltime"
3798
4110
  };
3799
4111
  }
3800
- async getLeaderboardHighlight(options) {
4112
+ async getPodiumScores(options) {
3801
4113
  const mode = options?.mode ?? "default";
3802
4114
  const modeEntries = [...this.getEntriesForMode(mode)];
3803
4115
  const topCount = Math.max(1, Math.min(options?.topCount ?? 3, 10));
@@ -4608,7 +4920,7 @@ var RemoteHost = class {
4608
4920
  this.popups = new RpcPopupsApi(rpcClient);
4609
4921
  this.profile = new HostProfileApi();
4610
4922
  this.cdn = new HostCdnApi(getCdnBaseUrl());
4611
- this.time = new HostTimeApi(rpcClient);
4923
+ this.time = new HostTimeApi(rpcClient, venusApi);
4612
4924
  this.post = new RpcPostApi(rpcClient);
4613
4925
  this.ai = new RpcAiApi(rpcClient);
4614
4926
  this.haptics = new RpcHapticsApi(rpcClient);
@@ -5289,6 +5601,6 @@ function initializeSocial(venusApi, host) {
5289
5601
  };
5290
5602
  }
5291
5603
 
5292
- export { HapticFeedbackStyle, HostCdnApi, HostProfileApi, HostTimeApi, MockAdsApi, MockAiApi, MockAnalyticsApi, MockAvatarApi, MockCdnApi, MockFeaturesApi, MockHapticsApi, MockIapApi, MockLeaderboardApi, MockLifecycleApi, MockLoggingApi, MockNavigationApi, MockNotificationsApi, MockPopupsApi, MockPreloaderApi, MockProfileApi, MockSharedAssetsApi, MockSimulationApi, MockSocialApi, MockStorageApi, MockTimeApi, RemoteHost, RpcAdsApi, RpcAiApi, RpcAnalyticsApi, RpcAvatarApi, RpcClient, RpcFeaturesApi, RpcHapticsApi, RpcIapApi, RpcLeaderboardApi, RpcLifecycleApi, RpcLoggingApi, RpcNavigationApi, RpcNotificationsApi, RpcPopupsApi, RpcPreloaderApi, RpcSharedAssetsApi, RpcSimulationApi, RpcSocialApi, RpcStorageApi, SDK_VERSION, VenusMessageId, VenusRoom, createHost, createMockStorageApi, init_rooms, initializeAds, initializeAi, initializeAnalytics, initializeAvatar3d, initializeCdn, initializeFeaturesApi, initializeHaptics, initializeIap, initializeLeaderboard, initializeLifecycleApi, initializeLocalNotifications, initializeLoggingApi, initializePopups, initializePost, initializePreloader, initializeProfile, initializeRoomsApi, initializeSimulation, initializeSocial, initializeStackNavigation, initializeStorage, initializeTime, isPacificDaylightTime, setupRoomNotifications };
5293
- //# sourceMappingURL=chunk-PXWCNWJ6.mjs.map
5294
- //# sourceMappingURL=chunk-PXWCNWJ6.mjs.map
5604
+ export { DEFAULT_SHARED_LIB_CDN_BASE, EMBEDDED_LIBRARIES, EMBEDDED_LIBRARY_BY_KEY, HASH_ALGORITHM_NODE, HASH_ALGORITHM_WEB_CRYPTO, HapticFeedbackStyle, HostCdnApi, HostProfileApi, HostTimeApi, MODULE_TO_LIBRARY_SPECIFIERS, MockAdsApi, MockAiApi, MockAnalyticsApi, MockAvatarApi, MockCdnApi, MockFeaturesApi, MockHapticsApi, MockIapApi, MockLeaderboardApi, MockLifecycleApi, MockLoggingApi, MockNavigationApi, MockNotificationsApi, MockPopupsApi, MockPreloaderApi, MockProfileApi, MockSharedAssetsApi, MockSimulationApi, MockSocialApi, MockStorageApi, MockTimeApi, RemoteHost, RpcAdsApi, RpcAiApi, RpcAnalyticsApi, RpcAvatarApi, RpcClient, RpcFeaturesApi, RpcHapticsApi, RpcIapApi, RpcLeaderboardApi, RpcLifecycleApi, RpcLoggingApi, RpcNavigationApi, RpcNotificationsApi, RpcPopupsApi, RpcPreloaderApi, RpcSharedAssetsApi, RpcSimulationApi, RpcSocialApi, RpcStorageApi, SDK_VERSION, VenusMessageId, VenusRoom, base64ToArrayBuffer, base64ToUtf8, computeScoreHash, createHost, createMockStorageApi, getLibraryDefinition, init_rooms, initializeAds, initializeAi, initializeAnalytics, initializeAvatar3d, initializeCdn, initializeFeaturesApi, initializeHaptics, initializeIap, initializeLeaderboard, initializeLifecycleApi, initializeLocalNotifications, initializeLoggingApi, initializePopups, initializePost, initializePreloader, initializeProfile, initializeRoomsApi, initializeSimulation, initializeSocial, initializeStackNavigation, initializeStorage, initializeTime, isPacificDaylightTime, setupRoomNotifications };
5605
+ //# sourceMappingURL=chunk-EMVTVSGL.mjs.map
5606
+ //# sourceMappingURL=chunk-EMVTVSGL.mjs.map