@liveauth-labs/sdk 0.1.2 → 0.2.1

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 CHANGED
@@ -1,48 +1,42 @@
1
- # LiveAuth Developer Portal Documentation
1
+ # LiveAuth JS SDK
2
2
 
3
- ## Getting Started
3
+ > Human verification through economics, not heuristics.
4
4
 
5
- LiveAuth verifies humans economically instead of heuristically.
5
+ [![npm version](https://img.shields.io/npm/v/@liveauth-labs/sdk.svg)](https://www.npmjs.com/package/@liveauth-labs/sdk)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## What is LiveAuth?
6
9
 
7
- Instead of CAPTCHAs or tracking, LiveAuth asks the browser to perform a short
8
- cryptographic proof. If that fails or is skipped, it falls back to a small
9
- Bitcoin Lightning payment.
10
+ LiveAuth verifies humans economically instead of heuristically.
10
11
 
11
- No cookies.
12
- No fingerprinting.
13
- No behavioral profiling.
12
+ Instead of CAPTCHAs or tracking, LiveAuth asks the browser to perform a short cryptographic proof. If that fails or is skipped, it falls back to a small Bitcoin Lightning payment.
14
13
 
15
- ---
14
+ - No cookies
15
+ - No fingerprinting
16
+ - No behavioral profiling
16
17
 
17
- ## What LiveAuth Does
18
+ ## How It Works
18
19
 
19
- When a user clicks “Verify”:
20
+ When a user triggers verification:
20
21
 
21
22
  1. **Browser attempts Proof-of-Work (PoW)**
22
- Takes ~200–800ms for a real device
23
- – Bots pay CPU / battery cost
23
+ Takes ~200–800ms for a real device. Bots pay CPU/battery cost.
24
24
 
25
25
  2. **If PoW fails → Lightning fallback**
26
- Small payment (e.g. 21 sats)
27
- – Real economic cost to bots
26
+ Small payment (e.g. 21 sats). Real economic cost to bots.
28
27
 
29
28
  3. **LiveAuth returns a short-lived JWT**
30
- Verifiable on your backend
31
- – No user identity required
29
+ Verifiable on your backend. No user identity required.
32
30
 
33
31
  Most humans never see the Lightning step.
34
32
 
35
- ---
36
-
37
- ## Installation (JavaScript)
33
+ ## Installation
38
34
 
39
35
  ```bash
40
36
  npm install @liveauth-labs/sdk
41
37
  ```
42
38
 
43
- ---
44
-
45
- ## Basic Usage
39
+ ## Quick Start
46
40
 
47
41
  ```ts
48
42
  import { LiveAuth } from '@liveauth-labs/sdk';
@@ -52,52 +46,187 @@ const liveauth = new LiveAuth({
52
46
  });
53
47
 
54
48
  const result = await liveauth.verify();
49
+
50
+ if (result.method === 'pow') {
51
+ // PoW succeeded - send token to your backend
52
+ console.log('Verified via PoW:', result.token);
53
+ } else {
54
+ // Lightning fallback - show invoice to user
55
+ console.log('Pay invoice:', result.lightning.invoice);
56
+
57
+ // Poll for payment confirmation
58
+ const token = await liveauth.pollLightning(result.lightning.sessionId);
59
+ console.log('Verified via Lightning:', token);
60
+ }
55
61
  ```
56
62
 
57
- ---
63
+ ## API Reference
64
+
65
+ ### `new LiveAuth(config)`
66
+
67
+ | Option | Type | Required | Description |
68
+ |--------|------|----------|-------------|
69
+ | `publicKey` | `string` | ✓ | Your LiveAuth public key |
70
+ | `baseUrl` | `string` | | API base URL (default: `https://api.liveauth.app`) |
71
+
72
+ ### `verify(options?)`
73
+
74
+ Attempts verification, starting with PoW and falling back to Lightning if needed.
58
75
 
59
- ## Example Result
76
+ | Option | Type | Default | Description |
77
+ |--------|------|---------|-------------|
78
+ | `forceLightning` | `boolean` | `false` | Skip PoW, go straight to Lightning |
79
+ | `onProgress` | `function` | | Callback: `(hashesPerSec, iterations) => void` |
80
+ | `powTimeoutMs` | `number` | `30000` | Max time for PoW before fallback |
81
+ | `maxPowIterations` | `number` | `50000000` | Max iterations before fallback |
82
+
83
+ **Returns:** `Promise<LiveAuthResult>`
60
84
 
61
85
  ```ts
86
+ // PoW success
62
87
  {
63
- token: "eyJhbGciOi...",
64
- method: "pow",
88
+ method: 'pow',
89
+ token: 'eyJhbGciOi...',
65
90
  solveMs: 412,
66
91
  difficultyBits: 18
67
92
  }
93
+
94
+ // Lightning fallback
95
+ {
96
+ method: 'lightning',
97
+ lightning: {
98
+ sessionId: 'sess_xxx',
99
+ invoice: 'lnbc...',
100
+ amountSats: 21,
101
+ expiresAtUnix: 1234567890,
102
+ mode: 'LIVE'
103
+ },
104
+ diagnostics: {
105
+ reason: 'pow_unsupported'
106
+ }
107
+ }
68
108
  ```
69
109
 
70
- ---
110
+ ### `pollLightning(sessionId, options?)`
71
111
 
72
- ## Verifying on Your Backend
112
+ Polls for Lightning payment confirmation.
73
113
 
74
- Send the JWT to your backend and verify it using your LiveAuth secret key.
114
+ | Option | Type | Default | Description |
115
+ |--------|------|---------|-------------|
116
+ | `timeoutMs` | `number` | `300000` | Max wait time (5 min) |
117
+ | `intervalMs` | `number` | `2000` | Poll interval |
118
+ | `signal` | `AbortSignal` | | Cancellation signal |
75
119
 
76
- The token includes:
120
+ **Returns:** `Promise<string>` - The verification token
77
121
 
78
- - projectId
79
- - projectPublicKey
80
- - authType (pow or lightning)
81
- - short expiration (default: 10 minutes)
122
+ ## Error Handling
82
123
 
83
- ---
124
+ ```ts
125
+ import {
126
+ LiveAuth,
127
+ LiveAuthTimeoutError,
128
+ LiveAuthCancelledError,
129
+ LiveAuthNetworkError,
130
+ LiveAuthPowTimeoutError
131
+ } from '@liveauth-labs/sdk';
132
+
133
+ try {
134
+ const result = await liveauth.verify();
135
+ } catch (err) {
136
+ if (err instanceof LiveAuthNetworkError) {
137
+ console.error('Network issue:', err.message);
138
+ } else if (err instanceof LiveAuthPowTimeoutError) {
139
+ console.error('PoW took too long');
140
+ }
141
+ }
142
+ ```
84
143
 
85
- ## Why LiveAuth
144
+ ## Progress Feedback
86
145
 
87
- | CAPTCHA | LiveAuth |
88
- |-------|----------|
89
- | Tracks behavior | No tracking |
90
- | ML heuristics | Cryptography |
91
- | CAPTCHA farms | Real economic cost |
92
- | Bad UX | Invisible to humans |
146
+ Show users what's happening during PoW:
147
+
148
+ ```ts
149
+ const result = await liveauth.verify({
150
+ onProgress: (hashesPerSec, iterations) => {
151
+ console.log(`${(iterations / 1000).toFixed(0)}k hashes @ ${hashesPerSec}/sec`);
152
+ }
153
+ });
154
+ ```
93
155
 
94
- ---
156
+ ## Backend Verification
157
+
158
+ Send the JWT to your backend and verify it using your LiveAuth secret key.
159
+
160
+ ### Example (Node.js)
161
+
162
+ ```ts
163
+ import jwt from 'jsonwebtoken';
164
+
165
+ app.post('/api/verify-liveauth', (req, res) => {
166
+ const { token } = req.body;
167
+
168
+ try {
169
+ // Verify JWT signature with your LiveAuth secret key
170
+ const decoded = jwt.verify(token, process.env.LIVEAUTH_SECRET_KEY);
171
+
172
+ // Check expiration (JWT library handles this, but you can also check manually)
173
+ if (decoded.exp && decoded.exp < Date.now() / 1000) {
174
+ return res.status(401).json({ error: 'Token expired' });
175
+ }
176
+
177
+ // Extract claims
178
+ const { projectId, projectPublicKey, authType, sub } = decoded;
179
+
180
+ // Verify it matches your project
181
+ if (projectPublicKey !== process.env.LIVEAUTH_PUBLIC_KEY) {
182
+ return res.status(401).json({ error: 'Invalid project' });
183
+ }
184
+
185
+ // Success - user is verified
186
+ res.json({
187
+ verified: true,
188
+ authType, // 'pow' or 'lightning'
189
+ userId: sub
190
+ });
191
+
192
+ } catch (err) {
193
+ res.status(401).json({ error: 'Invalid token' });
194
+ }
195
+ });
196
+ ```
197
+
198
+ ### Token Claims
199
+
200
+ The JWT contains:
201
+ - `sub` - Unique user identifier (format: `pow:{projectId}:{challengeHex}` or `lightning:{invoiceId}`)
202
+ - `projectId` - Your project's UUID
203
+ - `projectPublicKey` - Your public API key
204
+ - `authType` - Verification method: `pow` or `lightning`
205
+ - `exp` - Expiration timestamp (default: 10 minutes from issuance)
206
+ - `iat` - Issued at timestamp
207
+
208
+ **Security Notes:**
209
+ - Always verify the JWT signature using your secret key
210
+ - Check the `projectPublicKey` claim matches your expected key
211
+ - Respect the `exp` (expiration) claim
212
+ - The `sub` claim is ephemeral - don't use it as a permanent user ID unless you're tracking sessions
95
213
 
96
214
  ## Debug Mode
97
215
 
98
216
  Add `?liveauth_debug=1` to your URL to see:
217
+ - Verification method used
218
+ - PoW difficulty and solve time
219
+ - Lightning fallback triggers
220
+
221
+ ## Why LiveAuth?
222
+
223
+ | Traditional CAPTCHA | LiveAuth |
224
+ |--------------------|----------|
225
+ | Tracks behavior | No tracking |
226
+ | ML heuristics | Cryptography |
227
+ | CAPTCHA farms | Real economic cost |
228
+ | Bad UX | Invisible to most humans |
229
+
230
+ ## License
99
231
 
100
- - Verification method
101
- - PoW difficulty
102
- - Solve time
103
- - Lightning fallback (demo mode)
232
+ MIT
package/dist/index.cjs CHANGED
@@ -20,26 +20,51 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
- LiveAuth: () => LiveAuth
23
+ LiveAuth: () => LiveAuth,
24
+ LiveAuthCancelledError: () => LiveAuthCancelledError,
25
+ LiveAuthNetworkError: () => LiveAuthNetworkError,
26
+ LiveAuthPowTimeoutError: () => LiveAuthPowTimeoutError,
27
+ LiveAuthPowUnsupportedError: () => LiveAuthPowUnsupportedError,
28
+ LiveAuthTimeoutError: () => LiveAuthTimeoutError
24
29
  });
