@smartico/public-api 0.0.386 → 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 (35) 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/Missions/UserAchievementTask.d.ts +4 -0
  6. package/dist/SmarticoAPI.d.ts +11 -0
  7. package/dist/WSAPI/WSAPIAvatars.d.ts +103 -0
  8. package/dist/WSAPI/WSAPITypes.d.ts +6 -2
  9. package/dist/index.js +260 -78
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.modern.mjs +168 -6
  12. package/dist/index.modern.mjs.map +1 -1
  13. package/docs/SmarticoObject.md +15 -0
  14. package/docs/api/README.md +2 -0
  15. package/docs/api/classes/WSAPIAvatars.md +135 -0
  16. package/docs/api/classes/WSAPIClans.md +3 -5
  17. package/docs/api/documents/SmarticoObject.md +15 -0
  18. package/docs/api/enumerations/AvatarCustomizeErrorCode.md +21 -0
  19. package/docs/api/enumerations/JoinClanErrorCode.md +16 -17
  20. package/docs/api/interfaces/AvatarCustomizeResponse.md +31 -0
  21. package/docs/api/interfaces/TAvatarPrompt.md +2 -2
  22. package/docs/api/interfaces/TMissionOrBadgeTask.md +16 -0
  23. package/docs/api/interfaces/UserAchievementTask.md +16 -0
  24. package/docs/native/PROTOCOL.md +3 -1
  25. package/docs/ui/avatars/UIGuide_avatarsCustomize.md +69 -0
  26. package/package.json +1 -1
  27. package/src/Avatars/AvatarCustomizeErrorCode.ts +7 -5
  28. package/src/Avatars/AvatarCustomizeResponse.ts +17 -0
  29. package/src/Avatars/index.ts +1 -0
  30. package/src/Missions/UserAchievement.ts +2 -0
  31. package/src/Missions/UserAchievementTask.ts +4 -0
  32. package/src/SmarticoAPI.ts +53 -0
  33. package/src/WSAPI/WSAPIAvatars.ts +121 -0
  34. package/src/WSAPI/WSAPITypes.ts +6 -2
  35. package/tsconfig.json +3 -1
@@ -144,6 +144,7 @@ import { GetAvatarsListResponse, avatarDefinitionTransform } from './Avatars/Get
144
144
  import { GetAvatarsCustomizedResponse, avatarCustomizedTransform } from './Avatars/GetAvatarsCustomizedResponse';
145
145
  import { GetAvatarPromptsResponse, avatarPromptTransform } from './Avatars/GetAvatarPromptsResponse';
146
146
  import { SetAvatarRequest, SetAvatarResponse } from './Avatars';
147
+ import { AvatarCustomizeResponse } from './Avatars/AvatarCustomizeResponse';
147
148
  import { GetJackpotWinnersResponse, GetJackpotWinnersResponseTransform, JackpotWinnerHistory } from './Jackpots/GetJackpotWinnersResponse';
148
149
  import { GetJackpotWinnersRequest } from './Jackpots/GetJackpotWinnersRequest';
149
150
  import { GetJackpotEligibleGamesRequest } from './Jackpots/GetJackpotEligibleGamesRequest';
@@ -183,6 +184,7 @@ class SmarticoAPI {
183
184
  private gamesApiUrl: string;
184
185
  private baseRgApiParams: Record<string, string>;
185
186
  public avatarDomain: string;
187
+ private avatarOriginDomain: string;
186
188
  private envId: number;
187
189
 
188
190
  private logger: ILogger;
@@ -220,6 +222,7 @@ class SmarticoAPI {
220
222
  }
221
223
 
222
224
  this.avatarDomain = SmarticoAPI.getAvatarUrl(label_api_key || options.tracker?.label_api_key);
225
+ this.avatarOriginDomain = SmarticoAPI.getAvatarOriginUrl(label_api_key || options.tracker?.label_api_key);
223
226
 
224
227
  this.label_api_key = SmarticoAPI.getCleanLabelApiKey(label_api_key);
225
228
  }
@@ -292,6 +295,10 @@ class SmarticoAPI {
292
295
  return SmarticoAPI.replaceSmrDomainsWithCloudfront(avatarUrl);
293
296
  }
