@smartico/public-api 0.0.380 → 0.0.382

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 (178) hide show
  1. package/CLAUDE.md +103 -0
  2. package/README.md +32 -10
  3. package/dist/Base/ClassId.d.ts +2 -0
  4. package/dist/Jackpots/JackpotDetails.d.ts +14 -15
  5. package/dist/Jackpots/JackpotPot.d.ts +10 -6
  6. package/dist/MiniGames/SAWGameType.d.ts +3 -1
  7. package/dist/MiniGames/SAWTemplateUI.d.ts +7 -0
  8. package/dist/Raffle/GetRaffleWonPrizesRequest.d.ts +9 -0
  9. package/dist/Raffle/GetRaffleWonPrizesResponse.d.ts +52 -0
  10. package/dist/Raffle/index.d.ts +2 -0
  11. package/dist/SmarticoAPI.d.ts +6 -1
  12. package/dist/SmarticoLib/index.d.ts +5 -1
  13. package/dist/WSAPI/WSAPIAvatars.d.ts +267 -49
  14. package/dist/WSAPI/WSAPIBonuses.d.ts +224 -10
  15. package/dist/WSAPI/WSAPIGamePick.d.ts +538 -253
  16. package/dist/WSAPI/WSAPIGeneral.d.ts +156 -14
  17. package/dist/WSAPI/WSAPIInbox.d.ts +547 -58
  18. package/dist/WSAPI/WSAPIJackpots.d.ts +292 -57
  19. package/dist/WSAPI/WSAPILeaderBoard.d.ts +127 -13
  20. package/dist/WSAPI/WSAPIMiniGames.d.ts +465 -49
  21. package/dist/WSAPI/WSAPIRaffles.d.ts +576 -52
  22. package/dist/WSAPI/WSAPITournaments.d.ts +3 -3
  23. package/dist/WSAPI/WSAPITypes.d.ts +243 -132
  24. package/dist/WSAPI/WSAPIUser.d.ts +193 -43
  25. package/dist/index.js +3412 -616
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.modern.mjs +3395 -609
  28. package/dist/index.modern.mjs.map +1 -1
  29. package/docs/Callbacks.md +162 -0
  30. package/docs/SmarticoObject.md +445 -0
  31. package/docs/Transforms.md +99 -0
  32. package/docs/api/README.md +26 -0
  33. package/docs/api/classes/WSAPIAvatars.md +282 -54
  34. package/docs/api/classes/WSAPIBonuses.md +233 -12
  35. package/docs/api/classes/WSAPIClans.md +380 -10
  36. package/docs/api/classes/WSAPIGamePick.md +555 -26
  37. package/docs/api/classes/WSAPIGeneral.md +165 -16
  38. package/docs/api/classes/WSAPIInbox.md +588 -64
  39. package/docs/api/classes/WSAPIJackpots.md +320 -66
  40. package/docs/api/classes/WSAPILeaderBoard.md +133 -15
  41. package/docs/api/classes/WSAPIMiniGames.md +501 -64
  42. package/docs/api/classes/WSAPIMissions.md +58 -79
  43. package/docs/api/classes/WSAPIRaffles.md +647 -69
  44. package/docs/api/classes/WSAPIStore.md +83 -108
  45. package/docs/api/classes/WSAPITournaments.md +495 -28
  46. package/docs/api/classes/WSAPIUser.md +520 -83
  47. package/docs/api/documents/Callbacks.md +162 -0
  48. package/docs/api/documents/SmarticoObject.md +445 -0
  49. package/docs/api/documents/Transforms.md +99 -0
  50. package/docs/api/enumerations/BonusStatus-1.md +11 -6
  51. package/docs/api/enumerations/JoinClanErrorCode.md +81 -0
  52. package/docs/api/enumerations/TournamentRegistrationError.md +12 -0
  53. package/docs/api/functions/clanTournamentPlayersTransform.md +13 -0
  54. package/docs/api/interfaces/AvatarCustomized.md +25 -0
  55. package/docs/api/interfaces/AvatarDefinition.md +94 -0
  56. package/docs/api/interfaces/AvatarPrompt.md +45 -0
  57. package/docs/api/interfaces/BonusMetaMap-1.md +4 -1
  58. package/docs/api/interfaces/BonusTemplateMetaMap-1.md +9 -4
  59. package/docs/api/interfaces/Clan.md +4 -0
  60. package/docs/api/interfaces/ClanInfo.md +109 -0
  61. package/docs/api/interfaces/ClanMember.md +53 -0
  62. package/docs/api/interfaces/ClanTournamentPlayerRaw.md +67 -0
  63. package/docs/api/interfaces/GemsDiamondsLog.md +43 -0
  64. package/docs/api/interfaces/GetClanInfoResponse.md +61 -0
  65. package/docs/api/interfaces/GetClanTournamentPlayersResponse.md +81 -0
  66. package/docs/api/interfaces/GetRaffleWonPrizesRequest.md +59 -0
  67. package/docs/api/interfaces/GetRaffleWonPrizesResponse.md +95 -0
  68. package/docs/api/interfaces/InboxMarkMessageAction.md +10 -2
  69. package/docs/api/interfaces/JackpotDetails.md +14 -15
  70. package/docs/api/interfaces/JackpotPot.md +9 -6
  71. package/docs/api/interfaces/LeaderBoardDetailsT.md +14 -8
  72. package/docs/api/interfaces/LeaderBoardUserT.md +8 -5
  73. package/docs/api/interfaces/LeaderBoardsRewardsT.md +7 -0
  74. package/docs/api/interfaces/PointsLog.md +43 -0
  75. package/docs/api/interfaces/RaffleWonPrize.md +59 -0
  76. package/docs/api/interfaces/RaffleWonPrizePublicMeta.md +27 -0
  77. package/docs/api/interfaces/RaffleWonPrizeUser.md +43 -0
  78. package/docs/api/interfaces/TAchCategory.md +2 -7
  79. package/docs/api/interfaces/TAvatarCustomized.md +4 -4
  80. package/docs/api/interfaces/TAvatarDefinition.md +13 -14
  81. package/docs/api/interfaces/TAvatarPrompt.md +6 -6
  82. package/docs/api/interfaces/TBonus.md +16 -8
  83. package/docs/api/interfaces/TBuyStoreItemResult.md +4 -29
  84. package/docs/api/interfaces/TClaimBonusResult.md +5 -5
  85. package/docs/api/interfaces/TClan.md +8 -4
  86. package/docs/api/interfaces/TClanInfo.md +47 -0
  87. package/docs/api/interfaces/TClanJoinResult.md +11 -1
  88. package/docs/api/interfaces/TClanTournamentPlayer.md +55 -0
  89. package/docs/api/interfaces/TClanTournamentPlayersResult.md +27 -0
  90. package/docs/api/interfaces/TClans.md +3 -1
  91. package/docs/api/interfaces/TGetTranslations.md +4 -0
  92. package/docs/api/interfaces/TInboxMessage.md +14 -6
  93. package/docs/api/interfaces/TInboxMessageBody.md +18 -12
  94. package/docs/api/interfaces/TLevel.md +17 -20
  95. package/docs/api/interfaces/TLevelCurrent.md +19 -18
  96. package/docs/api/interfaces/TMiniGamePlayBatchResult.md +14 -6
  97. package/docs/api/interfaces/TMiniGamePlayResult.md +9 -4
  98. package/docs/api/interfaces/TMissionClaimRewardResult.md +1 -9
  99. package/docs/api/interfaces/TMissionOptInResult.md +1 -5
  100. package/docs/api/interfaces/TMissionOrBadge.md +4 -7
  101. package/docs/api/interfaces/TRaffleOptinResponse.md +4 -2
  102. package/docs/api/interfaces/TSegmentCheckResult.md +10 -0
  103. package/docs/api/interfaces/TSetAvatarResult.md +3 -3
  104. package/docs/api/interfaces/TStoreItem.md +3 -13
  105. package/docs/api/interfaces/TTournament.md +1 -1
  106. package/docs/api/interfaces/TTournamentDetailed.md +1 -1
  107. package/docs/api/interfaces/TTournamentRegistrationResult.md +4 -2
  108. package/docs/api/interfaces/TUICustomSection.md +23 -19
  109. package/docs/api/interfaces/TUserProfile.md +18 -16
  110. package/docs/api/interfaces/TransformedRaffleClaimPrizeResponse.md +6 -2
  111. package/docs/api/interfaces/UserLevelExtraCountersT.md +9 -2
  112. package/docs/api/type-aliases/ActivityLogEntry.md +3 -0
  113. package/docs/native/ADDING_METHODS.md +7 -2
  114. package/docs/native/PROTOCOL.md +337 -0
  115. package/docs/ui/avatars/UIGuide_getAvatarPrompts.md +100 -0
  116. package/docs/ui/avatars/UIGuide_getAvatarsCustomized.md +90 -0
  117. package/docs/ui/avatars/UIGuide_getAvatarsList.md +105 -0
  118. package/docs/ui/avatars/UIGuide_setAvatar.md +118 -0
  119. package/docs/ui/bonuses/UIGuide_claimBonus.md +144 -0
  120. package/docs/ui/bonuses/UIGuide_getBonuses.md +176 -0
  121. package/docs/ui/gamepick/UIGuide_gamePickGetActiveRound.md +99 -0
  122. package/docs/ui/gamepick/UIGuide_gamePickGetActiveRounds.md +76 -0
  123. package/docs/ui/gamepick/UIGuide_gamePickGetBoard.md +81 -0
  124. package/docs/ui/gamepick/UIGuide_gamePickGetGameInfo.md +78 -0
  125. package/docs/ui/gamepick/UIGuide_gamePickGetHistory.md +55 -0
  126. package/docs/ui/gamepick/UIGuide_gamePickGetRoundInfoForUser.md +71 -0
  127. package/docs/ui/gamepick/UIGuide_gamePickGetUserInfo.md +64 -0
  128. package/docs/ui/gamepick/UIGuide_gamePickSubmitSelection.md +103 -0
  129. package/docs/ui/gamepick/UIGuide_gamePickSubmitSelectionQuiz.md +67 -0
  130. package/docs/ui/general/UIGuide_getCustomSections.md +137 -0
  131. package/docs/ui/general/UIGuide_getRelatedItemsForGame.md +140 -0
  132. package/docs/ui/inbox/UIGuide_deleteInboxMessage.md +135 -0
  133. package/docs/ui/inbox/UIGuide_getInboxMessageBody.md +133 -0
  134. package/docs/ui/inbox/UIGuide_getInboxMessages.md +186 -0
  135. package/docs/ui/inbox/UIGuide_markInboxMessageAsRead.md +122 -0
  136. package/docs/ui/inbox/UIGuide_markUnmarkInboxMessageAsFavorite.md +84 -0
  137. package/docs/ui/jackpots/UIGuide_getJackpotEligibleGames.md +73 -0
  138. package/docs/ui/jackpots/UIGuide_getJackpotWinners.md +83 -0
  139. package/docs/ui/jackpots/UIGuide_jackpotGet.md +138 -0
  140. package/docs/ui/jackpots/UIGuide_jackpotOptIn.md +85 -0
  141. package/docs/ui/jackpots/UIGuide_jackpotOptOut.md +65 -0
  142. package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +166 -0
  143. package/docs/ui/minigames/UIGuide_getMiniGames.md +153 -0
  144. package/docs/ui/minigames/UIGuide_getMiniGamesHistory.md +90 -0
  145. package/docs/ui/minigames/UIGuide_playMiniGame.md +150 -0
  146. package/docs/ui/minigames/UIGuide_playMiniGameBatch.md +128 -0
  147. package/docs/ui/raffles/UIGuide_claimRafflePrize.md +99 -0
  148. package/docs/ui/raffles/UIGuide_getRaffleDrawRun.md +117 -0
  149. package/docs/ui/raffles/UIGuide_getRaffleDrawRunsHistory.md +92 -0
  150. package/docs/ui/raffles/UIGuide_getRaffleWonPrizes.md +120 -0
  151. package/docs/ui/raffles/UIGuide_getRaffles.md +175 -0
  152. package/docs/ui/raffles/UIGuide_requestRaffleOptin.md +114 -0
  153. package/docs/ui/user/UIGuide_getActivityLog.md +130 -0
  154. package/docs/ui/user/UIGuide_getLevels.md +47 -42
  155. package/package.json +1 -1
  156. package/src/Base/ClassId.ts +2 -0
  157. package/src/Jackpots/JackpotDetails.ts +14 -15
  158. package/src/Jackpots/JackpotPot.ts +10 -6
  159. package/src/MiniGames/SAWGameType.ts +3 -0
  160. package/src/MiniGames/SAWTemplateUI.ts +10 -0
  161. package/src/Raffle/GetRaffleWonPrizesRequest.ts +12 -0
  162. package/src/Raffle/GetRaffleWonPrizesResponse.ts +56 -0
  163. package/src/Raffle/index.ts +3 -1
  164. package/src/SmarticoAPI.ts +14 -1
  165. package/src/SmarticoLib/index.ts +4 -0
  166. package/src/WSAPI/WSAPIAvatars.ts +267 -49
  167. package/src/WSAPI/WSAPIBonuses.ts +224 -10
  168. package/src/WSAPI/WSAPIGamePick.ts +538 -253
  169. package/src/WSAPI/WSAPIGeneral.ts +156 -14
  170. package/src/WSAPI/WSAPIInbox.ts +545 -56
  171. package/src/WSAPI/WSAPIJackpots.ts +297 -61
  172. package/src/WSAPI/WSAPILeaderBoard.ts +127 -13
  173. package/src/WSAPI/WSAPIMiniGames.ts +465 -49
  174. package/src/WSAPI/WSAPIRaffles.ts +592 -64
  175. package/src/WSAPI/WSAPITournaments.ts +3 -3
  176. package/src/WSAPI/WSAPITypes.ts +243 -132
  177. package/src/WSAPI/WSAPIUser.ts +193 -43
  178. package/tsconfig.json +9 -1
