@looplay/sdk 0.8.9 → 0.8.10

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/auth/storage.ts","../src/auth/looplay-auth.ts","../src/version.ts","../src/apps/http.ts","../src/apps/service-client.ts","../src/apps/api-client.ts","../src/constants.ts","../src/looplay-sdk.ts","../src/auth/jwt.ts","../src/auth/providers/telegram-auth-provider.ts","../src/iframe/iframe-auth.ts"],"names":["LooplaySDKError","message","NotInitializedError","MissingBaseUrlError","MissingAuthError","NotAuthenticatedError","MemoryAuthStorage","key","value","BrowserLocalStorageAuthStorage","InvalidSessionError","LooplayAuth","options","params","result","now","refreshed","next","eventName","listener","raw","parsed","event","LOOPLAY_SDK_VERSION","getFetchFn","fetchOverride","HttpError","status","bodyText","HttpClient","method","path","url","headers","body","res","text","sources","src","query","normalizedPath","ServiceClient","telegramInitData","refreshToken","gameKey","auth","anonId","bearerToken","trackingSessionId","generateId","c","r","ApiClient","token","session","cacheKey","dto","playSessionId","previous","issue","playTimeSeconds","playSessionToken","actionCode","opts","offerCode","intent","DEFAULT_API_URL","resolveEnvParentOrigin","val","resolveEnvApiUrl","LooplaySDK","baseUrl","fetch","defaultHeaders","matchId","error","decodeJwtClaims","parts","payload","padded","json","decodeJwtExpMs","exp","MissingTelegramInitDataError","MissingRefreshTokenError","TelegramAuthProvider","initData","rawUser","currentSession","id","DEFAULT_ANON_ID_STORAGE_KEY","DEFAULT_ANONYMOUS_FALLBACK_TIMEOUT_MS","DEFAULT_REQUEST_ADS_TIMEOUT_MS","INITIAL_STATE","isRecord","toOptionalString","normalized","generateAnonymousId","readStoredAnonymousId","writeStoredAnonymousId","LooplayIframeAuth","parentOrigin","requestId","timeoutMs","resolve","timer","isEmbedded","pending","gameId","ok","apiUrl","identity","anonymousId","data","origin","jwt","resolvedGameId","resolvedApiUrl","currentApiUrl","envOrigin","details","config","threshold","chance"],"mappings":"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","file":"looplay-sdk.min.js","sourcesContent":["export class LooplaySDKError extends Error {\n constructor(message?: string) {\n super(message);\n this.name = 'LooplaySDKError';\n }\n}\n\nexport class NotInitializedError extends LooplaySDKError {\n constructor() {\n super('LooplaySDK not initialized. Call init({ gameId }) first.');\n this.name = 'NotInitializedError';\n }\n}\n\nexport class MissingBaseUrlError extends LooplaySDKError {\n constructor() {\n super('Missing baseUrl. Provide `baseUrl` to enable HTTP integration.');\n this.name = 'MissingBaseUrlError';\n }\n}\n\nexport class MissingAuthError extends LooplaySDKError {\n constructor() {\n super('Missing auth. Provide `auth` options to enable user login/session.');\n this.name = 'MissingAuthError';\n }\n}\n\nexport class NotAuthenticatedError extends LooplaySDKError {\n constructor() {\n super('Not authenticated. Login is required for this operation.');\n this.name = 'NotAuthenticatedError';\n }\n}\n","import type { AuthStorage } from './types';\n\nexport class MemoryAuthStorage implements AuthStorage {\n private readonly map = new Map<string, string>();\n\n async getItem(key: string): Promise<string | null> {\n return this.map.has(key) ? (this.map.get(key) as string) : null;\n }\n\n async setItem(key: string, value: string): Promise<void> {\n this.map.set(key, value);\n }\n\n async removeItem(key: string): Promise<void> {\n this.map.delete(key);\n }\n}\n\nexport class BrowserLocalStorageAuthStorage implements AuthStorage {\n async getItem(key: string): Promise<string | null> {\n if (typeof window === 'undefined' || !window.localStorage) return null;\n return window.localStorage.getItem(key);\n }\n\n async setItem(key: string, value: string): Promise<void> {\n if (typeof window === 'undefined' || !window.localStorage) return;\n window.localStorage.setItem(key, value);\n }\n\n async removeItem(key: string): Promise<void> {\n if (typeof window === 'undefined' || !window.localStorage) return;\n window.localStorage.removeItem(key);\n }\n}\n","import { LooplaySDKError } from '../errors';\nimport {\n type AuthEventName,\n type AuthLoginParams,\n type AuthProvider,\n type AuthStorage,\n type LooplayAuthOptions,\n type LooplaySession\n} from './types';\nimport { MemoryAuthStorage } from './storage';\n\nclass InvalidSessionError extends LooplaySDKError {\n constructor() {\n super('Invalid session returned by auth provider');\n this.name = 'InvalidSessionError';\n }\n}\n\ntype Listener = (session: LooplaySession | null) => void;\n\nexport class LooplayAuth {\n private readonly provider: AuthProvider;\n private readonly storage: AuthStorage;\n private readonly key: string;\n\n private session: LooplaySession | null = null;\n private readonly listeners = new Set<Listener>();\n\n constructor(options: LooplayAuthOptions) {\n this.provider = options.provider;\n this.storage = options.storage ?? new MemoryAuthStorage();\n this.key = `${options.storageKeyPrefix ?? 'looplay'}:auth:session`;\n }\n\n async init(): Promise<void> {\n await this.provider.init?.();\n await this.restoreFromStorage();\n\n // Keep provider in sync with restored session (if any).\n await this.provider.onSessionChanged?.(this.session);\n }\n\n getSession(): LooplaySession | null {\n return this.session;\n }\n\n async login(params?: AuthLoginParams): Promise<LooplaySession> {\n const result = await this.provider.login(params);\n\n if (!result?.session?.user?.id) {\n throw new InvalidSessionError();\n }\n\n await this.setSession(result.session, 'login');\n return result.session;\n }\n\n async logout(): Promise<void> {\n await this.provider.logout();\n await this.setSession(null, 'logout');\n }\n\n async getAccessToken(): Promise<string | undefined> {\n if (!this.session) return undefined;\n\n const now = Date.now();\n const isExpired =\n typeof this.session.expiresAt === 'number' && this.session.expiresAt <= now;\n\n if (!isExpired) return this.session.accessToken;\n\n if (!this.provider.refresh) return this.session.accessToken;\n\n const refreshed = await this.provider.refresh();\n const next = { ...this.session, ...refreshed };\n await this.setSession(next, 'sessionChanged');\n\n return next.accessToken;\n }\n\n on(eventName: AuthEventName, listener: Listener): () => void {\n // eventName reserved for future filtering; for now notify on any change\n void eventName;\n\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private async restoreFromStorage(): Promise<void> {\n const raw = await this.storage.getItem(this.key);\n if (!raw) return;\n\n try {\n const parsed = JSON.parse(raw) as LooplaySession;\n if (parsed?.user?.id) {\n this.session = parsed;\n }\n } catch {\n // ignore corrupted cache\n await this.storage.removeItem(this.key);\n }\n }\n\n private async setSession(next: LooplaySession | null, event: AuthEventName): Promise<void> {\n this.session = next;\n\n await this.provider.onSessionChanged?.(this.session);\n\n if (next) {\n await this.storage.setItem(this.key, JSON.stringify(next));\n } else {\n await this.storage.removeItem(this.key);\n }\n\n for (const listener of this.listeners) {\n listener(this.session);\n }\n\n // reserved for future event-specific hooks\n void event;\n }\n}\n","export const LOOPLAY_SDK_VERSION = '0.8.5';\n","import { LOOPLAY_SDK_VERSION } from '../version';\n\nexport type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nexport interface HttpClientOptions {\n baseUrl: string;\n fetch?: FetchLike;\n defaultHeaders?: Record<string, string>;\n}\n\nfunction getFetchFn(fetchOverride?: FetchLike): FetchLike {\n if (fetchOverride) {\n if (typeof window !== 'undefined' && fetchOverride === window.fetch) {\n return window.fetch.bind(window);\n }\n\n return fetchOverride;\n }\n\n return globalThis.fetch.bind(globalThis);\n}\n\nexport class HttpError extends Error {\n readonly status: number;\n readonly bodyText?: string;\n\n constructor(message: string, status: number, bodyText?: string) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.bodyText = bodyText;\n }\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly fetchFn: FetchLike;\n private readonly defaultHeaders: Record<string, string>;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\n this.fetchFn = getFetchFn(options.fetch);\n this.defaultHeaders = {\n 'x-looplay-sdk-version': LOOPLAY_SDK_VERSION,\n ...(options.defaultHeaders ?? {}),\n };\n }\n\n async request<T>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n path: string,\n options?: {\n query?: Record<string, string | number | boolean | undefined>;\n headers?: Record<string, string | undefined>;\n bearerToken?: string;\n /** Anonymous device id, used when there is no `bearerToken` (no logged-in user). */\n anonId?: string;\n body?: unknown;\n }\n ): Promise<T> {\n const url = this.buildUrl(path, options?.query);\n\n const headers: Record<string, string> = this.mergeHeaders(\n this.defaultHeaders,\n options?.headers\n );\n\n if (options?.bearerToken) {\n headers.Authorization = `Bearer ${options.bearerToken}`;\n } else if (options?.anonId) {\n headers['x-looplay-anon-id'] = options.anonId;\n }\n\n let body: BodyInit | undefined;\n if (options?.body !== undefined) {\n headers['Content-Type'] = headers['Content-Type'] ?? 'application/json';\n body = JSON.stringify(options.body);\n }\n\n const res = await this.fetchFn(url, { method, headers, body });\n\n if (!res.ok) {\n const text = await this.safeText(res);\n throw new HttpError(`HTTP ${res.status} ${res.statusText}`, res.status, text);\n }\n\n // Some endpoints may return empty body.\n const text = await this.safeText(res);\n if (!text) return undefined as T;\n\n return JSON.parse(text) as T;\n }\n\n private mergeHeaders(\n ...sources: Array<Record<string, string | undefined> | undefined>\n ): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const src of sources) {\n if (!src) continue;\n for (const [key, value] of Object.entries(src)) {\n if (value === undefined) continue;\n result[key] = value;\n }\n }\n\n return result;\n }\n\n private buildUrl(\n path: string,\n query?: Record<string, string | number | boolean | undefined>\n ): string {\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n const url = new URL(`${this.baseUrl}${normalizedPath}`);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n url.searchParams.set(key, String(value));\n }\n }\n\n return url.toString();\n }\n\n private async safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n }\n}\n","import { HttpClient, type HttpClientOptions } from './http';\nimport type {\n AuthResultDto,\n CompletePlaySessionRequest,\n CompleteGameplayMatchRequest,\n EmitGameEventResponse,\n GameAssetDto,\n GameOwnedAssetDto,\n PlaySessionDto,\n GameStoreCheckoutIntentDto,\n GameStoreDto,\n GameStoreOfferPurchaseResultDto,\n GameTrackingSessionDto,\n PagingResponse,\n RecordGameplayActionRequest,\n RefreshTokenRequest,\n RenewPlaySessionRequest,\n SdkCreateGameStoreCheckoutIntentRequest,\n SdkPurchaseGameStoreOfferRuntimeRequest,\n StartPlaySessionRequest,\n TelegramLoginRequest,\n} from './LooplaySDK.types';\n\nexport interface ServiceClientOptions extends HttpClientOptions {}\n\n/**\n * Auth for the tracking endpoints (view/play-session/match/action), which accept\n * either a real user's `bearerToken` (full tracking, eligible for\n * quest/reward) or an `anonId` for an unauthenticated device\n * (analytics-only — the backend never awards quest/reward progress to an\n * anonymous id). `trackingSessionId`/`anonTrackingToken` come from\n * `bootstrapTrackingSession()` and should be attached either way, per the\n * platform's tracking contract.\n */\nexport interface TrackingAuth {\n bearerToken?: string;\n anonId?: string;\n trackingSessionId?: string;\n anonTrackingToken?: string;\n}\n\n/**\n * Auth for the creator-secret tier (`createGameStoreCheckoutIntent`/\n * `purchaseGameStoreOffer`) — moves real coin balance. `creatorKey`/\n * `gameSecret` identify your integration (never embed these in\n * client/browser code); `bearerToken` identifies the player you're\n * purchasing on behalf of, same as any other authenticated call.\n */\nexport interface SdkKeyPairAuth {\n creatorKey: string;\n gameSecret: string;\n bearerToken: string;\n trackingSessionId?: string;\n}\n\n/**\n * Low-level HTTP client that maps 1:1 to backend routes.\n * Methods requiring user auth accept `bearerToken` explicitly.\n */\nexport class ServiceClient {\n private readonly http: HttpClient;\n\n constructor(options: ServiceClientOptions) {\n this.http = new HttpClient(options);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Auth\n // ─────────────────────────────────────────────────────────────────────────────\n\n async telegramLogin(telegramInitData: string): Promise<AuthResultDto> {\n const body: TelegramLoginRequest = { telegramInitData };\n return this.http.request('POST', '/account/telegram-login', { body });\n }\n\n async refresh(refreshToken: string): Promise<AuthResultDto> {\n const body: RefreshTokenRequest = { refreshToken };\n return this.http.request('POST', '/account/refresh', { body });\n }\n\n async logout(refreshToken: string): Promise<boolean> {\n const body: RefreshTokenRequest = { refreshToken };\n return this.http.request('POST', '/account/logout', { body });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Games — one SDK integration = one game, resolved on every call from the\n // public `x-game-key` header (the game's `appId`). There is no multi-game\n // catalog browsing here (list/search/detail across games) and no `:id`/\n // `storeId` path segments — that's the app-facing surface, out of scope\n // for this per-game SDK. Never use the creator-secret tier\n // (`x-creator-key`/`x-game-secret`) from client/browser code — that would\n // leak the secret to every player.\n // ─────────────────────────────────────────────────────────────────────────────\n\n async recordGameView(gameKey: string, auth: TrackingAuth = {}): Promise<boolean> {\n // `referer` is a forbidden header name — browsers attach it automatically,\n // it cannot (and doesn't need to) be set here.\n await this.http.request('POST', '/sdk/games/views/record', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n });\n return true;\n }\n\n /** Signs a fresh `playSessionToken` — required by `completePlaySession`/`completeGameplayMatch`/`recordGameplayAction`. */\n async startPlaySession(\n gameKey: string,\n auth: TrackingAuth = {},\n body: StartPlaySessionRequest = {}\n ): Promise<PlaySessionDto> {\n return this.http.request('POST', '/sdk/games/play-sessions/start', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n }\n\n /**\n * Re-issues a fresh `playSessionToken` for the SAME `playSessionId` — call\n * this instead of `startPlaySession` when refreshing an about-to-expire\n * (or just-expired, within the server's renewal grace window) token, so\n * long-running sessions keep a single `playSessionId` throughout.\n */\n async renewPlaySession(\n gameKey: string,\n auth: TrackingAuth = {},\n body: RenewPlaySessionRequest\n ): Promise<PlaySessionDto> {\n return this.http.request('POST', '/sdk/games/play-sessions/renew', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n }\n\n async completePlaySession(\n gameKey: string,\n auth: TrackingAuth,\n body: CompletePlaySessionRequest\n ): Promise<boolean> {\n await this.http.request('POST', '/sdk/games/play-sessions/complete', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n return true;\n }\n\n async completeGameplayMatch(\n gameKey: string,\n auth: TrackingAuth,\n body: CompleteGameplayMatchRequest\n ): Promise<boolean> {\n await this.http.request('POST', '/sdk/games/matches/complete', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n return true;\n }\n\n async recordGameplayAction(\n gameKey: string,\n auth: TrackingAuth,\n body: RecordGameplayActionRequest\n ): Promise<EmitGameEventResponse> {\n return this.http.request('POST', '/sdk/games/actions/record', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n }\n\n /**\n * Anonymous runtimes must call this before any tracking call; logged-in\n * runtimes should still call it to get a `trackingSessionId` for unified\n * tracing — see `GameTrackingSessionDto`.\n */\n async bootstrapTrackingSession(anonId?: string): Promise<GameTrackingSessionDto> {\n return this.http.request('POST', '/sdk/games/tracking/bootstrap', {\n headers: { 'x-looplay-anon-id': anonId },\n });\n }\n\n /**\n * Lightweight integration heartbeat for review/liveops. This intentionally\n * does not record a view/play metric.\n */\n async detectGameIntegration(gameKey: string): Promise<boolean> {\n await this.http.request('POST', '/sdk/games/integration/detect', {\n headers: { 'x-game-key': gameKey },\n });\n return true;\n }\n\n private trackingHeaders(auth: TrackingAuth): Record<string, string | undefined> {\n return {\n 'x-game-tracking-session-id': auth.trackingSessionId,\n 'x-looplay-anon-token': auth.anonTrackingToken,\n };\n }\n\n /** Public storefront (sections + offers) for the integration's game. Read-only. */\n async getStore(gameKey: string): Promise<GameStoreDto> {\n return this.http.request('GET', '/sdk/games/store/current', {\n headers: { 'x-game-key': gameKey },\n });\n }\n\n /** Public catalog of purchasable/ownable assets for the game. Read-only. */\n async listGameAssets(gameKey: string): Promise<GameAssetDto[]> {\n return this.http.request('GET', '/sdk/games/store/assets', {\n headers: { 'x-game-key': gameKey },\n });\n }\n\n /** Assets the authenticated player already owns for this game. */\n async listMyGameAssets(bearerToken: string, gameKey: string): Promise<GameOwnedAssetDto[]> {\n return this.http.request('GET', '/sdk/games/store/assets/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey },\n });\n }\n\n /** The authenticated player's past store purchases for this game. */\n async listMyStorePurchases(\n bearerToken: string,\n gameKey: string\n ): Promise<GameStoreOfferPurchaseResultDto[]> {\n return this.http.request('GET', '/sdk/games/store/purchases/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey },\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Self-serve purchase (public tier) — same trust level as tracking: public\n // `x-game-key` + the purchasing player's own bearer token, no backend or\n // secret pair required. Safe to call directly from client/browser code —\n // `checkoutToken` (short-lived, server-signed) plays the same role as\n // `playSessionToken` on the tracking routes. `ApiClient.purchaseStoreOffer`\n // wraps this pair for you.\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Signs a `checkoutToken` for one purchase — required by `purchaseMyStoreOffer`. */\n async createMyStoreCheckoutIntent(\n gameKey: string,\n bearerToken: string,\n body: SdkCreateGameStoreCheckoutIntentRequest,\n trackingSessionId?: string\n ): Promise<GameStoreCheckoutIntentDto> {\n return this.http.request('POST', '/sdk/games/store/checkout-intent/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey, 'x-game-tracking-session-id': trackingSessionId },\n body,\n });\n }\n\n async purchaseMyStoreOffer(\n gameKey: string,\n bearerToken: string,\n body: SdkPurchaseGameStoreOfferRuntimeRequest,\n trackingSessionId?: string\n ): Promise<GameStoreOfferPurchaseResultDto> {\n return this.http.request('POST', '/sdk/games/store/purchase/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey, 'x-game-tracking-session-id': trackingSessionId },\n body,\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Server-to-server (secret pair) — moves real coin balance. Requires the\n // creator+game *secret* pair (`x-creator-key`/`x-game-secret`), distinct\n // from the public `x-game-key` used everywhere above. Call these ONLY\n // from your own backend (e.g. a Node service holding the secret pair) —\n // never from client/browser code, or the secret is exposed to every\n // player. `ApiClient` deliberately does not expose these — it auto-injects\n // a *player's* access token for browser-facing calls and has no concept\n // of your creator secret. Prefer the self-serve tier above unless you\n // specifically need to initiate a purchase from your backend without the\n // player present.\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Signs a `checkoutToken` for one purchase — required by `purchaseGameStoreOffer`. */\n async createGameStoreCheckoutIntent(\n auth: SdkKeyPairAuth,\n body: SdkCreateGameStoreCheckoutIntentRequest\n ): Promise<GameStoreCheckoutIntentDto> {\n return this.http.request('POST', '/sdk/games/store/checkout-intent', {\n bearerToken: auth.bearerToken,\n headers: {\n 'x-creator-key': auth.creatorKey,\n 'x-game-secret': auth.gameSecret,\n 'x-game-tracking-session-id': auth.trackingSessionId,\n },\n body,\n });\n }\n\n async purchaseGameStoreOffer(\n auth: SdkKeyPairAuth,\n body: SdkPurchaseGameStoreOfferRuntimeRequest\n ): Promise<GameStoreOfferPurchaseResultDto> {\n return this.http.request('POST', '/sdk/games/store/purchase', {\n bearerToken: auth.bearerToken,\n headers: {\n 'x-creator-key': auth.creatorKey,\n 'x-game-secret': auth.gameSecret,\n 'x-game-tracking-session-id': auth.trackingSessionId,\n },\n body,\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Balance\n // ─────────────────────────────────────────────────────────────────────────────\n\n async getBalances(bearerToken: string, query?: Record<string, any>): Promise<any> {\n return this.http.request('GET', '/sdk/balance', { bearerToken, query });\n }\n\n async getBalanceHistory(\n bearerToken: string,\n query?: Record<string, any>\n ): Promise<PagingResponse<any>> {\n return this.http.request('GET', '/sdk/balance/history', { bearerToken, query });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // User\n // ─────────────────────────────────────────────────────────────────────────────\n\n async getMyProfile(bearerToken: string): Promise<any> {\n return this.http.request('GET', '/sdk/user/profile', { bearerToken });\n }\n\n async getMyBalance(bearerToken: string): Promise<any> {\n return this.http.request('GET', '/sdk/user/balance', { bearerToken });\n }\n}\n","import { MissingBaseUrlError, NotAuthenticatedError } from '../errors';\nimport type {\n EmitGameEventResponse,\n GameAssetDto,\n GameEventKey,\n GameOwnedAssetDto,\n GameStoreDto,\n GameStoreOfferPurchaseResultDto,\n PagingResponse,\n RecordGameplayActionRequest,\n} from './LooplaySDK.types';\nimport { ServiceClient, type TrackingAuth } from './service-client';\nimport type { ServiceClientOptions } from './service-client';\n\nfunction generateId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback UUID v4 for environments without crypto.randomUUID. Not\n // cryptographically strong, but only used as a non-sensitive tracking id.\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\ninterface CachedTrackingSession {\n cacheKey: string;\n trackingSessionId: string;\n anonTrackingToken: string;\n expiresAtMs: number;\n}\n\n/** Signed `playSessionToken` for the current play session — required on every play/match/action call. */\ninterface CachedPlaySession {\n cacheKey: string;\n gameKey: string;\n playSessionId: string;\n playSessionToken: string;\n expiresAtMs: number;\n}\n\nexport interface ApiClientOptions extends Omit<ServiceClientOptions, 'baseUrl'> {\n baseUrl?: string;\n getAccessToken?: () => Promise<string | undefined>;\n /**\n * Resolves an anonymous device id, used for the tracking endpoints\n * (`trackPlay`/`trackMatch`/`emit`) when `getAccessToken` yields nothing.\n * Anonymous tracking is analytics-only — see `TrackingAuth`.\n */\n getAnonymousId?: () => string | undefined;\n}\n\n/**\n * High-level API client that injects user auth automatically.\n */\nexport class ApiClient {\n private readonly raw: ServiceClient;\n private readonly getAccessToken?: () => Promise<string | undefined>;\n private readonly getAnonymousId?: () => string | undefined;\n private trackingSession?: CachedTrackingSession;\n private trackingSessionPromiseKey?: string;\n private trackingSessionPromise?: Promise<CachedTrackingSession | undefined>;\n private currentPlaySessionId?: string;\n private playSession?: CachedPlaySession;\n private playSessionPromiseKey?: string;\n private playSessionPromise?: Promise<CachedPlaySession>;\n\n constructor(options: ApiClientOptions) {\n if (!options.baseUrl) throw new MissingBaseUrlError();\n\n this.raw = new ServiceClient({\n baseUrl: options.baseUrl,\n fetch: options.fetch,\n defaultHeaders: options.defaultHeaders,\n });\n\n this.getAccessToken = options.getAccessToken;\n this.getAnonymousId = options.getAnonymousId;\n }\n\n /** Expose the underlying route-level client (requires manual bearerToken/gameKey passing). */\n unsafeRaw(): ServiceClient {\n return this.raw;\n }\n\n async detectIntegration(gameKey: string): Promise<boolean> {\n return this.raw.detectGameIntegration(gameKey);\n }\n\n // Real-time (balance_change / store_purchase_completed WebSocket events)\n // deliberately lives outside this class — import `WsClient` from\n // '@looplay/sdk/realtime' and construct it with the same `getAccessToken`\n // you passed here. Keeps the socket.io-client dependency (and its bundle\n // weight) out of every consumer that doesn't need real-time updates.\n\n private async requireToken(): Promise<string> {\n const token = await this.getAccessToken?.();\n if (!token) throw new NotAuthenticatedError();\n return token;\n }\n\n /**\n * Resolves auth for the tracking endpoints: a real bearer token if logged\n * in, otherwise an anonymous device id. Throws only when neither is\n * available — anonymous tracking still requires *some* identity. Also\n * attaches a `trackingSessionId`/`anonTrackingToken` (bootstrapped and\n * cached lazily) — the backend's tracking contract expects these even for\n * logged-in callers, for unified tracing.\n */\n private async resolveTrackingAuth(): Promise<TrackingAuth> {\n const bearerToken = await this.getAccessToken?.();\n const anonId = bearerToken ? undefined : this.getAnonymousId?.();\n\n if (!bearerToken && !anonId) throw new NotAuthenticatedError();\n\n const session = await this.ensureTrackingSession(\n bearerToken ? `bearer:${bearerToken}` : `anon:${anonId}`,\n anonId\n );\n\n return {\n bearerToken,\n anonId,\n trackingSessionId: session?.trackingSessionId,\n anonTrackingToken: session?.anonTrackingToken,\n };\n }\n\n /**\n * Bootstraps (and caches until near expiry) the platform tracking\n * session. Swallows failures — tracking calls still work without it,\n * just without unified session tracing.\n */\n private async ensureTrackingSession(\n cacheKey: string,\n anonId?: string\n ): Promise<CachedTrackingSession | undefined> {\n const now = Date.now();\n if (\n this.trackingSession &&\n this.trackingSession.cacheKey === cacheKey &&\n this.trackingSession.expiresAtMs > now + 30_000\n ) {\n return this.trackingSession;\n }\n\n if (!this.trackingSessionPromise || this.trackingSessionPromiseKey !== cacheKey) {\n this.trackingSessionPromiseKey = cacheKey;\n this.trackingSessionPromise = this.raw\n .bootstrapTrackingSession(anonId)\n .then((dto) => {\n this.trackingSession = {\n cacheKey,\n trackingSessionId: dto.trackingSessionId,\n anonTrackingToken: dto.trackingToken,\n expiresAtMs: new Date(dto.expiresAt).getTime(),\n };\n return this.trackingSession;\n })\n .catch(() => undefined)\n .finally(() => {\n this.trackingSessionPromise = undefined;\n this.trackingSessionPromiseKey = undefined;\n });\n }\n\n return this.trackingSessionPromise;\n }\n\n private getTrackingAuthKey(auth: TrackingAuth): string {\n return [\n auth.bearerToken ? `bearer:${auth.bearerToken}` : `anon:${auth.anonId ?? ''}`,\n auth.trackingSessionId ?? '',\n auth.anonTrackingToken ?? '',\n ].join('\\n');\n }\n\n /**\n * Signs (and caches until near expiry) the `playSessionToken` required by\n * `trackPlay`/`trackMatch`/`emit` for the current play session — does not\n * swallow failures, unlike `ensureTrackingSession`, since these calls\n * are rejected outright without a valid token.\n */\n private async ensurePlaySession(\n gameKey: string,\n auth: TrackingAuth,\n playSessionId: string\n ): Promise<CachedPlaySession> {\n const now = Date.now();\n const cacheKey = [gameKey, playSessionId, this.getTrackingAuthKey(auth)].join('\\n');\n if (\n this.playSession &&\n this.playSession.cacheKey === cacheKey &&\n this.playSession.gameKey === gameKey &&\n this.playSession.playSessionId === playSessionId &&\n this.playSession.expiresAtMs > now + 10_000\n ) {\n return this.playSession;\n }\n\n // A previous token for this exact play session exists but is about to\n // (or already did) expire — renew it instead of starting a brand new\n // session, so playSessionId/playSessionToken stay stable across the\n // refresh instead of silently swapping token+session together.\n const previous =\n this.playSession &&\n this.playSession.cacheKey === cacheKey &&\n this.playSession.gameKey === gameKey &&\n this.playSession.playSessionId === playSessionId\n ? this.playSession\n : undefined;\n\n if (!this.playSessionPromise || this.playSessionPromiseKey !== cacheKey) {\n this.playSessionPromiseKey = cacheKey;\n const issue = previous\n ? this.raw\n .renewPlaySession(gameKey, auth, {\n playSessionId,\n playSessionToken: previous.playSessionToken,\n })\n // Renewal grace window lapsed (or some other rejection) — fall\n // back to starting fresh under the same playSessionId rather\n // than leaving the caller stuck.\n .catch(() => this.raw.startPlaySession(gameKey, auth, { playSessionId }))\n : this.raw.startPlaySession(gameKey, auth, { playSessionId });\n\n this.playSessionPromise = issue\n .then((dto) => {\n this.playSession = {\n cacheKey,\n gameKey,\n playSessionId: dto.playSessionId,\n playSessionToken: dto.playSessionToken,\n expiresAtMs: new Date(dto.expiresAt).getTime(),\n };\n return this.playSession;\n })\n .finally(() => {\n this.playSessionPromise = undefined;\n this.playSessionPromiseKey = undefined;\n });\n }\n\n return this.playSessionPromise;\n }\n\n /**\n * Call once when the game view opens, before any play/match tracking.\n * `gameKey` is the game's public `appId`.\n */\n async trackView(gameKey: string): Promise<boolean> {\n const auth = await this.resolveTrackingAuth();\n return this.raw.recordGameView(gameKey, auth);\n }\n\n /**\n * Starts a new play session and returns its id. Call when the user\n * presses Play; `trackPlay`/`trackMatch`/`emit` reuse this id (and the\n * signed `playSessionToken` backing it) across calls until the next\n * `startPlaySession()`, auto-starting one on first use if none was started.\n */\n startPlaySession(): string {\n this.currentPlaySessionId = generateId();\n this.playSession = undefined;\n return this.currentPlaySessionId;\n }\n\n async trackPlay(gameKey: string, playTimeSeconds?: number): Promise<boolean> {\n const auth = await this.resolveTrackingAuth();\n const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();\n const { playSessionToken } = await this.ensurePlaySession(gameKey, auth, playSessionId);\n return this.raw.completePlaySession(gameKey, auth, { playTimeSeconds, playSessionId, playSessionToken });\n }\n\n async trackMatch(\n gameKey: string,\n body: { matchId: string; matchDurationSeconds: number; isCompleted?: boolean; isWin?: boolean }\n ): Promise<boolean> {\n const auth = await this.resolveTrackingAuth();\n const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();\n const { playSessionToken } = await this.ensurePlaySession(gameKey, auth, playSessionId);\n return this.raw.completeGameplayMatch(gameKey, auth, { ...body, playSessionId, playSessionToken });\n }\n\n async emit(\n gameKey: string,\n actionCode: GameEventKey | string,\n opts?: { value?: number; refId?: string; payload?: Record<string, unknown> }\n ): Promise<EmitGameEventResponse> {\n const auth = await this.resolveTrackingAuth();\n const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();\n const { playSessionToken } = await this.ensurePlaySession(gameKey, auth, playSessionId);\n const body: RecordGameplayActionRequest = {\n playSessionId,\n playSessionToken,\n actionCode,\n value: opts?.value,\n refId: opts?.refId,\n payload: opts?.payload,\n };\n return this.raw.recordGameplayAction(gameKey, auth, body);\n }\n\n /** Fetches the storefront (sections + offers) for the integration's game. Read-only, no auth required. */\n async getStore(gameKey: string): Promise<GameStoreDto> {\n return this.raw.getStore(gameKey);\n }\n\n /** Public catalog of purchasable/ownable assets for the game. Read-only, no auth required. */\n async listGameAssets(gameKey: string): Promise<GameAssetDto[]> {\n return this.raw.listGameAssets(gameKey);\n }\n\n /** Assets the authenticated player already owns for this game. */\n async listMyGameAssets(gameKey: string): Promise<GameOwnedAssetDto[]> {\n const token = await this.requireToken();\n return this.raw.listMyGameAssets(token, gameKey);\n }\n\n /** Purchase history for the authenticated player in the game's store. */\n async listMyStorePurchases(gameKey: string): Promise<GameStoreOfferPurchaseResultDto[]> {\n const token = await this.requireToken();\n return this.raw.listMyStorePurchases(token, gameKey);\n }\n\n /**\n * Spends coin balance to purchase a store offer — signs a checkout intent\n * first, then redeems it, mirroring the play session flow above.\n * Self-serve: only the player's own access token is used, no secret pair\n * required, safe to call directly from the game client. Also see\n * `onStorePurchase` to react to the result in real time from any tab.\n */\n async purchaseStoreOffer(\n gameKey: string,\n offerCode: string,\n opts?: { requestId?: string; quantity?: number }\n ): Promise<GameStoreOfferPurchaseResultDto> {\n const token = await this.requireToken();\n const intent = await this.raw.createMyStoreCheckoutIntent(gameKey, token, {\n offerCode,\n requestId: opts?.requestId,\n quantity: opts?.quantity,\n });\n return this.raw.purchaseMyStoreOffer(gameKey, token, {\n offerCode: intent.offerCode,\n requestId: intent.requestId,\n quantity: intent.quantity,\n checkoutToken: intent.checkoutToken,\n });\n }\n\n async getMyProfile(): Promise<any> {\n const token = await this.requireToken();\n return this.raw.getMyProfile(token);\n }\n\n async getMyBalance(): Promise<any> {\n const token = await this.requireToken();\n return this.raw.getMyBalance(token);\n }\n\n async getBalances(query?: Record<string, any>): Promise<any> {\n const token = await this.requireToken();\n return this.raw.getBalances(token, query);\n }\n\n async getBalanceHistory(query?: Record<string, any>): Promise<PagingResponse<any>> {\n const token = await this.requireToken();\n return this.raw.getBalanceHistory(token, query);\n }\n}\n","export const DEFAULT_API_URL = 'https://miniapp-api.looplay.gg';\n\ndeclare global {\n interface ImportMetaEnv {\n readonly VITE_PARENT_ORIGIN?: string;\n readonly VITE_API_URL?: string;\n readonly VITE_LOOPLAY_API_URL?: string;\n readonly [key: string]: string | undefined;\n }\n\n interface ImportMeta {\n readonly env?: ImportMetaEnv;\n }\n}\n\n/**\n * Resolves the parentOrigin from environment variables (e.g. Vite or Node).\n */\nexport function resolveEnvParentOrigin(): string | undefined {\n try {\n if (typeof import.meta !== 'undefined' && import.meta.env?.VITE_PARENT_ORIGIN) {\n const val = import.meta.env.VITE_PARENT_ORIGIN;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n try {\n if (typeof process !== 'undefined' && process.env?.VITE_PARENT_ORIGIN) {\n const val = process.env.VITE_PARENT_ORIGIN;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n return undefined;\n}\n\n/**\n * Resolves the apiUrl from environment variables (e.g. Vite or Node).\n */\nexport function resolveEnvApiUrl(): string | undefined {\n try {\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n const val = import.meta.env.VITE_API_URL ?? import.meta.env.VITE_LOOPLAY_API_URL;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n try {\n if (typeof process !== 'undefined' && process.env) {\n const val = process.env.VITE_API_URL ?? process.env.VITE_LOOPLAY_API_URL;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n return undefined;\n}\n","import type { LooplayInitParams, LooplaySDKCreateOptions } from './types';\nimport { LooplayAuth } from './auth/looplay-auth';\nimport { ApiClient } from './apps/api-client';\nimport type { EmitGameEventResponse, GameEventKey } from './apps/LooplaySDK.types';\nimport { MissingBaseUrlError, NotInitializedError } from './errors';\nimport { DEFAULT_API_URL, resolveEnvApiUrl } from './constants';\n\nexport class LooplaySDK {\n readonly auth?: LooplayAuth;\n readonly api?: ApiClient;\n\n private gameId?: string;\n private initialized = false;\n\n constructor(options: LooplaySDKCreateOptions = {}) {\n const {\n auth,\n baseUrl = resolveEnvApiUrl() ?? DEFAULT_API_URL,\n fetch,\n defaultHeaders,\n } = options;\n\n if (auth) {\n this.auth = new LooplayAuth(auth);\n }\n\n if (baseUrl) {\n this.api = new ApiClient({\n baseUrl,\n fetch,\n defaultHeaders,\n getAccessToken: async () => this.auth?.getAccessToken(),\n });\n }\n }\n\n async init(params: LooplayInitParams): Promise<void> {\n this.gameId = params.gameId;\n await this.auth?.init();\n await this.detectIntegration(params);\n await this.verifyGameId(params);\n this.initialized = true;\n }\n\n async getAccessToken(): Promise<string | undefined> {\n return this.auth?.getAccessToken();\n }\n\n getGameId(): string | undefined {\n return this.gameId;\n }\n\n async getMyProfile(): Promise<any> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n return this.api.getMyProfile();\n }\n\n /** Call once when the game view opens, before any play/match tracking. */\n async trackView(): Promise<boolean> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.trackView(this.gameId);\n }\n\n /** Starts a new play session; call when the user presses Play. Returns the play session id. */\n startPlaySession(): string {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n return this.api.startPlaySession();\n }\n\n async trackPlay(playTimeSeconds?: number): Promise<boolean> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.trackPlay(this.gameId, playTimeSeconds);\n }\n\n /**\n * Report that a match/round ended.\n * Maps to PLAY_MATCH (and WIN_MATCH when isWin=true).\n * matchId is the idempotency anchor — safe to call twice with the same matchId.\n */\n async trackMatch(\n matchId: string,\n opts: { durationSeconds: number; isCompleted?: boolean; isWin?: boolean }\n ): Promise<boolean> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.trackMatch(this.gameId, {\n matchId,\n matchDurationSeconds: opts.durationSeconds,\n isCompleted: opts.isCompleted,\n isWin: opts.isWin,\n });\n }\n\n /**\n * Emit a custom action event (CUSTOM_ACTION metric).\n * Use GameEventKey for platform-defined codes; custom strings for game-specific quests.\n * Pass refId to make the call idempotent — same refId = same event, dedup-safe.\n */\n async emit(\n actionCode: GameEventKey | string,\n opts?: { value?: number; refId?: string; payload?: Record<string, unknown> }\n ): Promise<EmitGameEventResponse> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.emit(this.gameId, actionCode, opts);\n }\n\n private assertInitialized(): void {\n if (!this.initialized) throw new NotInitializedError();\n }\n\n private async verifyGameId(params: LooplayInitParams): Promise<void> {\n if ((params.verifyMode ?? 'none') === 'none') return;\n // strict: resolves gameId (the game's public appId) via a read-only,\n // unauthenticated call — throws if the game doesn't exist or isn't LIVE.\n if (!this.api) throw new MissingBaseUrlError();\n await this.api.listGameAssets(params.gameId);\n }\n\n /**\n * Best-effort self-report — must never block init(). A missing/misconfigured\n * whitelist (a separate setup step from SDK integration) makes the backend\n * reject this call; if that rejection propagated, the whole init() would\n * reject too and every other SDK method would throw NotInitializedError,\n * breaking a game over what's really just an unfinished onboarding step.\n */\n private async detectIntegration(params: LooplayInitParams): Promise<void> {\n if (!this.api) return;\n try {\n await this.api.detectIntegration(params.gameId);\n } catch (error) {\n console.warn(\n '[LooplaySDK] detectIntegration failed (SDK will still initialize) — ' +\n 'check that this game has a whitelisted origin/domain configured:',\n error\n );\n }\n }\n}\n","export function decodeJwtClaims(token: string | undefined): Record<string, unknown> | undefined {\n if (!token) return undefined;\n const parts = token.split('.');\n if (parts.length < 2) return undefined;\n\n try {\n const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n const padded = payload + '==='.slice((payload.length + 3) % 4);\n if (typeof (globalThis as any).atob !== 'function') return undefined;\n\n const json = (globalThis as any).atob(padded) as string;\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\nexport function decodeJwtExpMs(token: string | undefined): number | undefined {\n const exp = decodeJwtClaims(token)?.exp;\n return typeof exp === 'number' ? exp * 1000 : undefined;\n}\n","import { LooplaySDKError } from '../../errors';\nimport { ServiceClient, type ServiceClientOptions } from '../../apps/service-client';\nimport { decodeJwtExpMs } from '../jwt';\nimport type {\n AuthLoginParams,\n AuthLoginResult,\n AuthProvider,\n LooplaySession,\n LooplayUser\n} from '../types';\n\nexport interface TelegramAuthLoginParams extends AuthLoginParams {\n telegramInitData?: string;\n}\n\nexport interface TelegramAuthProviderOptions extends ServiceClientOptions {\n /**\n * Optional override for how to read Telegram init data.\n * If omitted, provider will try `params.telegramInitData` then `globalThis.Telegram.WebApp.initData`.\n */\n getTelegramInitData?: () => string | undefined;\n\n /**\n * Optional mapper from backend user payload to LooplayUser.\n * If omitted, provider will try common fields like id/_id/userId/telegramId.\n */\n mapUser?: (rawUser: Record<string, any>) => LooplayUser;\n}\n\nclass MissingTelegramInitDataError extends LooplaySDKError {\n constructor() {\n super('Missing Telegram init data');\n this.name = 'MissingTelegramInitDataError';\n }\n}\n\nclass MissingRefreshTokenError extends LooplaySDKError {\n constructor() {\n super('Missing refresh token');\n this.name = 'MissingRefreshTokenError';\n }\n}\n\nexport class TelegramAuthProvider implements AuthProvider {\n readonly id = 'telegram';\n\n private readonly client: ServiceClient;\n private readonly getTelegramInitData?: () => string | undefined;\n private readonly mapUser?: (rawUser: Record<string, any>) => LooplayUser;\n\n private session: LooplaySession | null = null;\n\n constructor(options: TelegramAuthProviderOptions) {\n this.client = new ServiceClient(options);\n this.getTelegramInitData = options.getTelegramInitData;\n this.mapUser = options.mapUser;\n }\n\n onSessionChanged = (session: LooplaySession | null): void => {\n this.session = session;\n };\n\n async login(params?: TelegramAuthLoginParams): Promise<AuthLoginResult> {\n const initData =\n params?.telegramInitData ??\n this.getTelegramInitData?.() ??\n (globalThis as any)?.Telegram?.WebApp?.initData;\n\n if (!initData) throw new MissingTelegramInitDataError();\n\n const result = await this.client.telegramLogin(initData);\n\n const rawUser = (result.user ?? {}) as Record<string, any>;\n const user = this.mapUser ? this.mapUser(rawUser) : this.defaultMapUser(rawUser);\n\n const session: LooplaySession = {\n user,\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: decodeJwtExpMs(result.accessToken)\n };\n\n this.session = session;\n return { session };\n }\n\n async refresh(): Promise<Pick<LooplaySession, 'accessToken' | 'refreshToken' | 'expiresAt'>> {\n const currentSession = this.session;\n const refreshToken = currentSession?.refreshToken;\n if (!currentSession || !refreshToken) throw new MissingRefreshTokenError();\n\n const result = await this.client.refresh(refreshToken);\n\n const next = {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: decodeJwtExpMs(result.accessToken)\n } satisfies Pick<LooplaySession, 'accessToken' | 'refreshToken' | 'expiresAt'>;\n\n this.session = { ...currentSession, ...next };\n return next;\n }\n\n async logout(): Promise<void> {\n const refreshToken = this.session?.refreshToken;\n\n if (refreshToken) {\n try {\n await this.client.logout(refreshToken);\n } catch {\n // best-effort\n }\n }\n\n this.session = null;\n }\n\n private defaultMapUser(raw: Record<string, any>): LooplayUser {\n const id = raw.id ?? raw._id ?? raw.userId ?? raw.telegramId;\n if (id === undefined || id === null || String(id).trim() === '') {\n throw new LooplaySDKError('Missing user id from auth response');\n }\n\n return {\n id: String(id),\n displayName: raw.displayName ?? raw.username ?? raw.name,\n avatarUrl: raw.avatarUrl ?? raw.photoUrl ?? raw.avatar\n };\n }\n}\n","import { ApiClient } from \"../apps/api-client\";\nimport type {\n EmitGameEventResponse,\n GameEventKey,\n} from \"../apps/LooplaySDK.types\";\nimport {\n DEFAULT_API_URL,\n resolveEnvApiUrl,\n resolveEnvParentOrigin,\n} from \"../constants\";\nimport type {\n EmitGameEventOptions,\n LooplayIframeAuthListener,\n LooplayIframeAuthOptions,\n LooplayIframeAuthState,\n RequestAdsOptions,\n TrackMatchOptions,\n} from \"./types\";\n\nconst DEFAULT_ANON_ID_STORAGE_KEY = \"looplay:anon-id\";\nconst DEFAULT_ANONYMOUS_FALLBACK_TIMEOUT_MS = 4000;\nconst DEFAULT_REQUEST_ADS_TIMEOUT_MS = 5000;\n\nconst INITIAL_STATE: LooplayIframeAuthState = {\n jwt: null,\n gameId: null,\n apiUrl: null,\n anonymousId: null,\n origin: null,\n receivedAt: null,\n};\n\ntype LooplayIframeAuthMessage =\n | {\n type: \"LOOPLAY_AUTH\";\n jwt?: unknown;\n gameId?: unknown;\n apiUrl?: unknown;\n }\n | {\n type: \"LOOPLAY_ADS_WATCHED\";\n requestId?: unknown;\n }\n | {\n type: \"LOOPLAY_ADS_UNAVAILABLE\";\n requestId?: unknown;\n };\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst toOptionalString = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null;\n const normalized = value.trim();\n return normalized ? normalized : null;\n};\n\nfunction generateAnonymousId(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n\n // Fallback UUID v4 for environments without crypto.randomUUID (older\n // browsers, non-secure contexts). Not cryptographically strong, but only\n // used as an anonymous, non-sensitive device identifier.\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nfunction readStoredAnonymousId(key: string): string | null {\n if (typeof window === \"undefined\" || !window.localStorage) return null;\n try {\n return window.localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction writeStoredAnonymousId(key: string, value: string): void {\n if (typeof window === \"undefined\" || !window.localStorage) return;\n try {\n window.localStorage.setItem(key, value);\n } catch {\n // Private browsing, storage full, or blocked — the id just won't\n // persist across reloads; tracking for this session still works.\n }\n}\n\n/**\n * Handles auth for games that may run in two contexts:\n *\n * 1. Embedded as an iframe inside the Looplay web app — the host page\n * pushes `{ type: 'LOOPLAY_AUTH', jwt?, gameId, apiUrl }` via postMessage\n * in response to a `LOOPLAY_AUTH_REQUEST`. Tracking calls use the real\n * user's bearer token when available, otherwise fall back to anonymous\n * tracking (analytics-only, not eligible for quest/reward).\n * 2. Standalone — published anywhere else, or the parent never responds.\n * Falls back to an anonymous, locally-generated device id. Tracking\n * still works (the backend records it for analytics), but never feeds\n * the quest/reward engine.\n *\n * Either way, `appId` (issued to the creator after registering the game)\n * is required to track — see `LooplayIframeAuthOptions.appId`.\n */\nexport class LooplayIframeAuth {\n private state: LooplayIframeAuthState = INITIAL_STATE;\n private initialized = false;\n private lifecycleTrackingInitialized = false;\n private lastGameStartedKey: string | null = null;\n private readonly integrationDetectionKeys = new Set<string>();\n private client: ApiClient | null = null;\n private readonly listeners = new Set<LooplayIframeAuthListener>();\n private readonly options: LooplayIframeAuthOptions;\n private messageListener: ((event: MessageEvent<unknown>) => void) | null =\n null;\n private anonymousFallbackTimer: ReturnType<typeof setTimeout> | null = null;\n private pendingAdsRequests = new Map<\n string,\n {\n resolve: (value: boolean) => void;\n timer: ReturnType<typeof setTimeout> | null;\n }\n >();\n private requestAdsSequence = 0;\n private adsRequestInFlight = false;\n private adsRequestsSent = 0;\n private lastAdsRequestAt = 0;\n private autoAdsActionCount = 0;\n\n constructor(options: LooplayIframeAuthOptions = {}) {\n this.options = options;\n }\n\n getState(): LooplayIframeAuthState {\n return this.state;\n }\n\n getJwt(): string | null {\n return this.state.jwt;\n }\n\n getApiUrl(): string | null {\n return (\n this.state.apiUrl ??\n this.options.apiUrl ??\n resolveEnvApiUrl() ??\n DEFAULT_API_URL\n );\n }\n\n /** Resolves to the configured `appId`, falling back to whatever the parent pushed as `gameId`. */\n getGameId(): string | null {\n return this.state.gameId ?? this.options.appId ?? null;\n }\n\n getAnonymousId(): string | null {\n return this.state.anonymousId;\n }\n\n /** True once authenticated (bearer) or anonymous tracking is ready, given a configured `apiUrl`/`appId`. */\n canTrack(): boolean {\n if (!this.getApiUrl() || !this.getGameId()) return false;\n return Boolean(this.state.jwt || this.state.anonymousId);\n }\n\n subscribe(listener: LooplayIframeAuthListener): () => void {\n this.listeners.add(listener);\n listener(this.state);\n return () => this.listeners.delete(listener);\n }\n\n requestAuth(): void {\n if (typeof window === \"undefined\" || window.parent === window) {\n this.debug(\"standalone mode detected; auth request skipped\");\n return;\n }\n\n this.debug(\"requesting auth from parent\", {\n targetOrigin: this.resolveParentOrigin() ?? \"*\",\n });\n window.parent.postMessage(\n { type: \"LOOPLAY_AUTH_REQUEST\" },\n this.resolveParentOrigin() ?? \"*\"\n );\n }\n\n /**\n * Requests the parent host to show a rewarded ad.\n * In a Telegram Mini App setup, the game sends this request from the iframe\n * and the parent page (the Mini App shell) bridges it to Adsgram, then\n * responds with `LOOPLAY_ADS_WATCHED` after the ad finishes.\n */\n requestAds(options: RequestAdsOptions = {}): Promise<boolean> {\n if (typeof window === \"undefined\" || window.parent === window) {\n this.debug(\"requestAds skipped; standalone mode detected\");\n return Promise.resolve(false);\n }\n\n if (this.adsRequestInFlight) {\n this.debug(\"requestAds skipped; another ad request is already in flight\");\n return Promise.resolve(false);\n }\n\n const parentOrigin = this.resolveParentOrigin() ?? \"*\";\n const requestId = `ads-${Date.now()}-${++this.requestAdsSequence}`;\n const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_ADS_TIMEOUT_MS;\n\n this.adsRequestInFlight = true;\n this.adsRequestsSent += 1;\n this.lastAdsRequestAt = Date.now();\n this.debug(\"requesting rewarded ad from parent\", {\n requestId,\n targetOrigin: parentOrigin,\n gameId: this.getGameId(),\n });\n\n return new Promise<boolean>((resolve) => {\n const timer = setTimeout(() => {\n this.pendingAdsRequests.delete(requestId);\n this.adsRequestInFlight = false;\n this.debug(\"requestAds timed out\", { requestId, timeoutMs });\n resolve(false);\n }, timeoutMs);\n\n this.pendingAdsRequests.set(requestId, { resolve, timer });\n\n window.parent.postMessage(\n {\n type: \"LOOPLAY_REQUEST_ADS\",\n requestId,\n gameId: this.getGameId(),\n },\n parentOrigin\n );\n });\n }\n\n /** Idempotent; attaches the postMessage listener (if embedded) and arms the anonymous fallback. */\n init(): void {\n if (this.initialized || typeof window === \"undefined\") return;\n this.initialized = true;\n\n // When appId/apiUrl are supplied by the game (for example via env), the\n // integration can be detected immediately. If either value comes from\n // the parent, setState() below will retry once the auth message arrives.\n void this.detectIntegrationOnce();\n\n const isEmbedded = window.parent !== window;\n this.debug(\"auth listener initialized\", {\n isIframe: isEmbedded,\n parentOrigin: this.resolveParentOrigin(),\n });\n\n if (!isEmbedded) {\n // No parent frame to push auth at all — go anonymous right away.\n this.activateAnonymousMode();\n return;\n }\n\n const parentOrigin = this.resolveParentOrigin();\n\n if (!parentOrigin) {\n // `document.referrer` can be empty (Referrer-Policy, browser privacy\n // settings, extensions), which silently disables the origin check\n // below and lets any window that is literally `window.parent` push\n // auth. Pass `parentOrigin` explicitly to keep this check effective.\n console.warn(\n \"[LooplaySDK] LooplayIframeAuth could not resolve a parent origin to verify postMessage \" +\n \"against (document.referrer is empty). Auth messages from window.parent will be accepted \" +\n \"regardless of origin. Pass `parentOrigin` explicitly to harden this.\"\n );\n }\n\n this.messageListener = (event: MessageEvent<unknown>) => {\n if (event.source !== window.parent) return;\n if (parentOrigin && event.origin !== parentOrigin) {\n this.debug(\"ignored message from unexpected origin\", {\n expectedOrigin: parentOrigin,\n receivedOrigin: event.origin,\n });\n return;\n }\n\n this.handleIncomingMessage(event.data, event.origin);\n };\n\n window.addEventListener(\"message\", this.messageListener);\n\n // The host page might be an older protocol version, slow, or simply not\n // respond — don't leave the game untrackable forever.\n this.anonymousFallbackTimer = setTimeout(() => {\n if (this.state.jwt) return;\n this.activateAnonymousMode();\n }, this.options.anonymousFallbackTimeoutMs ?? DEFAULT_ANONYMOUS_FALLBACK_TIMEOUT_MS);\n\n this.requestAuth();\n }\n\n /** Removes the postMessage listener, cancels timers, and clears subscribers; safe to call multiple times. */\n dispose(): void {\n if (typeof window !== \"undefined\" && this.messageListener) {\n window.removeEventListener(\"message\", this.messageListener);\n }\n if (this.anonymousFallbackTimer !== null) {\n clearTimeout(this.anonymousFallbackTimer);\n }\n for (const pending of this.pendingAdsRequests.values()) {\n if (pending.timer !== null) clearTimeout(pending.timer);\n pending.resolve(false);\n }\n this.pendingAdsRequests.clear();\n\n this.messageListener = null;\n this.anonymousFallbackTimer = null;\n this.initialized = false;\n this.lifecycleTrackingInitialized = false;\n this.integrationDetectionKeys.clear();\n this.listeners.clear();\n }\n\n /** Lazily builds (and rebuilds on auth change) the `ApiClient` bound to the current auth mode. */\n getClient(): ApiClient {\n if (this.client) return this.client;\n\n const baseUrl = this.getApiUrl();\n\n this.debug(\"creating sdk ApiClient\", { baseUrl });\n this.client = new ApiClient({\n baseUrl: baseUrl ?? undefined,\n getAccessToken: async () => this.getJwt() ?? undefined,\n getAnonymousId: () => this.getAnonymousId() ?? undefined,\n });\n\n return this.client;\n }\n\n /** Call once when the game view opens, before any play/match tracking. */\n trackView(): Promise<boolean> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"trackView skipped; auth is not ready\", {\n hasGameId: Boolean(gameId),\n });\n return Promise.resolve(false);\n }\n\n this.debug(\"trackView dispatched\", { gameId });\n return this.getClient().trackView(gameId);\n }\n\n /** Starts a new play session; call when the user presses Play. Returns the play session id. */\n startPlaySession(): string {\n return this.getClient().startPlaySession();\n }\n\n trackPlay(playTimeSeconds?: number): Promise<boolean> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"trackPlay skipped; auth is not ready\", {\n hasGameId: Boolean(gameId),\n });\n return Promise.resolve(false);\n }\n\n this.debug(\"trackPlay dispatched\", { gameId, playTimeSeconds });\n return this.getClient().trackPlay(gameId, playTimeSeconds);\n }\n\n trackMatch(matchId: string, opts: TrackMatchOptions): Promise<boolean> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"trackMatch skipped; auth is not ready\", { matchId });\n return Promise.resolve(false);\n }\n\n this.debug(\"trackMatch dispatched\", { gameId, matchId, ...opts });\n const result = this.getClient().trackMatch(gameId, {\n matchId,\n matchDurationSeconds: opts.durationSeconds,\n isCompleted: opts.isCompleted,\n isWin: opts.isWin,\n });\n void result\n .then((ok) => {\n if (ok) this.recordAutoRequestAdsActivity();\n })\n .catch(() => undefined);\n return result;\n }\n\n emitGameEvent(\n actionCode: GameEventKey | string,\n opts?: EmitGameEventOptions\n ): Promise<EmitGameEventResponse | null> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"emitGameEvent skipped; auth is not ready\", { actionCode });\n return Promise.resolve(null);\n }\n\n this.debug(\"emitGameEvent dispatched\", { gameId, actionCode, ...opts });\n return this.getClient().emit(gameId, actionCode, opts);\n }\n\n /**\n * Idempotent; auto-emits GAME_STARTED exactly once per distinct auth\n * session (bearer or anonymous). SDK integration self-reporting for the\n * iframe path lives in `detectIntegrationOnce()` (fired from `setState()`\n * on every auth/config change, not gated behind lifecycle tracking being\n * enabled at all) — without it, games embedded via iframe would never\n * trigger the active detect call, only the passive heartbeat that\n * tracking calls leave behind (which doesn't fire while the game is still\n * IN_REVIEW/not LIVE, since tracking is blocked until then).\n */\n initLifecycleTracking(): void {\n if (this.lifecycleTrackingInitialized || typeof window === \"undefined\")\n return;\n this.lifecycleTrackingInitialized = true;\n this.debug(\"lifecycle tracking initialized\");\n\n this.subscribe(() => {\n const key = this.getTrackingKey();\n if (!key || this.lastGameStartedKey === key) return;\n\n this.lastGameStartedKey = key;\n this.debug(\"auto GAME_STARTED dispatch\");\n void this.emitGameEvent(\"GAME_STARTED\");\n });\n }\n\n private getTrackingKey(): string | null {\n const gameId = this.getGameId();\n const apiUrl = this.getApiUrl();\n const identity = this.state.jwt ?? this.state.anonymousId;\n if (!gameId || !apiUrl || !identity) return null;\n return `${apiUrl}\\n${gameId}\\n${identity}`;\n }\n\n /** Generates (or restores) a persisted anonymous device id and activates anonymous tracking. */\n private activateAnonymousMode(): void {\n if (this.state.anonymousId) return;\n\n const key =\n this.options.anonymousIdStorageKey ?? DEFAULT_ANON_ID_STORAGE_KEY;\n const anonymousId = readStoredAnonymousId(key) ?? generateAnonymousId();\n writeStoredAnonymousId(key, anonymousId);\n\n this.lastGameStartedKey = null;\n this.setState({ ...this.state, anonymousId, receivedAt: Date.now() });\n this.debug(\"anonymous tracking mode active\", { anonymousId });\n }\n\n private handleAuthMessage(\n data: Record<string, unknown>,\n origin: string\n ): void {\n if (this.anonymousFallbackTimer !== null) {\n clearTimeout(this.anonymousFallbackTimer);\n this.anonymousFallbackTimer = null;\n }\n\n const jwt = toOptionalString(data.jwt);\n const gameId = toOptionalString(data.gameId);\n const apiUrl = toOptionalString(data.apiUrl);\n const resolvedGameId = gameId ?? this.getGameId();\n const resolvedApiUrl = apiUrl ?? this.getApiUrl();\n\n if (!resolvedGameId || !resolvedApiUrl) {\n this.lastGameStartedKey = null;\n this.setState({\n ...this.state,\n jwt: null,\n gameId: null,\n apiUrl: null,\n origin,\n receivedAt: Date.now(),\n });\n this.debug(\n \"auth message missing game identity; falling back to anonymous tracking\"\n );\n this.activateAnonymousMode();\n return;\n }\n\n if (!jwt) {\n this.lastGameStartedKey = null;\n this.setState({\n ...this.state,\n jwt: null,\n gameId: resolvedGameId,\n apiUrl: resolvedApiUrl,\n origin,\n receivedAt: Date.now(),\n });\n this.debug(\n \"auth message missing jwt; falling back to anonymous tracking\",\n {\n gameId: resolvedGameId,\n apiUrl: resolvedApiUrl,\n }\n );\n this.activateAnonymousMode();\n return;\n }\n\n this.lastGameStartedKey = null;\n this.setState({\n jwt,\n gameId,\n apiUrl,\n anonymousId: null,\n origin,\n receivedAt: Date.now(),\n });\n }\n\n private handleRequestAdsResult(data: LooplayIframeAuthMessage): void {\n if (data.type !== \"LOOPLAY_ADS_WATCHED\") return;\n\n const requestId = toOptionalString(data.requestId);\n if (!requestId) return;\n\n const pending = this.pendingAdsRequests.get(requestId);\n if (!pending) return;\n\n this.pendingAdsRequests.delete(requestId);\n if (pending.timer !== null) clearTimeout(pending.timer);\n\n this.adsRequestInFlight = false;\n this.debug(\"requestAds watched message received\", { requestId });\n // TODO: call API to grant reward after the rewarded ad has been watched.\n pending.resolve(true);\n }\n\n private handleRequestAdsUnavailable(data: LooplayIframeAuthMessage): void {\n if (data.type !== \"LOOPLAY_ADS_UNAVAILABLE\") return;\n\n const requestId = toOptionalString(data.requestId);\n if (!requestId) return;\n\n const pending = this.pendingAdsRequests.get(requestId);\n if (!pending) return;\n\n this.pendingAdsRequests.delete(requestId);\n if (pending.timer !== null) clearTimeout(pending.timer);\n\n this.adsRequestInFlight = false;\n this.debug(\"requestAds unavailable message received\", { requestId });\n pending.resolve(false);\n }\n\n private handleIncomingMessage(data: unknown, origin: string): void {\n if (!isRecord(data)) return;\n\n if (data.type === \"LOOPLAY_AUTH\") {\n this.handleAuthMessage(data, origin);\n return;\n }\n\n if (data.type === \"LOOPLAY_ADS_WATCHED\") {\n this.handleRequestAdsResult(data as LooplayIframeAuthMessage);\n return;\n }\n\n if (data.type === \"LOOPLAY_ADS_UNAVAILABLE\") {\n this.handleRequestAdsUnavailable(data as LooplayIframeAuthMessage);\n return;\n }\n }\n\n private setState(next: LooplayIframeAuthState): void {\n const currentApiUrl = this.getApiUrl();\n this.state = next;\n if (this.getApiUrl() !== currentApiUrl) {\n this.client = null;\n }\n this.debug(\"auth state updated\", {\n gameId: this.getGameId(),\n apiUrl: this.getApiUrl(),\n origin: next.origin,\n hasJwt: Boolean(next.jwt),\n hasAnonymousId: Boolean(next.anonymousId),\n });\n this.listeners.forEach((listener) => listener(next));\n void this.detectIntegrationOnce();\n }\n\n /** Detects each resolved game/API pair at most once for this iframe session. */\n private async detectIntegrationOnce(): Promise<void> {\n const gameId = this.getGameId();\n const apiUrl = this.getApiUrl();\n if (!gameId || !apiUrl) return;\n\n const key = `${apiUrl}\\n${gameId}`;\n if (this.integrationDetectionKeys.has(key)) return;\n this.integrationDetectionKeys.add(key);\n\n try {\n await this.getClient().detectIntegration(gameId);\n this.debug(\"integration detected\", { gameId, apiUrl });\n } catch (error) {\n // Detection is a heartbeat and must not prevent auth/tracking from\n // working. Remove the key so a later auth/config update can retry it.\n this.integrationDetectionKeys.delete(key);\n this.debug(\"integration detection failed\", {\n gameId,\n apiUrl,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n private resolveParentOrigin(): string | null {\n if (this.options.parentOrigin) return this.options.parentOrigin;\n const envOrigin = resolveEnvParentOrigin();\n if (envOrigin) return envOrigin;\n if (typeof document === \"undefined\" || !document.referrer) return null;\n\n try {\n return new URL(document.referrer).origin;\n } catch {\n return null;\n }\n }\n\n private debug(message: string, details?: Record<string, unknown>): void {\n this.options.onDebug?.(message, details);\n }\n\n private recordAutoRequestAdsActivity(): void {\n this.autoAdsActionCount += 1;\n\n const config = this.options.autoRequestAds;\n if (!config?.enabled) return;\n if (this.adsRequestInFlight) return;\n if (!this.canTrack()) return;\n\n const now = Date.now();\n if (config.cooldownMs && now - this.lastAdsRequestAt < config.cooldownMs) {\n return;\n }\n\n if (config.maxRequestsPerSession && this.adsRequestsSent >= config.maxRequestsPerSession) {\n return;\n }\n\n const threshold = config.afterActionCount ?? 0;\n const shouldRequest = threshold > 0 && this.autoAdsActionCount % threshold === 0;\n\n if (!shouldRequest) return;\n\n const chance = config.chance ?? 1;\n if (chance <= 0 || Math.random() > chance) {\n this.debug(\"auto requestAds skipped by chance\", {\n actionCount: this.autoAdsActionCount,\n chance,\n });\n return;\n }\n\n this.debug(\"auto requestAds triggered\", {\n actionCount: this.autoAdsActionCount,\n });\n\n void this.requestAds();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/auth/storage.ts","../src/auth/looplay-auth.ts","../src/constants.ts","../src/version.ts","../src/apps/http.ts","../src/apps/service-client.ts","../src/apps/api-client.ts","../src/looplay-sdk.ts","../src/auth/jwt.ts","../src/auth/providers/telegram-auth-provider.ts","../src/iframe/iframe-auth.ts"],"names":["LooplaySDKError","message","NotInitializedError","MissingBaseUrlError","MissingAuthError","NotAuthenticatedError","MemoryAuthStorage","key","value","BrowserLocalStorageAuthStorage","InvalidSessionError","LooplayAuth","options","params","result","now","refreshed","next","eventName","listener","raw","parsed","event","DEFAULT_API_URL","resolveEnvParentOrigin","val","resolveEnvApiUrl","LOOPLAY_SDK_VERSION","getFetchFn","fetchOverride","HttpError","status","bodyText","HttpClient","rawBaseUrl","method","path","url","headers","body","res","text","sources","src","query","normalizedPath","ServiceClient","telegramInitData","refreshToken","gameKey","auth","anonId","bearerToken","trackingSessionId","generateId","c","r","ApiClient","baseUrl","token","session","cacheKey","dto","playSessionId","previous","issue","playTimeSeconds","playSessionToken","actionCode","opts","offerCode","intent","LooplaySDK","fetch","defaultHeaders","matchId","error","decodeJwtClaims","parts","payload","padded","json","decodeJwtExpMs","exp","MissingTelegramInitDataError","MissingRefreshTokenError","TelegramAuthProvider","initData","rawUser","currentSession","id","DEFAULT_ANON_ID_STORAGE_KEY","DEFAULT_ANONYMOUS_FALLBACK_TIMEOUT_MS","DEFAULT_REQUEST_ADS_TIMEOUT_MS","INITIAL_STATE","isRecord","toOptionalString","normalized","generateAnonymousId","readStoredAnonymousId","writeStoredAnonymousId","LooplayIframeAuth","parentOrigin","requestId","timeoutMs","resolve","timer","isEmbedded","pending","gameId","ok","apiUrl","identity","anonymousId","data","origin","jwt","resolvedGameId","resolvedApiUrl","currentApiUrl","opt","envOrigin","details","config","threshold","chance"],"mappings":"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","file":"looplay-sdk.min.js","sourcesContent":["export class LooplaySDKError extends Error {\n constructor(message?: string) {\n super(message);\n this.name = 'LooplaySDKError';\n }\n}\n\nexport class NotInitializedError extends LooplaySDKError {\n constructor() {\n super('LooplaySDK not initialized. Call init({ gameId }) first.');\n this.name = 'NotInitializedError';\n }\n}\n\nexport class MissingBaseUrlError extends LooplaySDKError {\n constructor() {\n super('Missing baseUrl. Provide `baseUrl` to enable HTTP integration.');\n this.name = 'MissingBaseUrlError';\n }\n}\n\nexport class MissingAuthError extends LooplaySDKError {\n constructor() {\n super('Missing auth. Provide `auth` options to enable user login/session.');\n this.name = 'MissingAuthError';\n }\n}\n\nexport class NotAuthenticatedError extends LooplaySDKError {\n constructor() {\n super('Not authenticated. Login is required for this operation.');\n this.name = 'NotAuthenticatedError';\n }\n}\n","import type { AuthStorage } from './types';\n\nexport class MemoryAuthStorage implements AuthStorage {\n private readonly map = new Map<string, string>();\n\n async getItem(key: string): Promise<string | null> {\n return this.map.has(key) ? (this.map.get(key) as string) : null;\n }\n\n async setItem(key: string, value: string): Promise<void> {\n this.map.set(key, value);\n }\n\n async removeItem(key: string): Promise<void> {\n this.map.delete(key);\n }\n}\n\nexport class BrowserLocalStorageAuthStorage implements AuthStorage {\n async getItem(key: string): Promise<string | null> {\n if (typeof window === 'undefined' || !window.localStorage) return null;\n return window.localStorage.getItem(key);\n }\n\n async setItem(key: string, value: string): Promise<void> {\n if (typeof window === 'undefined' || !window.localStorage) return;\n window.localStorage.setItem(key, value);\n }\n\n async removeItem(key: string): Promise<void> {\n if (typeof window === 'undefined' || !window.localStorage) return;\n window.localStorage.removeItem(key);\n }\n}\n","import { LooplaySDKError } from '../errors';\nimport {\n type AuthEventName,\n type AuthLoginParams,\n type AuthProvider,\n type AuthStorage,\n type LooplayAuthOptions,\n type LooplaySession\n} from './types';\nimport { MemoryAuthStorage } from './storage';\n\nclass InvalidSessionError extends LooplaySDKError {\n constructor() {\n super('Invalid session returned by auth provider');\n this.name = 'InvalidSessionError';\n }\n}\n\ntype Listener = (session: LooplaySession | null) => void;\n\nexport class LooplayAuth {\n private readonly provider: AuthProvider;\n private readonly storage: AuthStorage;\n private readonly key: string;\n\n private session: LooplaySession | null = null;\n private readonly listeners = new Set<Listener>();\n\n constructor(options: LooplayAuthOptions) {\n this.provider = options.provider;\n this.storage = options.storage ?? new MemoryAuthStorage();\n this.key = `${options.storageKeyPrefix ?? 'looplay'}:auth:session`;\n }\n\n async init(): Promise<void> {\n await this.provider.init?.();\n await this.restoreFromStorage();\n\n // Keep provider in sync with restored session (if any).\n await this.provider.onSessionChanged?.(this.session);\n }\n\n getSession(): LooplaySession | null {\n return this.session;\n }\n\n async login(params?: AuthLoginParams): Promise<LooplaySession> {\n const result = await this.provider.login(params);\n\n if (!result?.session?.user?.id) {\n throw new InvalidSessionError();\n }\n\n await this.setSession(result.session, 'login');\n return result.session;\n }\n\n async logout(): Promise<void> {\n await this.provider.logout();\n await this.setSession(null, 'logout');\n }\n\n async getAccessToken(): Promise<string | undefined> {\n if (!this.session) return undefined;\n\n const now = Date.now();\n const isExpired =\n typeof this.session.expiresAt === 'number' && this.session.expiresAt <= now;\n\n if (!isExpired) return this.session.accessToken;\n\n if (!this.provider.refresh) return this.session.accessToken;\n\n const refreshed = await this.provider.refresh();\n const next = { ...this.session, ...refreshed };\n await this.setSession(next, 'sessionChanged');\n\n return next.accessToken;\n }\n\n on(eventName: AuthEventName, listener: Listener): () => void {\n // eventName reserved for future filtering; for now notify on any change\n void eventName;\n\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private async restoreFromStorage(): Promise<void> {\n const raw = await this.storage.getItem(this.key);\n if (!raw) return;\n\n try {\n const parsed = JSON.parse(raw) as LooplaySession;\n if (parsed?.user?.id) {\n this.session = parsed;\n }\n } catch {\n // ignore corrupted cache\n await this.storage.removeItem(this.key);\n }\n }\n\n private async setSession(next: LooplaySession | null, event: AuthEventName): Promise<void> {\n this.session = next;\n\n await this.provider.onSessionChanged?.(this.session);\n\n if (next) {\n await this.storage.setItem(this.key, JSON.stringify(next));\n } else {\n await this.storage.removeItem(this.key);\n }\n\n for (const listener of this.listeners) {\n listener(this.session);\n }\n\n // reserved for future event-specific hooks\n void event;\n }\n}\n","export const DEFAULT_API_URL = 'https://miniapp-api.looplay.gg';\n\ndeclare global {\n interface ImportMetaEnv {\n readonly VITE_PARENT_ORIGIN?: string;\n readonly VITE_API_URL?: string;\n readonly VITE_LOOPLAY_API_URL?: string;\n readonly [key: string]: string | undefined;\n }\n\n interface ImportMeta {\n readonly env?: ImportMetaEnv;\n }\n}\n\n/**\n * Resolves the parentOrigin from environment variables (e.g. Vite or Node).\n */\nexport function resolveEnvParentOrigin(): string | undefined {\n try {\n if (typeof import.meta !== 'undefined' && import.meta.env?.VITE_PARENT_ORIGIN) {\n const val = import.meta.env.VITE_PARENT_ORIGIN;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n try {\n if (typeof process !== 'undefined' && process.env?.VITE_PARENT_ORIGIN) {\n const val = process.env.VITE_PARENT_ORIGIN;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n return undefined;\n}\n\n/**\n * Resolves the apiUrl from environment variables (e.g. Vite or Node).\n */\nexport function resolveEnvApiUrl(): string | undefined {\n try {\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n const val = import.meta.env.VITE_API_URL ?? import.meta.env.VITE_LOOPLAY_API_URL;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n try {\n if (typeof process !== 'undefined' && process.env) {\n const val = process.env.VITE_API_URL ?? process.env.VITE_LOOPLAY_API_URL;\n if (typeof val === 'string' && val.trim().length > 0) return val.trim();\n }\n } catch {\n // Ignore restricted environments\n }\n\n return undefined;\n}\n","export const LOOPLAY_SDK_VERSION = '0.8.10';\n","import { LOOPLAY_SDK_VERSION } from '../version';\nimport { DEFAULT_API_URL, resolveEnvApiUrl } from '../constants';\n\nexport type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nexport interface HttpClientOptions {\n baseUrl?: string;\n fetch?: FetchLike;\n defaultHeaders?: Record<string, string>;\n}\n\nfunction getFetchFn(fetchOverride?: FetchLike): FetchLike {\n if (fetchOverride) {\n if (typeof window !== 'undefined' && fetchOverride === window.fetch) {\n return window.fetch.bind(window);\n }\n\n return fetchOverride;\n }\n\n return globalThis.fetch.bind(globalThis);\n}\n\nexport class HttpError extends Error {\n readonly status: number;\n readonly bodyText?: string;\n\n constructor(message: string, status: number, bodyText?: string) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.bodyText = bodyText;\n }\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly fetchFn: FetchLike;\n private readonly defaultHeaders: Record<string, string>;\n\n constructor(options: HttpClientOptions = {}) {\n const rawBaseUrl =\n typeof options.baseUrl === 'string' && options.baseUrl.trim().length > 0\n ? options.baseUrl.trim()\n : resolveEnvApiUrl() ?? DEFAULT_API_URL;\n this.baseUrl = rawBaseUrl.replace(/\\/$/, '');\n this.fetchFn = getFetchFn(options.fetch);\n this.defaultHeaders = {\n 'x-looplay-sdk-version': LOOPLAY_SDK_VERSION,\n ...(options.defaultHeaders ?? {}),\n };\n }\n\n async request<T>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n path: string,\n options?: {\n query?: Record<string, string | number | boolean | undefined>;\n headers?: Record<string, string | undefined>;\n bearerToken?: string;\n /** Anonymous device id, used when there is no `bearerToken` (no logged-in user). */\n anonId?: string;\n body?: unknown;\n }\n ): Promise<T> {\n const url = this.buildUrl(path, options?.query);\n\n const headers: Record<string, string> = this.mergeHeaders(\n this.defaultHeaders,\n options?.headers\n );\n\n if (options?.bearerToken) {\n headers.Authorization = `Bearer ${options.bearerToken}`;\n } else if (options?.anonId) {\n headers['x-looplay-anon-id'] = options.anonId;\n }\n\n let body: BodyInit | undefined;\n if (options?.body !== undefined) {\n headers['Content-Type'] = headers['Content-Type'] ?? 'application/json';\n body = JSON.stringify(options.body);\n }\n\n const res = await this.fetchFn(url, { method, headers, body });\n\n if (!res.ok) {\n const text = await this.safeText(res);\n throw new HttpError(`HTTP ${res.status} ${res.statusText}`, res.status, text);\n }\n\n // Some endpoints may return empty body.\n const text = await this.safeText(res);\n if (!text) return undefined as T;\n\n return JSON.parse(text) as T;\n }\n\n private mergeHeaders(\n ...sources: Array<Record<string, string | undefined> | undefined>\n ): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const src of sources) {\n if (!src) continue;\n for (const [key, value] of Object.entries(src)) {\n if (value === undefined) continue;\n result[key] = value;\n }\n }\n\n return result;\n }\n\n private buildUrl(\n path: string,\n query?: Record<string, string | number | boolean | undefined>\n ): string {\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n const url = new URL(`${this.baseUrl}${normalizedPath}`);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n url.searchParams.set(key, String(value));\n }\n }\n\n return url.toString();\n }\n\n private async safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n }\n}\n","import { HttpClient, type HttpClientOptions } from './http';\nimport type {\n AuthResultDto,\n CompletePlaySessionRequest,\n CompleteGameplayMatchRequest,\n EmitGameEventResponse,\n GameAssetDto,\n GameOwnedAssetDto,\n PlaySessionDto,\n GameStoreCheckoutIntentDto,\n GameStoreDto,\n GameStoreOfferPurchaseResultDto,\n GameTrackingSessionDto,\n PagingResponse,\n RecordGameplayActionRequest,\n RefreshTokenRequest,\n RenewPlaySessionRequest,\n SdkCreateGameStoreCheckoutIntentRequest,\n SdkPurchaseGameStoreOfferRuntimeRequest,\n StartPlaySessionRequest,\n TelegramLoginRequest,\n} from './LooplaySDK.types';\n\nexport interface ServiceClientOptions extends HttpClientOptions {}\n\n/**\n * Auth for the tracking endpoints (view/play-session/match/action), which accept\n * either a real user's `bearerToken` (full tracking, eligible for\n * quest/reward) or an `anonId` for an unauthenticated device\n * (analytics-only — the backend never awards quest/reward progress to an\n * anonymous id). `trackingSessionId`/`anonTrackingToken` come from\n * `bootstrapTrackingSession()` and should be attached either way, per the\n * platform's tracking contract.\n */\nexport interface TrackingAuth {\n bearerToken?: string;\n anonId?: string;\n trackingSessionId?: string;\n anonTrackingToken?: string;\n}\n\n/**\n * Auth for the creator-secret tier (`createGameStoreCheckoutIntent`/\n * `purchaseGameStoreOffer`) — moves real coin balance. `creatorKey`/\n * `gameSecret` identify your integration (never embed these in\n * client/browser code); `bearerToken` identifies the player you're\n * purchasing on behalf of, same as any other authenticated call.\n */\nexport interface SdkKeyPairAuth {\n creatorKey: string;\n gameSecret: string;\n bearerToken: string;\n trackingSessionId?: string;\n}\n\n/**\n * Low-level HTTP client that maps 1:1 to backend routes.\n * Methods requiring user auth accept `bearerToken` explicitly.\n */\nexport class ServiceClient {\n private readonly http: HttpClient;\n\n constructor(options: ServiceClientOptions) {\n this.http = new HttpClient(options);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Auth\n // ─────────────────────────────────────────────────────────────────────────────\n\n async telegramLogin(telegramInitData: string): Promise<AuthResultDto> {\n const body: TelegramLoginRequest = { telegramInitData };\n return this.http.request('POST', '/account/telegram-login', { body });\n }\n\n async refresh(refreshToken: string): Promise<AuthResultDto> {\n const body: RefreshTokenRequest = { refreshToken };\n return this.http.request('POST', '/account/refresh', { body });\n }\n\n async logout(refreshToken: string): Promise<boolean> {\n const body: RefreshTokenRequest = { refreshToken };\n return this.http.request('POST', '/account/logout', { body });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Games — one SDK integration = one game, resolved on every call from the\n // public `x-game-key` header (the game's `appId`). There is no multi-game\n // catalog browsing here (list/search/detail across games) and no `:id`/\n // `storeId` path segments — that's the app-facing surface, out of scope\n // for this per-game SDK. Never use the creator-secret tier\n // (`x-creator-key`/`x-game-secret`) from client/browser code — that would\n // leak the secret to every player.\n // ─────────────────────────────────────────────────────────────────────────────\n\n async recordGameView(gameKey: string, auth: TrackingAuth = {}): Promise<boolean> {\n // `referer` is a forbidden header name — browsers attach it automatically,\n // it cannot (and doesn't need to) be set here.\n await this.http.request('POST', '/sdk/games/views/record', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n });\n return true;\n }\n\n /** Signs a fresh `playSessionToken` — required by `completePlaySession`/`completeGameplayMatch`/`recordGameplayAction`. */\n async startPlaySession(\n gameKey: string,\n auth: TrackingAuth = {},\n body: StartPlaySessionRequest = {}\n ): Promise<PlaySessionDto> {\n return this.http.request('POST', '/sdk/games/play-sessions/start', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n }\n\n /**\n * Re-issues a fresh `playSessionToken` for the SAME `playSessionId` — call\n * this instead of `startPlaySession` when refreshing an about-to-expire\n * (or just-expired, within the server's renewal grace window) token, so\n * long-running sessions keep a single `playSessionId` throughout.\n */\n async renewPlaySession(\n gameKey: string,\n auth: TrackingAuth = {},\n body: RenewPlaySessionRequest\n ): Promise<PlaySessionDto> {\n return this.http.request('POST', '/sdk/games/play-sessions/renew', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n }\n\n async completePlaySession(\n gameKey: string,\n auth: TrackingAuth,\n body: CompletePlaySessionRequest\n ): Promise<boolean> {\n await this.http.request('POST', '/sdk/games/play-sessions/complete', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n return true;\n }\n\n async completeGameplayMatch(\n gameKey: string,\n auth: TrackingAuth,\n body: CompleteGameplayMatchRequest\n ): Promise<boolean> {\n await this.http.request('POST', '/sdk/games/matches/complete', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n return true;\n }\n\n async recordGameplayAction(\n gameKey: string,\n auth: TrackingAuth,\n body: RecordGameplayActionRequest\n ): Promise<EmitGameEventResponse> {\n return this.http.request('POST', '/sdk/games/actions/record', {\n ...auth,\n headers: { 'x-game-key': gameKey, ...this.trackingHeaders(auth) },\n body,\n });\n }\n\n /**\n * Anonymous runtimes must call this before any tracking call; logged-in\n * runtimes should still call it to get a `trackingSessionId` for unified\n * tracing — see `GameTrackingSessionDto`.\n */\n async bootstrapTrackingSession(anonId?: string): Promise<GameTrackingSessionDto> {\n return this.http.request('POST', '/sdk/games/tracking/bootstrap', {\n headers: { 'x-looplay-anon-id': anonId },\n });\n }\n\n /**\n * Lightweight integration heartbeat for review/liveops. This intentionally\n * does not record a view/play metric.\n */\n async detectGameIntegration(gameKey: string): Promise<boolean> {\n await this.http.request('POST', '/sdk/games/integration/detect', {\n headers: { 'x-game-key': gameKey },\n });\n return true;\n }\n\n private trackingHeaders(auth: TrackingAuth): Record<string, string | undefined> {\n return {\n 'x-game-tracking-session-id': auth.trackingSessionId,\n 'x-looplay-anon-token': auth.anonTrackingToken,\n };\n }\n\n /** Public storefront (sections + offers) for the integration's game. Read-only. */\n async getStore(gameKey: string): Promise<GameStoreDto> {\n return this.http.request('GET', '/sdk/games/store/current', {\n headers: { 'x-game-key': gameKey },\n });\n }\n\n /** Public catalog of purchasable/ownable assets for the game. Read-only. */\n async listGameAssets(gameKey: string): Promise<GameAssetDto[]> {\n return this.http.request('GET', '/sdk/games/store/assets', {\n headers: { 'x-game-key': gameKey },\n });\n }\n\n /** Assets the authenticated player already owns for this game. */\n async listMyGameAssets(bearerToken: string, gameKey: string): Promise<GameOwnedAssetDto[]> {\n return this.http.request('GET', '/sdk/games/store/assets/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey },\n });\n }\n\n /** The authenticated player's past store purchases for this game. */\n async listMyStorePurchases(\n bearerToken: string,\n gameKey: string\n ): Promise<GameStoreOfferPurchaseResultDto[]> {\n return this.http.request('GET', '/sdk/games/store/purchases/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey },\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Self-serve purchase (public tier) — same trust level as tracking: public\n // `x-game-key` + the purchasing player's own bearer token, no backend or\n // secret pair required. Safe to call directly from client/browser code —\n // `checkoutToken` (short-lived, server-signed) plays the same role as\n // `playSessionToken` on the tracking routes. `ApiClient.purchaseStoreOffer`\n // wraps this pair for you.\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Signs a `checkoutToken` for one purchase — required by `purchaseMyStoreOffer`. */\n async createMyStoreCheckoutIntent(\n gameKey: string,\n bearerToken: string,\n body: SdkCreateGameStoreCheckoutIntentRequest,\n trackingSessionId?: string\n ): Promise<GameStoreCheckoutIntentDto> {\n return this.http.request('POST', '/sdk/games/store/checkout-intent/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey, 'x-game-tracking-session-id': trackingSessionId },\n body,\n });\n }\n\n async purchaseMyStoreOffer(\n gameKey: string,\n bearerToken: string,\n body: SdkPurchaseGameStoreOfferRuntimeRequest,\n trackingSessionId?: string\n ): Promise<GameStoreOfferPurchaseResultDto> {\n return this.http.request('POST', '/sdk/games/store/purchase/me', {\n bearerToken,\n headers: { 'x-game-key': gameKey, 'x-game-tracking-session-id': trackingSessionId },\n body,\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Server-to-server (secret pair) — moves real coin balance. Requires the\n // creator+game *secret* pair (`x-creator-key`/`x-game-secret`), distinct\n // from the public `x-game-key` used everywhere above. Call these ONLY\n // from your own backend (e.g. a Node service holding the secret pair) —\n // never from client/browser code, or the secret is exposed to every\n // player. `ApiClient` deliberately does not expose these — it auto-injects\n // a *player's* access token for browser-facing calls and has no concept\n // of your creator secret. Prefer the self-serve tier above unless you\n // specifically need to initiate a purchase from your backend without the\n // player present.\n // ─────────────────────────────────────────────────────────────────────────────\n\n /** Signs a `checkoutToken` for one purchase — required by `purchaseGameStoreOffer`. */\n async createGameStoreCheckoutIntent(\n auth: SdkKeyPairAuth,\n body: SdkCreateGameStoreCheckoutIntentRequest\n ): Promise<GameStoreCheckoutIntentDto> {\n return this.http.request('POST', '/sdk/games/store/checkout-intent', {\n bearerToken: auth.bearerToken,\n headers: {\n 'x-creator-key': auth.creatorKey,\n 'x-game-secret': auth.gameSecret,\n 'x-game-tracking-session-id': auth.trackingSessionId,\n },\n body,\n });\n }\n\n async purchaseGameStoreOffer(\n auth: SdkKeyPairAuth,\n body: SdkPurchaseGameStoreOfferRuntimeRequest\n ): Promise<GameStoreOfferPurchaseResultDto> {\n return this.http.request('POST', '/sdk/games/store/purchase', {\n bearerToken: auth.bearerToken,\n headers: {\n 'x-creator-key': auth.creatorKey,\n 'x-game-secret': auth.gameSecret,\n 'x-game-tracking-session-id': auth.trackingSessionId,\n },\n body,\n });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Balance\n // ─────────────────────────────────────────────────────────────────────────────\n\n async getBalances(bearerToken: string, query?: Record<string, any>): Promise<any> {\n return this.http.request('GET', '/sdk/balance', { bearerToken, query });\n }\n\n async getBalanceHistory(\n bearerToken: string,\n query?: Record<string, any>\n ): Promise<PagingResponse<any>> {\n return this.http.request('GET', '/sdk/balance/history', { bearerToken, query });\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // User\n // ─────────────────────────────────────────────────────────────────────────────\n\n async getMyProfile(bearerToken: string): Promise<any> {\n return this.http.request('GET', '/sdk/user/profile', { bearerToken });\n }\n\n async getMyBalance(bearerToken: string): Promise<any> {\n return this.http.request('GET', '/sdk/user/balance', { bearerToken });\n }\n}\n","import { MissingBaseUrlError, NotAuthenticatedError } from '../errors';\nimport { DEFAULT_API_URL, resolveEnvApiUrl } from '../constants';\nimport type {\n EmitGameEventResponse,\n GameAssetDto,\n GameEventKey,\n GameOwnedAssetDto,\n GameStoreDto,\n GameStoreOfferPurchaseResultDto,\n PagingResponse,\n RecordGameplayActionRequest,\n} from './LooplaySDK.types';\nimport { ServiceClient, type TrackingAuth } from './service-client';\nimport type { ServiceClientOptions } from './service-client';\n\nfunction generateId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback UUID v4 for environments without crypto.randomUUID. Not\n // cryptographically strong, but only used as a non-sensitive tracking id.\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\ninterface CachedTrackingSession {\n cacheKey: string;\n trackingSessionId: string;\n anonTrackingToken: string;\n expiresAtMs: number;\n}\n\n/** Signed `playSessionToken` for the current play session — required on every play/match/action call. */\ninterface CachedPlaySession {\n cacheKey: string;\n gameKey: string;\n playSessionId: string;\n playSessionToken: string;\n expiresAtMs: number;\n}\n\nexport interface ApiClientOptions extends Omit<ServiceClientOptions, 'baseUrl'> {\n baseUrl?: string;\n getAccessToken?: () => Promise<string | undefined>;\n /**\n * Resolves an anonymous device id, used for the tracking endpoints\n * (`trackPlay`/`trackMatch`/`emit`) when `getAccessToken` yields nothing.\n * Anonymous tracking is analytics-only — see `TrackingAuth`.\n */\n getAnonymousId?: () => string | undefined;\n}\n\n/**\n * High-level API client that injects user auth automatically.\n */\nexport class ApiClient {\n private readonly raw: ServiceClient;\n private readonly getAccessToken?: () => Promise<string | undefined>;\n private readonly getAnonymousId?: () => string | undefined;\n private trackingSession?: CachedTrackingSession;\n private trackingSessionPromiseKey?: string;\n private trackingSessionPromise?: Promise<CachedTrackingSession | undefined>;\n private currentPlaySessionId?: string;\n private playSession?: CachedPlaySession;\n private playSessionPromiseKey?: string;\n private playSessionPromise?: Promise<CachedPlaySession>;\n\n constructor(options: ApiClientOptions = {}) {\n const baseUrl =\n typeof options.baseUrl === 'string' && options.baseUrl.trim().length > 0\n ? options.baseUrl.trim()\n : resolveEnvApiUrl() ?? DEFAULT_API_URL;\n\n if (!baseUrl) throw new MissingBaseUrlError();\n\n this.raw = new ServiceClient({\n baseUrl,\n fetch: options.fetch,\n defaultHeaders: options.defaultHeaders,\n });\n\n this.getAccessToken = options.getAccessToken;\n this.getAnonymousId = options.getAnonymousId;\n }\n\n /** Expose the underlying route-level client (requires manual bearerToken/gameKey passing). */\n unsafeRaw(): ServiceClient {\n return this.raw;\n }\n\n async detectIntegration(gameKey: string): Promise<boolean> {\n return this.raw.detectGameIntegration(gameKey);\n }\n\n // Real-time (balance_change / store_purchase_completed WebSocket events)\n // deliberately lives outside this class — import `WsClient` from\n // '@looplay/sdk/realtime' and construct it with the same `getAccessToken`\n // you passed here. Keeps the socket.io-client dependency (and its bundle\n // weight) out of every consumer that doesn't need real-time updates.\n\n private async requireToken(): Promise<string> {\n const token = await this.getAccessToken?.();\n if (!token) throw new NotAuthenticatedError();\n return token;\n }\n\n /**\n * Resolves auth for the tracking endpoints: a real bearer token if logged\n * in, otherwise an anonymous device id. Throws only when neither is\n * available — anonymous tracking still requires *some* identity. Also\n * attaches a `trackingSessionId`/`anonTrackingToken` (bootstrapped and\n * cached lazily) — the backend's tracking contract expects these even for\n * logged-in callers, for unified tracing.\n */\n private async resolveTrackingAuth(): Promise<TrackingAuth> {\n const bearerToken = await this.getAccessToken?.();\n const anonId = bearerToken ? undefined : this.getAnonymousId?.();\n\n if (!bearerToken && !anonId) throw new NotAuthenticatedError();\n\n const session = await this.ensureTrackingSession(\n bearerToken ? `bearer:${bearerToken}` : `anon:${anonId}`,\n anonId\n );\n\n return {\n bearerToken,\n anonId,\n trackingSessionId: session?.trackingSessionId,\n anonTrackingToken: session?.anonTrackingToken,\n };\n }\n\n /**\n * Bootstraps (and caches until near expiry) the platform tracking\n * session. Swallows failures — tracking calls still work without it,\n * just without unified session tracing.\n */\n private async ensureTrackingSession(\n cacheKey: string,\n anonId?: string\n ): Promise<CachedTrackingSession | undefined> {\n const now = Date.now();\n if (\n this.trackingSession &&\n this.trackingSession.cacheKey === cacheKey &&\n this.trackingSession.expiresAtMs > now + 30_000\n ) {\n return this.trackingSession;\n }\n\n if (!this.trackingSessionPromise || this.trackingSessionPromiseKey !== cacheKey) {\n this.trackingSessionPromiseKey = cacheKey;\n this.trackingSessionPromise = this.raw\n .bootstrapTrackingSession(anonId)\n .then((dto) => {\n this.trackingSession = {\n cacheKey,\n trackingSessionId: dto.trackingSessionId,\n anonTrackingToken: dto.trackingToken,\n expiresAtMs: new Date(dto.expiresAt).getTime(),\n };\n return this.trackingSession;\n })\n .catch(() => undefined)\n .finally(() => {\n this.trackingSessionPromise = undefined;\n this.trackingSessionPromiseKey = undefined;\n });\n }\n\n return this.trackingSessionPromise;\n }\n\n private getTrackingAuthKey(auth: TrackingAuth): string {\n return [\n auth.bearerToken ? `bearer:${auth.bearerToken}` : `anon:${auth.anonId ?? ''}`,\n auth.trackingSessionId ?? '',\n auth.anonTrackingToken ?? '',\n ].join('\\n');\n }\n\n /**\n * Signs (and caches until near expiry) the `playSessionToken` required by\n * `trackPlay`/`trackMatch`/`emit` for the current play session — does not\n * swallow failures, unlike `ensureTrackingSession`, since these calls\n * are rejected outright without a valid token.\n */\n private async ensurePlaySession(\n gameKey: string,\n auth: TrackingAuth,\n playSessionId: string\n ): Promise<CachedPlaySession> {\n const now = Date.now();\n const cacheKey = [gameKey, playSessionId, this.getTrackingAuthKey(auth)].join('\\n');\n if (\n this.playSession &&\n this.playSession.cacheKey === cacheKey &&\n this.playSession.gameKey === gameKey &&\n this.playSession.playSessionId === playSessionId &&\n this.playSession.expiresAtMs > now + 10_000\n ) {\n return this.playSession;\n }\n\n // A previous token for this exact play session exists but is about to\n // (or already did) expire — renew it instead of starting a brand new\n // session, so playSessionId/playSessionToken stay stable across the\n // refresh instead of silently swapping token+session together.\n const previous =\n this.playSession &&\n this.playSession.cacheKey === cacheKey &&\n this.playSession.gameKey === gameKey &&\n this.playSession.playSessionId === playSessionId\n ? this.playSession\n : undefined;\n\n if (!this.playSessionPromise || this.playSessionPromiseKey !== cacheKey) {\n this.playSessionPromiseKey = cacheKey;\n const issue = previous\n ? this.raw\n .renewPlaySession(gameKey, auth, {\n playSessionId,\n playSessionToken: previous.playSessionToken,\n })\n // Renewal grace window lapsed (or some other rejection) — fall\n // back to starting fresh under the same playSessionId rather\n // than leaving the caller stuck.\n .catch(() => this.raw.startPlaySession(gameKey, auth, { playSessionId }))\n : this.raw.startPlaySession(gameKey, auth, { playSessionId });\n\n this.playSessionPromise = issue\n .then((dto) => {\n this.playSession = {\n cacheKey,\n gameKey,\n playSessionId: dto.playSessionId,\n playSessionToken: dto.playSessionToken,\n expiresAtMs: new Date(dto.expiresAt).getTime(),\n };\n return this.playSession;\n })\n .finally(() => {\n this.playSessionPromise = undefined;\n this.playSessionPromiseKey = undefined;\n });\n }\n\n return this.playSessionPromise;\n }\n\n /**\n * Call once when the game view opens, before any play/match tracking.\n * `gameKey` is the game's public `appId`.\n */\n async trackView(gameKey: string): Promise<boolean> {\n const auth = await this.resolveTrackingAuth();\n return this.raw.recordGameView(gameKey, auth);\n }\n\n /**\n * Starts a new play session and returns its id. Call when the user\n * presses Play; `trackPlay`/`trackMatch`/`emit` reuse this id (and the\n * signed `playSessionToken` backing it) across calls until the next\n * `startPlaySession()`, auto-starting one on first use if none was started.\n */\n startPlaySession(): string {\n this.currentPlaySessionId = generateId();\n this.playSession = undefined;\n return this.currentPlaySessionId;\n }\n\n async trackPlay(gameKey: string, playTimeSeconds?: number): Promise<boolean> {\n const auth = await this.resolveTrackingAuth();\n const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();\n const { playSessionToken } = await this.ensurePlaySession(gameKey, auth, playSessionId);\n return this.raw.completePlaySession(gameKey, auth, { playTimeSeconds, playSessionId, playSessionToken });\n }\n\n async trackMatch(\n gameKey: string,\n body: { matchId: string; matchDurationSeconds: number; isCompleted?: boolean; isWin?: boolean }\n ): Promise<boolean> {\n const auth = await this.resolveTrackingAuth();\n const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();\n const { playSessionToken } = await this.ensurePlaySession(gameKey, auth, playSessionId);\n return this.raw.completeGameplayMatch(gameKey, auth, { ...body, playSessionId, playSessionToken });\n }\n\n async emit(\n gameKey: string,\n actionCode: GameEventKey | string,\n opts?: { value?: number; refId?: string; payload?: Record<string, unknown> }\n ): Promise<EmitGameEventResponse> {\n const auth = await this.resolveTrackingAuth();\n const playSessionId = this.currentPlaySessionId ?? this.startPlaySession();\n const { playSessionToken } = await this.ensurePlaySession(gameKey, auth, playSessionId);\n const body: RecordGameplayActionRequest = {\n playSessionId,\n playSessionToken,\n actionCode,\n value: opts?.value,\n refId: opts?.refId,\n payload: opts?.payload,\n };\n return this.raw.recordGameplayAction(gameKey, auth, body);\n }\n\n /** Fetches the storefront (sections + offers) for the integration's game. Read-only, no auth required. */\n async getStore(gameKey: string): Promise<GameStoreDto> {\n return this.raw.getStore(gameKey);\n }\n\n /** Public catalog of purchasable/ownable assets for the game. Read-only, no auth required. */\n async listGameAssets(gameKey: string): Promise<GameAssetDto[]> {\n return this.raw.listGameAssets(gameKey);\n }\n\n /** Assets the authenticated player already owns for this game. */\n async listMyGameAssets(gameKey: string): Promise<GameOwnedAssetDto[]> {\n const token = await this.requireToken();\n return this.raw.listMyGameAssets(token, gameKey);\n }\n\n /** Purchase history for the authenticated player in the game's store. */\n async listMyStorePurchases(gameKey: string): Promise<GameStoreOfferPurchaseResultDto[]> {\n const token = await this.requireToken();\n return this.raw.listMyStorePurchases(token, gameKey);\n }\n\n /**\n * Spends coin balance to purchase a store offer — signs a checkout intent\n * first, then redeems it, mirroring the play session flow above.\n * Self-serve: only the player's own access token is used, no secret pair\n * required, safe to call directly from the game client. Also see\n * `onStorePurchase` to react to the result in real time from any tab.\n */\n async purchaseStoreOffer(\n gameKey: string,\n offerCode: string,\n opts?: { requestId?: string; quantity?: number }\n ): Promise<GameStoreOfferPurchaseResultDto> {\n const token = await this.requireToken();\n const intent = await this.raw.createMyStoreCheckoutIntent(gameKey, token, {\n offerCode,\n requestId: opts?.requestId,\n quantity: opts?.quantity,\n });\n return this.raw.purchaseMyStoreOffer(gameKey, token, {\n offerCode: intent.offerCode,\n requestId: intent.requestId,\n quantity: intent.quantity,\n checkoutToken: intent.checkoutToken,\n });\n }\n\n async getMyProfile(): Promise<any> {\n const token = await this.requireToken();\n return this.raw.getMyProfile(token);\n }\n\n async getMyBalance(): Promise<any> {\n const token = await this.requireToken();\n return this.raw.getMyBalance(token);\n }\n\n async getBalances(query?: Record<string, any>): Promise<any> {\n const token = await this.requireToken();\n return this.raw.getBalances(token, query);\n }\n\n async getBalanceHistory(query?: Record<string, any>): Promise<PagingResponse<any>> {\n const token = await this.requireToken();\n return this.raw.getBalanceHistory(token, query);\n }\n}\n","import type { LooplayInitParams, LooplaySDKCreateOptions } from './types';\nimport { LooplayAuth } from './auth/looplay-auth';\nimport { ApiClient } from './apps/api-client';\nimport type { EmitGameEventResponse, GameEventKey } from './apps/LooplaySDK.types';\nimport { MissingBaseUrlError, NotInitializedError } from './errors';\nimport { DEFAULT_API_URL, resolveEnvApiUrl } from './constants';\n\nexport class LooplaySDK {\n readonly auth?: LooplayAuth;\n readonly api?: ApiClient;\n\n private gameId?: string;\n private initialized = false;\n\n constructor(options: LooplaySDKCreateOptions = {}) {\n const {\n auth,\n fetch,\n defaultHeaders,\n } = options;\n\n const baseUrl =\n typeof options.baseUrl === 'string' && options.baseUrl.trim().length > 0\n ? options.baseUrl.trim()\n : resolveEnvApiUrl() ?? DEFAULT_API_URL;\n\n if (auth) {\n this.auth = new LooplayAuth(auth);\n }\n\n this.api = new ApiClient({\n baseUrl,\n fetch,\n defaultHeaders,\n getAccessToken: async () => this.auth?.getAccessToken(),\n });\n }\n\n async init(params: LooplayInitParams): Promise<void> {\n this.gameId = params.gameId;\n await this.auth?.init();\n await this.detectIntegration(params);\n await this.verifyGameId(params);\n this.initialized = true;\n }\n\n async getAccessToken(): Promise<string | undefined> {\n return this.auth?.getAccessToken();\n }\n\n getGameId(): string | undefined {\n return this.gameId;\n }\n\n async getMyProfile(): Promise<any> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n return this.api.getMyProfile();\n }\n\n /** Call once when the game view opens, before any play/match tracking. */\n async trackView(): Promise<boolean> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.trackView(this.gameId);\n }\n\n /** Starts a new play session; call when the user presses Play. Returns the play session id. */\n startPlaySession(): string {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n return this.api.startPlaySession();\n }\n\n async trackPlay(playTimeSeconds?: number): Promise<boolean> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.trackPlay(this.gameId, playTimeSeconds);\n }\n\n /**\n * Report that a match/round ended.\n * Maps to PLAY_MATCH (and WIN_MATCH when isWin=true).\n * matchId is the idempotency anchor — safe to call twice with the same matchId.\n */\n async trackMatch(\n matchId: string,\n opts: { durationSeconds: number; isCompleted?: boolean; isWin?: boolean }\n ): Promise<boolean> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.trackMatch(this.gameId, {\n matchId,\n matchDurationSeconds: opts.durationSeconds,\n isCompleted: opts.isCompleted,\n isWin: opts.isWin,\n });\n }\n\n /**\n * Emit a custom action event (CUSTOM_ACTION metric).\n * Use GameEventKey for platform-defined codes; custom strings for game-specific quests.\n * Pass refId to make the call idempotent — same refId = same event, dedup-safe.\n */\n async emit(\n actionCode: GameEventKey | string,\n opts?: { value?: number; refId?: string; payload?: Record<string, unknown> }\n ): Promise<EmitGameEventResponse> {\n this.assertInitialized();\n if (!this.api) throw new MissingBaseUrlError();\n if (!this.gameId) throw new NotInitializedError();\n return this.api.emit(this.gameId, actionCode, opts);\n }\n\n private assertInitialized(): void {\n if (!this.initialized) throw new NotInitializedError();\n }\n\n private async verifyGameId(params: LooplayInitParams): Promise<void> {\n if ((params.verifyMode ?? 'none') === 'none') return;\n // strict: resolves gameId (the game's public appId) via a read-only,\n // unauthenticated call — throws if the game doesn't exist or isn't LIVE.\n if (!this.api) throw new MissingBaseUrlError();\n await this.api.listGameAssets(params.gameId);\n }\n\n /**\n * Best-effort self-report — must never block init(). A missing/misconfigured\n * whitelist (a separate setup step from SDK integration) makes the backend\n * reject this call; if that rejection propagated, the whole init() would\n * reject too and every other SDK method would throw NotInitializedError,\n * breaking a game over what's really just an unfinished onboarding step.\n */\n private async detectIntegration(params: LooplayInitParams): Promise<void> {\n if (!this.api) return;\n try {\n await this.api.detectIntegration(params.gameId);\n } catch (error) {\n console.warn(\n '[LooplaySDK] detectIntegration failed (SDK will still initialize) — ' +\n 'check that this game has a whitelisted origin/domain configured:',\n error\n );\n }\n }\n}\n","export function decodeJwtClaims(token: string | undefined): Record<string, unknown> | undefined {\n if (!token) return undefined;\n const parts = token.split('.');\n if (parts.length < 2) return undefined;\n\n try {\n const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n const padded = payload + '==='.slice((payload.length + 3) % 4);\n if (typeof (globalThis as any).atob !== 'function') return undefined;\n\n const json = (globalThis as any).atob(padded) as string;\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\nexport function decodeJwtExpMs(token: string | undefined): number | undefined {\n const exp = decodeJwtClaims(token)?.exp;\n return typeof exp === 'number' ? exp * 1000 : undefined;\n}\n","import { LooplaySDKError } from '../../errors';\nimport { ServiceClient, type ServiceClientOptions } from '../../apps/service-client';\nimport { decodeJwtExpMs } from '../jwt';\nimport type {\n AuthLoginParams,\n AuthLoginResult,\n AuthProvider,\n LooplaySession,\n LooplayUser\n} from '../types';\n\nexport interface TelegramAuthLoginParams extends AuthLoginParams {\n telegramInitData?: string;\n}\n\nexport interface TelegramAuthProviderOptions extends ServiceClientOptions {\n /**\n * Optional override for how to read Telegram init data.\n * If omitted, provider will try `params.telegramInitData` then `globalThis.Telegram.WebApp.initData`.\n */\n getTelegramInitData?: () => string | undefined;\n\n /**\n * Optional mapper from backend user payload to LooplayUser.\n * If omitted, provider will try common fields like id/_id/userId/telegramId.\n */\n mapUser?: (rawUser: Record<string, any>) => LooplayUser;\n}\n\nclass MissingTelegramInitDataError extends LooplaySDKError {\n constructor() {\n super('Missing Telegram init data');\n this.name = 'MissingTelegramInitDataError';\n }\n}\n\nclass MissingRefreshTokenError extends LooplaySDKError {\n constructor() {\n super('Missing refresh token');\n this.name = 'MissingRefreshTokenError';\n }\n}\n\nexport class TelegramAuthProvider implements AuthProvider {\n readonly id = 'telegram';\n\n private readonly client: ServiceClient;\n private readonly getTelegramInitData?: () => string | undefined;\n private readonly mapUser?: (rawUser: Record<string, any>) => LooplayUser;\n\n private session: LooplaySession | null = null;\n\n constructor(options: TelegramAuthProviderOptions) {\n this.client = new ServiceClient(options);\n this.getTelegramInitData = options.getTelegramInitData;\n this.mapUser = options.mapUser;\n }\n\n onSessionChanged = (session: LooplaySession | null): void => {\n this.session = session;\n };\n\n async login(params?: TelegramAuthLoginParams): Promise<AuthLoginResult> {\n const initData =\n params?.telegramInitData ??\n this.getTelegramInitData?.() ??\n (globalThis as any)?.Telegram?.WebApp?.initData;\n\n if (!initData) throw new MissingTelegramInitDataError();\n\n const result = await this.client.telegramLogin(initData);\n\n const rawUser = (result.user ?? {}) as Record<string, any>;\n const user = this.mapUser ? this.mapUser(rawUser) : this.defaultMapUser(rawUser);\n\n const session: LooplaySession = {\n user,\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: decodeJwtExpMs(result.accessToken)\n };\n\n this.session = session;\n return { session };\n }\n\n async refresh(): Promise<Pick<LooplaySession, 'accessToken' | 'refreshToken' | 'expiresAt'>> {\n const currentSession = this.session;\n const refreshToken = currentSession?.refreshToken;\n if (!currentSession || !refreshToken) throw new MissingRefreshTokenError();\n\n const result = await this.client.refresh(refreshToken);\n\n const next = {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: decodeJwtExpMs(result.accessToken)\n } satisfies Pick<LooplaySession, 'accessToken' | 'refreshToken' | 'expiresAt'>;\n\n this.session = { ...currentSession, ...next };\n return next;\n }\n\n async logout(): Promise<void> {\n const refreshToken = this.session?.refreshToken;\n\n if (refreshToken) {\n try {\n await this.client.logout(refreshToken);\n } catch {\n // best-effort\n }\n }\n\n this.session = null;\n }\n\n private defaultMapUser(raw: Record<string, any>): LooplayUser {\n const id = raw.id ?? raw._id ?? raw.userId ?? raw.telegramId;\n if (id === undefined || id === null || String(id).trim() === '') {\n throw new LooplaySDKError('Missing user id from auth response');\n }\n\n return {\n id: String(id),\n displayName: raw.displayName ?? raw.username ?? raw.name,\n avatarUrl: raw.avatarUrl ?? raw.photoUrl ?? raw.avatar\n };\n }\n}\n","import { ApiClient } from \"../apps/api-client\";\nimport type {\n EmitGameEventResponse,\n GameEventKey,\n} from \"../apps/LooplaySDK.types\";\nimport {\n DEFAULT_API_URL,\n resolveEnvApiUrl,\n resolveEnvParentOrigin,\n} from \"../constants\";\nimport type {\n EmitGameEventOptions,\n LooplayIframeAuthListener,\n LooplayIframeAuthOptions,\n LooplayIframeAuthState,\n RequestAdsOptions,\n TrackMatchOptions,\n} from \"./types\";\n\nconst DEFAULT_ANON_ID_STORAGE_KEY = \"looplay:anon-id\";\nconst DEFAULT_ANONYMOUS_FALLBACK_TIMEOUT_MS = 4000;\nconst DEFAULT_REQUEST_ADS_TIMEOUT_MS = 5000;\n\nconst INITIAL_STATE: LooplayIframeAuthState = {\n jwt: null,\n gameId: null,\n apiUrl: null,\n anonymousId: null,\n origin: null,\n receivedAt: null,\n};\n\ntype LooplayIframeAuthMessage =\n | {\n type: \"LOOPLAY_AUTH\";\n jwt?: unknown;\n gameId?: unknown;\n apiUrl?: unknown;\n }\n | {\n type: \"LOOPLAY_ADS_WATCHED\";\n requestId?: unknown;\n }\n | {\n type: \"LOOPLAY_ADS_UNAVAILABLE\";\n requestId?: unknown;\n };\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst toOptionalString = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null;\n const normalized = value.trim();\n return normalized ? normalized : null;\n};\n\nfunction generateAnonymousId(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n\n // Fallback UUID v4 for environments without crypto.randomUUID (older\n // browsers, non-secure contexts). Not cryptographically strong, but only\n // used as an anonymous, non-sensitive device identifier.\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nfunction readStoredAnonymousId(key: string): string | null {\n if (typeof window === \"undefined\" || !window.localStorage) return null;\n try {\n return window.localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction writeStoredAnonymousId(key: string, value: string): void {\n if (typeof window === \"undefined\" || !window.localStorage) return;\n try {\n window.localStorage.setItem(key, value);\n } catch {\n // Private browsing, storage full, or blocked — the id just won't\n // persist across reloads; tracking for this session still works.\n }\n}\n\n/**\n * Handles auth for games that may run in two contexts:\n *\n * 1. Embedded as an iframe inside the Looplay web app — the host page\n * pushes `{ type: 'LOOPLAY_AUTH', jwt?, gameId, apiUrl }` via postMessage\n * in response to a `LOOPLAY_AUTH_REQUEST`. Tracking calls use the real\n * user's bearer token when available, otherwise fall back to anonymous\n * tracking (analytics-only, not eligible for quest/reward).\n * 2. Standalone — published anywhere else, or the parent never responds.\n * Falls back to an anonymous, locally-generated device id. Tracking\n * still works (the backend records it for analytics), but never feeds\n * the quest/reward engine.\n *\n * Either way, `appId` (issued to the creator after registering the game)\n * is required to track — see `LooplayIframeAuthOptions.appId`.\n */\nexport class LooplayIframeAuth {\n private state: LooplayIframeAuthState = INITIAL_STATE;\n private initialized = false;\n private lifecycleTrackingInitialized = false;\n private lastGameStartedKey: string | null = null;\n private readonly integrationDetectionKeys = new Set<string>();\n private client: ApiClient | null = null;\n private readonly listeners = new Set<LooplayIframeAuthListener>();\n private readonly options: LooplayIframeAuthOptions;\n private messageListener: ((event: MessageEvent<unknown>) => void) | null =\n null;\n private anonymousFallbackTimer: ReturnType<typeof setTimeout> | null = null;\n private pendingAdsRequests = new Map<\n string,\n {\n resolve: (value: boolean) => void;\n timer: ReturnType<typeof setTimeout> | null;\n }\n >();\n private requestAdsSequence = 0;\n private adsRequestInFlight = false;\n private adsRequestsSent = 0;\n private lastAdsRequestAt = 0;\n private autoAdsActionCount = 0;\n\n constructor(options: LooplayIframeAuthOptions = {}) {\n this.options = options;\n }\n\n getState(): LooplayIframeAuthState {\n return this.state;\n }\n\n getJwt(): string | null {\n return this.state.jwt;\n }\n\n getApiUrl(): string {\n const raw =\n toOptionalString(this.state.apiUrl) ??\n toOptionalString(this.options.apiUrl) ??\n resolveEnvApiUrl() ??\n DEFAULT_API_URL;\n return raw.trim();\n }\n\n /** Resolves to the configured `appId`, falling back to whatever the parent pushed as `gameId`. */\n getGameId(): string | null {\n return this.state.gameId ?? this.options.appId ?? null;\n }\n\n getAnonymousId(): string | null {\n return this.state.anonymousId;\n }\n\n /** True once authenticated (bearer) or anonymous tracking is ready, given a configured `apiUrl`/`appId`. */\n canTrack(): boolean {\n if (!this.getApiUrl() || !this.getGameId()) return false;\n return Boolean(this.state.jwt || this.state.anonymousId);\n }\n\n subscribe(listener: LooplayIframeAuthListener): () => void {\n this.listeners.add(listener);\n listener(this.state);\n return () => this.listeners.delete(listener);\n }\n\n requestAuth(): void {\n if (typeof window === \"undefined\" || window.parent === window) {\n this.debug(\"standalone mode detected; auth request skipped\");\n return;\n }\n\n this.debug(\"requesting auth from parent\", {\n targetOrigin: this.resolveParentOrigin() ?? \"*\",\n });\n window.parent.postMessage(\n { type: \"LOOPLAY_AUTH_REQUEST\" },\n this.resolveParentOrigin() ?? \"*\"\n );\n }\n\n /**\n * Requests the parent host to show a rewarded ad.\n * In a Telegram Mini App setup, the game sends this request from the iframe\n * and the parent page (the Mini App shell) bridges it to Adsgram, then\n * responds with `LOOPLAY_ADS_WATCHED` after the ad finishes.\n */\n requestAds(options: RequestAdsOptions = {}): Promise<boolean> {\n if (typeof window === \"undefined\" || window.parent === window) {\n this.debug(\"requestAds skipped; standalone mode detected\");\n return Promise.resolve(false);\n }\n\n if (this.adsRequestInFlight) {\n this.debug(\"requestAds skipped; another ad request is already in flight\");\n return Promise.resolve(false);\n }\n\n const parentOrigin = this.resolveParentOrigin() ?? \"*\";\n const requestId = `ads-${Date.now()}-${++this.requestAdsSequence}`;\n const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_ADS_TIMEOUT_MS;\n\n this.adsRequestInFlight = true;\n this.adsRequestsSent += 1;\n this.lastAdsRequestAt = Date.now();\n this.debug(\"requesting rewarded ad from parent\", {\n requestId,\n targetOrigin: parentOrigin,\n gameId: this.getGameId(),\n });\n\n return new Promise<boolean>((resolve) => {\n const timer = setTimeout(() => {\n this.pendingAdsRequests.delete(requestId);\n this.adsRequestInFlight = false;\n this.debug(\"requestAds timed out\", { requestId, timeoutMs });\n resolve(false);\n }, timeoutMs);\n\n this.pendingAdsRequests.set(requestId, { resolve, timer });\n\n window.parent.postMessage(\n {\n type: \"LOOPLAY_REQUEST_ADS\",\n requestId,\n gameId: this.getGameId(),\n },\n parentOrigin\n );\n });\n }\n\n /** Idempotent; attaches the postMessage listener (if embedded) and arms the anonymous fallback. */\n init(): void {\n if (this.initialized || typeof window === \"undefined\") return;\n this.initialized = true;\n\n // When appId/apiUrl are supplied by the game (for example via env), the\n // integration can be detected immediately. If either value comes from\n // the parent, setState() below will retry once the auth message arrives.\n void this.detectIntegrationOnce();\n\n const isEmbedded = window.parent !== window;\n this.debug(\"auth listener initialized\", {\n isIframe: isEmbedded,\n parentOrigin: this.resolveParentOrigin(),\n });\n\n if (!isEmbedded) {\n // No parent frame to push auth at all — go anonymous right away.\n this.activateAnonymousMode();\n return;\n }\n\n const parentOrigin = this.resolveParentOrigin();\n\n if (!parentOrigin) {\n // `document.referrer` can be empty (Referrer-Policy, browser privacy\n // settings, extensions), which silently disables the origin check\n // below and lets any window that is literally `window.parent` push\n // auth. Pass `parentOrigin` explicitly to keep this check effective.\n console.warn(\n \"[LooplaySDK] LooplayIframeAuth could not resolve a parent origin to verify postMessage \" +\n \"against (document.referrer is empty). Auth messages from window.parent will be accepted \" +\n \"regardless of origin. Pass `parentOrigin` explicitly to harden this.\"\n );\n }\n\n this.messageListener = (event: MessageEvent<unknown>) => {\n if (event.source !== window.parent) return;\n if (parentOrigin && event.origin !== parentOrigin) {\n this.debug(\"ignored message from unexpected origin\", {\n expectedOrigin: parentOrigin,\n receivedOrigin: event.origin,\n });\n return;\n }\n\n this.handleIncomingMessage(event.data, event.origin);\n };\n\n window.addEventListener(\"message\", this.messageListener);\n\n // The host page might be an older protocol version, slow, or simply not\n // respond — don't leave the game untrackable forever.\n this.anonymousFallbackTimer = setTimeout(() => {\n if (this.state.jwt) return;\n this.activateAnonymousMode();\n }, this.options.anonymousFallbackTimeoutMs ?? DEFAULT_ANONYMOUS_FALLBACK_TIMEOUT_MS);\n\n this.requestAuth();\n }\n\n /** Removes the postMessage listener, cancels timers, and clears subscribers; safe to call multiple times. */\n dispose(): void {\n if (typeof window !== \"undefined\" && this.messageListener) {\n window.removeEventListener(\"message\", this.messageListener);\n }\n if (this.anonymousFallbackTimer !== null) {\n clearTimeout(this.anonymousFallbackTimer);\n }\n for (const pending of this.pendingAdsRequests.values()) {\n if (pending.timer !== null) clearTimeout(pending.timer);\n pending.resolve(false);\n }\n this.pendingAdsRequests.clear();\n\n this.messageListener = null;\n this.anonymousFallbackTimer = null;\n this.initialized = false;\n this.lifecycleTrackingInitialized = false;\n this.integrationDetectionKeys.clear();\n this.listeners.clear();\n }\n\n /** Lazily builds (and rebuilds on auth change) the `ApiClient` bound to the current auth mode. */\n getClient(): ApiClient {\n if (this.client) return this.client;\n\n const baseUrl = this.getApiUrl();\n\n this.debug(\"creating sdk ApiClient\", { baseUrl });\n this.client = new ApiClient({\n baseUrl: baseUrl ?? undefined,\n getAccessToken: async () => this.getJwt() ?? undefined,\n getAnonymousId: () => this.getAnonymousId() ?? undefined,\n });\n\n return this.client;\n }\n\n /** Call once when the game view opens, before any play/match tracking. */\n trackView(): Promise<boolean> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"trackView skipped; auth is not ready\", {\n hasGameId: Boolean(gameId),\n });\n return Promise.resolve(false);\n }\n\n this.debug(\"trackView dispatched\", { gameId });\n return this.getClient().trackView(gameId);\n }\n\n /** Starts a new play session; call when the user presses Play. Returns the play session id. */\n startPlaySession(): string {\n return this.getClient().startPlaySession();\n }\n\n trackPlay(playTimeSeconds?: number): Promise<boolean> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"trackPlay skipped; auth is not ready\", {\n hasGameId: Boolean(gameId),\n });\n return Promise.resolve(false);\n }\n\n this.debug(\"trackPlay dispatched\", { gameId, playTimeSeconds });\n return this.getClient().trackPlay(gameId, playTimeSeconds);\n }\n\n trackMatch(matchId: string, opts: TrackMatchOptions): Promise<boolean> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"trackMatch skipped; auth is not ready\", { matchId });\n return Promise.resolve(false);\n }\n\n this.debug(\"trackMatch dispatched\", { gameId, matchId, ...opts });\n const result = this.getClient().trackMatch(gameId, {\n matchId,\n matchDurationSeconds: opts.durationSeconds,\n isCompleted: opts.isCompleted,\n isWin: opts.isWin,\n });\n void result\n .then((ok) => {\n if (ok) this.recordAutoRequestAdsActivity();\n })\n .catch(() => undefined);\n return result;\n }\n\n emitGameEvent(\n actionCode: GameEventKey | string,\n opts?: EmitGameEventOptions\n ): Promise<EmitGameEventResponse | null> {\n const gameId = this.getGameId();\n if (!this.canTrack() || !gameId) {\n this.debug(\"emitGameEvent skipped; auth is not ready\", { actionCode });\n return Promise.resolve(null);\n }\n\n this.debug(\"emitGameEvent dispatched\", { gameId, actionCode, ...opts });\n return this.getClient().emit(gameId, actionCode, opts);\n }\n\n /**\n * Idempotent; auto-emits GAME_STARTED exactly once per distinct auth\n * session (bearer or anonymous). SDK integration self-reporting for the\n * iframe path lives in `detectIntegrationOnce()` (fired from `setState()`\n * on every auth/config change, not gated behind lifecycle tracking being\n * enabled at all) — without it, games embedded via iframe would never\n * trigger the active detect call, only the passive heartbeat that\n * tracking calls leave behind (which doesn't fire while the game is still\n * IN_REVIEW/not LIVE, since tracking is blocked until then).\n */\n initLifecycleTracking(): void {\n if (this.lifecycleTrackingInitialized || typeof window === \"undefined\")\n return;\n this.lifecycleTrackingInitialized = true;\n this.debug(\"lifecycle tracking initialized\");\n\n this.subscribe(() => {\n const key = this.getTrackingKey();\n if (!key || this.lastGameStartedKey === key) return;\n\n this.lastGameStartedKey = key;\n this.debug(\"auto GAME_STARTED dispatch\");\n void this.emitGameEvent(\"GAME_STARTED\");\n });\n }\n\n private getTrackingKey(): string | null {\n const gameId = this.getGameId();\n const apiUrl = this.getApiUrl();\n const identity = this.state.jwt ?? this.state.anonymousId;\n if (!gameId || !apiUrl || !identity) return null;\n return `${apiUrl}\\n${gameId}\\n${identity}`;\n }\n\n /** Generates (or restores) a persisted anonymous device id and activates anonymous tracking. */\n private activateAnonymousMode(): void {\n if (this.state.anonymousId) return;\n\n const key =\n this.options.anonymousIdStorageKey ?? DEFAULT_ANON_ID_STORAGE_KEY;\n const anonymousId = readStoredAnonymousId(key) ?? generateAnonymousId();\n writeStoredAnonymousId(key, anonymousId);\n\n this.lastGameStartedKey = null;\n this.setState({ ...this.state, anonymousId, receivedAt: Date.now() });\n this.debug(\"anonymous tracking mode active\", { anonymousId });\n }\n\n private handleAuthMessage(\n data: Record<string, unknown>,\n origin: string\n ): void {\n if (this.anonymousFallbackTimer !== null) {\n clearTimeout(this.anonymousFallbackTimer);\n this.anonymousFallbackTimer = null;\n }\n\n const jwt = toOptionalString(data.jwt);\n const gameId = toOptionalString(data.gameId);\n const apiUrl = toOptionalString(data.apiUrl);\n const resolvedGameId = gameId ?? this.getGameId();\n const resolvedApiUrl = apiUrl ?? this.getApiUrl();\n\n if (!resolvedGameId || !resolvedApiUrl) {\n this.lastGameStartedKey = null;\n this.setState({\n ...this.state,\n jwt: null,\n gameId: null,\n apiUrl: null,\n origin,\n receivedAt: Date.now(),\n });\n this.debug(\n \"auth message missing game identity; falling back to anonymous tracking\"\n );\n this.activateAnonymousMode();\n return;\n }\n\n if (!jwt) {\n this.lastGameStartedKey = null;\n this.setState({\n ...this.state,\n jwt: null,\n gameId: resolvedGameId,\n apiUrl: resolvedApiUrl,\n origin,\n receivedAt: Date.now(),\n });\n this.debug(\n \"auth message missing jwt; falling back to anonymous tracking\",\n {\n gameId: resolvedGameId,\n apiUrl: resolvedApiUrl,\n }\n );\n this.activateAnonymousMode();\n return;\n }\n\n this.lastGameStartedKey = null;\n this.setState({\n jwt,\n gameId,\n apiUrl,\n anonymousId: null,\n origin,\n receivedAt: Date.now(),\n });\n }\n\n private handleRequestAdsResult(data: LooplayIframeAuthMessage): void {\n if (data.type !== \"LOOPLAY_ADS_WATCHED\") return;\n\n const requestId = toOptionalString(data.requestId);\n if (!requestId) return;\n\n const pending = this.pendingAdsRequests.get(requestId);\n if (!pending) return;\n\n this.pendingAdsRequests.delete(requestId);\n if (pending.timer !== null) clearTimeout(pending.timer);\n\n this.adsRequestInFlight = false;\n this.debug(\"requestAds watched message received\", { requestId });\n // TODO: call API to grant reward after the rewarded ad has been watched.\n pending.resolve(true);\n }\n\n private handleRequestAdsUnavailable(data: LooplayIframeAuthMessage): void {\n if (data.type !== \"LOOPLAY_ADS_UNAVAILABLE\") return;\n\n const requestId = toOptionalString(data.requestId);\n if (!requestId) return;\n\n const pending = this.pendingAdsRequests.get(requestId);\n if (!pending) return;\n\n this.pendingAdsRequests.delete(requestId);\n if (pending.timer !== null) clearTimeout(pending.timer);\n\n this.adsRequestInFlight = false;\n this.debug(\"requestAds unavailable message received\", { requestId });\n pending.resolve(false);\n }\n\n private handleIncomingMessage(data: unknown, origin: string): void {\n if (!isRecord(data)) return;\n\n if (data.type === \"LOOPLAY_AUTH\") {\n this.handleAuthMessage(data, origin);\n return;\n }\n\n if (data.type === \"LOOPLAY_ADS_WATCHED\") {\n this.handleRequestAdsResult(data as LooplayIframeAuthMessage);\n return;\n }\n\n if (data.type === \"LOOPLAY_ADS_UNAVAILABLE\") {\n this.handleRequestAdsUnavailable(data as LooplayIframeAuthMessage);\n return;\n }\n }\n\n private setState(next: LooplayIframeAuthState): void {\n const currentApiUrl = this.getApiUrl();\n this.state = next;\n if (this.getApiUrl() !== currentApiUrl) {\n this.client = null;\n }\n this.debug(\"auth state updated\", {\n gameId: this.getGameId(),\n apiUrl: this.getApiUrl(),\n origin: next.origin,\n hasJwt: Boolean(next.jwt),\n hasAnonymousId: Boolean(next.anonymousId),\n });\n this.listeners.forEach((listener) => listener(next));\n void this.detectIntegrationOnce();\n }\n\n /** Detects each resolved game/API pair at most once for this iframe session. */\n private async detectIntegrationOnce(): Promise<void> {\n const gameId = this.getGameId();\n const apiUrl = this.getApiUrl();\n if (!gameId || !apiUrl) return;\n\n const key = `${apiUrl}\\n${gameId}`;\n if (this.integrationDetectionKeys.has(key)) return;\n this.integrationDetectionKeys.add(key);\n\n try {\n await this.getClient().detectIntegration(gameId);\n this.debug(\"integration detected\", { gameId, apiUrl });\n } catch (error) {\n // Detection is a heartbeat and must not prevent auth/tracking from\n // working. Remove the key so a later auth/config update can retry it.\n this.integrationDetectionKeys.delete(key);\n this.debug(\"integration detection failed\", {\n gameId,\n apiUrl,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n private resolveParentOrigin(): string | null {\n if (this.options.parentOrigin) {\n const opt = toOptionalString(this.options.parentOrigin);\n if (opt) return opt;\n }\n const envOrigin = resolveEnvParentOrigin();\n if (envOrigin) return envOrigin;\n if (typeof document === \"undefined\" || !document.referrer) return null;\n\n try {\n return new URL(document.referrer).origin;\n } catch {\n return null;\n }\n }\n\n private debug(message: string, details?: Record<string, unknown>): void {\n this.options.onDebug?.(message, details);\n }\n\n private recordAutoRequestAdsActivity(): void {\n this.autoAdsActionCount += 1;\n\n const config = this.options.autoRequestAds;\n if (!config?.enabled) return;\n if (this.adsRequestInFlight) return;\n if (!this.canTrack()) return;\n\n const now = Date.now();\n if (config.cooldownMs && now - this.lastAdsRequestAt < config.cooldownMs) {\n return;\n }\n\n if (config.maxRequestsPerSession && this.adsRequestsSent >= config.maxRequestsPerSession) {\n return;\n }\n\n const threshold = config.afterActionCount ?? 0;\n const shouldRequest = threshold > 0 && this.autoAdsActionCount % threshold === 0;\n\n if (!shouldRequest) return;\n\n const chance = config.chance ?? 1;\n if (chance <= 0 || Math.random() > chance) {\n this.debug(\"auto requestAds skipped by chance\", {\n actionCount: this.autoAdsActionCount,\n chance,\n });\n return;\n }\n\n this.debug(\"auto requestAds triggered\", {\n actionCount: this.autoAdsActionCount,\n });\n\n void this.requestAds();\n }\n}\n"]}
@@ -25,7 +25,7 @@ export declare class ApiClient {
25
25
  private playSession?;
26
26
  private playSessionPromiseKey?;
27
27
  private playSessionPromise?;
28
- constructor(options: ApiClientOptions);
28
+ constructor(options?: ApiClientOptions);
29
29
  /** Expose the underlying route-level client (requires manual bearerToken/gameKey passing). */
30
30
  unsafeRaw(): ServiceClient;
31
31
  detectIntegration(gameKey: string): Promise<boolean>;
@@ -1,6 +1,6 @@
1
1
  export type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
2
2
  export interface HttpClientOptions {
3
- baseUrl: string;
3
+ baseUrl?: string;
4
4
  fetch?: FetchLike;
5
5
  defaultHeaders?: Record<string, string>;
6
6
  }
@@ -13,7 +13,7 @@ export declare class HttpClient {
13
13
  private readonly baseUrl;
14
14
  private readonly fetchFn;
15
15
  private readonly defaultHeaders;
16
- constructor(options: HttpClientOptions);
16
+ constructor(options?: HttpClientOptions);
17
17
  request<T>(method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE', path: string, options?: {
18
18
  query?: Record<string, string | number | boolean | undefined>;
19
19
  headers?: Record<string, string | undefined>;
@@ -37,7 +37,7 @@ export declare class LooplayIframeAuth {
37
37
  constructor(options?: LooplayIframeAuthOptions);
38
38
  getState(): LooplayIframeAuthState;
39
39
  getJwt(): string | null;
40
- getApiUrl(): string | null;
40
+ getApiUrl(): string;
41
41
  /** Resolves to the configured `appId`, falling back to whatever the parent pushed as `gameId`. */
42
42
  getGameId(): string | null;
43
43
  getAnonymousId(): string | null;
@@ -1 +1 @@
1
- export declare const LOOPLAY_SDK_VERSION = "0.8.5";
1
+ export declare const LOOPLAY_SDK_VERSION = "0.8.10";