@hyve-sdk/js 1.0.1 → 1.2.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/README.md +198 -16
- package/dist/index.d.mts +93 -21
- package/dist/index.d.ts +93 -21
- package/dist/index.js +130 -25
- package/dist/index.mjs +130 -25
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,34 +1,52 @@
|
|
|
1
|
-
# @hyve/
|
|
1
|
+
# @hyve-sdk/js
|
|
2
2
|
|
|
3
3
|
TypeScript SDK for web3 authentication and game integration, providing secure signature verification and utility functions.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
bun add @hyve/
|
|
8
|
+
bun add @hyve-sdk/js
|
|
9
9
|
# or
|
|
10
|
-
npm install @hyve/
|
|
10
|
+
npm install @hyve-sdk/js
|
|
11
11
|
# or
|
|
12
|
-
pnpm add @hyve/
|
|
12
|
+
pnpm add @hyve-sdk/js
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Features
|
|
16
16
|
|
|
17
17
|
- **Web3 Authentication**: EVM signature validation and verification
|
|
18
18
|
- **Modern & Legacy Token Support**: Dual authentication token formats
|
|
19
|
-
- **
|
|
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
|
+
- **Security Utilities**: Domain validation and referrer checking
|
|
20
24
|
- **URL Parameter Parsing**: Easy extraction of authentication parameters
|
|
21
25
|
- **UUID Generation**: Built-in UUID v4 generation
|
|
22
26
|
|
|
23
27
|
## Core Components
|
|
24
28
|
|
|
25
29
|
### HyveClient
|
|
26
|
-
Main client class for SDK operations
|
|
30
|
+
Main client class for SDK operations including authentication, telemetry, and API calls.
|
|
27
31
|
|
|
28
32
|
```typescript
|
|
29
|
-
import { HyveClient } from "@hyve/
|
|
33
|
+
import { HyveClient } from "@hyve-sdk/js";
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
// Initialize with optional configuration
|
|
36
|
+
const client = new HyveClient({
|
|
37
|
+
isDev: true, // Development mode (default: true)
|
|
38
|
+
apiBaseUrl: 'https://...' // Optional custom API URL
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Authenticate from URL parameters
|
|
42
|
+
// Extracts: hyve-token/signature, hyve-access (JWT), game-id
|
|
43
|
+
const authenticated = await client.authenticateFromUrl();
|
|
44
|
+
if (authenticated) {
|
|
45
|
+
console.log('User ID:', client.getUserId());
|
|
46
|
+
console.log('Session ID:', client.getSessionId());
|
|
47
|
+
console.log('Has JWT:', client.hasJwtToken());
|
|
48
|
+
console.log('Game ID:', client.getGameId());
|
|
49
|
+
}
|
|
32
50
|
```
|
|
33
51
|
|
|
34
52
|
### Authentication Utilities
|
|
@@ -37,17 +55,18 @@ const client = new HyveClient();
|
|
|
37
55
|
Extract authentication and game parameters from URL:
|
|
38
56
|
|
|
39
57
|
```typescript
|
|
40
|
-
import { parseUrlParams } from "@hyve/
|
|
58
|
+
import { parseUrlParams } from "@hyve-sdk/js";
|
|
41
59
|
|
|
42
60
|
const params = parseUrlParams(window.location.search);
|
|
43
61
|
// Returns:
|
|
44
62
|
// {
|
|
45
63
|
// signature: string,
|
|
46
64
|
// message: string,
|
|
47
|
-
// userId: string,
|
|
48
65
|
// gameStartTab: string,
|
|
49
66
|
// hyveToken: string,
|
|
50
|
-
// platform: string
|
|
67
|
+
// platform: string,
|
|
68
|
+
// hyveAccess: string, // JWT token
|
|
69
|
+
// gameId: string // Game identifier
|
|
51
70
|
// }
|
|
52
71
|
```
|
|
53
72
|
|
|
@@ -55,7 +74,7 @@ const params = parseUrlParams(window.location.search);
|
|
|
55
74
|
Unified verification supporting both modern and legacy tokens:
|
|
56
75
|
|
|
57
76
|
```typescript
|
|
58
|
-
import { verifyAuthentication } from "@hyve/
|
|
77
|
+
import { verifyAuthentication } from "@hyve-sdk/js";
|
|
59
78
|
|
|
60
79
|
const result = verifyAuthentication({
|
|
61
80
|
hyveToken: params.hyveToken, // Modern token format
|
|
@@ -73,7 +92,7 @@ if (result.isValid) {
|
|
|
73
92
|
Verify modern authentication tokens with expiration:
|
|
74
93
|
|
|
75
94
|
```typescript
|
|
76
|
-
import { verifyHyveToken } from "@hyve/
|
|
95
|
+
import { verifyHyveToken } from "@hyve-sdk/js";
|
|
77
96
|
|
|
78
97
|
// Token format: signature.address.randomBase64.timestamp
|
|
79
98
|
const address = verifyHyveToken(hyveToken, 600); // 600 seconds max age
|
|
@@ -86,7 +105,7 @@ if (address) {
|
|
|
86
105
|
Verify legacy signed messages with metadata:
|
|
87
106
|
|
|
88
107
|
```typescript
|
|
89
|
-
import { handleVerifyMessage, validateSignature } from "@hyve/
|
|
108
|
+
import { handleVerifyMessage, validateSignature } from "@hyve-sdk/js";
|
|
90
109
|
|
|
91
110
|
// Method 1: Verify message with embedded metadata
|
|
92
111
|
const address = handleVerifyMessage(signature, message);
|
|
@@ -101,7 +120,7 @@ const isValid = validateSignature(signature, message, userId);
|
|
|
101
120
|
Check if current domain is allowed:
|
|
102
121
|
|
|
103
122
|
```typescript
|
|
104
|
-
import { isDomainAllowed } from "@hyve/
|
|
123
|
+
import { isDomainAllowed } from "@hyve-sdk/js";
|
|
105
124
|
|
|
106
125
|
// Single domain
|
|
107
126
|
const allowed = isDomainAllowed('example.com', window.location.hostname);
|
|
@@ -121,11 +140,174 @@ const allowed = isDomainAllowed(
|
|
|
121
140
|
Generate random UUID v4:
|
|
122
141
|
|
|
123
142
|
```typescript
|
|
124
|
-
import { generateUUID } from "@hyve/
|
|
143
|
+
import { generateUUID } from "@hyve-sdk/js";
|
|
125
144
|
|
|
126
145
|
const id = generateUUID();
|
|
127
146
|
```
|
|
128
147
|
|
|
148
|
+
## Telemetry & Analytics
|
|
149
|
+
|
|
150
|
+
### Send Telemetry Events
|
|
151
|
+
Track user actions and game events using JWT authentication:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// Send a user-level telemetry event
|
|
155
|
+
// Game ID is automatically extracted from 'game-id' URL parameter
|
|
156
|
+
await client.sendTelemetry(
|
|
157
|
+
'game', // Event location
|
|
158
|
+
'player', // Event category
|
|
159
|
+
'action', // Event action
|
|
160
|
+
'combat', // Event sub-category (optional)
|
|
161
|
+
'attack', // Event sub-action (optional)
|
|
162
|
+
{ // Event details - auto-stringified (optional)
|
|
163
|
+
button: 'attack-btn',
|
|
164
|
+
screenPosition: { x: 100, y: 200 }
|
|
165
|
+
},
|
|
166
|
+
{ // Custom data - auto-stringified (optional)
|
|
167
|
+
damage: 100,
|
|
168
|
+
targetId: 'enemy-123',
|
|
169
|
+
weaponType: 'sword',
|
|
170
|
+
level: 3
|
|
171
|
+
},
|
|
172
|
+
'web-chrome' // Platform ID (optional)
|
|
173
|
+
);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Requirements:**
|
|
177
|
+
- Requires JWT token (from `hyve-access` URL parameter)
|
|
178
|
+
- Requires authenticated user
|
|
179
|
+
- Requires game ID (from `game-id` URL parameter)
|
|
180
|
+
- User ID is automatically extracted from JWT (cannot be spoofed)
|
|
181
|
+
|
|
182
|
+
**URL Parameters Expected:**
|
|
183
|
+
- `hyve-access` - JWT authentication token
|
|
184
|
+
- `game-id` - Game identifier (associates all telemetry with this game)
|
|
185
|
+
- `hyve-token` or `signature`+`message` - For user authentication
|
|
186
|
+
|
|
187
|
+
**Features:**
|
|
188
|
+
- Automatically includes `session_id` and `game_id` from client
|
|
189
|
+
- Objects in `event_details` and `custom_data` are auto-stringified to JSON
|
|
190
|
+
- All events tied to authenticated user identity
|
|
191
|
+
|
|
192
|
+
## API Integration
|
|
193
|
+
|
|
194
|
+
### JWT Authentication
|
|
195
|
+
The SDK supports JWT tokens and game IDs passed via URL parameters:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// URL: https://game.com?hyve-access=your-jwt-token&game-id=my-game
|
|
199
|
+
|
|
200
|
+
// Authenticate extracts JWT and game ID automatically
|
|
201
|
+
await client.authenticateFromUrl();
|
|
202
|
+
|
|
203
|
+
// Check availability
|
|
204
|
+
if (client.hasJwtToken()) {
|
|
205
|
+
console.log('JWT token:', client.getJwtToken());
|
|
206
|
+
console.log('Game ID:', client.getGameId());
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Generic API Calls
|
|
211
|
+
Make authenticated API requests:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
// GET request
|
|
215
|
+
const userData = await client.callApi('/api/v1/user');
|
|
216
|
+
|
|
217
|
+
// POST request with body
|
|
218
|
+
const result = await client.callApi('/api/v1/game/score', {
|
|
219
|
+
method: 'POST',
|
|
220
|
+
body: JSON.stringify({ score: 1000 })
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// With TypeScript typing
|
|
224
|
+
interface UserData {
|
|
225
|
+
id: string;
|
|
226
|
+
username: string;
|
|
227
|
+
}
|
|
228
|
+
const user = await client.callApi<UserData>('/api/v1/user');
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Inventory Management
|
|
232
|
+
|
|
233
|
+
#### Get User Inventory
|
|
234
|
+
Retrieve all inventory items:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
const inventory = await client.getInventory();
|
|
238
|
+
|
|
239
|
+
console.log(`Total items: ${inventory.total_count}`);
|
|
240
|
+
inventory.items.forEach(item => {
|
|
241
|
+
console.log(`${item.item_type}: ${item.quantity}x`);
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Response Type:**
|
|
246
|
+
```typescript
|
|
247
|
+
interface Inventory {
|
|
248
|
+
items: InventoryItem[];
|
|
249
|
+
total_count: number;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
interface InventoryItem {
|
|
253
|
+
id: string;
|
|
254
|
+
user_id: string;
|
|
255
|
+
item_type: string;
|
|
256
|
+
item_id: string;
|
|
257
|
+
quantity: number;
|
|
258
|
+
metadata?: Record<string, any>;
|
|
259
|
+
created_at: string;
|
|
260
|
+
updated_at: string;
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Get Specific Inventory Item
|
|
265
|
+
Fetch details for a single item:
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const item = await client.getInventoryItem('item-id-123');
|
|
269
|
+
|
|
270
|
+
console.log(`Item: ${item.item_type}`);
|
|
271
|
+
console.log(`Quantity: ${item.quantity}`);
|
|
272
|
+
if (item.metadata) {
|
|
273
|
+
console.log('Metadata:', item.metadata);
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**API Endpoints:**
|
|
278
|
+
- `GET /api/v1/inventory` - Get all inventory items
|
|
279
|
+
- `GET /api/v1/inventory/:id` - Get specific item
|
|
280
|
+
|
|
281
|
+
**Requirements:**
|
|
282
|
+
- JWT token must be available (via `hyve-access` URL parameter)
|
|
283
|
+
- User must be authenticated
|
|
284
|
+
|
|
285
|
+
## Client Methods Reference
|
|
286
|
+
|
|
287
|
+
### Authentication
|
|
288
|
+
- `authenticateFromUrl(urlParams?)` - Authenticate from URL parameters (extracts JWT, game ID, user auth)
|
|
289
|
+
- `getUserId()` - Get authenticated user ID (address)
|
|
290
|
+
- `getSessionId()` - Get unique session ID
|
|
291
|
+
- `getGameId()` - Get game ID from URL parameters
|
|
292
|
+
- `isUserAuthenticated()` - Check if user is authenticated
|
|
293
|
+
- `hasJwtToken()` - Check if JWT token is available
|
|
294
|
+
- `getJwtToken()` - Get JWT token string
|
|
295
|
+
- `logout()` - Clear user authentication
|
|
296
|
+
- `reset()` - Reset client state with new session
|
|
297
|
+
|
|
298
|
+
### API Calls
|
|
299
|
+
- `callApi<T>(endpoint, options?)` - Generic authenticated API call
|
|
300
|
+
- `getInventory()` - Get user's inventory
|
|
301
|
+
- `getInventoryItem(itemId)` - Get specific inventory item
|
|
302
|
+
|
|
303
|
+
### Telemetry
|
|
304
|
+
- `sendTelemetry(location, category, action, subCategory?, subAction?, details?, customData?, platformId?)` - Send JWT-authenticated analytics event (uses game ID from URL)
|
|
305
|
+
- `updateTelemetryConfig(config)` - Update telemetry settings
|
|
306
|
+
|
|
307
|
+
### Configuration
|
|
308
|
+
- `getApiBaseUrl()` - Get current API base URL
|
|
309
|
+
- `updateTelemetryConfig(config)` - Update client configuration
|
|
310
|
+
|
|
129
311
|
## Authentication Flow
|
|
130
312
|
|
|
131
313
|
### Modern Token Flow (Recommended)
|
package/dist/index.d.mts
CHANGED
|
@@ -2,31 +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;
|
|
7
|
+
/** Base API URL for all API calls (telemetry and external). Can be set via env. If not provided, defaults based on isDev */
|
|
8
|
+
apiBaseUrl?: string;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* 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
|
|
12
14
|
*/
|
|
13
15
|
interface TelemetryEvent {
|
|
14
|
-
/**
|
|
16
|
+
/** Game identifier (required) */
|
|
17
|
+
game_id: string;
|
|
18
|
+
/** Unique session identifier (required) */
|
|
15
19
|
session_id: string;
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
/** Location where the event occurred */
|
|
20
|
+
/** Platform/user identifier (optional) */
|
|
21
|
+
platform_id?: string | null;
|
|
22
|
+
/** Location where the event occurred (required) */
|
|
19
23
|
event_location: string;
|
|
20
|
-
/** Main category of the event */
|
|
24
|
+
/** Main category of the event (required) */
|
|
21
25
|
event_category: string;
|
|
22
|
-
/**
|
|
26
|
+
/** Sub-category for more granular classification (optional) */
|
|
27
|
+
event_sub_category?: string | null;
|
|
28
|
+
/** Primary action taken (required) */
|
|
23
29
|
event_action: string;
|
|
24
|
-
/** Sub-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
|
|
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;
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
40
|
* Additional telemetry data that can be passed with events
|
|
@@ -35,15 +43,37 @@ interface TelemetryAdditionalData {
|
|
|
35
43
|
/** Optional additional data object (will be JSON stringified and put in event_details) */
|
|
36
44
|
[key: string]: any;
|
|
37
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* User inventory item
|
|
48
|
+
*/
|
|
49
|
+
interface InventoryItem {
|
|
50
|
+
id: string;
|
|
51
|
+
user_id: string;
|
|
52
|
+
item_type: string;
|
|
53
|
+
item_id: string;
|
|
54
|
+
quantity: number;
|
|
55
|
+
metadata?: Record<string, any>;
|
|
56
|
+
created_at: string;
|
|
57
|
+
updated_at: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* User inventory response
|
|
61
|
+
*/
|
|
62
|
+
interface Inventory {
|
|
63
|
+
items: InventoryItem[];
|
|
64
|
+
total_count: number;
|
|
65
|
+
}
|
|
38
66
|
|
|
39
67
|
/**
|
|
40
68
|
* HyveClient provides telemetry and authentication functionality for Hyve games
|
|
41
69
|
*/
|
|
42
70
|
declare class HyveClient {
|
|
43
71
|
private telemetryConfig;
|
|
44
|
-
private
|
|
72
|
+
private apiBaseUrl;
|
|
45
73
|
private sessionId;
|
|
46
74
|
private userId;
|
|
75
|
+
private jwtToken;
|
|
76
|
+
private gameId;
|
|
47
77
|
/**
|
|
48
78
|
* Creates a new HyveClient instance
|
|
49
79
|
* @param config Optional telemetry configuration
|
|
@@ -56,17 +86,37 @@ declare class HyveClient {
|
|
|
56
86
|
*/
|
|
57
87
|
authenticateFromUrl(urlParams?: URLSearchParams | string): Promise<boolean>;
|
|
58
88
|
/**
|
|
59
|
-
* 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
|
|
60
91
|
* @param eventLocation Location where the event occurred
|
|
61
92
|
* @param eventCategory Main category of the event
|
|
62
93
|
* @param eventAction Primary action taken
|
|
63
94
|
* @param eventSubCategory Optional sub-category
|
|
64
95
|
* @param eventSubAction Optional sub-action
|
|
65
|
-
* @param eventDetails Optional event details
|
|
66
|
-
* @param
|
|
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
|
|
67
99
|
* @returns Promise resolving to boolean indicating success
|
|
68
100
|
*/
|
|
69
|
-
sendTelemetry(eventLocation: string, eventCategory: string, eventAction: string, eventSubCategory?: string | null, eventSubAction?: string | null, eventDetails?: string | null,
|
|
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>;
|
|
102
|
+
/**
|
|
103
|
+
* Makes an authenticated API call using the JWT token
|
|
104
|
+
* @param endpoint API endpoint path (will be appended to base URL)
|
|
105
|
+
* @param options Fetch options (method, body, etc.)
|
|
106
|
+
* @returns Promise resolving to the API response
|
|
107
|
+
*/
|
|
108
|
+
callApi<T = any>(endpoint: string, options?: RequestInit): Promise<T>;
|
|
109
|
+
/**
|
|
110
|
+
* Gets the user's inventory
|
|
111
|
+
* @returns Promise resolving to the user's inventory
|
|
112
|
+
*/
|
|
113
|
+
getInventory(): Promise<Inventory>;
|
|
114
|
+
/**
|
|
115
|
+
* Gets a specific inventory item by ID
|
|
116
|
+
* @param itemId The inventory item ID
|
|
117
|
+
* @returns Promise resolving to the inventory item details
|
|
118
|
+
*/
|
|
119
|
+
getInventoryItem(itemId: string): Promise<InventoryItem>;
|
|
70
120
|
/**
|
|
71
121
|
* Updates the telemetry configuration
|
|
72
122
|
* @param config New telemetry configuration
|
|
@@ -82,11 +132,31 @@ declare class HyveClient {
|
|
|
82
132
|
* @returns Current session ID
|
|
83
133
|
*/
|
|
84
134
|
getSessionId(): string;
|
|
135
|
+
/**
|
|
136
|
+
* Gets the current JWT token
|
|
137
|
+
* @returns Current JWT token or null if not available
|
|
138
|
+
*/
|
|
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;
|
|
145
|
+
/**
|
|
146
|
+
* Gets the API base URL
|
|
147
|
+
* @returns API base URL
|
|
148
|
+
*/
|
|
149
|
+
getApiBaseUrl(): string;
|
|
85
150
|
/**
|
|
86
151
|
* Checks if user is authenticated
|
|
87
152
|
* @returns Boolean indicating authentication status
|
|
88
153
|
*/
|
|
89
154
|
isUserAuthenticated(): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Checks if JWT token is available
|
|
157
|
+
* @returns Boolean indicating if JWT token is present
|
|
158
|
+
*/
|
|
159
|
+
hasJwtToken(): boolean;
|
|
90
160
|
/**
|
|
91
161
|
* Logs out the current user
|
|
92
162
|
*/
|
|
@@ -108,6 +178,8 @@ declare function parseUrlParams(searchParams: URLSearchParams | string): {
|
|
|
108
178
|
gameStartTab: string;
|
|
109
179
|
hyveToken: string;
|
|
110
180
|
platform: string;
|
|
181
|
+
hyveAccess: string;
|
|
182
|
+
gameId: string;
|
|
111
183
|
};
|
|
112
184
|
/**
|
|
113
185
|
* Validates an EVM signature against a message and user ID
|
|
@@ -158,4 +230,4 @@ declare function generateUUID(): string;
|
|
|
158
230
|
*/
|
|
159
231
|
declare function isDomainAllowed(allowedDomains?: string | string[], hostname?: string): boolean;
|
|
160
232
|
|
|
161
|
-
export { HyveClient, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
|
|
233
|
+
export { HyveClient, type Inventory, type InventoryItem, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,31 +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;
|
|
7
|
+
/** Base API URL for all API calls (telemetry and external). Can be set via env. If not provided, defaults based on isDev */
|
|
8
|
+
apiBaseUrl?: string;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* 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
|
|
12
14
|
*/
|
|
13
15
|
interface TelemetryEvent {
|
|
14
|
-
/**
|
|
16
|
+
/** Game identifier (required) */
|
|
17
|
+
game_id: string;
|
|
18
|
+
/** Unique session identifier (required) */
|
|
15
19
|
session_id: string;
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
/** Location where the event occurred */
|
|
20
|
+
/** Platform/user identifier (optional) */
|
|
21
|
+
platform_id?: string | null;
|
|
22
|
+
/** Location where the event occurred (required) */
|
|
19
23
|
event_location: string;
|
|
20
|
-
/** Main category of the event */
|
|
24
|
+
/** Main category of the event (required) */
|
|
21
25
|
event_category: string;
|
|
22
|
-
/**
|
|
26
|
+
/** Sub-category for more granular classification (optional) */
|
|
27
|
+
event_sub_category?: string | null;
|
|
28
|
+
/** Primary action taken (required) */
|
|
23
29
|
event_action: string;
|
|
24
|
-
/** Sub-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
|
|
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;
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
40
|
* Additional telemetry data that can be passed with events
|
|
@@ -35,15 +43,37 @@ interface TelemetryAdditionalData {
|
|
|
35
43
|
/** Optional additional data object (will be JSON stringified and put in event_details) */
|
|
36
44
|
[key: string]: any;
|
|
37
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* User inventory item
|
|
48
|
+
*/
|
|
49
|
+
interface InventoryItem {
|
|
50
|
+
id: string;
|
|
51
|
+
user_id: string;
|
|
52
|
+
item_type: string;
|
|
53
|
+
item_id: string;
|
|
54
|
+
quantity: number;
|
|
55
|
+
metadata?: Record<string, any>;
|
|
56
|
+
created_at: string;
|
|
57
|
+
updated_at: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* User inventory response
|
|
61
|
+
*/
|
|
62
|
+
interface Inventory {
|
|
63
|
+
items: InventoryItem[];
|
|
64
|
+
total_count: number;
|
|
65
|
+
}
|
|
38
66
|
|
|
39
67
|
/**
|
|
40
68
|
* HyveClient provides telemetry and authentication functionality for Hyve games
|
|
41
69
|
*/
|
|
42
70
|
declare class HyveClient {
|
|
43
71
|
private telemetryConfig;
|
|
44
|
-
private
|
|
72
|
+
private apiBaseUrl;
|
|
45
73
|
private sessionId;
|
|
46
74
|
private userId;
|
|
75
|
+
private jwtToken;
|
|
76
|
+
private gameId;
|
|
47
77
|
/**
|
|
48
78
|
* Creates a new HyveClient instance
|
|
49
79
|
* @param config Optional telemetry configuration
|
|
@@ -56,17 +86,37 @@ declare class HyveClient {
|
|
|
56
86
|
*/
|
|
57
87
|
authenticateFromUrl(urlParams?: URLSearchParams | string): Promise<boolean>;
|
|
58
88
|
/**
|
|
59
|
-
* 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
|
|
60
91
|
* @param eventLocation Location where the event occurred
|
|
61
92
|
* @param eventCategory Main category of the event
|
|
62
93
|
* @param eventAction Primary action taken
|
|
63
94
|
* @param eventSubCategory Optional sub-category
|
|
64
95
|
* @param eventSubAction Optional sub-action
|
|
65
|
-
* @param eventDetails Optional event details
|
|
66
|
-
* @param
|
|
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
|
|
67
99
|
* @returns Promise resolving to boolean indicating success
|
|
68
100
|
*/
|
|
69
|
-
sendTelemetry(eventLocation: string, eventCategory: string, eventAction: string, eventSubCategory?: string | null, eventSubAction?: string | null, eventDetails?: string | null,
|
|
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>;
|
|
102
|
+
/**
|
|
103
|
+
* Makes an authenticated API call using the JWT token
|
|
104
|
+
* @param endpoint API endpoint path (will be appended to base URL)
|
|
105
|
+
* @param options Fetch options (method, body, etc.)
|
|
106
|
+
* @returns Promise resolving to the API response
|
|
107
|
+
*/
|
|
108
|
+
callApi<T = any>(endpoint: string, options?: RequestInit): Promise<T>;
|
|
109
|
+
/**
|
|
110
|
+
* Gets the user's inventory
|
|
111
|
+
* @returns Promise resolving to the user's inventory
|
|
112
|
+
*/
|
|
113
|
+
getInventory(): Promise<Inventory>;
|
|
114
|
+
/**
|
|
115
|
+
* Gets a specific inventory item by ID
|
|
116
|
+
* @param itemId The inventory item ID
|
|
117
|
+
* @returns Promise resolving to the inventory item details
|
|
118
|
+
*/
|
|
119
|
+
getInventoryItem(itemId: string): Promise<InventoryItem>;
|
|
70
120
|
/**
|
|
71
121
|
* Updates the telemetry configuration
|
|
72
122
|
* @param config New telemetry configuration
|
|
@@ -82,11 +132,31 @@ declare class HyveClient {
|
|
|
82
132
|
* @returns Current session ID
|
|
83
133
|
*/
|
|
84
134
|
getSessionId(): string;
|
|
135
|
+
/**
|
|
136
|
+
* Gets the current JWT token
|
|
137
|
+
* @returns Current JWT token or null if not available
|
|
138
|
+
*/
|
|
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;
|
|
145
|
+
/**
|
|
146
|
+
* Gets the API base URL
|
|
147
|
+
* @returns API base URL
|
|
148
|
+
*/
|
|
149
|
+
getApiBaseUrl(): string;
|
|
85
150
|
/**
|
|
86
151
|
* Checks if user is authenticated
|
|
87
152
|
* @returns Boolean indicating authentication status
|
|
88
153
|
*/
|
|
89
154
|
isUserAuthenticated(): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Checks if JWT token is available
|
|
157
|
+
* @returns Boolean indicating if JWT token is present
|
|
158
|
+
*/
|
|
159
|
+
hasJwtToken(): boolean;
|
|
90
160
|
/**
|
|
91
161
|
* Logs out the current user
|
|
92
162
|
*/
|
|
@@ -108,6 +178,8 @@ declare function parseUrlParams(searchParams: URLSearchParams | string): {
|
|
|
108
178
|
gameStartTab: string;
|
|
109
179
|
hyveToken: string;
|
|
110
180
|
platform: string;
|
|
181
|
+
hyveAccess: string;
|
|
182
|
+
gameId: string;
|
|
111
183
|
};
|
|
112
184
|
/**
|
|
113
185
|
* Validates an EVM signature against a message and user ID
|
|
@@ -158,4 +230,4 @@ declare function generateUUID(): string;
|
|
|
158
230
|
*/
|
|
159
231
|
declare function isDomainAllowed(allowedDomains?: string | string[], hostname?: string): boolean;
|
|
160
232
|
|
|
161
|
-
export { HyveClient, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
|
|
233
|
+
export { HyveClient, type Inventory, type InventoryItem, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,9 @@ function parseUrlParams(searchParams) {
|
|
|
41
41
|
message: params.get("message") || "",
|
|
42
42
|
gameStartTab: params.get("game_start_tab") || "",
|
|
43
43
|
hyveToken: params.get("hyve-token") || "",
|
|
44
|
-
platform: params.get("platform") || ""
|
|
44
|
+
platform: params.get("platform") || "",
|
|
45
|
+
hyveAccess: params.get("hyve-access") || "",
|
|
46
|
+
gameId: params.get("game-id") || ""
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
function validateSignature(signature, message) {
|
|
@@ -186,9 +188,11 @@ function isDomainAllowed(allowedDomains, hostname) {
|
|
|
186
188
|
// src/core/client.ts
|
|
187
189
|
var HyveClient = class {
|
|
188
190
|
telemetryConfig;
|
|
189
|
-
|
|
191
|
+
apiBaseUrl;
|
|
190
192
|
sessionId;
|
|
191
193
|
userId = null;
|
|
194
|
+
jwtToken = null;
|
|
195
|
+
gameId = null;
|
|
192
196
|
/**
|
|
193
197
|
* Creates a new HyveClient instance
|
|
194
198
|
* @param config Optional telemetry configuration
|
|
@@ -199,10 +203,15 @@ var HyveClient = class {
|
|
|
199
203
|
// Default to dev environment
|
|
200
204
|
...config
|
|
201
205
|
};
|
|
202
|
-
|
|
206
|
+
if (this.telemetryConfig.apiBaseUrl) {
|
|
207
|
+
this.apiBaseUrl = this.telemetryConfig.apiBaseUrl;
|
|
208
|
+
} else {
|
|
209
|
+
this.apiBaseUrl = this.telemetryConfig.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
|
|
210
|
+
}
|
|
203
211
|
this.sessionId = generateUUID();
|
|
204
212
|
console.log("[Hyve SDK] Client initialized with sessionId:", this.sessionId);
|
|
205
|
-
console.log("[Hyve SDK]
|
|
213
|
+
console.log("[Hyve SDK] API Base URL:", this.apiBaseUrl);
|
|
214
|
+
console.log("[Hyve SDK] Environment:", this.telemetryConfig.isDev ? "dev" : "prod");
|
|
206
215
|
}
|
|
207
216
|
/**
|
|
208
217
|
* Authenticates a user from URL parameters
|
|
@@ -212,6 +221,18 @@ var HyveClient = class {
|
|
|
212
221
|
async authenticateFromUrl(urlParams) {
|
|
213
222
|
try {
|
|
214
223
|
const params = urlParams ? parseUrlParams(urlParams) : parseUrlParams(window.location.search);
|
|
224
|
+
if (params.hyveAccess) {
|
|
225
|
+
this.jwtToken = params.hyveAccess;
|
|
226
|
+
console.log("[Hyve SDK] JWT token extracted from hyve-access parameter");
|
|
227
|
+
}
|
|
228
|
+
if (params.gameId) {
|
|
229
|
+
this.gameId = params.gameId;
|
|
230
|
+
console.log("[Hyve SDK] Game ID extracted from game-id parameter:", this.gameId);
|
|
231
|
+
}
|
|
232
|
+
if (this.jwtToken) {
|
|
233
|
+
console.log("[Hyve SDK] Authentication successful via JWT");
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
215
236
|
const authResult = verifyAuthentication({
|
|
216
237
|
hyveToken: params.hyveToken,
|
|
217
238
|
signature: params.signature,
|
|
@@ -234,47 +255,51 @@ var HyveClient = class {
|
|
|
234
255
|
}
|
|
235
256
|
}
|
|
236
257
|
/**
|
|
237
|
-
* Sends a telemetry event
|
|
258
|
+
* Sends a user-level telemetry event using JWT authentication
|
|
259
|
+
* Requires JWT token, authenticated user, and game ID from URL parameters
|
|
238
260
|
* @param eventLocation Location where the event occurred
|
|
239
261
|
* @param eventCategory Main category of the event
|
|
240
262
|
* @param eventAction Primary action taken
|
|
241
263
|
* @param eventSubCategory Optional sub-category
|
|
242
264
|
* @param eventSubAction Optional sub-action
|
|
243
|
-
* @param eventDetails Optional event details
|
|
244
|
-
* @param
|
|
265
|
+
* @param eventDetails Optional event details (object or JSON string)
|
|
266
|
+
* @param customData Optional custom data (object or JSON string)
|
|
267
|
+
* @param platformId Optional platform identifier
|
|
245
268
|
* @returns Promise resolving to boolean indicating success
|
|
246
269
|
*/
|
|
247
|
-
async sendTelemetry(eventLocation, eventCategory, eventAction, eventSubCategory, eventSubAction, eventDetails,
|
|
248
|
-
if (!this.
|
|
249
|
-
console.error("[Hyve Telemetry]
|
|
270
|
+
async sendTelemetry(eventLocation, eventCategory, eventAction, eventSubCategory, eventSubAction, eventDetails, customData, platformId) {
|
|
271
|
+
if (!this.jwtToken) {
|
|
272
|
+
console.error("[Hyve Telemetry] JWT token required. Call authenticateFromUrl first.");
|
|
250
273
|
return false;
|
|
251
274
|
}
|
|
252
|
-
if (!this.
|
|
253
|
-
console.
|
|
275
|
+
if (!this.gameId) {
|
|
276
|
+
console.error("[Hyve Telemetry] Game ID required. Ensure game-id URL parameter is set.");
|
|
277
|
+
return false;
|
|
254
278
|
}
|
|
255
279
|
try {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
finalEventDetails = eventDetails;
|
|
261
|
-
}
|
|
280
|
+
const toJsonString = (data) => {
|
|
281
|
+
if (!data) return null;
|
|
282
|
+
return typeof data === "string" ? data : JSON.stringify(data);
|
|
283
|
+
};
|
|
262
284
|
const telemetryEvent = {
|
|
285
|
+
game_id: this.gameId,
|
|
263
286
|
session_id: this.sessionId,
|
|
264
|
-
|
|
287
|
+
platform_id: platformId || null,
|
|
265
288
|
event_location: eventLocation,
|
|
266
289
|
event_category: eventCategory,
|
|
267
290
|
event_action: eventAction,
|
|
268
291
|
event_sub_category: eventSubCategory || null,
|
|
269
292
|
event_sub_action: eventSubAction || null,
|
|
270
|
-
event_details:
|
|
293
|
+
event_details: toJsonString(eventDetails),
|
|
294
|
+
custom_data: toJsonString(customData)
|
|
271
295
|
};
|
|
272
|
-
console.log("[Hyve Telemetry] Sending event:", telemetryEvent);
|
|
273
|
-
const
|
|
296
|
+
console.log("[Hyve Telemetry] Sending user-level event:", telemetryEvent);
|
|
297
|
+
const telemetryUrl = `${this.apiBaseUrl}/api/v1/telemetry/send`;
|
|
298
|
+
const response = await fetch(telemetryUrl, {
|
|
274
299
|
method: "POST",
|
|
275
300
|
headers: {
|
|
276
301
|
"Content-Type": "application/json",
|
|
277
|
-
"
|
|
302
|
+
"Authorization": `Bearer ${this.jwtToken}`
|
|
278
303
|
},
|
|
279
304
|
body: JSON.stringify(telemetryEvent)
|
|
280
305
|
});
|
|
@@ -291,6 +316,51 @@ var HyveClient = class {
|
|
|
291
316
|
return false;
|
|
292
317
|
}
|
|
293
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Makes an authenticated API call using the JWT token
|
|
321
|
+
* @param endpoint API endpoint path (will be appended to base URL)
|
|
322
|
+
* @param options Fetch options (method, body, etc.)
|
|
323
|
+
* @returns Promise resolving to the API response
|
|
324
|
+
*/
|
|
325
|
+
async callApi(endpoint, options = {}) {
|
|
326
|
+
if (!this.jwtToken) {
|
|
327
|
+
throw new Error("[Hyve SDK] No JWT token available. Call authenticateFromUrl first.");
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
const url = `${this.apiBaseUrl}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
|
|
331
|
+
const response = await fetch(url, {
|
|
332
|
+
...options,
|
|
333
|
+
headers: {
|
|
334
|
+
"Content-Type": "application/json",
|
|
335
|
+
"Authorization": `Bearer ${this.jwtToken}`,
|
|
336
|
+
...options.headers
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
if (!response.ok) {
|
|
340
|
+
const errorText = await response.text();
|
|
341
|
+
throw new Error(`API request failed: ${response.status} ${errorText}`);
|
|
342
|
+
}
|
|
343
|
+
return await response.json();
|
|
344
|
+
} catch (error) {
|
|
345
|
+
console.error("[Hyve SDK] API call failed:", error);
|
|
346
|
+
throw error;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Gets the user's inventory
|
|
351
|
+
* @returns Promise resolving to the user's inventory
|
|
352
|
+
*/
|
|
353
|
+
async getInventory() {
|
|
354
|
+
return this.callApi("/api/v1/inventory");
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Gets a specific inventory item by ID
|
|
358
|
+
* @param itemId The inventory item ID
|
|
359
|
+
* @returns Promise resolving to the inventory item details
|
|
360
|
+
*/
|
|
361
|
+
async getInventoryItem(itemId) {
|
|
362
|
+
return this.callApi(`/api/v1/inventory/${itemId}`);
|
|
363
|
+
}
|
|
294
364
|
/**
|
|
295
365
|
* Updates the telemetry configuration
|
|
296
366
|
* @param config New telemetry configuration
|
|
@@ -300,8 +370,13 @@ var HyveClient = class {
|
|
|
300
370
|
...this.telemetryConfig,
|
|
301
371
|
...config
|
|
302
372
|
};
|
|
303
|
-
|
|
304
|
-
|
|
373
|
+
if (config.apiBaseUrl !== void 0) {
|
|
374
|
+
this.apiBaseUrl = config.apiBaseUrl;
|
|
375
|
+
} else if (config.isDev !== void 0) {
|
|
376
|
+
this.apiBaseUrl = config.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
|
|
377
|
+
}
|
|
378
|
+
console.log("[Hyve SDK] Config updated");
|
|
379
|
+
console.log("[Hyve SDK] API Base URL:", this.apiBaseUrl);
|
|
305
380
|
}
|
|
306
381
|
/**
|
|
307
382
|
* Gets the current user ID
|
|
@@ -317,6 +392,27 @@ var HyveClient = class {
|
|
|
317
392
|
getSessionId() {
|
|
318
393
|
return this.sessionId;
|
|
319
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* Gets the current JWT token
|
|
397
|
+
* @returns Current JWT token or null if not available
|
|
398
|
+
*/
|
|
399
|
+
getJwtToken() {
|
|
400
|
+
return this.jwtToken;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Gets the current game ID
|
|
404
|
+
* @returns Current game ID or null if not available
|
|
405
|
+
*/
|
|
406
|
+
getGameId() {
|
|
407
|
+
return this.gameId;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Gets the API base URL
|
|
411
|
+
* @returns API base URL
|
|
412
|
+
*/
|
|
413
|
+
getApiBaseUrl() {
|
|
414
|
+
return this.apiBaseUrl;
|
|
415
|
+
}
|
|
320
416
|
/**
|
|
321
417
|
* Checks if user is authenticated
|
|
322
418
|
* @returns Boolean indicating authentication status
|
|
@@ -324,11 +420,20 @@ var HyveClient = class {
|
|
|
324
420
|
isUserAuthenticated() {
|
|
325
421
|
return this.userId !== null;
|
|
326
422
|
}
|
|
423
|
+
/**
|
|
424
|
+
* Checks if JWT token is available
|
|
425
|
+
* @returns Boolean indicating if JWT token is present
|
|
426
|
+
*/
|
|
427
|
+
hasJwtToken() {
|
|
428
|
+
return this.jwtToken !== null;
|
|
429
|
+
}
|
|
327
430
|
/**
|
|
328
431
|
* Logs out the current user
|
|
329
432
|
*/
|
|
330
433
|
logout() {
|
|
331
434
|
this.userId = null;
|
|
435
|
+
this.jwtToken = null;
|
|
436
|
+
this.gameId = null;
|
|
332
437
|
console.log("[Hyve SDK] User logged out");
|
|
333
438
|
}
|
|
334
439
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,9 @@ function parseUrlParams(searchParams) {
|
|
|
8
8
|
message: params.get("message") || "",
|
|
9
9
|
gameStartTab: params.get("game_start_tab") || "",
|
|
10
10
|
hyveToken: params.get("hyve-token") || "",
|
|
11
|
-
platform: params.get("platform") || ""
|
|
11
|
+
platform: params.get("platform") || "",
|
|
12
|
+
hyveAccess: params.get("hyve-access") || "",
|
|
13
|
+
gameId: params.get("game-id") || ""
|
|
12
14
|
};
|
|
13
15
|
}
|
|
14
16
|
function validateSignature(signature, message) {
|
|
@@ -153,9 +155,11 @@ function isDomainAllowed(allowedDomains, hostname) {
|
|
|
153
155
|
// src/core/client.ts
|
|
154
156
|
var HyveClient = class {
|
|
155
157
|
telemetryConfig;
|
|
156
|
-
|
|
158
|
+
apiBaseUrl;
|
|
157
159
|
sessionId;
|
|
158
160
|
userId = null;
|
|
161
|
+
jwtToken = null;
|
|
162
|
+
gameId = null;
|
|
159
163
|
/**
|
|
160
164
|
* Creates a new HyveClient instance
|
|
161
165
|
* @param config Optional telemetry configuration
|
|
@@ -166,10 +170,15 @@ var HyveClient = class {
|
|
|
166
170
|
// Default to dev environment
|
|
167
171
|
...config
|
|
168
172
|
};
|
|
169
|
-
|
|
173
|
+
if (this.telemetryConfig.apiBaseUrl) {
|
|
174
|
+
this.apiBaseUrl = this.telemetryConfig.apiBaseUrl;
|
|
175
|
+
} else {
|
|
176
|
+
this.apiBaseUrl = this.telemetryConfig.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
|
|
177
|
+
}
|
|
170
178
|
this.sessionId = generateUUID();
|
|
171
179
|
console.log("[Hyve SDK] Client initialized with sessionId:", this.sessionId);
|
|
172
|
-
console.log("[Hyve SDK]
|
|
180
|
+
console.log("[Hyve SDK] API Base URL:", this.apiBaseUrl);
|
|
181
|
+
console.log("[Hyve SDK] Environment:", this.telemetryConfig.isDev ? "dev" : "prod");
|
|
173
182
|
}
|
|
174
183
|
/**
|
|
175
184
|
* Authenticates a user from URL parameters
|
|
@@ -179,6 +188,18 @@ var HyveClient = class {
|
|
|
179
188
|
async authenticateFromUrl(urlParams) {
|
|
180
189
|
try {
|
|
181
190
|
const params = urlParams ? parseUrlParams(urlParams) : parseUrlParams(window.location.search);
|
|
191
|
+
if (params.hyveAccess) {
|
|
192
|
+
this.jwtToken = params.hyveAccess;
|
|
193
|
+
console.log("[Hyve SDK] JWT token extracted from hyve-access parameter");
|
|
194
|
+
}
|
|
195
|
+
if (params.gameId) {
|
|
196
|
+
this.gameId = params.gameId;
|
|
197
|
+
console.log("[Hyve SDK] Game ID extracted from game-id parameter:", this.gameId);
|
|
198
|
+
}
|
|
199
|
+
if (this.jwtToken) {
|
|
200
|
+
console.log("[Hyve SDK] Authentication successful via JWT");
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
182
203
|
const authResult = verifyAuthentication({
|
|
183
204
|
hyveToken: params.hyveToken,
|
|
184
205
|
signature: params.signature,
|
|
@@ -201,47 +222,51 @@ var HyveClient = class {
|
|
|
201
222
|
}
|
|
202
223
|
}
|
|
203
224
|
/**
|
|
204
|
-
* Sends a telemetry event
|
|
225
|
+
* Sends a user-level telemetry event using JWT authentication
|
|
226
|
+
* Requires JWT token, authenticated user, and game ID from URL parameters
|
|
205
227
|
* @param eventLocation Location where the event occurred
|
|
206
228
|
* @param eventCategory Main category of the event
|
|
207
229
|
* @param eventAction Primary action taken
|
|
208
230
|
* @param eventSubCategory Optional sub-category
|
|
209
231
|
* @param eventSubAction Optional sub-action
|
|
210
|
-
* @param eventDetails Optional event details
|
|
211
|
-
* @param
|
|
232
|
+
* @param eventDetails Optional event details (object or JSON string)
|
|
233
|
+
* @param customData Optional custom data (object or JSON string)
|
|
234
|
+
* @param platformId Optional platform identifier
|
|
212
235
|
* @returns Promise resolving to boolean indicating success
|
|
213
236
|
*/
|
|
214
|
-
async sendTelemetry(eventLocation, eventCategory, eventAction, eventSubCategory, eventSubAction, eventDetails,
|
|
215
|
-
if (!this.
|
|
216
|
-
console.error("[Hyve Telemetry]
|
|
237
|
+
async sendTelemetry(eventLocation, eventCategory, eventAction, eventSubCategory, eventSubAction, eventDetails, customData, platformId) {
|
|
238
|
+
if (!this.jwtToken) {
|
|
239
|
+
console.error("[Hyve Telemetry] JWT token required. Call authenticateFromUrl first.");
|
|
217
240
|
return false;
|
|
218
241
|
}
|
|
219
|
-
if (!this.
|
|
220
|
-
console.
|
|
242
|
+
if (!this.gameId) {
|
|
243
|
+
console.error("[Hyve Telemetry] Game ID required. Ensure game-id URL parameter is set.");
|
|
244
|
+
return false;
|
|
221
245
|
}
|
|
222
246
|
try {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
finalEventDetails = eventDetails;
|
|
228
|
-
}
|
|
247
|
+
const toJsonString = (data) => {
|
|
248
|
+
if (!data) return null;
|
|
249
|
+
return typeof data === "string" ? data : JSON.stringify(data);
|
|
250
|
+
};
|
|
229
251
|
const telemetryEvent = {
|
|
252
|
+
game_id: this.gameId,
|
|
230
253
|
session_id: this.sessionId,
|
|
231
|
-
|
|
254
|
+
platform_id: platformId || null,
|
|
232
255
|
event_location: eventLocation,
|
|
233
256
|
event_category: eventCategory,
|
|
234
257
|
event_action: eventAction,
|
|
235
258
|
event_sub_category: eventSubCategory || null,
|
|
236
259
|
event_sub_action: eventSubAction || null,
|
|
237
|
-
event_details:
|
|
260
|
+
event_details: toJsonString(eventDetails),
|
|
261
|
+
custom_data: toJsonString(customData)
|
|
238
262
|
};
|
|
239
|
-
console.log("[Hyve Telemetry] Sending event:", telemetryEvent);
|
|
240
|
-
const
|
|
263
|
+
console.log("[Hyve Telemetry] Sending user-level event:", telemetryEvent);
|
|
264
|
+
const telemetryUrl = `${this.apiBaseUrl}/api/v1/telemetry/send`;
|
|
265
|
+
const response = await fetch(telemetryUrl, {
|
|
241
266
|
method: "POST",
|
|
242
267
|
headers: {
|
|
243
268
|
"Content-Type": "application/json",
|
|
244
|
-
"
|
|
269
|
+
"Authorization": `Bearer ${this.jwtToken}`
|
|
245
270
|
},
|
|
246
271
|
body: JSON.stringify(telemetryEvent)
|
|
247
272
|
});
|
|
@@ -258,6 +283,51 @@ var HyveClient = class {
|
|
|
258
283
|
return false;
|
|
259
284
|
}
|
|
260
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* Makes an authenticated API call using the JWT token
|
|
288
|
+
* @param endpoint API endpoint path (will be appended to base URL)
|
|
289
|
+
* @param options Fetch options (method, body, etc.)
|
|
290
|
+
* @returns Promise resolving to the API response
|
|
291
|
+
*/
|
|
292
|
+
async callApi(endpoint, options = {}) {
|
|
293
|
+
if (!this.jwtToken) {
|
|
294
|
+
throw new Error("[Hyve SDK] No JWT token available. Call authenticateFromUrl first.");
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
const url = `${this.apiBaseUrl}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
|
|
298
|
+
const response = await fetch(url, {
|
|
299
|
+
...options,
|
|
300
|
+
headers: {
|
|
301
|
+
"Content-Type": "application/json",
|
|
302
|
+
"Authorization": `Bearer ${this.jwtToken}`,
|
|
303
|
+
...options.headers
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
if (!response.ok) {
|
|
307
|
+
const errorText = await response.text();
|
|
308
|
+
throw new Error(`API request failed: ${response.status} ${errorText}`);
|
|
309
|
+
}
|
|
310
|
+
return await response.json();
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error("[Hyve SDK] API call failed:", error);
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Gets the user's inventory
|
|
318
|
+
* @returns Promise resolving to the user's inventory
|
|
319
|
+
*/
|
|
320
|
+
async getInventory() {
|
|
321
|
+
return this.callApi("/api/v1/inventory");
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Gets a specific inventory item by ID
|
|
325
|
+
* @param itemId The inventory item ID
|
|
326
|
+
* @returns Promise resolving to the inventory item details
|
|
327
|
+
*/
|
|
328
|
+
async getInventoryItem(itemId) {
|
|
329
|
+
return this.callApi(`/api/v1/inventory/${itemId}`);
|
|
330
|
+
}
|
|
261
331
|
/**
|
|
262
332
|
* Updates the telemetry configuration
|
|
263
333
|
* @param config New telemetry configuration
|
|
@@ -267,8 +337,13 @@ var HyveClient = class {
|
|
|
267
337
|
...this.telemetryConfig,
|
|
268
338
|
...config
|
|
269
339
|
};
|
|
270
|
-
|
|
271
|
-
|
|
340
|
+
if (config.apiBaseUrl !== void 0) {
|
|
341
|
+
this.apiBaseUrl = config.apiBaseUrl;
|
|
342
|
+
} else if (config.isDev !== void 0) {
|
|
343
|
+
this.apiBaseUrl = config.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
|
|
344
|
+
}
|
|
345
|
+
console.log("[Hyve SDK] Config updated");
|
|
346
|
+
console.log("[Hyve SDK] API Base URL:", this.apiBaseUrl);
|
|
272
347
|
}
|
|
273
348
|
/**
|
|
274
349
|
* Gets the current user ID
|
|
@@ -284,6 +359,27 @@ var HyveClient = class {
|
|
|
284
359
|
getSessionId() {
|
|
285
360
|
return this.sessionId;
|
|
286
361
|
}
|
|
362
|
+
/**
|
|
363
|
+
* Gets the current JWT token
|
|
364
|
+
* @returns Current JWT token or null if not available
|
|
365
|
+
*/
|
|
366
|
+
getJwtToken() {
|
|
367
|
+
return this.jwtToken;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Gets the current game ID
|
|
371
|
+
* @returns Current game ID or null if not available
|
|
372
|
+
*/
|
|
373
|
+
getGameId() {
|
|
374
|
+
return this.gameId;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Gets the API base URL
|
|
378
|
+
* @returns API base URL
|
|
379
|
+
*/
|
|
380
|
+
getApiBaseUrl() {
|
|
381
|
+
return this.apiBaseUrl;
|
|
382
|
+
}
|
|
287
383
|
/**
|
|
288
384
|
* Checks if user is authenticated
|
|
289
385
|
* @returns Boolean indicating authentication status
|
|
@@ -291,11 +387,20 @@ var HyveClient = class {
|
|
|
291
387
|
isUserAuthenticated() {
|
|
292
388
|
return this.userId !== null;
|
|
293
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* Checks if JWT token is available
|
|
392
|
+
* @returns Boolean indicating if JWT token is present
|
|
393
|
+
*/
|
|
394
|
+
hasJwtToken() {
|
|
395
|
+
return this.jwtToken !== null;
|
|
396
|
+
}
|
|
294
397
|
/**
|
|
295
398
|
* Logs out the current user
|
|
296
399
|
*/
|
|
297
400
|
logout() {
|
|
298
401
|
this.userId = null;
|
|
402
|
+
this.jwtToken = null;
|
|
403
|
+
this.gameId = null;
|
|
299
404
|
console.log("[Hyve SDK] User logged out");
|
|
300
405
|
}
|
|
301
406
|
/**
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyve-sdk/js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Hyve SDK - TypeScript wrapper for Hyve game server integration",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
7
|
-
"access": "
|
|
7
|
+
"access": "public",
|
|
8
8
|
"registry": "https://registry.npmjs.org/"
|
|
9
9
|
},
|
|
10
10
|
"main": "dist/index.js",
|
|
@@ -44,14 +44,14 @@
|
|
|
44
44
|
"@types/uuid": "^10.0.0",
|
|
45
45
|
"tsup": "^8.4.0",
|
|
46
46
|
"typescript": "^5.3.3",
|
|
47
|
-
"@repo/
|
|
48
|
-
"@repo/
|
|
47
|
+
"@repo/typescript-config": "0.0.0",
|
|
48
|
+
"@repo/eslint-config": "0.0.0"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"lint": "eslint . --max-warnings 0",
|
|
52
52
|
"check-types": "tsc --noEmit",
|
|
53
53
|
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
54
|
-
"publish:npm": "pnpm publish --access
|
|
55
|
-
"publish:dry-run": "pnpm publish --dry-run --access
|
|
54
|
+
"publish:npm": "pnpm publish --access public",
|
|
55
|
+
"publish:dry-run": "pnpm publish --dry-run --access public --no-git-checks"
|
|
56
56
|
}
|
|
57
57
|
}
|