@omen.foundation/game-sdk 1.0.16 → 1.0.17

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
@@ -12,6 +12,12 @@ The SDK supports two modes:
12
12
  npm install @omen.foundation/game-sdk
13
13
  ```
14
14
 
15
+ For **real-time updates** (balance & inventory), also install Ably:
16
+
17
+ ```bash
18
+ npm install ably
19
+ ```
20
+
15
21
  ## Quick Start
16
22
 
17
23
  ### Client Mode (OAuth Authentication)
@@ -188,6 +194,51 @@ if (sdk.isAuthenticated()) {
188
194
  await sdk.logout();
189
195
  ```
190
196
 
197
+ ### Real-Time Updates (Balance & Inventory)
198
+
199
+ So your game stays in sync when the user spends or receives OmenX / NFTs on the website or in another client, subscribe to the per-wallet Ably channel. The SDK provides the channel name, event names, and a subscribe helper with idempotency (eventId dedupe).
200
+
201
+ **Requires:** `ably` installed in your app. Use the same Ably API key as the OmenX frontend (subscribe capability for `wallet:*`).
202
+
203
+ ```typescript
204
+ import { subscribeWalletRealtime, getWalletChannelName, REALTIME_EVENTS } from '@omen.foundation/game-sdk';
205
+ import * as Ably from 'ably';
206
+
207
+ // After user logs in and you have their wallet address:
208
+ const ably = new Ably.Realtime({ key: 'YOUR_ABLY_API_KEY' });
209
+
210
+ const unsubscribe = subscribeWalletRealtime(ably, walletAddress, {
211
+ onBalance: (payload) => {
212
+ // Refetch balances (e.g. call your backend or GetPlayerBalances)
213
+ refetchBalances();
214
+ },
215
+ onInventory: (payload) => {
216
+ // Refetch inventory / NFTs (backend cache is source of truth)
217
+ refetchInventory();
218
+ },
219
+ });
220
+
221
+ // When user logs out or wallet changes:
222
+ unsubscribe();
223
+ ```
224
+
225
+ With React and `ably/react`, pass the client from `useAbly()`:
226
+
227
+ ```typescript
228
+ import { useAbly } from 'ably/react';
229
+ import { subscribeWalletRealtime } from '@omen.foundation/game-sdk';
230
+
231
+ // Inside your component, after wallet is available:
232
+ const ably = useAbly();
233
+ useEffect(() => {
234
+ if (!walletAddress || !ably) return;
235
+ return subscribeWalletRealtime(ably, walletAddress, {
236
+ onBalance: () => refetchBalances(),
237
+ onInventory: () => refetchInventory(),
238
+ });
239
+ }, [ably, walletAddress]);
240
+ ```
241
+
191
242
  ## API Reference
192
243
 
193
244
  See the [full documentation](./docs/README.md) for detailed API reference.
package/dist/index.d.mts CHANGED
@@ -276,13 +276,15 @@ declare class OmenXServerSDK {
276
276
  * NFT Template Operations
277
277
  */
278
278
  /**
279
- * Get all NFT templates for a game
279
+ * Get all NFT templates for the authenticated game (game is derived from API key).
280
+ * gameId is optional and ignored by the API; included for backward compatibility.
280
281
  */
281
- getNftTemplates(gameId: string): Promise<any>;
282
+ getNftTemplates(_gameId?: string): Promise<any>;
282
283
  /**
283
- * Get NFT contract address for a game
284
+ * Get NFT contract address for the authenticated game (game is derived from API key).
285
+ * gameId is optional and ignored by the API; included for backward compatibility.
284
286
  */
285
- getNftContract(gameId: string): Promise<any>;
287
+ getNftContract(_gameId?: string): Promise<any>;
286
288
  /**
287
289
  * Mint NFTs (single or batch)
288
290
  */
@@ -344,6 +346,129 @@ declare class OmenXServerSDK {
344
346
  phaseIndex?: number;
345
347
  };
346
348
  }>;
349
+ /**
350
+ * Quests API (game quests only).
351
+ * Requires scope: quests:read for getQuestsForPlayer; quests:write for assign, progress, complete, claim.
352
+ */
353
+ /** Get assigned quests for a player. Optional questType filter. */
354
+ getQuestsForPlayer(wallet: string, options?: {
355
+ questType?: 'daily' | 'weekly' | 'monthly' | 'oneTime';
356
+ }): Promise<{
357
+ success: boolean;
358
+ data: {
359
+ quests: any[];
360
+ };
361
+ }>;
362
+ /** Assign quests of a type to a player. Use idempotencyKey for safe retries. */
363
+ assignQuests(wallet: string, questType: 'daily' | 'weekly' | 'monthly' | 'oneTime', count: number, options?: {
364
+ idempotencyKey?: string;
365
+ }): Promise<{
366
+ success: boolean;
367
+ data: {
368
+ assigned: number;
369
+ assignmentIds?: string[];
370
+ };
371
+ }>;
372
+ /** Report progress for a quest step. Quest auto-completes when all steps meet targets. */
373
+ reportQuestProgress(wallet: string, questKey: string, value: number, options?: {
374
+ stepKey?: string;
375
+ }): Promise<{
376
+ success: boolean;
377
+ data?: object;
378
+ }>;
379
+ /** Mark a quest complete (all steps set to targets). */
380
+ completeQuest(wallet: string, questKey: string): Promise<{
381
+ success: boolean;
382
+ data?: object;
383
+ }>;
384
+ /** Claim VIP reward for a completed quest (from game pool). Use idempotencyKey for safe retries. */
385
+ claimQuestReward(wallet: string, questKey: string, options?: {
386
+ idempotencyKey?: string;
387
+ }): Promise<{
388
+ success: boolean;
389
+ data?: {
390
+ pointsGranted?: number;
391
+ };
392
+ }>;
393
+ /**
394
+ * Reset or wipe a player's quest state for this game. Requires quests:write.
395
+ * - wipe: delete all quest assignments for this game for the player.
396
+ * - reset: delete assignments for the specified questKey only (questKey required).
397
+ */
398
+ resetPlayerQuests(wallet: string, action: 'wipe' | 'reset', questKey?: string): Promise<{
399
+ success: boolean;
400
+ data: {
401
+ action: string;
402
+ deleted: number;
403
+ questKey?: string;
404
+ };
405
+ }>;
406
+ }
407
+
408
+ /**
409
+ * Real-time wallet updates (balance & inventory) for game clients.
410
+ * Subscribe to the per-wallet Ably channel so the game stays in sync when the user
411
+ * spends or receives OmenX / NFTs on the website or in another client.
412
+ *
413
+ * Requires the app to install `ably` and pass an Ably Realtime instance.
414
+ */
415
+ /** Payload for balance and inventory events. Use eventId for idempotency (ignore if already processed). */
416
+ interface RealtimeWalletPayload {
417
+ eventId: string;
418
+ timestamp: number;
419
+ reason?: string;
347
420
  }
421
+ /** Ably channel name prefix. Full channel = "wallet:" + normalized wallet address. */
422
+ declare const WALLET_CHANNEL_PREFIX = "wallet:";
423
+ /** Event names published by the OmenX backend on the wallet channel. */
424
+ declare const REALTIME_EVENTS: {
425
+ /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */
426
+ readonly balance: "balance";
427
+ /** NFT/inventory changed. Refetch via GetPlayerNfts or your inventory API (cache is source of truth). */
428
+ readonly inventory: "inventory";
429
+ };
430
+ /**
431
+ * Get the Ably channel name for a wallet. Use this when subscribing with your Ably client.
432
+ */
433
+ declare function getWalletChannelName(walletAddress: string): string;
434
+ /**
435
+ * Minimal Ably Realtime interface so the SDK works with any Ably.Realtime instance.
436
+ * The app provides the real Ably client from AblyProvider or new Ably.Realtime({ key }).
437
+ */
438
+ interface AblyRealtimeLike {
439
+ channels: {
440
+ get(name: string): {
441
+ subscribe(eventOrCallback: string | ((message: {
442
+ name: string;
443
+ data: unknown;
444
+ }) => void), callback?: (message: {
445
+ name: string;
446
+ data: unknown;
447
+ }) => void): void;
448
+ unsubscribe(eventOrCallback?: string | ((message: {
449
+ name: string;
450
+ data: unknown;
451
+ }) => void), callback?: (message: {
452
+ name: string;
453
+ data: unknown;
454
+ }) => void): void;
455
+ };
456
+ };
457
+ }
458
+ /**
459
+ * Subscribe to real-time balance and inventory events for a wallet.
460
+ * Call when the user logs in; call the returned unsubscribe when they log out or wallet changes.
461
+ *
462
+ * Uses eventId to dedupe (ignores already-seen events). Refetch in your app on each callback.
463
+ *
464
+ * @param ably - Ably Realtime instance (e.g. from useAbly() or new Ably.Realtime({ key }))
465
+ * @param walletAddress - Current player wallet (0x...)
466
+ * @param callbacks - onBalance and/or onInventory; each receives the payload (eventId, timestamp, reason?)
467
+ * @returns Unsubscribe function
468
+ */
469
+ declare function subscribeWalletRealtime(ably: AblyRealtimeLike, walletAddress: string, callbacks: {
470
+ onBalance?: (payload: RealtimeWalletPayload) => void;
471
+ onInventory?: (payload: RealtimeWalletPayload) => void;
472
+ }): () => void;
348
473
 
349
- export { type ApiCallOptions, type AuthData, type OAuthOptions, OmenXGameSDK, type OmenXGameSDKConfig, OmenXServerSDK, type UserInfo, type VipStatus, type VipTierInfo };
474
+ export { type AblyRealtimeLike, type ApiCallOptions, type AuthData, type OAuthOptions, OmenXGameSDK, type OmenXGameSDKConfig, OmenXServerSDK, REALTIME_EVENTS, type RealtimeWalletPayload, type UserInfo, type VipStatus, type VipTierInfo, WALLET_CHANNEL_PREFIX, getWalletChannelName, subscribeWalletRealtime };
package/dist/index.d.ts CHANGED
@@ -276,13 +276,15 @@ declare class OmenXServerSDK {
276
276
  * NFT Template Operations
277
277
  */
278
278
  /**
279
- * Get all NFT templates for a game
279
+ * Get all NFT templates for the authenticated game (game is derived from API key).
280
+ * gameId is optional and ignored by the API; included for backward compatibility.
280
281
  */
281
- getNftTemplates(gameId: string): Promise<any>;
282
+ getNftTemplates(_gameId?: string): Promise<any>;
282
283
  /**
283
- * Get NFT contract address for a game
284
+ * Get NFT contract address for the authenticated game (game is derived from API key).
285
+ * gameId is optional and ignored by the API; included for backward compatibility.
284
286
  */
285
- getNftContract(gameId: string): Promise<any>;
287
+ getNftContract(_gameId?: string): Promise<any>;
286
288
  /**
287
289
  * Mint NFTs (single or batch)
288
290
  */
@@ -344,6 +346,129 @@ declare class OmenXServerSDK {
344
346
  phaseIndex?: number;
345
347
  };
346
348
  }>;
349
+ /**
350
+ * Quests API (game quests only).
351
+ * Requires scope: quests:read for getQuestsForPlayer; quests:write for assign, progress, complete, claim.
352
+ */
353
+ /** Get assigned quests for a player. Optional questType filter. */
354
+ getQuestsForPlayer(wallet: string, options?: {
355
+ questType?: 'daily' | 'weekly' | 'monthly' | 'oneTime';
356
+ }): Promise<{
357
+ success: boolean;
358
+ data: {
359
+ quests: any[];
360
+ };
361
+ }>;
362
+ /** Assign quests of a type to a player. Use idempotencyKey for safe retries. */
363
+ assignQuests(wallet: string, questType: 'daily' | 'weekly' | 'monthly' | 'oneTime', count: number, options?: {
364
+ idempotencyKey?: string;
365
+ }): Promise<{
366
+ success: boolean;
367
+ data: {
368
+ assigned: number;
369
+ assignmentIds?: string[];
370
+ };
371
+ }>;
372
+ /** Report progress for a quest step. Quest auto-completes when all steps meet targets. */
373
+ reportQuestProgress(wallet: string, questKey: string, value: number, options?: {
374
+ stepKey?: string;
375
+ }): Promise<{
376
+ success: boolean;
377
+ data?: object;
378
+ }>;
379
+ /** Mark a quest complete (all steps set to targets). */
380
+ completeQuest(wallet: string, questKey: string): Promise<{
381
+ success: boolean;
382
+ data?: object;
383
+ }>;
384
+ /** Claim VIP reward for a completed quest (from game pool). Use idempotencyKey for safe retries. */
385
+ claimQuestReward(wallet: string, questKey: string, options?: {
386
+ idempotencyKey?: string;
387
+ }): Promise<{
388
+ success: boolean;
389
+ data?: {
390
+ pointsGranted?: number;
391
+ };
392
+ }>;
393
+ /**
394
+ * Reset or wipe a player's quest state for this game. Requires quests:write.
395
+ * - wipe: delete all quest assignments for this game for the player.
396
+ * - reset: delete assignments for the specified questKey only (questKey required).
397
+ */
398
+ resetPlayerQuests(wallet: string, action: 'wipe' | 'reset', questKey?: string): Promise<{
399
+ success: boolean;
400
+ data: {
401
+ action: string;
402
+ deleted: number;
403
+ questKey?: string;
404
+ };
405
+ }>;
406
+ }
407
+
408
+ /**
409
+ * Real-time wallet updates (balance & inventory) for game clients.
410
+ * Subscribe to the per-wallet Ably channel so the game stays in sync when the user
411
+ * spends or receives OmenX / NFTs on the website or in another client.
412
+ *
413
+ * Requires the app to install `ably` and pass an Ably Realtime instance.
414
+ */
415
+ /** Payload for balance and inventory events. Use eventId for idempotency (ignore if already processed). */
416
+ interface RealtimeWalletPayload {
417
+ eventId: string;
418
+ timestamp: number;
419
+ reason?: string;
347
420
  }
