@smartico/public-api 0.0.385 → 0.0.387

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 (54) hide show
  1. package/README.md +1 -1
  2. package/dist/Avatars/AvatarCustomizeErrorCode.d.ts +7 -1
  3. package/dist/Avatars/AvatarCustomizeResponse.d.ts +16 -0
  4. package/dist/Avatars/index.d.ts +1 -0
  5. package/dist/Clans/JoinClanErrorCode.d.ts +21 -11
  6. package/dist/Missions/UserAchievementTask.d.ts +4 -0
  7. package/dist/SmarticoAPI.d.ts +11 -0
  8. package/dist/Tournaments/TournamentRegistrationError.d.ts +32 -2
  9. package/dist/WSAPI/WSAPIAvatars.d.ts +103 -0
  10. package/dist/WSAPI/WSAPIClans.d.ts +3 -5
  11. package/dist/WSAPI/WSAPILeaderBoard.d.ts +3 -11
  12. package/dist/WSAPI/WSAPIMissions.d.ts +6 -0
  13. package/dist/WSAPI/WSAPITypes.d.ts +6 -2
  14. package/dist/WSAPI/WSAPIUser.d.ts +27 -16
  15. package/dist/index.js +362 -127
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.modern.mjs +270 -55
  18. package/dist/index.modern.mjs.map +1 -1
  19. package/docs/SmarticoObject.md +15 -0
  20. package/docs/api/README.md +2 -0
  21. package/docs/api/classes/WSAPIAvatars.md +135 -0
  22. package/docs/api/classes/WSAPIClans.md +3 -5
  23. package/docs/api/classes/WSAPILeaderBoard.md +3 -11
  24. package/docs/api/classes/WSAPIMissions.md +9 -0
  25. package/docs/api/classes/WSAPIUser.md +27 -16
  26. package/docs/api/documents/SmarticoObject.md +15 -0
  27. package/docs/api/enumerations/AvatarCustomizeErrorCode.md +21 -0
  28. package/docs/api/enumerations/JoinClanErrorCode.md +16 -17
  29. package/docs/api/enumerations/TournamentRegistrationError.md +47 -2
  30. package/docs/api/interfaces/AvatarCustomizeResponse.md +31 -0
  31. package/docs/api/interfaces/TAvatarPrompt.md +2 -2
  32. package/docs/api/interfaces/TMissionOrBadgeTask.md +16 -0
  33. package/docs/api/interfaces/UserAchievementTask.md +16 -0
  34. package/docs/native/PROTOCOL.md +3 -1
  35. package/docs/ui/avatars/UIGuide_avatarsCustomize.md +69 -0
  36. package/docs/ui/clans/UIGuide_joinClan.md +1 -2
  37. package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +15 -14
  38. package/package.json +1 -1
  39. package/src/Avatars/AvatarCustomizeErrorCode.ts +7 -5
  40. package/src/Avatars/AvatarCustomizeResponse.ts +17 -0
  41. package/src/Avatars/index.ts +1 -0
  42. package/src/Clans/JoinClanErrorCode.ts +20 -14
  43. package/src/Missions/UserAchievement.ts +2 -0
  44. package/src/Missions/UserAchievementTask.ts +4 -0
  45. package/src/SmarticoAPI.ts +53 -0
  46. package/src/Tournaments/TournamentRegistrationError.ts +32 -4
  47. package/src/WSAPI/WSAPI.ts +3 -1
  48. package/src/WSAPI/WSAPIAvatars.ts +121 -0
  49. package/src/WSAPI/WSAPIClans.ts +3 -5
  50. package/src/WSAPI/WSAPILeaderBoard.ts +7 -12
  51. package/src/WSAPI/WSAPIMissions.ts +12 -0
  52. package/src/WSAPI/WSAPITypes.ts +6 -2
  53. package/src/WSAPI/WSAPIUser.ts +27 -16
  54. package/tsconfig.json +3 -1
