@hyve-sdk/js 1.1.2 → 1.3.1-canary.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
@@ -20,6 +20,7 @@ pnpm add @hyve-sdk/js
20
20
  - **API Integration**: Authenticated API calls with JWT token support
21
21
  - **Inventory Management**: Built-in methods for user inventory operations
22
22
  - **Telemetry Tracking**: Session-based analytics and event tracking
23
+ - **Native Bridge**: Type-safe communication with React Native WebView apps
23
24
  - **Security Utilities**: Domain validation and referrer checking
24
25
  - **URL Parameter Parsing**: Easy extraction of authentication parameters
25
26
  - **UUID Generation**: Built-in UUID v4 generation
@@ -34,17 +35,18 @@ import { HyveClient } from "@hyve-sdk/js";
34
35
 
35
36
  // Initialize with optional configuration
36
37
  const client = new HyveClient({
37
- apiKey: 'your-api-key', // For telemetry
38
38
  isDev: true, // Development mode (default: true)
39
39
  apiBaseUrl: 'https://...' // Optional custom API URL
40
40
  });
41
41
 
42
42
  // Authenticate from URL parameters
43
+ // Extracts: hyve-token/signature, hyve-access (JWT), game-id
43
44
  const authenticated = await client.authenticateFromUrl();
44
45
  if (authenticated) {
45
46
  console.log('User ID:', client.getUserId());
46
47
  console.log('Session ID:', client.getSessionId());
47
48
  console.log('Has JWT:', client.hasJwtToken());
49
+ console.log('Game ID:', client.getGameId());
48
50
  }
49
51
  ```
50
52
 
@@ -61,10 +63,11 @@ const params = parseUrlParams(window.location.search);
61
63
  // {
62
64
  // signature: string,
63
65
  // message: string,
64
- // userId: string,
65
66
  // gameStartTab: string,
66
67
  // hyveToken: string,
67
- // platform: string
68
+ // platform: string,
69
+ // hyveAccess: string, // JWT token
70
+ // gameId: string // Game identifier
68
71
  // }
69
72
  ```
70
73
 
@@ -146,46 +149,62 @@ const id = generateUUID();
146
149
  ## Telemetry & Analytics
147
150
 
148
151
  ### Send Telemetry Events
149
- Track user actions and game events:
152
+ Track user actions and game events using JWT authentication:
150
153
 
151
154
  ```typescript
152
- // Send a custom telemetry event
155
+ // Send a user-level telemetry event
156
+ // Game ID is automatically extracted from 'game-id' URL parameter
153
157
  await client.sendTelemetry(
154
158
  'game', // Event location
155
159
  'player', // Event category
156
160
  'action', // Event action
157
161
  'combat', // Event sub-category (optional)
158
162
  'attack', // Event sub-action (optional)
159
- null, // Event details string (optional)
160
- { // Additional data (optional)
163
+ { // Event details - auto-stringified (optional)
164
+ button: 'attack-btn',
165
+ screenPosition: { x: 100, y: 200 }
166
+ },
167
+ { // Custom data - auto-stringified (optional)
161
168
  damage: 100,
162
169
  targetId: 'enemy-123',
163
- weaponType: 'sword'
164
- }
170
+ weaponType: 'sword',
171
+ level: 3
172
+ },
173
+ 'web-chrome' // Platform ID (optional)
165
174
  );
166
175
  ```
167
176
 
168
- **Configuration:**
169
- - Requires `apiKey` in client configuration
170
- - Automatically includes `session_id` and `user_id`
171
- - Additional data is JSON-stringified into `event_details`
172
- - Supports anonymous telemetry (without authentication)
177
+ **Requirements:**
178
+ - Requires JWT token (from `hyve-access` URL parameter)
179
+ - Requires authenticated user
180
+ - Requires game ID (from `game-id` URL parameter)
181
+ - User ID is automatically extracted from JWT (cannot be spoofed)
182
+
183
+ **URL Parameters Expected:**
184
+ - `hyve-access` - JWT authentication token
185
+ - `game-id` - Game identifier (associates all telemetry with this game)
186
+ - `hyve-token` or `signature`+`message` - For user authentication
187
+
188
+ **Features:**
189
+ - Automatically includes `session_id` and `game_id` from client
190
+ - Objects in `event_details` and `custom_data` are auto-stringified to JSON
191
+ - All events tied to authenticated user identity
173
192
 