421
+ /** Ably channel name prefix. Full channel = "wallet:" + normalized wallet address. */
422
+ declare const WALLET_CHANNEL_PREFIX = "wallet:";
423
+ /** Event names published by the OmenX backend on the wallet channel. */
424
+ declare const REALTIME_EVENTS: {
425
+ /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */
426
+ readonly balance: "balance";
427
+ /** NFT/inventory changed. Refetch via GetPlayerNfts or your inventory API (cache is source of truth). */
428
+ readonly inventory: "inventory";
429
+ };
430
+ /**
431
+ * Get the Ably channel name for a wallet. Use this when subscribing with your Ably client.
432
+ */
433
+ declare function getWalletChannelName(walletAddress: string): string;
434
+ /**
435
+ * Minimal Ably Realtime interface so the SDK works with any Ably.Realtime instance.
436
+ * The app provides the real Ably client from AblyProvider or new Ably.Realtime({ key }).
437
+ */
438
+ interface AblyRealtimeLike {
439
+ channels: {
440
+ get(name: string): {
441
+ subscribe(eventOrCallback: string | ((message: {
442
+ name: string;
443
+ data: unknown;
444
+ }) => void), callback?: (message: {
445
+ name: string;
446
+ data: unknown;
447
+ }) => void): void;
448
+ unsubscribe(eventOrCallback?: string | ((message: {
449
+ name: string;
450
+ data: unknown;
451
+ }) => void), callback?: (message: {
452
+ name: string;
453
+ data: unknown;
454
+ }) => void): void;
455
+ };
456
+ };
457
+ }
458
+ /**
459
+ * Subscribe to real-time balance and inventory events for a wallet.
460
+ * Call when the user logs in; call the returned unsubscribe when they log out or wallet changes.
461
+ *
462
+ * Uses eventId to dedupe (ignores already-seen events). Refetch in your app on each callback.
463
+ *
464
+ * @param ably - Ably Realtime instance (e.g. from useAbly() or new Ably.Realtime({ key }))
465
+ * @param walletAddress - Current player wallet (0x...)
466
+ * @param callbacks - onBalance and/or onInventory; each receives the payload (eventId, timestamp, reason?)
467
+ * @returns Unsubscribe function
468
+ */
469
+ declare function subscribeWalletRealtime(ably: AblyRealtimeLike, walletAddress: string, callbacks: {
470
+ onBalance?: (payload: RealtimeWalletPayload) => void;
471
+ onInventory?: (payload: RealtimeWalletPayload) => void;
472
+ }): () => void;
348
473
 
349
- export { type ApiCallOptions, type AuthData, type OAuthOptions, OmenXGameSDK, type OmenXGameSDKConfig, OmenXServerSDK, type UserInfo, type VipStatus, type VipTierInfo };
474
+ export { type AblyRealtimeLike, type ApiCallOptions, type AuthData, type OAuthOptions, OmenXGameSDK, type OmenXGameSDKConfig, OmenXServerSDK, REALTIME_EVENTS, type RealtimeWalletPayload, type UserInfo, type VipStatus, type VipTierInfo, WALLET_CHANNEL_PREFIX, getWalletChannelName, subscribeWalletRealtime };
package/dist/index.js CHANGED
@@ -630,17 +630,19 @@ var OmenXServerSDK = class {
630
630
  * NFT Template Operations
631
631
  */
632
632
  /**
633
- * Get all NFT templates for a game
633
+ * Get all NFT templates for the authenticated game (game is derived from API key).
634
+ * gameId is optional and ignored by the API; included for backward compatibility.
634
635
  */
635
- async getNftTemplates(gameId) {
636
- const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);
636
+ async getNftTemplates(_gameId) {
637
+ const response = await this.apiCall("/v1/nfts/templates");
637
638
  return response.json();
638
639
  }
639
640
  /**
640
- * Get NFT contract address for a game
641
+ * Get NFT contract address for the authenticated game (game is derived from API key).
642
+ * gameId is optional and ignored by the API; included for backward compatibility.
641
643
  */
642
- async getNftContract(gameId) {
643
- const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);
644
+ async getNftContract(_gameId) {
645
+ const response = await this.apiCall("/v1/nfts/contract");
644
646
  return response.json();
645
647
  }
646
648
  /**
@@ -715,9 +717,115 @@ var OmenXServerSDK = class {
715
717
  });
716
718
  return response.json();
717
719
  }
720
+ /**
721
+ * Quests API (game quests only).
722
+ * Requires scope: quests:read for getQuestsForPlayer; quests:write for assign, progress, complete, claim.
723
+ */
724
+ /** Get assigned quests for a player. Optional questType filter. */
725
+ async getQuestsForPlayer(wallet, options) {
726
+ const q = options?.questType ? `?questType=${options.questType}` : "";
727
+ const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}${q}`);
728
+ return response.json();
729
+ }
730
+ /** Assign quests of a type to a player. Use idempotencyKey for safe retries. */
731
+ async assignQuests(wallet, questType, count, options) {
732
+ const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}/assign`, {
733
+ method: "POST",
734
+ body: { questType, count },
735
+ headers: options?.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : void 0
736
+ });
737
+ return response.json();
738
+ }
739
+ /** Report progress for a quest step. Quest auto-completes when all steps meet targets. */
740
+ async reportQuestProgress(wallet, questKey, value, options) {
741
+ const response = await this.apiCall("/v1/quests/progress", {
742
+ method: "POST",
743
+ body: { wallet, questKey, value, stepKey: options?.stepKey }
744
+ });
745
+ return response.json();
746
+ }
747
+ /** Mark a quest complete (all steps set to targets). */
748
+ async completeQuest(wallet, questKey) {
749
+ const response = await this.apiCall("/v1/quests/complete", {
750
+ method: "POST",
751
+ body: { wallet, questKey }
752
+ });
753
+ return response.json();
754
+ }
755
+ /** Claim VIP reward for a completed quest (from game pool). Use idempotencyKey for safe retries. */
756
+ async claimQuestReward(wallet, questKey, options) {
757
+ const response = await this.apiCall("/v1/quests/claim", {
758
+ method: "POST",
759
+ body: { wallet, questKey },
760
+ headers: options?.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : void 0
761
+ });
762
+ return response.json();
763
+ }
764
+ /**
765
+ * Reset or wipe a player's quest state for this game. Requires quests:write.
766
+ * - wipe: delete all quest assignments for this game for the player.
767
+ * - reset: delete assignments for the specified questKey only (questKey required).
768
+ */
769
+ async resetPlayerQuests(wallet, action, questKey) {
770
+ const body = { action };
771
+ if (action === "reset" && questKey) body.questKey = questKey;
772
+ const response = await this.apiCall("/v1/quests/players/" + encodeURIComponent(wallet) + "/reset", {
773
+ method: "POST",
774
+ body
775
+ });
776
+ return response.json();
777
+ }
778
+ };
779
+
780
+ // src/realtime.ts
781
+ var WALLET_CHANNEL_PREFIX = "wallet:";
782
+ var REALTIME_EVENTS = {
783
+ /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */
784
+ balance: "balance",
785
+ /** NFT/inventory changed. Refetch via GetPlayerNfts or your inventory API (cache is source of truth). */
786
+ inventory: "inventory"
718
787
  };
788
+ var MAX_SEEN_IDS = 200;
789
+ function normalizeWallet(wallet) {
790
+ return (wallet || "").trim().toLowerCase();
791
+ }
792
+ function getWalletChannelName(walletAddress) {
793
+ return WALLET_CHANNEL_PREFIX + normalizeWallet(walletAddress);
794
+ }
795
+ function subscribeWalletRealtime(ably, walletAddress, callbacks) {
796
+ const normalized = normalizeWallet(walletAddress);
797
+ if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {
798
+ return () => {
799
+ };
800
+ }
801
+ const seenIds = /* @__PURE__ */ new Set();
802
+ const handleMessage = (message) => {
803
+ const data = message.data;
804
+ if (!data || typeof data !== "object" || typeof data.eventId !== "string") return;
805
+ if (seenIds.has(data.eventId)) return;
806
+ if (seenIds.size >= MAX_SEEN_IDS) {
807
+ const first = seenIds.values().next().value;
808
+ if (first != null) seenIds.delete(first);
809
+ }
810
+ seenIds.add(data.eventId);
811
+ if (message.name === REALTIME_EVENTS.balance && callbacks.onBalance) {
812
+ callbacks.onBalance(data);
813
+ } else if (message.name === REALTIME_EVENTS.inventory && callbacks.onInventory) {
814
+ callbacks.onInventory(data);
815
+ }
816
+ };
817
+ const channel = ably.channels.get(getWalletChannelName(normalized));
818
+ channel.subscribe(handleMessage);
819
+ return () => {
820
+ channel.unsubscribe(handleMessage);
821
+ };
822
+ }
719
823
 
720
824
  exports.OmenXGameSDK = OmenXGameSDK;
721
825
  exports.OmenXServerSDK = OmenXServerSDK;
826
+ exports.REALTIME_EVENTS = REALTIME_EVENTS;
827
+ exports.WALLET_CHANNEL_PREFIX = WALLET_CHANNEL_PREFIX;
828
+ exports.getWalletChannelName = getWalletChannelName;
829
+ exports.subscribeWalletRealtime = subscribeWalletRealtime;
722
830
  //# sourceMappingURL=index.js.map
