@hyve-sdk/js 1.5.0 → 2.1.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 CHANGED
@@ -1,329 +1,139 @@
1
1
  # @hyve-sdk/js
2
2
 
3
- TypeScript SDK for web3 authentication and game integration, providing secure signature verification and utility functions.
3
+ The core SDK for integrating with the Hyve platform, providing authentication, telemetry, persistent storage, billing, ads, and native bridge capabilities for web games.
4
4
 
5
- ## Installation
5
+ ## Setup
6
6
 
7
- ```bash
8
- bun add @hyve-sdk/js
9
- # or
10
- npm install @hyve-sdk/js
11
- # or
12
- pnpm add @hyve-sdk/js
13
- ```
14
-
15
- ## Features
16
-
17
- - **Web3 Authentication**: EVM signature validation and verification
18
- - **Modern & Legacy Token Support**: Dual authentication token formats
19
- - **JWT Authentication**: Support for JWT tokens passed via URL parameters
20
- - **API Integration**: Authenticated API calls with JWT token support
21
- - **Inventory Management**: Built-in methods for user inventory operations
22
- - **Telemetry Tracking**: Session-based analytics and event tracking
23
- - **Billing Integration**: Unified billing for web (Stripe) and native (In-App Purchases) platforms
24
- - **Ads Integration**: Google H5 Games Ads support (disabled by default)
25
- - **Native Bridge**: Type-safe communication with React Native WebView apps
26
- - **Logger**: Environment-aware logging system with configurable log levels
27
- - **Security Utilities**: Domain validation and referrer checking
28
- - **URL Parameter Parsing**: Easy extraction of authentication parameters
29
- - **UUID Generation**: Built-in UUID v4 generation
30
-
31
- ## Core Components
32
-
33
- ### HyveClient
34
- Main client class for SDK operations including authentication, telemetry, and API calls.
35
-
36
- ```typescript
37
- import { HyveClient } from "@hyve-sdk/js";
7
+ Load the SDK via script tag — no npm install required.
38
8
 
39
- // Initialize client
40
- // Environment (dev/prod) is automatically detected from the parent page URL
41
- const client = new HyveClient();
42
-
43
- // Authenticate from URL parameters
44
- // Extracts: hyve-token/signature, hyve-access (JWT), game-id
45
- const authenticated = await client.authenticateFromUrl();
46
- if (authenticated) {
47
- console.log('User ID:', client.getUserId());
48
- console.log('Session ID:', client.getSessionId());
49
- console.log('Has JWT:', client.hasJwtToken());
50
- console.log('Game ID:', client.getGameId());
51
- }
52
- ```
53
-
54
- **Environment Detection:**
55
- The SDK automatically detects whether to use dev or prod environment by checking the parent page URL:
56
- - **Dev**: `marvin.dev.hyve.gg` or `dev.hyve.gg`
57
- - **Prod**: `marvin.hyve.gg` or `hyve.gg`
58
-
59
- You can optionally override this for testing:
60
- ```typescript
61
- // Only use for local testing - NOT for production code
62
- const client = new HyveClient({
63
- isDev: true, // Force dev mode for testing
64
- apiBaseUrl: 'https://...' // Optional custom API URL
65
- });
66
- ```
67
-
68
- ### Authentication Utilities
69
-
70
- #### Parse URL Parameters
71
- Extract authentication and game parameters from URL:
72
-
73
- ```typescript
74
- import { parseUrlParams } from "@hyve-sdk/js";
75
-
76
- const params = parseUrlParams(window.location.search);
77
- // Returns:
78
- // {
79
- // signature: string,
80
- // message: string,
81
- // gameStartTab: string,
82
- // hyveToken: string,
83
- // platform: string,
84
- // hyveAccess: string, // JWT token
85
- // gameId: string // Game identifier
86
- // }
9
+ ```html
10
+ <script src="https://package.hyve.gg/hyve-sdk.global.js"></script>
87
11
  ```
88
12
 
89
- #### Verify Authentication
90
- Unified verification supporting both modern and legacy tokens:
91
-
92
- ```typescript
93
- import { verifyAuthentication } from "@hyve-sdk/js";
13
+ All exports are available on `window.HyveSDK`:
94
14
 
95
- const result = verifyAuthentication({
96
- hyveToken: params.hyveToken, // Modern token format
97
- signature: params.signature, // Legacy format
98
- message: params.message // Legacy format
99
- });
100
-
101
- if (result.isValid) {
102
- console.log('Authenticated address:', result.address);
103
- console.log('Auth method used:', result.method); // 'modern' or 'legacy'
104
- }
15
+ ```js
16
+ const { HyveClient, NativeBridge, NativeMessageType } = window.HyveSDK;
105
17
  ```
106
18
 
107
- #### Modern Token Verification (Hyve Token)
108
- Verify modern authentication tokens with expiration:
19
+ ## Authentication
109
20
 