294
297
 
298
+ public static getAvatarOriginUrl(label_api_key: string): string {
299
+ return AVATAR_DOMAIN.replace('{ENV_ID}', SmarticoAPI.getEnvDnsSuffix(label_api_key));
300
+ }
301
+
295
302
  private async send<T>(message: any, expectCID?: ClassId, force_language?: string): Promise<T> {
296
303
  if (this.logCIDs.includes(message.cid)) {
297
304
  this.logger.info('REQ', message);
@@ -1438,6 +1445,31 @@ class SmarticoAPI {
1438
1445
  }
1439
1446
  }
1440
1447
 
1448
+ private async sendAvatarApi<T>({ method, body }: { method: string, body: Record<string, any> }): Promise<T> {
1449
+ if (!this.tracker) {
1450
+ throw new Error(`Avatar APIs are not available in the visitor mode`);
1451
+ }
1452
+
1453
+ const url = `${this.avatarOriginDomain}/${method}`;
1454
+
1455
+ try {
1456
+ const response = await fetch(url, {
1457
+ method: 'POST',
1458
+ headers: {
1459
+ 'Accept': 'application/json',
1460
+ 'Content-Type': 'application/json',
1461
+ },
1462
+ body: JSON.stringify(body),
1463
+ });
1464
+
1465
+ const data = await response.json();
1466
+ return SmarticoAPI.replaceSmrDomainsWithCloudfront<T>(data);
1467
+ } catch (e) {
1468
+ this.logger.error(`Failed to call avatar API: ${method}`, { url, error: e.message });
1469
+ throw new Error(`Failed to call avatar API: ${method}. ${e.message}`);
1470
+ }
1471
+ }
1472
+
1441
1473
  public async gpGetActiveRounds(saw_template_id: number): Promise<GamesApiResponse<GamePickRound[]>> {
1442
1474
  const params = {
1443
1475
  ext_game_id: saw_template_id,
@@ -1539,6 +1571,27 @@ class SmarticoAPI {
1539
1571
  return await this.send<SetAvatarResponse>(message, ClassId.CLIENT_SET_AVATAR_RESPONSE);
1540
1572
  }
1541
1573
 
1574
+ public async avatarsCustomize(params: {
1575
+ label_id: number;
1576
+ user_id: number;
1577
+ prompt_id: number;
1578
+ avatar_url: string;
1579
+ avatar_real_id: number;
1580
+ }): Promise<AvatarCustomizeResponse> {
1581
+ return this.sendAvatarApi<AvatarCustomizeResponse>({
1582
+ method: 'avatar-customize',
1583
+ body: {
1584
+ label_id: params.label_id,
1585
+ user_id: params.user_id,
1586
+ user_ext_id: this.tracker?.getExtUserId(),
1587
+ brand_key: this.brand_api_key || this.tracker?.params?.brand_key,
1588
+ prompt_id: params.prompt_id,
1589
+ avatar_url: params.avatar_url,
1590
+ avatar_real_id: params.avatar_real_id,
1591
+ },
1592
+ });
1593
+ }
1594
+
1542
1595
  public async avatarsGetListT(user_ext_id: string): Promise<TAvatarDefinition[]> {
1543
1596
  return avatarDefinitionTransform((await this.avatarsGetList(user_ext_id)).avatars ?? [], this.avatarDomain);
1544
1597
  }
@@ -10,6 +10,7 @@ import {
10
10
  onUpdateContextKey,
11
11
  } from './WSAPIBase';
12
12
  import { WSAPIMiniGames } from './WSAPIMiniGames';
13
+ import { AvatarCustomizeResponse } from '../Avatars/AvatarCustomizeResponse';
13
14
 
14
15
  /** @group Avatars */
15
16
  export class WSAPIAvatars extends WSAPIMiniGames {
@@ -342,4 +343,124 @@ export class WSAPIAvatars extends WSAPIMiniGames {
342
343
  err_message: r.errMsg,
343
344
  };
344
345
  }
346
+
347
+ /**
348
+ * Generates an AI-customized variant of a base avatar by applying an
349
+ * operator-defined style prompt, returning the CDN URL of the result.
350
+ * This is a paid, generate-only step: it does NOT change the user's
351
+ * active avatar — pass the returned `cdn_url` to {@link setAvatar} to
352
+ * activate it.
353
+ *
354
+ * @remarks
355
+ * **Preconditions**
356
+ * - Authenticated session required; not available in visitor mode (throws).
357
+ * - All five fields are mandatory — the SDK throws synchronously
358
+ * (`Error("<field> is required")`) if any is missing or zero.
359
+ * - `prompt_id` must be one of the prompts from {@link getAvatarPrompts};
360
+ * `avatar_url` / `avatar_real_id` identify the base avatar to style.
361
+ *
362
+ * **Cost**
363
+ * Each generation costs the currency the operator configured on the
364
+ * chosen prompt (points, gems, or diamonds — some prompts are free; read
365
+ * `cost_currency_type_id` / `cost_value` from the {@link getAvatarPrompts}
366
+ * entry to gate the UI before calling). The cost is charged only on
367
+ * success; if the user can't afford it the call fails with `errCode -1`
368
+ * and nothing is generated or charged.
369
+ *
370
+ * **Latency**
371
+ * Generation runs server-side AI image synthesis and is synchronous from
372
+ * the caller's side — expect several seconds (roughly 5–20 s) before the
373
+ * promise resolves. There is no SDK cache and no push/subscription; show
374
+ * a loading state for the full duration and disable the trigger to
375
+ * prevent duplicate submissions.
376
+ *
377
+ * **Result & error codes**
378
+ * On success the result has `cdn_url` set; on failure it has `errCode` /
379
+ * `errMessage` set and no `cdn_url`. Branch on `errCode` — the generic
380
+ * message is fixed text, not cause-specific:
381
+ * - `12001` (`AvatarCustomizeErrorCode.AVATAR_USER_LIMIT`) — the user hit
382
+ * their monthly per-user generation cap. Nothing is generated or charged.
383
+ * - `12002` (`AvatarCustomizeErrorCode.AVATAR_LABEL_LIMIT`) — the brand's
384
+ * shared monthly pool is exhausted. Nothing is generated or charged;
385
+ * surface a "try again later" message.
386
+ * - `-1` — generic failure: insufficient balance, an unavailable prompt,
387
+ * or a generation error. Nothing is charged. Allow the user to retry.
388
+ *
389
+ * Both monthly caps are operator-configured and reset at the start of
390
+ * each calendar month.
391
+ *
392
+ * **Side effects (on success)**
393
+ * The generated variant is persisted to the user's customization history
394
+ * and counts toward the monthly caps **whether or not** it is later
395
+ * activated — generation is not reversible. The SDK clears the
396
+ * {@link getAvatarsCustomized} cache so the next call surfaces the new
397
+ * variant. The user's active avatar is unchanged until you call
398
+ * {@link setAvatar} with the returned `cdn_url`.
399
+ *
400
+ * **Idempotency**: not idempotent — each successful call generates (and
401
+ * charges for) a new variant. Guard the call site against double-clicks.
402
+ *
403
+ * **UI guidance**: see [UI Guide — `avatarsCustomize`](../../docs/ui/avatars/UIGuide_avatarsCustomize.md).
404
+ *
405
+ * **Visitor mode**: not supported (throws).
406
+ *
407
+ * @param props.label_id Numeric Smartico label (brand) ID the user belongs to.
408
+ * @param props.user_id Numeric Smartico user ID.
409
+ * @param props.prompt_id Style-prompt ID (`prompt_id`) from {@link getAvatarPrompts}.
410
+ * @param props.avatar_url CDN URL of the base avatar to customize.
411
+ * @param props.avatar_real_id `avatar_real_id` of the base avatar.
412
+ * @returns {@link AvatarCustomizeResponse} — `cdn_url` set on success;
413
+ * `errCode` / `errMessage` set on failure.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * // label_id / user_id identify the Smartico user being customized.
418
+ * const prompts = await window._smartico.api.getAvatarPrompts();
419
+ * const prompt = prompts[0];
420
+ *
421
+ * console.log('[smartico] generating avatar — show a spinner for ~5-20s and disable the Generate button');
422
+ * const result = await window._smartico.api.avatarsCustomize({
423
+ * label_id,
424
+ * user_id,
425
+ * prompt_id: prompt.prompt_id,
426
+ * avatar_url: baseAvatar.avatar_url,
427
+ * avatar_real_id: baseAvatar.avatar_real_id,
428
+ * });
429
+ *
430
+ * if (result.cdn_url) {
431
+ * console.log('[smartico] generation succeeded — preview this URL, then call setAvatar to apply it:', result.cdn_url);
432
+ * // await window._smartico.api.setAvatar({ avatar_url: result.cdn_url, avatar_real_id: baseAvatar.avatar_real_id });
433
+ * } else if (result.errCode === 12001) {
434
+ * console.error('[smartico] user monthly limit reached — show "you have used all your custom avatars this month"');
435
+ * } else if (result.errCode === 12002) {
436
+ * console.error('[smartico] brand monthly pool exhausted — show "custom avatars are unavailable right now, try later"');
437
+ * } else {
438
+ * console.error('[smartico] generation failed (e.g. not enough balance) — let the user retry:', result.errMessage);
439
+ * }
440
+ * ```
441
+ */
442
+ public async avatarsCustomize(props: {
443
+ label_id: number;
444
+ user_id: number;
445
+ prompt_id: number;
446
+ avatar_url: string;
447
+ avatar_real_id: number;
448
+ }): Promise<AvatarCustomizeResponse> {
449
+ const required: (keyof typeof props)[] = ['label_id', 'user_id', 'prompt_id', 'avatar_url', 'avatar_real_id'];
450
+ for (const field of required) {
451
+ if (!props[field]) {
452
+ throw new Error(`${field} is required`);
453
+ }
454
+ }
455
+
456
+ const r = await this.api.avatarsCustomize(props);
457
+
458
+ // On success a new variant is persisted server-side — drop the cached
459
+ // list so the next getAvatarsCustomized() surfaces it.
460
+ if (r.cdn_url) {
461
+ OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.AvatarsCustomized);
462
+ }
463
+
464
+ return r;
465
+ }
345
466
  }
@@ -953,6 +953,10 @@ export interface TMissionOrBadgeTask {
953
953
  progress: number;
954
954
  /** Reward for completing the task in points */
955
955
  points_reward: number;
956
+ /** Reward for completing the task in gems */
957
+ gems_reward?: number;
958
+ /** Reward for completing the task in diamonds */
959
+ diamonds_reward?: number;
956
960
  /** This is the total number of times the user needs to execute to complete task. e.g. he needs to bet 100 times. Here will be 100 */
957
961
  execution_count_expected?: number;
958
962
  /** This is the number of times the user has executed 'activity' of the task. e.g. he bet 5 times out of 100. Here will be 5 */
@@ -1780,9 +1784,9 @@ export interface TAvatarPrompt {
1780
1784
  name: string;
1781
1785
  /** Absolute CDN URL of the prompt's preview icon. */
1782
1786
  icon_url: string;
1783
- /** Currency used to pay for the customization. `0` = points, `1` = gems, `2` = diamonds. */
1787
+ /** Currency used to pay for the customization. `0` = points, `1` = gems, `2` = diamonds, `3` = free. A `cost_value` of `0` is also free. */
1784
1788
  cost_currency_type_id: number;
1785
- /** Cost amount in the currency named by `cost_currency_type_id`. */
1789
+ /** Cost amount in the currency named by `cost_currency_type_id`. `0` = free. */
1786
1790
  cost_value: number;
1787
1791
  }
1788
1792
 
package/tsconfig.json CHANGED
@@ -90,7 +90,9 @@
90
90
  "src/Tournaments/GetClanTournamentPlayersResponse.ts",
91
91
  "src/Avatars/AvatarDefinition.ts",
92
92
  "src/Avatars/AvatarCustomized.ts",
93
- "src/Avatars/AvatarPrompt.ts"
93
+ "src/Avatars/AvatarPrompt.ts",
94
+ "src/Avatars/AvatarCustomizeResponse.ts",
95
+ "src/Avatars/AvatarCustomizeErrorCode.ts"
94
96
  ],
95
97
  "out": "docs/api",
96
98
  "projectDocuments": ["docs/SmarticoObject.md", "docs/Callbacks.md", "docs/Transforms.md"],