@hyve-sdk/js 2.11.2 → 2.13.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -201,6 +201,10 @@ if (result.success) {
201
201
 
202
202
  await hyve.showAd("interstitial"); // between levels
203
203
  await hyve.showAd("preroll"); // game start
204
+
205
+ // Optional placement key, used by native AdMob to resolve a per-placement
206
+ // ad unit. Ignored on the web path.
207
+ await hyve.showAd("rewarded", "level_end");
204
208
  ```
205
209
 
206
210
  | Ad Type | Use Case |
@@ -211,6 +215,16 @@ await hyve.showAd("preroll"); // game start
211
215
 
212
216
  The SDK automatically routes ad calls through the appropriate platform SDK (CrazyGames, Playgama, or the default Google H5 Ads SDK) based on the current domain.
213
217
 
218
+ ### Native AdMob
219
+
220
+ Inside the Hyve mobile shell, set `useNativeAds: true` to serve ads via native
221
+ AdMob instead of Google H5. Routing is decided per call: when
222
+ `window.ReactNativeWebView` is present and `useNativeAds` is enabled, ad
223
+ requests go to native AdMob (`preroll` maps to a native interstitial);
224
+ otherwise the H5 web path is used. The game-facing API is unchanged, and any
225
+ `not_configured` / `config_fetch_failed` response from native falls back to H5
226
+ for that call. See [docs/ads.md](./docs/ads.md) for details.
227
+
214
228
  ## Platform Integrations
215
229
 
216
230
  ### CrazyGames
@@ -406,8 +420,8 @@ new HyveClient(config?: {
406
420
 
407
421
  | Method | Returns | Description |
408
422
  |--------|---------|-------------|
409
- | `configureAds(config)` | `void` | Configure the ads service |
410
- | `showAd(type)` | `Promise<AdResult>` | Show an ad |
423
+ | `configureAds(config)` | `void` | Configure the ads service (incl. `useNativeAds`) |
424
+ | `showAd(type, placement?)` | `Promise<AdResult>` | Show an ad; `placement` forwarded to native AdMob |
411
425
  | `areAdsReady()` | `boolean` | Check if ads have initialized |
412
426
  | `gameplayStart()` | `Promise<void>` | Notify gameplay started (CrazyGames) |
413
427
  | `gameplayStop()` | `Promise<void>` | Notify gameplay stopped (CrazyGames) |
package/dist/index.d.mts CHANGED
@@ -182,7 +182,17 @@ interface GetGameDataLeaderboardParams {
182
182
  *
183
183
  * @packageDocumentation
184
184
  */
185
+ /**
186
+ * Ad types the SDK's `show()` accepts. Limited to formats with a working
187
+ * native path; `'preroll'` maps to a native interstitial (Decision 2).
188
+ */
185
189
  type AdType = 'rewarded' | 'interstitial' | 'preroll';
190
+ /**
191
+ * AdMob format strings understood by the storage layer and native resolver.
192
+ * Broader than {@link AdType} — the extra formats are storage-only until a
193
+ * native show path is wired up for them (see docs/admob-migration.md).
194
+ */
195
+ type AdMobFormat = 'rewarded' | 'interstitial' | 'rewarded_interstitial' | 'banner' | 'native_advanced' | 'app_open';
186
196
  interface AdResult {
187
197
  success: boolean;
188
198
  type: AdType;
@@ -193,6 +203,19 @@ interface AdResult {
193
203
  interface AdConfig {
194
204
  sound?: 'on' | 'off';
195
205
  debug?: boolean;
206
+ /**
207
+ * Route ad requests through the native AdMob bridge when running inside the
208
+ * Hyve mobile shell (`window.ReactNativeWebView` present).
209
+ *
210
+ * Phase 0 rollout flag: defaults to `false`, where ads always use the
211
+ * existing H5 / Playgama web path. The native path is wired up behind this
212
+ * flag in a later phase — until then this is an inert toggle that exists so
213
+ * later releases can flip behavior without an API change. See
214
+ * `docs/admob-migration.md`.
215
+ *
216
+ * @default false
217
+ */
218
+ useNativeAds?: boolean;
196
219
  onBeforeAd?: (type: AdType) => void;
197
220
  onAfterAd?: (type: AdType) => void;
198
221
  onRewardEarned?: () => void;
@@ -225,6 +248,12 @@ declare class AdsService {
225
248
  private config;
226
249
  private initPromise;
227
250
  private ready;
251
+ private gameId;
252
+ /**
253
+ * Set the game ID used in native ad requests. Called by the client once the
254
+ * game ID is known (from URL params or JWT). No-op for the web ad path.
255
+ */
256
+ setGameId(gameId: string | null): void;
228
257
  /**
229
258
  * Optionally configure the ads service.
230
259
  * Not required — ads work without calling this.
@@ -237,11 +266,43 @@ declare class AdsService {
237
266
  private initialize;
238
267
  /**
239
268
  * Show an ad. Auto-initializes on the first call.
240
- * Returns immediately with success: false if ads are disabled or unavailable.
269
+ *
270
+ * Inside the Hyve mobile shell (`window.ReactNativeWebView` present) with
271
+ * `useNativeAds` enabled, the request is routed to native AdMob via the
272
+ * bridge. Otherwise — or when native reports the slot is `not_configured` /
273
+ * `config_fetch_failed` — it falls back to the Google H5 web path.
274
+ *
275
+ * Returns `success: false` if ads are disabled or unavailable.
276
+ *
277
+ * @param type - Ad type to show
278
+ * @param placement - Optional placement key, forwarded to native; ignored on
279
+ * the web path (H5 has no placement concept).
280
+ */
281
+ show(type: AdType, placement?: string): Promise<AdResult>;
282
+ /**
283
+ * True when running inside the Hyve mobile shell with native ads enabled.
284
+ */
285
+ private isNativeAdsContext;
286
+ /**
287
+ * Route an ad request to native AdMob via the bridge (Decision 7 — native
288
+ * owns unit-ID resolution; the SDK only sends `{ gameId, format, placement }`).
289
+ *
290
+ * Returns the resolved `AdResult`, or `null` to indicate the caller should
291
+ * fall back to the web ad path for this single call.
241
292
  */
242
- show(type: AdType): Promise<AdResult>;
293
+ private showNative;
294
+ /**
295
+ * Show an ad via the Google H5 web path. Auto-initializes on first call.
296
+ *
297
+ * @param fireBeforeAd - When false, `onBeforeAd` is not fired (the native
298
+ * fallback path already fired it before delegating here).
299
+ */
300
+ private showWeb;
243
301
  /**
244
302
  * Show an ad break via the Google H5 API.
303
+ *
304
+ * @param fireBeforeAd - When false, skips `onBeforeAd` (already fired by the
305
+ * native fallback path that delegated here).
245
306
  */
246
307
  private showAdBreak;
247
308
  /**
@@ -507,6 +568,59 @@ declare class HyveClient {
507
568
  * @returns Promise resolving to boolean indicating success
508
569
  */
509
570
  sendTelemetry(eventLocation: string, eventCategory: string, eventAction: string, eventSubCategory?: string | null, eventSubAction?: string | null, eventDetails?: Record<string, any> | string | null, platformId?: string | null): Promise<boolean>;
571
+ /**
572
+ * Required lifecycle telemetry — Session start.
573
+ * See https://docs.hyve.gg/docs/telemetry#required-lifecycle-events
574
+ */
575
+ sessionStart(): Promise<boolean>;
576
+ /**
577
+ * Required lifecycle telemetry — Session end.
578
+ */
579
+ sessionEnd(): Promise<boolean>;
580
+ /**
581
+ * Required lifecycle telemetry — Lobby loading start.
582
+ */
583
+ lobbyLoadingStart(): Promise<boolean>;
584
+ /**
585
+ * Required lifecycle telemetry — Lobby loading end.
586
+ */
587
+ lobbyLoadingEnd(): Promise<boolean>;
588
+ /**
589
+ * Required lifecycle telemetry — Game loading start.
590
+ */
591
+ gameLoadingStart(): Promise<boolean>;
592
+ /**
593
+ * Required lifecycle telemetry — Game loading end.
594
+ */
595
+ gameLoadingEnd(): Promise<boolean>;
596
+ /**
597
+ * Required lifecycle telemetry — Lobby initialization.
598
+ */
599
+ lobbyInit(): Promise<boolean>;
600
+ /**
601
+ * Required lifecycle telemetry — Gameplay end.
602
+ * Also notifies CrazyGames that gameplay has stopped.
603
+ */
604
+ gameplayEnd(): Promise<boolean>;
605
+ /**
606
+ * Required lifecycle telemetry — Store opened.
607
+ */
608
+ storeOpen(): Promise<boolean>;
609
+ /**
610
+ * Required lifecycle telemetry — Purchase complete.
611
+ * @param itemName Name of the purchased item (required by the platform)
612
+ */
613
+ purchaseComplete(itemName: string): Promise<boolean>;
614
+ /**
615
+ * Required lifecycle telemetry — Purchase failed.
616
+ * @param itemName Name of the item the purchase was for
617
+ */
618
+ purchaseFail(itemName: string): Promise<boolean>;
619
+ /**
620
+ * Required lifecycle telemetry — Purchase cancelled.
621
+ * @param itemName Name of the item the purchase was for
622
+ */
623
+ purchaseCancel(itemName: string): Promise<boolean>;
510
624
  /**
511
625
  * Makes an authenticated API call using the JWT token
512
626
  * @param endpoint API endpoint path (will be appended to base URL)
@@ -652,14 +766,16 @@ declare class HyveClient {
652
766
  /**
653
767
  * Show an ad
654
768
  * @param type Type of ad to show ('rewarded', 'interstitial', or 'preroll')
769
+ * @param placement Optional placement key, forwarded to the native AdMob path
770
+ * to resolve a per-placement unit ID. Ignored on the web (H5/Playgama) path.
655
771
  * @returns Promise resolving to ad result
656
772
  */
657
- showAd(type: AdType): Promise<AdResult>;
773
+ showAd(type: AdType, placement?: string): Promise<AdResult>;
658
774
  /**
659
- * Notifies CrazyGames that gameplay has started.
660
- * No-op on other platforms.
775
+ * Required lifecycle telemetry Gameplay start.
776
+ * Also notifies CrazyGames that gameplay has started.
661
777
  */
662
- gameplayStart(): Promise<void>;
778
+ gameplayStart(): Promise<boolean>;
663
779
  /**
664
780
  * Notifies CrazyGames that gameplay has stopped.
665
781
  * No-op on other platforms.
@@ -995,6 +1111,10 @@ declare enum NativeMessageType {
995
1111
  GET_PRODUCTS = "GET_PRODUCTS",
996
1112
  /** Initiate a purchase */
997
1113
  PURCHASE = "PURCHASE",
1114
+ /** Request a native AdMob rewarded ad */
1115
+ SHOW_REWARDED_AD = "SHOW_REWARDED_AD",
1116
+ /** Request a native AdMob interstitial ad */
1117
+ SHOW_INTERSTITIAL_AD = "SHOW_INTERSTITIAL_AD",
998
1118
  /** Response to CHECK_IAP_AVAILABILITY request */
999
1119
  IAP_AVAILABILITY_RESULT = "IAP_AVAILABILITY_RESULT",
1000
1120
  /** Push notification permission was granted */
@@ -1006,7 +1126,37 @@ declare enum NativeMessageType {
1006
1126
  /** Purchase completed successfully */
1007
1127
  PURCHASE_COMPLETE = "PURCHASE_COMPLETE",
1008
1128
  /** Purchase failed or was cancelled */
1009
- PURCHASE_ERROR = "PURCHASE_ERROR"
1129
+ PURCHASE_ERROR = "PURCHASE_ERROR",
1130
+ /** Result of a SHOW_REWARDED_AD / SHOW_INTERSTITIAL_AD request */
1131
+ AD_RESULT = "AD_RESULT"
1132
+ }
1133
+ /**
1134
+ * Payload sent to native for a SHOW_*_AD request.
1135
+ * Native is the sole authority for resolving (format, placement) → ad unit ID,
1136
+ * so the SDK never sends or sees unit IDs (see docs/admob-migration.md).
1137
+ */
1138
+ interface AdRequestPayload {
1139
+ /** Game the ad belongs to — native keys its unit-ID lookup on this. */
1140
+ gameId: string;
1141
+ /** AdMob format string, e.g. "rewarded" | "interstitial". */
1142
+ format: string;
1143
+ /** Optional placement key; native falls back to "default" when omitted. */
1144
+ placement?: string;
1145
+ }
1146
+ /**
1147
+ * Raw `AD_RESULT` payload as received from native.
1148
+ *
1149
+ * `error` is a string code (e.g. "not_configured", "config_fetch_failed"),
1150
+ * not an `Error` object — the SDK inspects it to decide whether to fall back
1151
+ * to the web ad path before converting it for the public `AdResult`.
1152
+ */
1153
+ interface NativeAdResult {
1154
+ /** Echoes the resolved ad type ("rewarded" | "interstitial"). */
1155
+ type: string;
1156
+ /** Whether the ad was shown successfully. */
1157
+ success: boolean;
1158
+ /** Error code when the ad did not show. */
1159
+ error?: string;
1010
1160
  }
1011
1161
  /**
1012
1162
  * Message handler function type for receiving messages from native
@@ -1032,6 +1182,12 @@ type NativeMessageHandler<T = any> = (payload: T) => void | Promise<void>;
1032
1182
  declare class NativeBridge {
1033
1183
  private static handlers;
1034
1184
  private static isInitialized;
1185
+ /**
1186
+ * Pending `sendAdRequest()` promises, keyed by the ad type native echoes
1187
+ * back in `AD_RESULT.type` ("rewarded" | "interstitial"). One in-flight
1188
+ * request per type — ads are shown sequentially.
1189
+ */
1190
+ private static adResultResolvers;
1035
1191
  /**
1036
1192
  * Checks if the app is running inside a React Native WebView
1037
1193
  */
@@ -1135,6 +1291,38 @@ declare class NativeBridge {
1135
1291
  * NativeBridge.purchase("product_123", "user_456");
1136
1292
  */
1137
1293
  static purchase(productId: string, userId: string): void;
1294
+ /**
1295
+ * Sends a native ad request and resolves with the `AD_RESULT` native sends
1296
+ * back. Never rejects — a missing native context, timeout, or superseded
1297
+ * request resolves to `{ success: false }` with an error code so callers can
1298
+ * decide whether to fall back to the web ad path.
1299
+ *
1300
+ * @param messageType - `SHOW_REWARDED_AD` or `SHOW_INTERSTITIAL_AD`
1301
+ * @param payload - `{ gameId, format, placement? }`
1302
+ * @param timeoutMs - How long to wait for `AD_RESULT` before giving up
1303
+ *
1304
+ * @example
1305
+ * const result = await NativeBridge.sendAdRequest(
1306
+ * NativeMessageType.SHOW_REWARDED_AD,
1307
+ * { gameId: "123", format: "rewarded", placement: "level_end" },
1308
+ * );
1309
+ * if (result.success) grantReward();
1310
+ */
1311
+ static sendAdRequest(messageType: NativeMessageType.SHOW_REWARDED_AD | NativeMessageType.SHOW_INTERSTITIAL_AD, payload: AdRequestPayload, timeoutMs?: number): Promise<NativeAdResult>;
1312
+ /**
1313
+ * Registers a handler invoked for every `AD_RESULT` message from native,
1314
+ * in addition to resolving any pending {@link sendAdRequest} promise.
1315
+ * Useful for diagnostics or availability tracking.
1316
+ *
1317
+ * @param handler - Called with the raw `AD_RESULT` payload
1318
+ */
1319
+ static onAdResult(handler: NativeMessageHandler<NativeAdResult>): void;
1320
+ /**
1321
+ * Resolves the pending {@link sendAdRequest} promise that matches an
1322
+ * incoming `AD_RESULT` payload. No-op when nothing is waiting (e.g. a late
1323
+ * result after a timeout).
1324
+ */
1325
+ private static resolveAdResult;
1138
1326
  }
1139
1327
 
1140
1328
  /**
@@ -1143,4 +1331,4 @@ declare class NativeBridge {
1143
1331
  */
1144
1332
  declare function generateUUID(): string;
1145
1333
 
1146
- export { type AdConfig, type AdResult, type AdType, AdsService, type BatchSaveGameDataResponse, type BatchSaveResultItem, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, CloudStorageAdapter, CrazyGamesService, type DeleteGameDataResponse, type GameDataBatchItem, type GameDataItem, type GameDataLeaderboardEntry, type GameDataLeaderboardResponse, type GameDataLeaderboardUserPosition, type GameDataOperation, type GameDataValue, type GetGameDataBatchResponse, type GetGameDataLeaderboardParams, type GetGameDataResponse, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, LocalStorageAdapter, Logger, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, PlaygamaService, type PurchaseResult, type SaveGameDataResponse, type StorageAdapter, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, isDomainAllowed, logger, parseUrlParams };
1334
+ export { type AdConfig, type AdMobFormat, type AdRequestPayload, type AdResult, type AdType, AdsService, type BatchSaveGameDataResponse, type BatchSaveResultItem, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, CloudStorageAdapter, CrazyGamesService, type DeleteGameDataResponse, type GameDataBatchItem, type GameDataItem, type GameDataLeaderboardEntry, type GameDataLeaderboardResponse, type GameDataLeaderboardUserPosition, type GameDataOperation, type GameDataValue, type GetGameDataBatchResponse, type GetGameDataLeaderboardParams, type GetGameDataResponse, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, LocalStorageAdapter, Logger, type NativeAdResult, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, PlaygamaService, type PurchaseResult, type SaveGameDataResponse, type StorageAdapter, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, isDomainAllowed, logger, parseUrlParams };
package/dist/index.d.ts CHANGED
@@ -182,7 +182,17 @@ interface GetGameDataLeaderboardParams {
182
182
  *
183
183
  * @packageDocumentation
184
184
  */
185
+ /**
186
+ * Ad types the SDK's `show()` accepts. Limited to formats with a working
187
+ * native path; `'preroll'` maps to a native interstitial (Decision 2).
188
+ */
185
189
  type AdType = 'rewarded' | 'interstitial' | 'preroll';
190
+ /**
191
+ * AdMob format strings understood by the storage layer and native resolver.
192
+ * Broader than {@link AdType} — the extra formats are storage-only until a
193
+ * native show path is wired up for them (see docs/admob-migration.md).
194
+ */
195
+ type AdMobFormat = 'rewarded' | 'interstitial' | 'rewarded_interstitial' | 'banner' | 'native_advanced' | 'app_open';
186
196
  interface AdResult {
187
197
  success: boolean;
188
198
  type: AdType;
@@ -193,6 +203,19 @@ interface AdResult {
193
203
  interface AdConfig {
194
204
  sound?: 'on' | 'off';
195
205
  debug?: boolean;
206
+ /**
207
+ * Route ad requests through the native AdMob bridge when running inside the
208
+ * Hyve mobile shell (`window.ReactNativeWebView` present).
209
+ *
210
+ * Phase 0 rollout flag: defaults to `false`, where ads always use the
211
+ * existing H5 / Playgama web path. The native path is wired up behind this
212
+ * flag in a later phase — until then this is an inert toggle that exists so
213
+ * later releases can flip behavior without an API change. See
214
+ * `docs/admob-migration.md`.
215
+ *
216
+ * @default false
217
+ */
218
+ useNativeAds?: boolean;
196
219
  onBeforeAd?: (type: AdType) => void;
197
220
  onAfterAd?: (type: AdType) => void;
198
221
  onRewardEarned?: () => void;
@@ -225,6 +248,12 @@ declare class AdsService {
225
248
  private config;
226
249
  private initPromise;
227
250
  private ready;
251
+ private gameId;
252
+ /**
253
+ * Set the game ID used in native ad requests. Called by the client once the
254
+ * game ID is known (from URL params or JWT). No-op for the web ad path.
255
+ */
256
+ setGameId(gameId: string | null): void;
228
257
  /**
229
258
  * Optionally configure the ads service.
230
259
  * Not required — ads work without calling this.
@@ -237,11 +266,43 @@ declare class AdsService {
237
266
  private initialize;
238
267
  /**
239
268
  * Show an ad. Auto-initializes on the first call.
240
- * Returns immediately with success: false if ads are disabled or unavailable.
269
+ *
270
+ * Inside the Hyve mobile shell (`window.ReactNativeWebView` present) with
271
+ * `useNativeAds` enabled, the request is routed to native AdMob via the
272
+ * bridge. Otherwise — or when native reports the slot is `not_configured` /
273
+ * `config_fetch_failed` — it falls back to the Google H5 web path.
274
+ *
275
+ * Returns `success: false` if ads are disabled or unavailable.
276
+ *
277
+ * @param type - Ad type to show
278
+ * @param placement - Optional placement key, forwarded to native; ignored on
279
+ * the web path (H5 has no placement concept).
280
+ */
281
+ show(type: AdType, placement?: string): Promise<AdResult>;
282
+ /**
283
+ * True when running inside the Hyve mobile shell with native ads enabled.
284
+ */
285
+ private isNativeAdsContext;
286
+ /**
287
+ * Route an ad request to native AdMob via the bridge (Decision 7 — native
288
+ * owns unit-ID resolution; the SDK only sends `{ gameId, format, placement }`).
289
+ *
290
+ * Returns the resolved `AdResult`, or `null` to indicate the caller should
291
+ * fall back to the web ad path for this single call.
241
292
  */
242
- show(type: AdType): Promise<AdResult>;
293
+ private showNative;
294
+ /**
295
+ * Show an ad via the Google H5 web path. Auto-initializes on first call.
296
+ *
297
+ * @param fireBeforeAd - When false, `onBeforeAd` is not fired (the native
298
+ * fallback path already fired it before delegating here).
299
+ */
300
+ private showWeb;
243
301
  /**
244
302
  * Show an ad break via the Google H5 API.
303
+ *
304
+ * @param fireBeforeAd - When false, skips `onBeforeAd` (already fired by the
305
+ * native fallback path that delegated here).
245
306
  */
246
307
  private showAdBreak;
247
308
  /**
@@ -507,6 +568,59 @@ declare class HyveClient {
507
568
  * @returns Promise resolving to boolean indicating success
508
569
  */
509
570
  sendTelemetry(eventLocation: string, eventCategory: string, eventAction: string, eventSubCategory?: string | null, eventSubAction?: string | null, eventDetails?: Record<string, any> | string | null, platformId?: string | null): Promise<boolean>;
571
+ /**
572
+ * Required lifecycle telemetry — Session start.
573
+ * See https://docs.hyve.gg/docs/telemetry#required-lifecycle-events
574
+ */
575
+ sessionStart(): Promise<boolean>;
576
+ /**
577
+ * Required lifecycle telemetry — Session end.
578
+ */
579
+ sessionEnd(): Promise<boolean>;
580
+ /**
581
+ * Required lifecycle telemetry — Lobby loading start.
582
+ */
583
+ lobbyLoadingStart(): Promise<boolean>;
584
+ /**
585
+ * Required lifecycle telemetry — Lobby loading end.
586
+ */
587
+ lobbyLoadingEnd(): Promise<boolean>;
588
+ /**
589
+ * Required lifecycle telemetry — Game loading start.
590
+ */
591
+ gameLoadingStart(): Promise<boolean>;
592
+ /**
593
+ * Required lifecycle telemetry — Game loading end.
594
+ */
595
+ gameLoadingEnd(): Promise<boolean>;
596
+ /**
597
+ * Required lifecycle telemetry — Lobby initialization.
598
+ */
599
+ lobbyInit(): Promise<boolean>;
600
+ /**
601
+ * Required lifecycle telemetry — Gameplay end.
602
+ * Also notifies CrazyGames that gameplay has stopped.
603
+ */
604
+ gameplayEnd(): Promise<boolean>;
605
+ /**
606
+ * Required lifecycle telemetry — Store opened.
607
+ */
608
+ storeOpen(): Promise<boolean>;
609
+ /**
610
+ * Required lifecycle telemetry — Purchase complete.
611
+ * @param itemName Name of the purchased item (required by the platform)
612
+ */
613
+ purchaseComplete(itemName: string): Promise<boolean>;
614
+ /**
615
+ * Required lifecycle telemetry — Purchase failed.
616
+ * @param itemName Name of the item the purchase was for
617
+ */
618
+ purchaseFail(itemName: string): Promise<boolean>;
619
+ /**
620
+ * Required lifecycle telemetry — Purchase cancelled.
621
+ * @param itemName Name of the item the purchase was for
622
+ */
623
+ purchaseCancel(itemName: string): Promise<boolean>;
510
624
  /**
511
625
  * Makes an authenticated API call using the JWT token
512
626
  * @param endpoint API endpoint path (will be appended to base URL)
@@ -652,14 +766,16 @@ declare class HyveClient {
652
766
  /**
653
767
  * Show an ad
654
768
  * @param type Type of ad to show ('rewarded', 'interstitial', or 'preroll')
769
+ * @param placement Optional placement key, forwarded to the native AdMob path
770
+ * to resolve a per-placement unit ID. Ignored on the web (H5/Playgama) path.
655
771
  * @returns Promise resolving to ad result
656
772
  */
657
- showAd(type: AdType): Promise<AdResult>;
773
+ showAd(type: AdType, placement?: string): Promise<AdResult>;
658
774
  /**
659
- * Notifies CrazyGames that gameplay has started.
660
- * No-op on other platforms.
775
+ * Required lifecycle telemetry Gameplay start.
776
+ * Also notifies CrazyGames that gameplay has started.
661
777
  */
662
- gameplayStart(): Promise<void>;
778
+ gameplayStart(): Promise<boolean>;
663
779
  /**
664
780
  * Notifies CrazyGames that gameplay has stopped.
665
781
  * No-op on other platforms.
@@ -995,6 +1111,10 @@ declare enum NativeMessageType {
995
1111
  GET_PRODUCTS = "GET_PRODUCTS",
996
1112
  /** Initiate a purchase */
997
1113
  PURCHASE = "PURCHASE",
1114
+ /** Request a native AdMob rewarded ad */
1115
+ SHOW_REWARDED_AD = "SHOW_REWARDED_AD",
1116
+ /** Request a native AdMob interstitial ad */
1117
+ SHOW_INTERSTITIAL_AD = "SHOW_INTERSTITIAL_AD",
998
1118
  /** Response to CHECK_IAP_AVAILABILITY request */
999
1119
  IAP_AVAILABILITY_RESULT = "IAP_AVAILABILITY_RESULT",
1000
1120
  /** Push notification permission was granted */
@@ -1006,7 +1126,37 @@ declare enum NativeMessageType {
1006
1126
  /** Purchase completed successfully */
1007
1127
  PURCHASE_COMPLETE = "PURCHASE_COMPLETE",
1008
1128
  /** Purchase failed or was cancelled */
1009
- PURCHASE_ERROR = "PURCHASE_ERROR"
1129
+ PURCHASE_ERROR = "PURCHASE_ERROR",
1130
+ /** Result of a SHOW_REWARDED_AD / SHOW_INTERSTITIAL_AD request */
1131
+ AD_RESULT = "AD_RESULT"
1132
+ }
1133
+ /**
1134
+ * Payload sent to native for a SHOW_*_AD request.
1135
+ * Native is the sole authority for resolving (format, placement) → ad unit ID,
1136
+ * so the SDK never sends or sees unit IDs (see docs/admob-migration.md).
1137
+ */
1138
+ interface AdRequestPayload {
1139
+ /** Game the ad belongs to — native keys its unit-ID lookup on this. */
1140
+ gameId: string;
1141
+ /** AdMob format string, e.g. "rewarded" | "interstitial". */
1142
+ format: string;
1143
+ /** Optional placement key; native falls back to "default" when omitted. */
1144
+ placement?: string;
1145
+ }
1146
+ /**
1147
+ * Raw `AD_RESULT` payload as received from native.
1148
+ *
1149
+ * `error` is a string code (e.g. "not_configured", "config_fetch_failed"),
1150
+ * not an `Error` object — the SDK inspects it to decide whether to fall back
1151
+ * to the web ad path before converting it for the public `AdResult`.
1152
+ */
1153
+ interface NativeAdResult {
1154
+ /** Echoes the resolved ad type ("rewarded" | "interstitial"). */
1155
+ type: string;
1156
+ /** Whether the ad was shown successfully. */
1157
+ success: boolean;
1158
+ /** Error code when the ad did not show. */
1159
+ error?: string;
1010
1160
  }
1011
1161
  /**
1012
1162
  * Message handler function type for receiving messages from native
@@ -1032,6 +1182,12 @@ type NativeMessageHandler<T = any> = (payload: T) => void | Promise<void>;
1032
1182
  declare class NativeBridge {
1033
1183
  private static handlers;
1034
1184
  private static isInitialized;
1185
+ /**
1186
+ * Pending `sendAdRequest()` promises, keyed by the ad type native echoes
1187
+ * back in `AD_RESULT.type` ("rewarded" | "interstitial"). One in-flight
1188
+ * request per type — ads are shown sequentially.
1189
+ */
1190
+ private static adResultResolvers;
1035
1191
  /**
1036
1192
  * Checks if the app is running inside a React Native WebView
1037
1193
  */
@@ -1135,6 +1291,38 @@ declare class NativeBridge {
1135
1291
  * NativeBridge.purchase("product_123", "user_456");
1136
1292
  */
1137
1293
  static purchase(productId: string, userId: string): void;
1294
+ /**
1295
+ * Sends a native ad request and resolves with the `AD_RESULT` native sends
1296
+ * back. Never rejects — a missing native context, timeout, or superseded
1297
+ * request resolves to `{ success: false }` with an error code so callers can
1298
+ * decide whether to fall back to the web ad path.
1299
+ *
1300
+ * @param messageType - `SHOW_REWARDED_AD` or `SHOW_INTERSTITIAL_AD`
1301
+ * @param payload - `{ gameId, format, placement? }`
1302
+ * @param timeoutMs - How long to wait for `AD_RESULT` before giving up
1303
+ *
1304
+ * @example
1305
+ * const result = await NativeBridge.sendAdRequest(
1306
+ * NativeMessageType.SHOW_REWARDED_AD,
1307
+ * { gameId: "123", format: "rewarded", placement: "level_end" },
1308
+ * );
1309
+ * if (result.success) grantReward();
1310
+ */
1311
+ static sendAdRequest(messageType: NativeMessageType.SHOW_REWARDED_AD | NativeMessageType.SHOW_INTERSTITIAL_AD, payload: AdRequestPayload, timeoutMs?: number): Promise<NativeAdResult>;
1312
+ /**
1313
+ * Registers a handler invoked for every `AD_RESULT` message from native,
1314
+ * in addition to resolving any pending {@link sendAdRequest} promise.
1315
+ * Useful for diagnostics or availability tracking.
1316
+ *
1317
+ * @param handler - Called with the raw `AD_RESULT` payload
1318
+ */
1319
+ static onAdResult(handler: NativeMessageHandler<NativeAdResult>): void;
1320
+ /**
1321
+ * Resolves the pending {@link sendAdRequest} promise that matches an
1322
+ * incoming `AD_RESULT` payload. No-op when nothing is waiting (e.g. a late
1323
+ * result after a timeout).
1324
+ */
1325
+ private static resolveAdResult;
1138
1326
  }
1139
1327
 
1140
1328
  /**
@@ -1143,4 +1331,4 @@ declare class NativeBridge {
1143
1331
  */
1144
1332
  declare function generateUUID(): string;
1145
1333
 
1146
- export { type AdConfig, type AdResult, type AdType, AdsService, type BatchSaveGameDataResponse, type BatchSaveResultItem, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, CloudStorageAdapter, CrazyGamesService, type DeleteGameDataResponse, type GameDataBatchItem, type GameDataItem, type GameDataLeaderboardEntry, type GameDataLeaderboardResponse, type GameDataLeaderboardUserPosition, type GameDataOperation, type GameDataValue, type GetGameDataBatchResponse, type GetGameDataLeaderboardParams, type GetGameDataResponse, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, LocalStorageAdapter, Logger, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, PlaygamaService, type PurchaseResult, type SaveGameDataResponse, type StorageAdapter, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, isDomainAllowed, logger, parseUrlParams };
1334
+ export { type AdConfig, type AdMobFormat, type AdRequestPayload, type AdResult, type AdType, AdsService, type BatchSaveGameDataResponse, type BatchSaveResultItem, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, CloudStorageAdapter, CrazyGamesService, type DeleteGameDataResponse, type GameDataBatchItem, type GameDataItem, type GameDataLeaderboardEntry, type GameDataLeaderboardResponse, type GameDataLeaderboardUserPosition, type GameDataOperation, type GameDataValue, type GetGameDataBatchResponse, type GetGameDataLeaderboardParams, type GetGameDataResponse, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, LocalStorageAdapter, Logger, type NativeAdResult, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, PlaygamaService, type PurchaseResult, type SaveGameDataResponse, type StorageAdapter, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, isDomainAllowed, logger, parseUrlParams };