110
- ```typescript
111
- import { verifyHyveToken } from "@hyve-sdk/js";
21
+ Authenticate using the `hyve-access` JWT passed in the URL:
112
22
 
113
- // Token format: signature.address.randomBase64.timestamp
114
- const address = verifyHyveToken(hyveToken, 600); // 600 seconds max age
115
- if (address) {
116
- console.log('Valid token for address:', address);
117
- }
118
23
  ```
119
-
120
- #### Legacy Token Verification
121
- Verify legacy signed messages with metadata:
122
-
123
- ```typescript
124
- import { handleVerifyMessage, validateSignature } from "@hyve-sdk/js";
125
-
126
- // Method 1: Verify message with embedded metadata
127
- const address = handleVerifyMessage(signature, message);
128
-
129
- // Method 2: Simple signature validation
130
- const isValid = validateSignature(signature, message, userId);
24
+ https://your-game.com?hyve-access=eyJhbGci...&game-id=my-game
131
25
  ```
132
26
 
133
- ### Security Utilities
134
-
135
- #### Domain Validation
136
- Check if current domain is allowed:
137
-
138
- ```typescript
139
- import { isDomainAllowed } from "@hyve-sdk/js";
27
+ ```js
28
+ const { HyveClient } = window.HyveSDK;
140
29
 
141
- // Single domain
142
- const allowed = isDomainAllowed('example.com', window.location.hostname);
143
-
144
- // Multiple domains with wildcard support
145
- const allowed = isDomainAllowed(
146
- ['example.com', '*.subdomain.com'],
147
- window.location.hostname
148
- );
30
+ const client = new HyveClient();
31
+ await client.authenticateFromUrl(window.location.search);
149
32
 
150
- // Note: localhost is always allowed
33
+ console.log('User ID:', client.getUserId());
34
+ console.log('Game ID:', client.getGameId());
151
35
  ```
152
36
 
153
- ### Utility Functions
154
-
155
- #### UUID Generation
156
- Generate random UUID v4:
37
+ **Environment Detection:**
38
+ The SDK automatically detects dev vs prod by checking the parent page URL:
39
+ - **Dev**: `marvin.dev.hyve.gg` or `dev.hyve.gg`
40
+ - **Prod**: `marvin.hyve.gg` or `hyve.gg`
157
41
 
158
- ```typescript
159
- import { generateUUID } from "@hyve-sdk/js";
42
+ ## Telemetry & Analytics
160
43
 
161
- const id = generateUUID();
162
- ```
44
+ Track user actions and game events:
163
45
 
164
- ## Telemetry & Analytics
46
+ ```js
47
+ const { HyveClient } = window.HyveSDK;
165
48
 
166
- ### Send Telemetry Events
167
- Track user actions and game events using JWT authentication:
49
+ const client = new HyveClient();
50
+ await client.authenticateFromUrl(window.location.search);
168
51
 
169
- ```typescript
170
- // Send a user-level telemetry event
171
- // Game ID is automatically extracted from 'game-id' URL parameter
172
52
  await client.sendTelemetry(
173
- 'game', // Event location
174
- 'player', // Event category
175
- 'action', // Event action
176
- 'combat', // Event sub-category (optional)
177
- 'attack', // Event sub-action (optional)
178
- { // Event details - auto-stringified (optional)
53
+ 'game', // location
54
+ 'player', // category
55
+ 'action', // action
56
+ 'combat', // sub-category (optional)
57
+ 'attack', // sub-action (optional)
58
+ { // event details (optional)
179
59
  button: 'attack-btn',
180
- screenPosition: { x: 100, y: 200 },
181
60
  damage: 100,
182
61
  targetId: 'enemy-123',
183
- weaponType: 'sword',
184
- level: 3
185
- },
186
- 'web-chrome' // Platform ID (optional)
62
+ }
187
63
  );
188
64
  ```
189
65
 
190
66
  **Requirements:**
191
- - Requires JWT token (from `hyve-access` URL parameter)
192
- - Requires authenticated user
193
- - Requires game ID (from `game-id` URL parameter)
194
- - User ID is automatically extracted from JWT (cannot be spoofed)
195
-
196
- **URL Parameters Expected:**
197
- - `hyve-access` - JWT authentication token
198
- - `game-id` - Game identifier (associates all telemetry with this game)
199
- - `hyve-token` or `signature`+`message` - For user authentication
200
-
201
- **Features:**
202
- - Automatically includes `session_id` and `game_id` from client
203
- - Objects in `event_details` are auto-stringified to JSON
204
- - Validates `event_details` is valid JSON before sending (returns false if invalid)
205
- - All events tied to authenticated user identity
206
-
207
- ## API Integration
208
-
209
- ### JWT Authentication
210
- The SDK supports JWT tokens and game IDs passed via URL parameters:
211
-
212
- ```typescript
213
- // URL: https://game.com?hyve-access=your-jwt-token&game-id=my-game
67
+ - `hyve-access` JWT in URL
68
+ - `game-id` in URL or JWT
69
+ - User authenticated via `authenticateFromUrl`
214
70
 
215
- // Authenticate extracts JWT and game ID automatically
216
- await client.authenticateFromUrl();
71
+ See [docs/TELEMETRY.md](./docs/TELEMETRY.md) for validation rules and examples.
217
72
 
218
- // Check availability
219
- if (client.hasJwtToken()) {
220
- console.log('JWT token:', client.getJwtToken());
221
- console.log('Game ID:', client.getGameId());
222
- }
223
- ```
73
+ ## API Integration
224
74
 
