@smartico/public-api 0.0.380 → 0.0.381
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +103 -0
- package/README.md +32 -10
- package/dist/Base/ClassId.d.ts +2 -0
- package/dist/Jackpots/JackpotDetails.d.ts +14 -15
- package/dist/Jackpots/JackpotPot.d.ts +10 -6
- package/dist/Raffle/GetRaffleWonPrizesRequest.d.ts +9 -0
- package/dist/Raffle/GetRaffleWonPrizesResponse.d.ts +52 -0
- package/dist/Raffle/index.d.ts +2 -0
- package/dist/SmarticoAPI.d.ts +6 -1
- package/dist/SmarticoLib/index.d.ts +5 -1
- package/dist/WSAPI/WSAPIAvatars.d.ts +267 -49
- package/dist/WSAPI/WSAPIBonuses.d.ts +224 -10
- package/dist/WSAPI/WSAPIGamePick.d.ts +538 -253
- package/dist/WSAPI/WSAPIGeneral.d.ts +156 -14
- package/dist/WSAPI/WSAPIInbox.d.ts +547 -58
- package/dist/WSAPI/WSAPIJackpots.d.ts +292 -57
- package/dist/WSAPI/WSAPILeaderBoard.d.ts +127 -13
- package/dist/WSAPI/WSAPIMiniGames.d.ts +465 -49
- package/dist/WSAPI/WSAPIRaffles.d.ts +576 -52
- package/dist/WSAPI/WSAPITournaments.d.ts +3 -3
- package/dist/WSAPI/WSAPITypes.d.ts +243 -132
- package/dist/WSAPI/WSAPIUser.d.ts +193 -43
- package/dist/index.js +3409 -615
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +3391 -608
- package/dist/index.modern.mjs.map +1 -1
- package/docs/Callbacks.md +162 -0
- package/docs/SmarticoObject.md +445 -0
- package/docs/Transforms.md +99 -0
- package/docs/api/README.md +26 -0
- package/docs/api/classes/WSAPIAvatars.md +282 -54
- package/docs/api/classes/WSAPIBonuses.md +233 -12
- package/docs/api/classes/WSAPIClans.md +380 -10
- package/docs/api/classes/WSAPIGamePick.md +555 -26
- package/docs/api/classes/WSAPIGeneral.md +165 -16
- package/docs/api/classes/WSAPIInbox.md +588 -64
- package/docs/api/classes/WSAPIJackpots.md +320 -66
- package/docs/api/classes/WSAPILeaderBoard.md +133 -15
- package/docs/api/classes/WSAPIMiniGames.md +501 -64
- package/docs/api/classes/WSAPIMissions.md +58 -79
- package/docs/api/classes/WSAPIRaffles.md +647 -69
- package/docs/api/classes/WSAPIStore.md +83 -108
- package/docs/api/classes/WSAPITournaments.md +495 -28
- package/docs/api/classes/WSAPIUser.md +520 -83
- package/docs/api/documents/Callbacks.md +162 -0
- package/docs/api/documents/SmarticoObject.md +445 -0
- package/docs/api/documents/Transforms.md +99 -0
- package/docs/api/enumerations/BonusStatus-1.md +11 -6
- package/docs/api/enumerations/JoinClanErrorCode.md +81 -0
- package/docs/api/enumerations/TournamentRegistrationError.md +12 -0
- package/docs/api/functions/clanTournamentPlayersTransform.md +13 -0
- package/docs/api/interfaces/AvatarCustomized.md +25 -0
- package/docs/api/interfaces/AvatarDefinition.md +94 -0
- package/docs/api/interfaces/AvatarPrompt.md +45 -0
- package/docs/api/interfaces/BonusMetaMap-1.md +4 -1
- package/docs/api/interfaces/BonusTemplateMetaMap-1.md +9 -4
- package/docs/api/interfaces/Clan.md +4 -0
- package/docs/api/interfaces/ClanInfo.md +109 -0
- package/docs/api/interfaces/ClanMember.md +53 -0
- package/docs/api/interfaces/ClanTournamentPlayerRaw.md +67 -0
- package/docs/api/interfaces/GemsDiamondsLog.md +43 -0
- package/docs/api/interfaces/GetClanInfoResponse.md +61 -0
- package/docs/api/interfaces/GetClanTournamentPlayersResponse.md +81 -0
- package/docs/api/interfaces/GetRaffleWonPrizesRequest.md +59 -0
- package/docs/api/interfaces/GetRaffleWonPrizesResponse.md +95 -0
- package/docs/api/interfaces/InboxMarkMessageAction.md +10 -2
- package/docs/api/interfaces/JackpotDetails.md +14 -15
- package/docs/api/interfaces/JackpotPot.md +9 -6
- package/docs/api/interfaces/LeaderBoardDetailsT.md +14 -8
- package/docs/api/interfaces/LeaderBoardUserT.md +8 -5
- package/docs/api/interfaces/LeaderBoardsRewardsT.md +7 -0
- package/docs/api/interfaces/PointsLog.md +43 -0
- package/docs/api/interfaces/RaffleWonPrize.md +59 -0
- package/docs/api/interfaces/RaffleWonPrizePublicMeta.md +27 -0
- package/docs/api/interfaces/RaffleWonPrizeUser.md +43 -0
- package/docs/api/interfaces/TAchCategory.md +2 -7
- package/docs/api/interfaces/TAvatarCustomized.md +4 -4
- package/docs/api/interfaces/TAvatarDefinition.md +13 -14
- package/docs/api/interfaces/TAvatarPrompt.md +6 -6
- package/docs/api/interfaces/TBonus.md +16 -8
- package/docs/api/interfaces/TBuyStoreItemResult.md +4 -29
- package/docs/api/interfaces/TClaimBonusResult.md +5 -5
- package/docs/api/interfaces/TClan.md +8 -4
- package/docs/api/interfaces/TClanInfo.md +47 -0
- package/docs/api/interfaces/TClanJoinResult.md +11 -1
- package/docs/api/interfaces/TClanTournamentPlayer.md +55 -0
- package/docs/api/interfaces/TClanTournamentPlayersResult.md +27 -0
- package/docs/api/interfaces/TClans.md +3 -1
- package/docs/api/interfaces/TGetTranslations.md +4 -0
- package/docs/api/interfaces/TInboxMessage.md +14 -6
- package/docs/api/interfaces/TInboxMessageBody.md +18 -12
- package/docs/api/interfaces/TLevel.md +17 -20
- package/docs/api/interfaces/TLevelCurrent.md +19 -18
- package/docs/api/interfaces/TMiniGamePlayBatchResult.md +14 -6
- package/docs/api/interfaces/TMiniGamePlayResult.md +9 -4
- package/docs/api/interfaces/TMissionClaimRewardResult.md +1 -9
- package/docs/api/interfaces/TMissionOptInResult.md +1 -5
- package/docs/api/interfaces/TMissionOrBadge.md +4 -7
- package/docs/api/interfaces/TRaffleOptinResponse.md +4 -2
- package/docs/api/interfaces/TSegmentCheckResult.md +10 -0
- package/docs/api/interfaces/TSetAvatarResult.md +3 -3
- package/docs/api/interfaces/TStoreItem.md +3 -13
- package/docs/api/interfaces/TTournament.md +1 -1
- package/docs/api/interfaces/TTournamentDetailed.md +1 -1
- package/docs/api/interfaces/TTournamentRegistrationResult.md +4 -2
- package/docs/api/interfaces/TUICustomSection.md +23 -19
- package/docs/api/interfaces/TUserProfile.md +18 -16
- package/docs/api/interfaces/TransformedRaffleClaimPrizeResponse.md +6 -2
- package/docs/api/interfaces/UserLevelExtraCountersT.md +9 -2
- package/docs/api/type-aliases/ActivityLogEntry.md +3 -0
- package/docs/native/ADDING_METHODS.md +7 -2
- package/docs/native/PROTOCOL.md +337 -0
- package/docs/ui/avatars/UIGuide_getAvatarPrompts.md +100 -0
- package/docs/ui/avatars/UIGuide_getAvatarsCustomized.md +90 -0
- package/docs/ui/avatars/UIGuide_getAvatarsList.md +105 -0
- package/docs/ui/avatars/UIGuide_setAvatar.md +118 -0
- package/docs/ui/bonuses/UIGuide_claimBonus.md +144 -0
- package/docs/ui/bonuses/UIGuide_getBonuses.md +176 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetActiveRound.md +99 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetActiveRounds.md +76 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetBoard.md +81 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetGameInfo.md +78 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetHistory.md +55 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetRoundInfoForUser.md +71 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetUserInfo.md +64 -0
- package/docs/ui/gamepick/UIGuide_gamePickSubmitSelection.md +103 -0
- package/docs/ui/gamepick/UIGuide_gamePickSubmitSelectionQuiz.md +67 -0
- package/docs/ui/general/UIGuide_getCustomSections.md +137 -0
- package/docs/ui/general/UIGuide_getRelatedItemsForGame.md +140 -0
- package/docs/ui/inbox/UIGuide_deleteInboxMessage.md +135 -0
- package/docs/ui/inbox/UIGuide_getInboxMessageBody.md +133 -0
- package/docs/ui/inbox/UIGuide_getInboxMessages.md +186 -0
- package/docs/ui/inbox/UIGuide_markInboxMessageAsRead.md +122 -0
- package/docs/ui/inbox/UIGuide_markUnmarkInboxMessageAsFavorite.md +84 -0
- package/docs/ui/jackpots/UIGuide_getJackpotEligibleGames.md +73 -0
- package/docs/ui/jackpots/UIGuide_getJackpotWinners.md +83 -0
- package/docs/ui/jackpots/UIGuide_jackpotGet.md +138 -0
- package/docs/ui/jackpots/UIGuide_jackpotOptIn.md +85 -0
- package/docs/ui/jackpots/UIGuide_jackpotOptOut.md +65 -0
- package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +166 -0
- package/docs/ui/minigames/UIGuide_getMiniGames.md +153 -0
- package/docs/ui/minigames/UIGuide_getMiniGamesHistory.md +90 -0
- package/docs/ui/minigames/UIGuide_playMiniGame.md +150 -0
- package/docs/ui/minigames/UIGuide_playMiniGameBatch.md +128 -0
- package/docs/ui/raffles/UIGuide_claimRafflePrize.md +99 -0
- package/docs/ui/raffles/UIGuide_getRaffleDrawRun.md +117 -0
- package/docs/ui/raffles/UIGuide_getRaffleDrawRunsHistory.md +92 -0
- package/docs/ui/raffles/UIGuide_getRaffleWonPrizes.md +120 -0
- package/docs/ui/raffles/UIGuide_getRaffles.md +175 -0
- package/docs/ui/raffles/UIGuide_requestRaffleOptin.md +114 -0
- package/docs/ui/user/UIGuide_getActivityLog.md +130 -0
- package/docs/ui/user/UIGuide_getLevels.md +47 -42
- package/package.json +1 -1
- package/src/Base/ClassId.ts +2 -0
- package/src/Jackpots/JackpotDetails.ts +14 -15
- package/src/Jackpots/JackpotPot.ts +10 -6
- package/src/Raffle/GetRaffleWonPrizesRequest.ts +12 -0
- package/src/Raffle/GetRaffleWonPrizesResponse.ts +56 -0
- package/src/Raffle/index.ts +3 -1
- package/src/SmarticoAPI.ts +14 -1
- package/src/SmarticoLib/index.ts +4 -0
- package/src/WSAPI/WSAPIAvatars.ts +267 -49
- package/src/WSAPI/WSAPIBonuses.ts +224 -10
- package/src/WSAPI/WSAPIGamePick.ts +538 -253
- package/src/WSAPI/WSAPIGeneral.ts +156 -14
- package/src/WSAPI/WSAPIInbox.ts +545 -56
- package/src/WSAPI/WSAPIJackpots.ts +297 -61
- package/src/WSAPI/WSAPILeaderBoard.ts +127 -13
- package/src/WSAPI/WSAPIMiniGames.ts +465 -49
- package/src/WSAPI/WSAPIRaffles.ts +592 -64
- package/src/WSAPI/WSAPITournaments.ts +3 -3
- package/src/WSAPI/WSAPITypes.ts +243 -132
- package/src/WSAPI/WSAPIUser.ts +193 -43
- package/tsconfig.json +9 -1
|
@@ -14,19 +14,63 @@ import { WSAPIMiniGames } from './WSAPIMiniGames';
|
|
|
14
14
|
/** @group Avatars */
|
|
15
15
|
export class WSAPIAvatars extends WSAPIMiniGames {
|
|
16
16
|
/**
|
|
17
|
-
* Returns the
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
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
|
|
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
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
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
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
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
|
-
*
|
|
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
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
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
|
-
*
|
|
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);
|