723
831
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":[],"mappings":";;;AAWO,IAAM,YAAN,MAAgB;AAAA,EAGrB,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAA,CAAa,OAAA,GAAwB,EAAC,EAAgC;AAE1E,IAAA,MAAM,KAAA,GAAQ,KAAK,aAAA,EAAc;AAGjC,IAAA,MAAM,YAAA,GAAe,KAAK,oBAAA,EAAqB;AAC/C,IAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,qBAAA,CAAsB,YAAY,CAAA;AAEnE,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AAGtC,MAAA,cAAA,CAAe,OAAA,CAAQ,CAAA,WAAA,EAAc,KAAK,CAAA,CAAA,EAAI,YAAY,CAAA;AAG1D,MAAA,MAAM,cAAc,OAAA,CAAQ,WAAA,IAAe,CAAA,EAAG,MAAA,CAAO,SAAS,MAAM,CAAA,cAAA,CAAA;AACpE,MAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAA,CAAK,OAAO,iBAAiB,CAAA;AACrD,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,WAAA,EAAa,IAAA,CAAK,OAAO,MAAM,CAAA;AACxD,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,cAAA,EAAgB,WAAW,CAAA;AACpD,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,eAAA,EAAiB,MAAM,CAAA;AAChD,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,sBAAsB,CAAA;AACxD,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,KAAK,CAAA;AACvC,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,gBAAA,EAAkB,aAAa,CAAA;AACxD,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,uBAAA,EAAyB,MAAM,CAAA;AAGxD,MAAA,MAAM,eAAA,GAAkB,qBAAqB,KAAK,CAAA,CAAA;AAClD,MAAA,cAAA,CAAe,OAAA,CAAQ,iBAAiB,KAAK,CAAA;AAG7C,MAAA,MAAM,QAAQ,MAAA,CAAO,IAAA;AAAA,QACnB,QAAQ,QAAA,EAAS;AAAA,QACjB,aAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,iEAAiE,CAAA;AACzF,QAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAK,CAAA;AAC3B,QAAA,MAAA,CAAO,KAAK,CAAA;AACZ,QAAA;AAAA,MACF;AAGA,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,CAAE,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,CAAW,uBAAuB,CAAC,CAAA;AAC3F,QAAA,OAAA,CAAQ,QAAQ,CAAA,GAAA,KAAO;AACrB,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,GAAO,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA;AACrC,YAAA,IAAI,IAAA,EAAM;AACR,cAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,cAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,EAAI,IAAK,OAAO,SAAA,IAAa,CAAA,CAAA;AAE9C,cAAA,IAAI,MAAM,GAAA,EAAQ;AAChB,gBAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,cAC7B;AAAA,YACF;AAAA,UACF,SAAS,CAAA,EAAG;AACV,YAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,UAC7B;AAAA,QACF,CAAC,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AAAA,MAEhB;AAGA,MAAA,MAAM,UAAA,GAAa,wBAAwB,KAAK,CAAA,CAAA;AAChD,MAAA,IAAI,eAAA,GAAkB,KAAA;AAEtB,MAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,QAAA,IAAI,eAAA,EAAiB;AACnB,UAAA,aAAA,CAAc,YAAY,CAAA;AAC1B,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,UAAU,CAAA;AAE9C,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAG9B,YAAA,IAAI,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,KAAA,KAAU,KAAA,EAAO;AACrC,cAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,EAAI,IAAK,KAAK,SAAA,IAAa,CAAA,CAAA;AAC5C,cAAA,IAAI,MAAM,GAAA,EAAO;AACf,gBAAA,eAAA,GAAkB,IAAA;AAClB,gBAAA,aAAA,CAAc,YAAY,CAAA;AAG1B,gBAAA,YAAA,CAAa,WAAW,UAAU,CAAA;AAClC,gBAAA,cAAA,CAAe,UAAA,CAAW,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AAC/C,gBAAA,cAAA,CAAe,WAAW,eAAe,CAAA;AAGzC,gBAAA,IAAA,CAAK,oBAAA,CAAqB,KAAK,IAAA,EAAM,WAAA,EAAa,YAAY,CAAA,CAC3D,IAAA,CAAK,OAAO,aAAA,KAAkB;AAC7B,kBAAA,MAAM,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,aAAa,CAAA;AAE/C,kBAAA,IAAI,KAAA,IAAS,CAAC,KAAA,CAAM,MAAA,EAAQ;AAC1B,oBAAA,IAAI;AACF,sBAAA,KAAA,CAAM,KAAA,EAAM;AAAA,oBACd,SAAS,CAAA,EAAG;AAAA,oBAEZ;AAAA,kBACF;AACA,kBAAA,OAAA,CAAQ,aAAa,CAAA;AAAA,gBACvB,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAU;AAChB,kBAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAc,CAAA;AACpC,kBAAA,MAAA,CAAO,KAAK,CAAA;AAAA,gBACd,CAAC,CAAA;AACH,gBAAA;AAAA,cACF,CAAA,MAAO;AAEL,gBAAA,YAAA,CAAa,WAAW,UAAU,CAAA;AAAA,cACpC;AAAA,YACF;AAAA,UACF,SAAS,KAAA,EAAO;AACd,YAAA,OAAA,CAAQ,KAAA,CAAM,oDAAoD,KAAK,CAAA;AAAA,UACzE;AAAA,QACF;AAAA,MACF,GAAG,GAAG,CAAA;AAGN,MAAA,MAAM,WAAA,GAAc,YAAY,MAAM;AACpC,QAAA,IAAI,eAAA,EAAiB;AACnB,UAAA,aAAA,CAAc,WAAW,CAAA;AACzB,UAAA;AAAA,QACF;AAGA,QAAA,IAAI,QAAA,GAAW,KAAA;AACf,QAAA,IAAI;AACF,UAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,YAAA,IAAI;AAEF,cAAA,KAAA,CAAM,QAAA,CAAS,IAAA;AACf,cAAA,QAAA,GAAW,IAAA;AAAA,YACb,SAAS,CAAA,EAAG;AAEV,cAAA,QAAA,GAAW,KAAA;AAAA,YACb;AAAA,UACF;AAAA,QACF,SAAS,CAAA,EAAG;AACV,UAAA,QAAA,GAAW,KAAA;AAAA,QACb;AAEA,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,aAAA,CAAc,WAAW,CAAA;AACzB,UAAA,aAAA,CAAc,YAAY,CAAA;AAG1B,UAAA,cAAA,CAAe,UAAA,CAAW,CAAA,WAAA,EAAc,KAAK,CAAA,CAAE,CAAA;AAC/C,UAAA,cAAA,CAAe,WAAW,eAAe,CAAA;AAEzC,UAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,+BAA+B,CAAA;AACvD,UAAA,IAAA,CAAK,MAAA,CAAO,UAAU,KAAK,CAAA;AAC3B,UAAA,MAAA,CAAO,KAAK,CAAA;AAAA,QACd;AAAA,MACF,GAAG,GAAI,CAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAA,CACZ,IAAA,EACA,WAAA,EACA,YAAA,EAC6B;AAC7B,IAAA,MAAM,IAAA,GAAY;AAAA,MAChB,IAAA;AAAA,MACA,YAAA,EAAc,WAAA;AAAA,MACd,UAAA,EAAY,oBAAA;AAAA,MACZ,SAAA,EAAW,KAAK,MAAA,CAAO;AAAA,KACzB;AAEA,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,IACvB;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,IAAA,CAAK,OAAO,aAAA,EAAe;AAAA,MACtD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,KAC1B,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK,CAAE,MAAM,OAAO,EAAE,OAAA,EAAS,mCAAA,EAAoC,CAAE,CAAA;AAClG,MAAA,MAAM,IAAI,KAAA,CAAM,KAAA,CAAM,OAAA,IAAW,mCAAmC,CAAA;AAAA,IACtE;AAEA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAA,GAAwB;AAC9B,IAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,IAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC5B,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAA,IAAA,KAAQ,KAAK,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAA,GAA+B;AACrC,IAAA,MAAM,OAAA,GAAU,oEAAA;AAChB,IAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,GAAG,CAAA;AAChC,IAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC5B,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAA,IAAA,KAAQ,OAAA,CAAQ,IAAA,GAAO,OAAA,CAAQ,MAAM,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,sBAAsB,QAAA,EAAmC;AACrE,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA;AACpC,IAAA,MAAM,OAAO,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,IAAI,CAAA;AACvD,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,YAAA,CAAa,GAAG,IAAI,UAAA,CAAW,IAAI,CAAC,CAAC,CAAA;AAChE,IAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA;AAAA,EACxE;AACF,CAAA;;;AC3OO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAAY,MAAA,EAA0B;AAFtC,IAAA,IAAA,CAAQ,eAAA,GAA0D,IAAA;AAGhE,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,GAAa;AAEX,IAAA,IAAA,CAAK,WAAA,EAAY;AAGjB,IAAA,IAAA,CAAK,eAAA,GAAkB,CAAC,KAAA,KAAwB;AAE9C,MAAA,IAAI,IAAA,CAAK,OAAO,YAAA,EAAc;AAC5B,QAAA,IAAI;AACF,UAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,IAAA,CAAK,OAAO,YAAY,CAAA;AAClD,UAAA,IAAI,KAAA,CAAM,MAAA,KAAW,SAAA,CAAU,MAAA,EAAQ;AACrC,YAAA;AAAA,UACF;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAGA,MAAA,IAAI,KAAA,CAAM,IAAA,EAAM,IAAA,KAAS,YAAA,EAAc;AACrC,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAG5B,QAAA,IAAI,QAAA,CAAS,MAAA,KAAW,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ;AAC1C,UAAA,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,MAAA,EAAS,QAAA,CAAS,MAAM,CAAA,CAAE,CAAC,CAAA;AAC3G,UAAA;AAAA,QACF;AAGA,QAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,EAAI,GAAK,IAAI,EAAA,GAAK,GAAA;AAC9C,QAAA,IAAI,QAAA,CAAS,YAAY,cAAA,EAAgB;AACvC,UAAA,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,IAAI,KAAA,CAAM,mBAAmB,CAAC,CAAA;AACpD,UAAA;AAAA,QACF;AAEA,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,MAC7B;AAAA,IACF,CAAA;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,eAAe,CAAA;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAA,GAAoB;AAC1B,IAAA,IAAI,MAAA,CAAO,WAAW,MAAA,EAAQ;AAE5B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,YAAA,IAAgB,GAAA;AACjD,IAAA,MAAA,CAAO,MAAA,CAAO,WAAA;AAAA,MACZ;AAAA,QACE,IAAA,EAAM,oBAAA;AAAA,QACN,MAAA,EAAQ,KAAK,MAAA,CAAO;AAAA,OACtB;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,IAAA,CAAK,eAAe,CAAA;AAC1D,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,IACzB;AAAA,EACF;AACF,CAAA;;;ACzFO,IAAM,eAAN,MAAmB;AAAA,EAGxB,WAAA,CAAY,mBAA2B,aAAA,EAAe;AACpD,IAAA,IAAA,CAAK,gBAAA,GAAmB,gBAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,CAAU,QAAA,EAAoB,YAAA,EAAsB,SAAA,EAAyB;AAC3E,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,GAAG,IAAA,CAAK,gBAAgB,QAAQ,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAC7E,MAAA,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,iBAAiB,YAAY,CAAA;AAC1E,MAAA,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,UAAA,CAAA,EAAc,MAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAK,SAAA,GAAY,GAAK,CAAC,CAAA;AAAA,IACpG,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,6CAA6C,KAAK,CAAA;AAAA,IACjE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA,GAAiC;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,IAAA,CAAM,CAAA;AAClE,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,IAC1B,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,gDAAgD,KAAK,CAAA;AAClE,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAAiC;AAC/B,IAAA,IAAI;AACF,MAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,aAAA,CAAe,CAAA;AAAA,IACrE,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,oDAAoD,KAAK,CAAA;AACtE,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAqB;AACnB,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,IAAA,CAAM,CAAA;AACtD,MAAA,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,aAAA,CAAe,CAAA;AAC/D,MAAA,YAAA,CAAa,UAAA,CAAW,CAAA,EAAG,IAAA,CAAK,gBAAgB,CAAA,UAAA,CAAY,CAAA;AAAA,IAC9D,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,2CAA2C,KAAK,CAAA;AAAA,IAC/D;AAAA,EACF;AACF,CAAA;;;AC/CO,IAAM,eAAN,MAAmB;AAAA,EAOxB,YAAY,MAAA,EAA4B;AAJxC,IAAA,IAAA,CAAQ,UAAA,GAAgC,IAAA;AAExC,IAAA,IAAA,CAAQ,eAAA,GAAmC,IAAA;AAIzC,IAAA,MAAM,UAAA,GAAa,OAAO,UAAA,IAAc,6BAAA;AACxC,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,UAAA;AAAA,MACA,iBAAA,EAAmB,MAAA,CAAO,iBAAA,IAAqB,CAAA,EAAG,UAAU,CAAA,mBAAA,CAAA;AAAA,MAC5D,aAAA,EAAe,MAAA,CAAO,aAAA,IAAiB,CAAA,EAAG,UAAU,CAAA,eAAA,CAAA;AAAA,MACpD,MAAA,EAAQ,MAAA,CAAO,MAAA,KAAW,MAAM;AAAA,MAAC,CAAA,CAAA;AAAA,MACjC,WAAA,EAAa,OAAO,WAAA,KAAgB,CAAC,UAAU,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA,CAAA;AAAA,MAC7F,QAAA,EAAU,MAAA,CAAO,QAAA,KAAa,MAAM;AAAA,MAAC,CAAA,CAAA;AAAA,MACrC,gBAAA,EAAkB,OAAO,gBAAA,KAAqB,KAAA;AAAA,MAC9C,YAAA,EAAc,OAAO,YAAA,IAAgB,EAAA;AAAA,MACrC,gBAAA,EAAkB,OAAO,gBAAA,IAAoB;AAAA,KAC/C;AAGA,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,YAAA,CAAa,IAAA,CAAK,OAAO,gBAAgB,CAAA;AACjE,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,SAAA,CAAU;AAAA,MAC7B,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,MACpB,iBAAA,EAAmB,KAAK,MAAA,CAAO,iBAAA;AAAA,MAC/B,aAAA,EAAe,KAAK,MAAA,CAAO,aAAA;AAAA,MAC3B,UAAA,EAAY,KAAK,MAAA,CAAO,UAAA;AAAA,MACxB,eAAA,EAAiB,IAAA,CAAK,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA;AAAA,MACnD,OAAA,EAAS,KAAK,MAAA,CAAO;AAAA,KACtB,CAAA;AAED,IAAA,IAAI,IAAA,CAAK,OAAO,gBAAA,EAAkB;AAChC,MAAA,IAAA,CAAK,UAAA,GAAa,IAAI,UAAA,CAAW;AAAA,QAC/B,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,QACpB,YAAA,EAAc,IAAA,CAAK,MAAA,CAAO,YAAA,IAAgB,MAAA;AAAA,QAC1C,MAAA,EAAQ,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA;AAAA,QACrC,OAAA,EAAS,KAAK,MAAA,CAAO;AAAA,OACtB,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,IAAA,GAAsB;AAE1B,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,aAAA,EAAc;AACnD,IAAA,IAAI,UAAA,EAAY;AAEd,MAAA,MAAM,SAAA,GAAY,UAAA,CAAW,SAAA,GAAa,IAAA,GAAO,GAAA;AACjD,MAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA,EAAW;AAC1B,QAAA,IAAA,CAAK,eAAA,GAAkB,UAAA;AACvB,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,UAAU,CAAA;AAC7B,QAAA;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,MAAM,YAAA,GAAe,IAAA,CAAK,YAAA,CAAa,eAAA,EAAgB;AACvD,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,CAAK,mBAAmB,YAAY,CAAA;AAC1C,YAAA;AAAA,UACF,SAAS,KAAA,EAAO;AAEd,YAAA,IAAA,CAAK,aAAa,YAAA,EAAa;AAAA,UACjC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,gBAAA,IAAoB,IAAA,CAAK,eAAe,IAAA,EAAM;AAC5D,MAAA,IAAA,CAAK,WAAW,IAAA,EAAK;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,OAAA,EAA0C;AAC3D,IAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,SAAA,CAAU,aAAa,OAAO,CAAA;AAE/D,IAAA,OAAO;AAAA,MACL,aAAa,aAAA,CAAc,YAAA;AAAA,MAC3B,aAAA,EAAe,cAAc,IAAA,CAAK,aAAA;AAAA,MAClC,MAAA,EAAQ,cAAc,IAAA,CAAK,MAAA;AAAA,MAC3B,WAAA,EAAa,cAAc,IAAA,CAAK,WAAA;AAAA,MAChC,cAAA,EAAgB,cAAc,IAAA,CAAK,cAAA;AAAA,MACnC,KAAA,EAAO,cAAc,IAAA,CAAK,KAAA;AAAA,MAC1B,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,MACpB,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAA+B;AAC7B,IAAA,OAAO,IAAA,CAAK,eAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAA2B;AACzB,IAAA,OAAO,KAAK,eAAA,KAAoB,IAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,GAAwB;AAE5B,IAAA,IAAI,IAAA,CAAK,iBAAiB,WAAA,EAAa;AACrC,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,QAAQ,kBAAA,EAAoB;AAAA,UACrC,MAAA,EAAQ,MAAA;AAAA,UACR,IAAA,EAAM,EAAE,KAAA,EAAO,IAAA,CAAK,gBAAgB,WAAA,EAAY;AAAA,UAChD,WAAA,EAAa;AAAA;AAAA,SACd,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AAEd,QAAA,OAAA,CAAQ,IAAA,CAAK,uCAAuC,KAAK,CAAA;AAAA,MAC3D;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AACvB,IAAA,IAAA,CAAK,aAAa,YAAA,EAAa;AAC/B,IAAA,IAAA,CAAK,OAAO,QAAA,EAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,CAAQ,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAsB;AAC/E,IAAA,MAAM,MAAM,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,GAClC,QAAA,GACA,GAAG,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,EAAG,SAAS,UAAA,CAAW,GAAG,IAAI,QAAA,GAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA,CAAA;AAEpF,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,cAAA,EAAgB,kBAAA;AAAA,MAChB,GAAG,OAAA,CAAQ;AAAA,KACb;AAGA,IAAA,IAAI,OAAA,CAAQ,WAAA,KAAgB,KAAA,IAAS,IAAA,CAAK,iBAAiB,WAAA,EAAa;AACtE,MAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,gBAAgB,WAAW,CAAA,CAAA;AAAA,IACvE;AAEA,IAAA,MAAM,YAAA,GAA4B;AAAA,MAChC,MAAA,EAAQ,QAAQ,MAAA,IAAU,KAAA;AAAA,MAC1B;AAAA,KACF;AAEA,IAAA,IAAI,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,MAAA,KAAW,KAAA,EAAO;AAC5C,MAAA,YAAA,CAAa,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAAA,IACjD;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,YAAY,CAAA;AAG9C,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,IAAO,IAAA,CAAK,eAAA,EAAiB;AACnD,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,YAAA,CAAa,eAAA,EAAgB;AACvD,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,CAAK,mBAAmB,YAAY,CAAA;AAE1C,UAAA,IAAI,IAAA,CAAK,iBAAiB,WAAA,EAAa;AACrC,YAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,gBAAgB,WAAW,CAAA,CAAA;AACrE,YAAA,OAAO,MAAM,GAAA,EAAK,EAAE,GAAG,YAAA,EAAc,SAAS,CAAA;AAAA,UAChD;AAAA,QACF,SAAS,KAAA,EAAO;AAEd,UAAA,MAAM,KAAK,MAAA,EAAO;AAClB,UAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBAAoB,aAAA,EAAkD;AAClF,IAAA,MAAM,QAAA,GAAqB;AAAA,MACzB,aAAa,aAAA,CAAc,YAAA;AAAA,MAC3B,aAAA,EAAe,cAAc,IAAA,CAAK,aAAA;AAAA,MAClC,MAAA,EAAQ,cAAc,IAAA,CAAK,MAAA;AAAA,MAC3B,WAAA,EAAa,cAAc,IAAA,CAAK,WAAA;AAAA,MAChC,cAAA,EAAgB,cAAc,IAAA,CAAK,cAAA;AAAA,MACnC,KAAA,EAAO,cAAc,IAAA,CAAK,KAAA;AAAA,MAC1B,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,MACpB,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AAGA,IAAA,IAAA,CAAK,aAAa,SAAA,CAAU,QAAA,EAAU,aAAA,CAAc,aAAA,EAAe,cAAc,UAAU,CAAA;AAG3F,IAAA,IAAA,CAAK,eAAA,GAAkB,QAAA;AACvB,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,QAAA,EAA0B;AAE/C,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,EAAI,GAAK,IAAI,EAAA,GAAK,GAAA;AAC9C,IAAA,IAAI,QAAA,CAAS,YAAY,cAAA,EAAgB;AACvC,MAAA,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,IAAI,KAAA,CAAM,mBAAmB,CAAC,CAAA;AACtD,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,eAAA,GAAkB,QAAA;AACvB,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAA,GAA0C;AAC9C,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,aAAa,CAAA;AACjD,IAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,IAAA;AACzB,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,IAAA,SAAa,IAAA,CAAK,IAAA;AAC3C,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,uBAAA,GAAkD;AACtD,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,YAAA,EAAa;AACvC,IAAA,IAAI,CAAC,MAAA,EAAQ,IAAA,EAAM,OAAO,IAAA;AAC1B,IAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,oBAAA,IAAyB,MAAA,CAAO,KAAK,KAAA,EAAO,uBAAA;AACtE,IAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,SAAS,CAAA,IAAK,KAAA,IAAS,KAAK,KAAA,GAAQ,IAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAmB,YAAA,EAAqC;AACpE,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,IAAA,CAAK,OAAO,aAAA,EAAe;AAAA,MACtD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,UAAA,EAAY,eAAA;AAAA,QACZ,aAAA,EAAe;AAAA,OAChB;AAAA,KACF,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,IAC3C;AAEA,IAAA,MAAM,aAAA,GAAoC,MAAM,QAAA,CAAS,IAAA,EAAK;AAC9D,IAAA,MAAM,IAAA,CAAK,oBAAoB,aAAa,CAAA;AAAA,EAC9C;AACF;;;AC5QO,IAAM,iBAAN,MAAqB;AAAA,EAI1B,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,UAAA,EAAY,OAAO,UAAA,IAAc;AAAA,KACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,CAAQ,QAAA,EAAkB,OAAA,GAA0B,EAAC,EAAsB;AAC/E,IAAA,MAAM,MAAM,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,GAClC,QAAA,GACA,GAAG,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,EAAG,SAAS,UAAA,CAAW,GAAG,IAAI,QAAA,GAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA,CAAA;AAEpF,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,cAAA,EAAgB,kBAAA;AAAA,MAChB,eAAA,EAAiB,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,MACtC,GAAG,OAAA,CAAQ;AAAA,KACb;AAEA,IAAA,MAAM,YAAA,GAA4B;AAAA,MAChC,MAAA,EAAQ,QAAQ,MAAA,IAAU,KAAA;AAAA,MAC1B;AAAA,KACF;AAEA,IAAA,IAAI,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,MAAA,KAAW,KAAA,EAAO;AAC5C,MAAA,YAAA,CAAa,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAAA,IACjD;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,YAAY,CAAA;AAE9C,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,YAAY,MAAM,QAAA,CAAS,MAAK,CAAE,KAAA,CAAM,MAAM,eAAe,CAAA;AACnE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,QAAA,CAAS,MAAM,IAAI,QAAA,CAAS,UAAU,CAAA,GAAA,EAAM,SAAS,CAAA,CAAE,CAAA;AAAA,IAC7F;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,GAA4B;AAChC,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,cAAc,EAAE,WAAA,EAAa,OAAO,CAAA;AACxE,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAA,GAA8B;AAClC,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,aAAa,CAAA;AACjD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SAAA,CAAU,MAAA,EAAgB,OAAA,EAA+B;AAC7D,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAAA,MAC1B,eAAe,kBAAA,CAAmB,MAAM,CAAC,CAAA,SAAA,EAAY,kBAAA,CAAmB,OAAO,CAAC,CAAA;AAAA,KAClF;AACA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAA,CAAkB,MAAA,EAAgB,OAAA,EAA+B;AACrE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAAA,MAC1B,eAAe,kBAAA,CAAmB,MAAM,CAAC,CAAA,kBAAA,EAAqB,kBAAA,CAAmB,OAAO,CAAC,CAAA;AAAA,KAC3F;AACA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAA,CACJ,MAAA,EACA,OAAA,EACA,OAAA,EAKc;AACd,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB,EAAE,SAAS,CAAA;AAC9C,IAAA,IAAI,SAAS,QAAA,EAAU,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,QAAQ,QAAQ,CAAA;AAC9D,IAAA,IAAI,SAAS,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,QAAQ,MAAM,CAAA;AACxD,IAAA,IAAI,OAAA,EAAS,SAAS,IAAA,EAAM,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAErE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA;AAAA,MAC1B,eAAe,kBAAA,CAAmB,MAAM,CAAC,CAAA,MAAA,EAAS,MAAA,CAAO,UAAU,CAAA;AAAA,KACrE;AACA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,MAAA,EASJ;AACf,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB;AAAA,MACnD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,MAAA;AAAA,MACN,OAAA,EAAS,OAAO,cAAA,GAAiB;AAAA,QAC/B,mBAAmB,MAAA,CAAO;AAAA,OAC5B,GAAI;AAAA,KACL,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBAAgB,MAAA,EAA8B;AAClD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,0BAAA,EAA6B,MAAM,CAAA,CAAE,CAAA;AACzE,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,MAAA,EAA8B;AACjD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,yBAAA,EAA4B,MAAM,CAAA,CAAE,CAAA;AACxE,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,MAAA,EAIE;AACf,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB;AAAA,MACnD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,KAAA,EAIF;AAChB,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,KAAA;AAAM,KACf,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAA,CACJ,OAAA,EACA,QAAA,EAMc;AACd,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,SAAA,EAAY,OAAO,CAAA,SAAA,CAAA,EAAa;AAAA,MAClE,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,OAAA,EAA+B;AAC3C,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,SAAA,EAAY,OAAO,CAAA,CAAA,EAAI;AAAA,MACzD,MAAA,EAAQ;AAAA,KACT,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,QAAA,EAAkC;AACpD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,QAAA;AAAS,KAClB,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,MAAA,EAGA;AACf,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,sBAAA,EAAwB;AAAA,MAC1D,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,MAAA,EAO6E;AAChG,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,sBAAA,EAAwB;AAAA,MAC1D,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AACF","file":"index.js","sourcesContent":["import type { OAuthTokenResponse, OAuthOptions } from './types';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (token: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth 2.0 Authorization Code Grant with PKCE\r\n */\r\n async authenticate(options: OAuthOptions = {}): Promise<OAuthTokenResponse> {\r\n // Generate state for CSRF protection\r\n const state = this.generateState();\r\n \r\n // Generate PKCE code verifier and challenge\r\n const codeVerifier = this.generateCodeVerifier();\r\n const codeChallenge = await this.generateCodeChallenge(codeVerifier);\r\n \r\n return new Promise((resolve, reject) => {\r\n \r\n // Store code verifier in sessionStorage for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n \r\n // Build authorization URL\r\n const redirectUri = options.redirectUri || `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(this.config.oauthAuthorizeUrl);\r\n authUrl.searchParams.set('client_id', this.config.gameId);\r\n authUrl.searchParams.set('redirect_uri', redirectUri);\r\n authUrl.searchParams.set('response_type', 'code');\r\n authUrl.searchParams.set('scope', 'openid profile email');\r\n authUrl.searchParams.set('state', state);\r\n authUrl.searchParams.set('code_challenge', codeChallenge);\r\n authUrl.searchParams.set('code_challenge_method', 'S256');\r\n \r\n // Store state for verification\r\n const stateStorageKey = `omenx_oauth_state_${state}`;\r\n sessionStorage.setItem(stateStorageKey, state);\r\n \r\n // Open popup window\r\n const popup = window.open(\r\n authUrl.toString(),\r\n 'OmenX OAuth',\r\n 'width=500,height=600,left=100,top=100'\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Clean up old OAuth callback entries from localStorage\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n }\r\n }\r\n } catch (e) {\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n // Ignore cleanup errors\r\n }\r\n\r\n // Poll localStorage for callback data\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n let messageReceived = false;\r\n \r\n const pollInterval = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(pollInterval);\r\n return;\r\n }\r\n \r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Validate state and check timestamp\r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n localStorage.removeItem(storageKey);\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(data.code, redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n // Close popup after successful token exchange\r\n if (popup && !popup.closed) {\r\n try {\r\n popup.close();\r\n } catch (e) {\r\n // Ignore errors closing popup\r\n }\r\n }\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n return;\r\n } else {\r\n // Data too old, remove it\r\n localStorage.removeItem(storageKey);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error parsing localStorage callback:', error);\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Check if popup was closed without completing auth\r\n const checkClosed = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(checkClosed);\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed\r\n let isClosed = false;\r\n try {\r\n if (popup.closed) {\r\n try {\r\n // Try to access location to verify it's actually closed\r\n popup.location.href; // Accessing this will throw if popup is on different origin\r\n isClosed = true;\r\n } catch (e) {\r\n // Can't access location - popup is on different origin (still open)\r\n isClosed = false;\r\n }\r\n }\r\n } catch (e) {\r\n isClosed = false;\r\n }\r\n \r\n if (isClosed) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n client_id: this.config.gameId,\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code verifier\r\n */\r\n private generateCodeVerifier(): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(128);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code challenge from verifier\r\n */\r\n private async generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const hash = await crypto.subtle.digest('SHA-256', data);\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n VipStatus,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n const tokenResponse = await this.oauthFlow.authenticate(options);\r\n // Convert OAuthTokenResponse to AuthData\r\n return {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Get current VIP status for the authenticated user (tier, allocation, claimable, perks).\r\n * Games can read tier.gameBonusPointsLevel (1–21) for Alpha/Beta access or in-game gifts.\r\n */\r\n async getVipStatus(): Promise<VipStatus | null> {\r\n const response = await this.apiCall('/api/vip/me');\r\n if (!response.ok) return null;\r\n const data = await response.json();\r\n if (data.success && data.data) return data.data as VipStatus;\r\n return null;\r\n }\r\n\r\n /**\r\n * Get the current user's game bonus points level (1–21) from their VIP tier.\r\n * Use for Game Alpha Access (e.g. level >= 6), Game Beta Access (e.g. level >= 1), or in-game gifts.\r\n */\r\n async getGameBonusPointsLevel(): Promise<number | null> {\r\n const status = await this.getVipStatus();\r\n if (!status?.tier) return null;\r\n const level = status.tier.gameBonusPointsLevel ?? (status.tier.perks?.GAME_BONUS_POINTS_LEVEL as number);\r\n return typeof level === 'number' && level >= 1 && level <= 21 ? level : null;\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\n\ninterface ServerSDKConfig {\n /**\n * Your developer API key (from developer portal)\n */\n apiKey: string;\n\n /**\n * OmenX API base URL (default: https://api.omen.foundation)\n */\n apiBaseUrl?: string;\n}\n\n/**\n * OmenX Game SDK - Server Mode\n * \n * For Node.js backends using developer API keys.\n * This mode allows server-to-server communication with the OmenX API.\n */\nexport class OmenXServerSDK {\n private config: Required<ServerSDKConfig>;\n private apiKey: string;\n\n constructor(config: ServerSDKConfig) {\n this.apiKey = config.apiKey;\n this.config = {\n apiKey: config.apiKey,\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\n };\n }\n\n /**\n * Make an authenticated API call using the developer API key\n */\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\n const url = endpoint.startsWith('http') \n ? endpoint \n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...options.headers,\n };\n\n const fetchOptions: RequestInit = {\n method: options.method || 'GET',\n headers,\n };\n\n if (options.body && options.method !== 'GET') {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\n }\n\n return response;\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<any> {\n const response = await this.apiCall('/v1/health', { includeAuth: false });\n return response.json();\n }\n\n /**\n * Get API key information\n */\n async getApiKeyInfo(): Promise<any> {\n const response = await this.apiCall('/v1/auth/me');\n return response.json();\n }\n\n /**\n * Player Operations\n */\n\n /**\n * Get full player data: NFTs (system + game) and balances for a wallet.\n * Requires both nfts:read and balances:read scopes.\n */\n async getPlayer(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get native and ERC20 token balances for a wallet\n */\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/balances?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get paginated NFTs for a wallet.\n * With no contract: returns OmenX system NFTs (Asset Manager, Faucet, Early Adopter) + game NFTs.\n * With contract: returns only NFTs for that contract.\n */\n async getPlayerNfts(\n wallet: string,\n chainId: string,\n options?: {\n contract?: string;\n cursor?: string;\n limit?: number;\n }\n ): Promise<any> {\n const params = new URLSearchParams({ chainId });\n if (options?.contract) params.set('contract', options.contract);\n if (options?.cursor) params.set('cursor', options.cursor);\n if (options?.limit != null) params.set('limit', String(options.limit));\n\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/nfts?${params.toString()}`\n );\n return response.json();\n }\n\n /**\n * Purchase Operations\n */\n\n /**\n * Create a server-authoritative purchase\n */\n async createPurchase(params: {\n playerWallet?: string;\n walletAddress?: string; // Legacy field name\n skuId?: string;\n sku?: string; // Legacy field name\n quantity?: number;\n idempotencyKey?: string;\n paymentMethod?: string;\n metadata?: Record<string, any>;\n }): Promise<any> {\n const response = await this.apiCall('/v1/purchases', {\n method: 'POST',\n body: params,\n headers: params.idempotencyKey ? {\n 'Idempotency-Key': params.idempotencyKey,\n } : undefined,\n });\n return response.json();\n }\n\n /**\n * NFT Template Operations\n */\n\n /**\n * Get all NFT templates for a game\n */\n async getNftTemplates(gameId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\n return response.json();\n }\n\n /**\n * Get NFT contract address for a game\n */\n async getNftContract(gameId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\n return response.json();\n }\n\n /**\n * Mint NFTs (single or batch)\n */\n async mintNfts(params: {\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * Batch mint NFTs\n */\n async batchMintNfts(mints: Array<{\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }>): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint/batch', {\n method: 'POST',\n body: { mints },\n });\n return response.json();\n }\n\n /**\n * Update NFT metadata\n */\n async updateNftMetadata(\n tokenId: string,\n metadata: {\n attributes?: Record<string, string | number | boolean>;\n name?: string;\n description?: string;\n imageUrl?: string;\n }\n ): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\n method: 'PUT',\n body: metadata,\n });\n return response.json();\n }\n\n /**\n * Burn NFT (single)\n */\n async burnNft(tokenId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\n method: 'DELETE',\n });\n return response.json();\n }\n\n /**\n * Batch burn NFTs\n */\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\n const response = await this.apiCall('/v1/nfts/burn/batch', {\n method: 'POST',\n body: { tokenIds },\n });\n return response.json();\n }\n\n /**\n * Pack opener - mint random NFTs from a drop table\n */\n async packOpener(params: {\n dropTableId: string;\n recipientAddress: string;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/pack-opener', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * VIP Points (Developer pool)\n * Requires scope: vip_points:write.\n * Grants VIP points to a player from this game's allocated pool. Enforces total allocation and max per quest.\n * Call from your game backend only (API key auth); not for client-side use.\n */\n async grantVipPoints(params: {\n /** Player wallet address (0x-prefixed, 40 hex chars). */\n wallet: string;\n /** Points to grant (positive integer). Capped by pool remaining and max per quest. */\n amount: number;\n /** Optional quest/activity id for idempotency or auditing. */\n questId?: string;\n }): Promise<{ success: boolean; data?: { wallet: string; amount: number; phaseIndex?: number } }> {\n const response = await this.apiCall('/v1/vip/grant-points', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts","../src/realtime.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { OAuthTokenResponse, OAuthOptions } from './types';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (token: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth 2.0 Authorization Code Grant with PKCE\r\n */\r\n async authenticate(options: OAuthOptions = {}): Promise<OAuthTokenResponse> {\r\n // Generate state for CSRF protection\r\n const state = this.generateState();\r\n \r\n // Generate PKCE code verifier and challenge\r\n const codeVerifier = this.generateCodeVerifier();\r\n const codeChallenge = await this.generateCodeChallenge(codeVerifier);\r\n \r\n return new Promise((resolve, reject) => {\r\n \r\n // Store code verifier in sessionStorage for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n \r\n // Build authorization URL\r\n const redirectUri = options.redirectUri || `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(this.config.oauthAuthorizeUrl);\r\n authUrl.searchParams.set('client_id', this.config.gameId);\r\n authUrl.searchParams.set('redirect_uri', redirectUri);\r\n authUrl.searchParams.set('response_type', 'code');\r\n authUrl.searchParams.set('scope', 'openid profile email');\r\n authUrl.searchParams.set('state', state);\r\n authUrl.searchParams.set('code_challenge', codeChallenge);\r\n authUrl.searchParams.set('code_challenge_method', 'S256');\r\n \r\n // Store state for verification\r\n const stateStorageKey = `omenx_oauth_state_${state}`;\r\n sessionStorage.setItem(stateStorageKey, state);\r\n \r\n // Open popup window\r\n const popup = window.open(\r\n authUrl.toString(),\r\n 'OmenX OAuth',\r\n 'width=500,height=600,left=100,top=100'\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Clean up old OAuth callback entries from localStorage\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n }\r\n }\r\n } catch (e) {\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n // Ignore cleanup errors\r\n }\r\n\r\n // Poll localStorage for callback data\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n let messageReceived = false;\r\n \r\n const pollInterval = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(pollInterval);\r\n return;\r\n }\r\n \r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Validate state and check timestamp\r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n localStorage.removeItem(storageKey);\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(data.code, redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n // Close popup after successful token exchange\r\n if (popup && !popup.closed) {\r\n try {\r\n popup.close();\r\n } catch (e) {\r\n // Ignore errors closing popup\r\n }\r\n }\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n return;\r\n } else {\r\n // Data too old, remove it\r\n localStorage.removeItem(storageKey);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error parsing localStorage callback:', error);\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Check if popup was closed without completing auth\r\n const checkClosed = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(checkClosed);\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed\r\n let isClosed = false;\r\n try {\r\n if (popup.closed) {\r\n try {\r\n // Try to access location to verify it's actually closed\r\n popup.location.href; // Accessing this will throw if popup is on different origin\r\n isClosed = true;\r\n } catch (e) {\r\n // Can't access location - popup is on different origin (still open)\r\n isClosed = false;\r\n }\r\n }\r\n } catch (e) {\r\n isClosed = false;\r\n }\r\n \r\n if (isClosed) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n client_id: this.config.gameId,\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code verifier\r\n */\r\n private generateCodeVerifier(): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(128);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code challenge from verifier\r\n */\r\n private async generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const hash = await crypto.subtle.digest('SHA-256', data);\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n VipStatus,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n const tokenResponse = await this.oauthFlow.authenticate(options);\r\n // Convert OAuthTokenResponse to AuthData\r\n return {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Get current VIP status for the authenticated user (tier, allocation, claimable, perks).\r\n * Games can read tier.gameBonusPointsLevel (1–21) for Alpha/Beta access or in-game gifts.\r\n */\r\n async getVipStatus(): Promise<VipStatus | null> {\r\n const response = await this.apiCall('/api/vip/me');\r\n if (!response.ok) return null;\r\n const data = await response.json();\r\n if (data.success && data.data) return data.data as VipStatus;\r\n return null;\r\n }\r\n\r\n /**\r\n * Get the current user's game bonus points level (1–21) from their VIP tier.\r\n * Use for Game Alpha Access (e.g. level >= 6), Game Beta Access (e.g. level >= 1), or in-game gifts.\r\n */\r\n async getGameBonusPointsLevel(): Promise<number | null> {\r\n const status = await this.getVipStatus();\r\n if (!status?.tier) return null;\r\n const level = status.tier.gameBonusPointsLevel ?? (status.tier.perks?.GAME_BONUS_POINTS_LEVEL as number);\r\n return typeof level === 'number' && level >= 1 && level <= 21 ? level : null;\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\n\ninterface ServerSDKConfig {\n /**\n * Your developer API key (from developer portal)\n */\n apiKey: string;\n\n /**\n * OmenX API base URL (default: https://api.omen.foundation)\n */\n apiBaseUrl?: string;\n}\n\n/**\n * OmenX Game SDK - Server Mode\n * \n * For Node.js backends using developer API keys.\n * This mode allows server-to-server communication with the OmenX API.\n */\nexport class OmenXServerSDK {\n private config: Required<ServerSDKConfig>;\n private apiKey: string;\n\n constructor(config: ServerSDKConfig) {\n this.apiKey = config.apiKey;\n this.config = {\n apiKey: config.apiKey,\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\n };\n }\n\n /**\n * Make an authenticated API call using the developer API key\n */\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\n const url = endpoint.startsWith('http') \n ? endpoint \n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...options.headers,\n };\n\n const fetchOptions: RequestInit = {\n method: options.method || 'GET',\n headers,\n };\n\n if (options.body && options.method !== 'GET') {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\n }\n\n return response;\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<any> {\n const response = await this.apiCall('/v1/health', { includeAuth: false });\n return response.json();\n }\n\n /**\n * Get API key information\n */\n async getApiKeyInfo(): Promise<any> {\n const response = await this.apiCall('/v1/auth/me');\n return response.json();\n }\n\n /**\n * Player Operations\n */\n\n /**\n * Get full player data: NFTs (system + game) and balances for a wallet.\n * Requires both nfts:read and balances:read scopes.\n */\n async getPlayer(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get native and ERC20 token balances for a wallet\n */\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/balances?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get paginated NFTs for a wallet.\n * With no contract: returns OmenX system NFTs (Asset Manager, Faucet, Early Adopter) + game NFTs.\n * With contract: returns only NFTs for that contract.\n */\n async getPlayerNfts(\n wallet: string,\n chainId: string,\n options?: {\n contract?: string;\n cursor?: string;\n limit?: number;\n }\n ): Promise<any> {\n const params = new URLSearchParams({ chainId });\n if (options?.contract) params.set('contract', options.contract);\n if (options?.cursor) params.set('cursor', options.cursor);\n if (options?.limit != null) params.set('limit', String(options.limit));\n\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/nfts?${params.toString()}`\n );\n return response.json();\n }\n\n /**\n * Purchase Operations\n */\n\n /**\n * Create a server-authoritative purchase\n */\n async createPurchase(params: {\n playerWallet?: string;\n walletAddress?: string; // Legacy field name\n skuId?: string;\n sku?: string; // Legacy field name\n quantity?: number;\n idempotencyKey?: string;\n paymentMethod?: string;\n metadata?: Record<string, any>;\n }): Promise<any> {\n const response = await this.apiCall('/v1/purchases', {\n method: 'POST',\n body: params,\n headers: params.idempotencyKey ? {\n 'Idempotency-Key': params.idempotencyKey,\n } : undefined,\n });\n return response.json();\n }\n\n /**\n * NFT Template Operations\n */\n\n /**\n * Get all NFT templates for the authenticated game (game is derived from API key).\n * gameId is optional and ignored by the API; included for backward compatibility.\n */\n async getNftTemplates(_gameId?: string): Promise<any> {\n const response = await this.apiCall('/v1/nfts/templates');\n return response.json();\n }\n\n /**\n * Get NFT contract address for the authenticated game (game is derived from API key).\n * gameId is optional and ignored by the API; included for backward compatibility.\n */\n async getNftContract(_gameId?: string): Promise<any> {\n const response = await this.apiCall('/v1/nfts/contract');\n return response.json();\n }\n\n /**\n * Mint NFTs (single or batch)\n */\n async mintNfts(params: {\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * Batch mint NFTs\n */\n async batchMintNfts(mints: Array<{\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }>): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint/batch', {\n method: 'POST',\n body: { mints },\n });\n return response.json();\n }\n\n /**\n * Update NFT metadata\n */\n async updateNftMetadata(\n tokenId: string,\n metadata: {\n attributes?: Record<string, string | number | boolean>;\n name?: string;\n description?: string;\n imageUrl?: string;\n }\n ): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\n method: 'PUT',\n body: metadata,\n });\n return response.json();\n }\n\n /**\n * Burn NFT (single)\n */\n async burnNft(tokenId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\n method: 'DELETE',\n });\n return response.json();\n }\n\n /**\n * Batch burn NFTs\n */\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\n const response = await this.apiCall('/v1/nfts/burn/batch', {\n method: 'POST',\n body: { tokenIds },\n });\n return response.json();\n }\n\n /**\n * Pack opener - mint random NFTs from a drop table\n */\n async packOpener(params: {\n dropTableId: string;\n recipientAddress: string;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/pack-opener', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * VIP Points (Developer pool)\n * Requires scope: vip_points:write.\n * Grants VIP points to a player from this game's allocated pool. Enforces total allocation and max per quest.\n * Call from your game backend only (API key auth); not for client-side use.\n */\n async grantVipPoints(params: {\n /** Player wallet address (0x-prefixed, 40 hex chars). */\n wallet: string;\n /** Points to grant (positive integer). Capped by pool remaining and max per quest. */\n amount: number;\n /** Optional quest/activity id for idempotency or auditing. */\n questId?: string;\n }): Promise<{ success: boolean; data?: { wallet: string; amount: number; phaseIndex?: number } }> {\n const response = await this.apiCall('/v1/vip/grant-points', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * Quests API (game quests only).\n * Requires scope: quests:read for getQuestsForPlayer; quests:write for assign, progress, complete, claim.\n */\n\n /** Get assigned quests for a player. Optional questType filter. */\n async getQuestsForPlayer(\n wallet: string,\n options?: { questType?: 'daily' | 'weekly' | 'monthly' | 'oneTime' }\n ): Promise<{ success: boolean; data: { quests: any[] } }> {\n const q = options?.questType ? `?questType=${options.questType}` : '';\n const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}${q}`);\n return response.json();\n }\n\n /** Assign quests of a type to a player. Use idempotencyKey for safe retries. */\n async assignQuests(\n wallet: string,\n questType: 'daily' | 'weekly' | 'monthly' | 'oneTime',\n count: number,\n options?: { idempotencyKey?: string }\n ): Promise<{ success: boolean; data: { assigned: number; assignmentIds?: string[] } }> {\n const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}/assign`, {\n method: 'POST',\n body: { questType, count },\n headers: options?.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : undefined,\n });\n return response.json();\n }\n\n /** Report progress for a quest step. Quest auto-completes when all steps meet targets. */\n async reportQuestProgress(\n wallet: string,\n questKey: string,\n value: number,\n options?: { stepKey?: string }\n ): Promise<{ success: boolean; data?: object }> {\n const response = await this.apiCall('/v1/quests/progress', {\n method: 'POST',\n body: { wallet, questKey, value, stepKey: options?.stepKey },\n });\n return response.json();\n }\n\n /** Mark a quest complete (all steps set to targets). */\n async completeQuest(wallet: string, questKey: string): Promise<{ success: boolean; data?: object }> {\n const response = await this.apiCall('/v1/quests/complete', {\n method: 'POST',\n body: { wallet, questKey },\n });\n return response.json();\n }\n\n /** Claim VIP reward for a completed quest (from game pool). Use idempotencyKey for safe retries. */\n async claimQuestReward(\n wallet: string,\n questKey: string,\n options?: { idempotencyKey?: string }\n ): Promise<{ success: boolean; data?: { pointsGranted?: number } }> {\n const response = await this.apiCall('/v1/quests/claim', {\n method: 'POST',\n body: { wallet, questKey },\n headers: options?.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : undefined,\n });\n return response.json();\n }\n\n /**\n * Reset or wipe a player's quest state for this game. Requires quests:write.\n * - wipe: delete all quest assignments for this game for the player.\n * - reset: delete assignments for the specified questKey only (questKey required).\n */\n async resetPlayerQuests(\n wallet: string,\n action: 'wipe' | 'reset',\n questKey?: string\n ): Promise<{ success: boolean; data: { action: string; deleted: number; questKey?: string } }> {\n const body: { action: 'wipe' | 'reset'; questKey?: string } = { action };\n if (action === 'reset' && questKey) body.questKey = questKey;\n const response = await this.apiCall('/v1/quests/players/' + encodeURIComponent(wallet) + '/reset', {\n method: 'POST',\n body,\n });\n return response.json();\n }\n}\n","/**\r\n * Real-time wallet updates (balance & inventory) for game clients.\r\n * Subscribe to the per-wallet Ably channel so the game stays in sync when the user\r\n * spends or receives OmenX / NFTs on the website or in another client.\r\n *\r\n * Requires the app to install `ably` and pass an Ably Realtime instance.\r\n */\r\n\r\n/** Payload for balance and inventory events. Use eventId for idempotency (ignore if already processed). */\r\nexport interface RealtimeWalletPayload {\r\n eventId: string;\r\n timestamp: number;\r\n reason?: string;\r\n}\r\n\r\n/** Ably channel name prefix. Full channel = \"wallet:\" + normalized wallet address. */\r\nexport const WALLET_CHANNEL_PREFIX = 'wallet:';\r\n\r\n/** Event names published by the OmenX backend on the wallet channel. */\r\nexport const REALTIME_EVENTS = {\r\n /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */\r\n balance: 'balance',\r\n /** NFT/inventory changed. Refetch via GetPlayerNfts or your inventory API (cache is source of truth). */\r\n inventory: 'inventory',\r\n} as const;\r\n\r\nconst MAX_SEEN_IDS = 200;\r\n\r\n/**\r\n * Normalize wallet address for channel name (lowercase, no 0x prefix change).\r\n */\r\nfunction normalizeWallet(wallet: string): string {\r\n return (wallet || '').trim().toLowerCase();\r\n}\r\n\r\n/**\r\n * Get the Ably channel name for a wallet. Use this when subscribing with your Ably client.\r\n */\r\nexport function getWalletChannelName(walletAddress: string): string {\r\n return WALLET_CHANNEL_PREFIX + normalizeWallet(walletAddress);\r\n}\r\n\r\n/**\r\n * Minimal Ably Realtime interface so the SDK works with any Ably.Realtime instance.\r\n * The app provides the real Ably client from AblyProvider or new Ably.Realtime({ key }).\r\n */\r\nexport interface AblyRealtimeLike {\r\n channels: {\r\n get(name: string): {\r\n subscribe(eventOrCallback: string | ((message: { name: string; data: unknown }) => void), callback?: (message: { name: string; data: unknown }) => void): void;\r\n unsubscribe(eventOrCallback?: string | ((message: { name: string; data: unknown }) => void), callback?: (message: { name: string; data: unknown }) => void): void;\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Subscribe to real-time balance and inventory events for a wallet.\r\n * Call when the user logs in; call the returned unsubscribe when they log out or wallet changes.\r\n *\r\n * Uses eventId to dedupe (ignores already-seen events). Refetch in your app on each callback.\r\n *\r\n * @param ably - Ably Realtime instance (e.g. from useAbly() or new Ably.Realtime({ key }))\r\n * @param walletAddress - Current player wallet (0x...)\r\n * @param callbacks - onBalance and/or onInventory; each receives the payload (eventId, timestamp, reason?)\r\n * @returns Unsubscribe function\r\n */\r\nexport function subscribeWalletRealtime(\r\n ably: AblyRealtimeLike,\r\n walletAddress: string,\r\n callbacks: {\r\n onBalance?: (payload: RealtimeWalletPayload) => void;\r\n onInventory?: (payload: RealtimeWalletPayload) => void;\r\n }\r\n): () => void {\r\n const normalized = normalizeWallet(walletAddress);\r\n if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {\r\n return () => {};\r\n }\r\n\r\n const seenIds = new Set<string>();\r\n\r\n const handleMessage = (message: { name: string; data: unknown }) => {\r\n const data = message.data as RealtimeWalletPayload | undefined;\r\n if (!data || typeof data !== 'object' || typeof data.eventId !== 'string') return;\r\n if (seenIds.has(data.eventId)) return;\r\n if (seenIds.size >= MAX_SEEN_IDS) {\r\n const first = seenIds.values().next().value;\r\n if (first != null) seenIds.delete(first);\r\n }\r\n seenIds.add(data.eventId);\r\n\r\n if (message.name === REALTIME_EVENTS.balance && callbacks.onBalance) {\r\n callbacks.onBalance(data);\r\n } else if (message.name === REALTIME_EVENTS.inventory && callbacks.onInventory) {\r\n callbacks.onInventory(data);\r\n }\r\n };\r\n\r\n const channel = ably.channels.get(getWalletChannelName(normalized));\r\n channel.subscribe(handleMessage);\r\n\r\n return () => {\r\n channel.unsubscribe(handleMessage);\r\n };\r\n}\r\n"]}
package/dist/index.mjs CHANGED
@@ -628,17 +628,19 @@ var OmenXServerSDK = class {
628
628
  * NFT Template Operations
629
629
  */
630
630
  /**
631
- * Get all NFT templates for a game
631
+ * Get all NFT templates for the authenticated game (game is derived from API key).
632
+ * gameId is optional and ignored by the API; included for backward compatibility.
632
633
  */
633
- async getNftTemplates(gameId) {
634
- const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);
634
+ async getNftTemplates(_gameId) {
635
+ const response = await this.apiCall("/v1/nfts/templates");
635
636
  return response.json();
636
637
  }
637
638
  /**
638
- * Get NFT contract address for a game
639
+ * Get NFT contract address for the authenticated game (game is derived from API key).
640
+ * gameId is optional and ignored by the API; included for backward compatibility.
639
641
  */
640
- async getNftContract(gameId) {
641
- const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);
642
+ async getNftContract(_gameId) {
643
+ const response = await this.apiCall("/v1/nfts/contract");
642
644
  return response.json();
643
645
  }
644
646
  /**
@@ -713,8 +715,110 @@ var OmenXServerSDK = class {
713
715
  });
714
716
  return response.json();
715
717
  }
718
+ /**
719
+ * Quests API (game quests only).
720
+ * Requires scope: quests:read for getQuestsForPlayer; quests:write for assign, progress, complete, claim.
721
+ */
722
+ /** Get assigned quests for a player. Optional questType filter. */
723
+ async getQuestsForPlayer(wallet, options) {
724
+ const q = options?.questType ? `?questType=${options.questType}` : "";
725
+ const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}${q}`);
726
+ return response.json();
727
+ }
728
+ /** Assign quests of a type to a player. Use idempotencyKey for safe retries. */
729
+ async assignQuests(wallet, questType, count, options) {
730
+ const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}/assign`, {
731
+ method: "POST",
732
+ body: { questType, count },
733
+ headers: options?.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : void 0
734
+ });
735
+ return response.json();
736
+ }
737
+ /** Report progress for a quest step. Quest auto-completes when all steps meet targets. */
738
+ async reportQuestProgress(wallet, questKey, value, options) {
739
+ const response = await this.apiCall("/v1/quests/progress", {
740
+ method: "POST",
741
+ body: { wallet, questKey, value, stepKey: options?.stepKey }
742
+ });
743
+ return response.json();
744
+ }
745
+ /** Mark a quest complete (all steps set to targets). */
746
+ async completeQuest(wallet, questKey) {
747
+ const response = await this.apiCall("/v1/quests/complete", {
748
+ method: "POST",
749
+ body: { wallet, questKey }
750
+ });
751
+ return response.json();
752
+ }
753
+ /** Claim VIP reward for a completed quest (from game pool). Use idempotencyKey for safe retries. */
754
+ async claimQuestReward(wallet, questKey, options) {
755
+ const response = await this.apiCall("/v1/quests/claim", {
756
+ method: "POST",
757
+ body: { wallet, questKey },
758
+ headers: options?.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : void 0
759
+ });
760
+ return response.json();
761
+ }
762
+ /**
763
+ * Reset or wipe a player's quest state for this game. Requires quests:write.
764
+ * - wipe: delete all quest assignments for this game for the player.
765
+ * - reset: delete assignments for the specified questKey only (questKey required).
766
+ */
767
+ async resetPlayerQuests(wallet, action, questKey) {
768
+ const body = { action };
769
+ if (action === "reset" && questKey) body.questKey = questKey;
770
+ const response = await this.apiCall("/v1/quests/players/" + encodeURIComponent(wallet) + "/reset", {
771
+ method: "POST",
772
+ body
773
+ });
774
+ return response.json();
775
+ }
776
+ };
777
+
778
+ // src/realtime.ts
779
+ var WALLET_CHANNEL_PREFIX = "wallet:";
780
+ var REALTIME_EVENTS = {
781
+ /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */
782
+ balance: "balance",
783
+ /** NFT/inventory changed. Refetch via GetPlayerNfts or your inventory API (cache is source of truth). */
784
+ inventory: "inventory"
716
785
  };
