@omen.foundation/game-sdk 1.0.17 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -410,7 +410,9 @@ declare class OmenXServerSDK {
410
410
  * Subscribe to the per-wallet Ably channel so the game stays in sync when the user
411
411
  * spends or receives OmenX / NFTs on the website or in another client.
412
412
  *
413
- * Requires the app to install `ably` and pass an Ably Realtime instance.
413
+ * Two options:
414
+ * 1. subscribeWalletRealtimeWithOmenXAuth – no API key needed; SDK gets a scoped token from the OmenX platform using your access token.
415
+ * 2. subscribeWalletRealtime – pass your own Ably Realtime instance (e.g. from an API key or your own token).
414
416
  */
415
417
  /** Payload for balance and inventory events. Use eventId for idempotency (ignore if already processed). */
416
418
  interface RealtimeWalletPayload {
@@ -470,5 +472,25 @@ declare function subscribeWalletRealtime(ably: AblyRealtimeLike, walletAddress:
470
472
  onBalance?: (payload: RealtimeWalletPayload) => void;
471
473
  onInventory?: (payload: RealtimeWalletPayload) => void;
472
474
  }): () => void;
475
+ /** Options for subscribing via OmenX platform token (no Ably API key required). */
476
+ interface SubscribeWalletRealtimeWithOmenXAuthOptions {
477
+ /** Base URL of the OmenX API (e.g. https://api.omen.foundation). No trailing slash. */
478
+ apiBaseUrl: string;
479
+ /** Returns the current OmenX access token (from your OAuth flow). Called when Ably needs to authenticate. */
480
+ getAccessToken: () => Promise<string | null>;
481
+ /** Wallet address (0x...) to subscribe to. Must match the wallet in the access token. */
482
+ walletAddress: string;
483
+ onBalance?: (payload: RealtimeWalletPayload) => void;
484
+ onInventory?: (payload: RealtimeWalletPayload) => void;
485
+ }
486
+ /**
487
+ * Subscribe to real-time balance and inventory for a wallet using OmenX platform auth.
488
+ * The SDK fetches a short-lived, subscribe-only Ably token from the OmenX API using your
489
+ * access token. No Ably API key or .env is required – ideal for third-party developers.
490
+ *
491
+ * Requires the app to have `ably` installed (peer dependency). Call when the user is
492
+ * logged in; call the returned function on logout or wallet change.
493
+ */
494
+ declare function subscribeWalletRealtimeWithOmenXAuth(options: SubscribeWalletRealtimeWithOmenXAuthOptions): () => void;
473
495
 
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 };
496
+ export { type AblyRealtimeLike, type ApiCallOptions, type AuthData, type OAuthOptions, OmenXGameSDK, type OmenXGameSDKConfig, OmenXServerSDK, REALTIME_EVENTS, type RealtimeWalletPayload, type SubscribeWalletRealtimeWithOmenXAuthOptions, type UserInfo, type VipStatus, type VipTierInfo, WALLET_CHANNEL_PREFIX, getWalletChannelName, subscribeWalletRealtime, subscribeWalletRealtimeWithOmenXAuth };
package/dist/index.d.ts CHANGED
@@ -410,7 +410,9 @@ declare class OmenXServerSDK {
410
410
  * Subscribe to the per-wallet Ably channel so the game stays in sync when the user
411
411
  * spends or receives OmenX / NFTs on the website or in another client.
412
412
  *
413
- * Requires the app to install `ably` and pass an Ably Realtime instance.
413
+ * Two options:
414
+ * 1. subscribeWalletRealtimeWithOmenXAuth – no API key needed; SDK gets a scoped token from the OmenX platform using your access token.
415
+ * 2. subscribeWalletRealtime – pass your own Ably Realtime instance (e.g. from an API key or your own token).
414
416
  */
415
417
  /** Payload for balance and inventory events. Use eventId for idempotency (ignore if already processed). */
416
418
  interface RealtimeWalletPayload {
@@ -470,5 +472,25 @@ declare function subscribeWalletRealtime(ably: AblyRealtimeLike, walletAddress:
470
472
  onBalance?: (payload: RealtimeWalletPayload) => void;
471
473
  onInventory?: (payload: RealtimeWalletPayload) => void;
472
474
  }): () => void;
475
+ /** Options for subscribing via OmenX platform token (no Ably API key required). */
476
+ interface SubscribeWalletRealtimeWithOmenXAuthOptions {
477
+ /** Base URL of the OmenX API (e.g. https://api.omen.foundation). No trailing slash. */
478
+ apiBaseUrl: string;
479
+ /** Returns the current OmenX access token (from your OAuth flow). Called when Ably needs to authenticate. */
480
+ getAccessToken: () => Promise<string | null>;
481
+ /** Wallet address (0x...) to subscribe to. Must match the wallet in the access token. */
482
+ walletAddress: string;
483
+ onBalance?: (payload: RealtimeWalletPayload) => void;
484
+ onInventory?: (payload: RealtimeWalletPayload) => void;
485
+ }
486
+ /**
487
+ * Subscribe to real-time balance and inventory for a wallet using OmenX platform auth.
488
+ * The SDK fetches a short-lived, subscribe-only Ably token from the OmenX API using your
489
+ * access token. No Ably API key or .env is required – ideal for third-party developers.
490
+ *
491
+ * Requires the app to have `ably` installed (peer dependency). Call when the user is
492
+ * logged in; call the returned function on logout or wallet change.
493
+ */
494
+ declare function subscribeWalletRealtimeWithOmenXAuth(options: SubscribeWalletRealtimeWithOmenXAuthOptions): () => void;
473
495
 
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 };
496
+ export { type AblyRealtimeLike, type ApiCallOptions, type AuthData, type OAuthOptions, OmenXGameSDK, type OmenXGameSDKConfig, OmenXServerSDK, REALTIME_EVENTS, type RealtimeWalletPayload, type SubscribeWalletRealtimeWithOmenXAuthOptions, type UserInfo, type VipStatus, type VipTierInfo, WALLET_CHANNEL_PREFIX, getWalletChannelName, subscribeWalletRealtime, subscribeWalletRealtimeWithOmenXAuth };
package/dist/index.js CHANGED
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ var Ably = require('ably');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var Ably__default = /*#__PURE__*/_interopDefault(Ably);
8
+
3
9
  // src/oauth.ts
