@hyve-sdk/js 1.2.2 → 1.3.1-canary.1

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/dist/index.js CHANGED
@@ -20,10 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AdsService: () => AdsService,
23
24
  HyveClient: () => HyveClient,
25
+ Logger: () => Logger,
26
+ NativeBridge: () => NativeBridge,
27
+ NativeMessageType: () => NativeMessageType,
24
28
  generateUUID: () => generateUUID,
25
29
  handleVerifyMessage: () => handleVerifyMessage,
26
30
  isDomainAllowed: () => isDomainAllowed,
31
+ logger: () => logger,
27
32
  parseUrlParams: () => parseUrlParams,
28
33
  validateSignature: () => validateSignature,
29
34
  verifyAuthentication: () => verifyAuthentication,
@@ -32,8 +37,132 @@ __export(index_exports, {
32
37
  module.exports = __toCommonJS(index_exports);
33
38
 
34
39
  // src/utils/index.ts
35
- var import_ethers = require("ethers");
36
40
  var import_uuid = require("uuid");
41
+
42
+ // src/utils/logger.ts
43
+ var Logger = class _Logger {
44
+ config;
45
+ constructor() {
46
+ this.config = this.initializeConfig();
47
+ }
48
+ /**
49
+ * Initialize logger configuration based on NODE_ENV
50
+ */
51
+ initializeConfig() {
52
+ const isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
53
+ let enabled = false;
54
+ let levels = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
55
+ if (isNode) {
56
+ const nodeEnv = process.env.NODE_ENV;
57
+ enabled = nodeEnv !== "production";
58
+ const logLevelEnv = process.env.HYVE_SDK_LOG_LEVEL;
59
+ if (logLevelEnv) {
60
+ const configuredLevels = logLevelEnv.split(",").map((l) => l.trim());
61
+ levels = new Set(configuredLevels);
62
+ }
63
+ } else if (typeof window !== "undefined") {
64
+ try {
65
+ enabled = process.env.NODE_ENV !== "production";
66
+ } catch (e) {
67
+ enabled = true;
68
+ }
69
+ try {
70
+ const localStorageLogLevel = localStorage.getItem("HYVE_SDK_LOG_LEVEL");
71
+ if (localStorageLogLevel) {
72
+ const configuredLevels = localStorageLogLevel.split(",").map((l) => l.trim());
73
+ levels = new Set(configuredLevels);
74
+ }
75
+ } catch (e) {
76
+ }
77
+ }
78
+ return {
79
+ enabled,
80
+ prefix: "[Hyve SDK]",
81
+ levels
82
+ };
83
+ }
84
+ /**
85
+ * Set which log levels to display
86
+ */
87
+ setLevels(levels) {
88
+ this.config.levels = new Set(levels);
89
+ if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
90
+ try {
91
+ localStorage.setItem("HYVE_SDK_LOG_LEVEL", levels.join(","));
92
+ } catch (e) {
93
+ }
94
+ }
95
+ }
96
+ /**
97
+ * Check if logging is enabled
98
+ */
99
+ isEnabled() {
100
+ return this.config.enabled;
101
+ }
102
+ /**
103
+ * Internal log method
104
+ */
105
+ log(level, ...args) {
106
+ if (!this.config.enabled || !this.config.levels.has(level)) {
107
+ return;
108
+ }
109
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
110
+ const prefix = `${this.config.prefix} [${level.toUpperCase()}] [${timestamp}]`;
111
+ switch (level) {
112
+ case "debug":
113
+ console.debug(prefix, ...args);
114
+ break;
115
+ case "info":
116
+ console.info(prefix, ...args);
117
+ break;
118
+ case "warn":
119
+ console.warn(prefix, ...args);
120
+ break;
121
+ case "error":
122
+ console.error(prefix, ...args);
123
+ break;
124
+ }
125
+ }
126
+ /**
127
+ * Log a debug message
128
+ */
129
+ debug(...args) {
130
+ this.log("debug", ...args);
131
+ }
132
+ /**
133
+ * Log an info message
134
+ */
135
+ info(...args) {
136
+ this.log("info", ...args);
137
+ }
138
+ /**
139
+ * Log a warning message
140
+ */
141
+ warn(...args) {
142
+ this.log("warn", ...args);
143
+ }
144
+ /**
145
+ * Log an error message
146
+ */
147
+ error(...args) {
148
+ this.log("error", ...args);
149
+ }
150
+ /**
151
+ * Create a child logger with a specific prefix
152
+ */
153
+ child(prefix) {
154
+ const childLogger = new _Logger();
155
+ childLogger.config = {
156
+ ...this.config,
157
+ prefix: `${this.config.prefix} [${prefix}]`
158
+ };
159
+ return childLogger;
160
+ }
161
+ };
162
+ var logger = new Logger();
163
+
164
+ // src/utils/auth.ts
165
+ var import_ethers = require("ethers");
37
166
  function parseUrlParams(searchParams) {
38
167
  const params = typeof searchParams === "string" ? new URLSearchParams(searchParams) : searchParams;
39
168
  return {
@@ -51,7 +180,7 @@ function validateSignature(signature, message) {
51
180
  const recoveredAddress = import_ethers.ethers.verifyMessage(message, signature);
52
181
  return !!recoveredAddress;
53
182
  } catch (error) {
54
- console.error("Signature validation error:", error);
183
+ logger.error("Signature validation error:", error);
55
184
  return false;
56
185
  }
57
186
  }
@@ -78,7 +207,7 @@ function handleVerifyMessage(signature, message) {
78
207
  }
79
208
  return userAddress;
80
209
  } catch (error) {
81
- console.error("Error verifying message:", error);
210
+ logger.error("Error verifying message:", error);
82
211
  return false;
83
212
  }
84
213
  }
