@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 +137 -22
- package/dist/index.d.mts +250 -25
- package/dist/index.d.ts +250 -25
- package/dist/index.js +426 -51
- package/dist/index.mjs +422 -51
- package/package.json +13 -12
package/dist/index.js
CHANGED
|
@@ -21,9 +21,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
HyveClient: () => HyveClient,
|
|
24
|
+
Logger: () => Logger,
|
|
25
|
+
NativeBridge: () => NativeBridge,
|
|
26
|
+
NativeMessageType: () => NativeMessageType,
|
|
24
27
|
generateUUID: () => generateUUID,
|
|
25
28
|
handleVerifyMessage: () => handleVerifyMessage,
|
|
26
29
|
isDomainAllowed: () => isDomainAllowed,
|
|
30
|
+
logger: () => logger,
|
|
27
31
|
parseUrlParams: () => parseUrlParams,
|
|
28
32
|
validateSignature: () => validateSignature,
|
|
29
33
|
verifyAuthentication: () => verifyAuthentication,
|
|
@@ -32,8 +36,132 @@ __export(index_exports, {
|
|
|
32
36
|
module.exports = __toCommonJS(index_exports);
|
|
33
37
|
|
|
34
38
|
// src/utils/index.ts
|
|
35
|
-
var import_ethers = require("ethers");
|
|
36
39
|
var import_uuid = require("uuid");
|
|
40
|
+
|
|
41
|
+
// src/utils/logger.ts
|
|
42
|
+
var Logger = class _Logger {
|
|
43
|
+
config;
|
|
44
|
+
constructor() {
|
|
45
|
+
this.config = this.initializeConfig();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Initialize logger configuration based on NODE_ENV
|
|
49
|
+
*/
|
|
50
|
+
initializeConfig() {
|
|
51
|
+
const isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
52
|
+
let enabled = false;
|
|
53
|
+
let levels = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
54
|
+
if (isNode) {
|
|
55
|
+
const nodeEnv = process.env.NODE_ENV;
|
|
56
|
+
enabled = nodeEnv !== "production";
|
|
57
|
+
const logLevelEnv = process.env.HYVE_SDK_LOG_LEVEL;
|
|
58
|
+
if (logLevelEnv) {
|
|
59
|
+
const configuredLevels = logLevelEnv.split(",").map((l) => l.trim());
|
|
60
|
+
levels = new Set(configuredLevels);
|
|
61
|
+
}
|
|
62
|
+
} else if (typeof window !== "undefined") {
|
|
63
|
+
try {
|
|
64
|
+
enabled = process.env.NODE_ENV !== "production";
|
|
65
|
+
} catch (e) {
|
|
66
|
+
enabled = true;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const localStorageLogLevel = localStorage.getItem("HYVE_SDK_LOG_LEVEL");
|
|
70
|
+
if (localStorageLogLevel) {
|
|
71
|
+
const configuredLevels = localStorageLogLevel.split(",").map((l) => l.trim());
|
|
72
|
+
levels = new Set(configuredLevels);
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
enabled,
|
|
79
|
+
prefix: "[Hyve SDK]",
|
|
80
|
+
levels
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Set which log levels to display
|
|
85
|
+
*/
|
|
86
|
+
setLevels(levels) {
|
|
87
|
+
this.config.levels = new Set(levels);
|
|
88
|
+
if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
|
|
89
|
+
try {
|
|
90
|
+
localStorage.setItem("HYVE_SDK_LOG_LEVEL", levels.join(","));
|
|
91
|
+
} catch (e) {
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if logging is enabled
|
|
97
|
+
*/
|
|
98
|
+
isEnabled() {
|
|
99
|
+
return this.config.enabled;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Internal log method
|
|
103
|
+
*/
|
|
104
|
+
log(level, ...args) {
|
|
105
|
+
if (!this.config.enabled || !this.config.levels.has(level)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
109
|
+
const prefix = `${this.config.prefix} [${level.toUpperCase()}] [${timestamp}]`;
|
|
110
|
+
switch (level) {
|
|
111
|
+
case "debug":
|
|
112
|
+
console.debug(prefix, ...args);
|
|
113
|
+
break;
|
|
114
|
+
case "info":
|
|
115
|
+
console.info(prefix, ...args);
|
|
116
|
+
break;
|
|
117
|
+
case "warn":
|
|
118
|
+
console.warn(prefix, ...args);
|
|
119
|
+
break;
|
|
120
|
+
case "error":
|
|
121
|
+
console.error(prefix, ...args);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Log a debug message
|
|
127
|
+
*/
|
|
128
|
+
debug(...args) {
|
|
129
|
+
this.log("debug", ...args);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Log an info message
|
|
133
|
+
*/
|
|
134
|
+
info(...args) {
|
|
135
|
+
this.log("info", ...args);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Log a warning message
|
|
139
|
+
*/
|
|
140
|
+
warn(...args) {
|
|
141
|
+
this.log("warn", ...args);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Log an error message
|
|
145
|
+
*/
|
|
146
|
+
error(...args) {
|
|
147
|
+
this.log("error", ...args);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Create a child logger with a specific prefix
|
|
151
|
+
*/
|
|
152
|
+
child(prefix) {
|
|
153
|
+
const childLogger = new _Logger();
|
|
154
|
+
childLogger.config = {
|
|
155
|
+
...this.config,
|
|
156
|
+
prefix: `${this.config.prefix} [${prefix}]`
|
|
157
|
+
};
|
|
158
|
+
return childLogger;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var logger = new Logger();
|
|
162
|
+
|
|
163
|
+
// src/utils/auth.ts
|
|
164
|
+
var import_ethers = require("ethers");
|
|
37
165
|
function parseUrlParams(searchParams) {
|
|
38
166
|
const params = typeof searchParams === "string" ? new URLSearchParams(searchParams) : searchParams;
|
|
39
167
|
return {
|
|
@@ -42,7 +170,8 @@ function parseUrlParams(searchParams) {
|
|
|
42
170
|
gameStartTab: params.get("game_start_tab") || "",
|
|
43
171
|
hyveToken: params.get("hyve-token") || "",
|
|
44
172
|
platform: params.get("platform") || "",
|
|
45
|
-
hyveAccess: params.get("hyve-access") || ""
|
|
173
|
+
hyveAccess: params.get("hyve-access") || "",
|
|
174
|
+
gameId: params.get("game-id") || ""
|
|
46
175
|
};
|
|
47
176
|
}
|
|
48
177
|
function validateSignature(signature, message) {
|
|
@@ -50,7 +179,7 @@ function validateSignature(signature, message) {
|
|
|
50
179
|
const recoveredAddress = import_ethers.ethers.verifyMessage(message, signature);
|
|
51
180
|
return !!recoveredAddress;
|
|
52
181
|
} catch (error) {
|
|
53
|
-
|
|
182
|
+
logger.error("Signature validation error:", error);
|
|
54
183
|
return false;
|
|
55
184
|
}
|
|
56
185
|
}
|
|
@@ -77,7 +206,7 @@ function handleVerifyMessage(signature, message) {
|
|
|
77
206
|
}
|
|
78
207
|
return userAddress;
|
|
79
208
|
} catch (error) {
|
|
80
|
-
|
|
209
|
+
logger.error("Error verifying message:", error);
|
|
81
210
|
return false;
|
|
82
211
|
}
|
|
83
212
|
}
|
|
@@ -85,7 +214,7 @@ function verifyHyveToken(hyveToken, maxAgeSec = 600) {
|
|
|
85
214
|
try {
|
|
86
215
|
const parts = hyveToken.split(".");
|
|
87
216
|
if (parts.length !== 4) {
|
|
88
|
-
|
|
217
|
+
logger.error(
|
|
89
218
|
"Invalid hyve-token format: expected 4 parts, got",
|
|
90
219
|
parts.length
|
|
91
220
|
);
|
|
@@ -93,30 +222,30 @@ function verifyHyveToken(hyveToken, maxAgeSec = 600) {
|
|
|
93
222
|
}
|
|
94
223
|
const [signature, address, randomBase64, timestampStr] = parts;
|
|
95
224
|
if (!signature || !address || !randomBase64 || !timestampStr) {
|
|
96
|
-
|
|
225
|
+
logger.error("Missing hyve-token components");
|
|
97
226
|
return false;
|
|
98
227
|
}
|
|
99
228
|
const message = `${address}.${randomBase64}.${timestampStr}`;
|
|
100
229
|
const recoveredAddress = import_ethers.ethers.verifyMessage(message, signature);
|
|
101
230
|
if (recoveredAddress.toLowerCase() !== address.toLowerCase()) {
|
|
102
|
-
|
|
231
|
+
logger.error("Hyve-token signature verification failed");
|
|
103
232
|
return false;
|
|
104
233
|
}
|
|
105
234
|
const timestamp = parseInt(timestampStr, 10);
|
|
106
235
|
if (!Number.isFinite(timestamp)) {
|
|
107
|
-
|
|
236
|
+
logger.error("Invalid hyve-token timestamp");
|
|
108
237
|
return false;
|
|
109
238
|
}
|
|
110
239
|
const now = Math.floor(Date.now() / 1e3);
|
|
111
240
|
if (now - timestamp > maxAgeSec) {
|
|
112
|
-
|
|
241
|
+
logger.error(
|
|
113
242
|
`Hyve-token expired (age: ${now - timestamp}s, max: ${maxAgeSec}s)`
|
|
114
243
|
);
|
|
115
244
|
return false;
|
|
116
245
|
}
|
|
117
246
|
return address;
|
|
118
247
|
} catch (error) {
|
|
119
|
-
|
|
248
|
+
logger.error("Hyve-token verification error:", error);
|
|
120
249
|
return false;
|
|
121
250
|
}
|
|
122
251
|
}
|
|
@@ -162,11 +291,8 @@ function verifyAuthentication(params, maxAgeSec = 600) {
|
|
|
162
291
|
error: "No authentication tokens provided"
|
|
163
292
|
};
|
|
164
293
|
}
|
|
165
|
-
function generateUUID() {
|
|
166
|
-
return (0, import_uuid.v4)();
|
|
167
|
-
}
|
|
168
294
|
function isDomainAllowed(allowedDomains, hostname) {
|
|
169
|
-
|
|
295
|
+
logger.debug("Checking hostname:", hostname);
|
|
170
296
|
if (!allowedDomains) return true;
|
|
171
297
|
const targetHostname = hostname || "";
|
|
172
298
|
if (!targetHostname) return false;
|
|
@@ -184,6 +310,216 @@ function isDomainAllowed(allowedDomains, hostname) {
|
|
|
184
310
|
});
|
|
185
311
|
}
|
|
186
312
|
|
|
313
|
+
// src/utils/native-bridge.ts
|
|
314
|
+
var NativeMessageType = /* @__PURE__ */ ((NativeMessageType2) => {
|
|
315
|
+
NativeMessageType2["CHECK_IAP_AVAILABILITY"] = "CHECK_IAP_AVAILABILITY";
|
|
316
|
+
NativeMessageType2["REQUEST_NOTIFICATION_PERMISSION"] = "REQUEST_NOTIFICATION_PERMISSION";
|
|
317
|
+
NativeMessageType2["GET_PRODUCTS"] = "GET_PRODUCTS";
|
|
318
|
+
NativeMessageType2["PURCHASE"] = "PURCHASE";
|
|
319
|
+
NativeMessageType2["IAP_AVAILABILITY_RESULT"] = "IAP_AVAILABILITY_RESULT";
|
|
320
|
+
NativeMessageType2["PUSH_PERMISSION_GRANTED"] = "PUSH_PERMISSION_GRANTED";
|
|
321
|
+
NativeMessageType2["PUSH_PERMISSION_DENIED"] = "PUSH_PERMISSION_DENIED";
|
|
322
|
+
NativeMessageType2["PRODUCTS_RESULT"] = "PRODUCTS_RESULT";
|
|
323
|
+
NativeMessageType2["PURCHASE_COMPLETE"] = "PURCHASE_COMPLETE";
|
|
324
|
+
NativeMessageType2["PURCHASE_ERROR"] = "PURCHASE_ERROR";
|
|
325
|
+
return NativeMessageType2;
|
|
326
|
+
})(NativeMessageType || {});
|
|
327
|
+
var NativeBridge = class {
|
|
328
|
+
static handlers = /* @__PURE__ */ new Map();
|
|
329
|
+
static isInitialized = false;
|
|
330
|
+
/**
|
|
331
|
+
* Checks if the app is running inside a React Native WebView
|
|
332
|
+
*/
|
|
333
|
+
static isNativeContext() {
|
|
334
|
+
return typeof window !== "undefined" && "ReactNativeWebView" in window;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Initializes the native bridge message listener
|
|
338
|
+
* Call this once when your app starts
|
|
339
|
+
*/
|
|
340
|
+
static initialize() {
|
|
341
|
+
if (this.isInitialized) {
|
|
342
|
+
logger.debug("[NativeBridge] Already initialized");
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (typeof window === "undefined") {
|
|
346
|
+
logger.warn("[NativeBridge] Window not available, skipping initialization");
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const boundHandler = this.handleNativeMessage.bind(this);
|
|
350
|
+
window.addEventListener("message", boundHandler);
|
|
351
|
+
document.addEventListener("message", boundHandler);
|
|
352
|
+
this.isInitialized = true;
|
|
353
|
+
logger.info("[NativeBridge] Initialized and listening for native messages");
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Handles incoming messages from React Native
|
|
357
|
+
*/
|
|
358
|
+
static handleNativeMessage(event) {
|
|
359
|
+
try {
|
|
360
|
+
let data;
|
|
361
|
+
if (typeof event.data === "string") {
|
|
362
|
+
try {
|
|
363
|
+
data = JSON.parse(event.data);
|
|
364
|
+
logger.debug("[NativeBridge] Parsed message string:", data);
|
|
365
|
+
} catch (parseError) {
|
|
366
|
+
logger.debug("[NativeBridge] Failed to parse message, not JSON:", event.data);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
} else if (typeof event.data === "object" && event.data !== null) {
|
|
370
|
+
data = event.data;
|
|
371
|
+
logger.debug("[NativeBridge] Received message object:", data);
|
|
372
|
+
} else {
|
|
373
|
+
logger.debug("[NativeBridge] Received invalid message type:", typeof event.data);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (!data || !data.type) {
|
|
377
|
+
logger.debug("[NativeBridge] Received message without type, ignoring");
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const handler = this.handlers.get(data.type);
|
|
381
|
+
if (handler) {
|
|
382
|
+
logger.info(`[NativeBridge] Handling message: ${data.type}`, data.payload);
|
|
383
|
+
handler(data.payload);
|
|
384
|
+
} else {
|
|
385
|
+
logger.warn(`[NativeBridge] No handler registered for: ${data.type}`);
|
|
386
|
+
}
|
|
387
|
+
} catch (error) {
|
|
388
|
+
logger.error("[NativeBridge] Error handling native message:", error);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Sends a message to React Native
|
|
393
|
+
* @param type Message type
|
|
394
|
+
* @param payload Optional payload data
|
|
395
|
+
*/
|
|
396
|
+
static send(type, payload) {
|
|
397
|
+
if (!this.isNativeContext()) {
|
|
398
|
+
logger.debug(
|
|
399
|
+
`[NativeBridge] Not in native context, skipping message: ${type}`
|
|
400
|
+
);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
try {
|
|
404
|
+
const message = {
|
|
405
|
+
type,
|
|
406
|
+
payload,
|
|
407
|
+
timestamp: Date.now()
|
|
408
|
+
};
|
|
409
|
+
window.ReactNativeWebView.postMessage(JSON.stringify(message));
|
|
410
|
+
logger.debug(`[NativeBridge] Sent message to native: ${type}`, payload);
|
|
411
|
+
} catch (error) {
|
|
412
|
+
logger.error(`[NativeBridge] Error sending message to native:`, error);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Registers a handler for messages from React Native
|
|
417
|
+
* @param type Message type to listen for
|
|
418
|
+
* @param handler Function to call when message is received
|
|
419
|
+
*/
|
|
420
|
+
static on(type, handler) {
|
|
421
|
+
this.handlers.set(type, handler);
|
|
422
|
+
logger.debug(`[NativeBridge] Registered handler for: ${type}`);
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Unregisters a handler for a specific message type
|
|
426
|
+
* @param type Message type to stop listening for
|
|
427
|
+
*/
|
|
428
|
+
static off(type) {
|
|
429
|
+
this.handlers.delete(type);
|
|
430
|
+
logger.debug(`[NativeBridge] Unregistered handler for: ${type}`);
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Clears all registered handlers
|
|
434
|
+
*/
|
|
435
|
+
static clearHandlers() {
|
|
436
|
+
this.handlers.clear();
|
|
437
|
+
logger.debug("[NativeBridge] Cleared all handlers");
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Checks if In-App Purchases are available on the device
|
|
441
|
+
* The native app will respond with a message containing availability status
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* // Listen for the response
|
|
445
|
+
* NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
|
|
446
|
+
* console.log("IAP available:", payload.available);
|
|
447
|
+
* });
|
|
448
|
+
*
|
|
449
|
+
* // Send the request
|
|
450
|
+
* NativeBridge.checkIAPAvailability();
|
|
451
|
+
*/
|
|
452
|
+
static checkIAPAvailability() {
|
|
453
|
+
this.send("CHECK_IAP_AVAILABILITY" /* CHECK_IAP_AVAILABILITY */);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Requests notification permission from the native app
|
|
457
|
+
* The native app will respond with PUSH_PERMISSION_GRANTED or PUSH_PERMISSION_DENIED
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* // Listen for the response
|
|
461
|
+
* NativeBridge.on("PUSH_PERMISSION_GRANTED", () => {
|
|
462
|
+
* console.log("Permission granted");
|
|
463
|
+
* });
|
|
464
|
+
*
|
|
465
|
+
* NativeBridge.on("PUSH_PERMISSION_DENIED", () => {
|
|
466
|
+
* console.log("Permission denied");
|
|
467
|
+
* });
|
|
468
|
+
*
|
|
469
|
+
* // Send the request
|
|
470
|
+
* NativeBridge.requestNotificationPermission();
|
|
471
|
+
*/
|
|
472
|
+
static requestNotificationPermission() {
|
|
473
|
+
this.send("REQUEST_NOTIFICATION_PERMISSION" /* REQUEST_NOTIFICATION_PERMISSION */);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Requests available products for a specific game
|
|
477
|
+
* The native app will respond with PRODUCTS_RESULT containing product details
|
|
478
|
+
*
|
|
479
|
+
* @param gameId - The game ID to fetch products for
|
|
480
|
+
*
|
|
481
|
+
* @example
|
|
482
|
+
* // Listen for the response
|
|
483
|
+
* NativeBridge.on("PRODUCTS_RESULT", (payload) => {
|
|
484
|
+
* console.log("Products:", payload.products);
|
|
485
|
+
* });
|
|
486
|
+
*
|
|
487
|
+
* // Send the request
|
|
488
|
+
* NativeBridge.getProducts(123);
|
|
489
|
+
*/
|
|
490
|
+
static getProducts(gameId) {
|
|
491
|
+
this.send("GET_PRODUCTS" /* GET_PRODUCTS */, { gameId });
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Initiates a purchase for a specific product
|
|
495
|
+
* The native app will respond with PURCHASE_COMPLETE or PURCHASE_ERROR
|
|
496
|
+
*
|
|
497
|
+
* @param productId - The product ID to purchase
|
|
498
|
+
* @param userId - The user ID making the purchase
|
|
499
|
+
*
|
|
500
|
+
* @example
|
|
501
|
+
* // Listen for responses
|
|
502
|
+
* NativeBridge.on("PURCHASE_COMPLETE", (payload) => {
|
|
503
|
+
* console.log("Purchase successful:", payload.productId);
|
|
504
|
+
* });
|
|
505
|
+
*
|
|
506
|
+
* NativeBridge.on("PURCHASE_ERROR", (payload) => {
|
|
507
|
+
* console.error("Purchase failed:", payload.error);
|
|
508
|
+
* });
|
|
509
|
+
*
|
|
510
|
+
* // Initiate purchase
|
|
511
|
+
* NativeBridge.purchase("product_123", "user_456");
|
|
512
|
+
*/
|
|
513
|
+
static purchase(productId, userId) {
|
|
514
|
+
this.send("PURCHASE" /* PURCHASE */, { productId, userId });
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
// src/utils/index.ts
|
|
519
|
+
function generateUUID() {
|
|
520
|
+
return (0, import_uuid.v4)();
|
|
521
|
+
}
|
|
522
|
+
|
|
187
523
|
// src/core/client.ts
|
|
188
524
|
var HyveClient = class {
|
|
189
525
|
telemetryConfig;
|
|
@@ -191,6 +527,7 @@ var HyveClient = class {
|
|
|
191
527
|
sessionId;
|
|
192
528
|
userId = null;
|
|
193
529
|
jwtToken = null;
|
|
530
|
+
gameId = null;
|
|
194
531
|
/**
|
|
195
532
|
* Creates a new HyveClient instance
|
|
196
533
|
* @param config Optional telemetry configuration
|
|
@@ -207,9 +544,9 @@ var HyveClient = class {
|
|
|
207
544
|
this.apiBaseUrl = this.telemetryConfig.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
|
|
208
545
|
}
|
|
209
546
|
this.sessionId = generateUUID();
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
547
|
+
logger.info("Client initialized with sessionId:", this.sessionId);
|
|
548
|
+
logger.info("API Base URL:", this.apiBaseUrl);
|
|
549
|
+
logger.info("Environment:", this.telemetryConfig.isDev ? "dev" : "prod");
|
|
213
550
|
}
|
|
214
551
|
/**
|
|
215
552
|
* Authenticates a user from URL parameters
|
|
@@ -221,7 +558,23 @@ var HyveClient = class {
|
|
|
221
558
|
const params = urlParams ? parseUrlParams(urlParams) : parseUrlParams(window.location.search);
|
|
222
559
|
if (params.hyveAccess) {
|
|
223
560
|
this.jwtToken = params.hyveAccess;
|
|
224
|
-
|
|
561
|
+
logger.info("JWT token extracted from hyve-access parameter");
|
|
562
|
+
}
|
|
563
|
+
if (params.gameId) {
|
|
564
|
+
this.gameId = params.gameId;
|
|
565
|
+
logger.info("Game ID extracted from game-id parameter:", this.gameId);
|
|
566
|
+
}
|
|
567
|
+
if (this.jwtToken) {
|
|
568
|
+
logger.info("Authentication successful via JWT");
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
if (params.gameId) {
|
|
572
|
+
this.gameId = params.gameId;
|
|
573
|
+
logger.info("Game ID extracted from game-id parameter:", this.gameId);
|
|
574
|
+
}
|
|
575
|
+
if (this.jwtToken) {
|
|
576
|
+
logger.info("Authentication successful via JWT");
|
|
577
|
+
return true;
|
|
225
578
|
}
|
|
226
579
|
const authResult = verifyAuthentication({
|
|
227
580
|
hyveToken: params.hyveToken,
|
|
@@ -230,76 +583,83 @@ var HyveClient = class {
|
|
|
230
583
|
});
|
|
231
584
|
if (authResult.isValid && authResult.address) {
|
|
232
585
|
this.userId = authResult.address;
|
|
233
|
-
|
|
234
|
-
|
|
586
|
+
logger.info("Authentication successful:", authResult.address);
|
|
587
|
+
logger.info("Authentication method:", authResult.method);
|
|
235
588
|
return true;
|
|
236
589
|
} else {
|
|
237
|
-
|
|
590
|
+
logger.error("Authentication failed:", authResult.error);
|
|
238
591
|
this.userId = null;
|
|
239
592
|
return false;
|
|
240
593
|
}
|
|
241
594
|
} catch (error) {
|
|
242
|
-
|
|
595
|
+
logger.error("Authentication error:", error);
|
|
243
596
|
this.userId = null;
|
|
244
597
|
return false;
|
|
245
598
|
}
|
|
246
599
|
}
|
|
247
600
|
/**
|
|
248
|
-
* Sends a telemetry event
|
|
601
|
+
* Sends a user-level telemetry event using JWT authentication
|
|
602
|
+
* Requires JWT token, authenticated user, and game ID from URL parameters
|
|
249
603
|
* @param eventLocation Location where the event occurred
|
|
250
604
|
* @param eventCategory Main category of the event
|
|
251
605
|
* @param eventAction Primary action taken
|
|
252
606
|
* @param eventSubCategory Optional sub-category
|
|
253
607
|
* @param eventSubAction Optional sub-action
|
|
254
|
-
* @param eventDetails Optional event details
|
|
255
|
-
* @param
|
|
608
|
+
* @param eventDetails Optional event details (object or JSON string)
|
|
609
|
+
* @param customData Optional custom data (object or JSON string)
|
|
610
|
+
* @param platformId Optional platform identifier
|
|
256
611
|
* @returns Promise resolving to boolean indicating success
|
|
257
612
|
*/
|
|
258
|
-
async sendTelemetry(eventLocation, eventCategory, eventAction, eventSubCategory, eventSubAction, eventDetails,
|
|
259
|
-
if (!this.
|
|
260
|
-
|
|
613
|
+
async sendTelemetry(eventLocation, eventCategory, eventAction, eventSubCategory, eventSubAction, eventDetails, customData, platformId) {
|
|
614
|
+
if (!this.jwtToken) {
|
|
615
|
+
logger.error("JWT token required. Call authenticateFromUrl first.");
|
|
261
616
|
return false;
|
|
262
617
|
}
|
|
263
|
-
if (!this.
|
|
264
|
-
|
|
618
|
+
if (!this.gameId) {
|
|
619
|
+
logger.error("Game ID required. Ensure game-id URL parameter is set.");
|
|
620
|
+
return false;
|
|
265
621
|
}
|
|
266
622
|
try {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
finalEventDetails = eventDetails;
|
|
272
|
-
}
|
|
623
|
+
const toJsonString = (data) => {
|
|
624
|
+
if (!data) return null;
|
|
625
|
+
return typeof data === "string" ? data : JSON.stringify(data);
|
|
626
|
+
};
|
|
273
627
|
const telemetryEvent = {
|
|
628
|
+
game_id: this.gameId,
|
|
274
629
|
session_id: this.sessionId,
|
|
275
|
-
|
|
630
|
+
platform_id: platformId || null,
|
|
276
631
|
event_location: eventLocation,
|
|
277
632
|
event_category: eventCategory,
|
|
278
633
|
event_action: eventAction,
|
|
279
634
|
event_sub_category: eventSubCategory || null,
|
|
280
635
|
event_sub_action: eventSubAction || null,
|
|
281
|
-
event_details:
|
|
636
|
+
event_details: toJsonString(eventDetails),
|
|
637
|
+
custom_data: toJsonString(customData)
|
|
282
638
|
};
|
|
283
|
-
|
|
284
|
-
const telemetryUrl = `${this.apiBaseUrl}/api/v1/
|
|
639
|
+
logger.debug("Sending telemetry event:", telemetryEvent);
|
|
640
|
+
const telemetryUrl = `${this.apiBaseUrl}/api/v1/telemetry/send`;
|
|
285
641
|
const response = await fetch(telemetryUrl, {
|
|
286
642
|
method: "POST",
|
|
287
643
|
headers: {
|
|
288
644
|
"Content-Type": "application/json",
|
|
289
|
-
|
|
645
|
+
Authorization: `Bearer ${this.jwtToken}`
|
|
290
646
|
},
|
|
291
647
|
body: JSON.stringify(telemetryEvent)
|
|
292
648
|
});
|
|
293
649
|
if (response.ok) {
|
|
294
|
-
|
|
650
|
+
logger.info("Telemetry event sent successfully:", response.status);
|
|
295
651
|
return true;
|
|
296
652
|
} else {
|
|
297
653
|
const errorText = await response.text();
|
|
298
|
-
|
|
654
|
+
logger.error(
|
|
655
|
+
"Failed to send telemetry event:",
|
|
656
|
+
response.status,
|
|
657
|
+
errorText
|
|
658
|
+
);
|
|
299
659
|
return false;
|
|
300
660
|
}
|
|
301
661
|
} catch (error) {
|
|
302
|
-
|
|
662
|
+
logger.error("Error sending telemetry event:", error);
|
|
303
663
|
return false;
|
|
304
664
|
}
|
|
305
665
|
}
|
|
@@ -311,15 +671,18 @@ var HyveClient = class {
|
|
|
311
671
|
*/
|
|
312
672
|
async callApi(endpoint, options = {}) {
|
|
313
673
|
if (!this.jwtToken) {
|
|
314
|
-
throw new Error(
|
|
674
|
+
throw new Error(
|
|
675
|
+
"No JWT token available. Call authenticateFromUrl first."
|
|
676
|
+
);
|
|
315
677
|
}
|
|
316
678
|
try {
|
|
317
679
|
const url = `${this.apiBaseUrl}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
|
|
680
|
+
logger.debug("Making API call to:", url);
|
|
318
681
|
const response = await fetch(url, {
|
|
319
682
|
...options,
|
|
320
683
|
headers: {
|
|
321
684
|
"Content-Type": "application/json",
|
|
322
|
-
|
|
685
|
+
Authorization: `Bearer ${this.jwtToken}`,
|
|
323
686
|
...options.headers
|
|
324
687
|
}
|
|
325
688
|
});
|
|
@@ -329,7 +692,7 @@ var HyveClient = class {
|
|
|
329
692
|
}
|
|
330
693
|
return await response.json();
|
|
331
694
|
} catch (error) {
|
|
332
|
-
|
|
695
|
+
logger.error("API call failed:", error);
|
|
333
696
|
throw error;
|
|
334
697
|
}
|
|
335
698
|
}
|
|
@@ -362,8 +725,8 @@ var HyveClient = class {
|
|
|
362
725
|
} else if (config.isDev !== void 0) {
|
|
363
726
|
this.apiBaseUrl = config.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
|
|
364
727
|
}
|
|
365
|
-
|
|
366
|
-
|
|
728
|
+
logger.info("Config updated");
|
|
729
|
+
logger.info("API Base URL:", this.apiBaseUrl);
|
|
367
730
|
}
|
|
368
731
|
/**
|
|
369
732
|
* Gets the current user ID
|
|
@@ -386,6 +749,13 @@ var HyveClient = class {
|
|
|
386
749
|
getJwtToken() {
|
|
387
750
|
return this.jwtToken;
|
|
388
751
|
}
|
|
752
|
+
/**
|
|
753
|
+
* Gets the current game ID
|
|
754
|
+
* @returns Current game ID or null if not available
|
|
755
|
+
*/
|
|
756
|
+
getGameId() {
|
|
757
|
+
return this.gameId;
|
|
758
|
+
}
|
|
389
759
|
/**
|
|
390
760
|
* Gets the API base URL
|
|
391
761
|
* @returns API base URL
|
|
@@ -413,7 +783,8 @@ var HyveClient = class {
|
|
|
413
783
|
logout() {
|
|
414
784
|
this.userId = null;
|
|
415
785
|
this.jwtToken = null;
|
|
416
|
-
|
|
786
|
+
this.gameId = null;
|
|
787
|
+
logger.info("User logged out");
|
|
417
788
|
}
|
|
418
789
|
/**
|
|
419
790
|
* Resets the client state
|
|
@@ -421,15 +792,19 @@ var HyveClient = class {
|
|
|
421
792
|
reset() {
|
|
422
793
|
this.logout();
|
|
423
794
|
this.sessionId = generateUUID();
|
|
424
|
-
|
|
795
|
+
logger.info("Client reset with new sessionId:", this.sessionId);
|
|
425
796
|
}
|
|
426
797
|
};
|
|
427
798
|
// Annotate the CommonJS export names for ESM import in node:
|
|
428
799
|
0 && (module.exports = {
|
|
429
800
|
HyveClient,
|
|
801
|
+
Logger,
|
|
802
|
+
NativeBridge,
|
|
803
|
+
NativeMessageType,
|
|
430
804
|
generateUUID,
|
|
431
805
|
handleVerifyMessage,
|
|
432
806
|
isDomainAllowed,
|
|
807
|
+
logger,
|
|
433
808
|
parseUrlParams,
|
|
434
809
|
validateSignature,
|
|
435
810
|
verifyAuthentication,
|