786
+ var MAX_SEEN_IDS = 200;
787
+ function normalizeWallet(wallet) {
788
+ return (wallet || "").trim().toLowerCase();
789
+ }
790
+ function getWalletChannelName(walletAddress) {
791
+ return WALLET_CHANNEL_PREFIX + normalizeWallet(walletAddress);
792
+ }
793
+ function subscribeWalletRealtime(ably, walletAddress, callbacks) {
794
+ const normalized = normalizeWallet(walletAddress);
795
+ if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {
796
+ return () => {
797
+ };
798
+ }
799
+ const seenIds = /* @__PURE__ */ new Set();
800
+ const handleMessage = (message) => {
801
+ const data = message.data;
802
+ if (!data || typeof data !== "object" || typeof data.eventId !== "string") return;
803
+ if (seenIds.has(data.eventId)) return;
804
+ if (seenIds.size >= MAX_SEEN_IDS) {
805
+ const first = seenIds.values().next().value;
806
+ if (first != null) seenIds.delete(first);
807
+ }
808
+ seenIds.add(data.eventId);
809
+ if (message.name === REALTIME_EVENTS.balance && callbacks.onBalance) {
810
+ callbacks.onBalance(data);
811
+ } else if (message.name === REALTIME_EVENTS.inventory && callbacks.onInventory) {
812
+ callbacks.onInventory(data);
813
+ }
814
+ };
815
+ const channel = ably.channels.get(getWalletChannelName(normalized));
816
+ channel.subscribe(handleMessage);
817
+ return () => {
818
+ channel.unsubscribe(handleMessage);
819
+ };
820
+ }
717
821
 
