@pixels-online/pixels-client-js-sdk 1.4.0 → 1.5.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.
- package/README.md +84 -14
- package/dist/core/OfferStore.d.ts +4 -4
- package/dist/core/OfferwallClient.d.ts +7 -4
- package/dist/core/SSEConnection.d.ts +1 -1
- package/dist/index.esm.js +227 -46
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +230 -45
- package/dist/index.js.map +1 -1
- package/dist/offerwall-sdk.umd.js +230 -45
- package/dist/offerwall-sdk.umd.js.map +1 -1
- package/dist/types/events.d.ts +2 -2
- package/dist/types/index.d.ts +3 -0
- package/dist/types/offer.d.ts +6 -5
- package/dist/types/player.d.ts +37 -5
- package/dist/types/reward.d.ts +22 -6
- package/dist/utils/conditions.d.ts +29 -3
- package/dist/utils/env.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,7 +68,8 @@ client.on('offersUpdated', (offers) => {
|
|
|
68
68
|
|
|
69
69
|
// Listen for player updates
|
|
70
70
|
client.on('playerUpdated', (player) => {
|
|
71
|
-
console.log('Player
|
|
71
|
+
console.log('Player snapshot updated:', player.snapshot);
|
|
72
|
+
console.log('Player data updated:', player.data);
|
|
72
73
|
updatePlayerStatsUI(player);
|
|
73
74
|
});
|
|
74
75
|
```
|
|
@@ -85,6 +86,36 @@ try {
|
|
|
85
86
|
}
|
|
86
87
|
```
|
|
87
88
|
|
|
89
|
+
## 📊 Player Data Structure
|
|
90
|
+
|
|
91
|
+
The SDK provides player information through the `IClientPlayer` interface:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface IClientPlayer {
|
|
95
|
+
snapshot: IPlayerSnapshot; // Core player data (levels, currencies, achievements, etc.)
|
|
96
|
+
data?: IPlayerData | null; // Additional game-specific data
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Accessing Player Information
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// Get the current player
|
|
104
|
+
const player = client.getPlayer();
|
|
105
|
+
|
|
106
|
+
if (player) {
|
|
107
|
+
// Access core player data
|
|
108
|
+
console.log('Player ID:', player.snapshot.playerId);
|
|
109
|
+
console.log('Player level:', player.snapshot.levels?.combat?.level);
|
|
110
|
+
console.log('Currency balance:', player.snapshot.currencies?.gold?.balance);
|
|
111
|
+
|
|
112
|
+
// Access additional player data (if available)
|
|
113
|
+
if (player.data) {
|
|
114
|
+
console.log('Additional currencies:', player.data.currencies);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
88
119
|
## 🎯 Configuration Options
|
|
89
120
|
|
|
90
121
|
### OfferwallConfig
|
|
@@ -157,7 +188,8 @@ const client = new OfferwallClient({
|
|
|
157
188
|
// Control which offers to show
|
|
158
189
|
onOfferSurfaced: (offer) => {
|
|
159
190
|
// Custom logic to determine if offer should be shown
|
|
160
|
-
|
|
191
|
+
const currentPlayer = client.getPlayer();
|
|
192
|
+
return currentPlayer?.snapshot.levels?.overall?.level >= offer.minLevel;
|
|
161
193
|
},
|
|
162
194
|
|
|
163
195
|
// Handle successful offer claims
|
|
@@ -234,22 +266,14 @@ Initialize the client and establish connection.
|
|
|
234
266
|
|
|
235
267
|
Disconnect from the service.
|
|
236
268
|
|
|
237
|
-
#### `
|
|
238
|
-
|
|
239
|
-
Get all current offers.
|
|
269
|
+
#### `refreshOffersAndPlayer(): { offers: IClientOffer[], player: IClientPlayer }`
|
|
240
270
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
Get a specific offer by ID.
|
|
271
|
+
Refresh and get all current offers.
|
|
244
272
|
|
|
245
273
|
#### `claimOffer(offerId: string): Promise<ClaimResult>`
|
|
246
274
|
|
|
247
275
|
Claim an offer and receive rewards.
|
|
248
276
|
|
|
249
|
-
#### `getPlayer(): IClientPlayerSnapshot | null`
|
|
250
|
-
|
|
251
|
-
Get current player data.
|
|
252
|
-
|
|
253
277
|
#### `getConnectionState(): ConnectionState`
|
|
254
278
|
|
|
255
279
|
Get current connection status.
|
|
@@ -260,7 +284,7 @@ Get current connection status.
|
|
|
260
284
|
import { meetsConditions, AssetHelper } from '@pixels-online/pixels-client-js-sdk';
|
|
261
285
|
|
|
262
286
|
// Check if player meets offer conditions
|
|
263
|
-
const canClaim = meetsConditions(player, offer.surfacingConditions);
|
|
287
|
+
const canClaim = meetsConditions(player.snapshot, offer.surfacingConditions);
|
|
264
288
|
|
|
265
289
|
// Asset helper utilities
|
|
266
290
|
const assetHelper = new AssetHelper(assetResolver, fallbackImage);
|
|
@@ -302,7 +326,53 @@ The SDK supports multiple environments:
|
|
|
302
326
|
- **`dev`** - Development environment
|
|
303
327
|
- **Custom URL** - Provide your own endpoint
|
|
304
328
|
|
|
305
|
-
##
|
|
329
|
+
## � Migration Guide
|
|
330
|
+
|
|
331
|
+
### v1.0.0+ Breaking Changes
|
|
332
|
+
|
|
333
|
+
**Player Data Structure Update**
|
|
334
|
+
|
|
335
|
+
The player data structure has been updated to provide better separation between core player data and additional game-specific data:
|
|
336
|
+
|
|
337
|
+
- **Old**: `IClientPlayerSnapshot` (flat structure)
|
|
338
|
+
- **New**: `IClientPlayer` (structured with `snapshot` and `data` properties)
|
|
339
|
+
|
|
340
|
+
**Migration Steps:**
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
// Before (v0.x)
|
|
344
|
+
const player = client.getPlayer(); // IClientPlayerSnapshot
|
|
345
|
+
const level = player.levels?.combat?.level;
|
|
346
|
+
const gold = player.currencies?.gold?.balance;
|
|
347
|
+
|
|
348
|
+
// After (v1.0+)
|
|
349
|
+
const player = client.getPlayer(); // IClientPlayer
|
|
350
|
+
const level = player.snapshot.levels?.combat?.level;
|
|
351
|
+
const gold = player.snapshot.currencies?.gold?.balance;
|
|
352
|
+
|
|
353
|
+
// Access additional data (new feature)
|
|
354
|
+
const additionalCurrencies = player.data?.currencies;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**Event Handler Updates:**
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
// Before
|
|
361
|
+
client.on('playerUpdated', (playerSnapshot) => {
|
|
362
|
+
updateUI(playerSnapshot.currencies);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// After
|
|
366
|
+
client.on('playerUpdated', (player) => {
|
|
367
|
+
updateUI(player.snapshot.currencies);
|
|
368
|
+
// Also handle additional data if needed
|
|
369
|
+
if (player.data) {
|
|
370
|
+
handleAdditionalData(player.data);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## �📋 Requirements
|
|
306
376
|
|
|
307
377
|
- Node.js 16+
|
|
308
378
|
- TypeScript 4.5+ (if using TypeScript)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { OfferwallConfig } from '../types';
|
|
2
2
|
import { IClientOffer, PlayerOfferStatus } from '../types/offer';
|
|
3
|
-
import {
|
|
3
|
+
import { IClientPlayer } from '../types/player';
|
|
4
4
|
export declare class OfferStore {
|
|
5
5
|
private offers;
|
|
6
|
-
private
|
|
6
|
+
private player;
|
|
7
7
|
private logger;
|
|
8
8
|
constructor(config: OfferwallConfig);
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
getPlayer(): IClientPlayer | null;
|
|
10
|
+
setPlayer(player: IClientPlayer): void;
|
|
11
11
|
/**
|
|
12
12
|
* Set all offers (replaces existing)
|
|
13
13
|
*/
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { EventEmitter } from '../events/EventEmitter';
|
|
2
2
|
import { OfferStore } from './OfferStore';
|
|
3
3
|
import { AssetHelper } from '../utils/assets';
|
|
4
|
-
import { OfferwallConfig } from '../types';
|
|
4
|
+
import { OfferwallConfig } from '../types/index';
|
|
5
|
+
import { IClientOffer } from '../types/offer';
|
|
5
6
|
import { ConnectionState } from '../types/connection';
|
|
6
|
-
|
|
7
|
+
import { IClientPlayer } from '../types/player';
|
|
7
8
|
export declare const mapEnvToOfferClientUrl: (env: "test" | "live" | (string & {})) => "https://offers.pixels.xyz" | "https://offers.sandbox.pixels.xyz" | "https://offers.staging.pixels.xyz" | "https://offers.preview.pixels.xyz" | "https://offers.dev.pixels.xyz";
|
|
8
9
|
export declare class OfferwallClient {
|
|
9
10
|
private config;
|
|
@@ -59,8 +60,10 @@ export declare class OfferwallClient {
|
|
|
59
60
|
*/
|
|
60
61
|
private postWithAuth;
|
|
61
62
|
private claimOfferAPI;
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
getPlayer(): IClientPlayer | null;
|
|
64
|
+
getOffers(): IClientOffer[];
|
|
65
|
+
refreshOffersAndPlayer(): Promise<void>;
|
|
66
|
+
private getOffersAndPlayer;
|
|
64
67
|
getAuthLinkToken(): Promise<string>;
|
|
65
68
|
getGameId(): string | null;
|
|
66
69
|
getDashboardRedirectUrl(): Promise<string | null>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from '../events/EventEmitter';
|
|
2
|
-
import { OfferwallConfig } from '../types';
|
|
2
|
+
import { OfferwallConfig } from '../types/index';
|
|
3
3
|
import { ConnectionState } from '../types/connection';
|
|
4
4
|
import { TokenManager } from './TokenManager';
|
|
5
5
|
export declare class SSEConnection {
|
package/dist/index.esm.js
CHANGED
|
@@ -332,6 +332,24 @@ class CustomEventSource {
|
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
+
const mapEnvToBuildOnApiUrl = (env) => {
|
|
336
|
+
switch (env) {
|
|
337
|
+
case 'live':
|
|
338
|
+
return 'https://api.pixels.xyz';
|
|
339
|
+
case 'test':
|
|
340
|
+
return 'https://api.sandbox.pixels.xyz';
|
|
341
|
+
case 'staging':
|
|
342
|
+
return 'https://api.staging.pixels.xyz';
|
|
343
|
+
case 'preview':
|
|
344
|
+
return 'https://api.preview.pixels.xyz';
|
|
345
|
+
case 'dev':
|
|
346
|
+
case 'development':
|
|
347
|
+
return 'https://api.dev.pixels.xyz';
|
|
348
|
+
default:
|
|
349
|
+
return 'https://api.sandbox.pixels.xyz';
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
335
353
|
class SSEConnection {
|
|
336
354
|
constructor(config, eventEmitter, tokenManager) {
|
|
337
355
|
this.config = config;
|
|
@@ -606,22 +624,22 @@ class SSEConnection {
|
|
|
606
624
|
class OfferStore {
|
|
607
625
|
constructor(config) {
|
|
608
626
|
this.offers = new Map();
|
|
609
|
-
this.
|
|
627
|
+
this.player = null;
|
|
610
628
|
this.logger = createLogger(config, 'OfferStore');
|
|
611
629
|
}
|
|
612
|
-
|
|
613
|
-
return this.
|
|
630
|
+
getPlayer() {
|
|
631
|
+
return this.player || null;
|
|
614
632
|
}
|
|
615
|
-
|
|
616
|
-
this.
|
|
617
|
-
this.logger.log('Updated player
|
|
633
|
+
setPlayer(player) {
|
|
634
|
+
this.player = player;
|
|
635
|
+
this.logger.log('Updated player:', player);
|
|
618
636
|
}
|
|
619
637
|
/**
|
|
620
638
|
* Set all offers (replaces existing)
|
|
621
639
|
*/
|
|
622
640
|
setOffers(offers) {
|
|
623
641
|
this.offers.clear();
|
|
624
|
-
offers.forEach(offer => {
|
|
642
|
+
offers.forEach((offer) => {
|
|
625
643
|
this.offers.set(offer.instanceId, offer);
|
|
626
644
|
});
|
|
627
645
|
this.logger.log(`Set ${offers.length} offers`);
|
|
@@ -661,16 +679,18 @@ class OfferStore {
|
|
|
661
679
|
* Get offers filtered by status
|
|
662
680
|
*/
|
|
663
681
|
getOffersByStatus(status) {
|
|
664
|
-
return this.getAllOffers().filter(offer => offer.status === status);
|
|
682
|
+
return this.getAllOffers().filter((offer) => offer.status === status);
|
|
665
683
|
}
|
|
666
684
|
/**
|
|
667
685
|
* Get active offers (not expired, not claimed)
|
|
668
686
|
*/
|
|
669
687
|
getActiveOffers() {
|
|
670
|
-
return this.getAllOffers().filter(offer => {
|
|
688
|
+
return this.getAllOffers().filter((offer) => {
|
|
671
689
|
if (!offer.status)
|
|
672
690
|
return false; // Must have a status
|
|
673
|
-
return offer.status === 'surfaced' ||
|
|
691
|
+
return (offer.status === 'surfaced' ||
|
|
692
|
+
offer.status === 'viewed' ||
|
|
693
|
+
offer.status === 'claimable');
|
|
674
694
|
});
|
|
675
695
|
}
|
|
676
696
|
/**
|
|
@@ -810,12 +830,11 @@ class AssetHelper {
|
|
|
810
830
|
case 'exp':
|
|
811
831
|
id = reward.skillId;
|
|
812
832
|
break;
|
|
813
|
-
case 'on_chain':
|
|
814
|
-
id = reward.assetId;
|
|
815
|
-
break;
|
|
816
833
|
case 'trust_points':
|
|
817
834
|
id = 'trust_points';
|
|
818
835
|
break;
|
|
836
|
+
case 'loyalty_currency':
|
|
837
|
+
id = reward.currencyId;
|
|
819
838
|
}
|
|
820
839
|
// Fallback to reward's built-in name, we should add 5x popberry etc
|
|
821
840
|
const formattedName = reward.amount > 1 ? `${reward.amount}x ${reward.name}` : reward.name;
|
|
@@ -825,40 +844,23 @@ class AssetHelper {
|
|
|
825
844
|
if (content) {
|
|
826
845
|
return {
|
|
827
846
|
name: content.name || formattedName,
|
|
828
|
-
image: content.image || this.config.fallbackRewardImage
|
|
847
|
+
image: content.image || this.config.fallbackRewardImage,
|
|
829
848
|
};
|
|
830
849
|
}
|
|
831
850
|
}
|
|
832
851
|
return {
|
|
833
852
|
name: formattedName,
|
|
834
|
-
image: this.config.fallbackRewardImage
|
|
853
|
+
image: this.config.fallbackRewardImage,
|
|
835
854
|
};
|
|
836
855
|
}
|
|
837
856
|
resolveOfferRewards(offer) {
|
|
838
|
-
return offer.rewards.map(reward => ({
|
|
857
|
+
return offer.rewards.map((reward) => ({
|
|
839
858
|
...reward,
|
|
840
859
|
...this.resolveReward(reward),
|
|
841
860
|
}));
|
|
842
861
|
}
|
|
843
862
|
}
|
|
844
863
|
|
|
845
|
-
const mapEnvToBuildOnApiUrl = (env) => {
|
|
846
|
-
switch (env) {
|
|
847
|
-
case 'live':
|
|
848
|
-
return 'https://api.pixels.xyz';
|
|
849
|
-
case 'test':
|
|
850
|
-
return 'https://api.sandbox.pixels.xyz';
|
|
851
|
-
case 'staging':
|
|
852
|
-
return 'https://api.staging.pixels.xyz';
|
|
853
|
-
case 'preview':
|
|
854
|
-
return 'https://api.preview.pixels.xyz';
|
|
855
|
-
case 'dev':
|
|
856
|
-
case 'development':
|
|
857
|
-
return 'https://api.dev.pixels.xyz';
|
|
858
|
-
default:
|
|
859
|
-
return 'https://api.sandbox.pixels.xyz';
|
|
860
|
-
}
|
|
861
|
-
};
|
|
862
864
|
const mapEnvToOfferClientUrl = (env) => {
|
|
863
865
|
switch (env) {
|
|
864
866
|
case 'live':
|
|
@@ -930,7 +932,7 @@ class OfferwallClient {
|
|
|
930
932
|
return;
|
|
931
933
|
}
|
|
932
934
|
this.isInitializing = true;
|
|
933
|
-
await this.
|
|
935
|
+
await this.refreshOffersAndPlayer();
|
|
934
936
|
await this.connect();
|
|
935
937
|
this.isInitializing = false;
|
|
936
938
|
}
|
|
@@ -1089,28 +1091,34 @@ class OfferwallClient {
|
|
|
1089
1091
|
kind: 'offer',
|
|
1090
1092
|
});
|
|
1091
1093
|
}
|
|
1092
|
-
|
|
1094
|
+
getPlayer() {
|
|
1095
|
+
return this.offerStore.getPlayer();
|
|
1096
|
+
}
|
|
1097
|
+
getOffers() {
|
|
1098
|
+
return this.offerStore.getAllOffers();
|
|
1099
|
+
}
|
|
1100
|
+
async refreshOffersAndPlayer() {
|
|
1093
1101
|
try {
|
|
1094
|
-
const { offers,
|
|
1102
|
+
const { offers, player } = await this.getOffersAndPlayer();
|
|
1095
1103
|
this.offerStore.setOffers(offers);
|
|
1096
|
-
this.offerStore.
|
|
1097
|
-
this.eventEmitter.emit(OfferEvent.REFRESH, { offers,
|
|
1104
|
+
this.offerStore.setPlayer(player);
|
|
1105
|
+
this.eventEmitter.emit(OfferEvent.REFRESH, { offers, player: player });
|
|
1098
1106
|
this.logger.log('Refreshed offers and player snapshot');
|
|
1099
1107
|
}
|
|
1100
1108
|
catch (error) {
|
|
1101
|
-
this.handleError(error, '
|
|
1109
|
+
this.handleError(error, 'refreshOffersAndPlayer');
|
|
1102
1110
|
throw error;
|
|
1103
1111
|
}
|
|
1104
1112
|
}
|
|
1105
|
-
async
|
|
1113
|
+
async getOffersAndPlayer() {
|
|
1106
1114
|
const data = await this.postWithAuth('/v1/client/player/campaigns', {
|
|
1107
1115
|
viewingCampaigns: true,
|
|
1108
1116
|
});
|
|
1109
1117
|
if (!data.offers || !Array.isArray(data.offers)) {
|
|
1110
1118
|
throw new Error('No offers returned from offers endpoint');
|
|
1111
1119
|
}
|
|
1112
|
-
if (!data.
|
|
1113
|
-
throw new Error('No player
|
|
1120
|
+
if (!data.player) {
|
|
1121
|
+
throw new Error('No player returned from offers endpoint');
|
|
1114
1122
|
}
|
|
1115
1123
|
return data;
|
|
1116
1124
|
}
|
|
@@ -1477,6 +1485,93 @@ const meetsBaseConditions = ({ conditions, playerSnap, addDetails, }) => {
|
|
|
1477
1485
|
}
|
|
1478
1486
|
return { isValid, conditionData: addDetails ? conditionData : undefined };
|
|
1479
1487
|
};
|
|
1488
|
+
const meetsSurfacingConditions = ({ surfacingContexts, surfacingConditions, playerSnap, context, }) => {
|
|
1489
|
+
if (surfacingContexts?.length && !surfacingContexts.includes(context || '')) {
|
|
1490
|
+
// context is not in the list of surfacing contexts, so we don't want to surface this offer
|
|
1491
|
+
return { isValid: false };
|
|
1492
|
+
}
|
|
1493
|
+
const conditions = surfacingConditions;
|
|
1494
|
+
if (conditions?.andTags?.length) {
|
|
1495
|
+
// check if player has all of the tags
|
|
1496
|
+
const hasAllTags = conditions.andTags.every((tag) => playerSnap.tags?.includes(tag));
|
|
1497
|
+
if (!hasAllTags) {
|
|
1498
|
+
return { isValid: false };
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
if (conditions?.orTags?.length) {
|
|
1502
|
+
// check if player has any of the tags
|
|
1503
|
+
const hasAnyTags = conditions.orTags.some((tag) => playerSnap.tags?.includes(tag));
|
|
1504
|
+
if (!hasAnyTags) {
|
|
1505
|
+
return { isValid: false };
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
if (conditions?.notTags?.length) {
|
|
1509
|
+
// check if player has any of the tags
|
|
1510
|
+
const hasAnyTags = conditions.notTags.some((tag) => playerSnap.tags?.includes(tag));
|
|
1511
|
+
if (hasAnyTags) {
|
|
1512
|
+
return { isValid: false };
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
if (conditions?.maxDaysInGame &&
|
|
1516
|
+
(playerSnap.daysInGame || Infinity) > conditions.maxDaysInGame) {
|
|
1517
|
+
return { isValid: false };
|
|
1518
|
+
}
|
|
1519
|
+
if (conditions.loginStreak && (playerSnap.loginStreak || 0) < conditions.loginStreak) {
|
|
1520
|
+
return { isValid: false };
|
|
1521
|
+
}
|
|
1522
|
+
// Check dynamic conditions if present
|
|
1523
|
+
if (conditions.dynamic?.conditions?.length) {
|
|
1524
|
+
if (!meetsDynamicConditions(playerSnap.dynamic || {}, conditions.dynamic)) {
|
|
1525
|
+
return { isValid: false };
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
return meetsBaseConditions({ conditions, playerSnap });
|
|
1529
|
+
};
|
|
1530
|
+
const hasConditions = (conditions) => {
|
|
1531
|
+
if (!conditions)
|
|
1532
|
+
return false;
|
|
1533
|
+
if (Object.keys(conditions.currencies || {}).length > 0)
|
|
1534
|
+
return true;
|
|
1535
|
+
if (Object.keys(conditions.levels || {}).length > 0)
|
|
1536
|
+
return true;
|
|
1537
|
+
if (Object.keys(conditions.stakedTokens || {}).length > 0)
|
|
1538
|
+
return true;
|
|
1539
|
+
if (Object.keys(conditions.memberships || {}).length > 0)
|
|
1540
|
+
return true;
|
|
1541
|
+
if (Object.keys(conditions.quests || {}).length > 0)
|
|
1542
|
+
return true;
|
|
1543
|
+
if (conditions.minTrustScore)
|
|
1544
|
+
return true;
|
|
1545
|
+
if (conditions.maxTrustScore)
|
|
1546
|
+
return true;
|
|
1547
|
+
if (conditions.achievements)
|
|
1548
|
+
return true;
|
|
1549
|
+
if (conditions.minDaysInGame)
|
|
1550
|
+
return true;
|
|
1551
|
+
const surCond = conditions;
|
|
1552
|
+
if (surCond.andTags?.length)
|
|
1553
|
+
return true;
|
|
1554
|
+
if (surCond.orTags?.length)
|
|
1555
|
+
return true;
|
|
1556
|
+
if (surCond.notTags?.length)
|
|
1557
|
+
return true;
|
|
1558
|
+
if (surCond.maxDaysInGame)
|
|
1559
|
+
return true;
|
|
1560
|
+
if (surCond.loginStreak)
|
|
1561
|
+
return true;
|
|
1562
|
+
const compCond = conditions;
|
|
1563
|
+
if (compCond.buyItem)
|
|
1564
|
+
return true;
|
|
1565
|
+
if (compCond.spendCurrency)
|
|
1566
|
+
return true;
|
|
1567
|
+
if (compCond.depositCurrency)
|
|
1568
|
+
return true;
|
|
1569
|
+
if (compCond.login)
|
|
1570
|
+
return true;
|
|
1571
|
+
if (compCond.loginStreak)
|
|
1572
|
+
return true;
|
|
1573
|
+
return false;
|
|
1574
|
+
};
|
|
1480
1575
|
const meetsCompletionConditions = ({ completionConditions, completionTrackers, playerSnap, addDetails = false, }) => {
|
|
1481
1576
|
if (completionConditions) {
|
|
1482
1577
|
const conditions = completionConditions;
|
|
@@ -1579,8 +1674,84 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1579
1674
|
}
|
|
1580
1675
|
return { isValid: true, conditionData: [] };
|
|
1581
1676
|
};
|
|
1677
|
+
/**
|
|
1678
|
+
* Checks if a dynamic object meets a set of dynamic field conditions.
|
|
1679
|
+
* @param dynamicObj - The object with any key and string or number value.
|
|
1680
|
+
* @param conditions - Array of conditions to check.
|
|
1681
|
+
* @returns true if all conditions are met, false otherwise.
|
|
1682
|
+
*/
|
|
1683
|
+
/**
|
|
1684
|
+
* Evaluates a single dynamic condition against the dynamic object.
|
|
1685
|
+
*/
|
|
1686
|
+
function evaluateDynamicCondition(dynamicObj, cond) {
|
|
1687
|
+
const val = dynamicObj[cond.key];
|
|
1688
|
+
if (val === undefined)
|
|
1689
|
+
return false;
|
|
1690
|
+
switch (cond.operator) {
|
|
1691
|
+
case '==':
|
|
1692
|
+
return val === cond.compareTo;
|
|
1693
|
+
case '!=':
|
|
1694
|
+
return val !== cond.compareTo;
|
|
1695
|
+
case '>':
|
|
1696
|
+
return (typeof val === 'number' &&
|
|
1697
|
+
typeof cond.compareTo === 'number' &&
|
|
1698
|
+
val > cond.compareTo);
|
|
1699
|
+
case '>=':
|
|
1700
|
+
return (typeof val === 'number' &&
|
|
1701
|
+
typeof cond.compareTo === 'number' &&
|
|
1702
|
+
val >= cond.compareTo);
|
|
1703
|
+
case '<':
|
|
1704
|
+
return (typeof val === 'number' &&
|
|
1705
|
+
typeof cond.compareTo === 'number' &&
|
|
1706
|
+
val < cond.compareTo);
|
|
1707
|
+
case '<=':
|
|
1708
|
+
return (typeof val === 'number' &&
|
|
1709
|
+
typeof cond.compareTo === 'number' &&
|
|
1710
|
+
val <= cond.compareTo);
|
|
1711
|
+
case 'has':
|
|
1712
|
+
return (typeof val === 'string' &&
|
|
1713
|
+
typeof cond.compareTo === 'string' &&
|
|
1714
|
+
val.includes(cond.compareTo));
|
|
1715
|
+
case 'not_has':
|
|
1716
|
+
return (typeof val === 'string' &&
|
|
1717
|
+
typeof cond.compareTo === 'string' &&
|
|
1718
|
+
!val.includes(cond.compareTo));
|
|
1719
|
+
default:
|
|
1720
|
+
return false;
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* Evaluates a group of dynamic conditions with logical links (AND, OR, AND NOT).
|
|
1725
|
+
* @param dynamicObj - The player's dynamic object with any key and string or number value.
|
|
1726
|
+
* @param dynamicGroup - The group of conditions and links to check.
|
|
1727
|
+
* @returns true if the group evaluates to true, false otherwise.
|
|
1728
|
+
*/
|
|
1729
|
+
function meetsDynamicConditions(dynamicObj, dynamicGroup) {
|
|
1730
|
+
const { conditions, links } = dynamicGroup;
|
|
1731
|
+
if (!conditions || conditions.length === 0)
|
|
1732
|
+
return true;
|
|
1733
|
+
// If no links, treat as AND between all conditions
|
|
1734
|
+
if (!links || links.length === 0) {
|
|
1735
|
+
return conditions.every((cond) => evaluateDynamicCondition(dynamicObj, cond));
|
|
1736
|
+
}
|
|
1737
|
+
// Evaluate the first condition
|
|
1738
|
+
let result = evaluateDynamicCondition(dynamicObj, conditions[0]);
|
|
1739
|
+
for (let i = 0; i < links.length; i++) {
|
|
1740
|
+
const nextCond = evaluateDynamicCondition(dynamicObj, conditions[i + 1]);
|
|
1741
|
+
const link = links[i];
|
|
1742
|
+
if (link === 'AND') {
|
|
1743
|
+
result = result && nextCond;
|
|
1744
|
+
}
|
|
1745
|
+
else if (link === 'OR') {
|
|
1746
|
+
result = result || nextCond;
|
|
1747
|
+
}
|
|
1748
|
+
else if (link === 'AND NOT') {
|
|
1749
|
+
result = result && !nextCond;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
return result;
|
|
1753
|
+
}
|
|
1582
1754
|
|
|
1583
|
-
// Taken from buildon_server/src/commons/types/offer.ts and merged into a single interface
|
|
1584
1755
|
const PlayerOfferStatuses = [
|
|
1585
1756
|
'inQueue',
|
|
1586
1757
|
'surfaced',
|
|
@@ -1590,16 +1761,26 @@ const PlayerOfferStatuses = [
|
|
|
1590
1761
|
'expired',
|
|
1591
1762
|
];
|
|
1592
1763
|
|
|
1593
|
-
// Taken from buildon_server/src/commons/types/reward.ts
|
|
1594
1764
|
// Use a const assertion for the array and infer the union type directly
|
|
1595
1765
|
const rewardKinds = [
|
|
1596
1766
|
'item',
|
|
1597
1767
|
'coins',
|
|
1598
1768
|
'exp',
|
|
1599
1769
|
'trust_points',
|
|
1770
|
+
'loyalty_currency', // loyalty currency that the player can exchange for rewards like on-chain via withdraw, etc.
|
|
1600
1771
|
/** on-chain rewards require the builder to send funds to a custodial wallet that we use to send to player wallets*/
|
|
1601
|
-
'on_chain',
|
|
1602
1772
|
];
|
|
1773
|
+
const rewardSchema = {
|
|
1774
|
+
_id: false,
|
|
1775
|
+
kind: { type: String, enum: rewardKinds },
|
|
1776
|
+
rewardId: String,
|
|
1777
|
+
skillId: String,
|
|
1778
|
+
currencyId: String, // could be a loyalty currency
|
|
1779
|
+
itemId: String,
|
|
1780
|
+
amount: Number,
|
|
1781
|
+
name: String,
|
|
1782
|
+
image: String,
|
|
1783
|
+
};
|
|
1603
1784
|
|
|
1604
|
-
export { AssetHelper, ConnectionState, EventEmitter, OfferEvent, OfferStore, OfferwallClient, PlayerOfferStatuses, SSEConnection, meetsBaseConditions, meetsCompletionConditions, rewardKinds };
|
|
1785
|
+
export { AssetHelper, ConnectionState, EventEmitter, OfferEvent, OfferStore, OfferwallClient, PlayerOfferStatuses, SSEConnection, hasConditions, meetsBaseConditions, meetsCompletionConditions, meetsDynamicConditions, meetsSurfacingConditions, rewardKinds, rewardSchema };
|
|
1605
1786
|
//# sourceMappingURL=index.esm.js.map
|