@smartico/public-api 0.0.384 → 0.0.386
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/dist/Clans/JoinClanErrorCode.d.ts +21 -11
- package/dist/Tournaments/TournamentRegistrationError.d.ts +32 -2
- package/dist/WSAPI/WSAPIClans.d.ts +3 -5
- package/dist/WSAPI/WSAPILeaderBoard.d.ts +3 -11
- package/dist/WSAPI/WSAPIMissions.d.ts +6 -0
- package/dist/WSAPI/WSAPIUser.d.ts +27 -16
- package/dist/index.js +112 -50
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +112 -50
- package/dist/index.modern.mjs.map +1 -1
- package/docs/api/classes/WSAPILeaderBoard.md +3 -11
- package/docs/api/classes/WSAPIMissions.md +9 -0
- package/docs/api/classes/WSAPIUser.md +27 -16
- package/docs/api/enumerations/TournamentRegistrationError.md +47 -2
- package/docs/ui/clans/UIGuide_joinClan.md +1 -2
- package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +15 -14
- package/package.json +1 -1
- package/src/Clans/JoinClanErrorCode.ts +20 -14
- package/src/Inbox/InboxMessage.ts +3 -0
- package/src/Tournaments/Tournament.ts +1 -1
- package/src/Tournaments/TournamentRegistrationError.ts +32 -4
- package/src/WSAPI/WSAPI.ts +3 -1
- package/src/WSAPI/WSAPIClans.ts +3 -5
- package/src/WSAPI/WSAPIJackpots.ts +3 -0
- package/src/WSAPI/WSAPILeaderBoard.ts +7 -12
- package/src/WSAPI/WSAPIMiniGames.ts +3 -0
- package/src/WSAPI/WSAPIMissions.ts +12 -0
- package/src/WSAPI/WSAPIUser.ts +27 -16
|
@@ -80,15 +80,8 @@ gems, diamonds, store items, or bonuses. The first element of
|
|
|
80
80
|
the array is the prize for place 1, the second for place 2, and
|
|
81
81
|
so on. The array length is the number of paid places.
|
|
82
82
|
|
|
83
|
-
**Cache TTL
|
|
84
|
-
The SDK caches
|
|
85
|
-
key — calling `getLeaderBoard(DAILY)` followed by
|
|
86
|
-
`getLeaderBoard(WEEKLY)` within the same 30 s window returns the
|
|
87
|
-
cached DAILY result for the WEEKLY call. Same applies to
|
|
88
|
-
switching `getPreviousPeriod`. To force a fresh fetch when
|
|
89
|
-
switching periods or current/previous, call
|
|
90
|
-
`_smartico.api.clearCaches()` before the second call, or simply
|
|
91
|
-
wait out the TTL.
|
|
83
|
+
**Cache TTL**
|
|
84
|
+
The SDK caches each response for 30 seconds.
|
|
92
85
|
|
|
93
86
|
**Period boundaries**
|
|
94
87
|
The server finalizes each period on a server-configurable
|
|
@@ -145,8 +138,7 @@ if (board.me) {
|
|
|
145
138
|
}
|
|
146
139
|
}
|
|
147
140
|
|
|
148
|
-
// Switch to previous period view —
|
|
149
|
-
await window._smartico.api.clearCaches();
|
|
141
|
+
// Switch to previous period view — cached separately from the current period.
|
|
150
142
|
const prev = await window._smartico.api.getLeaderBoard(LeaderBoardPeriodType.WEEKLY, true);
|
|
151
143
|
console.log('[smartico] previous-week standings — render with greyed-out "ended" treatment:', prev?.users.length, 'finalists');
|
|
152
144
|
|
|
@@ -205,8 +205,17 @@ metadata and group badges by category.
|
|
|
205
205
|
**Idempotency / Side effects**: fetch-only; safe to call repeatedly.
|
|
206
206
|
The cache layer deduplicates concurrent calls within the TTL window.
|
|
207
207
|
|
|
208
|
+
**Visitor mode**: not supported. Badges are an authenticated-only
|
|
209
|
+
feature; calling this on the visitor-mode handle (`_smartico.vapi`)
|
|
210
|
+
throws synchronously rather than silently returning an empty list.
|
|
211
|
+
|
|
208
212
|
**UI guidance**: see [UI Guide — `getBadges`](../../ui/missions/UIGuide_getBadges.md).
|
|
209
213
|
|
|
214
|
+
#### Throws
|
|
215
|
+
|
|
216
|
+
`Error("getBadges is not available in visitor mode")` when
|
|
217
|
+
called from a visitor-mode session.
|
|
218
|
+
|
|
210
219
|
#### Example
|
|
211
220
|
|
|
212
221
|
```ts
|
|
@@ -401,12 +401,25 @@ source values directly from [getUserProfile](#getuserprofile)'s
|
|
|
401
401
|
`ach_points_ever` and [getLevels](#getlevels) would also work, but
|
|
402
402
|
`progress` saves the math.
|
|
403
403
|
|
|
404
|
-
**Cache TTL
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
404
|
+
**Cache TTL & freshness**
|
|
405
|
+
The response is cached for 30 seconds, but the SDK automatically
|
|
406
|
+
drops that cache whenever a user-properties update arrives — the
|
|
407
|
+
same live channel that backs [getUserProfile](#getuserprofile). The practical
|
|
408
|
+
effect depends on the label's leveling logic:
|
|
409
|
+
- **Points-based or operator-manual leveling**: a points or level
|
|
410
|
+
change flows through the user-properties channel, so the cache is
|
|
411
|
+
busted at that moment and the next `getCurrentLevel()` call
|
|
412
|
+
returns up-to-date data without waiting out the TTL.
|
|
413
|
+
- **Counter-based leveling** (level driven by sliding-window
|
|
414
|
+
counters such as deposit or wagering totals over a recent window —
|
|
415
|
+
see [getUserLevelExtraCounters](#getuserlevelextracounters)): ordinary progress changes
|
|
416
|
+
are recomputed by a periodic server job and do NOT emit a
|
|
417
|
+
user-properties update, so they become visible on this method only
|
|
418
|
+
after the 30 s TTL expires (or after `_smartico.api.clearCaches()`).
|
|
419
|
+
|
|
420
|
+
Avoid calling `clearCaches()` on the points/manual path — it's
|
|
421
|
+
unnecessary there (the cache is already refreshed on the property
|
|
422
|
+
update) and forces a slower extra round-trip.
|
|
410
423
|
|
|
411
424
|
**Leveling logic**
|
|
412
425
|
The semantics of how a user advances depends on the label's
|
|
@@ -432,10 +445,10 @@ const level = await window._smartico.api.getCurrentLevel();
|
|
|
432
445
|
console.log('[smartico] render level badge — name:', level.name,
|
|
433
446
|
'progress:', Math.round(level.progress), '%');
|
|
434
447
|
|
|
435
|
-
// Detect level-up via getUserProfile's push channel.
|
|
448
|
+
// Detect level-up via getUserProfile's push channel. No clearCaches()
|
|
449
|
+
// needed — the SDK already drops the level cache on this update.
|
|
436
450
|
window._smartico.on('props_change', async (changed) => {
|
|
437
451
|
if ('ach_level_current_id' in changed) {
|
|
438
|
-
await window._smartico.api.clearCaches(); // bust the 30 s cache
|
|
439
452
|
const fresh = await window._smartico.api.getCurrentLevel();
|
|
440
453
|
console.log('[smartico] user levelled up — animate badge to new level:', fresh.name);
|
|
441
454
|
}
|
|
@@ -481,14 +494,12 @@ stored under the translation keys `levelsCounter1Name` and
|
|
|
481
494
|
`levelsCounter2Name`.
|
|
482
495
|
|
|
483
496
|
**Refresh cadence**
|
|
484
|
-
Sliding-window counters are recomputed by a server-side
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
[getUserProfile](#getuserprofile)'s `ach_level_current_id`, call
|
|
491
|
-
`_smartico.api.clearCaches()` to force a fresh fetch.
|
|
497
|
+
Sliding-window counters are recomputed by a periodic server-side
|
|
498
|
+
job. Its rebuild cadence is operator-configured per brand —
|
|
499
|
+
commonly daily, though it can be set more frequent — so level
|
|
500
|
+
transitions driven by counter changes surface with a latency tied
|
|
501
|
+
to that rebuild schedule after the underlying activity (e.g. a
|
|
502
|
+
deposit), not in real time.
|
|
492
503
|
|
|
493
504
|
**Idempotency**: safe. Read-only. Repeated calls within the cache
|
|
494
505
|
window return a deep-cloned cached value without a network
|
|
@@ -1,73 +1,118 @@
|
|
|
1
1
|
# Enumeration: TournamentRegistrationError
|
|
2
2
|
|
|
3
|
+
Error codes returned in `err_code` by the `registerInTournament` method.
|
|
4
|
+
|
|
5
|
+
These are terse value definitions for lookup. The full per-code narrative —
|
|
6
|
+
when each fires and how the consumer's UI should react — lives in the
|
|
7
|
+
`registerInTournament` method TSDoc, which owns the error table.
|
|
8
|
+
|
|
9
|
+
Note the numbering break: the gems / diamonds codes are 6-digit
|
|
10
|
+
(`300010` / `300011`) while the rest of the tournament block is 5-digit;
|
|
11
|
+
they were appended after the original `30001`–`30009` range was occupied.
|
|
12
|
+
Branch on the exact numeric value, not on digit count.
|
|
13
|
+
|
|
3
14
|
## Enumeration Members
|
|
4
15
|
|
|
5
16
|
### NO\_ERROR
|
|
6
17
|
|
|
7
18
|
> **NO\_ERROR**: `0`
|
|
8
19
|
|
|
20
|
+
Success — registration persisted; buy-in (if any) deducted.
|
|
21
|
+
|
|
9
22
|
***
|
|
10
23
|
|
|
11
24
|
### TOURNAMENT\_USER\_CANNOT\_JOIN\_WITHOUT\_CLAN
|
|
12
25
|
|
|
13
26
|
> **TOURNAMENT\_USER\_CANNOT\_JOIN\_WITHOUT\_CLAN**: `1010`
|
|
14
27
|
|
|
28
|
+
Clan-based tournament and the user does not belong to a clan yet.
|
|
29
|
+
|
|
15
30
|
***
|
|
16
31
|
|
|
17
32
|
### TOURNAMENT\_INSTANCE\_NOT\_FOUND
|
|
18
33
|
|
|
19
34
|
> **TOURNAMENT\_INSTANCE\_NOT\_FOUND**: `30001`
|
|
20
35
|
|
|
36
|
+
Instance id is invalid or the tournament was deleted.
|
|
37
|
+
|
|
21
38
|
***
|
|
22
39
|
|
|
23
40
|
### TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_POINTS
|
|
24
41
|
|
|
25
42
|
> **TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_POINTS**: `30002`
|
|
26
43
|
|
|
44
|
+
Insufficient points balance for a points-priced buy-in.
|
|
45
|
+
|
|
27
46
|
***
|
|
28
47
|
|
|
29
48
|
### TOURNAMENT\_INSTANCE\_NOT\_IN\_STATE
|
|
30
49
|
|
|
31
50
|
> **TOURNAMENT\_INSTANCE\_NOT\_IN\_STATE**: `30003`
|
|
32
51
|
|
|
52
|
+
Tournament is no longer in a registerable state (finished, cancelled, finalizing, or not yet open).
|
|
53
|
+
|
|
33
54
|
***
|
|
34
55
|
|
|
35
56
|
### TOURNAMENT\_ALREADY\_REGISTERED
|
|
36
57
|
|
|
37
58
|
> **TOURNAMENT\_ALREADY\_REGISTERED**: `30004`
|
|
38
59
|
|
|
60
|
+
User is already registered; treat as an idempotent success.
|
|
61
|
+
|
|
39
62
|
***
|
|
40
63
|
|
|
41
64
|
### TOURNAMENT\_USER\_DONT\_MATCH\_CONDITIONS
|
|
42
65
|
|
|
43
66
|
> **TOURNAMENT\_USER\_DONT\_MATCH\_CONDITIONS**: `30005`
|
|
44
67
|
|
|
68
|
+
User does not satisfy the tournament's segment / entry conditions.
|
|
69
|
+
|
|
45
70
|
***
|
|
46
71
|
|
|
47
72
|
### TOURNAMENT\_USER\_NOT\_REGISTERED
|
|
48
73
|
|
|
49
74
|
> **TOURNAMENT\_USER\_NOT\_REGISTERED**: `30006`
|
|
50
75
|
|
|
76
|
+
User is not registered; anomalous on a register call (usually a server-side race).
|
|
77
|
+
|
|
51
78
|
***
|
|
52
79
|
|
|
53
80
|
### TOURNAMENT\_CANT\_CHANGE\_REGISTRATION\_STATUS
|
|
54
81
|
|
|
55
82
|
> **TOURNAMENT\_CANT\_CHANGE\_REGISTRATION\_STATUS**: `30007`
|
|
56
83
|
|
|
84
|
+
Registration status transition is not allowed (e.g. re-registering a finished tournament).
|
|
85
|
+
|
|
57
86
|
***
|
|
58
87
|
|
|
59
88
|
### TOURNAMENT\_MAX\_REGISTRATIONS\_REACHED
|
|
60
89
|
|
|
61
90
|
> **TOURNAMENT\_MAX\_REGISTRATIONS\_REACHED**: `30008`
|
|
62
91
|
|
|
92
|
+
Tournament filled up — maximum registrations reached.
|
|
93
|
+
|
|
94
|
+
***
|
|
95
|
+
|
|
96
|
+
### TOURNAMENT\_INVALID\_USER\_CURRENCY
|
|
97
|
+
|
|
98
|
+
> **TOURNAMENT\_INVALID\_USER\_CURRENCY**: `30009`
|
|
99
|
+
|
|
100
|
+
The user's wallet currency could not be resolved. Emitted server-side
|
|
101
|
+
during tournament score processing, NOT during registration — it is
|
|
102
|
+
never returned by `registerInTournament`. Included for completeness.
|
|
103
|
+
|
|
63
104
|
***
|
|
64
105
|
|
|
65
106
|
### TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_GEMS
|
|
66
107
|
|
|
67
|
-
> **TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_GEMS**: `
|
|
108
|
+
> **TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_GEMS**: `300010`
|
|
109
|
+
|
|
110
|
+
Insufficient gems balance for a gems-priced buy-in.
|
|
68
111
|
|
|
69
112
|
***
|
|
70
113
|
|
|
71
114
|
### TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_DIAMONDS
|
|
72
115
|
|
|
73
|
-
> **TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_DIAMONDS**: `
|
|
116
|
+
> **TOURNAMENT\_REGISTRATION\_NOT\_ENOUGH\_DIAMONDS**: `300011`
|
|
117
|
+
|
|
118
|
+
Insufficient diamonds balance for a diamonds-priced buy-in.
|
|
@@ -76,8 +76,7 @@ table of codes; UI handling per code:
|
|
|
76
76
|
| `1003` (insufficient funds) | Show insufficient-balance UI naming the currency (`['points','gems','diamonds'][entry_fee_currency_type_id]`) and the deficit (`entry_fee_amount`). Optional: deep-link to a currency-earning surface. |
|
|
77
77
|
| `1004` (segment mismatch) | Show a gating message — operator-supplied copy if the clan exposes one; otherwise a generic "Not eligible for this clan". Don't retry. |
|
|
78
78
|
| `1005` | `joinClan` does NOT return `1005`. If you see it in this method's response, treat as a generic error. |
|
|
79
|
-
| `1006` (cooldown active) | Show "Cooldown until {cooldown_until local-formatted}". Disable the Join CTA across ALL clans until cooldown expires. |
|
|
80
|
-
| `1007` (archived) | Defined in the public enum but the server emits `1001` instead. Handle as a synonym for `1001` defensively. |
|
|
79
|
+
| `1006` (cooldown active) | Show "Cooldown until {cooldown_until local-formatted}". Disable the Join CTA across ALL clans until cooldown expires. Only fires when the user is already in a *different* clan (a switch); a first-time join never returns it. |
|
|
81
80
|
| `1011` | `joinClan` does NOT return `1011`. If you see it in this method's response, treat as a generic error. |
|
|
82
81
|
| Other | Generic error toast with `errMsg` if any. |
|
|
83
82
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
- Returns the top-20 ranked entries for one period, the current user's
|
|
5
5
|
own rank, and the configured prize table.
|
|
6
6
|
- One call per (period type, current-or-previous) — the SDK caches
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
each combination independently for 30 s, so switching periods or
|
|
8
|
+
current/previous fetches the correct board (no cross-tab collision).
|
|
9
9
|
- No subscription, no push refresh. Poll manually if the consumer
|
|
10
10
|
needs live updates during an in-progress period.
|
|
11
11
|
|
|
@@ -92,15 +92,13 @@ content.
|
|
|
92
92
|
|
|
93
93
|
When the user switches between current and previous period:
|
|
94
94
|
|
|
95
|
-
1. Call `
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
3. Replace the rendered data.
|
|
95
|
+
1. Call `getLeaderBoard(periodType, getPreviousPeriod)` with the new
|
|
96
|
+
`getPreviousPeriod` value — current and previous are cached under
|
|
97
|
+
distinct keys, so no manual cache-busting is needed.
|
|
98
|
+
2. Replace the rendered data.
|
|
100
99
|
|
|
101
100
|
```ts
|
|
102
101
|
const onTogglePrevious = async (showPrevious: boolean) => {
|
|
103
|
-
await window._smartico.api.clearCaches();
|
|
104
102
|
const board = await window._smartico.api.getLeaderBoard(
|
|
105
103
|
activePeriodType,
|
|
106
104
|
showPrevious,
|
|
@@ -109,8 +107,11 @@ const onTogglePrevious = async (showPrevious: boolean) => {
|
|
|
109
107
|
};
|
|
110
108
|
```
|
|
111
109
|
|
|
112
|
-
|
|
113
|
-
(`DAILY` → `WEEKLY` → `MONTHLY`).
|
|
110
|
+
The same holds when switching between period types
|
|
111
|
+
(`DAILY` → `WEEKLY` → `MONTHLY`): each is cached separately. To force
|
|
112
|
+
a fresh fetch within the TTL (e.g. a manual refresh button), call
|
|
113
|
+
`clearCaches()` first — it clears the whole SDK cache, not just this
|
|
114
|
+
board.
|
|
114
115
|
|
|
115
116
|
## Status-specific visual treatments
|
|
116
117
|
|
|
@@ -155,10 +156,10 @@ Same pattern applies when switching between period types
|
|
|
155
156
|
|
|
156
157
|
## Performance
|
|
157
158
|
|
|
158
|
-
- The 30 s cache deduplicates rapid refetches
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
- The 30 s cache deduplicates rapid refetches and is keyed per
|
|
160
|
+
`(periodType, getPreviousPeriod)`, so switching tabs returns the
|
|
161
|
+
correct board. `clearCaches()` forces a fresh fetch before the TTL
|
|
162
|
+
expires (it clears the entire SDK cache).
|
|
162
163
|
- For live polling during an in-progress period, ~30 s cadence is
|
|
163
164
|
appropriate (matching the cache TTL — additional polls within
|
|
164
165
|
the window are free).
|
package/package.json
CHANGED
|
@@ -1,26 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
*
|
|
1
|
+
/**
|
|
2
|
+
* Error codes returned in `errCode` by the `joinClan` method (also carried
|
|
3
|
+
* on `TClanJoinResult`). These are terse value definitions for lookup; the
|
|
4
|
+
* full per-code narrative and UI handling lives in the `joinClan` method
|
|
5
|
+
* TSDoc, which owns the error table.
|
|
4
6
|
*/
|
|
5
7
|
export enum JoinClanErrorCode {
|
|
6
|
-
/**
|
|
8
|
+
/** Success — join completed; entry fee (if any) deducted. */
|
|
7
9
|
JOIN_CLAN_OK = 0,
|
|
8
|
-
/**
|
|
10
|
+
/** Request was malformed (missing or invalid parameters). */
|
|
9
11
|
JOIN_CLAN_INVALID_PARAMETERS = 1000,
|
|
10
|
-
/**
|
|
12
|
+
/** Clan doesn't exist for this label. Archived clans are also reported as `1001`. */
|
|
11
13
|
JOIN_CLAN_NOT_FOUND = 1001,
|
|
12
|
-
/**
|
|
14
|
+
/** Clan is full — member capacity reached. */
|
|
13
15
|
JOIN_CLAN_FULL = 1002,
|
|
14
|
-
/**
|
|
16
|
+
/** Insufficient balance for the entry fee (points / gems / diamonds). */
|
|
15
17
|
JOIN_CLAN_INSUFFICIENT_FUNDS = 1003,
|
|
16
|
-
/** User doesn't
|
|
18
|
+
/** User doesn't meet the clan's entry segment or conditions. */
|
|
17
19
|
JOIN_CLAN_SEGMENT_MISMATCH = 1004,
|
|
18
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* User is not in a clan. Note: a `registerInTournament` response code
|
|
22
|
+
* that shares this enum — never returned by `joinClan`.
|
|
23
|
+
*/
|
|
19
24
|
JOIN_CLAN_USER_IS_NOT_IN_CLAN = 1005,
|
|
20
|
-
/** User is within the
|
|
25
|
+
/** User is within the clan-switch cooldown window (switch only). */
|
|
21
26
|
JOIN_CLAN_COOLDOWN_ACTIVE = 1006,
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Clan joined after tournament start. Note: a `registerInTournament`
|
|
29
|
+
* response code that shares this enum — never returned by `joinClan`.
|
|
30
|
+
*/
|
|
25
31
|
JOIN_CLAN_JOINED_AFTER_TOURNAMENT_START = 1011,
|
|
26
32
|
}
|
|
@@ -76,7 +76,7 @@ export interface Tournament {
|
|
|
76
76
|
|
|
77
77
|
export const TournamentItemsTransform = (items: Tournament[]): TTournament[] => {
|
|
78
78
|
return items
|
|
79
|
-
.filter((r) => r.tournamentId >= 1)
|
|
79
|
+
.filter((r) => r != null && r.tournamentId >= 1)
|
|
80
80
|
.map((r) => {
|
|
81
81
|
const x: TTournament = {
|
|
82
82
|
instance_id: r.tournamentInstanceId,
|
|
@@ -1,16 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error codes returned in `err_code` by the `registerInTournament` method.
|
|
3
|
+
*
|
|
4
|
+
* These are terse value definitions for lookup. The full per-code narrative —
|
|
5
|
+
* when each fires and how the consumer's UI should react — lives in the
|
|
6
|
+
* `registerInTournament` method TSDoc, which owns the error table.
|
|
7
|
+
*
|
|
8
|
+
* Note the numbering break: the gems / diamonds codes are 6-digit
|
|
9
|
+
* (`300010` / `300011`) while the rest of the tournament block is 5-digit;
|
|
10
|
+
* they were appended after the original `30001`–`30009` range was occupied.
|
|
11
|
+
* Branch on the exact numeric value, not on digit count.
|
|
12
|
+
*/
|
|
1
13
|
export enum TournamentRegistrationError {
|
|
14
|
+
/** Success — registration persisted; buy-in (if any) deducted. */
|
|
2
15
|
NO_ERROR = 0,
|
|
16
|
+
/** Clan-based tournament and the user does not belong to a clan yet. */
|
|
3
17
|
TOURNAMENT_USER_CANNOT_JOIN_WITHOUT_CLAN = 1010,
|
|
18
|
+
/** Instance id is invalid or the tournament was deleted. */
|
|
4
19
|
TOURNAMENT_INSTANCE_NOT_FOUND = 30001,
|
|
20
|
+
/** Insufficient points balance for a points-priced buy-in. */
|
|
5
21
|
TOURNAMENT_REGISTRATION_NOT_ENOUGH_POINTS = 30002,
|
|
22
|
+
/** Tournament is no longer in a registerable state (finished, cancelled, finalizing, or not yet open). */
|
|
6
23
|
TOURNAMENT_INSTANCE_NOT_IN_STATE = 30003,
|
|
24
|
+
/** User is already registered; treat as an idempotent success. */
|
|
7
25
|
TOURNAMENT_ALREADY_REGISTERED = 30004,
|
|
26
|
+
/** User does not satisfy the tournament's segment / entry conditions. */
|
|
8
27
|
TOURNAMENT_USER_DONT_MATCH_CONDITIONS = 30005,
|
|
28
|
+
/** User is not registered; anomalous on a register call (usually a server-side race). */
|
|
9
29
|
TOURNAMENT_USER_NOT_REGISTERED = 30006,
|
|
30
|
+
/** Registration status transition is not allowed (e.g. re-registering a finished tournament). */
|
|
10
31
|
TOURNAMENT_CANT_CHANGE_REGISTRATION_STATUS = 30007,
|
|
32
|
+
/** Tournament filled up — maximum registrations reached. */
|
|
11
33
|
TOURNAMENT_MAX_REGISTRATIONS_REACHED = 30008,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The user's wallet currency could not be resolved. Emitted server-side
|
|
36
|
+
* during tournament score processing, NOT during registration — it is
|
|
37
|
+
* never returned by `registerInTournament`. Included for completeness.
|
|
38
|
+
*/
|
|
39
|
+
TOURNAMENT_INVALID_USER_CURRENCY = 30009,
|
|
40
|
+
/** Insufficient gems balance for a gems-priced buy-in. */
|
|
41
|
+
TOURNAMENT_REGISTRATION_NOT_ENOUGH_GEMS = 300010,
|
|
42
|
+
/** Insufficient diamonds balance for a diamonds-priced buy-in. */
|
|
43
|
+
TOURNAMENT_REGISTRATION_NOT_ENOUGH_DIAMONDS = 300011,
|
|
16
44
|
}
|
package/src/WSAPI/WSAPI.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { SmarticoAPI } from '../SmarticoAPI';
|
|
|
5
5
|
import { JackpotWinPush, JackpotsOptinResponse, JackpotsOptoutRequest } from '../Jackpots';
|
|
6
6
|
import { onUpdateContextKey } from './WSAPIBase';
|
|
7
7
|
import { WSAPIInbox } from './WSAPIInbox';
|
|
8
|
+
import { TUserProfile } from './WSAPITypes';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Public surface of the Smartico WebSocket API. The consumer reaches every
|
|
@@ -64,13 +65,14 @@ export class WSAPI extends WSAPIInbox {
|
|
|
64
65
|
this.updateInboxUnreadCount(res.unread_count);
|
|
65
66
|
}
|
|
66
67
|
});
|
|
67
|
-
on(ClassId.CLIENT_PUBLIC_PROPERTIES_CHANGED_EVENT, (data: { props:
|
|
68
|
+
on(ClassId.CLIENT_PUBLIC_PROPERTIES_CHANGED_EVENT, (data: { props: TUserProfile }) => {
|
|
68
69
|
if (data?.props?.core_inbox_unread_count !== undefined && data?.props?.core_inbox_unread_count !== null) {
|
|
69
70
|
this.updateInboxUnreadCount(data.props.core_inbox_unread_count);
|
|
70
71
|
}
|
|
71
72
|
if (data?.props?.ach_points_balance !== undefined || data?.props?.ach_gems_balance !== undefined || data?.props?.ach_diamonds_balance !== undefined) {
|
|
72
73
|
this.notifyActivityLogUpdate();
|
|
73
74
|
}
|
|
75
|
+
OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.CurrentLevel);
|
|
74
76
|
});
|
|
75
77
|
on(ClassId.RAF_OPTIN_RESPONSE, () => this.updateRaffles());
|
|
76
78
|
}
|
package/src/WSAPI/WSAPIClans.ts
CHANGED
|
@@ -303,12 +303,10 @@ export class WSAPIClans extends WSAPITournaments {
|
|
|
303
303
|
* tournament requires the user to be in a clan first.
|
|
304
304
|
* - `1006` (`JOIN_CLAN_COOLDOWN_ACTIVE`) — user is inside the
|
|
305
305
|
* switch-cooldown window from a previous clan join (default
|
|
306
|
-
* 7 days, configurable per label).
|
|
306
|
+
* 7 days, configurable per label). Only reachable when the user is
|
|
307
|
+
* already in a *different* clan (this call is then a clan switch);
|
|
308
|
+
* a first-time join never returns `1006`. Surface the
|
|
307
309
|
* `TClans.cooldown_until` expiry in the disabled CTA.
|
|
308
|
-
* - `1007` (`JOIN_CLAN_ARCHIVED`) — defined on the public enum but
|
|
309
|
-
* the server does NOT emit this code in practice (archived clans
|
|
310
|
-
* are reported as `1001`). Handle it as a synonym for `1001`
|
|
311
|
-
* defensively, but do not rely on it.
|
|
312
310
|
* - `1011` (`JOIN_CLAN_JOINED_AFTER_TOURNAMENT_START`) — this
|
|
313
311
|
* method does NOT return `1011` directly. The code fires on
|
|
314
312
|
* {@link registerInTournament} responses when the user joined
|
|
@@ -121,6 +121,9 @@ export class WSAPIJackpots extends WSAPIClans {
|
|
|
121
121
|
ECacheContext.WSAPI,
|
|
122
122
|
async () => {
|
|
123
123
|
const _jackpots = await this.api.jackpotGet(this.userExtId, filter);
|
|
124
|
+
if (!_jackpots?.items) {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
124
127
|
const _pots = _jackpots.items.map((jp) => jp.pot);
|
|
125
128
|
|
|
126
129
|
_jackpots.items.forEach((jp) => {
|
|
@@ -56,15 +56,8 @@ export class WSAPILeaderBoard extends WSAPIGamePick {
|
|
|
56
56
|
* the array is the prize for place 1, the second for place 2, and
|
|
57
57
|
* so on. The array length is the number of paid places.
|
|
58
58
|
*
|
|
59
|
-
* **Cache TTL
|
|
60
|
-
* The SDK caches
|
|
61
|
-
* key — calling `getLeaderBoard(DAILY)` followed by
|
|
62
|
-
* `getLeaderBoard(WEEKLY)` within the same 30 s window returns the
|
|
63
|
-
* cached DAILY result for the WEEKLY call. Same applies to
|
|
64
|
-
* switching `getPreviousPeriod`. To force a fresh fetch when
|
|
65
|
-
* switching periods or current/previous, call
|
|
66
|
-
* `_smartico.api.clearCaches()` before the second call, or simply
|
|
67
|
-
* wait out the TTL.
|
|
59
|
+
* **Cache TTL**
|
|
60
|
+
* The SDK caches each response for 30 seconds.
|
|
68
61
|
*
|
|
69
62
|
* **Period boundaries**
|
|
70
63
|
* The server finalizes each period on a server-configurable
|
|
@@ -134,8 +127,7 @@ export class WSAPILeaderBoard extends WSAPIGamePick {
|
|
|
134
127
|
* }
|
|
135
128
|
* }
|
|
136
129
|
*
|
|
137
|
-
* // Switch to previous period view —
|
|
138
|
-
* await window._smartico.api.clearCaches();
|
|
130
|
+
* // Switch to previous period view — cached separately from the current period.
|
|
139
131
|
* const prev = await window._smartico.api.getLeaderBoard(LeaderBoardPeriodType.WEEKLY, true);
|
|
140
132
|
* console.log('[smartico] previous-week standings — render with greyed-out "ended" treatment:', prev?.users.length, 'finalists');
|
|
141
133
|
*
|
|
@@ -144,8 +136,11 @@ export class WSAPILeaderBoard extends WSAPIGamePick {
|
|
|
144
136
|
* ```
|
|
145
137
|
*/
|
|
146
138
|
public async getLeaderBoard(periodType: LeaderBoardPeriodType, getPreviousPeriod?: boolean): Promise<LeaderBoardDetailsT> {
|
|
139
|
+
// Cache per (periodType, current/previous) so switching tabs or
|
|
140
|
+
// current↔previous within the TTL doesn't return a colliding board.
|
|
141
|
+
const cacheKey = `${onUpdateContextKey.LeaderBoards}:${periodType}:${getPreviousPeriod ? 1 : 0}`;
|
|
147
142
|
return OCache.use(
|
|
148
|
-
|
|
143
|
+
cacheKey,
|
|
149
144
|
ECacheContext.WSAPI,
|
|
150
145
|
() => this.api.leaderboardsGetT(this.userExtId, periodType, getPreviousPeriod),
|
|
151
146
|
CACHE_DATA_SEC,
|
|
@@ -586,6 +586,9 @@ export class WSAPIMiniGames extends WSAPIRaffles {
|
|
|
586
586
|
CACHE_DATA_SEC,
|
|
587
587
|
);
|
|
588
588
|
const index = templates.findIndex((t) => t.id === data.saw_template_id);
|
|
589
|
+
if (index === -1) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
589
592
|
templates[index].spin_count = data.spin_count;
|
|
590
593
|
this.updateEntity(onUpdateContextKey.Saw, templates);
|
|
591
594
|
}
|
|
@@ -198,8 +198,14 @@ export class WSAPIMissions extends WSAPIGeneral {
|
|
|
198
198
|
* **Idempotency / Side effects**: fetch-only; safe to call repeatedly.
|
|
199
199
|
* The cache layer deduplicates concurrent calls within the TTL window.
|
|
200
200
|
*
|
|
201
|
+
* **Visitor mode**: not supported. Badges are an authenticated-only
|
|
202
|
+
* feature; calling this on the visitor-mode handle (`_smartico.vapi`)
|
|
203
|
+
* throws synchronously rather than silently returning an empty list.
|
|
204
|
+
*
|
|
201
205
|
* **UI guidance**: see [UI Guide — `getBadges`](../../docs/ui/missions/UIGuide_getBadges.md).
|
|
202
206
|
*
|
|
207
|
+
* @throws `Error("getBadges is not available in visitor mode")` when
|
|
208
|
+
* called from a visitor-mode session.
|
|
203
209
|
* @returns Promise resolving to `TMissionOrBadge[]`. Every item has
|
|
204
210
|
* `type === 'badge'`. Cached for 30 s under the `Badges` key.
|
|
205
211
|
*
|
|
@@ -241,6 +247,12 @@ export class WSAPIMissions extends WSAPIGeneral {
|
|
|
241
247
|
* ```
|
|
242
248
|
*/
|
|
243
249
|
public async getBadges(): Promise<TMissionOrBadge[]> {
|
|
250
|
+
// Badges are an authenticated-only feature. The visitor-mode WSAPI
|
|
251
|
+
// instance (`_smartico.vapi`) is constructed without a tracker, so the
|
|
252
|
+
// server would silently return nothing; throw a clear error instead.
|
|
253
|
+
if (!this.api.tracker) {
|
|
254
|
+
throw new Error('getBadges is not available in visitor mode');
|
|
255
|
+
}
|
|
244
256
|
return OCache.use(onUpdateContextKey.Badges, ECacheContext.WSAPI, () => this.api.badgetsGetItemsT(this.userExtId), CACHE_DATA_SEC);
|
|
245
257
|
}
|
|
246
258
|
|
package/src/WSAPI/WSAPIUser.ts
CHANGED
|
@@ -371,12 +371,25 @@ export class WSAPIUser extends WSAPIBase {
|
|
|
371
371
|
* `ach_points_ever` and {@link getLevels} would also work, but
|
|
372
372
|
* `progress` saves the math.
|
|
373
373
|
*
|
|
374
|
-
* **Cache TTL
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
374
|
+
* **Cache TTL & freshness**
|
|
375
|
+
* The response is cached for 30 seconds, but the SDK automatically
|
|
376
|
+
* drops that cache whenever a user-properties update arrives — the
|
|
377
|
+
* same live channel that backs {@link getUserProfile}. The practical
|
|
378
|
+
* effect depends on the label's leveling logic:
|
|
379
|
+
* - **Points-based or operator-manual leveling**: a points or level
|
|
380
|
+
* change flows through the user-properties channel, so the cache is
|
|
381
|
+
* busted at that moment and the next `getCurrentLevel()` call
|
|
382
|
+
* returns up-to-date data without waiting out the TTL.
|
|
383
|
+
* - **Counter-based leveling** (level driven by sliding-window
|
|
384
|
+
* counters such as deposit or wagering totals over a recent window —
|
|
385
|
+
* see {@link getUserLevelExtraCounters}): ordinary progress changes
|
|
386
|
+
* are recomputed by a periodic server job and do NOT emit a
|
|
387
|
+
* user-properties update, so they become visible on this method only
|
|
388
|
+
* after the 30 s TTL expires (or after `_smartico.api.clearCaches()`).
|
|
389
|
+
*
|
|
390
|
+
* Avoid calling `clearCaches()` on the points/manual path — it's
|
|
391
|
+
* unnecessary there (the cache is already refreshed on the property
|
|
392
|
+
* update) and forces a slower extra round-trip.
|
|
380
393
|
*
|
|
381
394
|
* **Leveling logic**
|
|
382
395
|
* The semantics of how a user advances depends on the label's
|
|
@@ -404,10 +417,10 @@ export class WSAPIUser extends WSAPIBase {
|
|
|
404
417
|
* console.log('[smartico] render level badge — name:', level.name,
|
|
405
418
|
* 'progress:', Math.round(level.progress), '%');
|
|
406
419
|
*
|
|
407
|
-
* // Detect level-up via getUserProfile's push channel.
|
|
420
|
+
* // Detect level-up via getUserProfile's push channel. No clearCaches()
|
|
421
|
+
* // needed — the SDK already drops the level cache on this update.
|
|
408
422
|
* window._smartico.on('props_change', async (changed) => {
|
|
409
423
|
* if ('ach_level_current_id' in changed) {
|
|
410
|
-
* await window._smartico.api.clearCaches(); // bust the 30 s cache
|
|
411
424
|
* const fresh = await window._smartico.api.getCurrentLevel();
|
|
412
425
|
* console.log('[smartico] user levelled up — animate badge to new level:', fresh.name);
|
|
413
426
|
* }
|
|
@@ -443,14 +456,12 @@ export class WSAPIUser extends WSAPIBase {
|
|
|
443
456
|
* `levelsCounter2Name`.
|
|
444
457
|
*
|
|
445
458
|
* **Refresh cadence**
|
|
446
|
-
* Sliding-window counters are recomputed by a server-side
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
* {@link getUserProfile}'s `ach_level_current_id`, call
|
|
453
|
-
* `_smartico.api.clearCaches()` to force a fresh fetch.
|
|
459
|
+
* Sliding-window counters are recomputed by a periodic server-side
|
|
460
|
+
* job. Its rebuild cadence is operator-configured per brand —
|
|
461
|
+
* commonly daily, though it can be set more frequent — so level
|
|
462
|
+
* transitions driven by counter changes surface with a latency tied
|
|
463
|
+
* to that rebuild schedule after the underlying activity (e.g. a
|
|
464
|
+
* deposit), not in real time.
|
|
454
465
|
*
|
|
455
466
|
* **Idempotency**: safe. Read-only. Repeated calls within the cache
|
|
456
467
|
* window return a deep-cloned cached value without a network
|