@smartico/public-api 0.0.351 → 0.0.353

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.
@@ -40,6 +40,15 @@ import {
40
40
  TActivityLog,
41
41
  TRaffleOptinResponse,
42
42
  } from './WSAPITypes';
43
+ import {
44
+ GamesApiResponse,
45
+ GamePickRound,
46
+ GamePickRoundBoard,
47
+ GamePickUserInfo,
48
+ GamePickGameInfo,
49
+ GamePickRequestParams,
50
+ GamePickRoundRequestParams,
51
+ } from '../GamePick';
43
52
  import { LeaderBoardPeriodType } from '../Leaderboard';
44
53
  import {
45
54
  JackpotDetails,
@@ -102,9 +111,11 @@ enum onUpdateContextKey {
102
111
  export class WSAPI {
103
112
  private onUpdateCallback: Map<onUpdateContextKey, (data: any) => void> = new Map();
104
113
  private jackpotGetSignature: string = '';
114
+ private userExtId: string = null;
105
115
 
106
116
  /** @private */
107
- constructor(private api: SmarticoAPI) {
117
+ constructor(private api: SmarticoAPI, userExtId: string = null) {
118
+ this.userExtId = userExtId;
108
119
  OCache.clearAll();
109
120
  if (this.api.tracker) {
110
121
  const on = this.api.tracker.on;
@@ -193,7 +204,7 @@ export class WSAPI {
193
204
  * **Visitor mode: not supported**
194
205
  */
195
206
  public async checkSegmentMatch(segment_id: number): Promise<boolean> {
196
- const r = await this.api.coreCheckSegments(null, [segment_id]);
207
+ const r = await this.api.coreCheckSegments(this.userExtId, [segment_id]);
197
208
  if (r && r.find((s) => s.segment_id === segment_id && s.is_matching)) {
198
209
  return true;
199
210
  } else {
@@ -211,7 +222,7 @@ export class WSAPI {
211
222
  * **Visitor mode: not supported**
212
223
  */
213
224
  public async checkSegmentListMatch(segment_ids: number[]): Promise<TSegmentCheckResult[]> {
214
- return await this.api.coreCheckSegments(null, Array.isArray(segment_ids) ? segment_ids : [segment_ids]);
225
+ return await this.api.coreCheckSegments(this.userExtId, Array.isArray(segment_ids) ? segment_ids : [segment_ids]);
215
226
  }
216
227
 
217
228
  /** Returns all the levels available the current user
@@ -230,7 +241,7 @@ export class WSAPI {
230
241
  * ```
231
242
  */
232
243
  public async getLevels(): Promise<TLevel[]> {
233
- return OCache.use(onUpdateContextKey.Levels, ECacheContext.WSAPI, () => this.api.levelsGetT(null), CACHE_DATA_SEC);
244
+ return OCache.use(onUpdateContextKey.Levels, ECacheContext.WSAPI, () => this.api.levelsGetT(this.userExtId), CACHE_DATA_SEC);
234
245
  }
235
246
 
236
247
  /**
@@ -246,7 +257,7 @@ export class WSAPI {
246
257
  * **Visitor mode: not supported**
247
258
  */
248
259
  public async getCurrentLevel(): Promise<TLevelCurrent> {
249
- return OCache.use(onUpdateContextKey.CurrentLevel, ECacheContext.WSAPI, () => this.api.getLevelCurrent(null), CACHE_DATA_SEC);
260
+ return OCache.use(onUpdateContextKey.CurrentLevel, ECacheContext.WSAPI, () => this.api.getLevelCurrent(this.userExtId), CACHE_DATA_SEC);
250
261
  }
251
262
 
252
263
  /** Returns all the missions configured for the current user (server-side scoped, not filtered by Widget visibility).
@@ -276,7 +287,7 @@ export class WSAPI {
276
287
  return OCache.use(
277
288
  onUpdateContextKey.Missions,
278
289
  ECacheContext.WSAPI,
279
- () => this.api.missionsGetItemsT(null),
290
+ () => this.api.missionsGetItemsT(this.userExtId),
280
291
  CACHE_DATA_SEC,
281
292
  );
282
293
  }
@@ -287,7 +298,7 @@ export class WSAPI {
287
298
  * **Visitor mode: not supported**
288
299
  */
289
300
  public async getBadges(): Promise<TMissionOrBadge[]> {
290
- return OCache.use(onUpdateContextKey.Badges, ECacheContext.WSAPI, () => this.api.badgetsGetItemsT(null), CACHE_DATA_SEC);
301
+ return OCache.use(onUpdateContextKey.Badges, ECacheContext.WSAPI, () => this.api.badgetsGetItemsT(this.userExtId), CACHE_DATA_SEC);
291
302
  }
292
303
 
293
304
  /**
@@ -303,7 +314,7 @@ export class WSAPI {
303
314
  this.onUpdateCallback.set(onUpdateContextKey.Bonuses, onUpdate);
304
315
  }
305
316
 
306
- return OCache.use(onUpdateContextKey.Bonuses, ECacheContext.WSAPI, () => this.api.bonusesGetItemsT(null), CACHE_DATA_SEC);
317
+ return OCache.use(onUpdateContextKey.Bonuses, ECacheContext.WSAPI, () => this.api.bonusesGetItemsT(this.userExtId), CACHE_DATA_SEC);
307
318
  }
308
319
 
309
320
  /**
@@ -315,7 +326,7 @@ export class WSAPI {
315
326
  * **Visitor mode: not supported**
316
327
  */
317
328
  public async claimBonus(bonus_id: number): Promise<TClaimBonusResult> {
318
- const r = await this.api.bonusClaimItem(null, bonus_id);
329
+ const r = await this.api.bonusClaimItem(this.userExtId, bonus_id);
319
330
 
320
331
  const o: TClaimBonusResult = {
321
332
  err_code: r.errCode,
@@ -344,7 +355,7 @@ export class WSAPI {
344
355
  return OCache.use(
345
356
  onUpdateContextKey.LevelExtraCounters,
346
357
  ECacheContext.WSAPI,
347
- () => this.api.getUserGamificationInfoT(null),
358
+ () => this.api.getUserGamificationInfoT(this.userExtId),
348
359
  CACHE_DATA_SEC,
349
360
  );
350
361
  }
@@ -380,7 +391,7 @@ export class WSAPI {
380
391
  return OCache.use(
381
392
  onUpdateContextKey.StoreItems,
382
393
  ECacheContext.WSAPI,
383
- () => this.api.storeGetItemsT(null),
394
+ () => this.api.storeGetItemsT(this.userExtId),
384
395
  CACHE_DATA_SEC,
385
396
  );
386
397
  }
@@ -396,7 +407,7 @@ export class WSAPI {
396
407
  * **Visitor mode: not supported**
397
408
  */
398
409
  public async buyStoreItem(item_id: number): Promise<TBuyStoreItemResult> {
399
- const r = await this.api.buyStoreItem(null, item_id);
410
+ const r = await this.api.buyStoreItem(this.userExtId, item_id);
400
411
 
401
412
  const o: TBuyStoreItemResult = {
402
413
  err_code: r.errCode,
@@ -428,7 +439,7 @@ export class WSAPI {
428
439
  return OCache.use(
429
440
  onUpdateContextKey.StoreCategories,
430
441
  ECacheContext.WSAPI,
431
- () => this.api.storeGetCategoriesT(null),
442
+ () => this.api.storeGetCategoriesT(this.userExtId),
432
443
  CACHE_DATA_SEC,
433
444
  );
434
445
  }
@@ -462,7 +473,7 @@ export class WSAPI {
462
473
  return OCache.use(
463
474
  onUpdateContextKey.StoreHistory,
464
475
  ECacheContext.WSAPI,
465
- () => this.api.storeGetPurchasedItemsT(null, limit, offset),
476
+ () => this.api.storeGetPurchasedItemsT(this.userExtId, limit, offset),
466
477
  CACHE_DATA_SEC,
467
478
  );
468
479
  }
@@ -489,7 +500,7 @@ export class WSAPI {
489
500
  return OCache.use(
490
501
  onUpdateContextKey.AchCategories,
491
502
  ECacheContext.WSAPI,
492
- () => this.api.achGetCategoriesT(null),
503
+ () => this.api.achGetCategoriesT(this.userExtId),
493
504
  CACHE_DATA_SEC,
494
505
  );
495
506
  }
@@ -516,7 +527,7 @@ export class WSAPI {
516
527
  return OCache.use(
517
528
  onUpdateContextKey.CustomSections,
518
529
  ECacheContext.WSAPI,
519
- () => this.api.customSectionsGetT(null),
530
+ () => this.api.customSectionsGetT(this.userExtId),
520
531
  CACHE_DATA_SEC,
521
532
  );
522
533
  }
@@ -548,7 +559,7 @@ export class WSAPI {
548
559
  this.onUpdateCallback.set(onUpdateContextKey.Saw, onUpdate);
549
560
  }
550
561
 
551
- return OCache.use(onUpdateContextKey.Saw, ECacheContext.WSAPI, () => this.api.sawGetTemplatesT(null), CACHE_DATA_SEC);
562
+ return OCache.use(onUpdateContextKey.Saw, ECacheContext.WSAPI, () => this.api.sawGetTemplatesT(this.userExtId), CACHE_DATA_SEC);
552
563
  }
553
564
 
554
565
  /**
@@ -579,7 +590,7 @@ export class WSAPI {
579
590
  return OCache.use(
580
591
  onUpdateContextKey.SAWHistory,
581
592
  ECacheContext.WSAPI,
582
- () => this.api.getSawWinningHistoryT(null, limit, offset, saw_template_id),
593
+ () => this.api.getSawWinningHistoryT(this.userExtId, limit, offset, saw_template_id),
583
594
  CACHE_DATA_SEC,
584
595
  );
585
596
  }
@@ -606,8 +617,8 @@ export class WSAPI {
606
617
  this.onUpdateCallback.set(onUpdateContextKey.Saw, onUpdate);
607
618
  }
608
619
 
609
- const r = await this.api.sawSpinRequest(null, template_id);
610
- this.api.doAcknowledgeRequest(null, r.request_id);
620
+ const r = await this.api.sawSpinRequest(this.userExtId, template_id);
621
+ this.api.doAcknowledgeRequest(this.userExtId, r.request_id);
611
622
 
612
623
  const o: TMiniGamePlayResult = {
613
624
  err_code: r.errCode,
@@ -628,7 +639,7 @@ export class WSAPI {
628
639
  * ```
629
640
  */
630
641
  public async miniGameWinAcknowledgeRequest(request_id: string) {
631
- return this.api.doAcknowledgeRequest(null, request_id);
642
+ return this.api.doAcknowledgeRequest(this.userExtId, request_id);
632
643
  }
633
644
 
634
645
  /**
@@ -653,10 +664,10 @@ export class WSAPI {
653
664
  this.onUpdateCallback.set(onUpdateContextKey.Saw, onUpdate);
654
665
  }
655
666
 
656
- const response = await this.api.sawSpinBatchRequest(null, template_id, spin_count);
667
+ const response = await this.api.sawSpinBatchRequest(this.userExtId, template_id, spin_count);
657
668
 
658
669
  const request_ids = response.results.map((result) => result.request_id);
659
- this.api.doAcknowledgeBatchRequest(null, request_ids);
670
+ this.api.doAcknowledgeBatchRequest(this.userExtId, request_ids);
660
671
 
661
672
  const o: TMiniGamePlayBatchResult[] = response.results.map((result) => ({
662
673
  errCode: result.errCode,
@@ -675,7 +686,7 @@ export class WSAPI {
675
686
  * **Visitor mode: not supported**
676
687
  */
677
688
  public async requestMissionOptIn(mission_id: number): Promise<TMissionOptInResult> {
678
- const r = await this.api.missionOptIn(null, mission_id);
689
+ const r = await this.api.missionOptIn(this.userExtId, mission_id);
679
690
 
680
691
  const o: TMissionOptInResult = {
681
692
  err_code: r.errCode,
@@ -691,7 +702,7 @@ export class WSAPI {
691
702
  * **Visitor mode: not supported**
692
703
  */
693
704
  public async requestMissionClaimReward(mission_id: number, ach_completed_id: number): Promise<TMissionClaimRewardResult> {
694
- const r = await this.api.missionClaimPrize(null, mission_id, ach_completed_id);
705
+ const r = await this.api.missionClaimPrize(this.userExtId, mission_id, ach_completed_id);
695
706
 
696
707
  const o: TMissionClaimRewardResult = {
697
708
  err_code: r.errCode,
@@ -727,7 +738,7 @@ export class WSAPI {
727
738
  return OCache.use(
728
739
  onUpdateContextKey.TournamentList,
729
740
  ECacheContext.WSAPI,
730
- () => this.api.tournamentsGetLobbyT(null),
741
+ () => this.api.tournamentsGetLobbyT(this.userExtId),
731
742
  CACHE_DATA_SEC,
732
743
  );
733
744
  }
@@ -758,7 +769,7 @@ export class WSAPI {
758
769
  * ```
759
770
  */
760
771
  public async getTournamentInstanceInfo(tournamentInstanceId: number): Promise<TTournamentDetailed> {
761
- return this.api.tournamentsGetInfoT(null, tournamentInstanceId);
772
+ return this.api.tournamentsGetInfoT(this.userExtId, tournamentInstanceId);
762
773
  }
763
774
 
764
775
  /**
@@ -767,7 +778,7 @@ export class WSAPI {
767
778
  * **Visitor mode: not supported**
768
779
  */
769
780
  public async registerInTournament(tournamentInstanceId: number): Promise<TTournamentRegistrationResult> {
770
- const r = await this.api.registerInTournament(null, tournamentInstanceId);
781
+ const r = await this.api.registerInTournament(this.userExtId, tournamentInstanceId);
771
782
 
772
783
  const o: TTournamentRegistrationResult = {
773
784
  err_code: r.errCode,
@@ -799,7 +810,7 @@ export class WSAPI {
799
810
  return OCache.use(
800
811
  onUpdateContextKey.LeaderBoards,
801
812
  ECacheContext.WSAPI,
802
- () => this.api.leaderboardsGetT(null, periodType, getPreviousPeriod),
813
+ () => this.api.leaderboardsGetT(this.userExtId, periodType, getPreviousPeriod),
803
814
  CACHE_DATA_SEC,
804
815
  );
805
816
  }
@@ -836,7 +847,7 @@ export class WSAPI {
836
847
  if (onUpdate) {
837
848
  this.onUpdateCallback.set(onUpdateContextKey.InboxMessages, onUpdate);
838
849
  }
839
- return await this.api.getInboxMessagesT(null, from, to, onlyFavorite, categoryId, read_status);
850
+ return await this.api.getInboxMessagesT(this.userExtId, from, to, onlyFavorite, categoryId, read_status);
840
851
  }
841
852
 
842
853
  /**
@@ -852,7 +863,7 @@ export class WSAPI {
852
863
  return OCache.use(
853
864
  onUpdateContextKey.InboxUnreadCount,
854
865
  ECacheContext.WSAPI,
855
- () => this.api.getInboxUnreadCountT(null),
866
+ () => this.api.getInboxUnreadCountT(this.userExtId),
856
867
  CACHE_DATA_SEC,
857
868
  );
858
869
  }
@@ -872,7 +883,7 @@ export class WSAPI {
872
883
  * **Visitor mode: not supported**
873
884
  */
874
885
  public async markInboxMessageAsRead(messageGuid: string): Promise<InboxMarkMessageAction> {
875
- const r = await this.api.markInboxMessageRead(null, messageGuid);
886
+ const r = await this.api.markInboxMessageRead(this.userExtId, messageGuid);
876
887
 
877
888
  return {
878
889
  err_code: r.errCode,
@@ -886,7 +897,7 @@ export class WSAPI {
886
897
  * **Visitor mode: not supported**
887
898
  */
888
899
  public async markAllInboxMessagesAsRead(): Promise<InboxMarkMessageAction> {
889
- const r = await this.api.markAllInboxMessageRead(null);
900
+ const r = await this.api.markAllInboxMessageRead(this.userExtId);
890
901
 
891
902
  return {
892
903
  err_code: r.errCode,
@@ -900,7 +911,7 @@ export class WSAPI {
900
911
  * **Visitor mode: not supported**
901
912
  */
902
913
  public async markUnmarkInboxMessageAsFavorite(messageGuid: string, mark: boolean): Promise<InboxMarkMessageAction> {
903
- const r = await this.api.markUnmarkInboxMessageAsFavorite(null, messageGuid, mark);
914
+ const r = await this.api.markUnmarkInboxMessageAsFavorite(this.userExtId, messageGuid, mark);
904
915
 
905
916
  return {
906
917
  err_code: r.errCode,
@@ -915,7 +926,7 @@ export class WSAPI {
915
926
  */
916
927
 
917
928
  public async deleteInboxMessage(messageGuid: string): Promise<InboxMarkMessageAction> {
918
- const r = await this.api.deleteInboxMessage(null, messageGuid);
929
+ const r = await this.api.deleteInboxMessage(this.userExtId, messageGuid);
919
930
 
920
931
  return {
921
932
  err_code: r.errCode,
@@ -930,7 +941,7 @@ export class WSAPI {
930
941
  */
931
942
 
932
943
  public async deleteAllInboxMessages(): Promise<InboxMarkMessageAction> {
933
- const r = await this.api.deleteAllInboxMessages(null);
944
+ const r = await this.api.deleteAllInboxMessages(this.userExtId);
934
945
 
935
946
  return {
936
947
  err_code: r.errCode,
@@ -942,7 +953,7 @@ export class WSAPI {
942
953
  * Requests translations for the given language. Returns the object including translation key/translation value pairs. All possible translation keys defined in the back office.
943
954
  */
944
955
  public async getTranslations(lang_code: string): Promise<TGetTranslations> {
945
- const r = await this.api.getTranslationsT(null, lang_code, []);
956
+ const r = await this.api.getTranslationsT(this.userExtId, lang_code, []);
946
957
 
947
958
  return {
948
959
  translations: r.translations,
@@ -974,7 +985,7 @@ export class WSAPI {
974
985
  engagement_uid: string;
975
986
  activityType: ActivityTypeLimited | number;
976
987
  }): void {
977
- this.api.reportEngagementImpression(null, engagement_uid, activityType);
988
+ this.api.reportEngagementImpression(this.userExtId, engagement_uid, activityType);
978
989
  }
979
990
 
980
991
  /**
@@ -1007,7 +1018,7 @@ export class WSAPI {
1007
1018
  activityType: ActivityTypeLimited | number;
1008
1019
  action?: string;
1009
1020
  }): void {
1010
- this.api.reportEngagementAction(null, engagement_uid, activityType, action);
1021
+ this.api.reportEngagementAction(this.userExtId, engagement_uid, activityType, action);
1011
1022
  }
1012
1023
 
1013
1024
  /**
@@ -1062,16 +1073,419 @@ export class WSAPI {
1062
1073
  return await OCache.use(
1063
1074
  onUpdateContextKey.ActivityLog,
1064
1075
  ECacheContext.WSAPI,
1065
- () => this.api.getActivityLogT(null, startTimeSeconds, endTimeSeconds, from, to),
1076
+ () => this.api.getActivityLogT(this.userExtId, startTimeSeconds, endTimeSeconds, from, to),
1066
1077
  CACHE_DATA_SEC,
1067
1078
  );
1068
1079
  }
1069
1080
 
1081
+ /**
1082
+ * Returns the active rounds for the specified MatchX or Quiz game.
1083
+ * Each round includes its events (matches/questions) along with the current user's selections and scores.
1084
+ *
1085
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1086
+ *
1087
+ * **Response** `GamesApiResponse<GamePickRound[]>`:
1088
+ * - `errCode` - 0 on success
1089
+ * - `data` - Array of rounds, each containing:
1090
+ * - `round_id`, `round_name` - Round identifier and display name
1091
+ * - `open_date`, `last_bet_date` - Timestamps (ms) for round open and betting deadline
1092
+ * - `is_active_now`, `is_resolved` - Round state flags
1093
+ * - `round_status_id` - Round status: -1 (active), 2 (no more bets), 3 (all events resolved), 4 (round resolved)
1094
+ * - `score_full_win`, `score_part_win`, `score_lost` - Scoring rules per prediction outcome
1095
+ * - `user_score` - Current user's total score in this round
1096
+ * - `user_placed_bet` - Whether the user has submitted predictions
1097
+ * - `has_open_for_bet_events` - Whether there are events still open for betting
1098
+ * - `events[]` - Array of events with `gp_event_id`, `market_type_id`, `event_meta` (team names, images, sport), `match_date`, `is_open_for_bets`, `odds_details`, and user selection fields
1099
+ *
1100
+ * **Example**:
1101
+ * ```
1102
+ * _smartico.api.getGamePickActiveRounds({
1103
+ * saw_template_id: 1083,
1104
+ * }).then((result) => {
1105
+ * console.log(result.data); // GamePickRound[]
1106
+ * result.data.forEach(round => {
1107
+ * console.log(round.round_name, round.events.length);
1108
+ * });
1109
+ * });
1110
+ * ```
1111
+ *
1112
+ * **Visitor mode: not supported**
1113
+ */
1114
+ public async getGamePickActiveRounds(props: GamePickRequestParams): Promise<GamesApiResponse<GamePickRound[]>> {
1115
+ if (!props.saw_template_id) {
1116
+ throw new Error('saw_template_id is required');
1117
+ }
1118
+ return this.api.gpGetActiveRounds(props.saw_template_id);
1119
+ }
1120
+
1121
+ /**
1122
+ * Returns a single active round for the specified MatchX or Quiz game.
1123
+ * The round includes full event details with the current user's selections.
1124
+ *
1125
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1126
+ * @param props.round_id - The specific round to retrieve
1127
+ *
1128
+ * **Response** `GamesApiResponse<GamePickRound>`:
1129
+ * - `errCode` - 0 on success
1130
+ * - `data` - Single round object with the same structure as in `getGamePickActiveRounds`,
1131
+ * including `events[]` with full event details, user selections, and resolution info
1132
+ *
1133
+ * **Example**:
1134
+ * ```
1135
+ * _smartico.api.getGamePickActiveRound({
1136
+ * saw_template_id: 1083,
1137
+ * round_id: 31652,
1138
+ * }).then((result) => {
1139
+ * console.log(result.data.round_name, result.data.events.length);
1140
+ * console.log(result.data.user_score, result.data.user_placed_bet);
1141
+ * });
1142
+ * ```
1143
+ *
1144
+ * **Visitor mode: not supported**
1145
+ */
1146
+ public async getGamePickActiveRound(props: GamePickRoundRequestParams): Promise<GamesApiResponse<GamePickRound>> {
1147
+ if (!props.saw_template_id) {
1148
+ throw new Error('saw_template_id is required');
1149
+ }
1150
+ if (!props.round_id) {
1151
+ throw new Error('round_id is required');
1152
+ }
1153
+ return this.api.gpGetActiveRound(props.saw_template_id, props.round_id);
1154
+ }
1155
+
1156
+ /**
1157
+ * Returns the history of all rounds (including resolved ones) for the specified MatchX or Quiz game.
1158
+ * Each round contains full event details with results and the current user's predictions.
1159
+ *
1160
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1161
+ *
1162
+ * **Response** `GamesApiResponse<GamePickRound[]>`:
1163
+ * - `errCode` - 0 on success
1164
+ * - `data` - Array of rounds ordered by `round_row_id` descending (newest first).
1165
+ * Each round has the same structure as in `getGamePickActiveRounds`, including resolved events
1166
+ * with `resolution_type_id` (0=None, 2=Lost, 3=PartialWin, 4=FullWin) and `resolution_score`
1167
+ *
1168
+ * **Example**:
1169
+ * ```
1170
+ * _smartico.api.getGamePickHistory({
1171
+ * saw_template_id: 1083,
1172
+ * }).then((result) => {
1173
+ * result.data.forEach(round => {
1174
+ * console.log(round.round_name, 'Score:', round.user_score, 'Resolved:', round.is_resolved);
1175
+ * });
1176
+ * });
1177
+ * ```
1178
+ *
1179
+ * **Visitor mode: not supported**
1180
+ */
1181
+ public async getGamePickHistory(props: GamePickRequestParams): Promise<GamesApiResponse<GamePickRound[]>> {
1182
+ if (!props.saw_template_id) {
1183
+ throw new Error('saw_template_id is required');
1184
+ }
1185
+ return this.api.gpGetGamesHistory(props.saw_template_id);
1186
+ }
1187
+
1188
+ /**
1189
+ * Returns the leaderboard for a specific round within a MatchX or Quiz game.
1190
+ * Use `round_id = -1` (AllRoundsGameBoardID) to get the season/overall leaderboard across all rounds.
1191
+ *
1192
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1193
+ * @param props.round_id - The round to get the leaderboard for. Use -1 for overall/seasonal leaderboard
1194
+ *
1195
+ * **Response** `GamesApiResponse<GamePickRoundBoard>`:
1196
+ * - `errCode` - 0 on success
1197
+ * - `data` - Leaderboard object containing:
1198
+ * - Round base fields (`round_id`, `round_name`, `open_date`, `last_bet_date`, etc.)
1199
+ * - `users[]` - Ranked list of players, each with:
1200
+ * - `ext_user_id`, `int_user_id` - User identifiers
1201
+ * - `public_username`, `avatar_url` - Display info (usernames may be masked based on label settings)
1202
+ * - `gp_position` - Leaderboard rank (null if not yet ranked)
1203
+ * - `resolution_score` - Total score in this round
1204
+ * - `full_wins_count`, `part_wins_count`, `lost_count` - Prediction outcome counts
1205
+ * - `my_user` - Current user's entry (same fields as above), or null if user hasn't participated
1206
+ *
1207
+ * **Example**:
1208
+ * ```
1209
+ * _smartico.api.getGamePickBoard({
1210
+ * saw_template_id: 1083,
1211
+ * round_id: 31652,
1212
+ * }).then((result) => {
1213
+ * console.log('Top players:', result.data.users);
1214
+ * console.log('My position:', result.data.my_user?.gp_position);
1215
+ * });
1216
+ * ```
1217
+ *
1218
+ * **Visitor mode: not supported**
1219
+ */
1220
+ public async getGamePickBoard(props: GamePickRoundRequestParams): Promise<GamesApiResponse<GamePickRoundBoard>> {
1221
+ if (!props.saw_template_id) {
1222
+ throw new Error('saw_template_id is required');
1223
+ }
1224
+ if (!props.round_id) {
1225
+ throw new Error('round_id is required');
1226
+ }
1227
+ return this.api.gpGetGameBoard(props.saw_template_id, props.round_id);
1228
+ }
1229
+
1230
+ /**
1231
+ * Submits score predictions for a round in a MatchX game.
1232
+ * Sends the round object with user selections for all events at once.
1233
+ * Each event must include `team1_user_selection` and `team2_user_selection` representing predicted scores.
1234
+ * If the user hasn't placed bets before, one game attempt (spin) will be consumed.
1235
+ * Predictions can be edited until each match starts (if `allow_edit_answers` is enabled on the round).
1236
+ *
1237
+ * @param props.saw_template_id - The ID of the MatchX game template
1238
+ * @param props.round - Round object containing `round_id` and `events[]`. Typically obtained from `getGamePickActiveRound`
1239
+ * and modified with user predictions. Each event needs: `gp_event_id`, `team1_user_selection`, `team2_user_selection`
1240
+ *
1241
+ * **Response** `GamesApiResponse<GamePickRound>`:
1242
+ * - `errCode` - 0 on success. Non-zero codes indicate errors (e.g. not enough points/attempts)
1243
+ * - `data` - Updated round with all events reflecting the submitted selections.
1244
+ * `user_placed_bet` will be `true`, `has_not_submitted_changes` will be `false`
1245
+ *
1246
+ * **Example**:
1247
+ * ```
1248
+ * _smartico.api.getGamePickActiveRound({
1249
+ * saw_template_id: 1190,
1250
+ * round_id: 38665,
1251
+ * }).then((roundData) => {
1252
+ * const round = roundData.data;
1253
+ * round.events = round.events.map(e => ({
1254
+ * gp_event_id: e.gp_event_id,
1255
+ * team1_user_selection: 1,
1256
+ * team2_user_selection: 0,
1257
+ * }));
1258
+ * _smartico.api.submitGamePickSelection({
1259
+ * saw_template_id: 1190,
1260
+ * round: round,
1261
+ * }).then((result) => {
1262
+ * console.log(result.data.user_placed_bet); // true
1263
+ * });
1264
+ * });
1265
+ * ```
1266
+ *
1267
+ * **Visitor mode: not supported**
1268
+ */
1269
+ public async submitGamePickSelection(props: GamePickRequestParams & { round: Partial<GamePickRound> }): Promise<GamesApiResponse<GamePickRound>> {
1270
+ if (!props.saw_template_id) {
1271
+ throw new Error('saw_template_id is required');
1272
+ }
1273
+ if (!props.round?.round_id) {
1274
+ throw new Error('round is required');
1275
+ }
1276
+ return this.api.gpSubmitSelection(props.saw_template_id, props.round, false);
1277
+ }
1278
+
1279
+ /**
1280
+ * Submits answers for a round in a Quiz game.
1281
+ * Sends the round object with user answers for all events at once.
1282
+ * Each event must include `user_selection` with the answer value (e.g. '1', '2', 'x', 'yes', 'no' — depending on the market type).
1283
+ * If the user hasn't placed bets before, one game attempt (spin) will be consumed.
1284
+ * Answers can be edited until each match starts (if `allow_edit_answers` is enabled on the round).
1285
+ *
1286
+ * @param props.saw_template_id - The ID of the Quiz game template
1287
+ * @param props.round - Round object containing `round_id` and `events[]`. Typically obtained from `getGamePickActiveRound`
1288
+ * and modified with user answers. Each event needs: `gp_event_id`, `user_selection`
1289
+ *
1290
+ * **Response** `GamesApiResponse<GamePickRound>`:
1291
+ * - `errCode` - 0 on success. Non-zero codes indicate errors (e.g. not enough points/attempts)
1292
+ * - `data` - Updated round with all events reflecting the submitted answers.
1293
+ * `user_placed_bet` will be `true`, `has_not_submitted_changes` will be `false`
1294
+ *
1295
+ * **Example**:
1296
+ * ```
1297
+ * _smartico.api.getGamePickActiveRound({
1298
+ * saw_template_id: 1183,
1299
+ * round_id: 37974,
1300
+ * }).then((roundData) => {
1301
+ * const round = roundData.data;
1302
+ * round.events = round.events.map(e => ({
1303
+ * gp_event_id: e.gp_event_id,
1304
+ * user_selection: 'x',
1305
+ * }));
1306
+ * _smartico.api.submitGamePickSelectionQuiz({
1307
+ * saw_template_id: 1183,
1308
+ * round: round,
1309
+ * }).then((result) => {
1310
+ * console.log(result.data.user_placed_bet); // true
1311
+ * });
1312
+ * });
1313
+ * ```
1314
+ *
1315
+ * **Visitor mode: not supported**
1316
+ */
1317
+ public async submitGamePickSelectionQuiz(props: GamePickRequestParams & { round: Partial<GamePickRound> }): Promise<GamesApiResponse<GamePickRound>> {
1318
+ if (!props.saw_template_id) {
1319
+ throw new Error('saw_template_id is required');
1320
+ }
1321
+ if (!props.round?.round_id) {
1322
+ throw new Error('round is required');
1323
+ }
1324
+ return this.api.gpSubmitSelection(props.saw_template_id, props.round, true);
1325
+ }
1326
+
1327
+ /**
1328
+ * Returns the current user's profile information within the specified MatchX or Quiz game.
1329
+ * The user record is synced from the Smartico platform into the games DB (synced every 1 minute).
1330
+ * If the user doesn't exist in the games DB yet, it will be created automatically on first call.
1331
+ *
1332
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1333
+ *
1334
+ * **Response** `GamesApiResponse<GamePickUserInfo>`:
1335
+ * - `errCode` - 0 on success
1336
+ * - `data`:
1337
+ * - `ext_user_id` - External user ID (Smartico internal numeric ID)
1338
+ * - `int_user_id` - Internal user ID within the games system
1339
+ * - `public_username` - Display name
1340
+ * - `avatar_url` - User's avatar image URL
1341
+ * - `last_wallet_sync_time` - Last time the user's balance was synced from Smartico
1342
+ * - `ach_points_balance` - User's current points balance
1343
+ * - `ach_gems_balance` - User's current gems balance
1344
+ * - `ach_diamonds_balance` - User's current diamonds balance
1345
+ * - `pubic_username_set` - Whether the user has set a custom username
1346
+ *
1347
+ * **Example**:
1348
+ * ```
1349
+ * _smartico.api.getGamePickUserInfo({
1350
+ * saw_template_id: 1083,
1351
+ * }).then((result) => {
1352
+ * console.log(result.data.public_username, result.data.ach_points_balance);
1353
+ * });
1354
+ * ```
1355
+ *
1356
+ * **Visitor mode: not supported**
1357
+ */
1358
+ public async getGamePickUserInfo(props: GamePickRequestParams): Promise<GamesApiResponse<GamePickUserInfo>> {
1359
+ if (!props.saw_template_id) {
1360
+ throw new Error('saw_template_id is required');
1361
+ }
1362
+ return this.api.gpGetUserInfo(props.saw_template_id);
1363
+ }
1364
+
1365
+ /**
1366
+ * Returns the game configuration and the list of all rounds for the specified MatchX or Quiz game.
1367
+ * Includes the SAW template definition, label settings, and round metadata (without events).
1368
+ *
1369
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1370
+ *
1371
+ * **Response** `GamesApiResponse<GamePickGameInfo>`:
1372
+ * - `errCode` - 0 on success
1373
+ * - `data`:
1374
+ * - `sawTemplate` - Game template configuration including:
1375
+ * - `saw_template_id`, `saw_game_type_id` (6 = MatchX/Quiz)
1376
+ * - `saw_template_ui_definition` - UI settings (name, ranking options, ask_for_username, etc.)
1377
+ * - `saw_buyin_type_id` - Cost type (1=Free, 2=Points, 3=Gems, 4=Diamonds, 5=Spins)
1378
+ * - `buyin_cost_points` - Cost per attempt
1379
+ * - `spin_count` - Available attempts for the current user
1380
+ * - `allRounds[]` - List of all rounds (metadata only, no events), each with:
1381
+ * - `round_id`, `round_name`, `round_description`
1382
+ * - `open_date`, `last_bet_date` - Timestamps (ms)
1383
+ * - `is_active_now`, `is_resolved`, `round_status_id`
1384
+ * - `labelInfo` - Label/brand configuration and settings
1385
+ *
1386
+ * **Example**:
1387
+ * ```
1388
+ * _smartico.api.getGamePickGameInfo({
1389
+ * saw_template_id: 1189,
1390
+ * }).then((result) => {
1391
+ * console.log(result.data.sawTemplate.saw_template_ui_definition.name);
1392
+ * console.log('Rounds:', result.data.allRounds.length);
1393
+ * console.log('Buy-in type:', result.data.sawTemplate.saw_buyin_type_id);
1394
+ * });
1395
+ * ```
1396
+ *
1397
+ * **Visitor mode: not supported**
1398
+ */
1399
+ public async getGamePickGameInfo(props: GamePickRequestParams): Promise<GamesApiResponse<GamePickGameInfo>> {
1400
+ if (!props.saw_template_id) {
1401
+ throw new Error('saw_template_id is required');
1402
+ }
1403
+ return this.api.gpGetGameInfo(props.saw_template_id);
1404
+ }
1405
+
1406
+ /**
1407
+ * Returns translations for the MatchX/Quiz game UI.
1408
+ * Translations are returned as a key-value map for the Gamification and RetentionGames areas,
1409
+ * resolved to the current user's language.
1410
+ *
1411
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1412
+ *
1413
+ * **Response** `GamesApiResponse<any>`:
1414
+ * - `errCode` - 0 on success
1415
+ * - `data`:
1416
+ * - `translations` - Key-value map of translation strings (e.g. `rgSubmitSelection`, `rgLeaderboardTitle`, `quizConfirmAnswer`, etc.)
1417
+ * - `hash_code` - Hash for cache invalidation
1418
+ * - `lang_code` - Resolved language code (e.g. 'EN')
1419
+ *
1420
+ * **Example**:
1421
+ * ```
1422
+ * _smartico.api.getGamePickTranslations({
1423
+ * saw_template_id: 1083,
1424
+ * }).then((result) => {
1425
+ * const tr = result.data.translations;
1426
+ * console.log(tr.rgSubmitSelection); // "Submit selection"
1427
+ * console.log(tr.rgLeaderboardTitle); // "Leaderboard"
1428
+ * });
1429
+ * ```
1430
+ *
1431
+ * **Visitor mode: not supported**
1432
+ */
1433
+ public async getGamePickTranslations(props: GamePickRequestParams): Promise<GamesApiResponse<any>> {
1434
+ if (!props.saw_template_id) {
1435
+ throw new Error('saw_template_id is required');
1436
+ }
1437
+ return this.api.gpGetTranslations(props.saw_template_id);
1438
+ }
1439
+
1440
+ /**
1441
+ * Returns round data with events and picks for a specific user (identified by their internal user ID).
1442
+ * Useful for viewing another user's predictions from the leaderboard.
1443
+ * The `int_user_id` can be obtained from the `getGamePickBoard` response (`users[].int_user_id`).
1444
+ *
1445
+ * @param props.saw_template_id - The ID of the MatchX or Quiz game template
1446
+ * @param props.round_id - The round to get info for
1447
+ * @param props.int_user_id - Internal user ID of the player whose predictions to view (from leaderboard data)
1448
+ *
1449
+ * **Response** `GamesApiResponse<GamePickRound>`:
1450
+ * - `errCode` - 0 on success
1451
+ * - `data` - Round object with the target user's selections.
1452
+ * Same structure as `getGamePickActiveRound`, but `user_selection`/`team1_user_selection`/`team2_user_selection`
1453
+ * fields on events reflect the specified user's picks instead of the current user's.
1454
+ * Events also include `resolution_type_id` (0=None, 2=Lost, 3=PartialWin, 4=FullWin) showing how each prediction was scored
1455
+ *
1456
+ * **Example**:
1457
+ * ```
1458
+ * _smartico.api.getGamePickRoundInfoForUser({
1459
+ * saw_template_id: 1083,
1460
+ * round_id: 31652,
1461
+ * int_user_id: 65653810,
1462
+ * }).then((result) => {
1463
+ * result.data.events.forEach(e => {
1464
+ * console.log(e.event_meta.team1_name, 'vs', e.event_meta.team2_name, '→', e.user_selection);
1465
+ * });
1466
+ * });
1467
+ * ```
1468
+ *
1469
+ * **Visitor mode: not supported**
1470
+ */
1471
+ public async getGamePickRoundInfoForUser(props: GamePickRoundRequestParams & { int_user_id: number }): Promise<GamesApiResponse<GamePickRound>> {
1472
+ if (!props.saw_template_id) {
1473
+ throw new Error('saw_template_id is required');
1474
+ }
1475
+ if (!props.round_id) {
1476
+ throw new Error('round_id is required');
1477
+ }
1478
+ if (!props.int_user_id) {
1479
+ throw new Error('int_user_id is required');
1480
+ }
1481
+ return this.api.gpGetRoundInfoForUser(props.saw_template_id, props.round_id, props.int_user_id);
1482
+ }
1483
+
1070
1484
  private async updateOnSpin(data: SAWSpinsCountPush) {
1071
1485
  const templates: TMiniGameTemplate[] = await OCache.use(
1072
1486
  onUpdateContextKey.Saw,
1073
1487
  ECacheContext.WSAPI,
1074
- () => this.api.sawGetTemplatesT(null),
1488
+ () => this.api.sawGetTemplatesT(this.userExtId),
1075
1489
  CACHE_DATA_SEC,
1076
1490
  );
1077
1491
  const index = templates.findIndex((t) => t.id === data.saw_template_id);
@@ -1080,32 +1494,32 @@ export class WSAPI {
1080
1494
  }
1081
1495
 
1082
1496
  private async reloadMiniGameTemplate() {
1083
- const updatedTemplates = await this.api.sawGetTemplatesT(null);
1497
+ const updatedTemplates = await this.api.sawGetTemplatesT(this.userExtId);
1084
1498
  this.updateEntity(onUpdateContextKey.Saw, updatedTemplates);
1085
1499
  }
1086
1500
 
1087
1501
  private async updateMissions() {
1088
- const payload = await this.api.missionsGetItemsT(null);
1502
+ const payload = await this.api.missionsGetItemsT(this.userExtId);
1089
1503
  this.updateEntity(onUpdateContextKey.Missions, payload);
1090
1504
  }
1091
1505
 
1092
1506
  private async updateBonuses() {
1093
- const payload = await this.api.bonusesGetItemsT(null);
1507
+ const payload = await this.api.bonusesGetItemsT(this.userExtId);
1094
1508
  this.updateEntity(onUpdateContextKey.Bonuses, payload);
1095
1509
  }
1096
1510
 
1097
1511
  private async updateTournaments() {
1098
- const payload = await this.api.tournamentsGetLobbyT(null);
1512
+ const payload = await this.api.tournamentsGetLobbyT(this.userExtId);
1099
1513
  this.updateEntity(onUpdateContextKey.TournamentList, payload);
1100
1514
  }
1101
1515
 
1102
1516
  private async updateStorePurchasedItems() {
1103
- const payload = await this.api.storeGetPurchasedItemsT(null, 20, 0);
1517
+ const payload = await this.api.storeGetPurchasedItemsT(this.userExtId, 20, 0);
1104
1518
  this.updateEntity(onUpdateContextKey.StoreHistory, payload);
1105
1519
  }
1106
1520
 
1107
1521
  private async updateStoreItems() {
1108
- const payload = await this.api.storeGetItemsT(null);
1522
+ const payload = await this.api.storeGetItemsT(this.userExtId);
1109
1523
  this.updateEntity(onUpdateContextKey.StoreItems, payload);
1110
1524
  }
1111
1525
 
@@ -1114,19 +1528,19 @@ export class WSAPI {
1114
1528
  }
1115
1529
 
1116
1530
  private async updateInboxMessages() {
1117
- const payload = await this.api.getInboxMessagesT(null);
1531
+ const payload = await this.api.getInboxMessagesT(this.userExtId);
1118
1532
  this.updateEntity(onUpdateContextKey.InboxMessages, payload);
1119
1533
  }
1120
1534
 
1121
1535
  private async updateRaffles() {
1122
- const payload = await this.api.getRafflesT(null);
1536
+ const payload = await this.api.getRafflesT(this.userExtId);
1123
1537
  this.updateEntity(onUpdateContextKey.Raffles, payload);
1124
1538
  }
1125
1539
 
1126
1540
  private async notifyActivityLogUpdate() {
1127
1541
  const startSeconds = Date.now() / 1000 - 600;
1128
1542
  const endSeconds = Date.now() / 1000;
1129
- const payload = await this.api.getActivityLogT(null, startSeconds, endSeconds, 0, 50);
1543
+ const payload = await this.api.getActivityLogT(this.userExtId, startSeconds, endSeconds, 0, 50);
1130
1544
 
1131
1545
  this.updateEntity(onUpdateContextKey.ActivityLog, payload);
1132
1546
  }
@@ -1180,7 +1594,7 @@ export class WSAPI {
1180
1594
  onUpdateContextKey.Jackpots,
1181
1595
  ECacheContext.WSAPI,
1182
1596
  async () => {
1183
- const _jackpots = await this.api.jackpotGet(null, filter);
1597
+ const _jackpots = await this.api.jackpotGet(this.userExtId, filter);
1184
1598
  const _pots = _jackpots.items.map((jp) => jp.pot);
1185
1599
 
1186
1600
  _jackpots.items.forEach((jp) => {
@@ -1199,7 +1613,7 @@ export class WSAPI {
1199
1613
  ECacheContext.WSAPI,
1200
1614
  async () => {
1201
1615
  const jp_template_ids = jackpots.map((jp) => jp.jp_template_id);
1202
- return (await this.api.potGet(null, { jp_template_ids })).items;
1616
+ return (await this.api.potGet(this.userExtId, { jp_template_ids })).items;
1203
1617
  },
1204
1618
  JACKPOT_POT_CACHE_SEC,
1205
1619
  );
@@ -1233,7 +1647,7 @@ export class WSAPI {
1233
1647
  throw new Error('jp_template_id is required in jackpotOptIn');
1234
1648
  }
1235
1649
 
1236
- const result = await this.api.jackpotOptIn(null, filter);
1650
+ const result = await this.api.jackpotOptIn(this.userExtId, filter);
1237
1651
 
1238
1652
  return result;
1239
1653
  }
@@ -1257,7 +1671,7 @@ export class WSAPI {
1257
1671
  throw new Error('jp_template_id is required in jackpotOptOut');
1258
1672
  }
1259
1673
 
1260
- const result = await this.api.jackpotOptOut(null, filter);
1674
+ const result = await this.api.jackpotOptOut(this.userExtId, filter);
1261
1675
 
1262
1676
  return result;
1263
1677
  }
@@ -1290,7 +1704,7 @@ export class WSAPI {
1290
1704
  return OCache.use(
1291
1705
  onUpdateContextKey.JackpotWinners + jp_template_id,
1292
1706
  ECacheContext.WSAPI,
1293
- () => this.api.getJackpotWinnersT(null, limit, offset, jp_template_id),
1707
+ () => this.api.getJackpotWinnersT(this.userExtId, limit, offset, jp_template_id),
1294
1708
  JACKPOT_WINNERS_CACHE_SEC,
1295
1709
  );
1296
1710
  }
@@ -1317,7 +1731,7 @@ export class WSAPI {
1317
1731
  return OCache.use(
1318
1732
  onUpdateContextKey.JackpotEligibleGames + jp_template_id,
1319
1733
  ECacheContext.WSAPI,
1320
- () => this.api.getJackpotEligibleGamesT(null, { jp_template_id }),
1734
+ () => this.api.getJackpotEligibleGamesT(this.userExtId, { jp_template_id }),
1321
1735
  JACKPOT_ELIGIBLE_GAMES_CACHE_SEC,
1322
1736
  );
1323
1737
  }
@@ -1341,7 +1755,7 @@ export class WSAPI {
1341
1755
  * ```
1342
1756
  */
1343
1757
  public async getRelatedItemsForGame(related_game_id: string): Promise<GetRelatedAchTourResponse> {
1344
- const result = await this.api.getRelatedItemsForGame(null, related_game_id);
1758
+ const result = await this.api.getRelatedItemsForGame(this.userExtId, related_game_id);
1345
1759
  return result;
1346
1760
  }
1347
1761
 
@@ -1373,7 +1787,7 @@ export class WSAPI {
1373
1787
  this.onUpdateCallback.set(onUpdateContextKey.Raffles, onUpdate);
1374
1788
  }
1375
1789
 
1376
- return OCache.use(onUpdateContextKey.Raffles, ECacheContext.WSAPI, () => this.api.getRafflesT(null), CACHE_DATA_SEC);
1790
+ return OCache.use(onUpdateContextKey.Raffles, ECacheContext.WSAPI, () => this.api.getRafflesT(this.userExtId), CACHE_DATA_SEC);
1377
1791
  }
1378
1792
 
1379
1793
  /**
@@ -1405,7 +1819,7 @@ export class WSAPI {
1405
1819
  throw new Error('both raffle_id and run_id are required');
1406
1820
  }
1407
1821
 
1408
- return await this.api.getRaffleDrawRunT(null, props.raffle_id, props.run_id, props.winners_from, props.winners_to);
1822
+ return await this.api.getRaffleDrawRunT(this.userExtId, props.raffle_id, props.run_id, props.winners_from, props.winners_to);
1409
1823
  }
1410
1824
 
1411
1825
  /**
@@ -1431,7 +1845,7 @@ export class WSAPI {
1431
1845
  */
1432
1846
 
1433
1847
  public async getRaffleDrawRunsHistory(props: { raffle_id: number; draw_id?: number }): Promise<TRaffleDrawRun[]> {
1434
- const res = await this.api.getRaffleDrawRunsHistory(null, props);
1848
+ const res = await this.api.getRaffleDrawRunsHistory(this.userExtId, props);
1435
1849
 
1436
1850
  if (!props.raffle_id) {
1437
1851
  throw new Error('raffle_id is required');
@@ -1466,7 +1880,7 @@ export class WSAPI {
1466
1880
  throw new Error('won_id is required');
1467
1881
  }
1468
1882
 
1469
- const res = await this.api.claimRafflePrize(null, { won_id: props.won_id });
1883
+ const res = await this.api.claimRafflePrize(this.userExtId, { won_id: props.won_id });
1470
1884
  return raffleClaimPrizeResponseTransform(res);
1471
1885
  }
1472
1886
 
@@ -1486,7 +1900,7 @@ export class WSAPI {
1486
1900
  throw new Error('raffle_run_id is required');
1487
1901
  }
1488
1902
 
1489
- const r = await this.api.raffleOptin(null, props);
1903
+ const r = await this.api.raffleOptin(this.userExtId, props);
1490
1904
 
1491
1905
  return {
1492
1906
  err_code: r.errCode,