playe-developer-sdk 1.0.3 → 1.0.4
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 +431 -437
- package/dist/index.cjs.js +211 -264
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -32
- package/dist/index.esm.js +212 -263
- package/dist/index.esm.js.map +1 -1
- package/dist/playe-sdk.umd.js +211 -264
- package/dist/playe-sdk.umd.js.map +1 -1
- package/dist/playe-sdk.umd.min.js +1 -1
- package/dist/playe-sdk.umd.min.js.map +1 -1
- package/examples/basic-usage.ts +5 -6
- package/examples/browser-example.html +2 -10
- package/examples/flappy-bird.html +907 -0
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -1,437 +1,431 @@
|
|
|
1
|
-
# Playe Developer SDK
|
|
2
|
-
|
|
3
|
-
A comprehensive browser-based SDK for integrating games with the Playe platform. This SDK provides easy-to-use APIs for game session management, campaign integration, leaderboards, and anti-cheat validation.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- 🎮 **Game Session Management** - Initialize, start, update, and complete game sessions
|
|
8
|
-
- 🛡️ **Integrity Verification** - Built-in session integrity with cryptographic hashing and validation
|
|
9
|
-
- 🏆 **Campaign Integration** - Access campaign information, leaderboards, and player attempts
|
|
10
|
-
- 🔄 **Anti-Cheat Protection** - Advanced validation, heartbeat mechanisms, and session monitoring
|
|
11
|
-
- 📱 **Device Detection** - Automatic device information and fingerprinting
|
|
12
|
-
- 🔧 **Developer Tools** - Test game sessions and comprehensive debugging utilities
|
|
13
|
-
- 📊 **Real-time Updates** - Progress tracking and live leaderboards
|
|
14
|
-
- ⚡ **Browser Optimized** - Lightweight and fast for web games with automatic retry logic
|
|
15
|
-
|
|
16
|
-
## Installation
|
|
17
|
-
|
|
18
|
-
### NPM (Recommended)
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
npm install playe-developer-sdk
|
|
22
|
-
# or
|
|
23
|
-
yarn add playe-developer-sdk
|
|
24
|
-
# or
|
|
25
|
-
pnpm add playe-developer-sdk
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### CDN (No build tools required)
|
|
29
|
-
|
|
30
|
-
```html
|
|
31
|
-
<!-- For production -->
|
|
32
|
-
<script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
33
|
-
|
|
34
|
-
<!-- Alternative CDN -->
|
|
35
|
-
<script src="https://cdn.jsdelivr.net/npm/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Workspace (Internal development)
|
|
39
|
-
|
|
40
|
-
```json
|
|
41
|
-
{
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"@workspace/playe-developer-sdk": "workspace:*"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Quick Start
|
|
49
|
-
|
|
50
|
-
### NPM Usage
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
import { createPlayeSDK } from "playe-developer-sdk";
|
|
54
|
-
|
|
55
|
-
// Initialize the SDK
|
|
56
|
-
const sdk = createPlayeSDK({
|
|
57
|
-
apiBaseUrl: "https://api.playe.com",
|
|
58
|
-
apiKey: "your-api-key",
|
|
59
|
-
enableDebugMode: true, // Enable for development
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Initialize a game session (gets sessionId from URL query parameter)
|
|
63
|
-
const session = await sdk.initializeGameSession();
|
|
64
|
-
|
|
65
|
-
console.log("Game session initialized:", {
|
|
66
|
-
sessionId: session.sessionId,
|
|
67
|
-
campaignId: session.campaign.id,
|
|
68
|
-
playerId: session.player.id,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Start the game
|
|
72
|
-
await sdk.startGameSession({
|
|
73
|
-
difficulty: "normal",
|
|
74
|
-
mode: "classic",
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// Update progress during gameplay (includes automatic integrity verification)
|
|
78
|
-
await sdk.updateGameProgress({
|
|
79
|
-
currentScore: 1500,
|
|
80
|
-
elapsedTime: 120, // seconds
|
|
81
|
-
gameState: {
|
|
82
|
-
level: 3,
|
|
83
|
-
lives: 2,
|
|
84
|
-
powerUps: ["speed", "shield"],
|
|
85
|
-
},
|
|
86
|
-
achievements: [
|
|
87
|
-
{
|
|
88
|
-
id: "level-3",
|
|
89
|
-
name: "Level 3 Complete",
|
|
90
|
-
unlockedAt: new Date().toISOString(),
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// Complete the game (includes integrity verification)
|
|
96
|
-
const result = await sdk.completeGame({
|
|
97
|
-
finalScore: 2500,
|
|
98
|
-
validationChecksum: "client-checksum",
|
|
99
|
-
gameMetrics: {
|
|
100
|
-
totalPlayTime: 300,
|
|
101
|
-
actionsPerformed: 150,
|
|
102
|
-
powerUpsUsed: 5,
|
|
103
|
-
levelsCompleted: 5,
|
|
104
|
-
},
|
|
105
|
-
finalGameState: {
|
|
106
|
-
level: 5,
|
|
107
|
-
finalLives: 1,
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
console.log("Game completed!", {
|
|
112
|
-
isWinner: result.isWinner,
|
|
113
|
-
finalRank: result.finalRank,
|
|
114
|
-
prizeAmount: result.prizeAmount,
|
|
115
|
-
});
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### CDN Usage
|
|
119
|
-
|
|
120
|
-
```html
|
|
121
|
-
<script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
122
|
-
<script>
|
|
123
|
-
// SDK is available as global PlayeSDK
|
|
124
|
-
const sdk = PlayeSDK.createPlayeSDK({
|
|
125
|
-
apiBaseUrl: 'https://api.playe.com',
|
|
126
|
-
apiKey: 'your-api-key',
|
|
127
|
-
enableDebugMode: true,
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// All utilities are available
|
|
131
|
-
const fingerprint = PlayeSDK.DeviceUtils.generateFingerprint();
|
|
132
|
-
|
|
133
|
-
// Same API as NPM version
|
|
134
|
-
const session = await sdk.initializeGameSession(); // Gets sessionId from URL
|
|
135
|
-
|
|
136
|
-
console.log('Session initialized:', session.sessionId);
|
|
137
|
-
</script>
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## API Reference
|
|
141
|
-
|
|
142
|
-
### SDK Configuration
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
interface SDKConfig {
|
|
146
|
-
apiBaseUrl: string; // Required: API base URL
|
|
147
|
-
apiKey?: string; // Optional: API key for authentication
|
|
148
|
-
enableDebugMode?: boolean; // Optional: Enable debug logging
|
|
149
|
-
retryAttempts?: number; // Optional: Number of retry attempts (default: 3)
|
|
150
|
-
timeoutMs?: number; // Optional: Request timeout in ms (default: 30000)
|
|
151
|
-
enableOfflineMode?: boolean; // Optional: Enable offline mode (default: false)
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Core Methods
|
|
156
|
-
|
|
157
|
-
#### Game Session Management
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
// Initialize game session (gets sessionId from URL query parameter)
|
|
161
|
-
const session = await sdk.initializeGameSession(): Promise<GameSessionResponse>;
|
|
162
|
-
|
|
163
|
-
// Start the game session
|
|
164
|
-
await sdk.startGameSession(config?: Record<string, any>): Promise<GameSessionResponse>;
|
|
165
|
-
|
|
166
|
-
// Update game progress with integrity verification
|
|
167
|
-
await sdk.updateGameProgress({
|
|
168
|
-
currentScore: number;
|
|
169
|
-
gameState?: Record<string, any>; // Automatically hashed for integrity
|
|
170
|
-
elapsedTime: number;
|
|
171
|
-
achievements?: Achievement[];
|
|
172
|
-
clientTimestamp?: string;
|
|
173
|
-
}): Promise<ProgressUpdateResponse>;
|
|
174
|
-
|
|
175
|
-
// Complete the game with integrity verification
|
|
176
|
-
await sdk.completeGame({
|
|
177
|
-
finalScore: number;
|
|
178
|
-
validationChecksum: string;
|
|
179
|
-
gameMetrics?: GameMetrics;
|
|
180
|
-
finalGameState?: Record<string, any>; // Automatically hashed for integrity
|
|
181
|
-
}): Promise<GameCompletionResponse>;
|
|
182
|
-
|
|
183
|
-
// Abandon the game
|
|
184
|
-
await sdk.abandonGame(reason?: string, lastKnownScore?: number): Promise<AbandonGameResponse>;
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
#### Campaign Information
|
|
188
|
-
|
|
189
|
-
```typescript
|
|
190
|
-
// Get campaign status
|
|
191
|
-
await sdk.getCampaignStatus(campaignId: string, playerId?: string): Promise<CampaignStatusResponse>;
|
|
192
|
-
|
|
193
|
-
// Get leaderboard
|
|
194
|
-
await sdk.getLeaderboard(campaignId: string, limit?: number, playerId?: string): Promise<LeaderboardResponse>;
|
|
195
|
-
|
|
196
|
-
// Get player attempts
|
|
197
|
-
await sdk.getPlayerAttempts(campaignId: string, playerId: string): Promise<PlayerAttemptsResponse>;
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
#### Validation & Anti-Cheat
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
// Validate game session with integrity verification
|
|
204
|
-
await sdk.validateGameSession({
|
|
205
|
-
clientChecksum: string;
|
|
206
|
-
stateSnapshot?: Record<string, unknown>; // Automatically hashed
|
|
207
|
-
timingData?: unknown;
|
|
208
|
-
behaviorMetrics?: unknown;
|
|
209
|
-
}): Promise<ValidationResponse>;
|
|
210
|
-
|
|
211
|
-
// Send heartbeat (usually handled automatically)
|
|
212
|
-
await sdk.sendHeartbeat(currentScore?: number): Promise<HeartbeatResponse>;
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
#### Developer Tools
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
// Create test game session for development
|
|
219
|
-
await sdk.createTestGameSession(testConfig?: Record<string, any>): Promise<TestGameResponse>;
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Utility Methods
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// Test SDK functionality
|
|
226
|
-
sdk.test('Custom test message'): void;
|
|
227
|
-
|
|
228
|
-
// Check if running in demo mode
|
|
229
|
-
const isDemoMode = sdk.isDemo(): boolean;
|
|
230
|
-
|
|
231
|
-
// Game lifecycle events
|
|
232
|
-
sdk.gameLoadingStart(): void; // Emit loading start event
|
|
233
|
-
sdk.gameLoadingFinished(): void; // Emit loading finished event
|
|
234
|
-
sdk.gamePlayStop(): void; // Stop heartbeat and emit stop event
|
|
235
|
-
|
|
236
|
-
// Clean up resources
|
|
237
|
-
sdk.destroy(): void; // Clean up session artifacts and stop heartbeat
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Integrity Verification Utilities
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
import { canonicalStringify, sha256Hex
|
|
244
|
-
|
|
245
|
-
// Canonical JSON stringification (deterministic)
|
|
246
|
-
const canonical = canonicalStringify({ b: 1, a: 2 }); // '{"a":2,"b":1}'
|
|
247
|
-
|
|
248
|
-
// SHA-256 hashing
|
|
249
|
-
const hash = await sha256Hex("data to hash");
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
//
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
//
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
if (error instanceof
|
|
292
|
-
console.error("
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
-
|
|
415
|
-
-
|
|
416
|
-
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
MIT License - see LICENSE file for details.
|
|
434
|
-
|
|
435
|
-
## Support
|
|
436
|
-
|
|
437
|
-
For support, please contact the Playe development team or create an issue in the repository.
|
|
1
|
+
# Playe Developer SDK
|
|
2
|
+
|
|
3
|
+
A comprehensive browser-based SDK for integrating games with the Playe platform. This SDK provides easy-to-use APIs for game session management, campaign integration, leaderboards, and anti-cheat validation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎮 **Game Session Management** - Initialize, start, update, and complete game sessions
|
|
8
|
+
- 🛡️ **Integrity Verification** - Built-in session integrity with cryptographic hashing and validation
|
|
9
|
+
- 🏆 **Campaign Integration** - Access campaign information, leaderboards, and player attempts
|
|
10
|
+
- 🔄 **Anti-Cheat Protection** - Advanced validation, heartbeat mechanisms, and session monitoring
|
|
11
|
+
- 📱 **Device Detection** - Automatic device information and fingerprinting
|
|
12
|
+
- 🔧 **Developer Tools** - Test game sessions and comprehensive debugging utilities
|
|
13
|
+
- 📊 **Real-time Updates** - Progress tracking and live leaderboards
|
|
14
|
+
- ⚡ **Browser Optimized** - Lightweight and fast for web games with automatic retry logic
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
### NPM (Recommended)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install playe-developer-sdk
|
|
22
|
+
# or
|
|
23
|
+
yarn add playe-developer-sdk
|
|
24
|
+
# or
|
|
25
|
+
pnpm add playe-developer-sdk
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### CDN (No build tools required)
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<!-- For production -->
|
|
32
|
+
<script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
33
|
+
|
|
34
|
+
<!-- Alternative CDN -->
|
|
35
|
+
<script src="https://cdn.jsdelivr.net/npm/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Workspace (Internal development)
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@workspace/playe-developer-sdk": "workspace:*"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
### NPM Usage
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { createPlayeSDK } from "playe-developer-sdk";
|
|
54
|
+
|
|
55
|
+
// Initialize the SDK
|
|
56
|
+
const sdk = createPlayeSDK({
|
|
57
|
+
apiBaseUrl: "https://api.playe.com",
|
|
58
|
+
apiKey: "your-api-key",
|
|
59
|
+
enableDebugMode: true, // Enable for development
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Initialize a game session (gets sessionId from URL query parameter)
|
|
63
|
+
const session = await sdk.initializeGameSession();
|
|
64
|
+
|
|
65
|
+
console.log("Game session initialized:", {
|
|
66
|
+
sessionId: session.sessionId,
|
|
67
|
+
campaignId: session.campaign.id,
|
|
68
|
+
playerId: session.player.id,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Start the game
|
|
72
|
+
await sdk.startGameSession({
|
|
73
|
+
difficulty: "normal",
|
|
74
|
+
mode: "classic",
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Update progress during gameplay (includes automatic integrity verification)
|
|
78
|
+
await sdk.updateGameProgress({
|
|
79
|
+
currentScore: 1500,
|
|
80
|
+
elapsedTime: 120, // seconds
|
|
81
|
+
gameState: {
|
|
82
|
+
level: 3,
|
|
83
|
+
lives: 2,
|
|
84
|
+
powerUps: ["speed", "shield"],
|
|
85
|
+
},
|
|
86
|
+
achievements: [
|
|
87
|
+
{
|
|
88
|
+
id: "level-3",
|
|
89
|
+
name: "Level 3 Complete",
|
|
90
|
+
unlockedAt: new Date().toISOString(),
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Complete the game (includes integrity verification)
|
|
96
|
+
const result = await sdk.completeGame({
|
|
97
|
+
finalScore: 2500,
|
|
98
|
+
validationChecksum: "client-checksum",
|
|
99
|
+
gameMetrics: {
|
|
100
|
+
totalPlayTime: 300,
|
|
101
|
+
actionsPerformed: 150,
|
|
102
|
+
powerUpsUsed: 5,
|
|
103
|
+
levelsCompleted: 5,
|
|
104
|
+
},
|
|
105
|
+
finalGameState: {
|
|
106
|
+
level: 5,
|
|
107
|
+
finalLives: 1,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
console.log("Game completed!", {
|
|
112
|
+
isWinner: result.isWinner,
|
|
113
|
+
finalRank: result.finalRank,
|
|
114
|
+
prizeAmount: result.prizeAmount,
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### CDN Usage
|
|
119
|
+
|
|
120
|
+
```html
|
|
121
|
+
<script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
|
|
122
|
+
<script>
|
|
123
|
+
// SDK is available as global PlayeSDK
|
|
124
|
+
const sdk = PlayeSDK.createPlayeSDK({
|
|
125
|
+
apiBaseUrl: 'https://api.playe.com',
|
|
126
|
+
apiKey: 'your-api-key',
|
|
127
|
+
enableDebugMode: true,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// All utilities are available
|
|
131
|
+
const fingerprint = PlayeSDK.DeviceUtils.generateFingerprint();
|
|
132
|
+
|
|
133
|
+
// Same API as NPM version
|
|
134
|
+
const session = await sdk.initializeGameSession(); // Gets sessionId from URL
|
|
135
|
+
|
|
136
|
+
console.log('Session initialized:', session.sessionId);
|
|
137
|
+
</script>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## API Reference
|
|
141
|
+
|
|
142
|
+
### SDK Configuration
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
interface SDKConfig {
|
|
146
|
+
apiBaseUrl: string; // Required: API base URL
|
|
147
|
+
apiKey?: string; // Optional: API key for authentication
|
|
148
|
+
enableDebugMode?: boolean; // Optional: Enable debug logging
|
|
149
|
+
retryAttempts?: number; // Optional: Number of retry attempts (default: 3)
|
|
150
|
+
timeoutMs?: number; // Optional: Request timeout in ms (default: 30000)
|
|
151
|
+
enableOfflineMode?: boolean; // Optional: Enable offline mode (default: false)
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Core Methods
|
|
156
|
+
|
|
157
|
+
#### Game Session Management
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// Initialize game session (gets sessionId from URL query parameter)
|
|
161
|
+
const session = await sdk.initializeGameSession(): Promise<GameSessionResponse>;
|
|
162
|
+
|
|
163
|
+
// Start the game session
|
|
164
|
+
await sdk.startGameSession(config?: Record<string, any>): Promise<GameSessionResponse>;
|
|
165
|
+
|
|
166
|
+
// Update game progress with integrity verification
|
|
167
|
+
await sdk.updateGameProgress({
|
|
168
|
+
currentScore: number;
|
|
169
|
+
gameState?: Record<string, any>; // Automatically hashed for integrity
|
|
170
|
+
elapsedTime: number;
|
|
171
|
+
achievements?: Achievement[];
|
|
172
|
+
clientTimestamp?: string;
|
|
173
|
+
}): Promise<ProgressUpdateResponse>;
|
|
174
|
+
|
|
175
|
+
// Complete the game with integrity verification
|
|
176
|
+
await sdk.completeGame({
|
|
177
|
+
finalScore: number;
|
|
178
|
+
validationChecksum: string;
|
|
179
|
+
gameMetrics?: GameMetrics;
|
|
180
|
+
finalGameState?: Record<string, any>; // Automatically hashed for integrity
|
|
181
|
+
}): Promise<GameCompletionResponse>;
|
|
182
|
+
|
|
183
|
+
// Abandon the game
|
|
184
|
+
await sdk.abandonGame(reason?: string, lastKnownScore?: number): Promise<AbandonGameResponse>;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### Campaign Information
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// Get campaign status
|
|
191
|
+
await sdk.getCampaignStatus(campaignId: string, playerId?: string): Promise<CampaignStatusResponse>;
|
|
192
|
+
|
|
193
|
+
// Get leaderboard
|
|
194
|
+
await sdk.getLeaderboard(campaignId: string, limit?: number, playerId?: string): Promise<LeaderboardResponse>;
|
|
195
|
+
|
|
196
|
+
// Get player attempts
|
|
197
|
+
await sdk.getPlayerAttempts(campaignId: string, playerId: string): Promise<PlayerAttemptsResponse>;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### Validation & Anti-Cheat
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Validate game session with integrity verification
|
|
204
|
+
await sdk.validateGameSession({
|
|
205
|
+
clientChecksum: string;
|
|
206
|
+
stateSnapshot?: Record<string, unknown>; // Automatically hashed
|
|
207
|
+
timingData?: unknown;
|
|
208
|
+
behaviorMetrics?: unknown;
|
|
209
|
+
}): Promise<ValidationResponse>;
|
|
210
|
+
|
|
211
|
+
// Send heartbeat (usually handled automatically)
|
|
212
|
+
await sdk.sendHeartbeat(currentScore?: number): Promise<HeartbeatResponse>;
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### Developer Tools
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Create test game session for development
|
|
219
|
+
await sdk.createTestGameSession(testConfig?: Record<string, any>): Promise<TestGameResponse>;
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Utility Methods
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// Test SDK functionality
|
|
226
|
+
sdk.test('Custom test message'): void;
|
|
227
|
+
|
|
228
|
+
// Check if running in demo mode
|
|
229
|
+
const isDemoMode = sdk.isDemo(): boolean;
|
|
230
|
+
|
|
231
|
+
// Game lifecycle events
|
|
232
|
+
sdk.gameLoadingStart(): void; // Emit loading start event
|
|
233
|
+
sdk.gameLoadingFinished(): void; // Emit loading finished event
|
|
234
|
+
sdk.gamePlayStop(): void; // Stop heartbeat and emit stop event
|
|
235
|
+
|
|
236
|
+
// Clean up resources
|
|
237
|
+
sdk.destroy(): void; // Clean up session artifacts and stop heartbeat
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Integrity Verification Utilities
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { canonicalStringify, sha256Hex } from "playe-developer-sdk";
|
|
244
|
+
|
|
245
|
+
// Canonical JSON stringification (deterministic)
|
|
246
|
+
const canonical = canonicalStringify({ b: 1, a: 2 }); // '{"a":2,"b":1}'
|
|
247
|
+
|
|
248
|
+
// SHA-256 hashing
|
|
249
|
+
const hash = await sha256Hex("data to hash");
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Device Utilities
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { DeviceUtils } from "@workspace/playe-developer-sdk";
|
|
256
|
+
|
|
257
|
+
// Get device information
|
|
258
|
+
const deviceInfo = DeviceUtils.getDeviceInfo();
|
|
259
|
+
|
|
260
|
+
// Get geolocation
|
|
261
|
+
const location = await DeviceUtils.getGeolocationData();
|
|
262
|
+
|
|
263
|
+
// Generate fingerprint
|
|
264
|
+
const fingerprint = DeviceUtils.generateFingerprint();
|
|
265
|
+
|
|
266
|
+
// Check browser support
|
|
267
|
+
const isSupported = DeviceUtils.isBrowser();
|
|
268
|
+
const features = DeviceUtils.getFeatureSupport();
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Error Handling
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import {
|
|
275
|
+
PlayeSDKError,
|
|
276
|
+
ValidationError,
|
|
277
|
+
NetworkError,
|
|
278
|
+
AuthenticationError,
|
|
279
|
+
GameSessionError,
|
|
280
|
+
} from "@workspace/playe-developer-sdk";
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
await sdk.initializeGameSession(params);
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (error instanceof ValidationError) {
|
|
286
|
+
console.error("Validation failed:", error.message);
|
|
287
|
+
} else if (error instanceof NetworkError) {
|
|
288
|
+
console.error("Network error:", error.message);
|
|
289
|
+
} else if (error instanceof AuthenticationError) {
|
|
290
|
+
console.error("Authentication failed:", error.message);
|
|
291
|
+
} else if (error instanceof PlayeSDKError) {
|
|
292
|
+
console.error("SDK error:", error.toJSON());
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Campaign Styles
|
|
298
|
+
|
|
299
|
+
The SDK supports different campaign styles:
|
|
300
|
+
|
|
301
|
+
- **SingleWinner**: One winner takes all
|
|
302
|
+
- **FixedPool**: Fixed number of winners
|
|
303
|
+
- **Leaderboard**: Winners based on ranking
|
|
304
|
+
- **RewardForAll**: Everyone gets rewards
|
|
305
|
+
|
|
306
|
+
## Events
|
|
307
|
+
|
|
308
|
+
The SDK emits custom browser events for tracking:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
// Listen for SDK events
|
|
312
|
+
window.addEventListener("playe:game-loading-start", () => {
|
|
313
|
+
console.log("Game loading started");
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
window.addEventListener("playe:game-loading-finished", () => {
|
|
317
|
+
console.log("Game loading finished");
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
window.addEventListener("playe:game-play-stop", () => {
|
|
321
|
+
console.log("Game play stopped");
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Integrity Verification
|
|
326
|
+
|
|
327
|
+
The SDK includes built-in integrity verification to prevent cheating and ensure fair play:
|
|
328
|
+
|
|
329
|
+
### Automatic Features
|
|
330
|
+
|
|
331
|
+
- **Session Integrity**: Each game session includes a unique session token and salt
|
|
332
|
+
- **Game State Hashing**: Game states are automatically hashed using SHA-256 with session salt
|
|
333
|
+
- **Integrity Headers**: All authenticated requests include cryptographic integrity headers
|
|
334
|
+
- **Retry Logic**: Failed requests due to integrity issues are automatically retried with fresh headers
|
|
335
|
+
|
|
336
|
+
### How It Works
|
|
337
|
+
|
|
338
|
+
1. **Session Initialization**: SDK receives session token and salt from server
|
|
339
|
+
2. **State Hashing**: Game states are canonicalized and hashed with session salt
|
|
340
|
+
3. **Request Signing**: Integrity headers are built with timestamp, nonce, and session token
|
|
341
|
+
4. **Server Validation**: Server verifies hashes and headers to detect tampering
|
|
342
|
+
|
|
343
|
+
### Manual Verification (Advanced)
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
// Manually validate game session
|
|
347
|
+
const validation = await sdk.validateGameSession({
|
|
348
|
+
clientChecksum: "calculated-checksum",
|
|
349
|
+
stateSnapshot: currentGameState,
|
|
350
|
+
timingData: { avgResponseTime: 250 },
|
|
351
|
+
behaviorMetrics: { clicksPerSecond: 5.2 },
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
if (!validation.isValid) {
|
|
355
|
+
console.log("Validation issues:", validation.validationIssues);
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Development
|
|
360
|
+
|
|
361
|
+
### Testing
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// Create a test game session for development
|
|
365
|
+
const testSession = await sdk.createTestGameSession({
|
|
366
|
+
testConfig: {
|
|
367
|
+
mockCampaign: true,
|
|
368
|
+
mockPlayers: 10,
|
|
369
|
+
testScenario: "leaderboard",
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
console.log("Test session created:", testSession.testSessionId);
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Debug Mode
|
|
377
|
+
|
|
378
|
+
Enable debug mode to see detailed logging:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
const sdk = createPlayeSDK({
|
|
382
|
+
apiBaseUrl: "https://api.playe.com",
|
|
383
|
+
enableDebugMode: true, // This will log all API calls, integrity operations, and responses
|
|
384
|
+
});
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### URL Requirements
|
|
388
|
+
|
|
389
|
+
For `initializeGameSession()` to work, the page URL must include a `sessionId` query parameter:
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
https://yourgame.com/play?sessionId=abc123-def456-ghi789
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
The SDK will automatically extract this sessionId and initialize the session.
|
|
396
|
+
|
|
397
|
+
## Browser Compatibility
|
|
398
|
+
|
|
399
|
+
- Chrome 60+
|
|
400
|
+
- Firefox 55+
|
|
401
|
+
- Safari 12+
|
|
402
|
+
- Edge 79+
|
|
403
|
+
|
|
404
|
+
## Distribution
|
|
405
|
+
|
|
406
|
+
The SDK is available in multiple formats:
|
|
407
|
+
|
|
408
|
+
- **NPM Package**: `npm install playe-developer-sdk`
|
|
409
|
+
- **CDN (UMD)**: `https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js`
|
|
410
|
+
- **Workspace**: `@workspace/playe-developer-sdk` (internal development)
|
|
411
|
+
|
|
412
|
+
### Bundle Sizes
|
|
413
|
+
|
|
414
|
+
- ESM: 27.3KB (8KB gzipped)
|
|
415
|
+
- CommonJS: 27.6KB (8KB gzipped)
|
|
416
|
+
- UMD: 30.8KB (9KB gzipped)
|
|
417
|
+
- UMD Minified: 13.7KB (5KB gzipped)
|
|
418
|
+
|
|
419
|
+
For detailed distribution information, see [DISTRIBUTION.md](./DISTRIBUTION.md).
|
|
420
|
+
|
|
421
|
+
## TypeScript Support
|
|
422
|
+
|
|
423
|
+
This SDK is written in TypeScript and includes full type definitions. No additional `@types` packages are needed.
|
|
424
|
+
|
|
425
|
+
## License
|
|
426
|
+
|
|
427
|
+
MIT License - see LICENSE file for details.
|
|
428
|
+
|
|
429
|
+
## Support
|
|
430
|
+
|
|
431
|
+
For support, please contact the Playe development team or create an issue in the repository.
|