@@ -2127,10 +2127,12 @@ declare enum EWidgetType {
2127
2127
  }
2128
2128
  declare enum EXTERNAL_CALLBACK_KEY {
2129
2129
  INIT = 'init',
2130
+ LABEL_INIT_COMPLETED = 'label_init_completed',
2130
2131
  IDENTIFY = 'identify',
2131
2132
  LOGIN = 'login',
2132
2133
  LOGOUT = 'logout',
2133
2134
  USER_PROPS_CHANGE = 'props_change',
2135
+ PAGE_NAVIGATION = 'page_navigation',
2134
2136
  SESSION_BASED_DP_DETECTED = 'session_based_dp_detected',
2135
2137
  GF_CLOSING = 'gf_closing',
2136
2138
  GF_STARTING = 'gf_starting',
@@ -2140,6 +2142,8 @@ declare enum EXTERNAL_CALLBACK_KEY {
2140
2142
  PROTOCOL_ERROR = 'protocol_error',
2141
2143
  MNIGAME_WIN = 'mini_game_win',
2142
2144
  ACH_GAME_OPENING = 'ach_game_opening',
2145
+ JACKPOT_WIN = 'jackpot_win',
2146
+ GF_UX = 'gf_ux',
2143
2147
  }
2144
2148
  declare enum DpType {
2145
2149
  AskPushPermissions = 'ask_push_permissions',
@@ -14,19 +14,63 @@ import { WSAPIMiniGames } from './WSAPIMiniGames';
14
14
  /** @group Avatars */
15
15
  export class WSAPIAvatars extends WSAPIMiniGames {
16
16
  /**
17
- * Returns the list of avatars available in the catalog for the current user.
18
- * The response includes both free avatars and earned/purchased ones.
19
- * Avatars with `hide_until_achieved = true` and `is_given = false` should be hidden from the user.
20
- * The result is cached for 30 seconds.
17
+ * Returns the avatar catalog available to the current user — every pre-defined
18
+ * avatar configured for the label, with per-user unlock flags (`is_given`, `is_in_use`)
19
+ * applied server-side.
21
20
  *
22
- * **Example**:
23
- * ```
24
- * _smartico.api.getAvatarsList().then((result) => {
25
- * console.log(result);
26
- * });
27
- * ```
21
+ * The returned `avatar_url` is the absolute CDN URL (the SDK prefixes relative paths
22
+ * with the configured avatar domain). AI-customized variants are NOT returned here —
23
+ * those live in {@link getAvatarsCustomized}.
24
+ *
25
+ * @remarks
26
+ * **Preconditions**
27
+ * - User must be authenticated. Visitor mode is not supported.
28
+ * - No other prerequisite calls.
29
+ *
30
+ * **Visibility filter** (consumer-applied)
31
+ * Avatars with `hide_until_achieved === true && is_given === false` should be filtered
32
+ * out of the grid — they represent surprise unlocks that should remain hidden until
33
+ * the user earns them. The default Smartico UI drops these before rendering.
34
+ *
35
+ * **Lock state** (consumer-applied)
36
+ * Lock condition: `!is_given && avatar_source_type_id !== 0`. Free avatars
37
+ * (`avatar_source_type_id === 0`) are always selectable; non-free avatars are locked
38
+ * until `is_given` flips to true (operator grants via campaign, mission reward, store
39
+ * purchase, etc.).
40
+ *
41
+ * **Sort order**
42
+ * Server does NOT pre-sort. Caller must sort by `priority` ascending (lower = first).
43
+ *
44
+ * **Refresh**
45
+ * - The SDK caches results for 30 seconds.
46
+ * - {@link setAvatar} clears this cache on completion; the next call re-fetches.
47
+ * - No push subscription — there is no `onUpdate` callback for avatar methods.
48
+ * - When `is_given` flips server-side (e.g. the user earns a new avatar), the change
49
+ * surfaces only on the next call after the 30-second cache window expires.
28
50
  *
29
- * **Visitor mode: not supported**
51
+ * **Visitor mode**: not supported.
52
+ *
53
+ * **UI guidance**: see [UI Guide — `getAvatarsList`](../../docs/ui/avatars/UIGuide_getAvatarsList.md).
54
+ *
55
+ * @returns Array of {@link TAvatarDefinition} — empty array if the feature is disabled
56
+ * on the label.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const avatars = await window._smartico.api.getAvatarsList();
61
+ *
62
+ * // Apply the standard visibility filter and sort.
63
+ * const visible = avatars
64
+ * .filter((a) => !a.hide_until_achieved || a.is_given)
65
+ * .sort((a, b) => a.priority - b.priority);
66
+ *
67
+ * console.log('[smartico] visible avatars:', visible.length, '— render as a grid');
68
+ *
69
+ * const active = visible.find((a) => a.is_in_use);
70
+ * if (active) {
71
+ * console.log('[smartico] currently in use — overlay a checkmark on this card:', active.avatar_real_id);
72
+ * }
73
+ * ```
30
74
  */
31
75
  public async getAvatarsList(): Promise<TAvatarDefinition[]> {
32
76
  return OCache.use(
@@ -38,18 +82,70 @@ export class WSAPIAvatars extends WSAPIMiniGames {
38
82
  }
39
83
 
40
84
  /**
41
- * Returns the list of AI-customized avatars for the current user.
42
- * Each entry represents a previously generated AI customization for a specific base avatar.
43
- * The result is cached for 30 seconds.
85
+ * Returns the user's previously generated AI-customized avatar variants.
44
86
  *
45
- * **Example**:
46
- * ```
47
- * _smartico.api.getAvatarsCustomized().then((result) => {
48
- * console.log(result);
49
- * });
50
- * ```
87
+ * Each entry is one AI-generated image derived from a base avatar in the catalog
88
+ * (the base is identified by `avatar_real_id` and was originally a
89
+ * {@link TAvatarDefinition} from {@link getAvatarsList}). These variants are stored
90
+ * server-side under the user record and persist across sessions.
91
+ *
92
+ * @remarks
93
+ * **Preconditions**
94
+ * - User must be authenticated. Visitor mode is not supported.
95
+ * - Has meaning only after at least one successful AI customization run (see below).
96
+ * New users get an empty array.
97
+ *
98
+ * **Where customized avatars come from**
99
+ * AI customization is **not** a WebSocket method on this SDK. It is a separate HTTP
100
+ * POST to the operator-configured `avatar-customize` endpoint that takes a base avatar
101
+ * plus a style prompt from {@link getAvatarPrompts} and returns a generated CDN URL.
102
+ * Once that POST resolves successfully, the new variant is persisted and surfaces in
103
+ * the next `getAvatarsCustomized()` call. The variant URL can then be passed to
104
+ * {@link setAvatar} to activate it.
105
+ *
106
+ * **Relation to `getAvatarsList`**
107
+ * AI variants do NOT appear in {@link getAvatarsList}. Catalog and variants are two
108
+ * separate collections — combine them client-side if the UI needs a unified view per
109
+ * base avatar.
110
+ *
111
+ * **Sort order**
112
+ * Server does NOT pre-sort. Caller typically sorts by `dt_created` descending to show
113
+ * the newest variant first.
114
+ *
115
+ * **Refresh**
116
+ * - The SDK caches results for 30 seconds.
117
+ * - {@link setAvatar} clears this cache on completion.
118
+ * - After a successful AI customization POST, the consumer should re-call to surface
119
+ * the new variant — the customization endpoint is outside the SDK so the SDK cannot
120
+ * auto-invalidate.
121
+ * - No push subscription.
122
+ *
123
+ * **Visitor mode**: not supported.
124
+ *
125
+ * **UI guidance**: see [UI Guide — `getAvatarsCustomized`](../../docs/ui/avatars/UIGuide_getAvatarsCustomized.md).
126
+ *
127
+ * @returns Array of {@link TAvatarCustomized} — empty if the user has never run AI
128
+ * customization, or if the feature is disabled on the label.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * const variants = await window._smartico.api.getAvatarsCustomized();
133
+ *
134
+ * // Group by the base avatar so the UI can show "this base has 3 AI variants".
135
+ * const byBase = new Map<number, typeof variants>();
136
+ * for (const v of variants) {
137
+ * const list = byBase.get(v.avatar_real_id) ?? [];
138
+ * list.push(v);
139
+ * byBase.set(v.avatar_real_id, list);
140
+ * }
141
+ *
142
+ * // Newest-first within each base.
143
+ * for (const list of byBase.values()) {
144
+ * list.sort((a, b) => b.dt_created.localeCompare(a.dt_created));
145
+ * }
51
146
  *
52
- * **Visitor mode: not supported**
147
+ * console.log('[smartico] AI variants by base avatar — render as a carousel under each base');
148
+ * ```
53
149
  */
54
150
  public async getAvatarsCustomized(): Promise<TAvatarCustomized[]> {
55
151
  return OCache.use(
@@ -61,18 +157,53 @@ export class WSAPIAvatars extends WSAPIMiniGames {
61
157
  }
62
158
 
63
159
  /**
64
- * Returns the list of AI customization prompts (styles) available for avatar customization.
65
- * Each prompt represents a visual style that can be applied to a base avatar.
66
- * The result is cached for 30 seconds.
160
+ * Returns the catalog of AI style prompts available for avatar customization.
67
161
  *
68
- * **Example**:
69
- * ```
70
- * _smartico.api.getAvatarPrompts().then((result) => {
71
- * console.log(result);
72
- * });
73
- * ```
162
+ * Each entry is a "style" the user can apply to a base avatar (e.g. "Cartoon",
163
+ * "Watercolor", "Cyberpunk"). Prompts carry a cost expressed in points, gems, or
164
+ * diamonds — applying a prompt deducts the cost server-side as part of the AI
165
+ * generation request.
166
+ *
167
+ * @remarks
168
+ * **Preconditions**
169
+ * - User must be authenticated. Visitor mode is not supported.
170
+ * - No other prerequisite calls. The customization UI typically calls this on demand
171
+ * when the user opens the style picker, not on app boot.
172
+ *
173
+ * **Cost handling**
174
+ * Each prompt declares `cost_currency_type_id` (0 = points, 1 = gems, 2 = diamonds)
175
+ * and `cost_value` (amount). The deduction happens server-side inside the
176
+ * `avatar-customize` HTTP POST (the AI generation request, which is NOT part of this
177
+ * SDK). The client should compare `cost_value` against the live balance from
178
+ * {@link getUserProfile} to disable prompts the user cannot afford, but the server is
179
+ * the source of truth and will reject under-funded requests authoritatively.
180
+ *
181
+ * **Refresh**
182
+ * - The SDK caches results for 30 seconds.
183
+ * - Not invalidated by {@link setAvatar} (prompts are catalog metadata, independent
184
+ * of the user's active avatar).
185
+ * - No push subscription.
74
186
  *
75
- * **Visitor mode: not supported**
187
+ * **Visitor mode**: not supported.
188
+ *
189
+ * **UI guidance**: see [UI Guide — `getAvatarPrompts`](../../docs/ui/avatars/UIGuide_getAvatarPrompts.md).
190
+ *
191
+ * @returns Array of {@link TAvatarPrompt} — empty if the AI customization feature is
192
+ * disabled on the label.
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * const [prompts, profile] = await Promise.all([
197
+ * window._smartico.api.getAvatarPrompts(),
198
+ * window._smartico.api.getUserProfile(),
199
+ * ]);
200
+ *
201
+ * for (const p of prompts) {
202
+ * // The consumer reads the matching balance from profile based on
203
+ * // p.cost_currency_type_id (0=points, 1=gems, 2=diamonds).
204
+ * console.log('[smartico] prompt', p.name, '— cost', p.cost_value, 'currency_type', p.cost_currency_type_id);
205
+ * }
206
+ * ```
76
207
  */
77
208
  public async getAvatarPrompts(): Promise<TAvatarPrompt[]> {
78
209
  return OCache.use(
@@ -84,27 +215,114 @@ export class WSAPIAvatars extends WSAPIMiniGames {
84
215
  }
85
216
 
86
217
  /**
87
- * Sets the specified avatar as the active avatar for the current user.
88
- * Pass `avatar_url` (the `TAvatarDefinition.url` path or a CDN URL for AI-customized avatars)
89
- * and `avatar_real_id` from the avatar catalog.
90
- * After a successful call, the avatar list cache is cleared so the next `getAvatarsList()` call reflects `is_in_use`.
218
+ * Activates the specified avatar for the current user. The chosen image becomes the
219
+ * profile avatar — any subsequent {@link getUserProfile} call will reflect the new
220
+ * `avatar_url`.
91
221
  *
92
- * **Example**:
93
- * ```
94
- * _smartico.api.getAvatarsList().then((avatars) => {
95
- * const avatar = avatars.find((a) => !a.hide_until_achieved || a.is_given);
96
- * if (avatar) {
97
- * _smartico.api.setAvatar({
98
- * avatar_url: avatar.url,
99
- * avatar_real_id: avatar.avatar_real_id,
100
- * }).then((result) => {
101
- * console.log(result);
102
- * });
103
- * }
222
+ * Pass `avatar_url` (a {@link TAvatarDefinition.url} from the catalog or a
223
+ * {@link TAvatarCustomized.url} from the AI-variant list) plus `avatar_real_id` of the
224
+ * base avatar. The server validates ownership before applying — locked avatars are
225
+ * rejected.
226
+ *
227
+ * @remarks
228
+ * **Preconditions**
229
+ * - User must be authenticated. Visitor mode is not supported.
230
+ * - `avatar_url` must be non-empty and `avatar_real_id` must be truthy — the SDK
231
+ * throws synchronously otherwise (the request never reaches the server).
232
+ * - The avatar must exist in the catalog from {@link getAvatarsList} (or be an AI
233
+ * variant of a base avatar the user already owns). Free avatars
234
+ * (`avatar_source_type_id === 0`) and the user's currently active avatar bypass the
235
+ * ownership check; all others require `is_given === true`.
236
+ *
237
+ * **Error codes** (in `err_code`)
238
+ * - `0` — success; cache is cleared and the profile avatar updates immediately.
239
+ * - `1` — avatar not found in the catalog. The `avatar_real_id` doesn't exist for
240
+ * this label.
241
+ * - `2` — avatar inactive (deactivated by the operator).
242
+ * - `3` — outside the avatar's active time window
243
+ * (`active_from_date` / `active_till_date`).
244
+ * - `4` — user does not own this avatar (it isn't in their `is_given` set and isn't
245
+ * a free / default avatar).
246
+ * - other non-zero — generic server error; surface `err_message` if present.
247
+ *
248
+ * The default Smartico UI shows a hardcoded "Failed to apply avatar" toast on any
249
+ * non-zero `err_code` and does not surface `err_message`. Custom UIs SHOULD branch
250
+ * on the code and prefer `err_message` when present (it is the localized server
251
+ * string).
252
+ *
253
+ * **Refresh after success**
254
+ * - The SDK clears both the `getAvatarsList` and `getAvatarsCustomized` caches —
255
+ * the next call to either returns fresh data with the new `is_in_use` flag set on
256
+ * the chosen avatar.
257
+ * - The server persists the new avatar URL on the user record; {@link getUserProfile}
258
+ * reflects it on the next read in this session.
259
+ * - **No push to other open sessions.** A second device / tab the user is logged in
260
+ * on will not see the new avatar until it next calls {@link getUserProfile} or
261
+ * re-identifies. Plan UI accordingly.
262
+ *
263
+ * **Idempotency**: safe to retry. Re-applying the same `avatar_real_id` returns
264
+ * `err_code: 0` and produces no double side effects (no double-deduction — this
265
+ * method does not charge any currency — and no duplicate log entries).
266
+ *
267
+ * **Side effects**: updates the user's stored `avatar_id` / `avatar_real_id`. Does
268
+ * NOT cost points, gems, or diamonds — the cost lives on the separate AI
269
+ * customization HTTP flow ({@link getAvatarPrompts}). Does NOT write a user-visible
270
+ * entry to {@link getActivityLog}.
271
+ *
272
+ * **UI guidance**: see [UI Guide — `setAvatar`](../../docs/ui/avatars/UIGuide_setAvatar.md).
273
+ *
274
+ * **Visitor mode**: not supported.
275
+ *
276
+ * @param props.avatar_url Absolute CDN URL of the avatar image. Read from
277
+ * {@link TAvatarDefinition.url} for catalog avatars or
278
+ * {@link TAvatarCustomized.url} for AI variants.
279
+ * @param props.avatar_real_id Numeric ID of the base avatar from
280
+ * {@link TAvatarDefinition.avatar_real_id}. For AI
281
+ * variants, this is the `avatar_real_id` of the base
282
+ * they were derived from.
283
+ * @returns {@link TSetAvatarResult} — check `err_code === 0` for success.
284
+ *
285
+ * @example
286
+ * ```ts
287
+ * const avatars = await window._smartico.api.getAvatarsList();
288
+ * const target = avatars.find((a) => a.avatar_real_id === 7);
289
+ *
290
+ * if (!target) {
291
+ * console.error('[smartico] avatar 7 not in catalog — hide the picker entry');
292
+ * return;
293
+ * }
294
+ *
295
+ * const isLocked = !target.is_given && target.avatar_source_type_id !== 0;
296
+ * if (isLocked) {
297
+ * console.log('[smartico] avatar is locked — show "earn this first" prompt instead of calling setAvatar');
298
+ * return;
299
+ * }
300
+ *
301
+ * const r = await window._smartico.api.setAvatar({
302
+ * avatar_url: target.avatar_url,
303
+ * avatar_real_id: target.avatar_real_id,
104
304
  * });
105
- * ```
106
305
  *
107
- * **Visitor mode: not supported**
306
+ * switch (r.err_code) {
307
+ * case 0:
308
+ * console.log('[smartico] avatar applied — close picker, refresh header avatar');
309
+ * break;
310
+ * case 1:
311
+ * console.error('[smartico] avatar not in catalog — refresh catalog and show error');
312
+ * break;
313
+ * case 2:
314
+ * console.error('[smartico] avatar inactive — operator disabled it; hide from picker');
315
+ * break;
316
+ * case 3:
317
+ * console.error('[smartico] outside time window — show "available on X" message');
318
+ * break;
319
+ * case 4:
320
+ * console.error('[smartico] not owned — show unlock requirements');
321
+ * break;
322
+ * default:
323
+ * console.error('[smartico] avatar apply failed — show generic error toast:', r.err_message);
324
+ * }
325
+ * ```
108
326
  */
109
327
  public async setAvatar(props: { avatar_url: string; avatar_real_id: number }): Promise<TSetAvatarResult> {
110
328
  if (!props.avatar_url) {
@@ -12,12 +12,125 @@ import { WSAPIMissions } from './WSAPIMissions';
12
12
  /** @group Bonuses */
13
13
  export class WSAPIBonuses extends WSAPIMissions {
14
14
  /**
15
- * Returns all the bonuses for the current user
16
- * The returned bonuses are cached for 30 seconds. But you can pass the onUpdate callback as a parameter.
17
- * Note that each time you call getBonuses with a new onUpdate callback, the old one will be overwritten by the new one.
18
- * The onUpdate callback will be called on bonus claimed and the updated bonuses will be passed to it.
15
+ * Returns the bonuses awarded to the current user — both pending
16
+ * (player-claim required) and already-redeemed. Each bonus carries
17
+ * a `bonus_status_id` ({@link BonusStatus}) describing its lifecycle
18
+ * stage and an `is_redeemable` flag that signals whether the
19
+ * consumer must trigger a manual {@link claimBonus} call.
19
20
  *
20
- * **Visitor mode: not supported**
21
+ * Bonuses originate from many sources (CRM rules, mission/tournament
22
+ * rewards, store redemptions, mini-game prizes, manual operator
23
+ * awards) and all surface through this single list. The consumer
24
+ * cannot distinguish the source server-side without operator
25
+ * coordination.
26
+ *
27
+ * @remarks
28
+ * **Subscription model (`onUpdate`)**
29
+ * The callback receives the FULL refreshed bonuses list (never a
30
+ * diff/patch). Each subsequent call to `getBonuses({ onUpdate })`
31
+ * REPLACES the prior callback. Pass `onUpdate: undefined` (or omit
32
+ * it) to keep the prior callback in place; the callback is never
33
+ * auto-cleared.
34
+ *
35
+ * **Update triggers** — the callback fires after every
36
+ * {@link claimBonus} call resolves on this connection (success OR
37
+ * failure). This is the ONLY trigger.
38
+ *
39
+ * Does NOT fire when: a new bonus is awarded server-side
40
+ * (CRM rule, mission completion, store purchase, etc.), a bonus
41
+ * expires, or an operator manually issues / cancels a bonus. Those
42
+ * changes surface only on the next cache miss (after the 30 s TTL).
43
+ * Re-call `getBonuses()` manually if your UI needs near-live state
44
+ * for server-driven awards.
45
+ *
46
+ * **Reading state from the returned bonus**
47
+ * Drive UI bucketing from `bonus_status_id` (enum {@link BonusStatus}):
48
+ *
49
+ * - `COUPON_ISSUED` (2) — actionable; player must claim. Pair with
50
+ * `is_redeemable === true` to gate the Claim button.
51
+ * - `REDEEM_FAILED` (4) — also actionable; the previous claim
52
+ * attempt failed but the bonus is still valid. Surface a retry CTA
53
+ * — the default Smartico UI treats this identically to
54
+ * `COUPON_ISSUED` from the player's perspective.
55
+ * - `REDEEMED` (3) — historical; show in a "claimed" tab.
56
+ * - `New` (1), `COUPON_ISSUE_FAILED` (5), `EXPIRED` (6) — these
57
+ * should not normally reach the client and are typically filtered
58
+ * out by operator-side widget configuration; if they do appear,
59
+ * they have no player-actionable state.
60
+ *
61
+ * `is_redeemable` is the authoritative gate for showing the Claim
62
+ * button — it's `true` only when the bonus is in a claimable status
63
+ * AND the operator's integration uses a coupon model (where the
64
+ * player must explicitly trigger delivery). Auto-redeemed bonuses
65
+ * arrive already in `REDEEMED` state with `is_redeemable: false`.
66
+ *
67
+ * **Field hierarchy — display amount**
68
+ * Bonuses carry both template-level (`label_bonus_template_meta_map.description`)
69
+ * and instance-level (`bonus_meta_map.uiAmount`) display strings.
70
+ * Prefer `bonus_meta_map.uiAmount` when present — it's the dynamic
71
+ * amount computed at issuance time (e.g. from a dynamic-bonus
72
+ * formula). Fall back to `label_bonus_template_meta_map.description`
73
+ * (which can include HTML; sanitize before injecting).
74
+ *
75
+ * **Date format**
76
+ * `create_date` and `redeem_date` are ISO 8601 UTC strings WITHOUT
77
+ * a timezone suffix (`"YYYY-MM-DDTHH:MM:SS"`). Parse as UTC and
78
+ * display in the user's local timezone. `redeem_date` is absent
79
+ * until the bonus reaches `REDEEMED` status.
80
+ *
81
+ * **Cache TTL**: the SDK caches the response for 30 seconds. Cache
82
+ * is fully cleared on login / logout.
83
+ *
84
+ * **Idempotency / Side effects**: safe. Read-only.
85
+ *
86
+ * **UI guidance**: see [UI Guide — `getBonuses`](../../docs/ui/bonuses/UIGuide_getBonuses.md).
87
+ *
88
+ * **Visitor mode**: not supported.
89
+ *
90
+ * @param params Optional. Omit to fetch without subscribing.
91
+ * @param params.onUpdate Callback invoked with the full refreshed
92
+ * bonuses list after every
93
+ * {@link claimBonus} resolves. Each call
94
+ * to `getBonuses` overwrites the prior
95
+ * callback.
96
+ * @returns Promise resolving to the bonuses list.
97
+ * Empty array if no bonuses are visible.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * const bonuses = await window._smartico.api.getBonuses({
102
+ * onUpdate: (refreshed) => {
103
+ * console.log('[smartico] bonuses refreshed (after claimBonus) — re-render the bonuses UI from this array:', refreshed);
104
+ * },
105
+ * });
106
+ *
107
+ * // Bucket into pending vs redeemed tabs. The default Smartico UI groups
108
+ * // COUPON_ISSUED + REDEEM_FAILED into the same "Pending" tab.
109
+ * const pending = bonuses.filter(b =>
110
+ * b.bonus_status_id === 2 || b.bonus_status_id === 4 // COUPON_ISSUED or REDEEM_FAILED
111
+ * );
112
+ * const redeemed = bonuses.filter(b => b.bonus_status_id === 3); // REDEEMED
113
+ *
114
+ * console.log('[smartico] render bonus tabs: pending=', pending.length, 'redeemed=', redeemed.length);
115
+ *
116
+ * // Render each pending bonus card; show Claim button only when redeemable.
117
+ * for (const b of pending) {
118
+ * const amount = b.bonus_meta_map?.uiAmount || b.label_bonus_template_meta_map?.description;
119
+ * if (b.is_redeemable) {
120
+ * console.log('[smartico] render Claim button for bonus', b.bonus_id, '— amount:', amount);
121
+ * } else {
122
+ * console.log('[smartico] render bonus as informational (no Claim button) — amount:', amount);
123
+ * }
124
+ * }
125
+ *
126
+ * // Server-awarded bonuses (e.g. from a CRM campaign) do NOT push;
127
+ * // poll if you need near-live awareness.
128
+ * setInterval(async () => {
129
+ * const fresh = await window._smartico.api.getBonuses();
130
+ * const newCount = fresh.filter(b => b.bonus_status_id === 2 || b.bonus_status_id === 4).length;
131
+ * console.log('[smartico] poll tick — pending bonuses now:', newCount);
132
+ * }, 30_000);
133
+ * ```
21
134
  */
22
135
  public async getBonuses({ onUpdate }: { onUpdate?: (data: TBonus[]) => void } = {}): Promise<TBonus[]> {
23
136
  if (onUpdate) {
@@ -28,12 +141,113 @@ export class WSAPIBonuses extends WSAPIMissions {
28
141
  }
29
142
 
30
143
  /**
31
- * Claim the bonus by bonus_id. Returns the err_code in case of success or error.
32
- * Note that this method can be used only on integrations where originally failed bonus can be claimed again.
33
- * For example, user won a bonus in the mini-game, but Operator rejected this bonus.
34
- * This bonus will be available for the user to claim again.
144
+ * Triggers manual redemption of a coupon-model bonus the user has
145
+ * been awarded. For bonuses with `is_redeemable === true` returned
146
+ * by {@link getBonuses}, this is the call that asks the operator's
147
+ * integration to actually credit the bonus to the player's account.
148
+ * Bonuses on integrations that auto-redeem arrive already in
149
+ * `REDEEMED` state and do not require this call.
150
+ *
151
+ * Use this for `bonus_status_id` of `COUPON_ISSUED` (2) as the
152
+ * first-time claim, and for `REDEEM_FAILED` (4) as a retry after a
153
+ * prior unsuccessful attempt.
154
+ *
155
+ * @remarks
156
+ * **Preconditions**
157
+ * Read the candidate bonus from {@link getBonuses} and gate the
158
+ * call on `is_redeemable === true`. The SDK forwards the request
159
+ * unconditionally — calling on a non-claimable bonus returns
160
+ * `err_code = -1`.
161
+ *
162
+ * **Error codes** (in `err_code`)
163
+ *
164
+ * The SDK currently types `err_code` as {@link SAWSpinErrorCode} for
165
+ * historical reasons, but the values returned by this method come
166
+ * from the server's general error space and are NOT mini-game codes.
167
+ * Branch on the numeric values:
168
+ *
169
+ * - `0` — success; the bonus has been redeemed and the operator's
170
+ * integration has credited the player's account.
171
+ * - `-1` — bonus not claimable: not found, already claimed by
172
+ * another session, or its status is no longer `COUPON_ISSUED` /
173
+ * `REDEEM_FAILED`. Treat as idempotent — refresh
174
+ * {@link getBonuses} and reconcile.
175
+ * - `1` — generic server error. Transient; allow retry after a brief
176
+ * delay.
177
+ * - `9999` — uncaught server exception. Treat as a transient failure;
178
+ * surface a generic error and allow retry.
179
+ * - other non-zero — generic server error. Surface `err_message` if
180
+ * any.
181
+ *
182
+ * **`success` field is unreliable**: the wire response does not
183
+ * carry a `success` boolean — the field on `TClaimBonusResult` will
184
+ * be `undefined` in practice. Always branch on `err_code === 0`
185
+ * for the success check.
186
+ *
187
+ * **Refresh after success (and after failure)**
188
+ * The SDK automatically refreshes the bonuses cache on every
189
+ * response (success OR failure) and fires any `onUpdate` callback
190
+ * registered via {@link getBonuses}'s `onUpdate`. After
191
+ * `err_code === 0`, the redeemed bonus shifts from
192
+ * `COUPON_ISSUED` / `REDEEM_FAILED` to `REDEEMED` on the refreshed
193
+ * array, with `redeem_date` populated. After a failure, the bonus
194
+ * typically lands in `REDEEM_FAILED` and remains claimable for a
195
+ * retry.
196
+ *
197
+ * **Idempotency**: NOT idempotent at the SDK level. A second call
198
+ * returns `err_code = -1` once the first has succeeded — treat that
199
+ * as success in the UI rather than as a real error. Guard the call
200
+ * site against double-clicks (set a local "claiming" flag on click,
201
+ * clear it on response).
202
+ *
203
+ * **Side effects** (on `err_code === 0`)
204
+ * - Bonus status transitions to `REDEEMED`; `redeem_date` is set.
205
+ * - The operator's integration credits the player's account
206
+ * externally. The SDK does not observe that credit directly —
207
+ * balance updates flow over the user-properties channel from the
208
+ * operator's side, not from this response.
209
+ * - Server-side analytics events fire downstream (not directly
210
+ * observable from the SDK).
211
+ *
212
+ * **UI guidance**: see [UI Guide — `claimBonus`](../../docs/ui/bonuses/UIGuide_claimBonus.md).
213
+ *
214
+ * **Visitor mode**: not supported.
215
+ *
216
+ * @param bonus_id The `bonus_id` from a `TBonus` returned by
217
+ * {@link getBonuses}.
218
+ * @returns `{ err_code, err_message, success? }`; success when
219
+ * `err_code === 0` (or `err_code === -1` when treated as
220
+ * idempotent no-op). The `success` field is unreliable —
221
+ * ignore it.
222
+ *
223
+ * @example
224
+ * ```ts
225
+ * const bonuses = await window._smartico.api.getBonuses({
226
+ * onUpdate: (refreshed) => console.log('[smartico] bonuses refreshed — re-render from this array', refreshed),
227
+ * });
228
+ * const bonus = bonuses.find(b => b.bonus_id === bonusId);
229
+ *
230
+ * if (!bonus) {
231
+ * console.log('[smartico] bonus no longer visible — refresh list and hide CTA');
232
+ * return;
233
+ * }
234
+ * if (!bonus.is_redeemable) {
235
+ * console.log('[smartico] bonus is not claimable (auto-redeemed or already finalised) — keep CTA hidden');
236
+ * return;
237
+ * }
238
+ *
239
+ * console.log('[smartico] claim starting — set in-flight flag, show loading dots on the Claim button, keep the modal open');
240
+ * const r = await window._smartico.api.claimBonus(bonus.bonus_id);
241
+ * console.log('[smartico] claim response received — clear in-flight flag');
35
242
  *
36
- * **Visitor mode: not supported**
243
+ * if (r.err_code === 0 || r.err_code === -1) {
244
+ * console.log('[smartico] claim succeeded (or was already done) — show a success toast; the getBonuses onUpdate above will fire with the refreshed list');
245
+ * } else if (r.err_code === 9999) {
246
+ * console.error('[smartico] uncaught server exception — show a generic error toast and allow retry');
247
+ * } else {
248
+ * console.error('[smartico] claim failed — surface this error message to the user; the bonus will move to REDEEM_FAILED state and remain claimable for a retry:', r.err_message);
249
+ * }
250
+ * ```
37
251
  */
38
252
  public async claimBonus(bonus_id: number): Promise<TClaimBonusResult> {
39
253
  const r = await this.api.bonusClaimItem(this.userExtId, bonus_id);