@omen.foundation/game-sdk 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +116 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -98,10 +98,120 @@ var OAuthFlow = class {
|
|
|
98
98
|
}
|
|
99
99
|
};
|
|
100
100
|
window.addEventListener("message", messageListener);
|
|
101
|
+
const storageListener = (event) => {
|
|
102
|
+
if (!event.key || !event.key.startsWith("omenx_oauth_callback_")) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const callbackState = event.key.replace("omenx_oauth_callback_", "");
|
|
106
|
+
if (callbackState !== state) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const data = JSON.parse(event.newValue || "{}");
|
|
111
|
+
if (data.code && data.state === state) {
|
|
112
|
+
console.log("[OAuthFlow] Received OAuth code via localStorage fallback");
|
|
113
|
+
messageReceived = true;
|
|
114
|
+
window.removeEventListener("storage", storageListener);
|
|
115
|
+
window.removeEventListener("message", wrappedMessageListener);
|
|
116
|
+
const { code: codeFromStorage } = data;
|
|
117
|
+
const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);
|
|
118
|
+
let codeVerifier2;
|
|
119
|
+
if (storedCodeVerifier) {
|
|
120
|
+
sessionStorage.removeItem(`omenx_pkce_${state}`);
|
|
121
|
+
codeVerifier2 = storedCodeVerifier;
|
|
122
|
+
}
|
|
123
|
+
this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier2).then(async (tokenResponse) => {
|
|
124
|
+
await this.config.onTokenReceived(tokenResponse);
|
|
125
|
+
resolve(tokenResponse);
|
|
126
|
+
}).catch((error) => {
|
|
127
|
+
this.config.onError?.(error);
|
|
128
|
+
reject(error);
|
|
129
|
+
});
|
|
130
|
+
localStorage.removeItem(event.key);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error("[OAuthFlow] Error processing localStorage callback:", error);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
window.addEventListener("storage", storageListener);
|
|
137
|
+
let pollCount = 0;
|
|
138
|
+
const pollInterval = setInterval(() => {
|
|
139
|
+
pollCount++;
|
|
140
|
+
const storageKey = `omenx_oauth_callback_${state}`;
|
|
141
|
+
const stored = localStorage.getItem(storageKey);
|
|
142
|
+
if (pollCount % 10 === 0) {
|
|
143
|
+
console.log("[OAuthFlow] Polling localStorage for callback...", { key: storageKey, found: !!stored, pollCount });
|
|
144
|
+
}
|
|
145
|
+
if (stored) {
|
|
146
|
+
try {
|
|
147
|
+
const data = JSON.parse(stored);
|
|
148
|
+
if (data.code && data.state === state) {
|
|
149
|
+
const age = Date.now() - (data.timestamp || 0);
|
|
150
|
+
if (age < 3e4) {
|
|
151
|
+
console.log("[OAuthFlow] \u2705 Found OAuth callback in localStorage!", { age: `${age}ms`, hasCode: !!data.code });
|
|
152
|
+
clearInterval(pollInterval);
|
|
153
|
+
storageListener(new StorageEvent("storage", {
|
|
154
|
+
key: storageKey,
|
|
155
|
+
newValue: stored,
|
|
156
|
+
storageArea: localStorage
|
|
157
|
+
}));
|
|
158
|
+
} else {
|
|
159
|
+
console.warn("[OAuthFlow] Callback data too old, removing:", { age: `${age}ms` });
|
|
160
|
+
localStorage.removeItem(storageKey);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.error("[OAuthFlow] Error parsing localStorage callback:", error);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}, 100);
|
|
168
|
+
let broadcastChannel = null;
|
|
169
|
+
try {
|
|
170
|
+
broadcastChannel = new BroadcastChannel("omenx_oauth");
|
|
171
|
+
const broadcastListener = (event) => {
|
|
172
|
+
if (event.data?.type === "OMENX_OAUTH_CODE" && event.data?.state === state) {
|
|
173
|
+
console.log("[OAuthFlow] \u2705 Received OAuth code via BroadcastChannel");
|
|
174
|
+
messageReceived = true;
|
|
175
|
+
clearInterval(pollInterval);
|
|
176
|
+
if (broadcastChannel) {
|
|
177
|
+
broadcastChannel.onmessage = null;
|
|
178
|
+
broadcastChannel.close();
|
|
179
|
+
}
|
|
180
|
+
window.removeEventListener("message", wrappedMessageListener);
|
|
181
|
+
window.removeEventListener("storage", storageListener);
|
|
182
|
+
const { code: codeFromBroadcast } = event.data;
|
|
183
|
+
const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);
|
|
184
|
+
let codeVerifier2;
|
|
185
|
+
if (storedCodeVerifier) {
|
|
186
|
+
sessionStorage.removeItem(`omenx_pkce_${state}`);
|
|
187
|
+
codeVerifier2 = storedCodeVerifier;
|
|
188
|
+
}
|
|
189
|
+
this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier2).then(async (tokenResponse) => {
|
|
190
|
+
await this.config.onTokenReceived(tokenResponse);
|
|
191
|
+
resolve(tokenResponse);
|
|
192
|
+
}).catch((error) => {
|
|
193
|
+
this.config.onError?.(error);
|
|
194
|
+
reject(error);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
broadcastChannel.onmessage = broadcastListener;
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.warn("[OAuthFlow] BroadcastChannel not supported:", error);
|
|
201
|
+
broadcastChannel = null;
|
|
202
|
+
}
|
|
203
|
+
console.log("[OAuthFlow] \u{1F50D} Starting OAuth flow, listening for callback...", {
|
|
204
|
+
state: state.substring(0, 10) + "...",
|
|
205
|
+
hasOpener: !!window.opener,
|
|
206
|
+
polling: true,
|
|
207
|
+
broadcastChannel: true
|
|
208
|
+
});
|
|
101
209
|
let messageReceived = false;
|
|
102
210
|
const originalMessageListener = messageListener;
|
|
103
211
|
const wrappedMessageListener = async (event) => {
|
|
104
212
|
messageReceived = true;
|
|
213
|
+
clearInterval(pollInterval);
|
|
214
|
+
window.removeEventListener("storage", storageListener);
|
|
105
215
|
await originalMessageListener(event);
|
|
106
216
|
};
|
|
107
217
|
window.removeEventListener("message", messageListener);
|
|
@@ -127,7 +237,13 @@ var OAuthFlow = class {
|
|
|
127
237
|
}
|
|
128
238
|
if (isPopupActuallyClosed()) {
|
|
129
239
|
clearInterval(checkClosed);
|
|
240
|
+
clearInterval(pollInterval);
|
|
130
241
|
window.removeEventListener("message", wrappedMessageListener);
|
|
242
|
+
window.removeEventListener("storage", storageListener);
|
|
243
|
+
if (broadcastChannel) {
|
|
244
|
+
broadcastChannel.onmessage = null;
|
|
245
|
+
broadcastChannel.close();
|
|
246
|
+
}
|
|
131
247
|
if (!messageReceived) {
|
|
132
248
|
const error = new Error("Authentication was cancelled.");
|
|
133
249
|
this.config.onError?.(error);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\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 * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\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 popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\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 // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\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 };\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 // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\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","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} 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 return this.oauthFlow.authenticate(options);\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 * 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';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\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 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\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 (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\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 * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\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 popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\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 // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\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 \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (pollCount % 10 === 0) {\r\n // Log every 1 second (10 * 100ms) for debugging\r\n console.log('[OAuthFlow] Polling localStorage for callback...', { key: storageKey, found: !!stored, pollCount });\r\n }\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\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 (increased from 10s)\r\n console.log('[OAuthFlow] ✅ Found OAuth callback in localStorage!', { age: `${age}ms`, hasCode: !!data.code });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n } else {\r\n console.warn('[OAuthFlow] Callback data too old, removing:', { age: `${age}ms` });\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 // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] ✅ Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\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 }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] 🔍 Starting OAuth flow, listening for callback...', { \r\n state: state.substring(0, 10) + '...',\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\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 };\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 // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\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","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} 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 return this.oauthFlow.authenticate(options);\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 * 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';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\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 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\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 (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -96,10 +96,120 @@ var OAuthFlow = class {
|
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
98
|
window.addEventListener("message", messageListener);
|
|
99
|
+
const storageListener = (event) => {
|
|
100
|
+
if (!event.key || !event.key.startsWith("omenx_oauth_callback_")) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const callbackState = event.key.replace("omenx_oauth_callback_", "");
|
|
104
|
+
if (callbackState !== state) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const data = JSON.parse(event.newValue || "{}");
|
|
109
|
+
if (data.code && data.state === state) {
|
|
110
|
+
console.log("[OAuthFlow] Received OAuth code via localStorage fallback");
|
|
111
|
+
messageReceived = true;
|
|
112
|
+
window.removeEventListener("storage", storageListener);
|
|
113
|
+
window.removeEventListener("message", wrappedMessageListener);
|
|
114
|
+
const { code: codeFromStorage } = data;
|
|
115
|
+
const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);
|
|
116
|
+
let codeVerifier2;
|
|
117
|
+
if (storedCodeVerifier) {
|
|
118
|
+
sessionStorage.removeItem(`omenx_pkce_${state}`);
|
|
119
|
+
codeVerifier2 = storedCodeVerifier;
|
|
120
|
+
}
|
|
121
|
+
this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier2).then(async (tokenResponse) => {
|
|
122
|
+
await this.config.onTokenReceived(tokenResponse);
|
|
123
|
+
resolve(tokenResponse);
|
|
124
|
+
}).catch((error) => {
|
|
125
|
+
this.config.onError?.(error);
|
|
126
|
+
reject(error);
|
|
127
|
+
});
|
|
128
|
+
localStorage.removeItem(event.key);
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error("[OAuthFlow] Error processing localStorage callback:", error);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
window.addEventListener("storage", storageListener);
|
|
135
|
+
let pollCount = 0;
|
|
136
|
+
const pollInterval = setInterval(() => {
|
|
137
|
+
pollCount++;
|
|
138
|
+
const storageKey = `omenx_oauth_callback_${state}`;
|
|
139
|
+
const stored = localStorage.getItem(storageKey);
|
|
140
|
+
if (pollCount % 10 === 0) {
|
|
141
|
+
console.log("[OAuthFlow] Polling localStorage for callback...", { key: storageKey, found: !!stored, pollCount });
|
|
142
|
+
}
|
|
143
|
+
if (stored) {
|
|
144
|
+
try {
|
|
145
|
+
const data = JSON.parse(stored);
|
|
146
|
+
if (data.code && data.state === state) {
|
|
147
|
+
const age = Date.now() - (data.timestamp || 0);
|
|
148
|
+
if (age < 3e4) {
|
|
149
|
+
console.log("[OAuthFlow] \u2705 Found OAuth callback in localStorage!", { age: `${age}ms`, hasCode: !!data.code });
|
|
150
|
+
clearInterval(pollInterval);
|
|
151
|
+
storageListener(new StorageEvent("storage", {
|
|
152
|
+
key: storageKey,
|
|
153
|
+
newValue: stored,
|
|
154
|
+
storageArea: localStorage
|
|
155
|
+
}));
|
|
156
|
+
} else {
|
|
157
|
+
console.warn("[OAuthFlow] Callback data too old, removing:", { age: `${age}ms` });
|
|
158
|
+
localStorage.removeItem(storageKey);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error("[OAuthFlow] Error parsing localStorage callback:", error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}, 100);
|
|
166
|
+
let broadcastChannel = null;
|
|
167
|
+
try {
|
|
168
|
+
broadcastChannel = new BroadcastChannel("omenx_oauth");
|
|
169
|
+
const broadcastListener = (event) => {
|
|
170
|
+
if (event.data?.type === "OMENX_OAUTH_CODE" && event.data?.state === state) {
|
|
171
|
+
console.log("[OAuthFlow] \u2705 Received OAuth code via BroadcastChannel");
|
|
172
|
+
messageReceived = true;
|
|
173
|
+
clearInterval(pollInterval);
|
|
174
|
+
if (broadcastChannel) {
|
|
175
|
+
broadcastChannel.onmessage = null;
|
|
176
|
+
broadcastChannel.close();
|
|
177
|
+
}
|
|
178
|
+
window.removeEventListener("message", wrappedMessageListener);
|
|
179
|
+
window.removeEventListener("storage", storageListener);
|
|
180
|
+
const { code: codeFromBroadcast } = event.data;
|
|
181
|
+
const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);
|
|
182
|
+
let codeVerifier2;
|
|
183
|
+
if (storedCodeVerifier) {
|
|
184
|
+
sessionStorage.removeItem(`omenx_pkce_${state}`);
|
|
185
|
+
codeVerifier2 = storedCodeVerifier;
|
|
186
|
+
}
|
|
187
|
+
this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier2).then(async (tokenResponse) => {
|
|
188
|
+
await this.config.onTokenReceived(tokenResponse);
|
|
189
|
+
resolve(tokenResponse);
|
|
190
|
+
}).catch((error) => {
|
|
191
|
+
this.config.onError?.(error);
|
|
192
|
+
reject(error);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
broadcastChannel.onmessage = broadcastListener;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.warn("[OAuthFlow] BroadcastChannel not supported:", error);
|
|
199
|
+
broadcastChannel = null;
|
|
200
|
+
}
|
|
201
|
+
console.log("[OAuthFlow] \u{1F50D} Starting OAuth flow, listening for callback...", {
|
|
202
|
+
state: state.substring(0, 10) + "...",
|
|
203
|
+
hasOpener: !!window.opener,
|
|
204
|
+
polling: true,
|
|
205
|
+
broadcastChannel: true
|
|
206
|
+
});
|
|
99
207
|
let messageReceived = false;
|
|
100
208
|
const originalMessageListener = messageListener;
|
|
101
209
|
const wrappedMessageListener = async (event) => {
|
|
102
210
|
messageReceived = true;
|
|
211
|
+
clearInterval(pollInterval);
|
|
212
|
+
window.removeEventListener("storage", storageListener);
|
|
103
213
|
await originalMessageListener(event);
|
|
104
214
|
};
|
|
105
215
|
window.removeEventListener("message", messageListener);
|
|
@@ -125,7 +235,13 @@ var OAuthFlow = class {
|
|
|
125
235
|
}
|
|
126
236
|
if (isPopupActuallyClosed()) {
|
|
127
237
|
clearInterval(checkClosed);
|
|
238
|
+
clearInterval(pollInterval);
|
|
128
239
|
window.removeEventListener("message", wrappedMessageListener);
|
|
240
|
+
window.removeEventListener("storage", storageListener);
|
|
241
|
+
if (broadcastChannel) {
|
|
242
|
+
broadcastChannel.onmessage = null;
|
|
243
|
+
broadcastChannel.close();
|
|
244
|
+
}
|
|
129
245
|
if (!messageReceived) {
|
|
130
246
|
const error = new Error("Authentication was cancelled.");
|
|
131
247
|
this.config.onError?.(error);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\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 * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\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 popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\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 // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\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 };\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 // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\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","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} 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 return this.oauthFlow.authenticate(options);\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 * 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';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\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 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\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 (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\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 * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\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 popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\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 // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\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 \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n if (pollCount % 10 === 0) {\r\n // Log every 1 second (10 * 100ms) for debugging\r\n console.log('[OAuthFlow] Polling localStorage for callback...', { key: storageKey, found: !!stored, pollCount });\r\n }\r\n \r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\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 (increased from 10s)\r\n console.log('[OAuthFlow] ✅ Found OAuth callback in localStorage!', { age: `${age}ms`, hasCode: !!data.code });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n } else {\r\n console.warn('[OAuthFlow] Callback data too old, removing:', { age: `${age}ms` });\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 // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] ✅ Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\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 }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] 🔍 Starting OAuth flow, listening for callback...', { \r\n state: state.substring(0, 10) + '...',\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\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 };\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 // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\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","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} 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 return this.oauthFlow.authenticate(options);\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 * 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';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\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 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\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 (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
|
package/package.json
CHANGED