@@ -1616,6 +1616,8 @@ const UserAchievementTransform = items => {
1616
1616
  id: t.task_id,
1617
1617
  name: (_t$task_public_meta = t.task_public_meta) == null ? void 0 : _t$task_public_meta.name,
1618
1618
  points_reward: t.points_reward,
1619
+ gems_reward: t.gems_reward,
1620
+ diamonds_reward: t.diamonds_reward,
1619
1621
  is_completed: t.isCompleted,
1620
1622
  progress: t.userProgress,
1621
1623
  execution_count_expected: t.executionCount,
@@ -2009,20 +2011,50 @@ const tournamentInfoItemTransform = t => {
2009
2011
  return response;
2010
2012
  };
2011
2013
 
2014
+ /**
2015
+ * Error codes returned in `err_code` by the `registerInTournament` method.
2016
+ *
2017
+ * These are terse value definitions for lookup. The full per-code narrative —
2018
+ * when each fires and how the consumer's UI should react — lives in the
2019
+ * `registerInTournament` method TSDoc, which owns the error table.
2020
+ *
2021
+ * Note the numbering break: the gems / diamonds codes are 6-digit
2022
+ * (`300010` / `300011`) while the rest of the tournament block is 5-digit;
2023
+ * they were appended after the original `30001`–`30009` range was occupied.
2024
+ * Branch on the exact numeric value, not on digit count.
2025
+ */
2012
2026
  var TournamentRegistrationError;
2013
2027
  (function (TournamentRegistrationError) {
2028
+ /** Success — registration persisted; buy-in (if any) deducted. */
2014
2029
  TournamentRegistrationError[TournamentRegistrationError["NO_ERROR"] = 0] = "NO_ERROR";
2030
+ /** Clan-based tournament and the user does not belong to a clan yet. */
2015
2031
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_USER_CANNOT_JOIN_WITHOUT_CLAN"] = 1010] = "TOURNAMENT_USER_CANNOT_JOIN_WITHOUT_CLAN";
2032
+ /** Instance id is invalid or the tournament was deleted. */
2016
2033
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_INSTANCE_NOT_FOUND"] = 30001] = "TOURNAMENT_INSTANCE_NOT_FOUND";
2034
+ /** Insufficient points balance for a points-priced buy-in. */
2017
2035
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_REGISTRATION_NOT_ENOUGH_POINTS"] = 30002] = "TOURNAMENT_REGISTRATION_NOT_ENOUGH_POINTS";
2036
+ /** Tournament is no longer in a registerable state (finished, cancelled, finalizing, or not yet open). */
2018
2037
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_INSTANCE_NOT_IN_STATE"] = 30003] = "TOURNAMENT_INSTANCE_NOT_IN_STATE";
2038
+ /** User is already registered; treat as an idempotent success. */
2019
2039
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_ALREADY_REGISTERED"] = 30004] = "TOURNAMENT_ALREADY_REGISTERED";
2040
+ /** User does not satisfy the tournament's segment / entry conditions. */
2020
2041
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_USER_DONT_MATCH_CONDITIONS"] = 30005] = "TOURNAMENT_USER_DONT_MATCH_CONDITIONS";
2042
+ /** User is not registered; anomalous on a register call (usually a server-side race). */
2021
2043
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_USER_NOT_REGISTERED"] = 30006] = "TOURNAMENT_USER_NOT_REGISTERED";
2044
+ /** Registration status transition is not allowed (e.g. re-registering a finished tournament). */
2022
2045
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_CANT_CHANGE_REGISTRATION_STATUS"] = 30007] = "TOURNAMENT_CANT_CHANGE_REGISTRATION_STATUS";
2046
+ /** Tournament filled up — maximum registrations reached. */
2023
2047
  TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_MAX_REGISTRATIONS_REACHED"] = 30008] = "TOURNAMENT_MAX_REGISTRATIONS_REACHED";
2024
- TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_REGISTRATION_NOT_ENOUGH_GEMS"] = 30010] = "TOURNAMENT_REGISTRATION_NOT_ENOUGH_GEMS";
2025
- TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_REGISTRATION_NOT_ENOUGH_DIAMONDS"] = 30011] = "TOURNAMENT_REGISTRATION_NOT_ENOUGH_DIAMONDS";
2048
+ /**
2049
+ * The user's wallet currency could not be resolved. Emitted server-side
2050
+ * during tournament score processing, NOT during registration — it is
2051
+ * never returned by `registerInTournament`. Included for completeness.
2052
+ */
2053
+ TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_INVALID_USER_CURRENCY"] = 30009] = "TOURNAMENT_INVALID_USER_CURRENCY";
2054
+ /** Insufficient gems balance for a gems-priced buy-in. */
2055
+ TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_REGISTRATION_NOT_ENOUGH_GEMS"] = 300010] = "TOURNAMENT_REGISTRATION_NOT_ENOUGH_GEMS";
2056
+ /** Insufficient diamonds balance for a diamonds-priced buy-in. */
2057
+ TournamentRegistrationError[TournamentRegistrationError["TOURNAMENT_REGISTRATION_NOT_ENOUGH_DIAMONDS"] = 300011] = "TOURNAMENT_REGISTRATION_NOT_ENOUGH_DIAMONDS";
2026
2058
  })(TournamentRegistrationError || (TournamentRegistrationError = {}));
2027
2059
 
2028
2060
  var TournamentType;
@@ -2744,12 +2776,25 @@ class WSAPIUser extends WSAPIBase {
2744
2776
  * `ach_points_ever` and {@link getLevels} would also work, but
2745
2777
  * `progress` saves the math.
2746
2778
  *
2747
- * **Cache TTL**: the SDK caches the response for 30 seconds. There is
2748
- * no push event that refreshes this cache; a server-side level change
2749
- * (visible immediately on {@link getUserProfile}'s `ach_level_current_id`
2750
- * via the user-properties update channel) becomes visible on this
2751
- * method only after the cache TTL expires, or after
2752
- * `_smartico.api.clearCaches()` is called.
2779
+ * **Cache TTL & freshness**
2780
+ * The response is cached for 30 seconds, but the SDK automatically
2781
+ * drops that cache whenever a user-properties update arrives — the
2782
+ * same live channel that backs {@link getUserProfile}. The practical
2783
+ * effect depends on the label's leveling logic:
2784
+ * - **Points-based or operator-manual leveling**: a points or level
2785
+ * change flows through the user-properties channel, so the cache is
2786
+ * busted at that moment and the next `getCurrentLevel()` call
2787
+ * returns up-to-date data without waiting out the TTL.
2788
+ * - **Counter-based leveling** (level driven by sliding-window
2789
+ * counters such as deposit or wagering totals over a recent window —
2790
+ * see {@link getUserLevelExtraCounters}): ordinary progress changes
2791
+ * are recomputed by a periodic server job and do NOT emit a
2792
+ * user-properties update, so they become visible on this method only
2793
+ * after the 30 s TTL expires (or after `_smartico.api.clearCaches()`).
2794
+ *
2795
+ * Avoid calling `clearCaches()` on the points/manual path — it's
2796
+ * unnecessary there (the cache is already refreshed on the property
2797
+ * update) and forces a slower extra round-trip.
2753
2798
  *
2754
2799
  * **Leveling logic**
2755
2800
  * The semantics of how a user advances depends on the label's
@@ -2777,10 +2822,10 @@ class WSAPIUser extends WSAPIBase {
2777
2822
  * console.log('[smartico] render level badge — name:', level.name,
2778
2823
  * 'progress:', Math.round(level.progress), '%');
2779
2824
  *
2780
- * // Detect level-up via getUserProfile's push channel.
2825
+ * // Detect level-up via getUserProfile's push channel. No clearCaches()
2826
+ * // needed — the SDK already drops the level cache on this update.
2781
2827
  * window._smartico.on('props_change', async (changed) => {
2782
2828
  * if ('ach_level_current_id' in changed) {
2783
- * await window._smartico.api.clearCaches(); // bust the 30 s cache
2784
2829
  * const fresh = await window._smartico.api.getCurrentLevel();
2785
2830
  * console.log('[smartico] user levelled up — animate badge to new level:', fresh.name);
2786
2831
  * }
@@ -2815,14 +2860,12 @@ class WSAPIUser extends WSAPIBase {
2815
2860
  * `levelsCounter2Name`.
2816
2861
  *
2817
2862
  * **Refresh cadence**
2818
- * Sliding-window counters are recomputed by a server-side job that
2819
- * runs roughly every 60 seconds against the operator's BigQuery
2820
- * dataset; level transitions driven by counter changes have a
2821
- * latency of up to several minutes after the underlying activity
2822
- * (e.g. a deposit). The SDK caches the response for 30 seconds; no
2823
- * push event refreshes this cache. After a level change visible on
2824
- * {@link getUserProfile}'s `ach_level_current_id`, call
2825
- * `_smartico.api.clearCaches()` to force a fresh fetch.
2863
+ * Sliding-window counters are recomputed by a periodic server-side
2864
+ * job. Its rebuild cadence is operator-configured per brand —
2865
+ * commonly daily, though it can be set more frequent — so level
2866
+ * transitions driven by counter changes surface with a latency tied
2867
+ * to that rebuild schedule after the underlying activity (e.g. a
2868
+ * deposit), not in real time.
2826
2869
  *
2827
2870
  * **Idempotency**: safe. Read-only. Repeated calls within the cache
2828
2871
  * window return a deep-cloned cached value without a network
@@ -3313,8 +3356,14 @@ class WSAPIMissions extends WSAPIGeneral {
3313
3356
  * **Idempotency / Side effects**: fetch-only; safe to call repeatedly.
3314
3357
  * The cache layer deduplicates concurrent calls within the TTL window.
3315
3358
  *
3359
+ * **Visitor mode**: not supported. Badges are an authenticated-only
3360
+ * feature; calling this on the visitor-mode handle (`_smartico.vapi`)
3361
+ * throws synchronously rather than silently returning an empty list.
3362
+ *
3316
3363
  * **UI guidance**: see [UI Guide — `getBadges`](../../docs/ui/missions/UIGuide_getBadges.md).
3317
3364
  *
3365
+ * @throws `Error("getBadges is not available in visitor mode")` when
3366
+ * called from a visitor-mode session.
3318
3367
  * @returns Promise resolving to `TMissionOrBadge[]`. Every item has
3319
3368
  * `type === 'badge'`. Cached for 30 s under the `Badges` key.
3320
3369
  *
@@ -3356,6 +3405,12 @@ class WSAPIMissions extends WSAPIGeneral {
3356
3405
  * ```
3357
3406
  */
3358
3407
  async getBadges() {
3408
+ // Badges are an authenticated-only feature. The visitor-mode WSAPI
3409
+ // instance (`_smartico.vapi`) is constructed without a tracker, so the
3410
+ // server would silently return nothing; throw a clear error instead.
3411
+ if (!this.api.tracker) {
3412
+ throw new Error('getBadges is not available in visitor mode');
3413
+ }
3359
3414
  return OCache.use(onUpdateContextKey.Badges, ECacheContext.WSAPI, () => this.api.badgetsGetItemsT(this.userExtId), CACHE_DATA_SEC);
3360
3415
  }
3361
3416
  /**
@@ -5434,12 +5489,10 @@ class WSAPIClans extends WSAPITournaments {
5434
5489
  * tournament requires the user to be in a clan first.
5435
5490
  * - `1006` (`JOIN_CLAN_COOLDOWN_ACTIVE`) — user is inside the
5436
5491
  * switch-cooldown window from a previous clan join (default
5437
- * 7 days, configurable per label). Surface the
5492
+ * 7 days, configurable per label). Only reachable when the user is
5493
+ * already in a *different* clan (this call is then a clan switch);
5494
+ * a first-time join never returns `1006`. Surface the
5438
5495
  * `TClans.cooldown_until` expiry in the disabled CTA.
5439
- * - `1007` (`JOIN_CLAN_ARCHIVED`) — defined on the public enum but
5440
- * the server does NOT emit this code in practice (archived clans
5441
- * are reported as `1001`). Handle it as a synonym for `1001`
5442
- * defensively, but do not rely on it.
5443
5496
  * - `1011` (`JOIN_CLAN_JOINED_AFTER_TOURNAMENT_START`) — this
5444
5497
  * method does NOT return `1011` directly. The code fires on
5445
5498
  * {@link registerInTournament} responses when the user joined
@@ -7480,6 +7533,116 @@ class WSAPIAvatars extends WSAPIMiniGames {
7480
7533
  err_message: r.errMsg
7481
7534
  };
7482
7535
  }
7536
+ /**
7537
+ * Generates an AI-customized variant of a base avatar by applying an
7538
+ * operator-defined style prompt, returning the CDN URL of the result.
7539
+ * This is a paid, generate-only step: it does NOT change the user's
7540
+ * active avatar — pass the returned `cdn_url` to {@link setAvatar} to
7541
+ * activate it.
7542
+ *
7543
+ * @remarks
7544
+ * **Preconditions**
7545
+ * - Authenticated session required; not available in visitor mode (throws).
7546
+ * - All five fields are mandatory — the SDK throws synchronously
7547
+ * (`Error("<field> is required")`) if any is missing or zero.
7548
+ * - `prompt_id` must be one of the prompts from {@link getAvatarPrompts};
7549
+ * `avatar_url` / `avatar_real_id` identify the base avatar to style.
7550
+ *
7551
+ * **Cost**
7552
+ * Each generation costs the currency the operator configured on the
7553
+ * chosen prompt (points, gems, or diamonds — some prompts are free; read
7554
+ * `cost_currency_type_id` / `cost_value` from the {@link getAvatarPrompts}
7555
+ * entry to gate the UI before calling). The cost is charged only on
7556
+ * success; if the user can't afford it the call fails with `errCode -1`
7557
+ * and nothing is generated or charged.
7558
+ *
7559
+ * **Latency**
7560
+ * Generation runs server-side AI image synthesis and is synchronous from
7561
+ * the caller's side — expect several seconds (roughly 5–20 s) before the
7562
+ * promise resolves. There is no SDK cache and no push/subscription; show
7563
+ * a loading state for the full duration and disable the trigger to
7564
+ * prevent duplicate submissions.
7565
+ *
7566
+ * **Result & error codes**
7567
+ * On success the result has `cdn_url` set; on failure it has `errCode` /
7568
+ * `errMessage` set and no `cdn_url`. Branch on `errCode` — the generic
7569
+ * message is fixed text, not cause-specific:
7570
+ * - `12001` (`AvatarCustomizeErrorCode.AVATAR_USER_LIMIT`) — the user hit
7571
+ * their monthly per-user generation cap. Nothing is generated or charged.
7572
+ * - `12002` (`AvatarCustomizeErrorCode.AVATAR_LABEL_LIMIT`) — the brand's
7573
+ * shared monthly pool is exhausted. Nothing is generated or charged;
7574
+ * surface a "try again later" message.
7575
+ * - `-1` — generic failure: insufficient balance, an unavailable prompt,
7576
+ * or a generation error. Nothing is charged. Allow the user to retry.
7577
+ *
7578
+ * Both monthly caps are operator-configured and reset at the start of
7579
+ * each calendar month.
7580
+ *
7581
+ * **Side effects (on success)**
7582
+ * The generated variant is persisted to the user's customization history
7583
+ * and counts toward the monthly caps **whether or not** it is later
7584
+ * activated — generation is not reversible. The SDK clears the
7585
+ * {@link getAvatarsCustomized} cache so the next call surfaces the new
7586
+ * variant. The user's active avatar is unchanged until you call
7587
+ * {@link setAvatar} with the returned `cdn_url`.
7588
+ *
7589
+ * **Idempotency**: not idempotent — each successful call generates (and
7590
+ * charges for) a new variant. Guard the call site against double-clicks.
7591
+ *
7592
+ * **UI guidance**: see [UI Guide — `avatarsCustomize`](../../docs/ui/avatars/UIGuide_avatarsCustomize.md).
7593
+ *
7594
+ * **Visitor mode**: not supported (throws).
7595
+ *
7596
+ * @param props.label_id Numeric Smartico label (brand) ID the user belongs to.
7597
+ * @param props.user_id Numeric Smartico user ID.
7598
+ * @param props.prompt_id Style-prompt ID (`prompt_id`) from {@link getAvatarPrompts}.
7599
+ * @param props.avatar_url CDN URL of the base avatar to customize.
7600
+ * @param props.avatar_real_id `avatar_real_id` of the base avatar.
7601
+ * @returns {@link AvatarCustomizeResponse} — `cdn_url` set on success;
7602
+ * `errCode` / `errMessage` set on failure.
7603
+ *
7604
+ * @example
7605
+ * ```ts
7606
+ * // label_id / user_id identify the Smartico user being customized.
7607
+ * const prompts = await window._smartico.api.getAvatarPrompts();
7608
+ * const prompt = prompts[0];
7609
+ *
7610
+ * console.log('[smartico] generating avatar — show a spinner for ~5-20s and disable the Generate button');
7611
+ * const result = await window._smartico.api.avatarsCustomize({
7612
+ * label_id,
7613
+ * user_id,
7614
+ * prompt_id: prompt.prompt_id,
7615
+ * avatar_url: baseAvatar.avatar_url,
7616
+ * avatar_real_id: baseAvatar.avatar_real_id,
7617
+ * });
7618
+ *
7619
+ * if (result.cdn_url) {
7620
+ * console.log('[smartico] generation succeeded — preview this URL, then call setAvatar to apply it:', result.cdn_url);
7621
+ * // await window._smartico.api.setAvatar({ avatar_url: result.cdn_url, avatar_real_id: baseAvatar.avatar_real_id });
7622
+ * } else if (result.errCode === 12001) {
7623
+ * console.error('[smartico] user monthly limit reached — show "you have used all your custom avatars this month"');
7624
+ * } else if (result.errCode === 12002) {
7625
+ * console.error('[smartico] brand monthly pool exhausted — show "custom avatars are unavailable right now, try later"');
7626
+ * } else {
7627
+ * console.error('[smartico] generation failed (e.g. not enough balance) — let the user retry:', result.errMessage);
7628
+ * }
7629
+ * ```
7630
+ */
7631
+ async avatarsCustomize(props) {
7632
+ const required = ['label_id', 'user_id', 'prompt_id', 'avatar_url', 'avatar_real_id'];
7633
+ for (const field of required) {
7634
+ if (!props[field]) {
7635
+ throw new Error(`${field} is required`);
7636
+ }
7637
+ }
7638
+ const r = await this.api.avatarsCustomize(props);
7639
+ // On success a new variant is persisted server-side — drop the cached
7640
+ // list so the next getAvatarsCustomized() surfaces it.
7641
+ if (r.cdn_url) {
7642
+ OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.AvatarsCustomized);
7643
+ }
7644
+ return r;
7645
+ }
7483
7646
  }
7484
7647
 
7485
7648
  /** @group GamePick */
@@ -8180,15 +8343,8 @@ class WSAPILeaderBoard extends WSAPIGamePick {
8180
8343
  * the array is the prize for place 1, the second for place 2, and
8181
8344
  * so on. The array length is the number of paid places.
8182
8345
  *
8183
- * **Cache TTL — single shared key (known limitation)**
8184
- * The SDK caches the response for 30 seconds under a SINGLE shared
8185
- * key — calling `getLeaderBoard(DAILY)` followed by
8186
- * `getLeaderBoard(WEEKLY)` within the same 30 s window returns the
8187
- * cached DAILY result for the WEEKLY call. Same applies to
8188
- * switching `getPreviousPeriod`. To force a fresh fetch when
8189
- * switching periods or current/previous, call
8190
- * `_smartico.api.clearCaches()` before the second call, or simply
8191
- * wait out the TTL.
8346
+ * **Cache TTL**
8347
+ * The SDK caches each response for 30 seconds.
8192
8348
  *
8193
8349
  * **Period boundaries**
8194
8350
  * The server finalizes each period on a server-configurable
@@ -8258,8 +8414,7 @@ class WSAPILeaderBoard extends WSAPIGamePick {
8258
8414
  * }
8259
8415
  * }
8260
8416
  *
8261
- * // Switch to previous period view — but bust the cache first to avoid the shared-key collision.
8262
- * await window._smartico.api.clearCaches();
8417
+ * // Switch to previous period view — cached separately from the current period.
8263
8418
  * const prev = await window._smartico.api.getLeaderBoard(LeaderBoardPeriodType.WEEKLY, true);
8264
8419
  * console.log('[smartico] previous-week standings — render with greyed-out "ended" treatment:', prev?.users.length, 'finalists');
8265
8420
  *
@@ -8268,7 +8423,10 @@ class WSAPILeaderBoard extends WSAPIGamePick {
8268
8423
  * ```
8269
8424
  */
8270
8425
  async getLeaderBoard(periodType, getPreviousPeriod) {
8271
- return OCache.use(onUpdateContextKey.LeaderBoards, ECacheContext.WSAPI, () => this.api.leaderboardsGetT(this.userExtId, periodType, getPreviousPeriod), CACHE_DATA_SEC);
8426
+ // Cache per (periodType, current/previous) so switching tabs or
8427
+ // current↔previous within the TTL doesn't return a colliding board.
8428
+ const cacheKey = `${onUpdateContextKey.LeaderBoards}:${periodType}:${getPreviousPeriod ? 1 : 0}`;
8429
+ return OCache.use(cacheKey, ECacheContext.WSAPI, () => this.api.leaderboardsGetT(this.userExtId, periodType, getPreviousPeriod), CACHE_DATA_SEC);
8272
8430
  }
8273
8431
  }
8274
8432
 
@@ -8993,6 +9151,7 @@ class WSAPI extends WSAPIInbox {
8993
9151
  if ((data == null || (_data$props3 = data.props) == null ? void 0 : _data$props3.ach_points_balance) !== undefined || (data == null || (_data$props4 = data.props) == null ? void 0 : _data$props4.ach_gems_balance) !== undefined || (data == null || (_data$props5 = data.props) == null ? void 0 : _data$props5.ach_diamonds_balance) !== undefined) {
8994
9152
  this.notifyActivityLogUpdate();
8995
9153
  }
9154
+ OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.CurrentLevel);
8996
9155
  });
8997
9156
  on(ClassId.RAF_OPTIN_RESPONSE, () => this.updateRaffles());
8998
9157
  }
@@ -9250,7 +9409,7 @@ const AVATAR_DOMAIN = 'https://img{ENV_ID}.smr.vc';
9250
9409
  const DEFAULT_LANG_EN = 'EN';
9251
9410
  class SmarticoAPI {
9252
9411
  constructor(label_api_key, brand_api_key, messageSender, options = {}) {
9253
- var _options$tracker;
9412
+ var _options$tracker, _options$tracker2;
9254
9413
  this.label_api_key = void 0;
9255
9414
  this.brand_api_key = void 0;
9256
9415
  this.messageSender = void 0;
@@ -9261,6 +9420,7 @@ class SmarticoAPI {
9261
9420
  this.gamesApiUrl = void 0;
9262
9421
  this.baseRgApiParams = void 0;
9263
9422
  this.avatarDomain = void 0;
9423
+ this.avatarOriginDomain = void 0;
9264
9424
  this.envId = void 0;
9265
9425
  this.logger = void 0;
9266
9426
  this.logCIDs = void 0;
@@ -9288,6 +9448,7 @@ class SmarticoAPI {
9288
9448
  };
9289
9449
  }
9290
9450
  this.avatarDomain = SmarticoAPI.getAvatarUrl(label_api_key || ((_options$tracker = options.tracker) == null ? void 0 : _options$tracker.label_api_key));
9451
+ this.avatarOriginDomain = SmarticoAPI.getAvatarOriginUrl(label_api_key || ((_options$tracker2 = options.tracker) == null ? void 0 : _options$tracker2.label_api_key));
9291
9452
  this.label_api_key = SmarticoAPI.getCleanLabelApiKey(label_api_key);
9292
9453
  }
9293
9454
  static getEnvDnsSuffix(label_api_key) {
@@ -9344,6 +9505,9 @@ class SmarticoAPI {
9344
9505
  const avatarUrl = AVATAR_DOMAIN.replace('{ENV_ID}', SmarticoAPI.getEnvDnsSuffix(label_api_key));
9345
9506
  return SmarticoAPI.replaceSmrDomainsWithCloudfront(avatarUrl);
9346
9507
  }
9508
+ static getAvatarOriginUrl(label_api_key) {
9509
+ return AVATAR_DOMAIN.replace('{ENV_ID}', SmarticoAPI.getEnvDnsSuffix(label_api_key));
9510
+ }
9347
9511
  async send(message, expectCID, force_language) {
9348
9512
  if (this.logCIDs.includes(message.cid)) {
9349
9513
  this.logger.info('REQ', message);
@@ -10098,6 +10262,33 @@ class SmarticoAPI {
10098
10262
  throw new Error(`Failed to call games API: ${method}. ${e.message}`);
10099
10263
  }
10100
10264
  }
10265
+ async sendAvatarApi({
10266
+ method,
10267
+ body
10268
+ }) {
10269
+ if (!this.tracker) {
10270
+ throw new Error(`Avatar APIs are not available in the visitor mode`);
10271
+ }
10272
+ const url = `${this.avatarOriginDomain}/${method}`;
10273
+ try {
10274
+ const response = await fetch(url, {
10275
+ method: 'POST',
10276
+ headers: {
10277
+ 'Accept': 'application/json',
10278
+ 'Content-Type': 'application/json'
10279
+ },
10280
+ body: JSON.stringify(body)
10281
+ });
10282
+ const data = await response.json();
10283
+ return SmarticoAPI.replaceSmrDomainsWithCloudfront(data);
10284
+ } catch (e) {
10285
+ this.logger.error(`Failed to call avatar API: ${method}`, {
10286
+ url,
10287
+ error: e.message
10288
+ });
10289
+ throw new Error(`Failed to call avatar API: ${method}. ${e.message}`);
10290
+ }
10291
+ }
10101
10292
  async gpGetActiveRounds(saw_template_id) {
10102
10293
  const params = {
10103
10294
  ext_game_id: saw_template_id
@@ -10205,6 +10396,21 @@ class SmarticoAPI {
10205
10396
  });
10206
10397
  return await this.send(message, ClassId.CLIENT_SET_AVATAR_RESPONSE);
10207
10398
  }
10399
+ async avatarsCustomize(params) {
10400
+ var _this$tracker, _this$tracker2;
10401
+ return this.sendAvatarApi({
10402
+ method: 'avatar-customize',
10403
+ body: {
10404
+ label_id: params.label_id,
10405
+ user_id: params.user_id,
10406
+ user_ext_id: (_this$tracker = this.tracker) == null ? void 0 : _this$tracker.getExtUserId(),
10407
+ brand_key: this.brand_api_key || ((_this$tracker2 = this.tracker) == null || (_this$tracker2 = _this$tracker2.params) == null ? void 0 : _this$tracker2.brand_key),
10408
+ prompt_id: params.prompt_id,
10409
+ avatar_url: params.avatar_url,
10410
+ avatar_real_id: params.avatar_real_id
10411
+ }
10412
+ });
10413
+ }
10208
10414
  async avatarsGetListT(user_ext_id) {
10209
10415
  var _await$this$avatarsGe;
10210
10416
  return avatarDefinitionTransform((_await$this$avatarsGe = (await this.avatarsGetList(user_ext_id)).avatars) != null ? _await$this$avatarsGe : [], this.avatarDomain);
@@ -10878,43 +11084,52 @@ var JackpotType;
10878
11084
  JackpotType[JackpotType["Personal"] = 2] = "Personal";
10879
11085
  })(JackpotType || (JackpotType = {}));
10880
11086
 
11087
+ /**
11088
+ * Limit error codes returned in `errCode` by the `avatarsCustomize` method.
11089
+ * See the `avatarsCustomize` TSDoc for the full table (including the generic
11090
+ * `-1` failure, which has no named member here).
11091
+ */
10881
11092
  var AvatarCustomizeErrorCode;
10882
11093
  (function (AvatarCustomizeErrorCode) {
11094
+ /** The user has reached the operator-configured per-user monthly cap on custom-avatar generations. */
10883
11095
  AvatarCustomizeErrorCode[AvatarCustomizeErrorCode["AVATAR_USER_LIMIT"] = 12001] = "AVATAR_USER_LIMIT";
11096
+ /** The brand's operator-configured shared monthly pool of custom-avatar generations is exhausted. */
10884
11097
  AvatarCustomizeErrorCode[AvatarCustomizeErrorCode["AVATAR_LABEL_LIMIT"] = 12002] = "AVATAR_LABEL_LIMIT";
10885
11098
  })(AvatarCustomizeErrorCode || (AvatarCustomizeErrorCode = {}));
10886
- const AvatarCustomizeErrorMessage = {
10887
- [AvatarCustomizeErrorCode.AVATAR_USER_LIMIT]: 'You have exceeded number of custom avatars creation, please try later',
10888
- [AvatarCustomizeErrorCode.AVATAR_LABEL_LIMIT]: 'The custom avatars are not available, please try again later'
10889
- };
10890
11099
 
10891
- /*
10892
- * Possible error codes returned in JOIN_CLAN_RESPONSE.errCode (cid: 575).
10893
- * Clan-protocol-specific numeric codes defined in the handler spec.
11100
+ /**
11101
+ * Error codes returned in `errCode` by the `joinClan` method (also carried
11102
+ * on `TClanJoinResult`). These are terse value definitions for lookup; the
11103
+ * full per-code narrative and UI handling lives in the `joinClan` method
11104
+ * TSDoc, which owns the error table.
10894
11105
  */
10895
11106
  var JoinClanErrorCode;
10896
11107
  (function (JoinClanErrorCode) {
10897
- /** No error, join completed */
11108
+ /** Success — join completed; entry fee (if any) deducted. */
10898
11109
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_OK"] = 0] = "JOIN_CLAN_OK";
10899
- /** Invalid parameters */
11110
+ /** Request was malformed (missing or invalid parameters). */
10900
11111
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_INVALID_PARAMETERS"] = 1000] = "JOIN_CLAN_INVALID_PARAMETERS";
10901
- /** clan_id doesn't exist for this label */
11112
+ /** Clan doesn't exist for this label. Archived clans are also reported as `1001`. */
10902
11113
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_NOT_FOUND"] = 1001] = "JOIN_CLAN_NOT_FOUND";
10903
- /** members_count >= capacity_limit */
11114
+ /** Clan is full — member capacity reached. */
10904
11115
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_FULL"] = 1002] = "JOIN_CLAN_FULL";
10905
- /** Not enough Points / Gems / Diamonds for entry fee */
11116
+ /** Insufficient balance for the entry fee (points / gems / diamonds). */
10906
11117
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_INSUFFICIENT_FUNDS"] = 1003] = "JOIN_CLAN_INSUFFICIENT_FUNDS";
10907
- /** User doesn't satisfy entry_conditions / entry_segment_id */
11118
+ /** User doesn't meet the clan's entry segment or conditions. */
10908
11119
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_SEGMENT_MISMATCH"] = 1004] = "JOIN_CLAN_SEGMENT_MISMATCH";
10909
- /** User is not in a clan */
11120
+ /**
11121
+ * User is not in a clan. Note: a `registerInTournament` response code
11122
+ * that shares this enum — never returned by `joinClan`.
11123
+ */
10910
11124
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_USER_IS_NOT_IN_CLAN"] = 1005] = "JOIN_CLAN_USER_IS_NOT_IN_CLAN";
10911
- /** User is within the CLAN_COOLDOWN_DAYS window */
11125
+ /** User is within the clan-switch cooldown window (switch only). */
10912
11126
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_COOLDOWN_ACTIVE"] = 1006] = "JOIN_CLAN_COOLDOWN_ACTIVE";
10913
- /** clan_status_id != 1 (clan is archived) */
10914
- JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_ARCHIVED"] = 1007] = "JOIN_CLAN_ARCHIVED";
10915
- /** Clan joined after tournament start */
11127
+ /**
11128
+ * Clan joined after tournament start. Note: a `registerInTournament`
11129
+ * response code that shares this enum — never returned by `joinClan`.
11130
+ */
10916
11131
  JoinClanErrorCode[JoinClanErrorCode["JOIN_CLAN_JOINED_AFTER_TOURNAMENT_START"] = 1011] = "JOIN_CLAN_JOINED_AFTER_TOURNAMENT_START";
10917
11132
  })(JoinClanErrorCode || (JoinClanErrorCode = {}));
10918
11133
 
10919
- export { AchCategoryTransform, AchCustomLayoutTheme, AchCustomSectionType, AchMissionsTabsOptions, AchOverviewMissionsFilter, AchievementAvailabilityStatus, AchievementClaimPeriodTypeId, AchievementStatus, AchievementTaskType, AchievementType, ActivityLogTransform, ActivityTypeLimited, AllRoundsGameBoardID, AnalyticsInboxSubScreenNameId, AnalyticsInterfaceType, AnalyticsScreenNameId, AnalyticsTournamentsLobbySubScreenNameId, AttemptPeriodType, AvatarCustomizeErrorCode, AvatarCustomizeErrorMessage, BadgesTimeLimitStates, BonusItemsTransform, BonusStatus, BuyStoreItemErrorCode, ClassId, CookieStore, CoreUtils, ECacheContext, GPRoundStatus, GamePickMarketType, GamePickResolutionType, GamePickScoreType, GamePickSportType, GameRoundOrderType, GetJackpotEligibleGamesResponseTransform, GetJackpotWinnersResponseTransform, GetLevelMapResponseTransform, InboxCategories, InboxMessageBodyTransform, InboxMessageType, InboxMessagesTransform, InboxReadStatus, JackPotTemparature, JackpotContributionType, JackpotType, JoinClanErrorCode, LeaderBoardPeriodType, LiquidEntityData, MiniGamePrizeTypeName, MiniGamePrizeTypeNamed, MissionCategory, MissionUtils, OCache, OpenLinksType, PointChangeSourceType, PrizeModifiers, PrizeModifiersKeysNames, PublicLabelSettings, QuizAnswersValueType, QuizMarketPerSport, QuizSportType, RaffleDrawInstanceState, RaffleDrawTypeExecution, RaffleTicketCapVisualization, SAWAcknowledgeType, SAWAcknowledgeTypeName, SAWAcknowledgeTypeNamed, SAWAskForUsername, SAWBuyInType, SAWBuyInTypeName, SAWBuyInTypeNamed, SAWExposeUserSpinId, SAWExposeUserSpinIdName, SAWExposeUserSpinIdNamed, SAWGPMarketType, SAWGameDifficultyType, SAWGameDifficultyTypeName, SAWGameLayout, SAWGameLayoutName, SAWGameLayoutNamed, SAWGameType, SAWGameTypeName, SAWGameTypeNamed, SAWHistoryTransform, SAWPrizeType, SAWSpinErrorCode, SAWTemplatesTransform, SAWUtils, SAWWheelLayout, SAWWinSoundFiles, SAWWinSoundType, SawGameDifficultyTypeNamed, ScheduledMissionType, SmarticoAPI, StoreCategoryTransform, StoreItemPurchaseType, StoreItemPurchasedTransform, StoreItemTransform, StoreItemType, StoreItemTypeName, StoreItemTypeNamed, TournamentInstanceStatus, TournamentInstanceStatusName, TournamentItemsTransform, TournamentRegistrationError, TournamentRegistrationStatus, TournamentRegistrationStatusName, TournamentRegistrationStatusNamed, TournamentRegistrationType, TournamentRegistrationTypeGetName, TournamentType, TournamentUtils, TranslationArea, UICustomSectionTransform, UserAchievementTransform, UserBalanceType, WSAPI, avatarCustomizedTransform, avatarDefinitionTransform, avatarPromptTransform, clanTournamentPlayersTransform, drawRunHistoryTransform, drawRunTransform, drawTransform, enrichUserAchievementsWithBadgeState, getLeaderBoardTransform, marketsInfo, prizeTransform, quizAnswerAwayTeamReplacementText, quizAnswerHomeTeamReplacementText, quizAnswersTrKeys, quizDrawReplacementText, quizEvenReplacementText, quizNoGoalsReplacementText, quizNoReplacementText, quizOddReplacementText, quizOrReplacementText, quizSupportedSports, quizYesReplacementText, raffleClaimPrizeResponseTransform, raffleTransform, ticketsTransform, tournamentInfoItemTransform, winnersTransform };
11134
+ export { AchCategoryTransform, AchCustomLayoutTheme, AchCustomSectionType, AchMissionsTabsOptions, AchOverviewMissionsFilter, AchievementAvailabilityStatus, AchievementClaimPeriodTypeId, AchievementStatus, AchievementTaskType, AchievementType, ActivityLogTransform, ActivityTypeLimited, AllRoundsGameBoardID, AnalyticsInboxSubScreenNameId, AnalyticsInterfaceType, AnalyticsScreenNameId, AnalyticsTournamentsLobbySubScreenNameId, AttemptPeriodType, AvatarCustomizeErrorCode, BadgesTimeLimitStates, BonusItemsTransform, BonusStatus, BuyStoreItemErrorCode, ClassId, CookieStore, CoreUtils, ECacheContext, GPRoundStatus, GamePickMarketType, GamePickResolutionType, GamePickScoreType, GamePickSportType, GameRoundOrderType, GetJackpotEligibleGamesResponseTransform, GetJackpotWinnersResponseTransform, GetLevelMapResponseTransform, InboxCategories, InboxMessageBodyTransform, InboxMessageType, InboxMessagesTransform, InboxReadStatus, JackPotTemparature, JackpotContributionType, JackpotType, JoinClanErrorCode, LeaderBoardPeriodType, LiquidEntityData, MiniGamePrizeTypeName, MiniGamePrizeTypeNamed, MissionCategory, MissionUtils, OCache, OpenLinksType, PointChangeSourceType, PrizeModifiers, PrizeModifiersKeysNames, PublicLabelSettings, QuizAnswersValueType, QuizMarketPerSport, QuizSportType, RaffleDrawInstanceState, RaffleDrawTypeExecution, RaffleTicketCapVisualization, SAWAcknowledgeType, SAWAcknowledgeTypeName, SAWAcknowledgeTypeNamed, SAWAskForUsername, SAWBuyInType, SAWBuyInTypeName, SAWBuyInTypeNamed, SAWExposeUserSpinId, SAWExposeUserSpinIdName, SAWExposeUserSpinIdNamed, SAWGPMarketType, SAWGameDifficultyType, SAWGameDifficultyTypeName, SAWGameLayout, SAWGameLayoutName, SAWGameLayoutNamed, SAWGameType, SAWGameTypeName, SAWGameTypeNamed, SAWHistoryTransform, SAWPrizeType, SAWSpinErrorCode, SAWTemplatesTransform, SAWUtils, SAWWheelLayout, SAWWinSoundFiles, SAWWinSoundType, SawGameDifficultyTypeNamed, ScheduledMissionType, SmarticoAPI, StoreCategoryTransform, StoreItemPurchaseType, StoreItemPurchasedTransform, StoreItemTransform, StoreItemType, StoreItemTypeName, StoreItemTypeNamed, TournamentInstanceStatus, TournamentInstanceStatusName, TournamentItemsTransform, TournamentRegistrationError, TournamentRegistrationStatus, TournamentRegistrationStatusName, TournamentRegistrationStatusNamed, TournamentRegistrationType, TournamentRegistrationTypeGetName, TournamentType, TournamentUtils, TranslationArea, UICustomSectionTransform, UserAchievementTransform, UserBalanceType, WSAPI, avatarCustomizedTransform, avatarDefinitionTransform, avatarPromptTransform, clanTournamentPlayersTransform, drawRunHistoryTransform, drawRunTransform, drawTransform, enrichUserAchievementsWithBadgeState, getLeaderBoardTransform, marketsInfo, prizeTransform, quizAnswerAwayTeamReplacementText, quizAnswerHomeTeamReplacementText, quizAnswersTrKeys, quizDrawReplacementText, quizEvenReplacementText, quizNoGoalsReplacementText, quizNoReplacementText, quizOddReplacementText, quizOrReplacementText, quizSupportedSports, quizYesReplacementText, raffleClaimPrizeResponseTransform, raffleTransform, ticketsTransform, tournamentInfoItemTransform, winnersTransform };
10920
11135
  //# sourceMappingURL=index.modern.mjs.map