718
- export { OmenXGameSDK, OmenXServerSDK };
822
+ export { OmenXGameSDK, OmenXServerSDK, REALTIME_EVENTS, WALLET_CHANNEL_PREFIX, getWalletChannelName, subscribeWalletRealtime };
719
823
  //# sourceMappingURL=index.mjs.map
720
824
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { OAuthTokenResponse, OAuthOptions } from './types';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (token: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth 2.0 Authorization Code Grant with PKCE\r\n */\r\n async authenticate(options: OAuthOptions = {}): Promise<OAuthTokenResponse> {\r\n // Generate state for CSRF protection\r\n const state = this.generateState();\r\n \r\n // Generate PKCE code verifier and challenge\r\n const codeVerifier = this.generateCodeVerifier();\r\n const codeChallenge = await this.generateCodeChallenge(codeVerifier);\r\n \r\n return new Promise((resolve, reject) => {\r\n \r\n // Store code verifier in sessionStorage for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n \r\n // Build authorization URL\r\n const redirectUri = options.redirectUri || `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(this.config.oauthAuthorizeUrl);\r\n authUrl.searchParams.set('client_id', this.config.gameId);\r\n authUrl.searchParams.set('redirect_uri', redirectUri);\r\n authUrl.searchParams.set('response_type', 'code');\r\n authUrl.searchParams.set('scope', 'openid profile email');\r\n authUrl.searchParams.set('state', state);\r\n authUrl.searchParams.set('code_challenge', codeChallenge);\r\n authUrl.searchParams.set('code_challenge_method', 'S256');\r\n \r\n // Store state for verification\r\n const stateStorageKey = `omenx_oauth_state_${state}`;\r\n sessionStorage.setItem(stateStorageKey, state);\r\n \r\n // Open popup window\r\n const popup = window.open(\r\n authUrl.toString(),\r\n 'OmenX OAuth',\r\n 'width=500,height=600,left=100,top=100'\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Clean up old OAuth callback entries from localStorage\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n }\r\n }\r\n } catch (e) {\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n // Ignore cleanup errors\r\n }\r\n\r\n // Poll localStorage for callback data\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n let messageReceived = false;\r\n \r\n const pollInterval = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(pollInterval);\r\n return;\r\n }\r\n \r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Validate state and check timestamp\r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n localStorage.removeItem(storageKey);\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(data.code, redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n // Close popup after successful token exchange\r\n if (popup && !popup.closed) {\r\n try {\r\n popup.close();\r\n } catch (e) {\r\n // Ignore errors closing popup\r\n }\r\n }\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n return;\r\n } else {\r\n // Data too old, remove it\r\n localStorage.removeItem(storageKey);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error parsing localStorage callback:', error);\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Check if popup was closed without completing auth\r\n const checkClosed = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(checkClosed);\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed\r\n let isClosed = false;\r\n try {\r\n if (popup.closed) {\r\n try {\r\n // Try to access location to verify it's actually closed\r\n popup.location.href; // Accessing this will throw if popup is on different origin\r\n isClosed = true;\r\n } catch (e) {\r\n // Can't access location - popup is on different origin (still open)\r\n isClosed = false;\r\n }\r\n }\r\n } catch (e) {\r\n isClosed = false;\r\n }\r\n \r\n if (isClosed) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n client_id: this.config.gameId,\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code verifier\r\n */\r\n private generateCodeVerifier(): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(128);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code challenge from verifier\r\n */\r\n private async generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const hash = await crypto.subtle.digest('SHA-256', data);\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n VipStatus,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n const tokenResponse = await this.oauthFlow.authenticate(options);\r\n // Convert OAuthTokenResponse to AuthData\r\n return {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Get current VIP status for the authenticated user (tier, allocation, claimable, perks).\r\n * Games can read tier.gameBonusPointsLevel (1–21) for Alpha/Beta access or in-game gifts.\r\n */\r\n async getVipStatus(): Promise<VipStatus | null> {\r\n const response = await this.apiCall('/api/vip/me');\r\n if (!response.ok) return null;\r\n const data = await response.json();\r\n if (data.success && data.data) return data.data as VipStatus;\r\n return null;\r\n }\r\n\r\n /**\r\n * Get the current user's game bonus points level (1–21) from their VIP tier.\r\n * Use for Game Alpha Access (e.g. level >= 6), Game Beta Access (e.g. level >= 1), or in-game gifts.\r\n */\r\n async getGameBonusPointsLevel(): Promise<number | null> {\r\n const status = await this.getVipStatus();\r\n if (!status?.tier) return null;\r\n const level = status.tier.gameBonusPointsLevel ?? (status.tier.perks?.GAME_BONUS_POINTS_LEVEL as number);\r\n return typeof level === 'number' && level >= 1 && level <= 21 ? level : null;\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\n\ninterface ServerSDKConfig {\n /**\n * Your developer API key (from developer portal)\n */\n apiKey: string;\n\n /**\n * OmenX API base URL (default: https://api.omen.foundation)\n */\n apiBaseUrl?: string;\n}\n\n/**\n * OmenX Game SDK - Server Mode\n * \n * For Node.js backends using developer API keys.\n * This mode allows server-to-server communication with the OmenX API.\n */\nexport class OmenXServerSDK {\n private config: Required<ServerSDKConfig>;\n private apiKey: string;\n\n constructor(config: ServerSDKConfig) {\n this.apiKey = config.apiKey;\n this.config = {\n apiKey: config.apiKey,\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\n };\n }\n\n /**\n * Make an authenticated API call using the developer API key\n */\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\n const url = endpoint.startsWith('http') \n ? endpoint \n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...options.headers,\n };\n\n const fetchOptions: RequestInit = {\n method: options.method || 'GET',\n headers,\n };\n\n if (options.body && options.method !== 'GET') {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\n }\n\n return response;\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<any> {\n const response = await this.apiCall('/v1/health', { includeAuth: false });\n return response.json();\n }\n\n /**\n * Get API key information\n */\n async getApiKeyInfo(): Promise<any> {\n const response = await this.apiCall('/v1/auth/me');\n return response.json();\n }\n\n /**\n * Player Operations\n */\n\n /**\n * Get full player data: NFTs (system + game) and balances for a wallet.\n * Requires both nfts:read and balances:read scopes.\n */\n async getPlayer(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get native and ERC20 token balances for a wallet\n */\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/balances?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get paginated NFTs for a wallet.\n * With no contract: returns OmenX system NFTs (Asset Manager, Faucet, Early Adopter) + game NFTs.\n * With contract: returns only NFTs for that contract.\n */\n async getPlayerNfts(\n wallet: string,\n chainId: string,\n options?: {\n contract?: string;\n cursor?: string;\n limit?: number;\n }\n ): Promise<any> {\n const params = new URLSearchParams({ chainId });\n if (options?.contract) params.set('contract', options.contract);\n if (options?.cursor) params.set('cursor', options.cursor);\n if (options?.limit != null) params.set('limit', String(options.limit));\n\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/nfts?${params.toString()}`\n );\n return response.json();\n }\n\n /**\n * Purchase Operations\n */\n\n /**\n * Create a server-authoritative purchase\n */\n async createPurchase(params: {\n playerWallet?: string;\n walletAddress?: string; // Legacy field name\n skuId?: string;\n sku?: string; // Legacy field name\n quantity?: number;\n idempotencyKey?: string;\n paymentMethod?: string;\n metadata?: Record<string, any>;\n }): Promise<any> {\n const response = await this.apiCall('/v1/purchases', {\n method: 'POST',\n body: params,\n headers: params.idempotencyKey ? {\n 'Idempotency-Key': params.idempotencyKey,\n } : undefined,\n });\n return response.json();\n }\n\n /**\n * NFT Template Operations\n */\n\n /**\n * Get all NFT templates for a game\n */\n async getNftTemplates(gameId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\n return response.json();\n }\n\n /**\n * Get NFT contract address for a game\n */\n async getNftContract(gameId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\n return response.json();\n }\n\n /**\n * Mint NFTs (single or batch)\n */\n async mintNfts(params: {\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * Batch mint NFTs\n */\n async batchMintNfts(mints: Array<{\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }>): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint/batch', {\n method: 'POST',\n body: { mints },\n });\n return response.json();\n }\n\n /**\n * Update NFT metadata\n */\n async updateNftMetadata(\n tokenId: string,\n metadata: {\n attributes?: Record<string, string | number | boolean>;\n name?: string;\n description?: string;\n imageUrl?: string;\n }\n ): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\n method: 'PUT',\n body: metadata,\n });\n return response.json();\n }\n\n /**\n * Burn NFT (single)\n */\n async burnNft(tokenId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\n method: 'DELETE',\n });\n return response.json();\n }\n\n /**\n * Batch burn NFTs\n */\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\n const response = await this.apiCall('/v1/nfts/burn/batch', {\n method: 'POST',\n body: { tokenIds },\n });\n return response.json();\n }\n\n /**\n * Pack opener - mint random NFTs from a drop table\n */\n async packOpener(params: {\n dropTableId: string;\n recipientAddress: string;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/pack-opener', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * VIP Points (Developer pool)\n * Requires scope: vip_points:write.\n * Grants VIP points to a player from this game's allocated pool. Enforces total allocation and max per quest.\n * Call from your game backend only (API key auth); not for client-side use.\n */\n async grantVipPoints(params: {\n /** Player wallet address (0x-prefixed, 40 hex chars). */\n wallet: string;\n /** Points to grant (positive integer). Capped by pool remaining and max per quest. */\n amount: number;\n /** Optional quest/activity id for idempotency or auditing. */\n questId?: string;\n }): Promise<{ success: boolean; data?: { wallet: string; amount: number; phaseIndex?: number } }> {\n const response = await this.apiCall('/v1/vip/grant-points', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts","../src/realtime.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { OAuthTokenResponse, OAuthOptions } from './types';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (token: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth 2.0 Authorization Code Grant with PKCE\r\n */\r\n async authenticate(options: OAuthOptions = {}): Promise<OAuthTokenResponse> {\r\n // Generate state for CSRF protection\r\n const state = this.generateState();\r\n \r\n // Generate PKCE code verifier and challenge\r\n const codeVerifier = this.generateCodeVerifier();\r\n const codeChallenge = await this.generateCodeChallenge(codeVerifier);\r\n \r\n return new Promise((resolve, reject) => {\r\n \r\n // Store code verifier in sessionStorage for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n \r\n // Build authorization URL\r\n const redirectUri = options.redirectUri || `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(this.config.oauthAuthorizeUrl);\r\n authUrl.searchParams.set('client_id', this.config.gameId);\r\n authUrl.searchParams.set('redirect_uri', redirectUri);\r\n authUrl.searchParams.set('response_type', 'code');\r\n authUrl.searchParams.set('scope', 'openid profile email');\r\n authUrl.searchParams.set('state', state);\r\n authUrl.searchParams.set('code_challenge', codeChallenge);\r\n authUrl.searchParams.set('code_challenge_method', 'S256');\r\n \r\n // Store state for verification\r\n const stateStorageKey = `omenx_oauth_state_${state}`;\r\n sessionStorage.setItem(stateStorageKey, state);\r\n \r\n // Open popup window\r\n const popup = window.open(\r\n authUrl.toString(),\r\n 'OmenX OAuth',\r\n 'width=500,height=600,left=100,top=100'\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Clean up old OAuth callback entries from localStorage\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n }\r\n }\r\n } catch (e) {\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n // Ignore cleanup errors\r\n }\r\n\r\n // Poll localStorage for callback data\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n let messageReceived = false;\r\n \r\n const pollInterval = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(pollInterval);\r\n return;\r\n }\r\n \r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Validate state and check timestamp\r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n localStorage.removeItem(storageKey);\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(data.code, redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n // Close popup after successful token exchange\r\n if (popup && !popup.closed) {\r\n try {\r\n popup.close();\r\n } catch (e) {\r\n // Ignore errors closing popup\r\n }\r\n }\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n return;\r\n } else {\r\n // Data too old, remove it\r\n localStorage.removeItem(storageKey);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error parsing localStorage callback:', error);\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Check if popup was closed without completing auth\r\n const checkClosed = setInterval(() => {\r\n if (messageReceived) {\r\n clearInterval(checkClosed);\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed\r\n let isClosed = false;\r\n try {\r\n if (popup.closed) {\r\n try {\r\n // Try to access location to verify it's actually closed\r\n popup.location.href; // Accessing this will throw if popup is on different origin\r\n isClosed = true;\r\n } catch (e) {\r\n // Can't access location - popup is on different origin (still open)\r\n isClosed = false;\r\n }\r\n }\r\n } catch (e) {\r\n isClosed = false;\r\n }\r\n \r\n if (isClosed) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n \r\n // Clean up\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n sessionStorage.removeItem(stateStorageKey);\r\n \r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n client_id: this.config.gameId,\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code verifier\r\n */\r\n private generateCodeVerifier(): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(128);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n }\r\n\r\n /**\r\n * Generate PKCE code challenge from verifier\r\n */\r\n private async generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const hash = await crypto.subtle.digest('SHA-256', data);\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n VipStatus,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n const tokenResponse = await this.oauthFlow.authenticate(options);\r\n // Convert OAuthTokenResponse to AuthData\r\n return {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Get current VIP status for the authenticated user (tier, allocation, claimable, perks).\r\n * Games can read tier.gameBonusPointsLevel (1–21) for Alpha/Beta access or in-game gifts.\r\n */\r\n async getVipStatus(): Promise<VipStatus | null> {\r\n const response = await this.apiCall('/api/vip/me');\r\n if (!response.ok) return null;\r\n const data = await response.json();\r\n if (data.success && data.data) return data.data as VipStatus;\r\n return null;\r\n }\r\n\r\n /**\r\n * Get the current user's game bonus points level (1–21) from their VIP tier.\r\n * Use for Game Alpha Access (e.g. level >= 6), Game Beta Access (e.g. level >= 1), or in-game gifts.\r\n */\r\n async getGameBonusPointsLevel(): Promise<number | null> {\r\n const status = await this.getVipStatus();\r\n if (!status?.tier) return null;\r\n const level = status.tier.gameBonusPointsLevel ?? (status.tier.perks?.GAME_BONUS_POINTS_LEVEL as number);\r\n return typeof level === 'number' && level >= 1 && level <= 21 ? level : null;\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\n\ninterface ServerSDKConfig {\n /**\n * Your developer API key (from developer portal)\n */\n apiKey: string;\n\n /**\n * OmenX API base URL (default: https://api.omen.foundation)\n */\n apiBaseUrl?: string;\n}\n\n/**\n * OmenX Game SDK - Server Mode\n * \n * For Node.js backends using developer API keys.\n * This mode allows server-to-server communication with the OmenX API.\n */\nexport class OmenXServerSDK {\n private config: Required<ServerSDKConfig>;\n private apiKey: string;\n\n constructor(config: ServerSDKConfig) {\n this.apiKey = config.apiKey;\n this.config = {\n apiKey: config.apiKey,\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\n };\n }\n\n /**\n * Make an authenticated API call using the developer API key\n */\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\n const url = endpoint.startsWith('http') \n ? endpoint \n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n ...options.headers,\n };\n\n const fetchOptions: RequestInit = {\n method: options.method || 'GET',\n headers,\n };\n\n if (options.body && options.method !== 'GET') {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\n }\n\n return response;\n }\n\n /**\n * Health check\n */\n async healthCheck(): Promise<any> {\n const response = await this.apiCall('/v1/health', { includeAuth: false });\n return response.json();\n }\n\n /**\n * Get API key information\n */\n async getApiKeyInfo(): Promise<any> {\n const response = await this.apiCall('/v1/auth/me');\n return response.json();\n }\n\n /**\n * Player Operations\n */\n\n /**\n * Get full player data: NFTs (system + game) and balances for a wallet.\n * Requires both nfts:read and balances:read scopes.\n */\n async getPlayer(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get native and ERC20 token balances for a wallet\n */\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/balances?chainId=${encodeURIComponent(chainId)}`\n );\n return response.json();\n }\n\n /**\n * Get paginated NFTs for a wallet.\n * With no contract: returns OmenX system NFTs (Asset Manager, Faucet, Early Adopter) + game NFTs.\n * With contract: returns only NFTs for that contract.\n */\n async getPlayerNfts(\n wallet: string,\n chainId: string,\n options?: {\n contract?: string;\n cursor?: string;\n limit?: number;\n }\n ): Promise<any> {\n const params = new URLSearchParams({ chainId });\n if (options?.contract) params.set('contract', options.contract);\n if (options?.cursor) params.set('cursor', options.cursor);\n if (options?.limit != null) params.set('limit', String(options.limit));\n\n const response = await this.apiCall(\n `/v1/players/${encodeURIComponent(wallet)}/nfts?${params.toString()}`\n );\n return response.json();\n }\n\n /**\n * Purchase Operations\n */\n\n /**\n * Create a server-authoritative purchase\n */\n async createPurchase(params: {\n playerWallet?: string;\n walletAddress?: string; // Legacy field name\n skuId?: string;\n sku?: string; // Legacy field name\n quantity?: number;\n idempotencyKey?: string;\n paymentMethod?: string;\n metadata?: Record<string, any>;\n }): Promise<any> {\n const response = await this.apiCall('/v1/purchases', {\n method: 'POST',\n body: params,\n headers: params.idempotencyKey ? {\n 'Idempotency-Key': params.idempotencyKey,\n } : undefined,\n });\n return response.json();\n }\n\n /**\n * NFT Template Operations\n */\n\n /**\n * Get all NFT templates for the authenticated game (game is derived from API key).\n * gameId is optional and ignored by the API; included for backward compatibility.\n */\n async getNftTemplates(_gameId?: string): Promise<any> {\n const response = await this.apiCall('/v1/nfts/templates');\n return response.json();\n }\n\n /**\n * Get NFT contract address for the authenticated game (game is derived from API key).\n * gameId is optional and ignored by the API; included for backward compatibility.\n */\n async getNftContract(_gameId?: string): Promise<any> {\n const response = await this.apiCall('/v1/nfts/contract');\n return response.json();\n }\n\n /**\n * Mint NFTs (single or batch)\n */\n async mintNfts(params: {\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * Batch mint NFTs\n */\n async batchMintNfts(mints: Array<{\n templateId: string;\n recipientAddress: string;\n quantity: number;\n }>): Promise<any> {\n const response = await this.apiCall('/v1/nfts/mint/batch', {\n method: 'POST',\n body: { mints },\n });\n return response.json();\n }\n\n /**\n * Update NFT metadata\n */\n async updateNftMetadata(\n tokenId: string,\n metadata: {\n attributes?: Record<string, string | number | boolean>;\n name?: string;\n description?: string;\n imageUrl?: string;\n }\n ): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\n method: 'PUT',\n body: metadata,\n });\n return response.json();\n }\n\n /**\n * Burn NFT (single)\n */\n async burnNft(tokenId: string): Promise<any> {\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\n method: 'DELETE',\n });\n return response.json();\n }\n\n /**\n * Batch burn NFTs\n */\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\n const response = await this.apiCall('/v1/nfts/burn/batch', {\n method: 'POST',\n body: { tokenIds },\n });\n return response.json();\n }\n\n /**\n * Pack opener - mint random NFTs from a drop table\n */\n async packOpener(params: {\n dropTableId: string;\n recipientAddress: string;\n }): Promise<any> {\n const response = await this.apiCall('/v1/nfts/pack-opener', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * VIP Points (Developer pool)\n * Requires scope: vip_points:write.\n * Grants VIP points to a player from this game's allocated pool. Enforces total allocation and max per quest.\n * Call from your game backend only (API key auth); not for client-side use.\n */\n async grantVipPoints(params: {\n /** Player wallet address (0x-prefixed, 40 hex chars). */\n wallet: string;\n /** Points to grant (positive integer). Capped by pool remaining and max per quest. */\n amount: number;\n /** Optional quest/activity id for idempotency or auditing. */\n questId?: string;\n }): Promise<{ success: boolean; data?: { wallet: string; amount: number; phaseIndex?: number } }> {\n const response = await this.apiCall('/v1/vip/grant-points', {\n method: 'POST',\n body: params,\n });\n return response.json();\n }\n\n /**\n * Quests API (game quests only).\n * Requires scope: quests:read for getQuestsForPlayer; quests:write for assign, progress, complete, claim.\n */\n\n /** Get assigned quests for a player. Optional questType filter. */\n async getQuestsForPlayer(\n wallet: string,\n options?: { questType?: 'daily' | 'weekly' | 'monthly' | 'oneTime' }\n ): Promise<{ success: boolean; data: { quests: any[] } }> {\n const q = options?.questType ? `?questType=${options.questType}` : '';\n const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}${q}`);\n return response.json();\n }\n\n /** Assign quests of a type to a player. Use idempotencyKey for safe retries. */\n async assignQuests(\n wallet: string,\n questType: 'daily' | 'weekly' | 'monthly' | 'oneTime',\n count: number,\n options?: { idempotencyKey?: string }\n ): Promise<{ success: boolean; data: { assigned: number; assignmentIds?: string[] } }> {\n const response = await this.apiCall(`/v1/quests/players/${encodeURIComponent(wallet)}/assign`, {\n method: 'POST',\n body: { questType, count },\n headers: options?.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : undefined,\n });\n return response.json();\n }\n\n /** Report progress for a quest step. Quest auto-completes when all steps meet targets. */\n async reportQuestProgress(\n wallet: string,\n questKey: string,\n value: number,\n options?: { stepKey?: string }\n ): Promise<{ success: boolean; data?: object }> {\n const response = await this.apiCall('/v1/quests/progress', {\n method: 'POST',\n body: { wallet, questKey, value, stepKey: options?.stepKey },\n });\n return response.json();\n }\n\n /** Mark a quest complete (all steps set to targets). */\n async completeQuest(wallet: string, questKey: string): Promise<{ success: boolean; data?: object }> {\n const response = await this.apiCall('/v1/quests/complete', {\n method: 'POST',\n body: { wallet, questKey },\n });\n return response.json();\n }\n\n /** Claim VIP reward for a completed quest (from game pool). Use idempotencyKey for safe retries. */\n async claimQuestReward(\n wallet: string,\n questKey: string,\n options?: { idempotencyKey?: string }\n ): Promise<{ success: boolean; data?: { pointsGranted?: number } }> {\n const response = await this.apiCall('/v1/quests/claim', {\n method: 'POST',\n body: { wallet, questKey },\n headers: options?.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : undefined,\n });\n return response.json();\n }\n\n /**\n * Reset or wipe a player's quest state for this game. Requires quests:write.\n * - wipe: delete all quest assignments for this game for the player.\n * - reset: delete assignments for the specified questKey only (questKey required).\n */\n async resetPlayerQuests(\n wallet: string,\n action: 'wipe' | 'reset',\n questKey?: string\n ): Promise<{ success: boolean; data: { action: string; deleted: number; questKey?: string } }> {\n const body: { action: 'wipe' | 'reset'; questKey?: string } = { action };\n if (action === 'reset' && questKey) body.questKey = questKey;\n const response = await this.apiCall('/v1/quests/players/' + encodeURIComponent(wallet) + '/reset', {\n method: 'POST',\n body,\n });\n return response.json();\n }\n}\n","/**\r\n * Real-time wallet updates (balance & inventory) for game clients.\r\n * Subscribe to the per-wallet Ably channel so the game stays in sync when the user\r\n * spends or receives OmenX / NFTs on the website or in another client.\r\n *\r\n * Requires the app to install `ably` and pass an Ably Realtime instance.\r\n */\r\n\r\n/** Payload for balance and inventory events. Use eventId for idempotency (ignore if already processed). */\r\nexport interface RealtimeWalletPayload {\r\n eventId: string;\r\n timestamp: number;\r\n reason?: string;\r\n}\r\n\r\n/** Ably channel name prefix. Full channel = \"wallet:\" + normalized wallet address. */\r\nexport const WALLET_CHANNEL_PREFIX = 'wallet:';\r\n\r\n/** Event names published by the OmenX backend on the wallet channel. */\r\nexport const REALTIME_EVENTS = {\r\n /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */\r\n balance: 'balance',\r\n /** NFT/inventory changed. Refetch via GetPlayerNfts or your inventory API (cache is source of truth). */\r\n inventory: 'inventory',\r\n} as const;\r\n\r\nconst MAX_SEEN_IDS = 200;\r\n\r\n/**\r\n * Normalize wallet address for channel name (lowercase, no 0x prefix change).\r\n */\r\nfunction normalizeWallet(wallet: string): string {\r\n return (wallet || '').trim().toLowerCase();\r\n}\r\n\r\n/**\r\n * Get the Ably channel name for a wallet. Use this when subscribing with your Ably client.\r\n */\r\nexport function getWalletChannelName(walletAddress: string): string {\r\n return WALLET_CHANNEL_PREFIX + normalizeWallet(walletAddress);\r\n}\r\n\r\n/**\r\n * Minimal Ably Realtime interface so the SDK works with any Ably.Realtime instance.\r\n * The app provides the real Ably client from AblyProvider or new Ably.Realtime({ key }).\r\n */\r\nexport interface AblyRealtimeLike {\r\n channels: {\r\n get(name: string): {\r\n subscribe(eventOrCallback: string | ((message: { name: string; data: unknown }) => void), callback?: (message: { name: string; data: unknown }) => void): void;\r\n unsubscribe(eventOrCallback?: string | ((message: { name: string; data: unknown }) => void), callback?: (message: { name: string; data: unknown }) => void): void;\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Subscribe to real-time balance and inventory events for a wallet.\r\n * Call when the user logs in; call the returned unsubscribe when they log out or wallet changes.\r\n *\r\n * Uses eventId to dedupe (ignores already-seen events). Refetch in your app on each callback.\r\n *\r\n * @param ably - Ably Realtime instance (e.g. from useAbly() or new Ably.Realtime({ key }))\r\n * @param walletAddress - Current player wallet (0x...)\r\n * @param callbacks - onBalance and/or onInventory; each receives the payload (eventId, timestamp, reason?)\r\n * @returns Unsubscribe function\r\n */\r\nexport function subscribeWalletRealtime(\r\n ably: AblyRealtimeLike,\r\n walletAddress: string,\r\n callbacks: {\r\n onBalance?: (payload: RealtimeWalletPayload) => void;\r\n onInventory?: (payload: RealtimeWalletPayload) => void;\r\n }\r\n): () => void {\r\n const normalized = normalizeWallet(walletAddress);\r\n if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {\r\n return () => {};\r\n }\r\n\r\n const seenIds = new Set<string>();\r\n\r\n const handleMessage = (message: { name: string; data: unknown }) => {\r\n const data = message.data as RealtimeWalletPayload | undefined;\r\n if (!data || typeof data !== 'object' || typeof data.eventId !== 'string') return;\r\n if (seenIds.has(data.eventId)) return;\r\n if (seenIds.size >= MAX_SEEN_IDS) {\r\n const first = seenIds.values().next().value;\r\n if (first != null) seenIds.delete(first);\r\n }\r\n seenIds.add(data.eventId);\r\n\r\n if (message.name === REALTIME_EVENTS.balance && callbacks.onBalance) {\r\n callbacks.onBalance(data);\r\n } else if (message.name === REALTIME_EVENTS.inventory && callbacks.onInventory) {\r\n callbacks.onInventory(data);\r\n }\r\n };\r\n\r\n const channel = ably.channels.get(getWalletChannelName(normalized));\r\n channel.subscribe(handleMessage);\r\n\r\n return () => {\r\n channel.unsubscribe(handleMessage);\r\n };\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@omen.foundation/game-sdk",
3
- "version": "1.0.16",
4
- "description": "OmenX Game SDK for web applications - OAuth authentication and API integration",
3
+ "version": "1.0.17",
4
+ "description": "OmenX Game SDK for web applications - OAuth authentication, API integration, and real-time balance/inventory updates",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -41,7 +41,9 @@
41
41
  "tsup": "^8.0.0",
42
42
  "typescript": "^5.0.0"
43
43
  },
44
- "peerDependencies": {},
44
+ "peerDependencies": {
45
+ "ably": ">=1.2.0"
46
+ },
45
47
  "publishConfig": {
46
48
  "access": "public"
47
49
  }