4
10
  var OAuthFlow = class {
5
11
  constructor(config) {
@@ -776,8 +782,6 @@ var OmenXServerSDK = class {
776
782
  return response.json();
777
783
  }
778
784
  };
779
-
780
- // src/realtime.ts
781
785
  var WALLET_CHANNEL_PREFIX = "wallet:";
782
786
  var REALTIME_EVENTS = {
783
787
  /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */
@@ -820,6 +824,54 @@ function subscribeWalletRealtime(ably, walletAddress, callbacks) {
820
824
  channel.unsubscribe(handleMessage);
821
825
  };
822
826
  }
827
+ function subscribeWalletRealtimeWithOmenXAuth(options) {
828
+ const { apiBaseUrl, getAccessToken, walletAddress, onBalance, onInventory } = options;
829
+ const normalized = (walletAddress || "").trim().toLowerCase();
830
+ if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {
831
+ return () => {
832
+ };
833
+ }
834
+ const base = apiBaseUrl.replace(/\/$/, "");
835
+ const authCallback = (_tokenParams, callback) => {
836
+ getAccessToken().then((token) => {
837
+ if (!token) {
838
+ callback("Not authenticated", null);
839
+ return;
840
+ }
841
+ return fetch(`${base}/api/sdk/ably-token`, {
842
+ method: "POST",
843
+ headers: {
844
+ Authorization: `Bearer ${token}`,
845
+ "Content-Type": "application/json"
846
+ }
847
+ });
848
+ }).then((res) => {
849
+ if (!res) return;
850
+ if (!res.ok) {
851
+ return res.json().then((body) => {
852
+ callback(body && body.message || res.statusText || "Request failed", null);
853
+ });
854
+ }
855
+ return res.json().then((tokenRequest) => {
856
+ callback(null, tokenRequest);
857
+ });
858
+ }).catch((err) => {
859
+ callback(err instanceof Error ? err.message : String(err), null);
860
+ });
861
+ };
862
+ const ably = new Ably__default.default.Realtime({
863
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
864
+ authCallback
865
+ });
866
+ const unsubscribe = subscribeWalletRealtime(ably, walletAddress, {
867
+ onBalance,
868
+ onInventory
869
+ });
870
+ return () => {
871
+ unsubscribe();
872
+ ably.close();
873
+ };
874
+ }
823
875
 
824
876
  exports.OmenXGameSDK = OmenXGameSDK;
825
877
  exports.OmenXServerSDK = OmenXServerSDK;
@@ -827,5 +879,6 @@ exports.REALTIME_EVENTS = REALTIME_EVENTS;
827
879
  exports.WALLET_CHANNEL_PREFIX = WALLET_CHANNEL_PREFIX;
828
880
  exports.getWalletChannelName = getWalletChannelName;
829
881
  exports.subscribeWalletRealtime = subscribeWalletRealtime;
882
+ exports.subscribeWalletRealtimeWithOmenXAuth = subscribeWalletRealtimeWithOmenXAuth;
830
883
  //# sourceMappingURL=index.js.map
831
884
  //# 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","../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"]}
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":["Ably"],"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 * Two options:\r\n * 1. subscribeWalletRealtimeWithOmenXAuth – no API key needed; SDK gets a scoped token from the OmenX platform using your access token.\r\n * 2. subscribeWalletRealtime – pass your own Ably Realtime instance (e.g. from an API key or your own token).\r\n */\r\n\r\nimport Ably from 'ably';\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\r\n/** Options for subscribing via OmenX platform token (no Ably API key required). */\r\nexport interface SubscribeWalletRealtimeWithOmenXAuthOptions {\r\n /** Base URL of the OmenX API (e.g. https://api.omen.foundation). No trailing slash. */\r\n apiBaseUrl: string;\r\n /** Returns the current OmenX access token (from your OAuth flow). Called when Ably needs to authenticate. */\r\n getAccessToken: () => Promise<string | null>;\r\n /** Wallet address (0x...) to subscribe to. Must match the wallet in the access token. */\r\n walletAddress: string;\r\n onBalance?: (payload: RealtimeWalletPayload) => void;\r\n onInventory?: (payload: RealtimeWalletPayload) => void;\r\n}\r\n\r\n/**\r\n * Subscribe to real-time balance and inventory for a wallet using OmenX platform auth.\r\n * The SDK fetches a short-lived, subscribe-only Ably token from the OmenX API using your\r\n * access token. No Ably API key or .env is required – ideal for third-party developers.\r\n *\r\n * Requires the app to have `ably` installed (peer dependency). Call when the user is\r\n * logged in; call the returned function on logout or wallet change.\r\n */\r\nexport function subscribeWalletRealtimeWithOmenXAuth(\r\n options: SubscribeWalletRealtimeWithOmenXAuthOptions\r\n): () => void {\r\n const { apiBaseUrl, getAccessToken, walletAddress, onBalance, onInventory } = options;\r\n const normalized = (walletAddress || '').trim().toLowerCase();\r\n if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {\r\n return () => {};\r\n }\r\n\r\n const base = apiBaseUrl.replace(/\\/$/, '');\r\n const authCallback = (\r\n _tokenParams: unknown,\r\n callback: (error: string | null, tokenRequestOrDetails: unknown) => void\r\n ): void => {\r\n getAccessToken()\r\n .then((token) => {\r\n if (!token) {\r\n callback('Not authenticated', null);\r\n return;\r\n }\r\n return fetch(`${base}/api/sdk/ably-token`, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n })\r\n .then((res) => {\r\n if (!res) return;\r\n if (!res.ok) {\r\n return res.json().then((body: { message?: string }) => {\r\n callback((body && body.message) || res.statusText || 'Request failed', null);\r\n });\r\n }\r\n return res.json().then((tokenRequest: unknown) => {\r\n callback(null, tokenRequest);\r\n });\r\n })\r\n .catch((err: unknown) => {\r\n callback(err instanceof Error ? err.message : String(err), null);\r\n });\r\n };\r\n const ably = new Ably.Realtime({\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n authCallback: authCallback as any,\r\n });\r\n\r\n const unsubscribe = subscribeWalletRealtime(ably as AblyRealtimeLike, walletAddress, {\r\n onBalance,\r\n onInventory,\r\n });\r\n\r\n return () => {\r\n unsubscribe();\r\n ably.close();\r\n };\r\n}\r\n"]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import Ably from 'ably';
2
+
1
3
  // src/oauth.ts
2
4
  var OAuthFlow = class {
3
5
  constructor(config) {
@@ -774,8 +776,6 @@ var OmenXServerSDK = class {
774
776
  return response.json();
775
777
  }
776
778
  };
777
-
778
- // src/realtime.ts
779
779
  var WALLET_CHANNEL_PREFIX = "wallet:";
780
780
  var REALTIME_EVENTS = {
781
781
  /** Currency balance changed. Refetch via GetPlayerBalances or your balance API. */
@@ -818,7 +818,55 @@ function subscribeWalletRealtime(ably, walletAddress, callbacks) {
818
818
  channel.unsubscribe(handleMessage);
819
819
  };
820
820
  }
821
+ function subscribeWalletRealtimeWithOmenXAuth(options) {
822
+ const { apiBaseUrl, getAccessToken, walletAddress, onBalance, onInventory } = options;
823
+ const normalized = (walletAddress || "").trim().toLowerCase();
824
+ if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {
825
+ return () => {
826
+ };
827
+ }
828
+ const base = apiBaseUrl.replace(/\/$/, "");
829
+ const authCallback = (_tokenParams, callback) => {
830
+ getAccessToken().then((token) => {
831
+ if (!token) {
832
+ callback("Not authenticated", null);
833
+ return;
834
+ }
835
+ return fetch(`${base}/api/sdk/ably-token`, {
836
+ method: "POST",
837
+ headers: {
838
+ Authorization: `Bearer ${token}`,
839
+ "Content-Type": "application/json"
840
+ }
841
+ });
842
+ }).then((res) => {
843
+ if (!res) return;
844
+ if (!res.ok) {
845
+ return res.json().then((body) => {
846
+ callback(body && body.message || res.statusText || "Request failed", null);
847
+ });
848
+ }
849
+ return res.json().then((tokenRequest) => {
850
+ callback(null, tokenRequest);
851
+ });
852
+ }).catch((err) => {
853
+ callback(err instanceof Error ? err.message : String(err), null);
854
+ });
855
+ };
856
+ const ably = new Ably.Realtime({
857
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
858
+ authCallback
859
+ });
860
+ const unsubscribe = subscribeWalletRealtime(ably, walletAddress, {
861
+ onBalance,
862
+ onInventory
863
+ });
864
+ return () => {
865
+ unsubscribe();
866
+ ably.close();
867
+ };
868
+ }
821
869
 
822
- export { OmenXGameSDK, OmenXServerSDK, REALTIME_EVENTS, WALLET_CHANNEL_PREFIX, getWalletChannelName, subscribeWalletRealtime };
870
+ export { OmenXGameSDK, OmenXServerSDK, REALTIME_EVENTS, WALLET_CHANNEL_PREFIX, getWalletChannelName, subscribeWalletRealtime, subscribeWalletRealtimeWithOmenXAuth };
823
871
  //# sourceMappingURL=index.mjs.map
824
872
  //# 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","../src/realtime.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;AAAA,EAUA,MAAM,gBAAgB,OAAA,EAAgC;AACpD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,oBAAoB,CAAA;AACxD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAe,OAAA,EAAgC;AACnD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,mBAAmB,CAAA;AACvD,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAA,CACJ,MAAA,EACA,OAAA,EACwD;AACxD,IAAA,MAAM,IAAI,OAAA,EAAS,SAAA,GAAY,CAAA,WAAA,EAAc,OAAA,CAAQ,SAAS,CAAA,CAAA,GAAK,EAAA;AACnE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,mBAAA,EAAsB,mBAAmB,MAAM,CAAC,CAAA,EAAG,CAAC,CAAA,CAAE,CAAA;AAC1F,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,YAAA,CACJ,MAAA,EACA,SAAA,EACA,OACA,OAAA,EACqF;AACrF,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,sBAAsB,kBAAA,CAAmB,MAAM,CAAC,CAAA,OAAA,CAAA,EAAW;AAAA,MAC7F,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,SAAA,EAAW,KAAA,EAAM;AAAA,MACzB,SAAS,OAAA,EAAS,cAAA,GAAiB,EAAE,iBAAA,EAAmB,OAAA,CAAQ,gBAAe,GAAI;AAAA,KACpF,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,mBAAA,CACJ,MAAA,EACA,QAAA,EACA,OACA,OAAA,EAC8C;AAC9C,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,MAAM,EAAE,MAAA,EAAQ,UAAU,KAAA,EAAO,OAAA,EAAS,SAAS,OAAA;AAAQ,KAC5D,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,aAAA,CAAc,MAAA,EAAgB,QAAA,EAAgE;AAClG,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB;AAAA,MACzD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,MAAA,EAAQ,QAAA;AAAS,KAC1B,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA,EAGA,MAAM,gBAAA,CACJ,MAAA,EACA,QAAA,EACA,OAAA,EACkE;AAClE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,kBAAA,EAAoB;AAAA,MACtD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,EAAE,MAAA,EAAQ,QAAA,EAAS;AAAA,MACzB,SAAS,OAAA,EAAS,cAAA,GAAiB,EAAE,iBAAA,EAAmB,OAAA,CAAQ,gBAAe,GAAI;AAAA,KACpF,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBAAA,CACJ,MAAA,EACA,MAAA,EACA,QAAA,EAC6F;AAC7F,IAAA,MAAM,IAAA,GAAwD,EAAE,MAAA,EAAO;AACvE,IAAA,IAAI,MAAA,KAAW,OAAA,IAAW,QAAA,EAAU,IAAA,CAAK,QAAA,GAAW,QAAA;AACpD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,wBAAwB,kBAAA,CAAmB,MAAM,IAAI,QAAA,EAAU;AAAA,MACjG,MAAA,EAAQ,MAAA;AAAA,MACR;AAAA,KACD,CAAA;AACD,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AACF;;;AClWO,IAAM,qBAAA,GAAwB;AAG9B,IAAM,eAAA,GAAkB;AAAA;AAAA,EAE7B,OAAA,EAAS,SAAA;AAAA;AAAA,EAET,SAAA,EAAW;AACb;AAEA,IAAM,YAAA,GAAe,GAAA;AAKrB,SAAS,gBAAgB,MAAA,EAAwB;AAC/C,EAAA,OAAA,CAAQ,MAAA,IAAU,EAAA,EAAI,IAAA,EAAK,CAAE,WAAA,EAAY;AAC3C;AAKO,SAAS,qBAAqB,aAAA,EAA+B;AAClE,EAAA,OAAO,qBAAA,GAAwB,gBAAgB,aAAa,CAAA;AAC9D;AA0BO,SAAS,uBAAA,CACd,IAAA,EACA,aAAA,EACA,SAAA,EAIY;AACZ,EAAA,MAAM,UAAA,GAAa,gBAAgB,aAAa,CAAA;AAChD,EAAA,IAAI,CAAC,UAAA,IAAc,CAAC,qBAAA,CAAsB,IAAA,CAAK,UAAU,CAAA,EAAG;AAC1D,IAAA,OAAO,MAAM;AAAA,IAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAEhC,EAAA,MAAM,aAAA,GAAgB,CAAC,OAAA,KAA6C;AAClE,IAAA,MAAM,OAAO,OAAA,CAAQ,IAAA;AACrB,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA,KAAS,YAAY,OAAO,IAAA,CAAK,YAAY,QAAA,EAAU;AAC3E,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA,EAAG;AAC/B,IAAA,IAAI,OAAA,CAAQ,QAAQ,YAAA,EAAc;AAChC,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,EAAO,CAAE,MAAK,CAAE,KAAA;AACtC,MAAA,IAAI,KAAA,IAAS,IAAA,EAAM,OAAA,CAAQ,MAAA,CAAO,KAAK,CAAA;AAAA,IACzC;AACA,IAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,OAAO,CAAA;AAExB,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,eAAA,CAAgB,OAAA,IAAW,UAAU,SAAA,EAAW;AACnE,MAAA,SAAA,CAAU,UAAU,IAAI,CAAA;AAAA,IAC1B,WAAW,OAAA,CAAQ,IAAA,KAAS,eAAA,CAAgB,SAAA,IAAa,UAAU,WAAA,EAAa;AAC9E,MAAA,SAAA,CAAU,YAAY,IAAI,CAAA;AAAA,IAC5B;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,UAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,oBAAA,CAAqB,UAAU,CAAC,CAAA;AAClE,EAAA,OAAA,CAAQ,UAAU,aAAa,CAAA;AAE/B,EAAA,OAAO,MAAM;AACX,IAAA,OAAA,CAAQ,YAAY,aAAa,CAAA;AAAA,EACnC,CAAA;AACF","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"]}
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 * Two options:\r\n * 1. subscribeWalletRealtimeWithOmenXAuth – no API key needed; SDK gets a scoped token from the OmenX platform using your access token.\r\n * 2. subscribeWalletRealtime – pass your own Ably Realtime instance (e.g. from an API key or your own token).\r\n */\r\n\r\nimport Ably from 'ably';\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\r\n/** Options for subscribing via OmenX platform token (no Ably API key required). */\r\nexport interface SubscribeWalletRealtimeWithOmenXAuthOptions {\r\n /** Base URL of the OmenX API (e.g. https://api.omen.foundation). No trailing slash. */\r\n apiBaseUrl: string;\r\n /** Returns the current OmenX access token (from your OAuth flow). Called when Ably needs to authenticate. */\r\n getAccessToken: () => Promise<string | null>;\r\n /** Wallet address (0x...) to subscribe to. Must match the wallet in the access token. */\r\n walletAddress: string;\r\n onBalance?: (payload: RealtimeWalletPayload) => void;\r\n onInventory?: (payload: RealtimeWalletPayload) => void;\r\n}\r\n\r\n/**\r\n * Subscribe to real-time balance and inventory for a wallet using OmenX platform auth.\r\n * The SDK fetches a short-lived, subscribe-only Ably token from the OmenX API using your\r\n * access token. No Ably API key or .env is required – ideal for third-party developers.\r\n *\r\n * Requires the app to have `ably` installed (peer dependency). Call when the user is\r\n * logged in; call the returned function on logout or wallet change.\r\n */\r\nexport function subscribeWalletRealtimeWithOmenXAuth(\r\n options: SubscribeWalletRealtimeWithOmenXAuthOptions\r\n): () => void {\r\n const { apiBaseUrl, getAccessToken, walletAddress, onBalance, onInventory } = options;\r\n const normalized = (walletAddress || '').trim().toLowerCase();\r\n if (!normalized || !/^0x[a-fa-f0-9]{40}$/.test(normalized)) {\r\n return () => {};\r\n }\r\n\r\n const base = apiBaseUrl.replace(/\\/$/, '');\r\n const authCallback = (\r\n _tokenParams: unknown,\r\n callback: (error: string | null, tokenRequestOrDetails: unknown) => void\r\n ): void => {\r\n getAccessToken()\r\n .then((token) => {\r\n if (!token) {\r\n callback('Not authenticated', null);\r\n return;\r\n }\r\n return fetch(`${base}/api/sdk/ably-token`, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n })\r\n .then((res) => {\r\n if (!res) return;\r\n if (!res.ok) {\r\n return res.json().then((body: { message?: string }) => {\r\n callback((body && body.message) || res.statusText || 'Request failed', null);\r\n });\r\n }\r\n return res.json().then((tokenRequest: unknown) => {\r\n callback(null, tokenRequest);\r\n });\r\n })\r\n .catch((err: unknown) => {\r\n callback(err instanceof Error ? err.message : String(err), null);\r\n });\r\n };\r\n const ably = new Ably.Realtime({\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n authCallback: authCallback as any,\r\n });\r\n\r\n const unsubscribe = subscribeWalletRealtime(ably as AblyRealtimeLike, walletAddress, {\r\n onBalance,\r\n onInventory,\r\n });\r\n\r\n return () => {\r\n unsubscribe();\r\n ably.close();\r\n };\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omen.foundation/game-sdk",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
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",