@pixels-online/pixels-client-js-sdk 1.4.0 → 1.6.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 -64
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +230 -63
- package/dist/index.js.map +1 -1
- package/dist/offerwall-sdk.umd.js +230 -63
- package/dist/offerwall-sdk.umd.js.map +1 -1
- package/dist/types/events.d.ts +2 -2
- package/dist/types/hooks.d.ts +0 -6
- package/dist/types/index.d.ts +13 -4
- 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
|
/**
|
|
@@ -798,67 +818,31 @@ class AssetHelper {
|
|
|
798
818
|
this.config = config;
|
|
799
819
|
}
|
|
800
820
|
resolveReward(reward) {
|
|
801
|
-
// Determine the ID to translate based on reward kind
|
|
802
|
-
let id;
|
|
803
|
-
switch (reward.kind) {
|
|
804
|
-
case 'item':
|
|
805
|
-
id = reward.itemId;
|
|
806
|
-
break;
|
|
807
|
-
case 'coins':
|
|
808
|
-
id = reward.currencyId;
|
|
809
|
-
break;
|
|
810
|
-
case 'exp':
|
|
811
|
-
id = reward.skillId;
|
|
812
|
-
break;
|
|
813
|
-
case 'on_chain':
|
|
814
|
-
id = reward.assetId;
|
|
815
|
-
break;
|
|
816
|
-
case 'trust_points':
|
|
817
|
-
id = 'trust_points';
|
|
818
|
-
break;
|
|
819
|
-
}
|
|
820
821
|
// Fallback to reward's built-in name, we should add 5x popberry etc
|
|
821
822
|
const formattedName = reward.amount > 1 ? `${reward.amount}x ${reward.name}` : reward.name;
|
|
822
823
|
// Try to resolve asset content if ID exists and resolver is set
|
|
823
|
-
if (
|
|
824
|
-
const content = this.config.assetResolver(reward
|
|
824
|
+
if (this.config.assetResolver) {
|
|
825
|
+
const content = this.config.assetResolver(reward);
|
|
825
826
|
if (content) {
|
|
826
827
|
return {
|
|
827
828
|
name: content.name || formattedName,
|
|
828
|
-
image: content.image || this.config.fallbackRewardImage
|
|
829
|
+
image: content.image || this.config.fallbackRewardImage,
|
|
829
830
|
};
|
|
830
831
|
}
|
|
831
832
|
}
|
|
832
833
|
return {
|
|
833
834
|
name: formattedName,
|
|
834
|
-
image: this.config.fallbackRewardImage
|
|
835
|
+
image: this.config.fallbackRewardImage,
|
|
835
836
|
};
|
|
836
837
|
}
|
|
837
838
|
resolveOfferRewards(offer) {
|
|
838
|
-
return offer.rewards.map(reward => ({
|
|
839
|
+
return offer.rewards.map((reward) => ({
|
|
839
840
|
...reward,
|
|
840
841
|
...this.resolveReward(reward),
|
|
841
842
|
}));
|
|
842
843
|
}
|
|
843
844
|
}
|
|
844
845
|
|
|
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
846
|
const mapEnvToOfferClientUrl = (env) => {
|
|
863
847
|
switch (env) {
|
|
864
848
|
case 'live':
|
|
@@ -930,7 +914,7 @@ class OfferwallClient {
|
|
|
930
914
|
return;
|
|
931
915
|
}
|
|
932
916
|
this.isInitializing = true;
|
|
933
|
-
await this.
|
|
917
|
+
await this.refreshOffersAndPlayer();
|
|
934
918
|
await this.connect();
|
|
935
919
|
this.isInitializing = false;
|
|
936
920
|
}
|
|
@@ -1089,28 +1073,34 @@ class OfferwallClient {
|
|
|
1089
1073
|
kind: 'offer',
|
|
1090
1074
|
});
|
|
1091
1075
|
}
|
|
1092
|
-
|
|
1076
|
+
getPlayer() {
|
|
1077
|
+
return this.offerStore.getPlayer();
|
|
1078
|
+
}
|
|
1079
|
+
getOffers() {
|
|
1080
|
+
return this.offerStore.getAllOffers();
|
|
1081
|
+
}
|
|
1082
|
+
async refreshOffersAndPlayer() {
|
|
1093
1083
|
try {
|
|
1094
|
-
const { offers,
|
|
1084
|
+
const { offers, player } = await this.getOffersAndPlayer();
|
|
1095
1085
|
this.offerStore.setOffers(offers);
|
|
1096
|
-
this.offerStore.
|
|
1097
|
-
this.eventEmitter.emit(OfferEvent.REFRESH, { offers,
|
|
1086
|
+
this.offerStore.setPlayer(player);
|
|
1087
|
+
this.eventEmitter.emit(OfferEvent.REFRESH, { offers, player: player });
|
|
1098
1088
|
this.logger.log('Refreshed offers and player snapshot');
|
|
1099
1089
|
}
|
|
1100
1090
|
catch (error) {
|
|
1101
|
-
this.handleError(error, '
|
|
1091
|
+
this.handleError(error, 'refreshOffersAndPlayer');
|
|
1102
1092
|
throw error;
|
|
1103
1093
|
}
|
|
1104
1094
|
}
|
|
1105
|
-
async
|
|
1095
|
+
async getOffersAndPlayer() {
|
|
1106
1096
|
const data = await this.postWithAuth('/v1/client/player/campaigns', {
|
|
1107
1097
|
viewingCampaigns: true,
|
|
1108
1098
|
});
|
|
1109
1099
|
if (!data.offers || !Array.isArray(data.offers)) {
|
|
1110
1100
|
throw new Error('No offers returned from offers endpoint');
|
|
1111
1101
|
}
|
|
1112
|
-
if (!data.
|
|
1113
|
-
throw new Error('No player
|
|
1102
|
+
if (!data.player) {
|
|
1103
|
+
throw new Error('No player returned from offers endpoint');
|
|
1114
1104
|
}
|
|
1115
1105
|
return data;
|
|
1116
1106
|
}
|
|
@@ -1477,6 +1467,93 @@ const meetsBaseConditions = ({ conditions, playerSnap, addDetails, }) => {
|
|
|
1477
1467
|
}
|
|
1478
1468
|
return { isValid, conditionData: addDetails ? conditionData : undefined };
|
|
1479
1469
|
};
|
|
1470
|
+
const meetsSurfacingConditions = ({ surfacingContexts, surfacingConditions, playerSnap, context, }) => {
|
|
1471
|
+
if (surfacingContexts?.length && !surfacingContexts.includes(context || '')) {
|
|
1472
|
+
// context is not in the list of surfacing contexts, so we don't want to surface this offer
|
|
1473
|
+
return { isValid: false };
|
|
1474
|
+
}
|
|
1475
|
+
const conditions = surfacingConditions;
|
|
1476
|
+
if (conditions?.andTags?.length) {
|
|
1477
|
+
// check if player has all of the tags
|
|
1478
|
+
const hasAllTags = conditions.andTags.every((tag) => playerSnap.tags?.includes(tag));
|
|
1479
|
+
if (!hasAllTags) {
|
|
1480
|
+
return { isValid: false };
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
if (conditions?.orTags?.length) {
|
|
1484
|
+
// check if player has any of the tags
|
|
1485
|
+
const hasAnyTags = conditions.orTags.some((tag) => playerSnap.tags?.includes(tag));
|
|
1486
|
+
if (!hasAnyTags) {
|
|
1487
|
+
return { isValid: false };
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
if (conditions?.notTags?.length) {
|
|
1491
|
+
// check if player has any of the tags
|
|
1492
|
+
const hasAnyTags = conditions.notTags.some((tag) => playerSnap.tags?.includes(tag));
|
|
1493
|
+
if (hasAnyTags) {
|
|
1494
|
+
return { isValid: false };
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
if (conditions?.maxDaysInGame &&
|
|
1498
|
+
(playerSnap.daysInGame || Infinity) > conditions.maxDaysInGame) {
|
|
1499
|
+
return { isValid: false };
|
|
1500
|
+
}
|
|
1501
|
+
if (conditions.loginStreak && (playerSnap.loginStreak || 0) < conditions.loginStreak) {
|
|
1502
|
+
return { isValid: false };
|
|
1503
|
+
}
|
|
1504
|
+
// Check dynamic conditions if present
|
|
1505
|
+
if (conditions.dynamic?.conditions?.length) {
|
|
1506
|
+
if (!meetsDynamicConditions(playerSnap.dynamic || {}, conditions.dynamic)) {
|
|
1507
|
+
return { isValid: false };
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
return meetsBaseConditions({ conditions, playerSnap });
|
|
1511
|
+
};
|
|
1512
|
+
const hasConditions = (conditions) => {
|
|
1513
|
+
if (!conditions)
|
|
1514
|
+
return false;
|
|
1515
|
+
if (Object.keys(conditions.currencies || {}).length > 0)
|
|
1516
|
+
return true;
|
|
1517
|
+
if (Object.keys(conditions.levels || {}).length > 0)
|
|
1518
|
+
return true;
|
|
1519
|
+
if (Object.keys(conditions.stakedTokens || {}).length > 0)
|
|
1520
|
+
return true;
|
|
1521
|
+
if (Object.keys(conditions.memberships || {}).length > 0)
|
|
1522
|
+
return true;
|
|
1523
|
+
if (Object.keys(conditions.quests || {}).length > 0)
|
|
1524
|
+
return true;
|
|
1525
|
+
if (conditions.minTrustScore)
|
|
1526
|
+
return true;
|
|
1527
|
+
if (conditions.maxTrustScore)
|
|
1528
|
+
return true;
|
|
1529
|
+
if (conditions.achievements)
|
|
1530
|
+
return true;
|
|
1531
|
+
if (conditions.minDaysInGame)
|
|
1532
|
+
return true;
|
|
1533
|
+
const surCond = conditions;
|
|
1534
|
+
if (surCond.andTags?.length)
|
|
1535
|
+
return true;
|
|
1536
|
+
if (surCond.orTags?.length)
|
|
1537
|
+
return true;
|
|
1538
|
+
if (surCond.notTags?.length)
|
|
1539
|
+
return true;
|
|
1540
|
+
if (surCond.maxDaysInGame)
|
|
1541
|
+
return true;
|
|
1542
|
+
if (surCond.loginStreak)
|
|
1543
|
+
return true;
|
|
1544
|
+
const compCond = conditions;
|
|
1545
|
+
if (compCond.buyItem)
|
|
1546
|
+
return true;
|
|
1547
|
+
if (compCond.spendCurrency)
|
|
1548
|
+
return true;
|
|
1549
|
+
if (compCond.depositCurrency)
|
|
1550
|
+
return true;
|
|
1551
|
+
if (compCond.login)
|
|
1552
|
+
return true;
|
|
1553
|
+
if (compCond.loginStreak)
|
|
1554
|
+
return true;
|
|
1555
|
+
return false;
|
|
1556
|
+
};
|
|
1480
1557
|
const meetsCompletionConditions = ({ completionConditions, completionTrackers, playerSnap, addDetails = false, }) => {
|
|
1481
1558
|
if (completionConditions) {
|
|
1482
1559
|
const conditions = completionConditions;
|
|
@@ -1579,8 +1656,84 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1579
1656
|
}
|
|
1580
1657
|
return { isValid: true, conditionData: [] };
|
|
1581
1658
|
};
|
|
1659
|
+
/**
|
|
1660
|
+
* Checks if a dynamic object meets a set of dynamic field conditions.
|
|
1661
|
+
* @param dynamicObj - The object with any key and string or number value.
|
|
1662
|
+
* @param conditions - Array of conditions to check.
|
|
1663
|
+
* @returns true if all conditions are met, false otherwise.
|
|
1664
|
+
*/
|
|
1665
|
+
/**
|
|
1666
|
+
* Evaluates a single dynamic condition against the dynamic object.
|
|
1667
|
+
*/
|
|
1668
|
+
function evaluateDynamicCondition(dynamicObj, cond) {
|
|
1669
|
+
const val = dynamicObj[cond.key];
|
|
1670
|
+
if (val === undefined)
|
|
1671
|
+
return false;
|
|
1672
|
+
switch (cond.operator) {
|
|
1673
|
+
case '==':
|
|
1674
|
+
return val === cond.compareTo;
|
|
1675
|
+
case '!=':
|
|
1676
|
+
return val !== cond.compareTo;
|
|
1677
|
+
case '>':
|
|
1678
|
+
return (typeof val === 'number' &&
|
|
1679
|
+
typeof cond.compareTo === 'number' &&
|
|
1680
|
+
val > cond.compareTo);
|
|
1681
|
+
case '>=':
|
|
1682
|
+
return (typeof val === 'number' &&
|
|
1683
|
+
typeof cond.compareTo === 'number' &&
|
|
1684
|
+
val >= cond.compareTo);
|
|
1685
|
+
case '<':
|
|
1686
|
+
return (typeof val === 'number' &&
|
|
1687
|
+
typeof cond.compareTo === 'number' &&
|
|
1688
|
+
val < cond.compareTo);
|
|
1689
|
+
case '<=':
|
|
1690
|
+
return (typeof val === 'number' &&
|
|
1691
|
+
typeof cond.compareTo === 'number' &&
|
|
1692
|
+
val <= cond.compareTo);
|
|
1693
|
+
case 'has':
|
|
1694
|
+
return (typeof val === 'string' &&
|
|
1695
|
+
typeof cond.compareTo === 'string' &&
|
|
1696
|
+
val.includes(cond.compareTo));
|
|
1697
|
+
case 'not_has':
|
|
1698
|
+
return (typeof val === 'string' &&
|
|
1699
|
+
typeof cond.compareTo === 'string' &&
|
|
1700
|
+
!val.includes(cond.compareTo));
|
|
1701
|
+
default:
|
|
1702
|
+
return false;
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
/**
|
|
1706
|
+
* Evaluates a group of dynamic conditions with logical links (AND, OR, AND NOT).
|
|
1707
|
+
* @param dynamicObj - The player's dynamic object with any key and string or number value.
|
|
1708
|
+
* @param dynamicGroup - The group of conditions and links to check.
|
|
1709
|
+
* @returns true if the group evaluates to true, false otherwise.
|
|
1710
|
+
*/
|
|
1711
|
+
function meetsDynamicConditions(dynamicObj, dynamicGroup) {
|
|
1712
|
+
const { conditions, links } = dynamicGroup;
|
|
1713
|
+
if (!conditions || conditions.length === 0)
|
|
1714
|
+
return true;
|
|
1715
|
+
// If no links, treat as AND between all conditions
|
|
1716
|
+
if (!links || links.length === 0) {
|
|
1717
|
+
return conditions.every((cond) => evaluateDynamicCondition(dynamicObj, cond));
|
|
1718
|
+
}
|
|
1719
|
+
// Evaluate the first condition
|
|
1720
|
+
let result = evaluateDynamicCondition(dynamicObj, conditions[0]);
|
|
1721
|
+
for (let i = 0; i < links.length; i++) {
|
|
1722
|
+
const nextCond = evaluateDynamicCondition(dynamicObj, conditions[i + 1]);
|
|
1723
|
+
const link = links[i];
|
|
1724
|
+
if (link === 'AND') {
|
|
1725
|
+
result = result && nextCond;
|
|
1726
|
+
}
|
|
1727
|
+
else if (link === 'OR') {
|
|
1728
|
+
result = result || nextCond;
|
|
1729
|
+
}
|
|
1730
|
+
else if (link === 'AND NOT') {
|
|
1731
|
+
result = result && !nextCond;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
return result;
|
|
1735
|
+
}
|
|
1582
1736
|
|
|
1583
|
-
// Taken from buildon_server/src/commons/types/offer.ts and merged into a single interface
|
|
1584
1737
|
const PlayerOfferStatuses = [
|
|
1585
1738
|
'inQueue',
|
|
1586
1739
|
'surfaced',
|
|
@@ -1590,16 +1743,26 @@ const PlayerOfferStatuses = [
|
|
|
1590
1743
|
'expired',
|
|
1591
1744
|
];
|
|
1592
1745
|
|
|
1593
|
-
// Taken from buildon_server/src/commons/types/reward.ts
|
|
1594
1746
|
// Use a const assertion for the array and infer the union type directly
|
|
1595
1747
|
const rewardKinds = [
|
|
1596
1748
|
'item',
|
|
1597
1749
|
'coins',
|
|
1598
1750
|
'exp',
|
|
1599
1751
|
'trust_points',
|
|
1752
|
+
'loyalty_currency', // loyalty currency that the player can exchange for rewards like on-chain via withdraw, etc.
|
|
1600
1753
|
/** 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
1754
|
];
|
|
1755
|
+
const rewardSchema = {
|
|
1756
|
+
_id: false,
|
|
1757
|
+
kind: { type: String, enum: rewardKinds },
|
|
1758
|
+
rewardId: String,
|
|
1759
|
+
skillId: String,
|
|
1760
|
+
currencyId: String, // could be a loyalty currency
|
|
1761
|
+
itemId: String,
|
|
1762
|
+
amount: Number,
|
|
1763
|
+
name: String,
|
|
1764
|
+
image: String,
|
|
1765
|
+
};
|
|
1603
1766
|
|
|
1604
|
-
export { AssetHelper, ConnectionState, EventEmitter, OfferEvent, OfferStore, OfferwallClient, PlayerOfferStatuses, SSEConnection, meetsBaseConditions, meetsCompletionConditions, rewardKinds };
|
|
1767
|
+
export { AssetHelper, ConnectionState, EventEmitter, OfferEvent, OfferStore, OfferwallClient, PlayerOfferStatuses, SSEConnection, hasConditions, meetsBaseConditions, meetsCompletionConditions, meetsDynamicConditions, meetsSurfacingConditions, rewardKinds, rewardSchema };
|
|
1605
1768
|
//# sourceMappingURL=index.esm.js.map
|