@@ -86,7 +215,7 @@ function verifyHyveToken(hyveToken, maxAgeSec = 600) {
86
215
  try {
87
216
  const parts = hyveToken.split(".");
88
217
  if (parts.length !== 4) {
89
- console.error(
218
+ logger.error(
90
219
  "Invalid hyve-token format: expected 4 parts, got",
91
220
  parts.length
92
221
  );
@@ -94,30 +223,30 @@ function verifyHyveToken(hyveToken, maxAgeSec = 600) {
94
223
  }
95
224
  const [signature, address, randomBase64, timestampStr] = parts;
96
225
  if (!signature || !address || !randomBase64 || !timestampStr) {
97
- console.error("Missing hyve-token components");
226
+ logger.error("Missing hyve-token components");
98
227
  return false;
99
228
  }
100
229
  const message = `${address}.${randomBase64}.${timestampStr}`;
101
230
  const recoveredAddress = import_ethers.ethers.verifyMessage(message, signature);
102
231
  if (recoveredAddress.toLowerCase() !== address.toLowerCase()) {
103
- console.error("Hyve-token signature verification failed");
232
+ logger.error("Hyve-token signature verification failed");
104
233
  return false;
105
234
  }
106
235
  const timestamp = parseInt(timestampStr, 10);
107
236
  if (!Number.isFinite(timestamp)) {
108
- console.error("Invalid hyve-token timestamp");
237
+ logger.error("Invalid hyve-token timestamp");
109
238
  return false;
110
239
  }
111
240
  const now = Math.floor(Date.now() / 1e3);
112
241
  if (now - timestamp > maxAgeSec) {
113
- console.error(
242
+ logger.error(
114
243
  `Hyve-token expired (age: ${now - timestamp}s, max: ${maxAgeSec}s)`
115
244
  );
116
245
  return false;
117
246
  }
118
247
  return address;
119
248
  } catch (error) {
120
- console.error("Hyve-token verification error:", error);
249
+ logger.error("Hyve-token verification error:", error);
121
250
  return false;
122
251
  }
123
252
  }
@@ -163,11 +292,8 @@ function verifyAuthentication(params, maxAgeSec = 600) {
163
292
  error: "No authentication tokens provided"
164
293
  };
165
294
  }
166
- function generateUUID() {
167
- return (0, import_uuid.v4)();
168
- }
169
295
  function isDomainAllowed(allowedDomains, hostname) {
170
- console.log("Hostname", hostname);
296
+ logger.debug("Checking hostname:", hostname);
171
297
  if (!allowedDomains) return true;
172
298
  const targetHostname = hostname || "";
173
299
  if (!targetHostname) return false;
@@ -185,6 +311,403 @@ function isDomainAllowed(allowedDomains, hostname) {
185
311
  });
186
312
  }
187
313
 
314
+ // src/utils/native-bridge.ts
315
+ var NativeMessageType = /* @__PURE__ */ ((NativeMessageType2) => {
316
+ NativeMessageType2["CHECK_IAP_AVAILABILITY"] = "CHECK_IAP_AVAILABILITY";
317
+ NativeMessageType2["REQUEST_NOTIFICATION_PERMISSION"] = "REQUEST_NOTIFICATION_PERMISSION";
318
+ NativeMessageType2["GET_PRODUCTS"] = "GET_PRODUCTS";
319
+ NativeMessageType2["PURCHASE"] = "PURCHASE";
320
+ NativeMessageType2["IAP_AVAILABILITY_RESULT"] = "IAP_AVAILABILITY_RESULT";
321
+ NativeMessageType2["PUSH_PERMISSION_GRANTED"] = "PUSH_PERMISSION_GRANTED";
322
+ NativeMessageType2["PUSH_PERMISSION_DENIED"] = "PUSH_PERMISSION_DENIED";
323
+ NativeMessageType2["PRODUCTS_RESULT"] = "PRODUCTS_RESULT";
324
+ NativeMessageType2["PURCHASE_COMPLETE"] = "PURCHASE_COMPLETE";
325
+ NativeMessageType2["PURCHASE_ERROR"] = "PURCHASE_ERROR";
326
+ return NativeMessageType2;
327
+ })(NativeMessageType || {});
328
+ var NativeBridge = class {
329
+ static handlers = /* @__PURE__ */ new Map();
330
+ static isInitialized = false;
331
+ /**
332
+ * Checks if the app is running inside a React Native WebView
333
+ */
334
+ static isNativeContext() {
335
+ return typeof window !== "undefined" && "ReactNativeWebView" in window;
336
+ }
337
+ /**
338
+ * Initializes the native bridge message listener
339
+ * Call this once when your app starts
340
+ */
341
+ static initialize() {
342
+ if (this.isInitialized) {
343
+ logger.debug("[NativeBridge] Already initialized");
344
+ return;
345
+ }
346
+ if (typeof window === "undefined") {
347
+ logger.warn("[NativeBridge] Window not available, skipping initialization");
348
+ return;
349
+ }
350
+ const boundHandler = this.handleNativeMessage.bind(this);
351
+ window.addEventListener("message", boundHandler);
352
+ document.addEventListener("message", boundHandler);
353
+ this.isInitialized = true;
354
+ logger.info("[NativeBridge] Initialized and listening for native messages");
355
+ }
356
+ /**
357
+ * Handles incoming messages from React Native
358
+ */
359
+ static handleNativeMessage(event) {
360
+ try {
361
+ let data;
362
+ if (typeof event.data === "string") {
363
+ try {
364
+ data = JSON.parse(event.data);
365
+ logger.debug("[NativeBridge] Parsed message string:", data);
366
+ } catch (parseError) {
367
+ logger.debug("[NativeBridge] Failed to parse message, not JSON:", event.data);
368
+ return;
369
+ }
370
+ } else if (typeof event.data === "object" && event.data !== null) {
371
+ data = event.data;
372
+ logger.debug("[NativeBridge] Received message object:", data);
373
+ } else {
374
+ logger.debug("[NativeBridge] Received invalid message type:", typeof event.data);
375
+ return;
376
+ }
377
+ if (!data || !data.type) {
378
+ logger.debug("[NativeBridge] Received message without type, ignoring");
379
+ return;
380
+ }
381
+ const handler = this.handlers.get(data.type);
382
+ if (handler) {
383
+ logger.info(`[NativeBridge] Handling message: ${data.type}`, data.payload);
384
+ handler(data.payload);
385
+ } else {
386
+ logger.warn(`[NativeBridge] No handler registered for: ${data.type}`);
387
+ }
388
+ } catch (error) {
389
+ logger.error("[NativeBridge] Error handling native message:", error);
390
+ }
391
+ }
392
+ /**
393
+ * Sends a message to React Native
394
+ * @param type Message type
395
+ * @param payload Optional payload data
396
+ */
397
+ static send(type, payload) {
398
+ if (!this.isNativeContext()) {
399
+ logger.debug(
400
+ `[NativeBridge] Not in native context, skipping message: ${type}`
401
+ );
402
+ return;
403
+ }
404
+ try {
405
+ const message = {
406
+ type,
407
+ payload,
408
+ timestamp: Date.now()
409
+ };
410
+ window.ReactNativeWebView.postMessage(JSON.stringify(message));
411
+ logger.debug(`[NativeBridge] Sent message to native: ${type}`, payload);
412
+ } catch (error) {
413
+ logger.error(`[NativeBridge] Error sending message to native:`, error);
414
+ }
415
+ }
416
+ /**
417
+ * Registers a handler for messages from React Native
418
+ * @param type Message type to listen for
419
+ * @param handler Function to call when message is received
420
+ */
421
+ static on(type, handler) {
422
+ this.handlers.set(type, handler);
423
+ logger.debug(`[NativeBridge] Registered handler for: ${type}`);
424
+ }
425
+ /**
426
+ * Unregisters a handler for a specific message type
427
+ * @param type Message type to stop listening for
428
+ */
429
+ static off(type) {
430
+ this.handlers.delete(type);
431
+ logger.debug(`[NativeBridge] Unregistered handler for: ${type}`);
432
+ }
433
+ /**
434
+ * Clears all registered handlers
435
+ */
436
+ static clearHandlers() {
437
+ this.handlers.clear();
438
+ logger.debug("[NativeBridge] Cleared all handlers");
439
+ }
440
+ /**
441
+ * Checks if In-App Purchases are available on the device
442
+ * The native app will respond with a message containing availability status
443
+ *
444
+ * @example
445
+ * // Listen for the response
446
+ * NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
447
+ * console.log("IAP available:", payload.available);
448
+ * });
449
+ *
450
+ * // Send the request
451
+ * NativeBridge.checkIAPAvailability();
452
+ */
453
+ static checkIAPAvailability() {
454
+ this.send("CHECK_IAP_AVAILABILITY" /* CHECK_IAP_AVAILABILITY */);
455
+ }
456
+ /**
457
+ * Requests notification permission from the native app
458
+ * The native app will respond with PUSH_PERMISSION_GRANTED or PUSH_PERMISSION_DENIED
459
+ *
460
+ * @example
461
+ * // Listen for the response
462
+ * NativeBridge.on("PUSH_PERMISSION_GRANTED", () => {
463
+ * console.log("Permission granted");
464
+ * });
465
+ *
466
+ * NativeBridge.on("PUSH_PERMISSION_DENIED", () => {
467
+ * console.log("Permission denied");
468
+ * });
469
+ *
470
+ * // Send the request
471
+ * NativeBridge.requestNotificationPermission();
472
+ */
473
+ static requestNotificationPermission() {
474
+ this.send("REQUEST_NOTIFICATION_PERMISSION" /* REQUEST_NOTIFICATION_PERMISSION */);
475
+ }
476
+ /**
477
+ * Requests available products for a specific game
478
+ * The native app will respond with PRODUCTS_RESULT containing product details
479
+ *
480
+ * @param gameId - The game ID to fetch products for
481
+ *
482
+ * @example
483
+ * // Listen for the response
484
+ * NativeBridge.on("PRODUCTS_RESULT", (payload) => {
485
+ * console.log("Products:", payload.products);
486
+ * });
487
+ *
488
+ * // Send the request
489
+ * NativeBridge.getProducts(123);
490
+ */
491
+ static getProducts(gameId) {
492
+ this.send("GET_PRODUCTS" /* GET_PRODUCTS */, { gameId });
493
+ }
494
+ /**
495
+ * Initiates a purchase for a specific product
496
+ * The native app will respond with PURCHASE_COMPLETE or PURCHASE_ERROR
497
+ *
498
+ * @param productId - The product ID to purchase
499
+ * @param userId - The user ID making the purchase
500
+ *
501
+ * @example
502
+ * // Listen for responses
503
+ * NativeBridge.on("PURCHASE_COMPLETE", (payload) => {
504
+ * console.log("Purchase successful:", payload.productId);
505
+ * });
506
+ *
507
+ * NativeBridge.on("PURCHASE_ERROR", (payload) => {
508
+ * console.error("Purchase failed:", payload.error);
509
+ * });
510
+ *
511
+ * // Initiate purchase
512
+ * NativeBridge.purchase("product_123", "user_456");
513
+ */
514
+ static purchase(productId, userId) {
515
+ this.send("PURCHASE" /* PURCHASE */, { productId, userId });
516
+ }
517
+ };
518
+
519
+ // src/utils/index.ts
520
+ function generateUUID() {
521
+ return (0, import_uuid.v4)();
522
+ }
523
+
524
+ // src/services/ads.ts
525
+ var AdsService = class {
526
+ config = {
527
+ enabled: false,
528
+ sound: "on",
529
+ debug: false,
530
+ onBeforeAd: () => {
531
+ },
532
+ onAfterAd: () => {
533
+ },
534
+ onRewardEarned: () => {
535
+ }
536
+ };
537
+ initialized = false;
538
+ ready = false;
539
+ /**
540
+ * Configure the ads service
541
+ * Must set enabled: true to activate ads
542
+ */
543
+ configure(config) {
544
+ this.config = {
545
+ ...this.config,
546
+ ...config,
547
+ onBeforeAd: config.onBeforeAd || this.config.onBeforeAd,
548
+ onAfterAd: config.onAfterAd || this.config.onAfterAd,
549
+ onRewardEarned: config.onRewardEarned || this.config.onRewardEarned
550
+ };
551
+ if (this.config.debug) {
552
+ console.log("[AdsService] Configuration updated:", {
553
+ enabled: this.config.enabled,
554
+ sound: this.config.sound
555
+ });
556
+ }
557
+ if (this.config.enabled && !this.initialized) {
558
+ this.initialize();
559
+ }
560
+ }
561
+ /**
562
+ * Initialize the ads system
563
+ */
564
+ initialize() {
565
+ if (this.initialized) return;
566
+ if (!this.config.enabled) {
567
+ if (this.config.debug) {
568
+ console.log("[AdsService] Ads disabled, skipping initialization");
569
+ }
570
+ return;
571
+ }
572
+ if (!window.adConfig || !window.adBreak) {
573
+ console.warn("[AdsService] Google Ads SDK not found. Ads will not be available.");
574
+ return;
575
+ }
576
+ if (this.config.debug) {
577
+ console.log("[AdsService] Initializing ads system...");
578
+ }
579
+ const googleConfig = {
580
+ sound: this.config.sound,
581
+ preloadAdBreaks: "on",
582
+ onReady: () => {
583
+ this.ready = true;
584
+ if (this.config.debug) {
585
+ console.log("[AdsService] Ads ready");
586
+ }
587
+ }
588
+ };
589
+ window.adConfig(googleConfig);
590
+ this.initialized = true;
591
+ }
592
+ /**
593
+ * Show an ad
594
+ * Returns immediately if ads are disabled
595
+ */
596
+ async show(type) {
597
+ const requestedAt = Date.now();
598
+ if (!this.config.enabled) {
599
+ if (this.config.debug) {
600
+ console.log("[AdsService] Ads disabled, skipping ad request");
601
+ }
602
+ return {
603
+ success: false,
604
+ type,
605
+ error: new Error("Ads are disabled"),
606
+ requestedAt,
607
+ completedAt: Date.now()
608
+ };
609
+ }
610
+ if (!this.initialized) {
611
+ this.initialize();
612
+ }
613
+ if (!this.ready || !window.adBreak) {
614
+ return {
615
+ success: false,
616
+ type,
617
+ error: new Error("Ads not ready"),
618
+ requestedAt,
619
+ completedAt: Date.now()
620
+ };
621
+ }
622
+ return this.showAdBreak(type);
623
+ }
624
+ /**
625
+ * Show an ad break
626
+ */
627
+ async showAdBreak(type) {
628
+ const requestedAt = Date.now();
629
+ return new Promise((resolve) => {
630
+ const googleType = type === "rewarded" ? "reward" : type === "preroll" ? "start" : "next";
631
+ const adName = `${type}-ad-${Date.now()}`;
632
+ if (this.config.debug) {
633
+ console.log(`[AdsService] Showing ${type} ad`);
634
+ }
635
+ this.config.onBeforeAd(type);
636
+ const adBreakConfig = {
637
+ type: googleType,
638
+ name: adName,
639
+ beforeAd: () => {
640
+ if (this.config.debug) {
641
+ console.log("[AdsService] Ad started");
642
+ }
643
+ },
644
+ afterAd: () => {
645
+ if (this.config.debug) {
646
+ console.log("[AdsService] Ad finished");
647
+ }
648
+ this.config.onAfterAd(type);
649
+ },
650
+ adBreakDone: (info) => {
651
+ const completedAt = Date.now();
652
+ let success = false;
653
+ if (type === "rewarded") {
654
+ success = info?.breakStatus === "viewed";
655
+ } else {
656
+ success = info?.breakStatus !== "error";
657
+ }
658
+ const error = info?.breakStatus === "error" && info?.error ? new Error(info.error) : void 0;
659
+ if (this.config.debug) {
660
+ console.log("[AdsService] Ad break done:", {
661
+ success,
662
+ status: info?.breakStatus
663
+ });
664
+ }
665
+ const result = {
666
+ success,
667
+ type,
668
+ error,
669
+ requestedAt,
670
+ completedAt
671
+ };
672
+ resolve(result);
673
+ }
674
+ };
675
+ if (type === "rewarded") {
676
+ adBreakConfig.beforeReward = (showAdFn) => {
677
+ if (this.config.debug) {
678
+ console.log("[AdsService] beforeReward callback");
679
+ }
680
+ showAdFn();
681
+ };
682
+ adBreakConfig.adViewed = () => {
683
+ if (this.config.debug) {
684
+ console.log("[AdsService] Rewarded ad watched successfully");
685
+ }
686
+ this.config.onRewardEarned();
687
+ };
688
+ adBreakConfig.adDismissed = () => {
689
+ if (this.config.debug) {
690
+ console.log("[AdsService] Rewarded ad dismissed");
691
+ }
692
+ };
693
+ }
694
+ window.adBreak(adBreakConfig);
695
+ });
696
+ }
697
+ /**
698
+ * Check if ads are enabled
699
+ */
700
+ isEnabled() {
701
+ return this.config.enabled;
702
+ }
703
+ /**
704
+ * Check if ads are ready to show
705
+ */
706
+ isReady() {
707
+ return this.config.enabled && this.ready;
708
+ }
709
+ };
710
+
188
711
  // src/core/client.ts
189
712
  var HyveClient = class {
190
713
  telemetryConfig;
@@ -193,9 +716,10 @@ var HyveClient = class {
193
716
  userId = null;
194
717
  jwtToken = null;
195
718
  gameId = null;
719
+ adsService;
196
720
  /**
197
721
  * Creates a new HyveClient instance
198
- * @param config Optional telemetry configuration
722
+ * @param config Optional configuration including telemetry and ads
199
723
  */
200
724
  constructor(config) {
201
725
  this.telemetryConfig = {
@@ -209,9 +733,14 @@ var HyveClient = class {
209
733
  this.apiBaseUrl = this.telemetryConfig.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
210
734
  }
211
735
  this.sessionId = generateUUID();
212
- console.log("[Hyve SDK] Client initialized with sessionId:", this.sessionId);
213
- console.log("[Hyve SDK] API Base URL:", this.apiBaseUrl);
214
- console.log("[Hyve SDK] Environment:", this.telemetryConfig.isDev ? "dev" : "prod");
736
+ this.adsService = new AdsService();
737
+ if (config?.ads) {
738
+ this.adsService.configure(config.ads);
739
+ }
740
+ logger.info("Client initialized with sessionId:", this.sessionId);
741
+ logger.info("API Base URL:", this.apiBaseUrl);
742
+ logger.info("Environment:", this.telemetryConfig.isDev ? "dev" : "prod");
743
+ logger.info("Ads enabled:", this.adsService.isEnabled());
215
744
  }
216
745
  /**
217
746
  * Authenticates a user from URL parameters
@@ -223,14 +752,22 @@ var HyveClient = class {
223
752
  const params = urlParams ? parseUrlParams(urlParams) : parseUrlParams(window.location.search);
224
753
  if (params.hyveAccess) {
225
754
  this.jwtToken = params.hyveAccess;
226
- console.log("[Hyve SDK] JWT token extracted from hyve-access parameter");
755
+ logger.info("JWT token extracted from hyve-access parameter");
227
756
  }
228
757
  if (params.gameId) {
229
758
  this.gameId = params.gameId;
230
- console.log("[Hyve SDK] Game ID extracted from game-id parameter:", this.gameId);
759
+ logger.info("Game ID extracted from game-id parameter:", this.gameId);
231
760
  }
232
761
  if (this.jwtToken) {
233
- console.log("[Hyve SDK] Authentication successful via JWT");
762
+ logger.info("Authentication successful via JWT");
763
+ return true;
764
+ }
765
+ if (params.gameId) {
766
+ this.gameId = params.gameId;
767
+ logger.info("Game ID extracted from game-id parameter:", this.gameId);
768
+ }
769
+ if (this.jwtToken) {
770
+ logger.info("Authentication successful via JWT");
234
771
  return true;
235
772
  }
236
773
  const authResult = verifyAuthentication({
@@ -240,16 +777,16 @@ var HyveClient = class {
240
777
  });
241
778
  if (authResult.isValid && authResult.address) {
242
779
  this.userId = authResult.address;
243
- console.log("[Hyve SDK] Authentication successful:", authResult.address);
244
- console.log("[Hyve SDK] Authentication method:", authResult.method);
780
+ logger.info("Authentication successful:", authResult.address);
781
+ logger.info("Authentication method:", authResult.method);
245
782
  return true;
246
783
  } else {
247
- console.error("[Hyve SDK] Authentication failed:", authResult.error);
784
+ logger.error("Authentication failed:", authResult.error);
248
785
  this.userId = null;
249
786
  return false;
250
787
  }
251
788
  } catch (error) {
252
- console.error("[Hyve SDK] Authentication error:", error);
789
+ logger.error("Authentication error:", error);
253
790
  this.userId = null;
254
791
  return false;
255
792
  }
@@ -269,11 +806,11 @@ var HyveClient = class {
269
806
  */
270
807
  async sendTelemetry(eventLocation, eventCategory, eventAction, eventSubCategory, eventSubAction, eventDetails, customData, platformId) {
271
808
  if (!this.jwtToken) {
272
- console.error("[Hyve Telemetry] JWT token required. Call authenticateFromUrl first.");
809
+ logger.error("JWT token required. Call authenticateFromUrl first.");
273
810
  return false;
274
811
  }
275
812
  if (!this.gameId) {
276
- console.error("[Hyve Telemetry] Game ID required. Ensure game-id URL parameter is set.");
813
+ logger.error("Game ID required. Ensure game-id URL parameter is set.");
277
814
  return false;
278
815
  }
279
816
  try {
@@ -293,26 +830,30 @@ var HyveClient = class {
293
830
  event_details: toJsonString(eventDetails),
294
831
  custom_data: toJsonString(customData)
295
832
  };
296
- console.log("[Hyve Telemetry] Sending user-level event:", telemetryEvent);
833
+ logger.debug("Sending telemetry event:", telemetryEvent);
297
834
  const telemetryUrl = `${this.apiBaseUrl}/api/v1/telemetry/send`;
298
835
  const response = await fetch(telemetryUrl, {
299
836
  method: "POST",
300
837
  headers: {
301
838
  "Content-Type": "application/json",
302
- "Authorization": `Bearer ${this.jwtToken}`
839
+ Authorization: `Bearer ${this.jwtToken}`
303
840
  },
304
841
  body: JSON.stringify(telemetryEvent)
305
842
  });
306
843
  if (response.ok) {
307
- console.log("[Hyve Telemetry] Event sent successfully:", response.status);
844
+ logger.info("Telemetry event sent successfully:", response.status);
308
845
  return true;
309
846
  } else {
310
847
  const errorText = await response.text();
311
- console.error("[Hyve Telemetry] Failed to send event:", response.status, errorText);
848
+ logger.error(
849
+ "Failed to send telemetry event:",
850
+ response.status,
851
+ errorText
852
+ );
312
853
  return false;
313
854
  }
314
855
  } catch (error) {
315
- console.error("[Hyve Telemetry] Error sending event:", error);
856
+ logger.error("Error sending telemetry event:", error);
316
857
  return false;
317
858
  }
318
859
  }
@@ -324,15 +865,18 @@ var HyveClient = class {
324
865
  */
325
866
  async callApi(endpoint, options = {}) {
326
867
  if (!this.jwtToken) {
327
- throw new Error("[Hyve SDK] No JWT token available. Call authenticateFromUrl first.");
868
+ throw new Error(
869
+ "No JWT token available. Call authenticateFromUrl first."
870
+ );
328
871
  }
329
872
  try {
330
873
  const url = `${this.apiBaseUrl}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
874
+ logger.debug("Making API call to:", url);
331
875
  const response = await fetch(url, {
332
876
  ...options,
333
877
  headers: {
334
878
  "Content-Type": "application/json",
335
- "Authorization": `Bearer ${this.jwtToken}`,
879
+ Authorization: `Bearer ${this.jwtToken}`,
336
880
  ...options.headers
337
881
  }
338
882
  });
@@ -342,7 +886,7 @@ var HyveClient = class {
342
886
  }
343
887
  return await response.json();
344
888
  } catch (error) {
345
- console.error("[Hyve SDK] API call failed:", error);
889
+ logger.error("API call failed:", error);
346
890
  throw error;
347
891
  }
348
892
  }
@@ -375,8 +919,8 @@ var HyveClient = class {
375
919
  } else if (config.isDev !== void 0) {
376
920
  this.apiBaseUrl = config.isDev ? "https://product-api.dev.hyve.gg" : "https://product-api.prod.hyve.gg";
377
921
  }
378
- console.log("[Hyve SDK] Config updated");
379
- console.log("[Hyve SDK] API Base URL:", this.apiBaseUrl);
922
+ logger.info("Config updated");
923
+ logger.info("API Base URL:", this.apiBaseUrl);
380
924
  }
381
925
  /**
382
926
  * Gets the current user ID
@@ -434,7 +978,7 @@ var HyveClient = class {
434
978
  this.userId = null;
435
979
  this.jwtToken = null;
436
980
  this.gameId = null;
437
- console.log("[Hyve SDK] User logged out");
981
+ logger.info("User logged out");
438
982
  }
439
983
  /**
440
984
  * Resets the client state
@@ -442,15 +986,50 @@ var HyveClient = class {
442
986
  reset() {
443
987
  this.logout();
444
988
  this.sessionId = generateUUID();
445
- console.log("[Hyve SDK] Client reset with new sessionId:", this.sessionId);
989
+ logger.info("Client reset with new sessionId:", this.sessionId);
990
+ }
991
+ /**
992
+ * Configure ads service
993
+ * @param config Ads configuration
994
+ */
995
+ configureAds(config) {
996
+ this.adsService.configure(config);
997
+ logger.info("Ads configuration updated");
998
+ }
999
+ /**
1000
+ * Show an ad
1001
+ * @param type Type of ad to show ('rewarded', 'interstitial', or 'preroll')
1002
+ * @returns Promise resolving to ad result
1003
+ */
1004
+ async showAd(type) {
1005
+ return this.adsService.show(type);
1006
+ }
1007
+ /**
1008
+ * Check if ads are enabled
1009
+ * @returns Boolean indicating if ads are enabled
1010
+ */
1011
+ areAdsEnabled() {
1012
+ return this.adsService.isEnabled();
1013
+ }
1014
+ /**
1015
+ * Check if ads are ready to show
1016
+ * @returns Boolean indicating if ads are ready
1017
+ */
1018
+ areAdsReady() {
1019
+ return this.adsService.isReady();
446
1020
  }
447
1021
  };
448
1022
  // Annotate the CommonJS export names for ESM import in node:
449
1023
  0 && (module.exports = {
1024
+ AdsService,
450
1025
  HyveClient,
1026
+ Logger,
1027
+ NativeBridge,
1028
+ NativeMessageType,
451
1029
  generateUUID,
452
1030
  handleVerifyMessage,
453
1031
  isDomainAllowed,
1032
+ logger,
454
1033
  parseUrlParams,
455
1034
  validateSignature,
456
1035
  verifyAuthentication,