playe-developer-sdk 1.0.0 → 1.0.2

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