@pixels-online/pixels-client-js-sdk 1.0.2 → 1.2.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 +338 -1
- package/dist/core/OfferwallClient.d.ts +2 -0
- package/dist/core/SSEConnection.d.ts +1 -0
- package/dist/index.esm.js +51 -24
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +51 -24
- package/dist/index.js.map +1 -1
- package/dist/offerwall-sdk.umd.js +51 -24
- package/dist/offerwall-sdk.umd.js.map +1 -1
- package/dist/types/index.d.ts +25 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1 +1,338 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Pixels BuildOn Client JS SDK
|
|
2
|
+
|
|
3
|
+
A powerful TypeScript SDK for integrating Pixels BuildOn offerwall functionality into web applications and games. This SDK provides real-time offer management, player progression tracking, and reward handling capabilities.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- **Real-time Offer Management** - Live updates via Server-Sent Events (SSE)
|
|
8
|
+
- **Player Progression Tracking** - Monitor player stats, achievements, and conditions
|
|
9
|
+
- **Reward System Integration** - Handle various reward types (coins, items, exp, etc.)
|
|
10
|
+
- **Event-Driven Architecture** - React to offer events and player actions
|
|
11
|
+
- **TypeScript Support** - Full type safety and IntelliSense support
|
|
12
|
+
- **Flexible Configuration** - Customizable asset resolution and hooks
|
|
13
|
+
- **Multi-Environment Support** - Local, Test, staging, and production environments
|
|
14
|
+
- **Auto-Reconnection** - Robust connection management with retry logic
|
|
15
|
+
|
|
16
|
+
## 📦 Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @pixels-online/pixels-client-js-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 🔧 Quick Start
|
|
23
|
+
|
|
24
|
+
### 1. Basic Setup
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { OfferwallClient } from '@pixels-online/pixels-client-js-sdk';
|
|
28
|
+
|
|
29
|
+
const client = new OfferwallClient({
|
|
30
|
+
env: 'test', // or 'live' for production
|
|
31
|
+
tokenProvider: async () => {
|
|
32
|
+
// Fetch JWT token from your server. We recommend using our server-side SDK on your server for JWT creation
|
|
33
|
+
const response = await fetch('/api/auth/pixels-token', {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: { 'Content-Type': 'application/json' },
|
|
36
|
+
});
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
return data.token;
|
|
39
|
+
},
|
|
40
|
+
assetResolver: (_, id: string) => {
|
|
41
|
+
return {
|
|
42
|
+
name: exampleGameLib[id]?.name || 'Unknown2',
|
|
43
|
+
image: exampleGameLib[id]?.image,
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
fallbackRewardImage: 'https://example.com/default-reward.png',
|
|
47
|
+
hooks: {
|
|
48
|
+
onOfferSurfaced: (offer) => {
|
|
49
|
+
var random = Math.random() < 0.5;
|
|
50
|
+
return random; // 50% chance to show the offer
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
autoConnect: true,
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 2. Initialize and Connect
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// Initialize the client
|
|
61
|
+
await client.initialize();
|
|
62
|
+
|
|
63
|
+
// Listen for offers
|
|
64
|
+
client.on('offersUpdated', (offers) => {
|
|
65
|
+
console.log('Available offers:', offers);
|
|
66
|
+
displayOffersInUI(offers);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Listen for player updates
|
|
70
|
+
client.on('playerUpdated', (player) => {
|
|
71
|
+
console.log('Player data updated:', player);
|
|
72
|
+
updatePlayerStatsUI(player);
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3. Claim Offers
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// Claim an offer
|
|
80
|
+
try {
|
|
81
|
+
const result = await client.claimOffer(offerId);
|
|
82
|
+
console.log('Offer claimed successfully:', result);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('Failed to claim offer:', error);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 🎯 Configuration Options
|
|
89
|
+
|
|
90
|
+
### OfferwallConfig
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
interface OfferwallConfig {
|
|
94
|
+
/** Environment: 'test' | 'live' | custom endpoint */
|
|
95
|
+
env: 'test' | 'live' | (string & {});
|
|
96
|
+
|
|
97
|
+
/** Auto-connect on initialization (default: false) */
|
|
98
|
+
autoConnect?: boolean;
|
|
99
|
+
|
|
100
|
+
/** Enable auto-reconnection (default: true) */
|
|
101
|
+
reconnect?: boolean;
|
|
102
|
+
|
|
103
|
+
/** Reconnection delay in ms (default: 1000) */
|
|
104
|
+
reconnectDelay?: number;
|
|
105
|
+
|
|
106
|
+
/** Max reconnection attempts (default: 5) */
|
|
107
|
+
maxReconnectAttempts?: number;
|
|
108
|
+
|
|
109
|
+
/** Enable debug logging (default: false) */
|
|
110
|
+
debug?: boolean;
|
|
111
|
+
|
|
112
|
+
/** Event hooks for custom logic */
|
|
113
|
+
hooks?: Partial<OfferwallHooks>;
|
|
114
|
+
|
|
115
|
+
/** Custom asset resolver for rewards */
|
|
116
|
+
assetResolver?: AssetResolver;
|
|
117
|
+
|
|
118
|
+
/** Fallback image for unknown rewards */
|
|
119
|
+
fallbackRewardImage: string;
|
|
120
|
+
|
|
121
|
+
/** JWT token provider function */
|
|
122
|
+
tokenProvider: TokenProvider;
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 🎨 Asset Resolution
|
|
127
|
+
|
|
128
|
+
Customize how rewards are displayed in your game:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const gameAssets = {
|
|
132
|
+
gems: { name: 'Gems', image: '/assets/gems.png' },
|
|
133
|
+
gold: { name: 'Gold Coins', image: '/assets/gold.png' },
|
|
134
|
+
sword_1: { name: 'Iron Sword', image: '/assets/sword_iron.png' },
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const client = new OfferwallClient({
|
|
138
|
+
// ... other config
|
|
139
|
+
assetResolver: (reward, assetId) => {
|
|
140
|
+
const asset = gameAssets[assetId];
|
|
141
|
+
if (asset) {
|
|
142
|
+
return { name: asset.name, image: asset.image };
|
|
143
|
+
}
|
|
144
|
+
return { name: `Unknown Item (${assetId})`, image: null };
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 🎣 Event Hooks
|
|
150
|
+
|
|
151
|
+
Implement custom logic with event hooks:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const client = new OfferwallClient({
|
|
155
|
+
// ... other config
|
|
156
|
+
hooks: {
|
|
157
|
+
// Control which offers to show
|
|
158
|
+
onOfferSurfaced: (offer) => {
|
|
159
|
+
// Custom logic to determine if offer should be shown
|
|
160
|
+
return player.level >= offer.minLevel;
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
// Handle successful offer claims
|
|
164
|
+
onOfferClaimed: async (offer, rewards) => {
|
|
165
|
+
console.log('Offer completed!', { offer, rewards });
|
|
166
|
+
// Award rewards in your game
|
|
167
|
+
await showConfetti(rewards);
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
// Handle connection events
|
|
171
|
+
onConnect: () => {
|
|
172
|
+
console.log('Connected to Pixels BuildOn');
|
|
173
|
+
showConnectionStatus('connected');
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
onDisconnect: () => {
|
|
177
|
+
console.log('Disconnected from Pixels BuildOn');
|
|
178
|
+
showConnectionStatus('disconnected');
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 📡 Events
|
|
185
|
+
|
|
186
|
+
Listen to various events emitted by the client:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Offer-related events
|
|
190
|
+
client.on('offersUpdated', (offers) => {
|
|
191
|
+
/* Handle offers update */
|
|
192
|
+
});
|
|
193
|
+
client.on('offerAdded', (offer) => {
|
|
194
|
+
/* Handle new offer */
|
|
195
|
+
});
|
|
196
|
+
client.on('offerRemoved', (offerId) => {
|
|
197
|
+
/* Handle offer removal */
|
|
198
|
+
});
|
|
199
|
+
client.on('offerUpdated', (offer) => {
|
|
200
|
+
/* Handle offer changes */
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Player-related events
|
|
204
|
+
client.on('playerUpdated', (player) => {
|
|
205
|
+
/* Handle player data changes */
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Connection events
|
|
209
|
+
client.on('connected', () => {
|
|
210
|
+
/* Handle connection */
|
|
211
|
+
});
|
|
212
|
+
client.on('disconnected', () => {
|
|
213
|
+
/* Handle disconnection */
|
|
214
|
+
});
|
|
215
|
+
client.on('reconnecting', (attempt) => {
|
|
216
|
+
/* Handle reconnection attempts */
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Error events
|
|
220
|
+
client.on('error', (error) => {
|
|
221
|
+
/* Handle errors */
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## 🏗️ API Reference
|
|
226
|
+
|
|
227
|
+
### OfferwallClient Methods
|
|
228
|
+
|
|
229
|
+
#### `initialize(): Promise<void>`
|
|
230
|
+
|
|
231
|
+
Initialize the client and establish connection.
|
|
232
|
+
|
|
233
|
+
#### `disconnect(): Promise<void>`
|
|
234
|
+
|
|
235
|
+
Disconnect from the service.
|
|
236
|
+
|
|
237
|
+
#### `getOffers(): IClientOffer[]`
|
|
238
|
+
|
|
239
|
+
Get all current offers.
|
|
240
|
+
|
|
241
|
+
#### `getOffer(offerId: string): IClientOffer | null`
|
|
242
|
+
|
|
243
|
+
Get a specific offer by ID.
|
|
244
|
+
|
|
245
|
+
#### `claimOffer(offerId: string): Promise<ClaimResult>`
|
|
246
|
+
|
|
247
|
+
Claim an offer and receive rewards.
|
|
248
|
+
|
|
249
|
+
#### `getPlayer(): IClientPlayerSnapshot | null`
|
|
250
|
+
|
|
251
|
+
Get current player data.
|
|
252
|
+
|
|
253
|
+
#### `getConnectionState(): ConnectionState`
|
|
254
|
+
|
|
255
|
+
Get current connection status.
|
|
256
|
+
|
|
257
|
+
### Utility Functions
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import { meetsConditions, AssetHelper } from '@pixels-online/pixels-client-js-sdk';
|
|
261
|
+
|
|
262
|
+
// Check if player meets offer conditions
|
|
263
|
+
const canClaim = meetsConditions(player, offer.surfacingConditions);
|
|
264
|
+
|
|
265
|
+
// Asset helper utilities
|
|
266
|
+
const assetHelper = new AssetHelper(assetResolver, fallbackImage);
|
|
267
|
+
const rewardAsset = assetHelper.resolveRewardAsset(reward, assetId);
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## 🧪 Testing
|
|
271
|
+
|
|
272
|
+
The SDK includes comprehensive test coverage:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# Run all tests
|
|
276
|
+
npm test
|
|
277
|
+
|
|
278
|
+
# Run unit tests
|
|
279
|
+
npm run test:unit
|
|
280
|
+
|
|
281
|
+
# Run integration tests
|
|
282
|
+
npm run test:integration
|
|
283
|
+
|
|
284
|
+
# Run e2e tests
|
|
285
|
+
npm run test:e2e
|
|
286
|
+
|
|
287
|
+
# Run with coverage
|
|
288
|
+
npm run test:coverage
|
|
289
|
+
|
|
290
|
+
# Watch mode
|
|
291
|
+
npm run test:watch
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## 🌍 Environments
|
|
295
|
+
|
|
296
|
+
The SDK supports multiple environments:
|
|
297
|
+
|
|
298
|
+
- **`test`** - Sandbox environment for development
|
|
299
|
+
- **`live`** - Production environment
|
|
300
|
+
- **`staging`** - Staging environment
|
|
301
|
+
- **`preview`** - Preview environment
|
|
302
|
+
- **`dev`** - Development environment
|
|
303
|
+
- **Custom URL** - Provide your own endpoint
|
|
304
|
+
|
|
305
|
+
## 📋 Requirements
|
|
306
|
+
|
|
307
|
+
- Node.js 16+
|
|
308
|
+
- TypeScript 4.5+ (if using TypeScript)
|
|
309
|
+
- Modern browser with EventSource support
|
|
310
|
+
|
|
311
|
+
## 🤝 Contributing
|
|
312
|
+
|
|
313
|
+
1. Fork the repository
|
|
314
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
315
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
316
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
317
|
+
5. Open a Pull Request
|
|
318
|
+
|
|
319
|
+
## 📄 License
|
|
320
|
+
|
|
321
|
+
This project is licensed under the AGPLv3 License - see the [LICENSE.md](LICENSE.md) file for details.
|
|
322
|
+
|
|
323
|
+
## 🔗 Links
|
|
324
|
+
|
|
325
|
+
- [GitLab Repository](https://gitlab.com/pixels-online-oss/pixels-buildon-client-js-sdk)
|
|
326
|
+
- [Issue Tracker](https://gitlab.com/pixels-online-oss/pixels-buildon-client-js-sdk/issues)
|
|
327
|
+
- [Pixels BuildOn Documentation](https://docs.pixels.xyz)
|
|
328
|
+
|
|
329
|
+
## 📞 Support
|
|
330
|
+
|
|
331
|
+
For support and questions:
|
|
332
|
+
|
|
333
|
+
- Create an issue on [GitLab](https://gitlab.com/pixels-online-oss/pixels-buildon-client-js-sdk/issues)
|
|
334
|
+
- Contact the Pixels team
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
Made with ❤️ by the Pixels team
|
|
@@ -3,8 +3,10 @@ import { OfferStore } from './OfferStore';
|
|
|
3
3
|
import { AssetHelper } from '../utils/assets';
|
|
4
4
|
import { OfferwallConfig } from '../types';
|
|
5
5
|
import { ConnectionState } from '../types/connection';
|
|
6
|
+
export declare const mapEnvToBuildOnApiUrl: (env: "test" | "live" | (string & {})) => "https://api.pixels.xyz" | "https://api.sandbox.pixels.xyz" | "https://api.staging.pixels.xyz" | "https://api.preview.pixels.xyz" | "https://api.dev.pixels.xyz";
|
|
6
7
|
export declare class OfferwallClient {
|
|
7
8
|
private config;
|
|
9
|
+
private endpoint;
|
|
8
10
|
private eventEmitter;
|
|
9
11
|
private sseConnection;
|
|
10
12
|
private offerStore;
|
package/dist/index.esm.js
CHANGED
|
@@ -344,6 +344,7 @@ class SSEConnection {
|
|
|
344
344
|
this.connectionState = ConnectionState.DISCONNECTED;
|
|
345
345
|
this.serverSuggestedRetryTime = null;
|
|
346
346
|
this.logger = createLogger(config, 'SSEConnection');
|
|
347
|
+
this.endpoint = mapEnvToBuildOnApiUrl(config.env);
|
|
347
348
|
}
|
|
348
349
|
/**
|
|
349
350
|
* Get current connection state
|
|
@@ -364,7 +365,7 @@ class SSEConnection {
|
|
|
364
365
|
previousState,
|
|
365
366
|
error,
|
|
366
367
|
attempt: this.reconnectAttempts,
|
|
367
|
-
maxAttempts: this.config.maxReconnectAttempts
|
|
368
|
+
maxAttempts: this.config.maxReconnectAttempts,
|
|
368
369
|
});
|
|
369
370
|
}
|
|
370
371
|
connect() {
|
|
@@ -384,13 +385,13 @@ class SSEConnection {
|
|
|
384
385
|
this.logger.log('Connecting to SSE endpoint...');
|
|
385
386
|
try {
|
|
386
387
|
// Create SSE URL
|
|
387
|
-
const url = new URL(this.
|
|
388
|
+
const url = new URL(this.endpoint + '/v1/sse/connect');
|
|
388
389
|
const token = await this.tokenManager.getTokenForConnection();
|
|
389
390
|
// Use CustomEventSource with Authorization Bearer header
|
|
390
391
|
this.eventSource = new CustomEventSource(url.toString(), {
|
|
391
392
|
headers: {
|
|
392
|
-
|
|
393
|
-
}
|
|
393
|
+
Authorization: `Bearer ${token}`,
|
|
394
|
+
},
|
|
394
395
|
});
|
|
395
396
|
// Listen for server-suggested retry time updates
|
|
396
397
|
this.eventSource.onRetryUpdate = (retryTime) => {
|
|
@@ -409,11 +410,14 @@ class SSEConnection {
|
|
|
409
410
|
this.logger.log('SSE connection error', error);
|
|
410
411
|
this.isConnecting = false;
|
|
411
412
|
// Check if it's an auth error
|
|
412
|
-
if (error?.detail?.isAuthError ||
|
|
413
|
+
if (error?.detail?.isAuthError ||
|
|
414
|
+
error?.message === 'jwt-expired' ||
|
|
415
|
+
error?.message === 'jwt-invalid') {
|
|
413
416
|
this.tokenManager.clearToken();
|
|
414
417
|
this.setConnectionState(ConnectionState.DISCONNECTED);
|
|
415
418
|
// Try to reconnect with fresh token if reconnect is enabled
|
|
416
|
-
if (this.config.reconnect &&
|
|
419
|
+
if (this.config.reconnect &&
|
|
420
|
+
this.reconnectAttempts < (this.config.maxReconnectAttempts || 5)) {
|
|
417
421
|
this.logger.log('JWT invalid/expired, attempting reconnect with fresh token');
|
|
418
422
|
this.handleReconnect();
|
|
419
423
|
resolve(); // Resolve instead of reject to allow reconnection
|
|
@@ -424,21 +428,22 @@ class SSEConnection {
|
|
|
424
428
|
return;
|
|
425
429
|
}
|
|
426
430
|
}
|
|
427
|
-
const errorMsg = this.eventSource?.getReadyState() === ReadyState.CLOSED
|
|
428
|
-
'Connection closed'
|
|
431
|
+
const errorMsg = this.eventSource?.getReadyState() === ReadyState.CLOSED
|
|
432
|
+
? 'Connection closed'
|
|
433
|
+
: 'Connection error';
|
|
429
434
|
const connectionError = new Error(errorMsg);
|
|
430
435
|
this.setConnectionState(ConnectionState.ERROR, connectionError);
|
|
431
436
|
if (this.eventSource?.getReadyState() === ReadyState.CLOSED) {
|
|
432
437
|
this.eventEmitter.emit(OfferEvent.CONNECTION_ERROR, {
|
|
433
438
|
error: connectionError,
|
|
434
|
-
timestamp: new Date()
|
|
439
|
+
timestamp: new Date(),
|
|
435
440
|
});
|
|
436
441
|
this.handleReconnect();
|
|
437
442
|
}
|
|
438
443
|
else {
|
|
439
444
|
this.eventEmitter.emit(OfferEvent.CONNECTION_ERROR, {
|
|
440
445
|
error: connectionError,
|
|
441
|
-
timestamp: new Date()
|
|
446
|
+
timestamp: new Date(),
|
|
442
447
|
});
|
|
443
448
|
reject(connectionError);
|
|
444
449
|
}
|
|
@@ -543,7 +548,7 @@ class SSEConnection {
|
|
|
543
548
|
this.logger.log('Error parsing SSE message:', error);
|
|
544
549
|
this.eventEmitter.emit(OfferEvent.ERROR, {
|
|
545
550
|
error: error,
|
|
546
|
-
context: 'sse_message_parse'
|
|
551
|
+
context: 'sse_message_parse',
|
|
547
552
|
});
|
|
548
553
|
}
|
|
549
554
|
}
|
|
@@ -558,7 +563,7 @@ class SSEConnection {
|
|
|
558
563
|
this.disconnect();
|
|
559
564
|
this.eventEmitter.emit(OfferEvent.DISCONNECTED, {
|
|
560
565
|
reason: 'max_reconnect_attempts',
|
|
561
|
-
timestamp: new Date()
|
|
566
|
+
timestamp: new Date(),
|
|
562
567
|
});
|
|
563
568
|
return;
|
|
564
569
|
}
|
|
@@ -587,7 +592,7 @@ class SSEConnection {
|
|
|
587
592
|
this.setConnectionState(ConnectionState.DISCONNECTED);
|
|
588
593
|
this.eventEmitter.emit(OfferEvent.DISCONNECTED, {
|
|
589
594
|
reason: 'manual',
|
|
590
|
-
timestamp: new Date()
|
|
595
|
+
timestamp: new Date(),
|
|
591
596
|
});
|
|
592
597
|
}
|
|
593
598
|
this.isConnecting = false;
|
|
@@ -837,18 +842,35 @@ class AssetHelper {
|
|
|
837
842
|
}
|
|
838
843
|
}
|
|
839
844
|
|
|
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
|
+
};
|
|
840
862
|
class OfferwallClient {
|
|
841
863
|
constructor(config) {
|
|
842
864
|
this.isInitializing = false;
|
|
843
865
|
this.config = {
|
|
844
|
-
endpoint: config.endpoint || 'https://api.buildon.pixels.xyz',
|
|
845
866
|
autoConnect: config.autoConnect ?? false,
|
|
846
867
|
reconnect: config.reconnect ?? true,
|
|
847
868
|
reconnectDelay: config.reconnectDelay ?? 1000,
|
|
848
869
|
maxReconnectAttempts: config.maxReconnectAttempts ?? 5,
|
|
849
870
|
debug: config.debug ?? false,
|
|
850
|
-
...config
|
|
871
|
+
...config,
|
|
851
872
|
};
|
|
873
|
+
this.endpoint = mapEnvToBuildOnApiUrl(config.env);
|
|
852
874
|
this.hooks = this.config.hooks || {};
|
|
853
875
|
this.logger = createLogger(this.config, 'OfferwallClient');
|
|
854
876
|
this.eventEmitter = new EventEmitter(this.config);
|
|
@@ -858,7 +880,7 @@ class OfferwallClient {
|
|
|
858
880
|
this.sseConnection = new SSEConnection(this.config, this.eventEmitter, this.tokenManager);
|
|
859
881
|
this.setupInternalListeners();
|
|
860
882
|
if (this.config.autoConnect) {
|
|
861
|
-
this.initialize().catch(err => {
|
|
883
|
+
this.initialize().catch((err) => {
|
|
862
884
|
this.logger.error('Auto-initialization failed:', err);
|
|
863
885
|
});
|
|
864
886
|
}
|
|
@@ -910,7 +932,7 @@ class OfferwallClient {
|
|
|
910
932
|
}
|
|
911
933
|
const token = await this.tokenManager.getTokenForConnection();
|
|
912
934
|
if (this.hooks.beforeConnect) {
|
|
913
|
-
await this.hooks.beforeConnect({ jwt: token, endpoint: this.
|
|
935
|
+
await this.hooks.beforeConnect({ jwt: token, endpoint: this.endpoint });
|
|
914
936
|
}
|
|
915
937
|
try {
|
|
916
938
|
await this.sseConnection.connect();
|
|
@@ -959,7 +981,7 @@ class OfferwallClient {
|
|
|
959
981
|
}
|
|
960
982
|
try {
|
|
961
983
|
const response = await this.claimOfferAPI(instanceId);
|
|
962
|
-
const updatedOffer = { ...offer, status: 'claimed'
|
|
984
|
+
const updatedOffer = { ...offer, status: 'claimed' };
|
|
963
985
|
this.offerStore.upsertOffer(updatedOffer);
|
|
964
986
|
this.eventEmitter.emit(OfferEvent.OFFER_CLAIMED, {
|
|
965
987
|
instanceId,
|
|
@@ -1023,11 +1045,11 @@ class OfferwallClient {
|
|
|
1023
1045
|
*/
|
|
1024
1046
|
async postWithAuth(endpoint, body, retry = false) {
|
|
1025
1047
|
const token = await this.tokenManager.getTokenForConnection();
|
|
1026
|
-
const response = await fetch(`${this.
|
|
1048
|
+
const response = await fetch(`${this.endpoint}${endpoint}`, {
|
|
1027
1049
|
method: 'POST',
|
|
1028
1050
|
headers: {
|
|
1029
|
-
|
|
1030
|
-
'Content-Type': 'application/json'
|
|
1051
|
+
Authorization: `Bearer ${token}`,
|
|
1052
|
+
'Content-Type': 'application/json',
|
|
1031
1053
|
},
|
|
1032
1054
|
body: body ? JSON.stringify(body) : undefined,
|
|
1033
1055
|
});
|
|
@@ -1045,7 +1067,10 @@ class OfferwallClient {
|
|
|
1045
1067
|
return response.json();
|
|
1046
1068
|
}
|
|
1047
1069
|
async claimOfferAPI(instanceId) {
|
|
1048
|
-
return this.postWithAuth('/client/reward/claim', {
|
|
1070
|
+
return this.postWithAuth('/v1/client/reward/claim', {
|
|
1071
|
+
instanceId,
|
|
1072
|
+
kind: 'offer',
|
|
1073
|
+
});
|
|
1049
1074
|
}
|
|
1050
1075
|
async refreshOffersAndSnapshot() {
|
|
1051
1076
|
try {
|
|
@@ -1061,7 +1086,9 @@ class OfferwallClient {
|
|
|
1061
1086
|
}
|
|
1062
1087
|
}
|
|
1063
1088
|
async getOffersAndSnapshot() {
|
|
1064
|
-
const data = await this.postWithAuth('/client/player/campaigns', {
|
|
1089
|
+
const data = await this.postWithAuth('/v1/client/player/campaigns', {
|
|
1090
|
+
viewingCampaigns: true,
|
|
1091
|
+
});
|
|
1065
1092
|
if (!data.offers || !Array.isArray(data.offers)) {
|
|
1066
1093
|
throw new Error('No offers returned from offers endpoint');
|
|
1067
1094
|
}
|
|
@@ -1071,7 +1098,7 @@ class OfferwallClient {
|
|
|
1071
1098
|
return data;
|
|
1072
1099
|
}
|
|
1073
1100
|
async getAuthLinkToken() {
|
|
1074
|
-
const data = await this.postWithAuth('/auth/one_time_token/generate');
|
|
1101
|
+
const data = await this.postWithAuth('/v1/auth/one_time_token/generate');
|
|
1075
1102
|
if (!data.token) {
|
|
1076
1103
|
throw new Error('No token returned from auth link endpoint');
|
|
1077
1104
|
}
|