@liveauth-labs/sdk 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +36 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +36 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -63,7 +63,6 @@ var LiveAuthPowTimeoutError = class extends Error {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
// src/index.ts
|
|
66
|
-
var import_meta = {};
|
|
67
66
|
var SDK_VERSION = "0.2.0";
|
|
68
67
|
var LiveAuth = class {
|
|
69
68
|
constructor(config) {
|
|
@@ -180,13 +179,42 @@ var LiveAuth = class {
|
|
|
180
179
|
if (!this.canUsePow()) {
|
|
181
180
|
return Promise.reject(new LiveAuthPowUnsupportedError());
|
|
182
181
|
}
|
|
182
|
+
const workerCode = `
|
|
183
|
+
self.onmessage = async (e) => {
|
|
184
|
+
const { projectPublicKey, challengeHex, targetHex, maxIterations = 50000000, progressInterval = 10000 } = e.data;
|
|
185
|
+
let nonce = 0;
|
|
186
|
+
const startTime = performance.now();
|
|
187
|
+
let lastProgressTime = startTime;
|
|
188
|
+
|
|
189
|
+
while (nonce < maxIterations) {
|
|
190
|
+
const input = projectPublicKey + ':' + challengeHex + ':' + nonce;
|
|
191
|
+
const hash = await sha256Hex(input);
|
|
192
|
+
if (hash <= targetHex) {
|
|
193
|
+
const elapsed = performance.now() - startTime;
|
|
194
|
+
self.postMessage({ type: 'solution', nonce, hashHex: hash, iterations: nonce + 1, hashesPerSec: Math.round((nonce + 1) / (elapsed / 1000)) });
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
nonce++;
|
|
198
|
+
if (nonce % progressInterval === 0) {
|
|
199
|
+
const now = performance.now();
|
|
200
|
+
self.postMessage({ type: 'progress', iterations: nonce, hashesPerSec: Math.round(progressInterval / ((now - lastProgressTime) / 1000)) });
|
|
201
|
+
lastProgressTime = now;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
self.postMessage({ type: 'timeout', iterations: nonce });
|
|
205
|
+
};
|
|
206
|
+
async function sha256Hex(input) {
|
|
207
|
+
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));
|
|
208
|
+
return [...new Uint8Array(buf)].map(b => b.toString(16).padStart(2, '0')).join('');
|
|
209
|
+
}
|
|
210
|
+
`;
|
|
211
|
+
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
212
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
183
213
|
return new Promise((resolve, reject) => {
|
|
184
|
-
const worker = new Worker(
|
|
185
|
-
new URL("./pow.worker.js", import_meta.url),
|
|
186
|
-
{ type: "module" }
|
|
187
|
-
);
|
|
214
|
+
const worker = new Worker(workerUrl);
|
|
188
215
|
const timeoutId = setTimeout(() => {
|
|
189
216
|
worker.terminate();
|
|
217
|
+
URL.revokeObjectURL(workerUrl);
|
|
190
218
|
reject(new LiveAuthPowTimeoutError(`PoW timed out after ${timeoutMs}ms`));
|
|
191
219
|
}, timeoutMs);
|
|
192
220
|
worker.onmessage = (e) => {
|
|
@@ -198,12 +226,14 @@ var LiveAuth = class {
|
|
|
198
226
|
if (data.type === "timeout") {
|
|
199
227
|
clearTimeout(timeoutId);
|
|
200
228
|
worker.terminate();
|
|
229
|
+
URL.revokeObjectURL(workerUrl);
|
|
201
230
|
reject(new LiveAuthPowTimeoutError(`PoW hit max iterations (${maxIterations})`));
|
|
202
231
|
return;
|
|
203
232
|
}
|
|
204
233
|
if (data.type === "solution" && data.nonce !== void 0 && data.hashHex) {
|
|
205
234
|
clearTimeout(timeoutId);
|
|
206
235
|
worker.terminate();
|
|
236
|
+
URL.revokeObjectURL(workerUrl);
|
|
207
237
|
resolve({ nonce: data.nonce, hashHex: data.hashHex });
|
|
208
238
|
return;
|
|
209
239
|
}
|
|
@@ -211,6 +241,7 @@ var LiveAuth = class {
|
|
|
211
241
|
worker.onerror = (e) => {
|
|
212
242
|
clearTimeout(timeoutId);
|
|
213
243
|
worker.terminate();
|
|
244
|
+
URL.revokeObjectURL(workerUrl);
|
|
214
245
|
reject(new LiveAuthPowUnsupportedError(`Worker error: ${e.message}`));
|
|
215
246
|
};
|
|
216
247
|
worker.postMessage({
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts"],"sourcesContent":["import type {\n LiveAuthResult,\n VerifyOptions,\n PowChallengeResponse,\n PowVerifyRequest,\n PowVerifyResponse,\n PowSolution,\n LiveAuthConfig,\n LightningStart\n} from './types';\nimport {\n LiveAuthCancelledError,\n LiveAuthTimeoutError,\n LiveAuthNetworkError,\n LiveAuthPowUnsupportedError,\n LiveAuthPowTimeoutError\n} from './errors';\nimport type { PowWorkerResult } from './pow.worker';\n\n// Re-export for consumers\nexport * from './types';\nexport * from './errors';\n\nconst SDK_VERSION = '0.2.0';\n\nexport class LiveAuth {\n private readonly baseUrl: string;\n private readonly headers: HeadersInit;\n\n constructor(private readonly config: LiveAuthConfig) {\n if (!config.publicKey) {\n throw new Error('LiveAuth: publicKey is required');\n }\n\n this.baseUrl = config.baseUrl ?? 'https://api.liveauth.app';\n\n this.headers = {\n 'Content-Type': 'application/json',\n 'X-LW-Public': config.publicKey,\n ...(config.apiKey && { 'Authorization': `Bearer ${config.apiKey}` }),\n 'X-LW-SDK-Version': SDK_VERSION\n };\n }\n\n /* ======================================================\n * PUBLIC ENTRYPOINT\n * ====================================================== */\n\n async verify(options: VerifyOptions = {}): Promise<LiveAuthResult> {\n const { \n forceLightning = false, \n onProgress,\n powTimeoutMs = 30_000,\n maxPowIterations = 50_000_000\n } = options;\n\n // Skip PoW if forced to Lightning or PoW not supported\n if (forceLightning) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'forced_lightning' }\n };\n }\n\n if (!this.canUsePow()) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_unsupported' }\n };\n }\n\n const startedAt = performance.now();\n\n try {\n const challenge = await this.getPowChallenge();\n const solution = await this.solvePow(challenge, { \n onProgress, \n timeoutMs: powTimeoutMs,\n maxIterations: maxPowIterations\n });\n\n const verifyRes = await this.verifyPow({\n challengeHex: challenge.challengeHex,\n nonce: solution.nonce,\n hashHex: solution.hashHex,\n expiresAtUnix: challenge.expiresAtUnix,\n difficultyBits: challenge.difficultyBits,\n sig: challenge.sig\n });\n\n if (verifyRes.verified && verifyRes.token) {\n return {\n method: 'pow',\n token: verifyRes.token,\n solveMs: Math.round(performance.now() - startedAt),\n difficultyBits: challenge.difficultyBits\n };\n }\n\n if (verifyRes.fallback === 'lightning') {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_server_fallback' }\n };\n }\n\n throw new Error('LiveAuth: verification failed');\n\n } catch (err) {\n // On PoW failure, fall back to Lightning\n if (err instanceof LiveAuthPowTimeoutError || err instanceof LiveAuthPowUnsupportedError) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { \n reason: 'pow_failed', \n detail: err.message \n }\n };\n }\n throw err;\n }\n }\n\n /* ======================================================\n * POW FLOW\n * ====================================================== */\n\n private async getPowChallenge(): Promise<PowChallengeResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/challenge`, {\n headers: this.headers\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW challenge failed');\n return res.json();\n }\n\n private async verifyPow(req: PowVerifyRequest): Promise<PowVerifyResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/verify`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(req)\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW verify failed');\n return res.json();\n }\n\n /* ======================================================\n * POW SOLVER (WORKER)\n * ====================================================== */\n\n private solvePow(\n challenge: PowChallengeResponse, \n options: {\n onProgress?: (hashesPerSec: number, iterations: number) => void;\n timeoutMs?: number;\n maxIterations?: number;\n } = {}\n ): Promise<PowSolution> {\n const { onProgress, timeoutMs = 30_000, maxIterations = 50_000_000 } = options;\n\n if (!this.canUsePow()) {\n return Promise.reject(new LiveAuthPowUnsupportedError());\n }\n\n return new Promise((resolve, reject) => {\n const worker = new Worker(\n new URL('./pow.worker.js', import.meta.url),\n { type: 'module' }\n );\n\n const timeoutId = setTimeout(() => {\n worker.terminate();\n reject(new LiveAuthPowTimeoutError(`PoW timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n worker.onmessage = (e: MessageEvent<PowWorkerResult>) => {\n const data = e.data;\n\n if (data.type === 'progress') {\n onProgress?.(data.hashesPerSec ?? 0, data.iterations ?? 0);\n return;\n }\n\n if (data.type === 'timeout') {\n clearTimeout(timeoutId);\n worker.terminate();\n reject(new LiveAuthPowTimeoutError(`PoW hit max iterations (${maxIterations})`));\n return;\n }\n\n if (data.type === 'solution' && data.nonce !== undefined && data.hashHex) {\n clearTimeout(timeoutId);\n worker.terminate();\n resolve({ nonce: data.nonce, hashHex: data.hashHex });\n return;\n }\n };\n\n worker.onerror = e => {\n clearTimeout(timeoutId);\n worker.terminate();\n reject(new LiveAuthPowUnsupportedError(`Worker error: ${e.message}`));\n };\n\n worker.postMessage({\n projectPublicKey: challenge.projectPublicKey,\n challengeHex: challenge.challengeHex,\n targetHex: challenge.targetHex,\n maxIterations\n });\n });\n }\n\n /* ======================================================\n * LIGHTNING FALLBACK\n * ====================================================== */\n\n private async startLightning(): Promise<LightningStart> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/auth/start`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ userHint: 'browser' })\n });\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning auth start failed');\n }\n\n return res.json();\n }\n\n async pollLightning(\n sessionId: string,\n options?: {\n timeoutMs?: number;\n signal?: AbortSignal;\n intervalMs?: number;\n }\n ): Promise<string> {\n const timeoutMs = options?.timeoutMs ?? 5 * 60_000; // 5 min\n const intervalMs = options?.intervalMs ?? 2000;\n const externalSignal = options?.signal;\n\n const controller = new AbortController();\n const signal = controller.signal;\n\n // If caller passes a signal, bridge it\n if (externalSignal) {\n if (externalSignal.aborted) {\n throw new LiveAuthCancelledError();\n }\n\n externalSignal.addEventListener('abort', () => {\n controller.abort();\n });\n }\n\n // Timeout enforcement\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, timeoutMs);\n\n try {\n while (true) {\n if (signal.aborted) {\n throw externalSignal?.aborted\n ? new LiveAuthCancelledError()\n : new LiveAuthTimeoutError();\n }\n\n const res = await fetch(\n `${this.baseUrl}/api/public/auth/confirm`,\n {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ sessionId }),\n signal\n }\n );\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning confirm failed');\n }\n\n const json = await res.json();\n\n if (json.verified && json.token) {\n return json.token;\n }\n\n await sleep(intervalMs);\n }\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /* ======================================================\n * UTILITIES\n * ====================================================== */\n\n private canUsePow(): boolean {\n try {\n // SSR / Node guard\n if (typeof window === 'undefined') return false;\n\n // Worker support\n if (typeof Worker === 'undefined') return false;\n\n // Basic URL support (needed for module workers)\n if (typeof URL === 'undefined') return false;\n\n // Crypto.subtle required for SHA-256\n if (typeof crypto === 'undefined' || !crypto.subtle) return false;\n\n return true;\n } catch {\n return false;\n }\n }\n\n private async fetchWithRetry(\n url: string,\n init?: RequestInit,\n retries = 2,\n backoffMs = 500\n ): Promise<Response> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const res = await fetch(url, init);\n return res;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n \n if (attempt < retries) {\n await sleep(backoffMs * Math.pow(2, attempt));\n }\n }\n }\n\n throw new LiveAuthNetworkError(\n `Request failed after ${retries + 1} attempts`,\n lastError\n );\n }\n}\n\n/* ======================================================\n * UTILS\n * ====================================================== */\n\nconst sleep = (ms: number) =>\n new Promise(resolve => setTimeout(resolve, ms));\n","export class LiveAuthTimeoutError extends Error {\n constructor(message = 'LiveAuth verification timed out') {\n super(message);\n this.name = 'LiveAuthTimeoutError';\n }\n}\n\nexport class LiveAuthCancelledError extends Error {\n constructor(message = 'LiveAuth verification cancelled') {\n super(message);\n this.name = 'LiveAuthCancelledError';\n }\n}\n\nexport class LiveAuthNetworkError extends Error {\n constructor(message = 'LiveAuth network request failed', public readonly cause?: Error) {\n super(message);\n this.name = 'LiveAuthNetworkError';\n }\n}\n\nexport class LiveAuthPowUnsupportedError extends Error {\n constructor(message = 'Proof-of-Work is not supported in this environment') {\n super(message);\n this.name = 'LiveAuthPowUnsupportedError';\n }\n}\n\nexport class LiveAuthPowTimeoutError extends Error {\n constructor(message = 'Proof-of-Work timed out') {\n super(message);\n this.name = 'LiveAuthPowTimeoutError';\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts"],"sourcesContent":["import type {\n LiveAuthResult,\n VerifyOptions,\n PowChallengeResponse,\n PowVerifyRequest,\n PowVerifyResponse,\n PowSolution,\n LiveAuthConfig,\n LightningStart\n} from './types';\nimport {\n LiveAuthCancelledError,\n LiveAuthTimeoutError,\n LiveAuthNetworkError,\n LiveAuthPowUnsupportedError,\n LiveAuthPowTimeoutError\n} from './errors';\nimport type { PowWorkerResult } from './pow.worker';\n\n// Re-export for consumers\nexport * from './types';\nexport * from './errors';\n\nconst SDK_VERSION = '0.2.0';\n\nexport class LiveAuth {\n private readonly baseUrl: string;\n private readonly headers: HeadersInit;\n\n constructor(private readonly config: LiveAuthConfig) {\n if (!config.publicKey) {\n throw new Error('LiveAuth: publicKey is required');\n }\n\n this.baseUrl = config.baseUrl ?? 'https://api.liveauth.app';\n\n this.headers = {\n 'Content-Type': 'application/json',\n 'X-LW-Public': config.publicKey,\n ...(config.apiKey && { 'Authorization': `Bearer ${config.apiKey}` }),\n 'X-LW-SDK-Version': SDK_VERSION\n };\n }\n\n /* ======================================================\n * PUBLIC ENTRYPOINT\n * ====================================================== */\n\n async verify(options: VerifyOptions = {}): Promise<LiveAuthResult> {\n const { \n forceLightning = false, \n onProgress,\n powTimeoutMs = 30_000,\n maxPowIterations = 50_000_000\n } = options;\n\n // Skip PoW if forced to Lightning or PoW not supported\n if (forceLightning) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'forced_lightning' }\n };\n }\n\n if (!this.canUsePow()) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_unsupported' }\n };\n }\n\n const startedAt = performance.now();\n\n try {\n const challenge = await this.getPowChallenge();\n const solution = await this.solvePow(challenge, { \n onProgress, \n timeoutMs: powTimeoutMs,\n maxIterations: maxPowIterations\n });\n\n const verifyRes = await this.verifyPow({\n challengeHex: challenge.challengeHex,\n nonce: solution.nonce,\n hashHex: solution.hashHex,\n expiresAtUnix: challenge.expiresAtUnix,\n difficultyBits: challenge.difficultyBits,\n sig: challenge.sig\n });\n\n if (verifyRes.verified && verifyRes.token) {\n return {\n method: 'pow',\n token: verifyRes.token,\n solveMs: Math.round(performance.now() - startedAt),\n difficultyBits: challenge.difficultyBits\n };\n }\n\n if (verifyRes.fallback === 'lightning') {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_server_fallback' }\n };\n }\n\n throw new Error('LiveAuth: verification failed');\n\n } catch (err) {\n // On PoW failure, fall back to Lightning\n if (err instanceof LiveAuthPowTimeoutError || err instanceof LiveAuthPowUnsupportedError) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { \n reason: 'pow_failed', \n detail: err.message \n }\n };\n }\n throw err;\n }\n }\n\n /* ======================================================\n * POW FLOW\n * ====================================================== */\n\n private async getPowChallenge(): Promise<PowChallengeResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/challenge`, {\n headers: this.headers\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW challenge failed');\n return res.json();\n }\n\n private async verifyPow(req: PowVerifyRequest): Promise<PowVerifyResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/verify`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(req)\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW verify failed');\n return res.json();\n }\n\n /* ======================================================\n * POW SOLVER (WORKER)\n * ====================================================== */\n\n private solvePow(\n challenge: PowChallengeResponse, \n options: {\n onProgress?: (hashesPerSec: number, iterations: number) => void;\n timeoutMs?: number;\n maxIterations?: number;\n } = {}\n ): Promise<PowSolution> {\n const { onProgress, timeoutMs = 30_000, maxIterations = 50_000_000 } = options;\n\n if (!this.canUsePow()) {\n return Promise.reject(new LiveAuthPowUnsupportedError());\n }\n\n // Inline worker as blob URL for better bundler compatibility\n const workerCode = `\n self.onmessage = async (e) => {\n const { projectPublicKey, challengeHex, targetHex, maxIterations = 50000000, progressInterval = 10000 } = e.data;\n let nonce = 0;\n const startTime = performance.now();\n let lastProgressTime = startTime;\n\n while (nonce < maxIterations) {\n const input = projectPublicKey + ':' + challengeHex + ':' + nonce;\n const hash = await sha256Hex(input);\n if (hash <= targetHex) {\n const elapsed = performance.now() - startTime;\n self.postMessage({ type: 'solution', nonce, hashHex: hash, iterations: nonce + 1, hashesPerSec: Math.round((nonce + 1) / (elapsed / 1000)) });\n return;\n }\n nonce++;\n if (nonce % progressInterval === 0) {\n const now = performance.now();\n self.postMessage({ type: 'progress', iterations: nonce, hashesPerSec: Math.round(progressInterval / ((now - lastProgressTime) / 1000)) });\n lastProgressTime = now;\n }\n }\n self.postMessage({ type: 'timeout', iterations: nonce });\n };\n async function sha256Hex(input) {\n const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n return [...new Uint8Array(buf)].map(b => b.toString(16).padStart(2, '0')).join('');\n }\n `;\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const workerUrl = URL.createObjectURL(blob);\n\n return new Promise((resolve, reject) => {\n const worker = new Worker(workerUrl);\n\n const timeoutId = setTimeout(() => {\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n reject(new LiveAuthPowTimeoutError(`PoW timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n worker.onmessage = (e: MessageEvent<PowWorkerResult>) => {\n const data = e.data;\n\n if (data.type === 'progress') {\n onProgress?.(data.hashesPerSec ?? 0, data.iterations ?? 0);\n return;\n }\n\n if (data.type === 'timeout') {\n clearTimeout(timeoutId);\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n reject(new LiveAuthPowTimeoutError(`PoW hit max iterations (${maxIterations})`));\n return;\n }\n\n if (data.type === 'solution' && data.nonce !== undefined && data.hashHex) {\n clearTimeout(timeoutId);\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n resolve({ nonce: data.nonce, hashHex: data.hashHex });\n return;\n }\n };\n\n worker.onerror = e => {\n clearTimeout(timeoutId);\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n reject(new LiveAuthPowUnsupportedError(`Worker error: ${e.message}`));\n };\n\n worker.postMessage({\n projectPublicKey: challenge.projectPublicKey,\n challengeHex: challenge.challengeHex,\n targetHex: challenge.targetHex,\n maxIterations\n });\n });\n }\n\n /* ======================================================\n * LIGHTNING FALLBACK\n * ====================================================== */\n\n private async startLightning(): Promise<LightningStart> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/auth/start`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ userHint: 'browser' })\n });\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning auth start failed');\n }\n\n return res.json();\n }\n\n async pollLightning(\n sessionId: string,\n options?: {\n timeoutMs?: number;\n signal?: AbortSignal;\n intervalMs?: number;\n }\n ): Promise<string> {\n const timeoutMs = options?.timeoutMs ?? 5 * 60_000; // 5 min\n const intervalMs = options?.intervalMs ?? 2000;\n const externalSignal = options?.signal;\n\n const controller = new AbortController();\n const signal = controller.signal;\n\n // If caller passes a signal, bridge it\n if (externalSignal) {\n if (externalSignal.aborted) {\n throw new LiveAuthCancelledError();\n }\n\n externalSignal.addEventListener('abort', () => {\n controller.abort();\n });\n }\n\n // Timeout enforcement\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, timeoutMs);\n\n try {\n while (true) {\n if (signal.aborted) {\n throw externalSignal?.aborted\n ? new LiveAuthCancelledError()\n : new LiveAuthTimeoutError();\n }\n\n const res = await fetch(\n `${this.baseUrl}/api/public/auth/confirm`,\n {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ sessionId }),\n signal\n }\n );\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning confirm failed');\n }\n\n const json = await res.json();\n\n if (json.verified && json.token) {\n return json.token;\n }\n\n await sleep(intervalMs);\n }\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /* ======================================================\n * UTILITIES\n * ====================================================== */\n\n private canUsePow(): boolean {\n try {\n // SSR / Node guard\n if (typeof window === 'undefined') return false;\n\n // Worker support\n if (typeof Worker === 'undefined') return false;\n\n // Basic URL support (needed for module workers)\n if (typeof URL === 'undefined') return false;\n\n // Crypto.subtle required for SHA-256\n if (typeof crypto === 'undefined' || !crypto.subtle) return false;\n\n return true;\n } catch {\n return false;\n }\n }\n\n private async fetchWithRetry(\n url: string,\n init?: RequestInit,\n retries = 2,\n backoffMs = 500\n ): Promise<Response> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const res = await fetch(url, init);\n return res;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n \n if (attempt < retries) {\n await sleep(backoffMs * Math.pow(2, attempt));\n }\n }\n }\n\n throw new LiveAuthNetworkError(\n `Request failed after ${retries + 1} attempts`,\n lastError\n );\n }\n}\n\n/* ======================================================\n * UTILS\n * ====================================================== */\n\nconst sleep = (ms: number) =>\n new Promise(resolve => setTimeout(resolve, ms));\n","export class LiveAuthTimeoutError extends Error {\n constructor(message = 'LiveAuth verification timed out') {\n super(message);\n this.name = 'LiveAuthTimeoutError';\n }\n}\n\nexport class LiveAuthCancelledError extends Error {\n constructor(message = 'LiveAuth verification cancelled') {\n super(message);\n this.name = 'LiveAuthCancelledError';\n }\n}\n\nexport class LiveAuthNetworkError extends Error {\n constructor(message = 'LiveAuth network request failed', public readonly cause?: Error) {\n super(message);\n this.name = 'LiveAuthNetworkError';\n }\n}\n\nexport class LiveAuthPowUnsupportedError extends Error {\n constructor(message = 'Proof-of-Work is not supported in this environment') {\n super(message);\n this.name = 'LiveAuthPowUnsupportedError';\n }\n}\n\nexport class LiveAuthPowTimeoutError extends Error {\n constructor(message = 'Proof-of-Work timed out') {\n super(message);\n this.name = 'LiveAuthPowTimeoutError';\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -148,13 +148,42 @@ var LiveAuth = class {
|
|
|
148
148
|
if (!this.canUsePow()) {
|
|
149
149
|
return Promise.reject(new LiveAuthPowUnsupportedError());
|
|
150
150
|
}
|
|
151
|
+
const workerCode = `
|
|
152
|
+
self.onmessage = async (e) => {
|
|
153
|
+
const { projectPublicKey, challengeHex, targetHex, maxIterations = 50000000, progressInterval = 10000 } = e.data;
|
|
154
|
+
let nonce = 0;
|
|
155
|
+
const startTime = performance.now();
|
|
156
|
+
let lastProgressTime = startTime;
|
|
157
|
+
|
|
158
|
+
while (nonce < maxIterations) {
|
|
159
|
+
const input = projectPublicKey + ':' + challengeHex + ':' + nonce;
|
|
160
|
+
const hash = await sha256Hex(input);
|
|
161
|
+
if (hash <= targetHex) {
|
|
162
|
+
const elapsed = performance.now() - startTime;
|
|
163
|
+
self.postMessage({ type: 'solution', nonce, hashHex: hash, iterations: nonce + 1, hashesPerSec: Math.round((nonce + 1) / (elapsed / 1000)) });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
nonce++;
|
|
167
|
+
if (nonce % progressInterval === 0) {
|
|
168
|
+
const now = performance.now();
|
|
169
|
+
self.postMessage({ type: 'progress', iterations: nonce, hashesPerSec: Math.round(progressInterval / ((now - lastProgressTime) / 1000)) });
|
|
170
|
+
lastProgressTime = now;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
self.postMessage({ type: 'timeout', iterations: nonce });
|
|
174
|
+
};
|
|
175
|
+
async function sha256Hex(input) {
|
|
176
|
+
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));
|
|
177
|
+
return [...new Uint8Array(buf)].map(b => b.toString(16).padStart(2, '0')).join('');
|
|
178
|
+
}
|
|
179
|
+
`;
|
|
180
|
+
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
181
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
151
182
|
return new Promise((resolve, reject) => {
|
|
152
|
-
const worker = new Worker(
|
|
153
|
-
new URL("./pow.worker.js", import.meta.url),
|
|
154
|
-
{ type: "module" }
|
|
155
|
-
);
|
|
183
|
+
const worker = new Worker(workerUrl);
|
|
156
184
|
const timeoutId = setTimeout(() => {
|
|
157
185
|
worker.terminate();
|
|
186
|
+
URL.revokeObjectURL(workerUrl);
|
|
158
187
|
reject(new LiveAuthPowTimeoutError(`PoW timed out after ${timeoutMs}ms`));
|
|
159
188
|
}, timeoutMs);
|
|
160
189
|
worker.onmessage = (e) => {
|
|
@@ -166,12 +195,14 @@ var LiveAuth = class {
|
|
|
166
195
|
if (data.type === "timeout") {
|
|
167
196
|
clearTimeout(timeoutId);
|
|
168
197
|
worker.terminate();
|
|
198
|
+
URL.revokeObjectURL(workerUrl);
|
|
169
199
|
reject(new LiveAuthPowTimeoutError(`PoW hit max iterations (${maxIterations})`));
|
|
170
200
|
return;
|
|
171
201
|
}
|
|
172
202
|
if (data.type === "solution" && data.nonce !== void 0 && data.hashHex) {
|
|
173
203
|
clearTimeout(timeoutId);
|
|
174
204
|
worker.terminate();
|
|
205
|
+
URL.revokeObjectURL(workerUrl);
|
|
175
206
|
resolve({ nonce: data.nonce, hashHex: data.hashHex });
|
|
176
207
|
return;
|
|
177
208
|
}
|
|
@@ -179,6 +210,7 @@ var LiveAuth = class {
|
|
|
179
210
|
worker.onerror = (e) => {
|
|
180
211
|
clearTimeout(timeoutId);
|
|
181
212
|
worker.terminate();
|
|
213
|
+
URL.revokeObjectURL(workerUrl);
|
|
182
214
|
reject(new LiveAuthPowUnsupportedError(`Worker error: ${e.message}`));
|
|
183
215
|
};
|
|
184
216
|
worker.postMessage({
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/index.ts"],"sourcesContent":["export class LiveAuthTimeoutError extends Error {\n constructor(message = 'LiveAuth verification timed out') {\n super(message);\n this.name = 'LiveAuthTimeoutError';\n }\n}\n\nexport class LiveAuthCancelledError extends Error {\n constructor(message = 'LiveAuth verification cancelled') {\n super(message);\n this.name = 'LiveAuthCancelledError';\n }\n}\n\nexport class LiveAuthNetworkError extends Error {\n constructor(message = 'LiveAuth network request failed', public readonly cause?: Error) {\n super(message);\n this.name = 'LiveAuthNetworkError';\n }\n}\n\nexport class LiveAuthPowUnsupportedError extends Error {\n constructor(message = 'Proof-of-Work is not supported in this environment') {\n super(message);\n this.name = 'LiveAuthPowUnsupportedError';\n }\n}\n\nexport class LiveAuthPowTimeoutError extends Error {\n constructor(message = 'Proof-of-Work timed out') {\n super(message);\n this.name = 'LiveAuthPowTimeoutError';\n }\n}\n","import type {\n LiveAuthResult,\n VerifyOptions,\n PowChallengeResponse,\n PowVerifyRequest,\n PowVerifyResponse,\n PowSolution,\n LiveAuthConfig,\n LightningStart\n} from './types';\nimport {\n LiveAuthCancelledError,\n LiveAuthTimeoutError,\n LiveAuthNetworkError,\n LiveAuthPowUnsupportedError,\n LiveAuthPowTimeoutError\n} from './errors';\nimport type { PowWorkerResult } from './pow.worker';\n\n// Re-export for consumers\nexport * from './types';\nexport * from './errors';\n\nconst SDK_VERSION = '0.2.0';\n\nexport class LiveAuth {\n private readonly baseUrl: string;\n private readonly headers: HeadersInit;\n\n constructor(private readonly config: LiveAuthConfig) {\n if (!config.publicKey) {\n throw new Error('LiveAuth: publicKey is required');\n }\n\n this.baseUrl = config.baseUrl ?? 'https://api.liveauth.app';\n\n this.headers = {\n 'Content-Type': 'application/json',\n 'X-LW-Public': config.publicKey,\n ...(config.apiKey && { 'Authorization': `Bearer ${config.apiKey}` }),\n 'X-LW-SDK-Version': SDK_VERSION\n };\n }\n\n /* ======================================================\n * PUBLIC ENTRYPOINT\n * ====================================================== */\n\n async verify(options: VerifyOptions = {}): Promise<LiveAuthResult> {\n const { \n forceLightning = false, \n onProgress,\n powTimeoutMs = 30_000,\n maxPowIterations = 50_000_000\n } = options;\n\n // Skip PoW if forced to Lightning or PoW not supported\n if (forceLightning) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'forced_lightning' }\n };\n }\n\n if (!this.canUsePow()) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_unsupported' }\n };\n }\n\n const startedAt = performance.now();\n\n try {\n const challenge = await this.getPowChallenge();\n const solution = await this.solvePow(challenge, { \n onProgress, \n timeoutMs: powTimeoutMs,\n maxIterations: maxPowIterations\n });\n\n const verifyRes = await this.verifyPow({\n challengeHex: challenge.challengeHex,\n nonce: solution.nonce,\n hashHex: solution.hashHex,\n expiresAtUnix: challenge.expiresAtUnix,\n difficultyBits: challenge.difficultyBits,\n sig: challenge.sig\n });\n\n if (verifyRes.verified && verifyRes.token) {\n return {\n method: 'pow',\n token: verifyRes.token,\n solveMs: Math.round(performance.now() - startedAt),\n difficultyBits: challenge.difficultyBits\n };\n }\n\n if (verifyRes.fallback === 'lightning') {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_server_fallback' }\n };\n }\n\n throw new Error('LiveAuth: verification failed');\n\n } catch (err) {\n // On PoW failure, fall back to Lightning\n if (err instanceof LiveAuthPowTimeoutError || err instanceof LiveAuthPowUnsupportedError) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { \n reason: 'pow_failed', \n detail: err.message \n }\n };\n }\n throw err;\n }\n }\n\n /* ======================================================\n * POW FLOW\n * ====================================================== */\n\n private async getPowChallenge(): Promise<PowChallengeResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/challenge`, {\n headers: this.headers\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW challenge failed');\n return res.json();\n }\n\n private async verifyPow(req: PowVerifyRequest): Promise<PowVerifyResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/verify`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(req)\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW verify failed');\n return res.json();\n }\n\n /* ======================================================\n * POW SOLVER (WORKER)\n * ====================================================== */\n\n private solvePow(\n challenge: PowChallengeResponse, \n options: {\n onProgress?: (hashesPerSec: number, iterations: number) => void;\n timeoutMs?: number;\n maxIterations?: number;\n } = {}\n ): Promise<PowSolution> {\n const { onProgress, timeoutMs = 30_000, maxIterations = 50_000_000 } = options;\n\n if (!this.canUsePow()) {\n return Promise.reject(new LiveAuthPowUnsupportedError());\n }\n\n return new Promise((resolve, reject) => {\n const worker = new Worker(\n new URL('./pow.worker.js', import.meta.url),\n { type: 'module' }\n );\n\n const timeoutId = setTimeout(() => {\n worker.terminate();\n reject(new LiveAuthPowTimeoutError(`PoW timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n worker.onmessage = (e: MessageEvent<PowWorkerResult>) => {\n const data = e.data;\n\n if (data.type === 'progress') {\n onProgress?.(data.hashesPerSec ?? 0, data.iterations ?? 0);\n return;\n }\n\n if (data.type === 'timeout') {\n clearTimeout(timeoutId);\n worker.terminate();\n reject(new LiveAuthPowTimeoutError(`PoW hit max iterations (${maxIterations})`));\n return;\n }\n\n if (data.type === 'solution' && data.nonce !== undefined && data.hashHex) {\n clearTimeout(timeoutId);\n worker.terminate();\n resolve({ nonce: data.nonce, hashHex: data.hashHex });\n return;\n }\n };\n\n worker.onerror = e => {\n clearTimeout(timeoutId);\n worker.terminate();\n reject(new LiveAuthPowUnsupportedError(`Worker error: ${e.message}`));\n };\n\n worker.postMessage({\n projectPublicKey: challenge.projectPublicKey,\n challengeHex: challenge.challengeHex,\n targetHex: challenge.targetHex,\n maxIterations\n });\n });\n }\n\n /* ======================================================\n * LIGHTNING FALLBACK\n * ====================================================== */\n\n private async startLightning(): Promise<LightningStart> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/auth/start`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ userHint: 'browser' })\n });\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning auth start failed');\n }\n\n return res.json();\n }\n\n async pollLightning(\n sessionId: string,\n options?: {\n timeoutMs?: number;\n signal?: AbortSignal;\n intervalMs?: number;\n }\n ): Promise<string> {\n const timeoutMs = options?.timeoutMs ?? 5 * 60_000; // 5 min\n const intervalMs = options?.intervalMs ?? 2000;\n const externalSignal = options?.signal;\n\n const controller = new AbortController();\n const signal = controller.signal;\n\n // If caller passes a signal, bridge it\n if (externalSignal) {\n if (externalSignal.aborted) {\n throw new LiveAuthCancelledError();\n }\n\n externalSignal.addEventListener('abort', () => {\n controller.abort();\n });\n }\n\n // Timeout enforcement\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, timeoutMs);\n\n try {\n while (true) {\n if (signal.aborted) {\n throw externalSignal?.aborted\n ? new LiveAuthCancelledError()\n : new LiveAuthTimeoutError();\n }\n\n const res = await fetch(\n `${this.baseUrl}/api/public/auth/confirm`,\n {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ sessionId }),\n signal\n }\n );\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning confirm failed');\n }\n\n const json = await res.json();\n\n if (json.verified && json.token) {\n return json.token;\n }\n\n await sleep(intervalMs);\n }\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /* ======================================================\n * UTILITIES\n * ====================================================== */\n\n private canUsePow(): boolean {\n try {\n // SSR / Node guard\n if (typeof window === 'undefined') return false;\n\n // Worker support\n if (typeof Worker === 'undefined') return false;\n\n // Basic URL support (needed for module workers)\n if (typeof URL === 'undefined') return false;\n\n // Crypto.subtle required for SHA-256\n if (typeof crypto === 'undefined' || !crypto.subtle) return false;\n\n return true;\n } catch {\n return false;\n }\n }\n\n private async fetchWithRetry(\n url: string,\n init?: RequestInit,\n retries = 2,\n backoffMs = 500\n ): Promise<Response> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const res = await fetch(url, init);\n return res;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n \n if (attempt < retries) {\n await sleep(backoffMs * Math.pow(2, attempt));\n }\n }\n }\n\n throw new LiveAuthNetworkError(\n `Request failed after ${retries + 1} attempts`,\n lastError\n );\n }\n}\n\n/* ======================================================\n * UTILS\n * ====================================================== */\n\nconst sleep = (ms: number) =>\n new Promise(resolve => setTimeout(resolve, ms));\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/index.ts"],"sourcesContent":["export class LiveAuthTimeoutError extends Error {\n constructor(message = 'LiveAuth verification timed out') {\n super(message);\n this.name = 'LiveAuthTimeoutError';\n }\n}\n\nexport class LiveAuthCancelledError extends Error {\n constructor(message = 'LiveAuth verification cancelled') {\n super(message);\n this.name = 'LiveAuthCancelledError';\n }\n}\n\nexport class LiveAuthNetworkError extends Error {\n constructor(message = 'LiveAuth network request failed', public readonly cause?: Error) {\n super(message);\n this.name = 'LiveAuthNetworkError';\n }\n}\n\nexport class LiveAuthPowUnsupportedError extends Error {\n constructor(message = 'Proof-of-Work is not supported in this environment') {\n super(message);\n this.name = 'LiveAuthPowUnsupportedError';\n }\n}\n\nexport class LiveAuthPowTimeoutError extends Error {\n constructor(message = 'Proof-of-Work timed out') {\n super(message);\n this.name = 'LiveAuthPowTimeoutError';\n }\n}\n","import type {\n LiveAuthResult,\n VerifyOptions,\n PowChallengeResponse,\n PowVerifyRequest,\n PowVerifyResponse,\n PowSolution,\n LiveAuthConfig,\n LightningStart\n} from './types';\nimport {\n LiveAuthCancelledError,\n LiveAuthTimeoutError,\n LiveAuthNetworkError,\n LiveAuthPowUnsupportedError,\n LiveAuthPowTimeoutError\n} from './errors';\nimport type { PowWorkerResult } from './pow.worker';\n\n// Re-export for consumers\nexport * from './types';\nexport * from './errors';\n\nconst SDK_VERSION = '0.2.0';\n\nexport class LiveAuth {\n private readonly baseUrl: string;\n private readonly headers: HeadersInit;\n\n constructor(private readonly config: LiveAuthConfig) {\n if (!config.publicKey) {\n throw new Error('LiveAuth: publicKey is required');\n }\n\n this.baseUrl = config.baseUrl ?? 'https://api.liveauth.app';\n\n this.headers = {\n 'Content-Type': 'application/json',\n 'X-LW-Public': config.publicKey,\n ...(config.apiKey && { 'Authorization': `Bearer ${config.apiKey}` }),\n 'X-LW-SDK-Version': SDK_VERSION\n };\n }\n\n /* ======================================================\n * PUBLIC ENTRYPOINT\n * ====================================================== */\n\n async verify(options: VerifyOptions = {}): Promise<LiveAuthResult> {\n const { \n forceLightning = false, \n onProgress,\n powTimeoutMs = 30_000,\n maxPowIterations = 50_000_000\n } = options;\n\n // Skip PoW if forced to Lightning or PoW not supported\n if (forceLightning) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'forced_lightning' }\n };\n }\n\n if (!this.canUsePow()) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_unsupported' }\n };\n }\n\n const startedAt = performance.now();\n\n try {\n const challenge = await this.getPowChallenge();\n const solution = await this.solvePow(challenge, { \n onProgress, \n timeoutMs: powTimeoutMs,\n maxIterations: maxPowIterations\n });\n\n const verifyRes = await this.verifyPow({\n challengeHex: challenge.challengeHex,\n nonce: solution.nonce,\n hashHex: solution.hashHex,\n expiresAtUnix: challenge.expiresAtUnix,\n difficultyBits: challenge.difficultyBits,\n sig: challenge.sig\n });\n\n if (verifyRes.verified && verifyRes.token) {\n return {\n method: 'pow',\n token: verifyRes.token,\n solveMs: Math.round(performance.now() - startedAt),\n difficultyBits: challenge.difficultyBits\n };\n }\n\n if (verifyRes.fallback === 'lightning') {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { reason: 'pow_server_fallback' }\n };\n }\n\n throw new Error('LiveAuth: verification failed');\n\n } catch (err) {\n // On PoW failure, fall back to Lightning\n if (err instanceof LiveAuthPowTimeoutError || err instanceof LiveAuthPowUnsupportedError) {\n const lightning = await this.startLightning();\n return {\n method: 'lightning',\n lightning,\n diagnostics: { \n reason: 'pow_failed', \n detail: err.message \n }\n };\n }\n throw err;\n }\n }\n\n /* ======================================================\n * POW FLOW\n * ====================================================== */\n\n private async getPowChallenge(): Promise<PowChallengeResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/challenge`, {\n headers: this.headers\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW challenge failed');\n return res.json();\n }\n\n private async verifyPow(req: PowVerifyRequest): Promise<PowVerifyResponse> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/verify`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(req)\n });\n\n if (!res.ok) throw new LiveAuthNetworkError('PoW verify failed');\n return res.json();\n }\n\n /* ======================================================\n * POW SOLVER (WORKER)\n * ====================================================== */\n\n private solvePow(\n challenge: PowChallengeResponse, \n options: {\n onProgress?: (hashesPerSec: number, iterations: number) => void;\n timeoutMs?: number;\n maxIterations?: number;\n } = {}\n ): Promise<PowSolution> {\n const { onProgress, timeoutMs = 30_000, maxIterations = 50_000_000 } = options;\n\n if (!this.canUsePow()) {\n return Promise.reject(new LiveAuthPowUnsupportedError());\n }\n\n // Inline worker as blob URL for better bundler compatibility\n const workerCode = `\n self.onmessage = async (e) => {\n const { projectPublicKey, challengeHex, targetHex, maxIterations = 50000000, progressInterval = 10000 } = e.data;\n let nonce = 0;\n const startTime = performance.now();\n let lastProgressTime = startTime;\n\n while (nonce < maxIterations) {\n const input = projectPublicKey + ':' + challengeHex + ':' + nonce;\n const hash = await sha256Hex(input);\n if (hash <= targetHex) {\n const elapsed = performance.now() - startTime;\n self.postMessage({ type: 'solution', nonce, hashHex: hash, iterations: nonce + 1, hashesPerSec: Math.round((nonce + 1) / (elapsed / 1000)) });\n return;\n }\n nonce++;\n if (nonce % progressInterval === 0) {\n const now = performance.now();\n self.postMessage({ type: 'progress', iterations: nonce, hashesPerSec: Math.round(progressInterval / ((now - lastProgressTime) / 1000)) });\n lastProgressTime = now;\n }\n }\n self.postMessage({ type: 'timeout', iterations: nonce });\n };\n async function sha256Hex(input) {\n const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n return [...new Uint8Array(buf)].map(b => b.toString(16).padStart(2, '0')).join('');\n }\n `;\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const workerUrl = URL.createObjectURL(blob);\n\n return new Promise((resolve, reject) => {\n const worker = new Worker(workerUrl);\n\n const timeoutId = setTimeout(() => {\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n reject(new LiveAuthPowTimeoutError(`PoW timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n worker.onmessage = (e: MessageEvent<PowWorkerResult>) => {\n const data = e.data;\n\n if (data.type === 'progress') {\n onProgress?.(data.hashesPerSec ?? 0, data.iterations ?? 0);\n return;\n }\n\n if (data.type === 'timeout') {\n clearTimeout(timeoutId);\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n reject(new LiveAuthPowTimeoutError(`PoW hit max iterations (${maxIterations})`));\n return;\n }\n\n if (data.type === 'solution' && data.nonce !== undefined && data.hashHex) {\n clearTimeout(timeoutId);\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n resolve({ nonce: data.nonce, hashHex: data.hashHex });\n return;\n }\n };\n\n worker.onerror = e => {\n clearTimeout(timeoutId);\n worker.terminate();\n URL.revokeObjectURL(workerUrl);\n reject(new LiveAuthPowUnsupportedError(`Worker error: ${e.message}`));\n };\n\n worker.postMessage({\n projectPublicKey: challenge.projectPublicKey,\n challengeHex: challenge.challengeHex,\n targetHex: challenge.targetHex,\n maxIterations\n });\n });\n }\n\n /* ======================================================\n * LIGHTNING FALLBACK\n * ====================================================== */\n\n private async startLightning(): Promise<LightningStart> {\n const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/auth/start`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ userHint: 'browser' })\n });\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning auth start failed');\n }\n\n return res.json();\n }\n\n async pollLightning(\n sessionId: string,\n options?: {\n timeoutMs?: number;\n signal?: AbortSignal;\n intervalMs?: number;\n }\n ): Promise<string> {\n const timeoutMs = options?.timeoutMs ?? 5 * 60_000; // 5 min\n const intervalMs = options?.intervalMs ?? 2000;\n const externalSignal = options?.signal;\n\n const controller = new AbortController();\n const signal = controller.signal;\n\n // If caller passes a signal, bridge it\n if (externalSignal) {\n if (externalSignal.aborted) {\n throw new LiveAuthCancelledError();\n }\n\n externalSignal.addEventListener('abort', () => {\n controller.abort();\n });\n }\n\n // Timeout enforcement\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, timeoutMs);\n\n try {\n while (true) {\n if (signal.aborted) {\n throw externalSignal?.aborted\n ? new LiveAuthCancelledError()\n : new LiveAuthTimeoutError();\n }\n\n const res = await fetch(\n `${this.baseUrl}/api/public/auth/confirm`,\n {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ sessionId }),\n signal\n }\n );\n\n if (!res.ok) {\n throw new LiveAuthNetworkError('Lightning confirm failed');\n }\n\n const json = await res.json();\n\n if (json.verified && json.token) {\n return json.token;\n }\n\n await sleep(intervalMs);\n }\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /* ======================================================\n * UTILITIES\n * ====================================================== */\n\n private canUsePow(): boolean {\n try {\n // SSR / Node guard\n if (typeof window === 'undefined') return false;\n\n // Worker support\n if (typeof Worker === 'undefined') return false;\n\n // Basic URL support (needed for module workers)\n if (typeof URL === 'undefined') return false;\n\n // Crypto.subtle required for SHA-256\n if (typeof crypto === 'undefined' || !crypto.subtle) return false;\n\n return true;\n } catch {\n return false;\n }\n }\n\n private async fetchWithRetry(\n url: string,\n init?: RequestInit,\n retries = 2,\n backoffMs = 500\n ): Promise<Response> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const res = await fetch(url, init);\n return res;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n \n if (attempt < retries) {\n await sleep(backoffMs * Math.pow(2, attempt));\n }\n }\n }\n\n throw new LiveAuthNetworkError(\n `Request failed after ${retries + 1} attempts`,\n lastError\n );\n }\n}\n\n/* ======================================================\n * UTILS\n * ====================================================== */\n\nconst sleep = (ms: number) =>\n new Promise(resolve => setTimeout(resolve, ms));\n"],"mappings":"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","names":[]}
|