174
193
  ## API Integration
175
194
 
176
195
  ### JWT Authentication
177
- The SDK supports JWT tokens passed via URL parameter `hyve-access`:
196
+ The SDK supports JWT tokens and game IDs passed via URL parameters:
178
197
 
179
198
  ```typescript
180
- // URL: https://game.com?hyve-access=your-jwt-token
199
+ // URL: https://game.com?hyve-access=your-jwt-token&game-id=my-game
181
200
 
182
- // Authenticate extracts JWT automatically
201
+ // Authenticate extracts JWT and game ID automatically
183
202
  await client.authenticateFromUrl();
184
203
 
185
- // Check JWT availability
204
+ // Check availability
186
205
  if (client.hasJwtToken()) {
187
- const token = client.getJwtToken();
188
- console.log('JWT token available');
206
+ console.log('JWT token:', client.getJwtToken());
207
+ console.log('Game ID:', client.getGameId());
189
208
  }
190
209
  ```
191
210
 
@@ -264,12 +283,108 @@ if (item.metadata) {
264
283
  - JWT token must be available (via `hyve-access` URL parameter)
265
284
  - User must be authenticated
266
285
 
286
+ ## Native Bridge (React Native WebView)
287
+
288
+ Provides type-safe bidirectional communication between your web application and the React Native mobile app.
289
+
290
+ ### Quick Start
291
+
292
+ ```typescript
293
+ import { NativeBridge, NativeMessageType } from "@hyve-sdk/js";
294
+
295
+ // Initialize on app start
296
+ if (NativeBridge.isNativeContext()) {
297
+ NativeBridge.initialize();
298
+ }
299
+ ```
300
+
301
+ ### Check IAP Availability
302
+
303
+ Request information about In-App Purchase availability:
304
+
305
+ ```typescript
306
+ // Register response handler
307
+ NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
308
+ if (payload.available) {
309
+ console.log("IAP is available on this device");
310
+ // Show purchase UI
311
+ } else {
312
+ console.log("IAP is not available");
313
+ // Hide purchase features
314
+ }
315
+ });
316
+
317
+ // Send request
318
+ NativeBridge.checkIAPAvailability();
319
+ ```
320
+
321
+ ### Request Push Notifications
322
+
323
+ Request notification permissions from the native app:
324
+
325
+ ```typescript
326
+ // Register response handlers
327
+ NativeBridge.on("PUSH_PERMISSION_GRANTED", (payload) => {
328
+ console.log("Push notifications enabled");
329
+ console.log("Token:", payload?.token);
330
+ });
331
+
332
+ NativeBridge.on("PUSH_PERMISSION_DENIED", () => {
333
+ console.log("Push notifications disabled");
334
+ });
335
+
336
+ // Send request
337
+ NativeBridge.requestNotificationPermission();
338
+ ```
339
+
340
+ ### Send Custom Messages
341
+
342
+ Send custom messages to the native app:
343
+
344
+ ```typescript
345
+ // Send message with payload
346
+ NativeBridge.send("CUSTOM_EVENT", {
347
+ action: "open_settings",
348
+ data: { setting: "notifications" }
349
+ });
350
+
351
+ // Listen for custom responses
352
+ NativeBridge.on("CUSTOM_RESPONSE", (payload) => {
353
+ console.log("Received:", payload);
354
+ });
355
+ ```
356
+
357
+ ### Built-in Message Types
358
+
359
+ **Web → Native:**
360
+ - `CHECK_IAP_AVAILABILITY` - Check if IAP is available
361
+ - `REQUEST_NOTIFICATION_PERMISSION` - Request push notification permission
362
+
363
+ **Native → Web:**
364
+ - `IAP_AVAILABILITY_RESULT` - Response with IAP availability
365
+ - `PUSH_PERMISSION_GRANTED` - Push permission granted
366
+ - `PUSH_PERMISSION_DENIED` - Push permission denied
367
+
368
+ ### API Reference
369
+
370
+ - `NativeBridge.isNativeContext()` - Check if running in React Native WebView
371
+ - `NativeBridge.initialize()` - Initialize message listener
372
+ - `NativeBridge.send(type, payload?)` - Send message to native
373
+ - `NativeBridge.on(type, handler)` - Register message handler
374
+ - `NativeBridge.off(type)` - Unregister message handler
375
+ - `NativeBridge.clearHandlers()` - Clear all handlers
376
+ - `NativeBridge.checkIAPAvailability()` - Helper for IAP check
377
+ - `NativeBridge.requestNotificationPermission()` - Helper for notification permission
378
+
379
+ For complete documentation, see [docs/NATIVE_BRIDGE.md](./docs/NATIVE_BRIDGE.md).
380
+
267
381
  ## Client Methods Reference
268
382
 
269
383
  ### Authentication
270
- - `authenticateFromUrl(urlParams?)` - Authenticate from URL parameters
384
+ - `authenticateFromUrl(urlParams?)` - Authenticate from URL parameters (extracts JWT, game ID, user auth)
271
385
  - `getUserId()` - Get authenticated user ID (address)
272
386
  - `getSessionId()` - Get unique session ID
387
+ - `getGameId()` - Get game ID from URL parameters
273
388
  - `isUserAuthenticated()` - Check if user is authenticated
274
389
  - `hasJwtToken()` - Check if JWT token is available
275
390
  - `getJwtToken()` - Get JWT token string
@@ -282,7 +397,7 @@ if (item.metadata) {
282
397
  - `getInventoryItem(itemId)` - Get specific inventory item
283
398
 
284
399
  ### Telemetry
285
- - `sendTelemetry(location, category, action, subCategory?, subAction?, details?, additionalData?)` - Send analytics event
400
+ - `sendTelemetry(location, category, action, subCategory?, subAction?, details?, customData?, platformId?)` - Send JWT-authenticated analytics event (uses game ID from URL)
286
401
  - `updateTelemetryConfig(config)` - Update telemetry settings
287
402
 
288
403
  ### Configuration
package/dist/index.d.mts CHANGED
@@ -2,33 +2,39 @@
2
2
  * Telemetry configuration options
3
3
  */
4
4
  interface TelemetryConfig {
5
- /** API key for telemetry service */
6
- apiKey?: string;
7
5
  /** Environment: true for dev, false for prod. Defaults to true (dev) */
8
6
  isDev?: boolean;
9
7
  /** Base API URL for all API calls (telemetry and external). Can be set via env. If not provided, defaults based on isDev */
10
8
  apiBaseUrl?: string;
11
9
  }
12
10
  /**
13
- * Telemetry event data structure
11
+ * Telemetry event data structure for user-level events (JWT authenticated)
12
+ * Matches backend SendTelemetryRequest model
13
+ * Note: hyve_user_id is extracted from JWT by backend, not sent in request
14
14
  */
15
15
  interface TelemetryEvent {
16
- /** Unique session identifier */
16
+ /** Game identifier (required) */
17
+ game_id: string;
18
+ /** Unique session identifier (required) */
17
19
  session_id: string;
18
- /** Hyve user identifier (address) */
19
- hyve_user_id: string;
20
- /** Location where the event occurred */
20
+ /** Platform/user identifier (optional) */
21
+ platform_id?: string | null;
22
+ /** Location where the event occurred (required) */
21
23
  event_location: string;
22
- /** Main category of the event */
24
+ /** Main category of the event (required) */
23
25
  event_category: string;
24
- /** Primary action taken */
26
+ /** Sub-category for more granular classification (optional) */
27
+ event_sub_category?: string | null;
28
+ /** Primary action taken (required) */
25
29
  event_action: string;
26
- /** Sub-category for more granular classification (null if not provided) */
27
- event_sub_category: string | null;
28
- /** Sub-action for detailed tracking (null if not provided) */
29
- event_sub_action: string | null;
30
- /** Additional data as JSON string (null if not provided) */
31
- event_details: string | null;
30
+ /** Sub-action for detailed tracking (optional) */
31
+ event_sub_action?: string | null;
32
+ /** Event details as JSON string or object (optional) */
33
+ event_details?: Record<string, any> | string | null;
34
+ /** Mapping details as JSON string or object (optional) */
35
+ mapping_details?: Record<string, any> | string | null;
36
+ /** Custom data as JSON string or object (optional) */
37
+ custom_data?: Record<string, any> | string | null;
32
38
  }
33
39
  /**
34
40
  * Additional telemetry data that can be passed with events
@@ -67,6 +73,7 @@ declare class HyveClient {
67
73
  private sessionId;
68
74
  private userId;
69
75
  private jwtToken;
76
+ private gameId;
70
77
  /**
71
78
  * Creates a new HyveClient instance
72
79
  * @param config Optional telemetry configuration
@@ -79,17 +86,19 @@ declare class HyveClient {
79
86
  */
80
87
  authenticateFromUrl(urlParams?: URLSearchParams | string): Promise<boolean>;
81
88
  /**
82
- * Sends a telemetry event
89
+ * Sends a user-level telemetry event using JWT authentication
90
+ * Requires JWT token, authenticated user, and game ID from URL parameters
83
91
  * @param eventLocation Location where the event occurred
84
92
  * @param eventCategory Main category of the event
85
93
  * @param eventAction Primary action taken
86
94
  * @param eventSubCategory Optional sub-category
87
95
  * @param eventSubAction Optional sub-action
88
- * @param eventDetails Optional event details
89
- * @param additionalData Optional additional data
96
+ * @param eventDetails Optional event details (object or JSON string)
97
+ * @param customData Optional custom data (object or JSON string)
98
+ * @param platformId Optional platform identifier
90
99
  * @returns Promise resolving to boolean indicating success
91
100
  */
92
- sendTelemetry(eventLocation: string, eventCategory: string, eventAction: string, eventSubCategory?: string | null, eventSubAction?: string | null, eventDetails?: string | null, additionalData?: TelemetryAdditionalData | null): Promise<boolean>;
101
+ sendTelemetry(eventLocation: string, eventCategory: string, eventAction: string, eventSubCategory?: string | null, eventSubAction?: string | null, eventDetails?: Record<string, any> | string | null, customData?: Record<string, any> | null, platformId?: string | null): Promise<boolean>;
93
102
  /**
94
103
  * Makes an authenticated API call using the JWT token
95
104
  * @param endpoint API endpoint path (will be appended to base URL)
@@ -128,6 +137,11 @@ declare class HyveClient {
128
137
  * @returns Current JWT token or null if not available
129
138
  */
130
139
  getJwtToken(): string | null;
140
+ /**
141
+ * Gets the current game ID
142
+ * @returns Current game ID or null if not available
143
+ */
144
+ getGameId(): string | null;
131
145
  /**
132
146
  * Gets the API base URL
133
147
  * @returns API base URL
@@ -153,6 +167,53 @@ declare class HyveClient {
153
167
  reset(): void;
154
168
  }
155
169
 
170
+ /**
171
+ * Logger utility for the Hyve SDK
172
+ * Automatically enabled in development (NODE_ENV !== 'production')
173
+ */
174
+ type LogLevel = "debug" | "info" | "warn" | "error";
175
+ declare class Logger {
176
+ private config;
177
+ constructor();
178
+ /**
179
+ * Initialize logger configuration based on NODE_ENV
180
+ */
181
+ private initializeConfig;
182
+ /**
183
+ * Set which log levels to display
184
+ */
185
+ setLevels(levels: LogLevel[]): void;
186
+ /**
187
+ * Check if logging is enabled
188
+ */
189
+ isEnabled(): boolean;
190
+ /**
191
+ * Internal log method
192
+ */
193
+ private log;
194
+ /**
195
+ * Log a debug message
196
+ */
197
+ debug(...args: unknown[]): void;
198
+ /**
199
+ * Log an info message
200
+ */
201
+ info(...args: unknown[]): void;
202
+ /**
203
+ * Log a warning message
204
+ */
205
+ warn(...args: unknown[]): void;
206
+ /**
207
+ * Log an error message
208
+ */
209
+ error(...args: unknown[]): void;
210
+ /**
211
+ * Create a child logger with a specific prefix
212
+ */
213
+ child(prefix: string): Logger;
214
+ }
215
+ declare const logger: Logger;
216
+
156
217
  /**
157
218
  * Parses URL search parameters and returns commonly used values
158
219
  * @param searchParams URLSearchParams object or string
@@ -165,6 +226,7 @@ declare function parseUrlParams(searchParams: URLSearchParams | string): {
165
226
  hyveToken: string;
166
227
  platform: string;
167
228
  hyveAccess: string;
229
+ gameId: string;
168
230
  };
169
231
  /**
170
232
  * Validates an EVM signature against a message and user ID
@@ -203,11 +265,6 @@ declare function verifyAuthentication(params: {
203
265
  method: "modern" | "legacy" | "none";
204
266
  error?: string;
205
267
  };
206
- /**
207
- * Generates a random UUID (v4) using the uuid library
208
- * @returns A string containing a randomly generated UUID
209
- */
210
- declare function generateUUID(): string;
211
268
  /**
212
269
  * Checks if the current domain is in the list of allowed domains
213
270
  * @param allowedDomains Array of allowed domains or a single domain string
@@ -215,4 +272,172 @@ declare function generateUUID(): string;
215
272
  */
216
273
  declare function isDomainAllowed(allowedDomains?: string | string[], hostname?: string): boolean;
217
274
 
218
- export { HyveClient, type Inventory, type InventoryItem, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
275
+ /**
276
+ * Message structure for WebView to Native communication
277
+ */
278
+ interface NativeMessage<T = any> {
279
+ type: string;
280
+ payload?: T;
281
+ timestamp?: number;
282
+ }
283
+ /**
284
+ * Message types for native communication
285
+ */
286
+ declare enum NativeMessageType {
287
+ /** Check if In-App Purchases are available on the device */
288
+ CHECK_IAP_AVAILABILITY = "CHECK_IAP_AVAILABILITY",
289
+ /** Request notification permission from the native app */
290
+ REQUEST_NOTIFICATION_PERMISSION = "REQUEST_NOTIFICATION_PERMISSION",
291
+ /** Request available products for a game */
292
+ GET_PRODUCTS = "GET_PRODUCTS",
293
+ /** Initiate a purchase */
294
+ PURCHASE = "PURCHASE",
295
+ /** Response to CHECK_IAP_AVAILABILITY request */
296
+ IAP_AVAILABILITY_RESULT = "IAP_AVAILABILITY_RESULT",
297
+ /** Push notification permission was granted */
298
+ PUSH_PERMISSION_GRANTED = "PUSH_PERMISSION_GRANTED",
299
+ /** Push notification permission was denied */
300
+ PUSH_PERMISSION_DENIED = "PUSH_PERMISSION_DENIED",
301
+ /** Response with available products */
302
+ PRODUCTS_RESULT = "PRODUCTS_RESULT",
303
+ /** Purchase completed successfully */
304
+ PURCHASE_COMPLETE = "PURCHASE_COMPLETE",
305
+ /** Purchase failed or was cancelled */
306
+ PURCHASE_ERROR = "PURCHASE_ERROR"
307
+ }
308
+ /**
309
+ * Message handler function type for receiving messages from native
310
+ */
311
+ type NativeMessageHandler<T = any> = (payload: T) => void | Promise<void>;
312
+ /**
313
+ * NativeBridge - Provides utilities for WebView to React Native communication
314
+ *
315
+ * @example
316
+ * // Send message to React Native
317
+ * NativeBridge.send(NativeMessageType.CHECK_IAP_AVAILABILITY);
318
+ *
319
+ * // Listen for messages from React Native
320
+ * NativeBridge.on("PUSH_PERMISSION_GRANTED", (payload) => {
321
+ * console.log("Permission granted:", payload);
322
+ * });
323
+ *
324
+ * // Check if running in React Native WebView
325
+ * if (NativeBridge.isNativeContext()) {
326
+ * NativeBridge.checkIAPAvailability();
327
+ * }
328
+ */
329
+ declare class NativeBridge {
330
+ private static handlers;
331
+ private static isInitialized;
332
+ /**
333
+ * Checks if the app is running inside a React Native WebView
334
+ */
335
+ static isNativeContext(): boolean;
336
+ /**
337
+ * Initializes the native bridge message listener
338
+ * Call this once when your app starts
339
+ */
340
+ static initialize(): void;
341
+ /**
342
+ * Handles incoming messages from React Native
343
+ */
344
+ private static handleNativeMessage;
345
+ /**
346
+ * Sends a message to React Native
347
+ * @param type Message type
348
+ * @param payload Optional payload data
349
+ */
350
+ static send<T = any>(type: string, payload?: T): void;
351
+ /**
352
+ * Registers a handler for messages from React Native
353
+ * @param type Message type to listen for
354
+ * @param handler Function to call when message is received
355
+ */
356
+ static on<T = any>(type: string, handler: NativeMessageHandler<T>): void;
357
+ /**
358
+ * Unregisters a handler for a specific message type
359
+ * @param type Message type to stop listening for
360
+ */
361
+ static off(type: string): void;
362
+ /**
363
+ * Clears all registered handlers
364
+ */
365
+ static clearHandlers(): void;
366
+ /**
367
+ * Checks if In-App Purchases are available on the device
368
+ * The native app will respond with a message containing availability status
369
+ *
370
+ * @example
371
+ * // Listen for the response
372
+ * NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
373
+ * console.log("IAP available:", payload.available);
374
+ * });
375
+ *
376
+ * // Send the request
377
+ * NativeBridge.checkIAPAvailability();
378
+ */
379
+ static checkIAPAvailability(): void;
380
+ /**
381
+ * Requests notification permission from the native app
382
+ * The native app will respond with PUSH_PERMISSION_GRANTED or PUSH_PERMISSION_DENIED
383
+ *
384
+ * @example
385
+ * // Listen for the response
386
+ * NativeBridge.on("PUSH_PERMISSION_GRANTED", () => {
387
+ * console.log("Permission granted");
388
+ * });
389
+ *
390
+ * NativeBridge.on("PUSH_PERMISSION_DENIED", () => {
391
+ * console.log("Permission denied");
392
+ * });
393
+ *
394
+ * // Send the request
395
+ * NativeBridge.requestNotificationPermission();
396
+ */
397
+ static requestNotificationPermission(): void;
398
+ /**
399
+ * Requests available products for a specific game
400
+ * The native app will respond with PRODUCTS_RESULT containing product details
401
+ *
402
+ * @param gameId - The game ID to fetch products for
403
+ *
404
+ * @example
405
+ * // Listen for the response
406
+ * NativeBridge.on("PRODUCTS_RESULT", (payload) => {
407
+ * console.log("Products:", payload.products);
408
+ * });
409
+ *
410
+ * // Send the request
411
+ * NativeBridge.getProducts(123);
412
+ */
413
+ static getProducts(gameId: number): void;
414
+ /**
415
+ * Initiates a purchase for a specific product
416
+ * The native app will respond with PURCHASE_COMPLETE or PURCHASE_ERROR
417
+ *
418
+ * @param productId - The product ID to purchase
419
+ * @param userId - The user ID making the purchase
420
+ *
421
+ * @example
422
+ * // Listen for responses
423
+ * NativeBridge.on("PURCHASE_COMPLETE", (payload) => {
424
+ * console.log("Purchase successful:", payload.productId);
425
+ * });
426
+ *
427
+ * NativeBridge.on("PURCHASE_ERROR", (payload) => {
428
+ * console.error("Purchase failed:", payload.error);
429
+ * });
430
+ *
431
+ * // Initiate purchase
432
+ * NativeBridge.purchase("product_123", "user_456");
433
+ */
434
+ static purchase(productId: string, userId: string): void;
435
+ }
436
+
437
+ /**
438
+ * Generates a random UUID (v4) using the uuid library
439
+ * @returns A string containing a randomly generated UUID
440
+ */
441
+ declare function generateUUID(): string;
442
+
443
+ export { HyveClient, type Inventory, type InventoryItem, Logger, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, logger, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };