@liveauth-labs/sdk 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/index.cjs +138 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -1
- package/dist/index.d.ts +97 -1
- package/dist/index.js +137 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,7 +42,8 @@ npm install @liveauth-labs/sdk
|
|
|
42
42
|
import { LiveAuth } from '@liveauth-labs/sdk';
|
|
43
43
|
|
|
44
44
|
const liveauth = new LiveAuth({
|
|
45
|
-
publicKey: 'la_pk_XXXXXXXX'
|
|
45
|
+
publicKey: 'la_pk_XXXXXXXX', // Public key from dashboard
|
|
46
|
+
apiKey: 'la_sk_XXXXXXXX' // Secret key from dashboard
|
|
46
47
|
});
|
|
47
48
|
|
|
48
49
|
const result = await liveauth.verify();
|
|
@@ -67,6 +68,8 @@ if (result.method === 'pow') {
|
|
|
67
68
|
| Option | Type | Required | Description |
|
|
68
69
|
|--------|------|----------|-------------|
|
|
69
70
|
| `publicKey` | `string` | ✓ | Your LiveAuth public key |
|
|
71
|
+
| `apiKey` | `string` | | Your LiveAuth secret key (for Lightning fallback) |
|
|
72
|
+
| `baseUrl` | `string` | | API base URL (default: `https://api.liveauth.app`) |
|
|
70
73
|
| `baseUrl` | `string` | | API base URL (default: `https://api.liveauth.app`) |
|
|
71
74
|
|
|
72
75
|
### `verify(options?)`
|
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
+
BillingClient: () => BillingClient,
|
|
23
24
|
LiveAuth: () => LiveAuth,
|
|
24
25
|
LiveAuthCancelledError: () => LiveAuthCancelledError,
|
|
25
26
|
LiveAuthNetworkError: () => LiveAuthNetworkError,
|
|
@@ -62,6 +63,138 @@ var LiveAuthPowTimeoutError = class extends Error {
|
|
|
62
63
|
}
|
|
63
64
|
};
|
|
64
65
|
|
|
66
|
+
// src/billing.ts
|
|
67
|
+
var BillingClient = class {
|
|
68
|
+
constructor(config) {
|
|
69
|
+
if (!config.jwt) throw new Error("LiveAuth Billing: jwt is required");
|
|
70
|
+
this.baseUrl = config.baseUrl ?? "https://api.liveauth.app";
|
|
71
|
+
this.headers = {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
"Authorization": `Bearer ${config.jwt}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Create a Lightning invoice to purchase L402 credits.
|
|
78
|
+
*
|
|
79
|
+
* @param amountSats Amount of sats to add to balance (min 10, max 100,000)
|
|
80
|
+
* @param projectId Optional project ID. Defaults to developer's active project.
|
|
81
|
+
* @returns Purchase result with Bolt11 invoice to show as QR
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const billing = new BillingClient({ jwt: developerJwt });
|
|
86
|
+
* const purchase = await billing.purchaseCredits({ amountSats: 1000 });
|
|
87
|
+
* // Show bolt11 as QR code
|
|
88
|
+
* lnurlPayQR(purchase.bolt11);
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
async purchaseCredits(opts) {
|
|
92
|
+
const { amountSats, projectId } = opts;
|
|
93
|
+
if (amountSats < 10) throw new Error("Minimum purchase is 10 sats");
|
|
94
|
+
if (amountSats > 1e5) throw new Error("Maximum purchase is 100,000 sats at a time");
|
|
95
|
+
const body = { amountSats };
|
|
96
|
+
if (projectId) body.projectId = projectId;
|
|
97
|
+
const res = await fetch(`${this.baseUrl}/api/billing/purchase`, {
|
|
98
|
+
method: "POST",
|
|
99
|
+
headers: this.headers,
|
|
100
|
+
body: JSON.stringify(body)
|
|
101
|
+
});
|
|
102
|
+
if (!res.ok) {
|
|
103
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
104
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
105
|
+
}
|
|
106
|
+
const json = await res.json();
|
|
107
|
+
return {
|
|
108
|
+
purchaseId: json.purchaseId,
|
|
109
|
+
bolt11: json.bolt11,
|
|
110
|
+
amountSats: json.amountSats,
|
|
111
|
+
expiresAtUnix: json.expiresAtUnix,
|
|
112
|
+
status: json.status
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Poll for invoice payment status.
|
|
117
|
+
* Call this after showing the QR code.
|
|
118
|
+
*
|
|
119
|
+
* @param purchaseId From purchaseCredits() result
|
|
120
|
+
* @param opts.pollIntervalMs How often to check (default 2000ms)
|
|
121
|
+
* @param opts.timeoutMs Max time to wait (default 10 min)
|
|
122
|
+
* @returns Final purchase status (settled or expired)
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* const status = await billing.getPurchaseStatus(purchase.purchaseId, {
|
|
127
|
+
* pollIntervalMs: 2000,
|
|
128
|
+
* timeoutMs: 600_000, // 10 min
|
|
129
|
+
* });
|
|
130
|
+
* if (status.status === 'settled') {
|
|
131
|
+
* console.log('New balance:', status.newBalanceSats, 'sats');
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
async getPurchaseStatus(purchaseId, opts = {}) {
|
|
136
|
+
const { pollIntervalMs = 2e3, timeoutMs = 6e5 } = opts;
|
|
137
|
+
const deadline = Date.now() + timeoutMs;
|
|
138
|
+
while (Date.now() < deadline) {
|
|
139
|
+
const res = await fetch(`${this.baseUrl}/api/billing/purchase/${purchaseId}`, {
|
|
140
|
+
headers: this.headers
|
|
141
|
+
});
|
|
142
|
+
if (!res.ok) {
|
|
143
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
144
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
145
|
+
}
|
|
146
|
+
const json = await res.json();
|
|
147
|
+
if (json.status === "settled") {
|
|
148
|
+
return {
|
|
149
|
+
purchaseId: json.purchaseId,
|
|
150
|
+
status: "settled",
|
|
151
|
+
amountSats: json.amountSats,
|
|
152
|
+
newBalanceSats: json.newBalanceSats ?? void 0,
|
|
153
|
+
bolt11: json.bolt11
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (json.status === "expired") {
|
|
157
|
+
return {
|
|
158
|
+
purchaseId: json.purchaseId,
|
|
159
|
+
status: "expired",
|
|
160
|
+
amountSats: json.amountSats,
|
|
161
|
+
bolt11: json.bolt11
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
await sleep(pollIntervalMs);
|
|
165
|
+
}
|
|
166
|
+
throw new Error("Purchase poll timed out");
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check L402 balance and today's usage for the developer's active project.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* const usage = await billing.getUsage();
|
|
174
|
+
* console.log('L402 balance:', usage.l402BalanceSats, 'sats');
|
|
175
|
+
* console.log('Calls today:', usage.callsUsedToday);
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
async getUsage() {
|
|
179
|
+
const res = await fetch(`${this.baseUrl}/api/billing/usage`, {
|
|
180
|
+
headers: this.headers
|
|
181
|
+
});
|
|
182
|
+
if (!res.ok) {
|
|
183
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
184
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
185
|
+
}
|
|
186
|
+
const json = await res.json();
|
|
187
|
+
return {
|
|
188
|
+
l402BalanceSats: json.l402BalanceSats,
|
|
189
|
+
callsUsedToday: json.callsUsedToday,
|
|
190
|
+
satsUsedToday: json.satsUsedToday,
|
|
191
|
+
freeDailyLimitSats: json.freeDailyLimitSats,
|
|
192
|
+
freeDailyLimitCalls: json.freeDailyLimitCalls
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
197
|
+
|
|
65
198
|
// src/index.ts
|
|
66
199
|
var SDK_VERSION = "0.2.0";
|
|
67
200
|
var LiveAuth = class {
|
|
@@ -74,7 +207,7 @@ var LiveAuth = class {
|
|
|
74
207
|
this.headers = {
|
|
75
208
|
"Content-Type": "application/json",
|
|
76
209
|
"X-LW-Public": config.publicKey,
|
|
77
|
-
...config.apiKey && { "
|
|
210
|
+
...config.apiKey && { "X-LW-Secret": config.apiKey },
|
|
78
211
|
"X-LW-SDK-Version": SDK_VERSION
|
|
79
212
|
};
|
|
80
213
|
}
|
|
@@ -304,7 +437,7 @@ var LiveAuth = class {
|
|
|
304
437
|
if (json.verified && json.token) {
|
|
305
438
|
return json.token;
|
|
306
439
|
}
|
|
307
|
-
await
|
|
440
|
+
await sleep2(intervalMs);
|
|
308
441
|
}
|
|
309
442
|
} finally {
|
|
310
443
|
clearTimeout(timeoutId);
|
|
@@ -333,7 +466,7 @@ var LiveAuth = class {
|
|
|
333
466
|
} catch (err) {
|
|
334
467
|
lastError = err instanceof Error ? err : new Error(String(err));
|
|
335
468
|
if (attempt < retries) {
|
|
336
|
-
await
|
|
469
|
+
await sleep2(backoffMs * Math.pow(2, attempt));
|
|
337
470
|
}
|
|
338
471
|
}
|
|
339
472
|
}
|
|
@@ -343,9 +476,10 @@ var LiveAuth = class {
|
|
|
343
476
|
);
|
|
344
477
|
}
|
|
345
478
|
};
|
|
346
|
-
var
|
|
479
|
+
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
347
480
|
// Annotate the CommonJS export names for ESM import in node:
|
|
348
481
|
0 && (module.exports = {
|
|
482
|
+
BillingClient,
|
|
349
483
|
LiveAuth,
|
|
350
484
|
LiveAuthCancelledError,
|
|
351
485
|
LiveAuthNetworkError,
|
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 // 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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/billing.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 && { 'X-LW-Secret': 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\n// Re-export billing client\nexport { BillingClient, type BillingClientConfig, type PurchaseResult, type PurchaseStatus } from './billing.js';\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","/* ======================================================\n * BILLING CLIENT\n * L402 balance purchase via Lightning\n * ====================================================== */\n\nexport interface BillingClientConfig {\n /**\n * Developer JWT from Lightning login (POST /api/dev/auth/start → confirm).\n * Get this by logging in via Lightning and extracting the JWT from the response.\n */\n jwt: string;\n\n /** Optional API base URL (defaults to liveauth.app) */\n baseUrl?: string;\n}\n\nexport interface PurchaseResult {\n /** ID to pass to getPurchaseStatus() */\n purchaseId: string;\n /** Bolt11 invoice — show as QR code */\n bolt11: string;\n /** Amount of sats being purchased */\n amountSats: number;\n /** Unix timestamp when invoice expires */\n expiresAtUnix: number;\n /** Always \"pending\" on creation */\n status: 'pending';\n}\n\nexport interface PurchaseStatus {\n purchaseId: string;\n /** \"pending\" | \"settling\" | \"settled\" | \"expired\" */\n status: 'pending' | 'settling' | 'settled' | 'expired';\n amountSats: number;\n /** Available after settlement */\n newBalanceSats?: number;\n bolt11: string;\n}\n\nexport class BillingClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n\n constructor(config: BillingClientConfig) {\n if (!config.jwt) throw new Error('LiveAuth Billing: jwt is required');\n this.baseUrl = config.baseUrl ?? 'https://api.liveauth.app';\n this.headers = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.jwt}`\n };\n }\n\n /**\n * Create a Lightning invoice to purchase L402 credits.\n *\n * @param amountSats Amount of sats to add to balance (min 10, max 100,000)\n * @param projectId Optional project ID. Defaults to developer's active project.\n * @returns Purchase result with Bolt11 invoice to show as QR\n *\n * @example\n * ```ts\n * const billing = new BillingClient({ jwt: developerJwt });\n * const purchase = await billing.purchaseCredits({ amountSats: 1000 });\n * // Show bolt11 as QR code\n * lnurlPayQR(purchase.bolt11);\n * ```\n */\n async purchaseCredits(opts: {\n amountSats: number;\n projectId?: string;\n }): Promise<PurchaseResult> {\n const { amountSats, projectId } = opts;\n\n if (amountSats < 10) throw new Error('Minimum purchase is 10 sats');\n if (amountSats > 100_000) throw new Error('Maximum purchase is 100,000 sats at a time');\n\n const body: Record<string, unknown> = { amountSats };\n if (projectId) body.projectId = projectId;\n\n const res = await fetch(`${this.baseUrl}/api/billing/purchase`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(body)\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: 'Unknown error' }));\n throw new Error(err.error ?? `HTTP ${res.status}`);\n }\n\n const json = await res.json();\n return {\n purchaseId: json.purchaseId,\n bolt11: json.bolt11,\n amountSats: json.amountSats,\n expiresAtUnix: json.expiresAtUnix,\n status: json.status\n };\n }\n\n /**\n * Poll for invoice payment status.\n * Call this after showing the QR code.\n *\n * @param purchaseId From purchaseCredits() result\n * @param opts.pollIntervalMs How often to check (default 2000ms)\n * @param opts.timeoutMs Max time to wait (default 10 min)\n * @returns Final purchase status (settled or expired)\n *\n * @example\n * ```ts\n * const status = await billing.getPurchaseStatus(purchase.purchaseId, {\n * pollIntervalMs: 2000,\n * timeoutMs: 600_000, // 10 min\n * });\n * if (status.status === 'settled') {\n * console.log('New balance:', status.newBalanceSats, 'sats');\n * }\n * ```\n */\n async getPurchaseStatus(\n purchaseId: string,\n opts: {\n pollIntervalMs?: number;\n timeoutMs?: number;\n } = {}\n ): Promise<PurchaseStatus> {\n const { pollIntervalMs = 2000, timeoutMs = 600_000 } = opts;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const res = await fetch(`${this.baseUrl}/api/billing/purchase/${purchaseId}`, {\n headers: this.headers\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: 'Unknown error' }));\n throw new Error(err.error ?? `HTTP ${res.status}`);\n }\n\n const json = await res.json();\n\n // Terminal states\n if (json.status === 'settled') {\n return {\n purchaseId: json.purchaseId,\n status: 'settled',\n amountSats: json.amountSats,\n newBalanceSats: json.newBalanceSats ?? undefined,\n bolt11: json.bolt11\n };\n }\n\n if (json.status === 'expired') {\n return {\n purchaseId: json.purchaseId,\n status: 'expired',\n amountSats: json.amountSats,\n bolt11: json.bolt11\n };\n }\n\n await sleep(pollIntervalMs);\n }\n\n throw new Error('Purchase poll timed out');\n }\n\n /**\n * Check L402 balance and today's usage for the developer's active project.\n *\n * @example\n * ```ts\n * const usage = await billing.getUsage();\n * console.log('L402 balance:', usage.l402BalanceSats, 'sats');\n * console.log('Calls today:', usage.callsUsedToday);\n * ```\n */\n async getUsage(): Promise<{\n l402BalanceSats: number;\n callsUsedToday: number;\n satsUsedToday: number;\n freeDailyLimitSats: number;\n freeDailyLimitCalls: number;\n }> {\n const res = await fetch(`${this.baseUrl}/api/billing/usage`, {\n headers: this.headers\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: 'Unknown error' }));\n throw new Error(err.error ?? `HTTP ${res.status}`);\n }\n\n const json = await res.json();\n return {\n l402BalanceSats: json.l402BalanceSats,\n callsUsedToday: json.callsUsedToday,\n satsUsedToday: json.satsUsedToday,\n freeDailyLimitSats: json.freeDailyLimitSats,\n freeDailyLimitCalls: json.freeDailyLimitCalls\n };\n }\n}\n\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\n"],"mappings":"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","names":["sleep"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -93,6 +93,102 @@ declare class LiveAuthPowTimeoutError extends Error {
|
|
|
93
93
|
constructor(message?: string);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
interface BillingClientConfig {
|
|
97
|
+
/**
|
|
98
|
+
* Developer JWT from Lightning login (POST /api/dev/auth/start → confirm).
|
|
99
|
+
* Get this by logging in via Lightning and extracting the JWT from the response.
|
|
100
|
+
*/
|
|
101
|
+
jwt: string;
|
|
102
|
+
/** Optional API base URL (defaults to liveauth.app) */
|
|
103
|
+
baseUrl?: string;
|
|
104
|
+
}
|
|
105
|
+
interface PurchaseResult {
|
|
106
|
+
/** ID to pass to getPurchaseStatus() */
|
|
107
|
+
purchaseId: string;
|
|
108
|
+
/** Bolt11 invoice — show as QR code */
|
|
109
|
+
bolt11: string;
|
|
110
|
+
/** Amount of sats being purchased */
|
|
111
|
+
amountSats: number;
|
|
112
|
+
/** Unix timestamp when invoice expires */
|
|
113
|
+
expiresAtUnix: number;
|
|
114
|
+
/** Always "pending" on creation */
|
|
115
|
+
status: 'pending';
|
|
116
|
+
}
|
|
117
|
+
interface PurchaseStatus {
|
|
118
|
+
purchaseId: string;
|
|
119
|
+
/** "pending" | "settling" | "settled" | "expired" */
|
|
120
|
+
status: 'pending' | 'settling' | 'settled' | 'expired';
|
|
121
|
+
amountSats: number;
|
|
122
|
+
/** Available after settlement */
|
|
123
|
+
newBalanceSats?: number;
|
|
124
|
+
bolt11: string;
|
|
125
|
+
}
|
|
126
|
+
declare class BillingClient {
|
|
127
|
+
private readonly baseUrl;
|
|
128
|
+
private readonly headers;
|
|
129
|
+
constructor(config: BillingClientConfig);
|
|
130
|
+
/**
|
|
131
|
+
* Create a Lightning invoice to purchase L402 credits.
|
|
132
|
+
*
|
|
133
|
+
* @param amountSats Amount of sats to add to balance (min 10, max 100,000)
|
|
134
|
+
* @param projectId Optional project ID. Defaults to developer's active project.
|
|
135
|
+
* @returns Purchase result with Bolt11 invoice to show as QR
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* const billing = new BillingClient({ jwt: developerJwt });
|
|
140
|
+
* const purchase = await billing.purchaseCredits({ amountSats: 1000 });
|
|
141
|
+
* // Show bolt11 as QR code
|
|
142
|
+
* lnurlPayQR(purchase.bolt11);
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
purchaseCredits(opts: {
|
|
146
|
+
amountSats: number;
|
|
147
|
+
projectId?: string;
|
|
148
|
+
}): Promise<PurchaseResult>;
|
|
149
|
+
/**
|
|
150
|
+
* Poll for invoice payment status.
|
|
151
|
+
* Call this after showing the QR code.
|
|
152
|
+
*
|
|
153
|
+
* @param purchaseId From purchaseCredits() result
|
|
154
|
+
* @param opts.pollIntervalMs How often to check (default 2000ms)
|
|
155
|
+
* @param opts.timeoutMs Max time to wait (default 10 min)
|
|
156
|
+
* @returns Final purchase status (settled or expired)
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* const status = await billing.getPurchaseStatus(purchase.purchaseId, {
|
|
161
|
+
* pollIntervalMs: 2000,
|
|
162
|
+
* timeoutMs: 600_000, // 10 min
|
|
163
|
+
* });
|
|
164
|
+
* if (status.status === 'settled') {
|
|
165
|
+
* console.log('New balance:', status.newBalanceSats, 'sats');
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
getPurchaseStatus(purchaseId: string, opts?: {
|
|
170
|
+
pollIntervalMs?: number;
|
|
171
|
+
timeoutMs?: number;
|
|
172
|
+
}): Promise<PurchaseStatus>;
|
|
173
|
+
/**
|
|
174
|
+
* Check L402 balance and today's usage for the developer's active project.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* const usage = await billing.getUsage();
|
|
179
|
+
* console.log('L402 balance:', usage.l402BalanceSats, 'sats');
|
|
180
|
+
* console.log('Calls today:', usage.callsUsedToday);
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
getUsage(): Promise<{
|
|
184
|
+
l402BalanceSats: number;
|
|
185
|
+
callsUsedToday: number;
|
|
186
|
+
satsUsedToday: number;
|
|
187
|
+
freeDailyLimitSats: number;
|
|
188
|
+
freeDailyLimitCalls: number;
|
|
189
|
+
}>;
|
|
190
|
+
}
|
|
191
|
+
|
|
96
192
|
declare class LiveAuth {
|
|
97
193
|
private readonly config;
|
|
98
194
|
private readonly baseUrl;
|
|
@@ -112,4 +208,4 @@ declare class LiveAuth {
|
|
|
112
208
|
private fetchWithRetry;
|
|
113
209
|
}
|
|
114
210
|
|
|
115
|
-
export { type AuthConfirmResponse, type AuthStartResponse, type LightningStart, LiveAuth, LiveAuthCancelledError, type LiveAuthConfig, type LiveAuthDiagnostics, type LiveAuthMethod, LiveAuthNetworkError, LiveAuthPowTimeoutError, LiveAuthPowUnsupportedError, type LiveAuthResult, LiveAuthTimeoutError, type PowChallengeResponse, type PowSolution, type PowVerifyRequest, type PowVerifyResponse, type VerifyOptions };
|
|
211
|
+
export { type AuthConfirmResponse, type AuthStartResponse, BillingClient, type BillingClientConfig, type LightningStart, LiveAuth, LiveAuthCancelledError, type LiveAuthConfig, type LiveAuthDiagnostics, type LiveAuthMethod, LiveAuthNetworkError, LiveAuthPowTimeoutError, LiveAuthPowUnsupportedError, type LiveAuthResult, LiveAuthTimeoutError, type PowChallengeResponse, type PowSolution, type PowVerifyRequest, type PowVerifyResponse, type PurchaseResult, type PurchaseStatus, type VerifyOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -93,6 +93,102 @@ declare class LiveAuthPowTimeoutError extends Error {
|
|
|
93
93
|
constructor(message?: string);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
interface BillingClientConfig {
|
|
97
|
+
/**
|
|
98
|
+
* Developer JWT from Lightning login (POST /api/dev/auth/start → confirm).
|
|
99
|
+
* Get this by logging in via Lightning and extracting the JWT from the response.
|
|
100
|
+
*/
|
|
101
|
+
jwt: string;
|
|
102
|
+
/** Optional API base URL (defaults to liveauth.app) */
|
|
103
|
+
baseUrl?: string;
|
|
104
|
+
}
|
|
105
|
+
interface PurchaseResult {
|
|
106
|
+
/** ID to pass to getPurchaseStatus() */
|
|
107
|
+
purchaseId: string;
|
|
108
|
+
/** Bolt11 invoice — show as QR code */
|
|
109
|
+
bolt11: string;
|
|
110
|
+
/** Amount of sats being purchased */
|
|
111
|
+
amountSats: number;
|
|
112
|
+
/** Unix timestamp when invoice expires */
|
|
113
|
+
expiresAtUnix: number;
|
|
114
|
+
/** Always "pending" on creation */
|
|
115
|
+
status: 'pending';
|
|
116
|
+
}
|
|
117
|
+
interface PurchaseStatus {
|
|
118
|
+
purchaseId: string;
|
|
119
|
+
/** "pending" | "settling" | "settled" | "expired" */
|
|
120
|
+
status: 'pending' | 'settling' | 'settled' | 'expired';
|
|
121
|
+
amountSats: number;
|
|
122
|
+
/** Available after settlement */
|
|
123
|
+
newBalanceSats?: number;
|
|
124
|
+
bolt11: string;
|
|
125
|
+
}
|
|
126
|
+
declare class BillingClient {
|
|
127
|
+
private readonly baseUrl;
|
|
128
|
+
private readonly headers;
|
|
129
|
+
constructor(config: BillingClientConfig);
|
|
130
|
+
/**
|
|
131
|
+
* Create a Lightning invoice to purchase L402 credits.
|
|
132
|
+
*
|
|
133
|
+
* @param amountSats Amount of sats to add to balance (min 10, max 100,000)
|
|
134
|
+
* @param projectId Optional project ID. Defaults to developer's active project.
|
|
135
|
+
* @returns Purchase result with Bolt11 invoice to show as QR
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* const billing = new BillingClient({ jwt: developerJwt });
|
|
140
|
+
* const purchase = await billing.purchaseCredits({ amountSats: 1000 });
|
|
141
|
+
* // Show bolt11 as QR code
|
|
142
|
+
* lnurlPayQR(purchase.bolt11);
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
purchaseCredits(opts: {
|
|
146
|
+
amountSats: number;
|
|
147
|
+
projectId?: string;
|
|
148
|
+
}): Promise<PurchaseResult>;
|
|
149
|
+
/**
|
|
150
|
+
* Poll for invoice payment status.
|
|
151
|
+
* Call this after showing the QR code.
|
|
152
|
+
*
|
|
153
|
+
* @param purchaseId From purchaseCredits() result
|
|
154
|
+
* @param opts.pollIntervalMs How often to check (default 2000ms)
|
|
155
|
+
* @param opts.timeoutMs Max time to wait (default 10 min)
|
|
156
|
+
* @returns Final purchase status (settled or expired)
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* const status = await billing.getPurchaseStatus(purchase.purchaseId, {
|
|
161
|
+
* pollIntervalMs: 2000,
|
|
162
|
+
* timeoutMs: 600_000, // 10 min
|
|
163
|
+
* });
|
|
164
|
+
* if (status.status === 'settled') {
|
|
165
|
+
* console.log('New balance:', status.newBalanceSats, 'sats');
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
getPurchaseStatus(purchaseId: string, opts?: {
|
|
170
|
+
pollIntervalMs?: number;
|
|
171
|
+
timeoutMs?: number;
|
|
172
|
+
}): Promise<PurchaseStatus>;
|
|
173
|
+
/**
|
|
174
|
+
* Check L402 balance and today's usage for the developer's active project.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* const usage = await billing.getUsage();
|
|
179
|
+
* console.log('L402 balance:', usage.l402BalanceSats, 'sats');
|
|
180
|
+
* console.log('Calls today:', usage.callsUsedToday);
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
getUsage(): Promise<{
|
|
184
|
+
l402BalanceSats: number;
|
|
185
|
+
callsUsedToday: number;
|
|
186
|
+
satsUsedToday: number;
|
|
187
|
+
freeDailyLimitSats: number;
|
|
188
|
+
freeDailyLimitCalls: number;
|
|
189
|
+
}>;
|
|
190
|
+
}
|
|
191
|
+
|
|
96
192
|
declare class LiveAuth {
|
|
97
193
|
private readonly config;
|
|
98
194
|
private readonly baseUrl;
|
|
@@ -112,4 +208,4 @@ declare class LiveAuth {
|
|
|
112
208
|
private fetchWithRetry;
|
|
113
209
|
}
|
|
114
210
|
|
|
115
|
-
export { type AuthConfirmResponse, type AuthStartResponse, type LightningStart, LiveAuth, LiveAuthCancelledError, type LiveAuthConfig, type LiveAuthDiagnostics, type LiveAuthMethod, LiveAuthNetworkError, LiveAuthPowTimeoutError, LiveAuthPowUnsupportedError, type LiveAuthResult, LiveAuthTimeoutError, type PowChallengeResponse, type PowSolution, type PowVerifyRequest, type PowVerifyResponse, type VerifyOptions };
|
|
211
|
+
export { type AuthConfirmResponse, type AuthStartResponse, BillingClient, type BillingClientConfig, type LightningStart, LiveAuth, LiveAuthCancelledError, type LiveAuthConfig, type LiveAuthDiagnostics, type LiveAuthMethod, LiveAuthNetworkError, LiveAuthPowTimeoutError, LiveAuthPowUnsupportedError, type LiveAuthResult, LiveAuthTimeoutError, type PowChallengeResponse, type PowSolution, type PowVerifyRequest, type PowVerifyResponse, type PurchaseResult, type PurchaseStatus, type VerifyOptions };
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,138 @@ var LiveAuthPowTimeoutError = class extends Error {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
// src/billing.ts
|
|
35
|
+
var BillingClient = class {
|
|
36
|
+
constructor(config) {
|
|
37
|
+
if (!config.jwt) throw new Error("LiveAuth Billing: jwt is required");
|
|
38
|
+
this.baseUrl = config.baseUrl ?? "https://api.liveauth.app";
|
|
39
|
+
this.headers = {
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
"Authorization": `Bearer ${config.jwt}`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a Lightning invoice to purchase L402 credits.
|
|
46
|
+
*
|
|
47
|
+
* @param amountSats Amount of sats to add to balance (min 10, max 100,000)
|
|
48
|
+
* @param projectId Optional project ID. Defaults to developer's active project.
|
|
49
|
+
* @returns Purchase result with Bolt11 invoice to show as QR
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const billing = new BillingClient({ jwt: developerJwt });
|
|
54
|
+
* const purchase = await billing.purchaseCredits({ amountSats: 1000 });
|
|
55
|
+
* // Show bolt11 as QR code
|
|
56
|
+
* lnurlPayQR(purchase.bolt11);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
async purchaseCredits(opts) {
|
|
60
|
+
const { amountSats, projectId } = opts;
|
|
61
|
+
if (amountSats < 10) throw new Error("Minimum purchase is 10 sats");
|
|
62
|
+
if (amountSats > 1e5) throw new Error("Maximum purchase is 100,000 sats at a time");
|
|
63
|
+
const body = { amountSats };
|
|
64
|
+
if (projectId) body.projectId = projectId;
|
|
65
|
+
const res = await fetch(`${this.baseUrl}/api/billing/purchase`, {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: this.headers,
|
|
68
|
+
body: JSON.stringify(body)
|
|
69
|
+
});
|
|
70
|
+
if (!res.ok) {
|
|
71
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
72
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
73
|
+
}
|
|
74
|
+
const json = await res.json();
|
|
75
|
+
return {
|
|
76
|
+
purchaseId: json.purchaseId,
|
|
77
|
+
bolt11: json.bolt11,
|
|
78
|
+
amountSats: json.amountSats,
|
|
79
|
+
expiresAtUnix: json.expiresAtUnix,
|
|
80
|
+
status: json.status
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Poll for invoice payment status.
|
|
85
|
+
* Call this after showing the QR code.
|
|
86
|
+
*
|
|
87
|
+
* @param purchaseId From purchaseCredits() result
|
|
88
|
+
* @param opts.pollIntervalMs How often to check (default 2000ms)
|
|
89
|
+
* @param opts.timeoutMs Max time to wait (default 10 min)
|
|
90
|
+
* @returns Final purchase status (settled or expired)
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* const status = await billing.getPurchaseStatus(purchase.purchaseId, {
|
|
95
|
+
* pollIntervalMs: 2000,
|
|
96
|
+
* timeoutMs: 600_000, // 10 min
|
|
97
|
+
* });
|
|
98
|
+
* if (status.status === 'settled') {
|
|
99
|
+
* console.log('New balance:', status.newBalanceSats, 'sats');
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
async getPurchaseStatus(purchaseId, opts = {}) {
|
|
104
|
+
const { pollIntervalMs = 2e3, timeoutMs = 6e5 } = opts;
|
|
105
|
+
const deadline = Date.now() + timeoutMs;
|
|
106
|
+
while (Date.now() < deadline) {
|
|
107
|
+
const res = await fetch(`${this.baseUrl}/api/billing/purchase/${purchaseId}`, {
|
|
108
|
+
headers: this.headers
|
|
109
|
+
});
|
|
110
|
+
if (!res.ok) {
|
|
111
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
112
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
113
|
+
}
|
|
114
|
+
const json = await res.json();
|
|
115
|
+
if (json.status === "settled") {
|
|
116
|
+
return {
|
|
117
|
+
purchaseId: json.purchaseId,
|
|
118
|
+
status: "settled",
|
|
119
|
+
amountSats: json.amountSats,
|
|
120
|
+
newBalanceSats: json.newBalanceSats ?? void 0,
|
|
121
|
+
bolt11: json.bolt11
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (json.status === "expired") {
|
|
125
|
+
return {
|
|
126
|
+
purchaseId: json.purchaseId,
|
|
127
|
+
status: "expired",
|
|
128
|
+
amountSats: json.amountSats,
|
|
129
|
+
bolt11: json.bolt11
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
await sleep(pollIntervalMs);
|
|
133
|
+
}
|
|
134
|
+
throw new Error("Purchase poll timed out");
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check L402 balance and today's usage for the developer's active project.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* const usage = await billing.getUsage();
|
|
142
|
+
* console.log('L402 balance:', usage.l402BalanceSats, 'sats');
|
|
143
|
+
* console.log('Calls today:', usage.callsUsedToday);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
async getUsage() {
|
|
147
|
+
const res = await fetch(`${this.baseUrl}/api/billing/usage`, {
|
|
148
|
+
headers: this.headers
|
|
149
|
+
});
|
|
150
|
+
if (!res.ok) {
|
|
151
|
+
const err = await res.json().catch(() => ({ error: "Unknown error" }));
|
|
152
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
153
|
+
}
|
|
154
|
+
const json = await res.json();
|
|
155
|
+
return {
|
|
156
|
+
l402BalanceSats: json.l402BalanceSats,
|
|
157
|
+
callsUsedToday: json.callsUsedToday,
|
|
158
|
+
satsUsedToday: json.satsUsedToday,
|
|
159
|
+
freeDailyLimitSats: json.freeDailyLimitSats,
|
|
160
|
+
freeDailyLimitCalls: json.freeDailyLimitCalls
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
165
|
+
|
|
34
166
|
// src/index.ts
|
|
35
167
|
var SDK_VERSION = "0.2.0";
|
|
36
168
|
var LiveAuth = class {
|
|
@@ -43,7 +175,7 @@ var LiveAuth = class {
|
|
|
43
175
|
this.headers = {
|
|
44
176
|
"Content-Type": "application/json",
|
|
45
177
|
"X-LW-Public": config.publicKey,
|
|
46
|
-
...config.apiKey && { "
|
|
178
|
+
...config.apiKey && { "X-LW-Secret": config.apiKey },
|
|
47
179
|
"X-LW-SDK-Version": SDK_VERSION
|
|
48
180
|
};
|
|
49
181
|
}
|
|
@@ -273,7 +405,7 @@ var LiveAuth = class {
|
|
|
273
405
|
if (json.verified && json.token) {
|
|
274
406
|
return json.token;
|
|
275
407
|
}
|
|
276
|
-
await
|
|
408
|
+
await sleep2(intervalMs);
|
|
277
409
|
}
|
|
278
410
|
} finally {
|
|
279
411
|
clearTimeout(timeoutId);
|
|
@@ -302,7 +434,7 @@ var LiveAuth = class {
|
|
|
302
434
|
} catch (err) {
|
|
303
435
|
lastError = err instanceof Error ? err : new Error(String(err));
|
|
304
436
|
if (attempt < retries) {
|
|
305
|
-
await
|
|
437
|
+
await sleep2(backoffMs * Math.pow(2, attempt));
|
|
306
438
|
}
|
|
307
439
|
}
|
|
308
440
|
}
|
|
@@ -312,8 +444,9 @@ var LiveAuth = class {
|
|
|
312
444
|
);
|
|
313
445
|
}
|
|
314
446
|
};
|
|
315
|
-
var
|
|
447
|
+
var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
316
448
|
export {
|
|
449
|
+
BillingClient,
|
|
317
450
|
LiveAuth,
|
|
318
451
|
LiveAuthCancelledError,
|
|
319
452
|
LiveAuthNetworkError,
|
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 // 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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/billing.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","/* ======================================================\n * BILLING CLIENT\n * L402 balance purchase via Lightning\n * ====================================================== */\n\nexport interface BillingClientConfig {\n /**\n * Developer JWT from Lightning login (POST /api/dev/auth/start → confirm).\n * Get this by logging in via Lightning and extracting the JWT from the response.\n */\n jwt: string;\n\n /** Optional API base URL (defaults to liveauth.app) */\n baseUrl?: string;\n}\n\nexport interface PurchaseResult {\n /** ID to pass to getPurchaseStatus() */\n purchaseId: string;\n /** Bolt11 invoice — show as QR code */\n bolt11: string;\n /** Amount of sats being purchased */\n amountSats: number;\n /** Unix timestamp when invoice expires */\n expiresAtUnix: number;\n /** Always \"pending\" on creation */\n status: 'pending';\n}\n\nexport interface PurchaseStatus {\n purchaseId: string;\n /** \"pending\" | \"settling\" | \"settled\" | \"expired\" */\n status: 'pending' | 'settling' | 'settled' | 'expired';\n amountSats: number;\n /** Available after settlement */\n newBalanceSats?: number;\n bolt11: string;\n}\n\nexport class BillingClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n\n constructor(config: BillingClientConfig) {\n if (!config.jwt) throw new Error('LiveAuth Billing: jwt is required');\n this.baseUrl = config.baseUrl ?? 'https://api.liveauth.app';\n this.headers = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.jwt}`\n };\n }\n\n /**\n * Create a Lightning invoice to purchase L402 credits.\n *\n * @param amountSats Amount of sats to add to balance (min 10, max 100,000)\n * @param projectId Optional project ID. Defaults to developer's active project.\n * @returns Purchase result with Bolt11 invoice to show as QR\n *\n * @example\n * ```ts\n * const billing = new BillingClient({ jwt: developerJwt });\n * const purchase = await billing.purchaseCredits({ amountSats: 1000 });\n * // Show bolt11 as QR code\n * lnurlPayQR(purchase.bolt11);\n * ```\n */\n async purchaseCredits(opts: {\n amountSats: number;\n projectId?: string;\n }): Promise<PurchaseResult> {\n const { amountSats, projectId } = opts;\n\n if (amountSats < 10) throw new Error('Minimum purchase is 10 sats');\n if (amountSats > 100_000) throw new Error('Maximum purchase is 100,000 sats at a time');\n\n const body: Record<string, unknown> = { amountSats };\n if (projectId) body.projectId = projectId;\n\n const res = await fetch(`${this.baseUrl}/api/billing/purchase`, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(body)\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: 'Unknown error' }));\n throw new Error(err.error ?? `HTTP ${res.status}`);\n }\n\n const json = await res.json();\n return {\n purchaseId: json.purchaseId,\n bolt11: json.bolt11,\n amountSats: json.amountSats,\n expiresAtUnix: json.expiresAtUnix,\n status: json.status\n };\n }\n\n /**\n * Poll for invoice payment status.\n * Call this after showing the QR code.\n *\n * @param purchaseId From purchaseCredits() result\n * @param opts.pollIntervalMs How often to check (default 2000ms)\n * @param opts.timeoutMs Max time to wait (default 10 min)\n * @returns Final purchase status (settled or expired)\n *\n * @example\n * ```ts\n * const status = await billing.getPurchaseStatus(purchase.purchaseId, {\n * pollIntervalMs: 2000,\n * timeoutMs: 600_000, // 10 min\n * });\n * if (status.status === 'settled') {\n * console.log('New balance:', status.newBalanceSats, 'sats');\n * }\n * ```\n */\n async getPurchaseStatus(\n purchaseId: string,\n opts: {\n pollIntervalMs?: number;\n timeoutMs?: number;\n } = {}\n ): Promise<PurchaseStatus> {\n const { pollIntervalMs = 2000, timeoutMs = 600_000 } = opts;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const res = await fetch(`${this.baseUrl}/api/billing/purchase/${purchaseId}`, {\n headers: this.headers\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: 'Unknown error' }));\n throw new Error(err.error ?? `HTTP ${res.status}`);\n }\n\n const json = await res.json();\n\n // Terminal states\n if (json.status === 'settled') {\n return {\n purchaseId: json.purchaseId,\n status: 'settled',\n amountSats: json.amountSats,\n newBalanceSats: json.newBalanceSats ?? undefined,\n bolt11: json.bolt11\n };\n }\n\n if (json.status === 'expired') {\n return {\n purchaseId: json.purchaseId,\n status: 'expired',\n amountSats: json.amountSats,\n bolt11: json.bolt11\n };\n }\n\n await sleep(pollIntervalMs);\n }\n\n throw new Error('Purchase poll timed out');\n }\n\n /**\n * Check L402 balance and today's usage for the developer's active project.\n *\n * @example\n * ```ts\n * const usage = await billing.getUsage();\n * console.log('L402 balance:', usage.l402BalanceSats, 'sats');\n * console.log('Calls today:', usage.callsUsedToday);\n * ```\n */\n async getUsage(): Promise<{\n l402BalanceSats: number;\n callsUsedToday: number;\n satsUsedToday: number;\n freeDailyLimitSats: number;\n freeDailyLimitCalls: number;\n }> {\n const res = await fetch(`${this.baseUrl}/api/billing/usage`, {\n headers: this.headers\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: 'Unknown error' }));\n throw new Error(err.error ?? `HTTP ${res.status}`);\n }\n\n const json = await res.json();\n return {\n l402BalanceSats: json.l402BalanceSats,\n callsUsedToday: json.callsUsedToday,\n satsUsedToday: json.satsUsedToday,\n freeDailyLimitSats: json.freeDailyLimitSats,\n freeDailyLimitCalls: json.freeDailyLimitCalls\n };\n }\n}\n\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\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 && { 'X-LW-Secret': 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\n// Re-export billing client\nexport { BillingClient, type BillingClientConfig, type PurchaseResult, type PurchaseStatus } from './billing.js';\n"],"mappings":"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","names":["sleep"]}
|