225
75
  ### Generic API Calls
226
- Make authenticated API requests:
227
76
 
228
- ```typescript
77
+ ```js
229
78
  // GET request
230
79
  const userData = await client.callApi('/api/v1/user');
231
80
 
232
- // POST request with body
81
+ // POST request
233
82
  const result = await client.callApi('/api/v1/game/score', {
234
83
  method: 'POST',
235
84
  body: JSON.stringify({ score: 1000 })
236
85
  });
237
-
238
- // With TypeScript typing
239
- interface UserData {
240
- id: string;
241
- username: string;
242
- }
243
- const user = await client.callApi<UserData>('/api/v1/user');
244
86
  ```
245
87
 
246
- ### Inventory Management
247
-
248
- #### Get User Inventory
249
- Retrieve all inventory items:
88
+ ### Inventory
250
89
 
251
- ```typescript
90
+ ```js
252
91
  const inventory = await client.getInventory();
253
-
254
92
  console.log(`Total items: ${inventory.total_count}`);
255
93
  inventory.items.forEach(item => {
256
94
  console.log(`${item.item_type}: ${item.quantity}x`);
257
95
  });
258
- ```
259
-
260
- **Response Type:**
261
- ```typescript
262
- interface Inventory {
263
- items: InventoryItem[];
264
- total_count: number;
265
- }
266
96
 
267
- interface InventoryItem {
268
- id: string;
269
- user_id: string;
270
- item_type: string;
271
- item_id: string;
272
- quantity: number;
273
- metadata?: Record<string, any>;
274
- created_at: string;
275
- updated_at: string;
276
- }
97
+ const item = await client.getInventoryItem('item-id-123');
277
98
  ```
278
99
 
279
- #### Get Specific Inventory Item
280
- Fetch details for a single item:
281
-
282
- ```typescript
283
- const item = await client.getInventoryItem('item-id-123');
100
+ ## Ads Integration
284
101
 
285
- console.log(`Item: ${item.item_type}`);
286
- console.log(`Quantity: ${item.quantity}`);
287
- if (item.metadata) {
288
- console.log('Metadata:', item.metadata);
289
- }
290
- ```
102
+ Ads are **disabled by default** — must be explicitly enabled.
291
103
 
292
- **API Endpoints:**
293
- - `GET /api/v1/inventory` - Get all inventory items
294
- - `GET /api/v1/inventory/:id` - Get specific item
104
+ ### Prerequisites
295
105
 
296
- ## Ads Integration
106
+ Add the Google H5 Games Ads SDK to your HTML before the Hyve SDK:
297
107
 
298
- The SDK includes support for Google H5 Games Ads. **Ads are disabled by default** and must be explicitly enabled in the configuration.
108
+ ```html
109
+ <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
110
+ <script>
111
+ window.adBreak = window.adBreak || function(o) {
112
+ (window.adsbygoogle = window.adsbygoogle || []).push(o);
113
+ };
114
+ window.adConfig = window.adConfig || function(o) {
115
+ (window.adsbygoogle = window.adsbygoogle || []).push(o);
116
+ };
117
+ </script>
118
+ <script src="https://package.hyve.gg/hyve-sdk.global.js"></script>
119
+ ```
299
120
 
300
121
  ### Quick Start
301
122
 
302
- ```typescript
303
- import { HyveClient } from "@hyve-sdk/js";
123
+ ```js
124
+ const { HyveClient } = window.HyveSDK;
304
125
 
305
- // Enable ads in initial config
306
126
  const client = new HyveClient({
307
127
  ads: {
308
- enabled: true, // Must be set to true
309
- sound: 'on',
310
- debug: true,
311
- onBeforeAd: (type) => {
312
- console.log('Pausing game for ad:', type);
313
- game.pause();
314
- },
315
- onAfterAd: (type) => {
316
- console.log('Resuming game after ad');
317
- game.resume();
318
- },
319
- onRewardEarned: () => {
320
- console.log('User earned reward!');
321
- player.coins += 100;
322
- }
128
+ enabled: true,
129
+ onBeforeAd: (type) => game.pause(),
130
+ onAfterAd: (type) => game.resume(),
131
+ onRewardEarned: () => { player.coins += 100; }
323
132
  }
324
133
  });
325
134
 
326
- // Show different ad types
135
+ await client.authenticateFromUrl(window.location.search);
136
+
327
137
  const result = await client.showAd('rewarded');
