playe-developer-sdk 1.0.10 → 1.0.13

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 CHANGED
@@ -1,629 +1,629 @@
1
- # 🎮 Playe Developer SDK
2
-
3
- [![Version](https://img.shields.io/npm/v/playe-developer-sdk)](https://npmjs.com/package/playe-developer-sdk)
4
- [![License](https://img.shields.io/npm/l/playe-developer-sdk)](https://github.com/playe/playe/blob/main/LICENSE)
5
- [![Bundle Size](https://img.shields.io/bundlephobia/min/playe-developer-sdk)](https://bundlephobia.com/package/playe-developer-sdk)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
7
-
8
- A browser-based SDK for integrating games with the Playe platform. Provides game session management, campaign integration, leaderboards, and integrity verification.
9
-
10
- ## ✨ Features
11
-
12
- - 🎮 **Game Session Management** - Initialize, start, update, and complete game sessions
13
- - 🛡️ **Integrity Verification** - Built-in session integrity with cryptographic hashing
14
- - 🏆 **Campaign Integration** - Access campaign information, leaderboards, and player attempts
15
- - 🔄 **Anti-Cheat Protection** - Advanced validation, heartbeat mechanisms, and session monitoring
16
- - 📱 **Device Detection** - Automatic device information and fingerprinting
17
- - 🔧 **Developer Tools** - Test game sessions and debugging utilities
18
- - 📊 **Real-time Updates** - Progress tracking and live leaderboards
19
- - ⚡ **Browser Optimized** - Lightweight and fast for web games with automatic retry logic
20
-
21
- ## 🚀 Installation
22
-
23
- ### NPM
24
-
25
- ```bash
26
- npm install playe-developer-sdk
27
- # or
28
- yarn add playe-developer-sdk
29
- # or
30
- pnpm add playe-developer-sdk
31
- ```
32
-
33
- ### CDN
34
-
35
- ```html
36
- <script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
37
- ```
38
-
39
- ### Workspace
40
-
41
- ```json
42
- {
43
- "dependencies": {
44
- "@workspace/playe-developer-sdk": "workspace:*"
45
- }
46
- }
47
- ```
48
-
49
- ## 📖 Quick Start
50
-
51
- ### NPM Usage
52
-
53
- ```typescript
54
- import { createPlayeSDK } from "playe-developer-sdk";
55
-
56
- // Initialize SDK
57
- const sdk = createPlayeSDK({
58
- apiBaseUrl: "https://api.playe.com",
59
- apiKey: "your-api-key",
60
- enableDebugMode: true,
61
- });
62
-
63
- // Initialize game session (gets sessionId from URL)
64
- const session = await sdk.initializeGameSession();
65
-
66
- // Start game
67
- await sdk.startGameSession({
68
- difficulty: "normal",
69
- mode: "classic",
70
- });
71
-
72
- // Update progress
73
- await sdk.updateGameProgress({
74
- currentScore: 1500,
75
- elapsedTime: 120,
76
- gameState: {
77
- level: 3,
78
- lives: 2,
79
- powerUps: ["speed", "shield"],
80
- },
81
- achievements: [
82
- {
83
- id: "level-3",
84
- name: "Level 3 Complete",
85
- unlockedAt: new Date().toISOString(),
86
- },
87
- ],
88
- });
89
-
90
- // Complete game
91
- const result = await sdk.completeGame({
92
- finalScore: 2500,
93
- validationChecksum: "client-checksum",
94
- gameMetrics: {
95
- totalPlayTime: 300,
96
- actionsPerformed: 150,
97
- powerUpsUsed: 5,
98
- levelsCompleted: 5,
99
- },
100
- finalGameState: {
101
- level: 5,
102
- finalLives: 1,
103
- },
104
- });
105
- ```
106
-
107
- ### CDN Usage
108
-
109
- ```html
110
- <script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
111
- <script>
112
- const sdk = PlayeSDK.createPlayeSDK({
113
- apiBaseUrl: 'https://api.playe.com',
114
- apiKey: 'your-api-key',
115
- enableDebugMode: true,
116
- });
117
-
118
- const session = await sdk.initializeGameSession();
119
- console.log('Session initialized:', session.sessionId);
120
- </script>
121
- ```
122
-
123
- ## 📋 Table of Contents
124
-
125
- - [🎮 Playe Developer SDK](#-playe-developer-sdk)
126
- - [✨ Features](#-features)
127
- - [🚀 Installation](#-installation)
128
- - [📖 Quick Start](#-quick-start)
129
- - [📋 Table of Contents](#-table-of-contents)
130
- - [🔧 API Reference](#-api-reference)
131
- - [🔒 Security & Integrity](#-security--integrity)
132
- - [🧪 Testing & Development](#-testing--development)
133
- - [🚨 Error Handling](#-error-handling)
134
- - [📚 Examples](#-examples)
135
- - [🔄 Migration Guide](#-migration-guide)
136
- - [🔧 Troubleshooting](#-troubleshooting)
137
- - [🤝 Contributing](#-contributing)
138
- - [📄 License](#-license)
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
- // Returns: { sessionId, campaignId, gameId, status, campaign, player, createdAt, expiresAt }
163
-
164
- // Start game session
165
- await sdk.startGameSession(config?: Record<string, any>): Promise<GameSessionResponse>;
166
- // Returns: { sessionId, status, startTime }
167
-
168
- // Update game progress with integrity verification
169
- await sdk.updateGameProgress({
170
- currentScore: number;
171
- gameState?: Record<string, any>; // Automatically hashed for integrity
172
- elapsedTime: number;
173
- achievements?: Achievement[];
174
- clientTimestamp?: string;
175
- }): Promise<ProgressUpdateResponse>;
176
- // Returns: { isValid, validationMessage, currentRank, isLeading, campaignStatus, warnings }
177
-
178
- // Complete game with integrity verification
179
- await sdk.completeGame({
180
- finalScore: number;
181
- validationChecksum: string;
182
- gameMetrics?: GameMetrics;
183
- finalGameState?: Record<string, any>; // Automatically hashed for integrity
184
- }): Promise<GameCompletionResponse>;
185
- // Returns: { isWinner, prizeAmount, prizeType, finalRank, totalParticipants, winnerDetails, reward, campaignResult }
186
-
187
- // Abandon game
188
- await sdk.abandonGame(reason?: string, lastKnownScore?: number): Promise<AbandonGameResponse>;
189
- // Returns: { success, message, gamepassRefunded, abandonedAt }
190
- ```
191
-
192
- #### Campaign Information
193
-
194
- ```typescript
195
- // Get campaign status
196
- await sdk.getCampaignStatus(campaignId: string, playerId?: string): Promise<CampaignStatusResponse>;
197
- // Returns: { campaignId, status, campaignStyle, remainingGamepasses, totalParticipants,
198
- // totalPrizePool, endDate, playerStatus, topPlayers, prizeBreakdown }
199
-
200
- // Get leaderboard
201
- await sdk.getLeaderboard(campaignId: string, limit?: number, playerId?: string): Promise<LeaderboardResponse>;
202
- // Returns: { campaignId, entries, playerRank, lastUpdated, isLive }
203
- // entries: [{ rank, playerId, displayName, score, achievedAt, isCurrentPlayer, prizeAmount }]
204
-
205
- // Get player attempts
206
- await sdk.getPlayerAttempts(campaignId: string, playerId: string): Promise<PlayerAttemptsResponse>;
207
- // Returns: { playerId, campaignId, totalAttempts, remainingAttempts, attempts, stats }
208
- // attempts: [{ sessionId, score, playedAt, duration, status, wasWinner }]
209
- // stats: { bestScore, averageScore, totalPlayTime, firstAttempt, lastAttempt }
210
- ```
211
-
212
- #### Validation & Anti-Cheat
213
-
214
- ```typescript
215
- // Validate game session with integrity verification
216
- await sdk.validateGameSession({
217
- clientChecksum: string;
218
- stateSnapshot?: Record<string, unknown>; // Automatically hashed
219
- timingData?: unknown;
220
- behaviorMetrics?: unknown;
221
- }): Promise<ValidationResponse>;
222
- // Returns: { isValid, confidenceScore, validationIssues, warnings, requiresRevalidation, validatedAt }
223
-
224
- // Send heartbeat (usually handled automatically)
225
- await sdk.sendHeartbeat(currentScore?: number): Promise<HeartbeatResponse>;
226
- // Returns: { acknowledged, serverTimestamp, nextHeartbeatIn, campaignStillActive, message }
227
- ```
228
-
229
- #### Developer Tools
230
-
231
- ```typescript
232
- // Create test game session for development
233
- await sdk.createTestGameSession(testConfig?: Record<string, any>): Promise<TestGameResponse>;
234
- // Returns: { testSessionId, testScenario, mockCampaign, testData, expiresAt }
235
- ```
236
-
237
- ### Utility Methods
238
-
239
- ```typescript
240
- // Test SDK functionality
241
- sdk.test('Custom test message'): void;
242
-
243
- // Check if running in demo mode
244
- const isDemoMode = sdk.isDemo(): boolean;
245
-
246
- // Game lifecycle events
247
- sdk.gameLoadingStart(): void; // Emit loading start event
248
- sdk.gameLoadingFinished(): void; // Emit loading finished event
249
- sdk.gamePlayStop(): void; // Stop heartbeat and emit stop event
250
-
251
- // Clean up resources
252
- sdk.destroy(): void; // Clean up session artifacts and stop heartbeat
253
- ```
254
-
255
- ### Response Types
256
-
257
- ```typescript
258
- // Game Session Response
259
- interface GameSessionResponse {
260
- sessionId: string;
261
- campaignId: string;
262
- gameId: string;
263
- status: string;
264
- campaign: CampaignInfo;
265
- player: PlayerInfo;
266
- createdAt: string;
267
- expiresAt?: string;
268
- }
269
-
270
- // Progress Update Response
271
- interface ProgressUpdateResponse {
272
- isValid: boolean;
273
- validationMessage?: string;
274
- currentRank: number;
275
- isLeading: boolean;
276
- campaignStatus?: CampaignStatusInfo;
277
- warnings?: string[];
278
- }
279
-
280
- // Game Completion Response
281
- interface GameCompletionResponse {
282
- isWinner: boolean;
283
- prizeAmount?: number;
284
- prizeType?: string;
285
- finalRank: number;
286
- totalParticipants: number;
287
- winnerDetails?: WinnerInfo;
288
- reward?: RewardInfo;
289
- campaignResult?: CampaignResultInfo;
290
- }
291
-
292
- // Campaign Status Response
293
- interface CampaignStatusResponse {
294
- campaignId: string;
295
- status: string;
296
- campaignStyle: string;
297
- remainingGamepasses: number;
298
- totalParticipants: number;
299
- totalPrizePool: number;
300
- endDate?: string;
301
- playerStatus?: PlayerStatusInfo;
302
- topPlayers?: TopPlayer[];
303
- prizeBreakdown?: PrizeBreakdown;
304
- }
305
-
306
- // Leaderboard Response
307
- interface LeaderboardResponse {
308
- campaignId: string;
309
- entries: LeaderboardEntry[];
310
- playerRank?: PlayerRankInfo;
311
- lastUpdated: string;
312
- isLive: boolean;
313
- }
314
-
315
- // Validation Response
316
- interface ValidationResponse {
317
- isValid: boolean;
318
- confidenceScore: number;
319
- validationIssues: string[];
320
- warnings: string[];
321
- requiresRevalidation: boolean;
322
- validatedAt: string;
323
- }
324
- ```
325
-
326
- ### Integrity Verification Utilities
327
-
328
- ```typescript
329
- import { canonicalStringify, sha256Hex } from "playe-developer-sdk";
330
-
331
- // Canonical JSON stringification (deterministic)
332
- const canonical = canonicalStringify({ b: 1, a: 2 }); // '{"a":2,"b":1}'
333
-
334
- // SHA-256 hashing
335
- const hash = await sha256Hex("data to hash");
336
- ```
337
-
338
- ### Device Utilities
339
-
340
- ```typescript
341
- import { DeviceUtils } from "@workspace/playe-developer-sdk";
342
-
343
- // Get device information
344
- const deviceInfo = DeviceUtils.getDeviceInfo();
345
-
346
- // Get geolocation
347
- const location = await DeviceUtils.getGeolocationData();
348
-
349
- // Generate fingerprint
350
- const fingerprint = DeviceUtils.generateFingerprint();
351
-
352
- // Check browser support
353
- const isSupported = DeviceUtils.isBrowser();
354
- const features = DeviceUtils.getFeatureSupport();
355
- ```
356
-
357
- ### Error Handling
358
-
359
- ```typescript
360
- import {
361
- PlayeSDKError,
362
- ValidationError,
363
- NetworkError,
364
- AuthenticationError,
365
- GameSessionError,
366
- } from "@workspace/playe-developer-sdk";
367
-
368
- try {
369
- await sdk.initializeGameSession(params);
370
- } catch (error) {
371
- if (error instanceof ValidationError) {
372
- console.error("Validation failed:", error.message);
373
- } else if (error instanceof NetworkError) {
374
- console.error("Network error:", error.message);
375
- } else if (error instanceof AuthenticationError) {
376
- console.error("Authentication failed:", error.message);
377
- } else if (error instanceof PlayeSDKError) {
378
- console.error("SDK error:", error.toJSON());
379
- }
380
- }
381
- ```
382
-
383
- ## 🔒 Security & Integrity
384
-
385
- The SDK includes built-in integrity verification to prevent cheating and ensure fair play:
386
-
387
- ### Automatic Features
388
-
389
- - **Session Integrity**: Each game session includes a unique session token and salt
390
- - **Game State Hashing**: Game states are automatically hashed using SHA-256 with session salt
391
- - **Integrity Headers**: All authenticated requests include cryptographic integrity headers
392
- - **Retry Logic**: Failed requests due to integrity issues are automatically retried with fresh headers
393
-
394
- ### How It Works
395
-
396
- 1. **Session Initialization**: SDK receives session token and salt from server
397
- 2. **State Hashing**: Game states are canonicalized and hashed with session salt
398
- 3. **Request Signing**: Integrity headers are built with timestamp, nonce, and session token
399
- 4. **Server Validation**: Server verifies hashes and headers to detect tampering
400
-
401
- ### Manual Verification (Advanced)
402
-
403
- ```typescript
404
- // Manually validate game session
405
- const validation = await sdk.validateGameSession({
406
- clientChecksum: "calculated-checksum",
407
- stateSnapshot: currentGameState,
408
- timingData: { avgResponseTime: 250 },
409
- behaviorMetrics: { clicksPerSecond: 5.2 },
410
- });
411
-
412
- if (!validation.isValid) {
413
- console.log("Validation issues:", validation.validationIssues);
414
- }
415
- ```
416
-
417
- ## 🧪 Testing & Development
418
-
419
- ### Testing
420
-
421
- ```typescript
422
- // Create a test game session for development
423
- const testSession = await sdk.createTestGameSession({
424
- testConfig: {
425
- mockCampaign: true,
426
- mockPlayers: 10,
427
- testScenario: "leaderboard",
428
- },
429
- });
430
-
431
- console.log("Test session created:", testSession.testSessionId);
432
- ```
433
-
434
- ### Debug Mode
435
-
436
- Enable debug mode to see detailed logging:
437
-
438
- ```typescript
439
- const sdk = createPlayeSDK({
440
- apiBaseUrl: "https://api.playe.com",
441
- enableDebugMode: true, // This will log all API calls, integrity operations, and responses
442
- });
443
- ```
444
-
445
- ### URL Requirements
446
-
447
- For `initializeGameSession()` to work, page URL must include a `sessionId` query parameter:
448
-
449
- ```
450
- https://yourgame.com/play?sessionId=abc123-def456-ghi789
451
- ```
452
-
453
- The SDK will automatically extract this sessionId and initialize session.
454
-
455
- ## 📚 Examples
456
-
457
- ### Browser Example
458
-
459
- The `examples/browser-example.html` provides a complete integration example with:
460
-
461
- - SDK initialization and configuration
462
- - Session management (initialize, start, update, complete)
463
- - Progress tracking with integrity verification
464
- - Leaderboard fetching and display
465
- - Error handling and recovery
466
- - Debug mode logging
467
- - Device fingerprinting
468
-
469
- ### Flappy Bird Example
470
-
471
- The `examples/flappy-bird.html` provides a complete game integration example with:
472
-
473
- - Player eligibility validation (attempts remaining, campaign status)
474
- - Game session initialization with SDK
475
- - Real-time progress tracking
476
- - Score submission with completion data
477
- - Graceful fallback to demo mode if SDK unavailable
478
- - Responsive game canvas with mobile support
479
-
480
- ## 🔄 Migration Guide
481
-
482
- ### Migrating from v0.x to v1.x
483
-
484
- #### Breaking Changes
485
-
486
- 1. **SDK Initialization**
487
- ```typescript
488
- // v0.x
489
- import { PlayeDeveloperSDK } from 'playe-developer-sdk';
490
- const sdk = new PlayeDeveloperSDK(config);
491
-
492
- // v1.x
493
- import { createPlayeSDK } from 'playe-developer-sdk';
494
- const sdk = createPlayeSDK(config);
495
- ```
496
-
497
- 2. **Method Signatures**
498
- ```typescript
499
- // v0.x - Callback-based
500
- sdk.initializeGameSession((error, session) => {
501
- if (error) handleError(error);
502
- else handleSuccess(session);
503
- });
504
-
505
- // v1.x - Promise-based
506
- try {
507
- const session = await sdk.initializeGameSession();
508
- handleSuccess(session);
509
- } catch (error) {
510
- handleError(error);
511
- }
512
- ```
513
-
514
- ## 🚨 Error Handling
515
-
516
- ### Error Types
517
-
518
- ```typescript
519
- // Base SDK error
520
- PlayeSDKError {
521
- name: string;
522
- message: string;
523
- originalError?: Error;
524
- context?: string;
525
- timestamp: string;
526
- }
527
-
528
- // Specific error types
529
- ValidationError extends PlayeSDKError; // Validation failures
530
- NetworkError extends PlayeSDKError; // Network issues
531
- AuthenticationError extends PlayeSDKError; // Authentication failures
532
- GameSessionError extends PlayeSDKError; // Session-specific errors
533
- ```
534
-
535
- ### Error Recovery
536
-
537
- ```typescript
538
- // Enable debug mode for detailed error information
539
- const sdk = createPlayeSDK({
540
- apiBaseUrl: 'https://api.playe.com',
541
- enableDebugMode: true,
542
- retryAttempts: 3, // Configure retry behavior
543
- timeoutMs: 30000, // Configure timeout
544
- });
545
- ```
546
-
547
- ## 🔧 Troubleshooting
548
-
549
- ### Common Issues
550
-
551
- #### "No sessionId found in URL" Error
552
-
553
- **Problem:** Getting an error when calling `initializeGameSession()`.
554
-
555
- **Solution:** Ensure your game URL includes a `sessionId` query parameter:
556
- ```
557
- https://yourgame.com/play?sessionId=abc123-def456-ghi789
558
- ```
559
-
560
- #### Network/Timeout Errors
561
-
562
- **Problem:** API calls failing with network errors.
563
-
564
- **Solutions:**
565
- 1. Check API endpoint configuration
566
- 2. Verify API key is correct
567
- 3. Check network connectivity
568
- 4. Increase timeout for slow networks
569
-
570
- #### Integrity Validation Failures
571
-
572
- **Problem:** Game completion failing with integrity validation errors.
573
-
574
- **Solutions:**
575
- 1. Ensure game state is valid and serializable
576
- 2. Check timing data is reasonable
577
- 3. Use debug mode to inspect requests
578
-
579
- ## 🤝 Contributing
580
-
581
- We welcome contributions to the Playe Developer SDK!
582
-
583
- ### Development Setup
584
-
585
- ```bash
586
- # Clone repository
587
- git clone https://github.com/playe/playe.git
588
- cd playe
589
-
590
- # Install dependencies
591
- pnpm install
592
-
593
- # Build SDK
594
- pnpm --filter playe-developer-sdk build
595
-
596
- # Run tests
597
- pnpm --filter playe-developer-sdk test
598
- ```
599
-
600
- ### Code Guidelines
601
-
602
- - Follow TypeScript best practices
603
- - Add tests for new functionality
604
- - Update documentation as needed
605
- - Ensure all tests pass
606
-
607
- ## 📄 License
608
-
609
- MIT License - see LICENSE file for details.
610
-
611
- Copyright (c) 2024 Playe
612
-
613
- Permission is hereby granted, free of charge, to any person obtaining a copy
614
- of this software and associated documentation files (the "Software"), to deal
615
- in the Software without restriction, including without limitation the rights
616
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
617
- copies of the Software, and to permit persons to whom the Software is
618
- furnished to do so, subject to the following conditions:
619
-
620
- The above copyright notice and this permission notice shall be included in all
621
- copies or substantial portions of the Software.
622
-
623
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
624
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
625
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
626
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
627
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
628
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ # 🎮 Playe Developer SDK
2
+
3
+ [![Version](https://img.shields.io/npm/v/playe-developer-sdk)](https://npmjs.com/package/playe-developer-sdk)
4
+ [![License](https://img.shields.io/npm/l/playe-developer-sdk)](https://github.com/playe/playe/blob/main/LICENSE)
5
+ [![Bundle Size](https://img.shields.io/bundlephobia/min/playe-developer-sdk)](https://bundlephobia.com/package/playe-developer-sdk)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
7
+
8
+ A browser-based SDK for integrating games with the Playe platform. Provides game session management, campaign integration, leaderboards, and integrity verification.
9
+
10
+ ## ✨ Features
11
+
12
+ - 🎮 **Game Session Management** - Initialize, start, update, and complete game sessions
13
+ - 🛡️ **Integrity Verification** - Built-in session integrity with cryptographic hashing
14
+ - 🏆 **Campaign Integration** - Access campaign information, leaderboards, and player attempts
15
+ - 🔄 **Anti-Cheat Protection** - Advanced validation, heartbeat mechanisms, and session monitoring
16
+ - 📱 **Device Detection** - Automatic device information and fingerprinting
17
+ - 🔧 **Developer Tools** - Test game sessions and debugging utilities
18
+ - 📊 **Real-time Updates** - Progress tracking and live leaderboards
19
+ - ⚡ **Browser Optimized** - Lightweight and fast for web games with automatic retry logic
20
+
21
+ ## 🚀 Installation
22
+
23
+ ### NPM
24
+
25
+ ```bash
26
+ npm install playe-developer-sdk
27
+ # or
28
+ yarn add playe-developer-sdk
29
+ # or
30
+ pnpm add playe-developer-sdk
31
+ ```
32
+
33
+ ### CDN
34
+
35
+ ```html
36
+ <script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
37
+ ```
38
+
39
+ ### Workspace
40
+
41
+ ```json
42
+ {
43
+ "dependencies": {
44
+ "@workspace/playe-developer-sdk": "workspace:*"
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## 📖 Quick Start
50
+
51
+ ### NPM Usage
52
+
53
+ ```typescript
54
+ import { createPlayeSDK } from "playe-developer-sdk";
55
+
56
+ // Initialize SDK
57
+ const sdk = createPlayeSDK({
58
+ apiBaseUrl: "https://api.playe.com",
59
+ apiKey: "your-api-key",
60
+ enableDebugMode: true,
61
+ });
62
+
63
+ // Initialize game session (gets sessionId from URL)
64
+ const session = await sdk.initializeGameSession();
65
+
66
+ // Start game
67
+ await sdk.startGameSession({
68
+ difficulty: "normal",
69
+ mode: "classic",
70
+ });
71
+
72
+ // Update progress
73
+ await sdk.updateGameProgress({
74
+ currentScore: 1500,
75
+ elapsedTime: 120,
76
+ gameState: {
77
+ level: 3,
78
+ lives: 2,
79
+ powerUps: ["speed", "shield"],
80
+ },
81
+ achievements: [
82
+ {
83
+ id: "level-3",
84
+ name: "Level 3 Complete",
85
+ unlockedAt: new Date().toISOString(),
86
+ },
87
+ ],
88
+ });
89
+
90
+ // Complete game
91
+ const result = await sdk.completeGame({
92
+ finalScore: 2500,
93
+ validationChecksum: "client-checksum",
94
+ gameMetrics: {
95
+ totalPlayTime: 300,
96
+ actionsPerformed: 150,
97
+ powerUpsUsed: 5,
98
+ levelsCompleted: 5,
99
+ },
100
+ finalGameState: {
101
+ level: 5,
102
+ finalLives: 1,
103
+ },
104
+ });
105
+ ```
106
+
107
+ ### CDN Usage
108
+
109
+ ```html
110
+ <script src="https://unpkg.com/playe-developer-sdk@latest/dist/playe-sdk.umd.min.js"></script>
111
+ <script>
112
+ const sdk = PlayeSDK.createPlayeSDK({
113
+ apiBaseUrl: 'https://api.playe.com',
114
+ apiKey: 'your-api-key',
115
+ enableDebugMode: true,
116
+ });
117
+
118
+ const session = await sdk.initializeGameSession();
119
+ console.log('Session initialized:', session.sessionId);
120
+ </script>
121
+ ```
122
+
123
+ ## 📋 Table of Contents
124
+
125
+ - [🎮 Playe Developer SDK](#-playe-developer-sdk)
126
+ - [✨ Features](#-features)
127
+ - [🚀 Installation](#-installation)
128
+ - [📖 Quick Start](#-quick-start)
129
+ - [📋 Table of Contents](#-table-of-contents)
130
+ - [🔧 API Reference](#-api-reference)
131
+ - [🔒 Security & Integrity](#-security--integrity)
132
+ - [🧪 Testing & Development](#-testing--development)
133
+ - [🚨 Error Handling](#-error-handling)
134
+ - [📚 Examples](#-examples)
135
+ - [🔄 Migration Guide](#-migration-guide)
136
+ - [🔧 Troubleshooting](#-troubleshooting)
137
+ - [🤝 Contributing](#-contributing)
138
+ - [📄 License](#-license)
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
+ // Returns: { sessionId, campaignId, gameId, status, campaign, player, createdAt, expiresAt }
163
+
164
+ // Start game session
165
+ await sdk.startGameSession(config?: Record<string, any>): Promise<GameSessionResponse>;
166
+ // Returns: { sessionId, status, startTime }
167
+
168
+ // Update game progress with integrity verification
169
+ await sdk.updateGameProgress({
170
+ currentScore: number;
171
+ gameState?: Record<string, any>; // Automatically hashed for integrity
172
+ elapsedTime: number;
173
+ achievements?: Achievement[];
174
+ clientTimestamp?: string;
175
+ }): Promise<ProgressUpdateResponse>;
176
+ // Returns: { isValid, validationMessage, currentRank, isLeading, campaignStatus, warnings }
177
+
178
+ // Complete game with integrity verification
179
+ await sdk.completeGame({
180
+ finalScore: number;
181
+ validationChecksum: string;
182
+ gameMetrics?: GameMetrics;
183
+ finalGameState?: Record<string, any>; // Automatically hashed for integrity
184
+ }): Promise<GameCompletionResponse>;
185
+ // Returns: { isWinner, prizeAmount, prizeType, finalRank, totalParticipants, winnerDetails, reward, campaignResult }
186
+
187
+ // Abandon game
188
+ await sdk.abandonGame(reason?: string, lastKnownScore?: number): Promise<AbandonGameResponse>;
189
+ // Returns: { success, message, gamepassRefunded, abandonedAt }
190
+ ```
191
+
192
+ #### Campaign Information
193
+
194
+ ```typescript
195
+ // Get campaign status
196
+ await sdk.getCampaignStatus(campaignId: string, playerId?: string): Promise<CampaignStatusResponse>;
197
+ // Returns: { campaignId, status, campaignStyle, remainingGamepasses, totalParticipants,
198
+ // totalPrizePool, endDate, playerStatus, topPlayers, prizeBreakdown }
199
+
200
+ // Get leaderboard
201
+ await sdk.getLeaderboard(campaignId: string, limit?: number, playerId?: string): Promise<LeaderboardResponse>;
202
+ // Returns: { campaignId, entries, playerRank, lastUpdated, isLive }
203
+ // entries: [{ rank, playerId, displayName, score, achievedAt, isCurrentPlayer, prizeAmount }]
204
+
205
+ // Get player attempts
206
+ await sdk.getPlayerAttempts(campaignId: string, playerId: string): Promise<PlayerAttemptsResponse>;
207
+ // Returns: { playerId, campaignId, totalAttempts, remainingAttempts, attempts, stats }
208
+ // attempts: [{ sessionId, score, playedAt, duration, status, wasWinner }]
209
+ // stats: { bestScore, averageScore, totalPlayTime, firstAttempt, lastAttempt }
210
+ ```
211
+
212
+ #### Validation & Anti-Cheat
213
+
214
+ ```typescript
215
+ // Validate game session with integrity verification
216
+ await sdk.validateGameSession({
217
+ clientChecksum: string;
218
+ stateSnapshot?: Record<string, unknown>; // Automatically hashed
219
+ timingData?: unknown;
220
+ behaviorMetrics?: unknown;
221
+ }): Promise<ValidationResponse>;
222
+ // Returns: { isValid, confidenceScore, validationIssues, warnings, requiresRevalidation, validatedAt }
223
+
224
+ // Send heartbeat (usually handled automatically)
225
+ await sdk.sendHeartbeat(currentScore?: number): Promise<HeartbeatResponse>;
226
+ // Returns: { acknowledged, serverTimestamp, nextHeartbeatIn, campaignStillActive, message }
227
+ ```
228
+
229
+ #### Developer Tools
230
+
231
+ ```typescript
232
+ // Create test game session for development
233
+ await sdk.createTestGameSession(testConfig?: Record<string, any>): Promise<TestGameResponse>;
234
+ // Returns: { testSessionId, testScenario, mockCampaign, testData, expiresAt }
235
+ ```
236
+
237
+ ### Utility Methods
238
+
239
+ ```typescript
240
+ // Test SDK functionality
241
+ sdk.test('Custom test message'): void;
242
+
243
+ // Check if running in demo mode
244
+ const isDemoMode = sdk.isDemo(): boolean;
245
+
246
+ // Game lifecycle events
247
+ sdk.gameLoadingStart(): void; // Emit loading start event
248
+ sdk.gameLoadingFinished(): void; // Emit loading finished event
249
+ sdk.gamePlayStop(): void; // Stop heartbeat and emit stop event
250
+
251
+ // Clean up resources
252
+ sdk.destroy(): void; // Clean up session artifacts and stop heartbeat
253
+ ```
254
+
255
+ ### Response Types
256
+
257
+ ```typescript
258
+ // Game Session Response
259
+ interface GameSessionResponse {
260
+ sessionId: string;
261
+ campaignId: string;
262
+ gameId: string;
263
+ status: string;
264
+ campaign: CampaignInfo;
265
+ player: PlayerInfo;
266
+ createdAt: string;
267
+ expiresAt?: string;
268
+ }
269
+
270
+ // Progress Update Response
271
+ interface ProgressUpdateResponse {
272
+ isValid: boolean;
273
+ validationMessage?: string;
274
+ currentRank: number;
275
+ isLeading: boolean;
276
+ campaignStatus?: CampaignStatusInfo;
277
+ warnings?: string[];
278
+ }
279
+
280
+ // Game Completion Response
281
+ interface GameCompletionResponse {
282
+ isWinner: boolean;
283
+ prizeAmount?: number;
284
+ prizeType?: string;
285
+ finalRank: number;
286
+ totalParticipants: number;
287
+ winnerDetails?: WinnerInfo;
288
+ reward?: RewardInfo;
289
+ campaignResult?: CampaignResultInfo;
290
+ }
291
+
292
+ // Campaign Status Response
293
+ interface CampaignStatusResponse {
294
+ campaignId: string;
295
+ status: string;
296
+ campaignStyle: string;
297
+ remainingGamepasses: number;
298
+ totalParticipants: number;
299
+ totalPrizePool: number;
300
+ endDate?: string;
301
+ playerStatus?: PlayerStatusInfo;
302
+ topPlayers?: TopPlayer[];
303
+ prizeBreakdown?: PrizeBreakdown;
304
+ }
305
+
306
+ // Leaderboard Response
307
+ interface LeaderboardResponse {
308
+ campaignId: string;
309
+ entries: LeaderboardEntry[];
310
+ playerRank?: PlayerRankInfo;
311
+ lastUpdated: string;
312
+ isLive: boolean;
313
+ }
314
+
315
+ // Validation Response
316
+ interface ValidationResponse {
317
+ isValid: boolean;
318
+ confidenceScore: number;
319
+ validationIssues: string[];
320
+ warnings: string[];
321
+ requiresRevalidation: boolean;
322
+ validatedAt: string;
323
+ }
324
+ ```
325
+
326
+ ### Integrity Verification Utilities
327
+
328
+ ```typescript
329
+ import { canonicalStringify, sha256Hex } from "playe-developer-sdk";
330
+
331
+ // Canonical JSON stringification (deterministic)
332
+ const canonical = canonicalStringify({ b: 1, a: 2 }); // '{"a":2,"b":1}'
333
+
334
+ // SHA-256 hashing
335
+ const hash = await sha256Hex("data to hash");
336
+ ```
337
+
338
+ ### Device Utilities
339
+
340
+ ```typescript
341
+ import { DeviceUtils } from "@workspace/playe-developer-sdk";
342
+
343
+ // Get device information
344
+ const deviceInfo = DeviceUtils.getDeviceInfo();
345
+
346
+ // Get geolocation
347
+ const location = await DeviceUtils.getGeolocationData();
348
+
349
+ // Generate fingerprint
350
+ const fingerprint = DeviceUtils.generateFingerprint();
351
+
352
+ // Check browser support
353
+ const isSupported = DeviceUtils.isBrowser();
354
+ const features = DeviceUtils.getFeatureSupport();
355
+ ```
356
+
357
+ ### Error Handling
358
+
359
+ ```typescript
360
+ import {
361
+ PlayeSDKError,
362
+ ValidationError,
363
+ NetworkError,
364
+ AuthenticationError,
365
+ GameSessionError,
366
+ } from "@workspace/playe-developer-sdk";
367
+
368
+ try {
369
+ await sdk.initializeGameSession(params);
370
+ } catch (error) {
371
+ if (error instanceof ValidationError) {
372
+ console.error("Validation failed:", error.message);
373
+ } else if (error instanceof NetworkError) {
374
+ console.error("Network error:", error.message);
375
+ } else if (error instanceof AuthenticationError) {
376
+ console.error("Authentication failed:", error.message);
377
+ } else if (error instanceof PlayeSDKError) {
378
+ console.error("SDK error:", error.toJSON());
379
+ }
380
+ }
381
+ ```
382
+
383
+ ## 🔒 Security & Integrity
384
+
385
+ The SDK includes built-in integrity verification to prevent cheating and ensure fair play:
386
+
387
+ ### Automatic Features
388
+
389
+ - **Session Integrity**: Each game session includes a unique session token and salt
390
+ - **Game State Hashing**: Game states are automatically hashed using SHA-256 with session salt
391
+ - **Integrity Headers**: All authenticated requests include cryptographic integrity headers
392
+ - **Retry Logic**: Failed requests due to integrity issues are automatically retried with fresh headers
393
+
394
+ ### How It Works
395
+
396
+ 1. **Session Initialization**: SDK receives session token and salt from server
397
+ 2. **State Hashing**: Game states are canonicalized and hashed with session salt
398
+ 3. **Request Signing**: Integrity headers are built with timestamp, nonce, and session token
399
+ 4. **Server Validation**: Server verifies hashes and headers to detect tampering
400
+
401
+ ### Manual Verification (Advanced)
402
+
403
+ ```typescript
404
+ // Manually validate game session
405
+ const validation = await sdk.validateGameSession({
406
+ clientChecksum: "calculated-checksum",
407
+ stateSnapshot: currentGameState,
408
+ timingData: { avgResponseTime: 250 },
409
+ behaviorMetrics: { clicksPerSecond: 5.2 },
410
+ });
411
+
412
+ if (!validation.isValid) {
413
+ console.log("Validation issues:", validation.validationIssues);
414
+ }
415
+ ```
416
+
417
+ ## 🧪 Testing & Development
418
+
419
+ ### Testing
420
+
421
+ ```typescript
422
+ // Create a test game session for development
423
+ const testSession = await sdk.createTestGameSession({
424
+ testConfig: {
425
+ mockCampaign: true,
426
+ mockPlayers: 10,
427
+ testScenario: "leaderboard",
428
+ },
429
+ });
430
+
431
+ console.log("Test session created:", testSession.testSessionId);
432
+ ```
433
+
434
+ ### Debug Mode
435
+
436
+ Enable debug mode to see detailed logging:
437
+
438
+ ```typescript
439
+ const sdk = createPlayeSDK({
440
+ apiBaseUrl: "https://api.playe.com",
441
+ enableDebugMode: true, // This will log all API calls, integrity operations, and responses
442
+ });
443
+ ```
444
+
445
+ ### URL Requirements
446
+
447
+ For `initializeGameSession()` to work, page URL must include a `sessionId` query parameter:
448
+
449
+ ```
450
+ https://yourgame.com/play?sessionId=abc123-def456-ghi789
451
+ ```
452
+
453
+ The SDK will automatically extract this sessionId and initialize session.
454
+
455
+ ## 📚 Examples
456
+
457
+ ### Browser Example
458
+
459
+ The `examples/browser-example.html` provides a complete integration example with:
460
+
461
+ - SDK initialization and configuration
462
+ - Session management (initialize, start, update, complete)
463
+ - Progress tracking with integrity verification
464
+ - Leaderboard fetching and display
465
+ - Error handling and recovery
466
+ - Debug mode logging
467
+ - Device fingerprinting
468
+
469
+ ### Flappy Bird Example
470
+
471
+ The `examples/flappy-bird.html` provides a complete game integration example with:
472
+
473
+ - Player eligibility validation (attempts remaining, campaign status)
474
+ - Game session initialization with SDK
475
+ - Real-time progress tracking
476
+ - Score submission with completion data
477
+ - Graceful fallback to demo mode if SDK unavailable
478
+ - Responsive game canvas with mobile support
479
+
480
+ ## 🔄 Migration Guide
481
+
482
+ ### Migrating from v0.x to v1.x
483
+
484
+ #### Breaking Changes
485
+
486
+ 1. **SDK Initialization**
487
+ ```typescript
488
+ // v0.x
489
+ import { PlayeDeveloperSDK } from 'playe-developer-sdk';
490
+ const sdk = new PlayeDeveloperSDK(config);
491
+
492
+ // v1.x
493
+ import { createPlayeSDK } from 'playe-developer-sdk';
494
+ const sdk = createPlayeSDK(config);
495
+ ```
496
+
497
+ 2. **Method Signatures**
498
+ ```typescript
499
+ // v0.x - Callback-based
500
+ sdk.initializeGameSession((error, session) => {
501
+ if (error) handleError(error);
502
+ else handleSuccess(session);
503
+ });
504
+
505
+ // v1.x - Promise-based
506
+ try {
507
+ const session = await sdk.initializeGameSession();
508
+ handleSuccess(session);
509
+ } catch (error) {
510
+ handleError(error);
511
+ }
512
+ ```
513
+
514
+ ## 🚨 Error Handling
515
+
516
+ ### Error Types
517
+
518
+ ```typescript
519
+ // Base SDK error
520
+ PlayeSDKError {
521
+ name: string;
522
+ message: string;
523
+ originalError?: Error;
524
+ context?: string;
525
+ timestamp: string;
526
+ }
527
+
528
+ // Specific error types
529
+ ValidationError extends PlayeSDKError; // Validation failures
530
+ NetworkError extends PlayeSDKError; // Network issues
531
+ AuthenticationError extends PlayeSDKError; // Authentication failures
532
+ GameSessionError extends PlayeSDKError; // Session-specific errors
533
+ ```
534
+
535
+ ### Error Recovery
536
+
537
+ ```typescript
538
+ // Enable debug mode for detailed error information
539
+ const sdk = createPlayeSDK({
540
+ apiBaseUrl: 'https://api.playe.com',
541
+ enableDebugMode: true,
542
+ retryAttempts: 3, // Configure retry behavior
543
+ timeoutMs: 30000, // Configure timeout
544
+ });
545
+ ```
546
+
547
+ ## 🔧 Troubleshooting
548
+
549
+ ### Common Issues
550
+
551
+ #### "No sessionId found in URL" Error
552
+
553
+ **Problem:** Getting an error when calling `initializeGameSession()`.
554
+
555
+ **Solution:** Ensure your game URL includes a `sessionId` query parameter:
556
+ ```
557
+ https://yourgame.com/play?sessionId=abc123-def456-ghi789
558
+ ```
559
+
560
+ #### Network/Timeout Errors
561
+
562
+ **Problem:** API calls failing with network errors.
563
+
564
+ **Solutions:**
565
+ 1. Check API endpoint configuration
566
+ 2. Verify API key is correct
567
+ 3. Check network connectivity
568
+ 4. Increase timeout for slow networks
569
+
570
+ #### Integrity Validation Failures
571
+
572
+ **Problem:** Game completion failing with integrity validation errors.
573
+
574
+ **Solutions:**
575
+ 1. Ensure game state is valid and serializable
576
+ 2. Check timing data is reasonable
577
+ 3. Use debug mode to inspect requests
578
+
579
+ ## 🤝 Contributing
580
+
581
+ We welcome contributions to the Playe Developer SDK!
582
+
583
+ ### Development Setup
584
+
585
+ ```bash
586
+ # Clone repository
587
+ git clone https://github.com/playe/playe.git
588
+ cd playe
589
+
590
+ # Install dependencies
591
+ pnpm install
592
+
593
+ # Build SDK
594
+ pnpm --filter playe-developer-sdk build
595
+
596
+ # Run tests
597
+ pnpm --filter playe-developer-sdk test
598
+ ```
599
+
600
+ ### Code Guidelines
601
+
602
+ - Follow TypeScript best practices
603
+ - Add tests for new functionality
604
+ - Update documentation as needed
605
+ - Ensure all tests pass
606
+
607
+ ## 📄 License
608
+
609
+ MIT License - see LICENSE file for details.
610
+
611
+ Copyright (c) 2024 Playe
612
+
613
+ Permission is hereby granted, free of charge, to any person obtaining a copy
614
+ of this software and associated documentation files (the "Software"), to deal
615
+ in the Software without restriction, including without limitation the rights
616
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
617
+ copies of the Software, and to permit persons to whom the Software is
618
+ furnished to do so, subject to the following conditions:
619
+
620
+ The above copyright notice and this permission notice shall be included in all
621
+ copies or substantial portions of the Software.
622
+
623
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
624
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
625
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
626
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
627
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
628
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
629
629
  SOFTWARE.