@pixels-online/pixels-client-js-sdk 1.13.0 → 1.15.0

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.
@@ -1,4 +1,5 @@
1
- import { IBlockchainSyncStatus, ICryptoBalance } from './user_wallet';
1
+ import { Stringable } from '.';
2
+ import { IBlockchainSyncStatus } from './user_wallet';
2
3
  export type IClientPlayer = {
3
4
  snapshot: Omit<IPlayerSnapshot, 'tags' | 'tagsLastUpdated'>;
4
5
  data?: IPlayerData | null;
@@ -7,10 +8,12 @@ export interface IPlayerSnapshot {
7
8
  _id: string;
8
9
  gameId: string;
9
10
  playerId: string;
11
+ /** when this was last linked to a unified user */
12
+ unifiedUserLinkedAt?: number;
13
+ /** when this was last unlinked to a unified user */
14
+ unifiedUserUnlinkedAt?: number;
10
15
  /** player that referred this player to this game */
11
16
  referredById?: string;
12
- /** did this player complete referee and can claim rewards now? Store this here so we don't need to do another db lookup */
13
- refereeRewardsClaimable?: boolean;
14
17
  username?: string;
15
18
  snapshotLastUpdated: number;
16
19
  offersLastChecked?: number;
@@ -56,20 +59,33 @@ export interface IPlayerSnapshot {
56
59
  expiresAt?: number;
57
60
  lastUpdated?: number;
58
61
  }>;
62
+ /** auth identifiers. like social tiktok or email or sms or whatever */
63
+ identifiers?: Array<{
64
+ /** id */
65
+ identifier: string;
66
+ /** sms/email/tiktok etc */
67
+ platform: string;
68
+ lastUpdated: number;
69
+ }>;
59
70
  cryptoWallets?: Array<{
60
71
  address: string;
61
72
  lastUpdated?: number;
62
73
  }>;
63
- /** wallets that this player has sent on-chain rewards to */
64
- rewardWallets?: Array<{
65
- address: string;
66
- /** list of chains that this wallet has received funds from */
67
- chainIds: Array<number>;
68
- /** list of contract IDs that this wallet has received funds from */
69
- contractIds: Array<string>;
70
- }>;
71
74
  tags?: Array<string>;
72
75
  tagsLastUpdated?: number;
76
+ /**
77
+ * Entity type - undefined or "player" for regular players, or custom types like "pet", "guild", "npc", etc.
78
+ */
79
+ target?: string;
80
+ /**
81
+ * Links to other entities (players, pets, guilds, etc.)
82
+ */
83
+ entityLinks?: Array<{
84
+ /** if undefined, it means same game */
85
+ gameId?: string;
86
+ playerId: string;
87
+ kind?: string;
88
+ }>;
73
89
  /**
74
90
  * collection of information about IP address player connected from
75
91
  */
@@ -82,10 +98,30 @@ export type Restriction = {
82
98
  eventCount: number;
83
99
  message?: string;
84
100
  };
101
+ export interface IPlayerDataCurrency {
102
+ /**
103
+ * balance held
104
+ */
105
+ balance: number;
106
+ /**
107
+ * total amount deposited
108
+ */
109
+ in?: number;
110
+ /**
111
+ * total amount withdrawn
112
+ */
113
+ out?: number;
114
+ /**
115
+ * last updated timestamp
116
+ * if not present, means never updated
117
+ */
118
+ lastUpdated?: number;
119
+ }
85
120
  export interface IPlayerData {
121
+ _id?: Stringable;
86
122
  gameId: string;
87
123
  playerId: string;
88
- currencies?: Record<string, ICryptoBalance>;
124
+ currencies?: Record<string, IPlayerDataCurrency>;
89
125
  blockchainSync?: Record<string, IBlockchainSyncStatus>;
90
126
  restriction?: Restriction;
91
127
  }
@@ -165,6 +201,26 @@ export interface IBaseCondition {
165
201
  /** if a min number of quest completions is required */
166
202
  completions?: number;
167
203
  }>;
204
+ /**
205
+ * For player snapshot entities that are linked to other player snap entities,
206
+ * what are the min and max number of links of a specific link kind?
207
+ * Keys are link kinds (e.g., "pet", "guild", "npc", etc.)
208
+ */
209
+ links?: Record<string, {
210
+ /** minimum number of links of this type required */
211
+ min?: number;
212
+ /** maximum number of links of this type allowed */
213
+ max?: number;
214
+ }>;
215
+ /** dynamic field conditions */
216
+ dynamic?: IDynamicGroup;
217
+ /** Auth platform identifiers condition */
218
+ identifiers?: {
219
+ /** List of auth platforms to check (e.g., 'tiktok', 'google', 'email') */
220
+ platforms: string[];
221
+ /** 'AND' = player must have ALL platforms, 'OR' = player must have ANY platform */
222
+ behaviour: 'AND' | 'OR';
223
+ };
168
224
  }
169
225
  export interface ISurfacingCondition extends IBaseCondition {
170
226
  /** number of days that the player has logged in-game. Not the absolute amount of time playing the game. But number of days they have logged in for.
@@ -177,8 +233,6 @@ export interface ISurfacingCondition extends IBaseCondition {
177
233
  orTags?: Array<string>;
178
234
  /** player cannot have any of these tags */
179
235
  notTags?: Array<string>;
180
- /** dynamic field conditions for surfacing */
181
- dynamic?: IDynamicGroup;
182
236
  /** minimum signup date (timestamp) - player must have signed up after this date */
183
237
  minDateSignedUp?: number;
184
238
  /** maximum signup date (timestamp) - player must have signed up before this date */
@@ -187,6 +241,10 @@ export interface ISurfacingCondition extends IBaseCondition {
187
241
  completedOffers?: Array<string>;
188
242
  /** surfacing contexts */
189
243
  contexts?: Array<string>;
244
+ /** if true, offer can only be surfaced programmatically (e.g., via spawnLinkedOffer) - never through normal auto-surfacing */
245
+ programmatic?: boolean;
246
+ /** entity types that this offer can surface to - undefined or empty means only regular players. */
247
+ targetEntityTypes?: string[];
190
248
  }
191
249
  /** conditions that must be met for an already surfaced offer to be claimable */
192
250
  export interface ICompletionCondition extends IBaseCondition {
@@ -213,6 +271,8 @@ export interface ICompletionCondition extends IBaseCondition {
213
271
  };
214
272
  /** social media content condition - player must attach content meeting requirements */
215
273
  social?: {
274
+ /** 'attach' (default) = user attaches single content, 'accumulate' = auto-sum all matching content */
275
+ mode?: 'attach' | 'accumulate';
216
276
  /** platforms accepted (OR logic) - e.g., ['tiktok', 'instagram', 'youtube'] */
217
277
  platforms: string[];
218
278
  /** words that must ALL appear in video title or description (case-insensitive). Hashtags must match exactly including # */
@@ -233,6 +293,13 @@ export interface ICompletionCondition extends IBaseCondition {
233
293
  id: string;
234
294
  name: string;
235
295
  };
296
+ /**
297
+ * Linked completions - wait for N linked entities to complete their offers
298
+ */
299
+ linkedCompletions?: {
300
+ /** Number of linked entity completions required */
301
+ min: number;
302
+ };
236
303
  }
237
304
  /**
238
305
  * TypeScript interface for dynamicGroupSchema
@@ -250,6 +317,44 @@ export type DynamicConditionLink = 'AND' | 'OR' | 'AND NOT';
250
317
  export interface IDynamicGroup {
251
318
  conditions: Array<IDynamicCondition>;
252
319
  links?: Array<DynamicConditionLink>;
320
+ /** Display template using {keyName} syntax for referenced dynamic keys */
321
+ template?: string;
322
+ }
323
+ /** Social tracker for attach mode - user manually attaches a single piece of content */
324
+ export interface ISocialTrackerAttach {
325
+ /** 'attach' or undefined = user-attached single content */
326
+ mode?: 'attach';
327
+ /** platform name - tiktok, instagram, or youtube */
328
+ platform: string;
329
+ /** video ID on the platform */
330
+ videoId: string;
331
+ /** platform specific user ID */
332
+ userId: string;
333
+ /** cached video title for display */
334
+ title?: string;
335
+ /** cached view count */
336
+ views: number;
337
+ /** cached like count */
338
+ likes?: number;
339
+ /** cached comment count */
340
+ comments?: number;
341
+ /** timestamp of last validation check (for 5-minute cache) */
342
+ lastChecked: Date;
343
+ }
344
+ /** Social tracker for accumulate mode - auto-sum all matching content */
345
+ export interface ISocialTrackerAccumulate {
346
+ /** 'accumulate' = auto-sum all matching content */
347
+ mode: 'accumulate';
348
+ /** sum of view counts across all matching content */
349
+ views: number;
350
+ /** sum of like counts across all matching content */
351
+ likes?: number;
352
+ /** sum of comment counts across all matching content */
353
+ comments?: number;
354
+ /** timestamp of last validation check (for 5-minute cache) */
355
+ lastChecked: Date;
356
+ /** number of matching content items */
357
+ matchCount: number;
253
358
  }
254
359
  /** tracking the player's status for completing the conditions to claim the offer, if
255
360
  * required.
@@ -264,25 +369,14 @@ export interface ICompletionTrackers {
264
369
  /** the number of days that have been consecutively logged in at the time of surfacing this offer */
265
370
  currentLoginStreak?: number;
266
371
  /** tracks attached social media content and cached validation state */
267
- social?: {
268
- /** platform name - tiktok, instagram, or youtube */
269
- platform: string;
270
- /** video ID on the platform */
271
- videoId: string;
272
- /** cached video title for display */
273
- title?: string;
274
- /** cached view count */
275
- views: number;
276
- /** cached like count */
277
- likes?: number;
278
- /** cached comment count */
279
- comments?: number;
280
- /** timestamp of last validation check (for 1-hour cache) */
281
- lastChecked: Date;
282
- /** platform specific user ID */
283
- userId: string;
284
- };
372
+ social?: ISocialTrackerAttach | ISocialTrackerAccumulate;
285
373
  login?: boolean;
286
374
  /** completed context for this player */
287
375
  context?: string;
376
+ /**
377
+ * Count of linked entities that have completed their offers.
378
+ * For example a referrer refers 5 other referees that have all
379
+ * completed the referral criteria. this would then be a value of 5.
380
+ */
381
+ linkedCompletions?: number;
288
382
  }
@@ -4,12 +4,6 @@ export interface IReward {
4
4
  /** if the trigger is type daily-login, which day is this reward for? */
5
5
  /** reward id for rewards of kind item, coins, exp or loyalty currency */
6
6
  rewardId?: string;
7
- /** @deprecated in favour of rewardId */
8
- skillId?: string;
9
- /** @deprecated in favour of rewardId */
10
- currencyId?: string;
11
- /** @deprecated in favour of rewardId */
12
- itemId?: string;
13
7
  /** amount of reward to give. If kind is discount, then this refers to the discount amount, as a fraction */
14
8
  amount: number;
15
9
  /** public facing name for this reward */
@@ -18,17 +12,24 @@ export interface IReward {
18
12
  image?: string;
19
13
  }
20
14
  export type RewardKind = (typeof rewardKinds)[number];
15
+ /** for client side sdk */
21
16
  export interface IResolvedReward extends IReward {
22
17
  image?: string;
23
18
  }
24
- export declare const rewardKinds: readonly ["item", "coins", "exp", "trust_points", "loyalty_currency"];
19
+ export declare const rewardKinds: readonly ["item", "coins", "exp", "trust_points", "loyalty_currency", "discount"];
25
20
  export declare const rewardSchema: {
26
21
  _id: boolean;
27
22
  kind: {
28
23
  type: StringConstructor;
29
- enum: readonly ["item", "coins", "exp", "trust_points", "loyalty_currency"];
24
+ enum: readonly ["item", "coins", "exp", "trust_points", "loyalty_currency", "discount"];
25
+ };
26
+ rewardId: {
27
+ type: StringConstructor;
28
+ validate: {
29
+ validator: (this: IReward, value: string | undefined) => boolean;
30
+ message: string;
31
+ };
30
32
  };
31
- rewardId: StringConstructor;
32
33
  skillId: StringConstructor;
33
34
  currencyId: StringConstructor;
34
35
  itemId: StringConstructor;
@@ -52,6 +52,22 @@ export declare const meetsCompletionConditions: ({ completionConditions, complet
52
52
  text: string;
53
53
  }[];
54
54
  };
55
+ /**
56
+ * Checks if completion conditions were met before a specific expiry time.
57
+ * Returns true if all relevant condition fields were updated before expiryTime.
58
+ *
59
+ * @param completionConditions - The completion conditions to check
60
+ * @param completionTrackers - The completion trackers (for buyItem, spendCurrency, etc.)
61
+ * @param playerSnap - The player snapshot with field timestamps
62
+ * @param expiryTime - The expiry timestamp in milliseconds
63
+ * @returns true if all conditions were met before expiry, false otherwise
64
+ */
65
+ export declare const meetsCompletionConditionsBeforeExpiry: ({ completionConditions, completionTrackers, playerSnap, expiryTime, }: {
66
+ completionConditions: ICompletionCondition;
67
+ completionTrackers?: ICompletionTrackers;
68
+ playerSnap: IPlayerSnapshot;
69
+ expiryTime: number;
70
+ }) => boolean;
55
71
  /**
56
72
  * Evaluates a group of dynamic conditions with logical links (AND, OR, AND NOT).
57
73
  * @param dynamicObj - The player's dynamic object with any key and string or number value.
@@ -0,0 +1,2 @@
1
+ export declare function extractTemplateKeys(template: string | undefined): Set<string>;
2
+ export declare function renderTemplate(template: string | undefined, dynamic: Record<string, string | number> | undefined): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixels-online/pixels-client-js-sdk",
3
- "version": "1.13.0",
3
+ "version": "1.15.0",
4
4
  "description": "Pixels Client JS SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",