328
138
  if (result.success) {
329
139
  console.log('User watched the ad!');
@@ -333,91 +143,38 @@ await client.showAd('interstitial'); // Between levels
333
143
  await client.showAd('preroll'); // Game start
334
144
  ```
335
145
 
336
- ### Prerequisites
337
-
338
- Add the Google H5 Games Ads SDK to your HTML:
339
-
340
- ```html
341
- <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
342
- <script>
343
- window.adBreak = window.adBreak || function(o) {
344
- (window.adsbygoogle = window.adsbygoogle || []).push(o);
345
- };
346
- window.adConfig = window.adConfig || function(o) {
347
- (window.adsbygoogle = window.adsbygoogle || []).push(o);
348
- };
349
- </script>
350
- ```
351
-
352
146
  ### Ad Types
353
147
 
354
148
  | Type | Use Case |
355
149
  |------|----------|
356
- | `rewarded` | User watches full ad for reward (coins, lives, etc.) |
150
+ | `rewarded` | User watches full ad for reward |
357
151
  | `interstitial` | Between levels or game screens |
358
152
  | `preroll` | Before game starts |
359
153
 
360
- ### Configuration
361
-
362
- ```typescript
363
- interface AdConfig {
364
- enabled?: boolean; // Enable/disable ads (default: false)
365
- sound?: 'on' | 'off'; // Sound setting (default: 'on')
366
- debug?: boolean; // Enable debug logging (default: false)
367
- onBeforeAd?: (type) => void; // Called before ad shows
368
- onAfterAd?: (type) => void; // Called after ad finishes
369
- onRewardEarned?: () => void; // Called when user earns reward
370
- }
371
- ```
372
-
373
- ### Methods
374
-
375
- ```typescript
376
- // Configure ads after initialization
377
- client.configureAds({ enabled: true, sound: 'off' });
378
-
379
- // Show an ad
380
- const result = await client.showAd('rewarded');
381
-
382
- // Check status
383
- client.areAdsEnabled(); // Boolean
384
- client.areAdsReady(); // Boolean
385
- ```
386
-
387
- See [docs/ads.md](./docs/ads.md) for detailed documentation and examples.
388
-
389
- **Requirements:**
390
- - JWT token must be available (via `hyve-access` URL parameter)
391
- - User must be authenticated
154
+ See [docs/ads.md](./docs/ads.md) for detailed documentation.
392
155
 
393
156
  ## Billing Integration
394
157
 
395
- The SDK includes unified billing support for both web (Stripe) and native (In-App Purchases) platforms. Billing automatically detects the platform and routes to the appropriate payment method.
158
+ Unified billing for web (Stripe) and native (In-App Purchases). Platform is detected automatically.
396
159
 
397
160
  ### Quick Start
398
161
 
399
- ```typescript
400
- import { HyveClient } from "@hyve-sdk/js";
162
+ ```js
163
+ const { HyveClient } = window.HyveSDK;
401
164
 
402
- // Enable billing in initial config
403
165
  const client = new HyveClient({
404
166
  billing: {
405
- stripePublishableKey: 'pk_test_...',
406
- checkoutUrl: 'https://your-api.com',
167
+ stripePublishableKey: 'pk_live_...',
168
+ checkoutUrl: 'https://checkout-api.hyve.gg',
407
169
  }
408
170
  });
409
171
 
410
- // Authenticate user
411
172
  await client.authenticateFromUrl(window.location.search);
412
-
413
- // Initialize billing (uses client's userId and gameId automatically)
414
173
  const initialized = await client.initializeBilling();
415
174
 
416
175
  if (initialized && client.isBillingAvailable()) {
417
- // Set up purchase callbacks
418
176
  client.onPurchaseComplete((result) => {
419
177
  console.log('Purchase successful!', result.transactionId);
420
- // Refresh inventory
421
178
  client.getInventory().then(inv => console.log('Updated inventory:', inv));
422
179
  });
423
180
 
@@ -425,409 +182,166 @@ if (initialized && client.isBillingAvailable()) {
425
182
  console.error('Purchase failed:', result.error?.message);
426
183
  });
427
184
 
428
- // Get available products
429
185
  const products = await client.getBillingProducts();
430
- console.log('Available products:', products);
431
-
432
- // Purchase a product
433
- await client.purchaseProduct('price_1234', {
434
- elementId: 'stripe-checkout-element' // For web platform
435
- });
186
+ await client.purchaseProduct('price_1234');
436
187
  }
437
188
  ```
438
189
 
439
190
  ### Platform Support
440
191
 
441
- The SDK automatically detects the platform and uses the appropriate billing method:
442
-
443
- | Platform | Payment Method | Requirements |
444
- |----------|---------------|--------------|
445
- | Web | Stripe Embedded Checkout | Stripe publishable key |
446
- | Native (iOS/Android) | In-App Purchases | Native app integration |
192
+ | Platform | Payment Method | Detection |
193
+ |----------|---------------|-----------|
194
+ | Web | Stripe Embedded Checkout | Default (no ReactNativeWebView) |
195
+ | Native (iOS/Android) | In-App Purchases | `ReactNativeWebView` in window |
447
196
 
448
197
  ### Prerequisites
449
198
 
450
- For web platform, add a container element for Stripe checkout:
199
+ For web, add a container element for the Stripe checkout UI:
451
200
 
452
201
  ```html
453
202
  <div id="stripe-checkout-element"></div>
454
203
  ```
455
204
 
456
- Stripe.js will be loaded automatically by the SDK.
457
-
458
- For native platform, ensure the mobile app implements the Native Bridge billing messages.
459
-
460
- ### Configuration
461
-
462
- ```typescript
463
- interface BillingConfig {
464
- stripePublishableKey?: string; // Stripe key for web (required for web)
465
- checkoutUrl?: string; // API endpoint for checkout
466
- gameId?: number; // Game identifier
467
- userId?: string; // User identifier
468
- }
469
- ```
470
-
471
- Note: When using billing through HyveClient, `userId` and `gameId` are automatically populated from the authenticated user.
472
-
473
- ### Methods
474
-
475
- ```typescript
476
- // Configure billing after initialization
477
- client.configureBilling({
478
- stripePublishableKey: 'pk_live_...',
479
- checkoutUrl: 'https://api.example.com'
480
- });
481
-
482
- // Initialize billing
483
- await client.initializeBilling();
484
-
485
- // Check platform and availability
486
- const platform = client.getBillingPlatform(); // 'web' | 'native' | 'unknown'
487
- const available = client.isBillingAvailable(); // Boolean
488
-
489
- // Get products
490
- const products = await client.getBillingProducts();
491
-
492
- // Purchase a product
493
- const result = await client.purchaseProduct(productId, {
494
- elementId: 'stripe-checkout-element' // Optional, defaults to 'stripe-checkout-element'
495
- });
496
-
497
- // Set up callbacks
498
- client.onPurchaseComplete((result) => {
499
- console.log('Success!', result);
500
- });
501
-
502
- client.onPurchaseError((result) => {
503
- console.error('Failed:', result.error);
504
- });
505
-
506
- // Optional: Listen to billing logs
507
- client.onBillingLog((level, message, data) => {
508
- console.log(`[${level}] ${message}`, data);
509
- });
510
-
511
- // Clean up checkout UI
512
- client.unmountBillingCheckout();
513
- ```
514
-
515
- ### Product Interface
516
-
517
- ```typescript
518
- interface BillingProduct {
519
- productId: string; // Product/price ID
520
- title: string; // Product name
521
- description: string; // Product description
522
- price: number; // Price in dollars (e.g., 9.99)
523
- localizedPrice: string; // Formatted price (e.g., "$9.99")
524
- currency: string; // Currency code (e.g., "USD")
525
- }
526
- ```
527
-
528
- ### Purchase Result
529
-
530
- ```typescript
531
- interface PurchaseResult {
532
- success: boolean;
533
- productId: string;
534
- transactionId?: string;
535
- transactionDate?: string;
536
- error?: {
537
- code: string;
538
- message: string;
539
- };
540
- }
541
- ```
542
-
543
- ### Complete Example with Telemetry
544
-
545
- ```typescript
546
- const client = new HyveClient({
547
- billing: {
548
- stripePublishableKey: process.env.VITE_STRIPE_KEY,
549
- checkoutUrl: process.env.VITE_CHECKOUT_URL,
550
- }
551
- });
552
-
553
- // Authenticate
554
- await client.authenticateFromUrl();
555
-
556
- // Initialize billing
557
- await client.initializeBilling();
558
-
559
- // Set up callbacks with telemetry
560
- client.onPurchaseComplete((result) => {
561
- // Send success telemetry
562
- client.sendTelemetry(
563
- 'shop',
564
- 'purchase',
565
- 'complete',
566
- 'success',
567
- null,
568
- { productId: result.productId, transactionId: result.transactionId }
569
- );
570
-
571
- // Refresh inventory
572
- client.getInventory();
573
- });
574
-
575
- client.onPurchaseError((result) => {
576
- // Send error telemetry
577
- client.sendTelemetry(
578
- 'shop',
579
- 'purchase',
580
- 'error',
581
- 'failed',
582
- null,
583
- {
584
- productId: result.productId,
585
- errorCode: result.error?.code,
586
- errorMessage: result.error?.message
587
- }
588
- );
589
- });
590
-
591
- // Get and display products
592
- const products = await client.getBillingProducts();
593
- ```
594
-
595
- See [docs/examples/billing-with-client-example.ts](./docs/examples/billing-with-client-example.ts) for detailed examples including React components and Phaser integration.
596
-
597
- **Requirements:**
598
- - JWT token must be available (via `hyve-access` URL parameter)
599
- - User must be authenticated
600
- - Game ID must be available (via `game-id` URL parameter or JWT)
601
- - For web: Stripe publishable key required
602
- - For native: Mobile app must implement Native Bridge billing integration
205
+ See [docs/BILLING_INTEGRATION.md](./docs/BILLING_INTEGRATION.md) for full documentation and examples.
603
206
 
604
207
  ## Native Bridge (React Native WebView)
605
208
 
606
- Provides type-safe bidirectional communication between your web application and the React Native mobile app.
209
+ Type-safe bidirectional communication between your web game and a React Native mobile app.
607
210
 
608
211
  ### Quick Start
609
212
 
610
- ```typescript
611
- import { NativeBridge, NativeMessageType } from "@hyve-sdk/js";
213
+ ```js
214
+ const { NativeBridge } = window.HyveSDK;
612
215
 
613
- // Initialize on app start
614
216
  if (NativeBridge.isNativeContext()) {
615
217
  NativeBridge.initialize();
616
218
  }
617
219
  ```
618
220
 
619
- ### Check IAP Availability
221
+ ### IAP Availability
620
222
 
621
- Request information about In-App Purchase availability:
622
-
623
- ```typescript
624
- // Register response handler
625
- NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
223
+ ```js
224
+ NativeBridge.on('IAP_AVAILABILITY_RESULT', (payload) => {
626
225
  if (payload.available) {
627
- console.log("IAP is available on this device");
628
- // Show purchase UI
629
- } else {
630
- console.log("IAP is not available");
631
- // Hide purchase features
226
+ console.log('IAP available on platform:', payload.platform);
632
227
  }
633
228
  });
634
229
 
635
- // Send request
636
230
  NativeBridge.checkIAPAvailability();
637
231
  ```
638
232
 
639
- ### Request Push Notifications
640
-
641
- Request notification permissions from the native app:
233
+ ### Push Notifications
642
234
 
643
- ```typescript
644
- // Register response handlers
645
- NativeBridge.on("PUSH_PERMISSION_GRANTED", (payload) => {
646
- console.log("Push notifications enabled");
647
- console.log("Token:", payload?.token);
235
+ ```js
236
+ NativeBridge.on('PUSH_PERMISSION_GRANTED', (payload) => {
237
+ console.log('Token:', payload?.token);
648
238
  });
649
239
 
650
- NativeBridge.on("PUSH_PERMISSION_DENIED", () => {
651
- console.log("Push notifications disabled");
240
+ NativeBridge.on('PUSH_PERMISSION_DENIED', () => {
241
+ console.log('Permission denied');
652
242
  });
653
243
 
654
- // Send request
655
244
  NativeBridge.requestNotificationPermission();
656
245
  ```
657
246
 
658
- ### Send Custom Messages
247
+ ### Custom Messages
659
248
 
660
- Send custom messages to the native app:
249
+ ```js
250
+ NativeBridge.send('GAME_EVENT', { action: 'level_complete', level: 3 });
661
251
 
662
- ```typescript
663
- // Send message with payload
664
- NativeBridge.send("CUSTOM_EVENT", {
665
- action: "open_settings",
666
- data: { setting: "notifications" }
667
- });
668
-
669
- // Listen for custom responses
670
- NativeBridge.on("CUSTOM_RESPONSE", (payload) => {
671
- console.log("Received:", payload);
252
+ NativeBridge.on('CUSTOM_RESPONSE', (payload) => {
253
+ console.log('Received:', payload);
672
254
  });
673
255
  ```
674
256
 
675
- ### Built-in Message Types
676
-
677
- **Web → Native:**
678
- - `CHECK_IAP_AVAILABILITY` - Check if IAP is available
679
- - `REQUEST_NOTIFICATION_PERMISSION` - Request push notification permission
680
-
681
- **Native → Web:**
682
- - `IAP_AVAILABILITY_RESULT` - Response with IAP availability
683
- - `PUSH_PERMISSION_GRANTED` - Push permission granted
684
- - `PUSH_PERMISSION_DENIED` - Push permission denied
685
-
686
257
  ### API Reference
687
258
 
688
- - `NativeBridge.isNativeContext()` - Check if running in React Native WebView
689
- - `NativeBridge.initialize()` - Initialize message listener
690
- - `NativeBridge.send(type, payload?)` - Send message to native
691
- - `NativeBridge.on(type, handler)` - Register message handler
692
- - `NativeBridge.off(type)` - Unregister message handler
693
- - `NativeBridge.clearHandlers()` - Clear all handlers
694
- - `NativeBridge.checkIAPAvailability()` - Helper for IAP check
695
- - `NativeBridge.requestNotificationPermission()` - Helper for notification permission
259
+ - `NativeBridge.isNativeContext()` Check if running in React Native WebView
260
+ - `NativeBridge.initialize()` Start message listener
261
+ - `NativeBridge.send(type, payload?)` Send message to native
262
+ - `NativeBridge.on(type, handler)` Register message handler
263
+ - `NativeBridge.off(type)` Remove message handler
264
+ - `NativeBridge.clearHandlers()` Remove all handlers
265
+ - `NativeBridge.checkIAPAvailability()` Request IAP availability
266
+ - `NativeBridge.requestNotificationPermission()` Request notification permission
696
267
 
697
- For complete documentation, see [docs/NATIVE_BRIDGE.md](./docs/NATIVE_BRIDGE.md).
268
+ See [docs/NATIVE_BRIDGE.md](./docs/NATIVE_BRIDGE.md) for full documentation.
698
269
 
699
270
  ## Logger
700
271
 
701
- The SDK includes a built-in logger that's automatically enabled in development environments.
702
-
703
- ### Quick Start
704
-
705
- ```typescript
706
- import { logger } from "@hyve-sdk/js";
707
-
708
- logger.debug("Debug information", { data: "value" });
709
- logger.info("Informational message");
710
- logger.warn("Warning message");
711
- logger.error("Error message", error);
712
- ```
713
-
714
- ### Configuration
272
+ ```js
273
+ const { logger } = window.HyveSDK;
715
274
 
716
- **Automatic Behavior:**
717
- - **Development** (`NODE_ENV !== 'production'`): Logging enabled by default
718
- - **Production** (`NODE_ENV === 'production'`): Logging disabled by default
719
-
720
- **Browser Override:**
721
- ```javascript
722
- // Enable specific log levels
723
- localStorage.setItem('HYVE_SDK_LOG_LEVEL', 'error,warn');
724
- ```
725
-
726
- **Node.js Override:**
727
- ```bash
728
- HYVE_SDK_LOG_LEVEL=error,warn node app.js
729
- ```
730
-
731
- **Programmatic Control:**
732
- ```typescript
733
- import { Logger } from "@hyve-sdk/js";
734
-
735
- const logger = new Logger();
736
- logger.setLevels(['error', 'warn']);
737
- ```
738
-
739
- ### Child Loggers
740
-
741
- Create namespaced loggers for different parts of your application:
742
-
743
- ```typescript
744
- import { logger } from "@hyve-sdk/js";
275
+ logger.debug('Debug info', { data: 'value' });
276
+ logger.info('Informational message');
277
+ logger.warn('Warning message');
278
+ logger.error('Error message', error);
745
279
 
280
+ // Namespaced child loggers
746
281
  const gameLogger = logger.child('Game');
747
282
  gameLogger.info('Game started');
748
283
  // Output: [Hyve SDK] [Game] [INFO] [timestamp] Game started
749
-
750
- const uiLogger = logger.child('UI');
751
- uiLogger.debug('Button clicked');
752
- // Output: [Hyve SDK] [UI] [DEBUG] [timestamp] Button clicked
753
284
  ```
754
285
 
755
- ### Features
756
-
757
- - **Automatic environment detection**: Enables/disables based on NODE_ENV
758
- - **Configurable log levels**: debug, info, warn, error
759
- - **Timestamps**: All logs include ISO 8601 timestamps
760
- - **Prefixed output**: All logs prefixed with `[Hyve SDK]`
761
- - **Child loggers**: Create namespaced loggers for different modules
762
- - **Browser storage**: Log level persists in localStorage
286
+ **Log level override (browser):**
287
+ ```js
288
+ localStorage.setItem('HYVE_SDK_LOG_LEVEL', 'error,warn');
289
+ ```
763
290
 
764
291
  ## Client Methods Reference
765
292
 
766
293
  ### Authentication
767
- - `authenticateFromUrl(urlParams?)` - Authenticate from URL parameters (extracts JWT, game ID, user auth)
768
- - `getUserId()` - Get authenticated user ID (address)
769
- - `getSessionId()` - Get unique session ID
770
- - `getGameId()` - Get game ID from URL parameters
771
- - `isUserAuthenticated()` - Check if user is authenticated
772
- - `hasJwtToken()` - Check if JWT token is available
773
- - `getJwtToken()` - Get JWT token string
774
- - `logout()` - Clear user authentication
775
- - `reset()` - Reset client state with new session
776
-
777
- ### API Calls
778
- - `callApi<T>(endpoint, options?)` - Generic authenticated API call
779
- - `getInventory()` - Get user's inventory
780
- - `getInventoryItem(itemId)` - Get specific inventory item
294
+ - `authenticateFromUrl(urlParams)` Extract JWT and game ID from URL, authenticate user
295
+ - `getUserId()` Authenticated user ID
296
+ - `getSessionId()` Unique session ID
297
+ - `getGameId()` Game ID from URL or JWT
298
+ - `isUserAuthenticated()` Check if authenticated
299
+ - `hasJwtToken()` Check if JWT available
300
+ - `getJwtToken()` Get JWT string
301
+ - `logout()` Clear authentication
302
+ - `reset()` Reset client state
303
+
304
+ ### API
305
+ - `callApi<T>(endpoint, options?)` Authenticated API call
306
+ - `getInventory()` Get user inventory
307
+ - `getInventoryItem(itemId)` Get specific inventory item
781
308
 
782
309
  ### Telemetry
783
- - `sendTelemetry(location, category, action, subCategory?, subAction?, details?, platformId?)` - Send JWT-authenticated analytics event (uses game ID from URL)
784
- - `updateTelemetryConfig(config)` - Update telemetry settings
310
+ - `sendTelemetry(location, category, action, subCategory?, subAction?, details?)` Send analytics event
311
+ - `updateTelemetryConfig(config)` Update telemetry settings
785
312
 
786
313
  ### Ads
787
- - `configureAds(config)` - Configure ads service
788
- - `showAd(type)` - Show an ad ('rewarded', 'interstitial', or 'preroll')
789
- - `areAdsEnabled()` - Check if ads are enabled
790
- - `areAdsReady()` - Check if ads are ready to show
791
-
792
- ### Configuration
793
- - `getApiBaseUrl()` - Get current API base URL
794
- - `updateTelemetryConfig(config)` - Update client configuration
795
-
796
- ## Authentication Flow
797
-
798
- ### Modern Token Flow (Recommended)
799
- 1. User authenticates on platform
800
- 2. Platform generates hyve-token: `signature.address.random.timestamp`
801
- 3. Token passed via URL parameter `hyve-token`
802
- 4. SDK verifies token with `verifyHyveToken()` or `verifyAuthentication()`
803
-
804
- ### Legacy Token Flow
805
- 1. User signs message containing metadata (expiration, address)
806
- 2. Signature and message passed via URL parameters
807
- 3. SDK verifies with `handleVerifyMessage()` or `verifyAuthentication()`
314
+ - `configureAds(config)` Configure ads service
315
+ - `showAd(type)` Show an ad (`'rewarded'` | `'interstitial'` | `'preroll'`)
316
+ - `areAdsEnabled()` Check if ads are enabled
317
+ - `areAdsReady()` Check if ads are ready
318
+
319
+ ### Billing
320
+ - `configureBilling(config)` Configure billing service
321
+ - `initializeBilling()` Initialize billing (resolves platform automatically)
322
+ - `getBillingPlatform()` — `'web'` | `'native'` | `'unknown'`
323
+ - `isBillingAvailable()` — Check if billing is ready
324
+ - `getBillingProducts()` — Fetch available products
325
+ - `purchaseProduct(productId, options?)` Initiate purchase
326
+ - `onPurchaseComplete(callback)` Register purchase success handler
327
+ - `onPurchaseError(callback)` Register purchase error handler
328
+ - `unmountBillingCheckout()` Clean up Stripe checkout UI
808
329
 
809
330
  ## Security Considerations
810
331
 
811
- - **Token Expiration**: Modern tokens expire after 10 minutes by default
812
- - **Domain Validation**: Always validate origin domains in production
813
- - **Signature Verification**: All signatures verified using ethers.js
814
- - **Localhost Exception**: localhost always allowed for development
332
+ - Never expose secret keys in game code
333
+ - Always validate receipts server-side
334
+ - Use HTTPS for all requests
335
+ - Don't trust client-reported prices
336
+ - Verify user authentication before crediting purchases
815
337
 
816
- ## TypeScript Support
338
+ ## Build Output
817
339
 
818
- Full TypeScript support with exported types for all utilities and return values.
819
-
820
- ## Dependencies
821
-
822
- - **ethers**: ^6.13.7 - Ethereum signature verification
823
- - **uuid**: (peer dependency) - UUID generation
824
-
825
- ## Build Configuration
826
-
827
- The SDK builds to multiple formats:
828
- - CommonJS (`dist/index.js`)
829
- - ES Modules (`dist/index.mjs`)
830
- - TypeScript declarations (`dist/index.d.ts`)
340
+ | Format | File | Use |
341
+ |--------|------|-----|
342
+ | CJS | `dist/index.js` | Node.js / bundler |
343
+ | ESM | `dist/index.mjs` | Bundler (tree-shakeable) |
344
+ | IIFE | `dist/hyve-sdk.global.js` | CDN / script tag |
831
345
 
832
346
  ## Development
833
347
 
@@ -847,16 +361,13 @@ bun run build
847
361
 
848
362
  ## Documentation
849
363
 
850
- For complete documentation and examples, visit [https://docs.hyve.gg](https://docs.hyve.gg)
851
-
852
- ### Additional Guides
853
-
854
- - [Telemetry Guide](./docs/TELEMETRY.md) - Best practices, validation rules, and examples for event tracking
855
- - [Billing Integration](./docs/BILLING_INTEGRATION.md) - Platform-aware billing with Stripe and In-App Purchases
856
- - [Billing Migration Guide](./docs/BILLING_MIGRATION_GUIDE.md) - Upgrading from older billing implementations
857
- - [Ads Integration](./docs/ads.md) - Google H5 Games Ads integration
858
- - [Native Bridge](./docs/NATIVE_BRIDGE.md) - React Native WebView communication
364
+ - [Telemetry Guide](./docs/TELEMETRY.md)
365
+ - [Billing Integration](./docs/BILLING_INTEGRATION.md)
366
+ - [Billing Migration Guide](./docs/BILLING_MIGRATION_GUIDE.md)
367
+ - [Ads Integration](./docs/ads.md)
368
+ - [Native Bridge](./docs/NATIVE_BRIDGE.md)
369
+ - [Platform-Aware Billing](./docs/PLATFORM_AWARE_BILLING.md)
859
370
 
860
371
  ## License
861
372
 
862
- MIT
373
+ MIT