25
30
  module.exports = __toCommonJS(src_exports);
26
31
 
27
32
  // src/errors.ts
28
33
  var LiveAuthTimeoutError = class extends Error {
29
- constructor(message = "Lightning verification timed out") {
34
+ constructor(message = "LiveAuth verification timed out") {
30
35
  super(message);
31
36
  this.name = "LiveAuthTimeoutError";
32
37
  }
33
38
  };
34
39
  var LiveAuthCancelledError = class extends Error {
35
- constructor(message = "Lightning verification cancelled") {
40
+ constructor(message = "LiveAuth verification cancelled") {
36
41
  super(message);
37
42
  this.name = "LiveAuthCancelledError";
38
43
  }
39
44
  };
45
+ var LiveAuthNetworkError = class extends Error {
46
+ constructor(message = "LiveAuth network request failed", cause) {
47
+ super(message);
48
+ this.cause = cause;
49
+ this.name = "LiveAuthNetworkError";
50
+ }
51
+ };
52
+ var LiveAuthPowUnsupportedError = class extends Error {
53
+ constructor(message = "Proof-of-Work is not supported in this environment") {
54
+ super(message);
55
+ this.name = "LiveAuthPowUnsupportedError";
56
+ }
57
+ };
58
+ var LiveAuthPowTimeoutError = class extends Error {
59
+ constructor(message = "Proof-of-Work timed out") {
60
+ super(message);
61
+ this.name = "LiveAuthPowTimeoutError";
62
+ }
63
+ };
40
64
 
41
65
  // src/index.ts
42
66
  var import_meta = {};
67
+ var SDK_VERSION = "0.2.0";
43
68
  var LiveAuth = class {
44
69
  constructor(config) {
45
70
  this.config = config;
@@ -49,85 +74,149 @@ var LiveAuth = class {
49
74
  this.baseUrl = config.baseUrl ?? "https://api.liveauth.app";
50
75
  this.headers = {
51
76
  "Content-Type": "application/json",
52
- "X-LW-Public": config.publicKey
77
+ "X-LW-Public": config.publicKey,
78
+ "X-LW-SDK-Version": SDK_VERSION
53
79
  };
54
80
  }
55
81
  /* ======================================================
56
82
  * PUBLIC ENTRYPOINT
57
83
  * ====================================================== */
58
- async verify() {
59
- const startedAt = performance.now();
60
- const challenge = await this.getPowChallenge();
61
- const solution = await this.solvePow(challenge);
62
- const verifyRes = await this.verifyPow({
63
- challengeHex: challenge.challengeHex,
64
- nonce: solution.nonce,
65
- hashHex: solution.hashHex,
66
- expiresAtUnix: challenge.expiresAtUnix,
67
- sig: challenge.sig
68
- });
69
- if (verifyRes.verified && verifyRes.token) {
84
+ async verify(options = {}) {
85
+ const {
86
+ forceLightning = false,
87
+ onProgress,
88
+ powTimeoutMs = 3e4,
89
+ maxPowIterations = 5e7
90
+ } = options;
91
+ if (forceLightning) {
92
+ const lightning = await this.startLightning();
70
93
  return {
71
- method: "pow",
72
- token: verifyRes.token,
73
- solveMs: Math.round(performance.now() - startedAt),
74
- difficultyBits: challenge.difficultyBits
94
+ method: "lightning",
95
+ lightning,
96
+ diagnostics: { reason: "forced_lightning" }
75
97
  };
76
98
  }
77
- if (verifyRes.fallback === "lightning") {
99
+ if (!this.canUsePow()) {
78
100
  const lightning = await this.startLightning();
79
101
  return {
80
102
  method: "lightning",
81
- lightning
103
+ lightning,
104
+ diagnostics: { reason: "pow_unsupported" }
82
105
  };
83
106
  }
84
- throw new Error("LiveAuth: verification failed");
107
+ const startedAt = performance.now();
108
+ try {
109
+ const challenge = await this.getPowChallenge();
110
+ const solution = await this.solvePow(challenge, {
111
+ onProgress,
112
+ timeoutMs: powTimeoutMs,
113
+ maxIterations: maxPowIterations
114
+ });
115
+ const verifyRes = await this.verifyPow({
116
+ challengeHex: challenge.challengeHex,
117
+ nonce: solution.nonce,
118
+ hashHex: solution.hashHex,
119
+ expiresAtUnix: challenge.expiresAtUnix,
120
+ difficultyBits: challenge.difficultyBits,
121
+ sig: challenge.sig
122
+ });
123
+ if (verifyRes.verified && verifyRes.token) {
124
+ return {
125
+ method: "pow",
126
+ token: verifyRes.token,
127
+ solveMs: Math.round(performance.now() - startedAt),
128
+ difficultyBits: challenge.difficultyBits
129
+ };
130
+ }
131
+ if (verifyRes.fallback === "lightning") {
132
+ const lightning = await this.startLightning();
133
+ return {
134
+ method: "lightning",
135
+ lightning,
136
+ diagnostics: { reason: "pow_server_fallback" }
137
+ };
138
+ }
139
+ throw new Error("LiveAuth: verification failed");
140
+ } catch (err) {
141
+ if (err instanceof LiveAuthPowTimeoutError || err instanceof LiveAuthPowUnsupportedError) {
142
+ const lightning = await this.startLightning();
143
+ return {
144
+ method: "lightning",
145
+ lightning,
146
+ diagnostics: {
147
+ reason: "pow_failed",
148
+ detail: err.message
149
+ }
150
+ };
151
+ }
152
+ throw err;
153
+ }
85
154
  }
86
155
  /* ======================================================
87
156
  * POW FLOW
88
157
  * ====================================================== */
89
158
  async getPowChallenge() {
90
- const res = await fetch(`${this.baseUrl}/api/public/pow/challenge`, {
159
+ const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/challenge`, {
91
160
  headers: this.headers
92
161
  });
93
- if (!res.ok) throw new Error("PoW challenge failed");
162
+ if (!res.ok) throw new LiveAuthNetworkError("PoW challenge failed");
94
163
  return res.json();
95
164
  }
96
165
  async verifyPow(req) {
97
- const res = await fetch(`${this.baseUrl}/api/public/pow/verify`, {
166
+ const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/pow/verify`, {
98
167
  method: "POST",
99
168
  headers: this.headers,
100
169
  body: JSON.stringify(req)
101
170
  });
102
- if (!res.ok) throw new Error("PoW verify failed");
171
+ if (!res.ok) throw new LiveAuthNetworkError("PoW verify failed");
103
172
  return res.json();
104
173
  }
105
174
  /* ======================================================
106
175
  * POW SOLVER (WORKER)
107
176
  * ====================================================== */
108
- solvePow(challenge) {
177
+ solvePow(challenge, options = {}) {
178
+ const { onProgress, timeoutMs = 3e4, maxIterations = 5e7 } = options;
109
179
  if (!this.canUsePow()) {
110
- return Promise.reject(
111
- new Error("LiveAuth: PoW not supported in this environment")
112
- );
180
+ return Promise.reject(new LiveAuthPowUnsupportedError());
113
181
  }
114
182
  return new Promise((resolve, reject) => {
115
183
  const worker = new Worker(
116
184
  new URL("./pow.worker.js", import_meta.url),
117
185
  { type: "module" }
118
186
  );
119
- worker.onmessage = (e) => {
187
+ const timeoutId = setTimeout(() => {
120
188
  worker.terminate();
121
- resolve(e.data);
189
+ reject(new LiveAuthPowTimeoutError(`PoW timed out after ${timeoutMs}ms`));
190
+ }, timeoutMs);
191
+ worker.onmessage = (e) => {
192
+ const data = e.data;
193
+ if (data.type === "progress") {
194
+ onProgress?.(data.hashesPerSec ?? 0, data.iterations ?? 0);
195
+ return;
196
+ }
197
+ if (data.type === "timeout") {
198
+ clearTimeout(timeoutId);
199
+ worker.terminate();
200
+ reject(new LiveAuthPowTimeoutError(`PoW hit max iterations (${maxIterations})`));
201
+ return;
202
+ }
203
+ if (data.type === "solution" && data.nonce !== void 0 && data.hashHex) {
204
+ clearTimeout(timeoutId);
205
+ worker.terminate();
206
+ resolve({ nonce: data.nonce, hashHex: data.hashHex });
207
+ return;
208
+ }
122
209
  };
123
210
  worker.onerror = (e) => {
211
+ clearTimeout(timeoutId);
124
212
  worker.terminate();
125
- reject(e);
213
+ reject(new LiveAuthPowUnsupportedError(`Worker error: ${e.message}`));
126
214
  };
127
215
  worker.postMessage({
128
216
  projectPublicKey: challenge.projectPublicKey,
129
217
  challengeHex: challenge.challengeHex,
130
- targetHex: challenge.targetHex
218
+ targetHex: challenge.targetHex,
219
+ maxIterations
131
220
  });
132
221
  });
133
222
  }
@@ -135,26 +224,16 @@ var LiveAuth = class {
135
224
  * LIGHTNING FALLBACK
136
225
  * ====================================================== */
137
226
  async startLightning() {
138
- const res = await fetch(`${this.baseUrl}/api/public/auth/start`, {
227
+ const res = await this.fetchWithRetry(`${this.baseUrl}/api/public/auth/start`, {
139
228
  method: "POST",
140
229
  headers: this.headers,
141
230
  body: JSON.stringify({ userHint: "browser" })
142
231
  });
143
232
  if (!res.ok) {
144
- throw new Error("Lightning auth start failed");
233
+ throw new LiveAuthNetworkError("Lightning auth start failed");
145
234
  }
146
235
  return res.json();
147
236
  }
148
- canUsePow() {
149
- try {
150
- if (typeof window === "undefined") return false;
151
- if (typeof Worker === "undefined") return false;
152
- if (typeof URL === "undefined") return false;
153
- return true;
154
- } catch {
155
- return false;
156
- }
157
- }
158
237
  async pollLightning(sessionId, options) {
159
238
  const timeoutMs = options?.timeoutMs ?? 5 * 6e4;
160
239
  const intervalMs = options?.intervalMs ?? 2e3;
@@ -187,7 +266,7 @@ var LiveAuth = class {
187
266
  }
188
267
  );
189
268
  if (!res.ok) {
190
- throw new Error("Lightning confirm failed");
269
+ throw new LiveAuthNetworkError("Lightning confirm failed");
191
270
  }
192
271
  const json = await res.json();
193
272
  if (json.verified && json.token) {
@@ -199,10 +278,47 @@ var LiveAuth = class {
199
278
  clearTimeout(timeoutId);
200
279
  }
201
280
  }
281
+ /* ======================================================
282
+ * UTILITIES
283
+ * ====================================================== */
284
+ canUsePow() {
285
+ try {
286
+ if (typeof window === "undefined") return false;
287
+ if (typeof Worker === "undefined") return false;
288
+ if (typeof URL === "undefined") return false;
289
+ if (typeof crypto === "undefined" || !crypto.subtle) return false;
290
+ return true;
291
+ } catch {
292
+ return false;
293
+ }
294
+ }
295
+ async fetchWithRetry(url, init, retries = 2, backoffMs = 500) {
296
+ let lastError;
297
+ for (let attempt = 0; attempt <= retries; attempt++) {
298
+ try {
299
+ const res = await fetch(url, init);
300
+ return res;
301
+ } catch (err) {
302
+ lastError = err instanceof Error ? err : new Error(String(err));
303
+ if (attempt < retries) {
304
+ await sleep(backoffMs * Math.pow(2, attempt));
305
+ }
306
+ }
307
+ }
308
+ throw new LiveAuthNetworkError(
309
+ `Request failed after ${retries + 1} attempts`,
310
+ lastError
311
+ );
312
+ }
202
313
  };
203
314
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
204
315
  // Annotate the CommonJS export names for ESM import in node:
205
316
  0 && (module.exports = {
206
- LiveAuth
317
+ LiveAuth,
318
+ LiveAuthCancelledError,
319
+ LiveAuthNetworkError,
320
+ LiveAuthPowTimeoutError,
321
+ LiveAuthPowUnsupportedError,
322
+ LiveAuthTimeoutError
207
323
  });
208
324
  //# sourceMappingURL=index.cjs.map
@@ -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 AuthStartResponse,\n AuthConfirmResponse,\n LiveAuthConfig, LightningStart\n} from './types';\nimport {LiveAuthCancelledError, LiveAuthTimeoutError} from \"./errors\";\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 };\n }\n\n /* ======================================================\n * PUBLIC ENTRYPOINT\n * ====================================================== */\n\n async verify(): Promise<LiveAuthResult> {\n const startedAt = performance.now();\n\n const challenge = await this.getPowChallenge();\n const solution = await this.solvePow(challenge);\n\n const verifyRes = await this.verifyPow({\n challengeHex: challenge.challengeHex,\n nonce: solution.nonce,\n hashHex: solution.hashHex,\n expiresAtUnix: challenge.expiresAtUnix,\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 };\n }\n\n throw new Error('LiveAuth: verification failed');\n }\n\n /* ======================================================\n * POW FLOW\n * ====================================================== */\n\n private async getPowChallenge(): Promise<PowChallengeResponse> {\n const res = await fetch(`${this.baseUrl}/api/public/pow/challenge`, {\n headers: this.headers\n });\n\n if (!res.ok) throw new Error('PoW challenge failed');\n return res.json();\n }\n\n private async verifyPow(req: PowVerifyRequest): Promise<PowVerifyResponse> {\n const res = await fetch(`${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 Error('PoW verify failed');\n return res.json();\n }\n\n /* ======================================================\n * POW SOLVER (WORKER)\n * ====================================================== */\n\n private solvePow(challenge: PowChallengeResponse): Promise<PowSolution> {\n if (!this.canUsePow()) {\n return Promise.reject(\n new Error('LiveAuth: PoW not supported in this environment')\n );\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 worker.onmessage = e => {\n worker.terminate();\n resolve(e.data);\n };\n\n worker.onerror = e => {\n worker.terminate();\n reject(e);\n };\n\n worker.postMessage({\n projectPublicKey: challenge.projectPublicKey,\n challengeHex: challenge.challengeHex,\n targetHex: challenge.targetHex\n });\n });\n }\n\n /* ======================================================\n * LIGHTNING FALLBACK\n * ====================================================== */\n\n private async startLightning(): Promise<LightningStart> {\n const res = await fetch(`${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 Error('Lightning auth start failed');\n }\n\n return res.json();\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 return true;\n } catch {\n return false;\n }\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 Error('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}\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 = 'Lightning verification timed out') {\n super(message);\n this.name = 'LiveAuthTimeoutError';\n }\n}\n\nexport class LiveAuthCancelledError extends Error {\n constructor(message = 'Lightning verification cancelled') {\n super(message);\n this.name = 'LiveAuthCancelledError';\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 '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":[]}