@embarkai/ui-kit 0.4.25 → 0.4.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1091 +0,0 @@
1
- import {
2
- AccountAbstractionError,
3
- DiscordIcon,
4
- ErrorCodes,
5
- GoogleIcon,
6
- TelegramIcon,
7
- TwitterIcon,
8
- getIframeManager,
9
- getServiceUrls,
10
- init_assets,
11
- init_initial
12
- } from "./chunk-MLUPZCC3.js";
13
- import {
14
- __export,
15
- __reExport
16
- } from "./chunk-DBFKMKYT.js";
17
-
18
- // src/internal/lib/site.ts
19
- var DAPP_NAME = "passport";
20
-
21
- // src/internal/auth/index.ts
22
- import {
23
- JwtTokenManager,
24
- createJwtTokenManager,
25
- jwtTokenManager as jwtTokenManager2,
26
- configureJwtModule,
27
- logout,
28
- verifyToken,
29
- ensureValidToken,
30
- getValidTokens,
31
- authenticatedFetch,
32
- loginWithUserId,
33
- loginWithEmail,
34
- loginWithTelegram,
35
- syncKeyshareStatus
36
- } from "@embarkai/core/auth";
37
-
38
- // src/internal/auth/passkeyAuth.ts
39
- init_initial();
40
- import { jwtTokenManager } from "@embarkai/core/auth";
41
-
42
- // src/internal/utils/projectId.ts
43
- function addProjectIdToUrl(url) {
44
- try {
45
- const projectId = typeof window !== "undefined" ? window.__EMBARK_PROJECT_ID__ : void 0;
46
- if (projectId) {
47
- const separator = url.includes("?") ? "&" : "?";
48
- return `${url}${separator}projectId=${encodeURIComponent(projectId)}`;
49
- }
50
- } catch {
51
- }
52
- return url;
53
- }
54
- function getProjectId() {
55
- try {
56
- return typeof window !== "undefined" ? window.__EMBARK_PROJECT_ID__ : void 0;
57
- } catch {
58
- return void 0;
59
- }
60
- }
61
-
62
- // src/internal/auth/base64url.ts
63
- var base64url_exports = {};
64
- __export(base64url_exports, {
65
- arrayBufferToBase64url: () => arrayBufferToBase64url,
66
- base64urlToUint8Array: () => base64urlToUint8Array
67
- });
68
- __reExport(base64url_exports, auth_star);
69
- import * as auth_star from "@embarkai/core/auth";
70
- function arrayBufferToBase64url(buffer) {
71
- const bytes = new Uint8Array(buffer);
72
- let binary = "";
73
- for (let i = 0; i < bytes.byteLength; i++) {
74
- binary += String.fromCharCode(bytes[i]);
75
- }
76
- const base64 = btoa(binary);
77
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
78
- }
79
- function base64urlToUint8Array(base64url) {
80
- const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
81
- const pad = base64.length % 4 ? 4 - base64.length % 4 : 0;
82
- const padded = base64 + "=".repeat(pad);
83
- const binary = atob(padded);
84
- const bytes = new Uint8Array(binary.length);
85
- for (let i = 0; i < binary.length; i++) {
86
- bytes[i] = binary.charCodeAt(i);
87
- }
88
- return bytes;
89
- }
90
-
91
- // src/internal/auth/webauthn.ts
92
- function credentialToAttestationPayload(credential) {
93
- const response = credential.response;
94
- const transports = response.getTransports?.() || [];
95
- return {
96
- id: credential.id,
97
- rawId: arrayBufferToBase64url(credential.rawId),
98
- type: credential.type,
99
- response: {
100
- clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),
101
- attestationObject: arrayBufferToBase64url(response.attestationObject),
102
- transports
103
- }
104
- };
105
- }
106
-
107
- // src/internal/auth/passkeyAuth.ts
108
- function getTssUrl() {
109
- return getServiceUrls().tssUrl;
110
- }
111
- async function beginPasskeyAuthentication(username) {
112
- const response = await fetch(addProjectIdToUrl(`${getTssUrl()}/api/auth/passkey/login/begin`), {
113
- method: "POST",
114
- headers: { "Content-Type": "application/json" },
115
- credentials: "include",
116
- body: JSON.stringify({ username })
117
- });
118
- if (!response.ok) {
119
- const errorText = await response.text().catch(() => "Failed to begin authentication");
120
- throw new Error(`Begin auth failed: ${response.status} ${errorText}`);
121
- }
122
- const beginResponse = await response.json();
123
- const options = {
124
- challenge: base64urlToUint8Array(beginResponse.challenge),
125
- allowCredentials: (beginResponse.allowCredentials || []).map((cred) => ({
126
- type: cred.type,
127
- id: base64urlToUint8Array(cred.id),
128
- transports: cred.transports
129
- })),
130
- timeout: beginResponse.timeout,
131
- userVerification: beginResponse.userVerification || "preferred",
132
- extensions: beginResponse.extensions
133
- };
134
- return {
135
- challenge: beginResponse.challenge,
136
- challengeId: beginResponse.challengeId,
137
- options
138
- };
139
- }
140
- async function completePasskeyAuthentication(challengeId, credential, options) {
141
- const response = credential.response;
142
- const credentialData = {
143
- id: credential.id,
144
- rawId: arrayBufferToBase64url(credential.rawId),
145
- type: credential.type,
146
- response: {
147
- clientDataJSON: arrayBufferToBase64url(response.clientDataJSON),
148
- authenticatorData: arrayBufferToBase64url(response.authenticatorData),
149
- signature: arrayBufferToBase64url(response.signature),
150
- userHandle: response.userHandle ? arrayBufferToBase64url(response.userHandle) : null
151
- }
152
- };
153
- const completeResponse = await fetch(addProjectIdToUrl(`${getTssUrl()}/api/auth/passkey/login/complete`), {
154
- method: "POST",
155
- headers: { "Content-Type": "application/json" },
156
- credentials: "include",
157
- body: JSON.stringify({ challengeId, credential: credentialData })
158
- });
159
- if (!completeResponse.ok) {
160
- let message = "Authentication failed";
161
- try {
162
- const err = await completeResponse.json();
163
- message = err?.message || message;
164
- } catch {
165
- try {
166
- const text = await completeResponse.text();
167
- message = (text || message).slice(0, 200);
168
- } catch {
169
- }
170
- }
171
- throw new Error(`Complete authentication failed: ${completeResponse.status} ${message}`);
172
- }
173
- const loginResponse = await completeResponse.json();
174
- if (!options?.skipTokenSave) {
175
- await jwtTokenManager.setTokens(loginResponse);
176
- }
177
- return loginResponse;
178
- }
179
- async function beginPasskeyRegistration(username) {
180
- const response = await fetch(addProjectIdToUrl(`${getTssUrl()}/api/auth/passkey/register/begin`), {
181
- method: "POST",
182
- headers: { "Content-Type": "application/json" },
183
- credentials: "include",
184
- body: JSON.stringify({ username })
185
- });
186
- if (!response.ok) {
187
- const errorText = await response.text().catch(() => "Failed to begin registration");
188
- throw new Error(`Begin registration failed: ${response.status} ${errorText}`);
189
- }
190
- const beginResponse = await response.json();
191
- const options = {
192
- rp: beginResponse.rp,
193
- user: {
194
- id: base64urlToUint8Array(beginResponse.user.id),
195
- name: beginResponse.user.name,
196
- displayName: beginResponse.user.displayName
197
- },
198
- challenge: base64urlToUint8Array(beginResponse.challenge),
199
- pubKeyCredParams: beginResponse.pubKeyCredParams,
200
- timeout: beginResponse.timeout,
201
- attestation: beginResponse.attestation,
202
- authenticatorSelection: {
203
- ...beginResponse.authenticatorSelection,
204
- residentKey: "preferred",
205
- requireResidentKey: false,
206
- userVerification: "preferred"
207
- },
208
- excludeCredentials: beginResponse.excludeCredentials?.map((cred) => ({
209
- type: cred.type,
210
- id: base64urlToUint8Array(cred.id),
211
- transports: cred.transports
212
- })) || void 0
213
- };
214
- return {
215
- challengeId: beginResponse.challengeId,
216
- options
217
- };
218
- }
219
- async function completePasskeyRegistration(challengeId, credential, options) {
220
- const credentialData = credentialToAttestationPayload(credential);
221
- const completeResponse = await fetch(addProjectIdToUrl(`${getTssUrl()}/api/auth/passkey/register/complete`), {
222
- method: "POST",
223
- headers: { "Content-Type": "application/json" },
224
- credentials: "include",
225
- body: JSON.stringify({ challengeId, credential: credentialData })
226
- });
227
- if (!completeResponse.ok) {
228
- const errorText = await completeResponse.text().catch(() => "Registration failed");
229
- throw new Error(errorText);
230
- }
231
- const loginResponse = await completeResponse.json();
232
- if (!options?.skipTokenSave) {
233
- await jwtTokenManager.setTokens(loginResponse);
234
- }
235
- return loginResponse;
236
- }
237
-
238
- // src/internal/auth/telegram.ts
239
- import { isHex, toHex, keccak256, stringToBytes } from "viem";
240
- function deriveDemoPrivateKey(user, salt) {
241
- const base = `${user.id}:${salt}`;
242
- const h = keccak256(stringToBytes(base));
243
- const pk = h.slice(0, 66);
244
- return isHex(pk) ? pk : toHex(h).slice(0, 66);
245
- }
246
- function initTelegramWidget(botUsername, onAuth, salt = "demo", rootId = "tg-root") {
247
- const root = document.getElementById(rootId);
248
- if (!root) {
249
- console.warn(`[Telegram] No ${rootId} element found`);
250
- return () => {
251
- };
252
- }
253
- root.innerHTML = "";
254
- window.onTelegramAuth = async (user) => {
255
- if (!user?.id || !user.auth_date || !user.hash) throw new Error("Invalid Telegram auth payload");
256
- const privateKey = deriveDemoPrivateKey(user, salt);
257
- const displayName = user.first_name || user.username || `User ${user.id}`;
258
- await onAuth({ user, privateKey, displayName });
259
- };
260
- const script = document.createElement("script");
261
- script.async = true;
262
- script.src = "https://telegram.org/js/telegram-widget.js?22";
263
- script.setAttribute("data-telegram-login", botUsername);
264
- script.setAttribute("data-size", "large");
265
- script.setAttribute("data-userpic", "true");
266
- script.setAttribute("data-onauth", "onTelegramAuth(user)");
267
- script.setAttribute("data-request-access", "write");
268
- script.onerror = (error) => {
269
- console.error("[Telegram] Failed to load widget script:", error);
270
- };
271
- root.appendChild(script);
272
- return () => {
273
- try {
274
- delete window.onTelegramAuth;
275
- if (root) root.innerHTML = "";
276
- if (script && script.parentElement && document.contains(script)) script.parentElement.removeChild(script);
277
- } catch {
278
- }
279
- };
280
- }
281
- function hideTelegramWidget() {
282
- try {
283
- const root = document.getElementById("tg-root");
284
- if (root) root.style.display = "none";
285
- } catch {
286
- }
287
- }
288
- function showTelegramWidget() {
289
- try {
290
- const root = document.getElementById("tg-root");
291
- if (root) root.style.display = "";
292
- } catch {
293
- }
294
- }
295
-
296
- // src/internal/lib/iframe-mpc-client.ts
297
- import { logSdkError } from "@embarkai/core/internal/error-tracking";
298
- var currentSigningStats = null;
299
- async function ensureDkgAndGetOwner(userId, _clientSeedHex) {
300
- try {
301
- const iframeManager = getIframeManager();
302
- const keyshareStatus = await iframeManager.checkKeyshare(userId);
303
- if (keyshareStatus.hasKeyshare && keyshareStatus.address) {
304
- return {
305
- sessionId: "iframe-session",
306
- ownerAddress: keyshareStatus.address
307
- };
308
- }
309
- await iframeManager.authenticate(userId);
310
- const { jwtTokenManager: jwtTokenManager3 } = await import("./auth-GP4VPOSM.js");
311
- let accessToken = jwtTokenManager3.getAccessToken();
312
- if (!accessToken) {
313
- console.warn("[iframe-mpc-client] No access token available for DKG, attempting cookie-based session");
314
- accessToken = void 0;
315
- }
316
- const ownerAddress = await iframeManager.startDKG(userId, accessToken);
317
- return {
318
- sessionId: "iframe-session",
319
- ownerAddress
320
- };
321
- } catch (error) {
322
- logSdkError(error instanceof Error ? error : new Error("DKG failed"), { userId }, "iframe-mpc");
323
- throw error;
324
- }
325
- }
326
- function isChannelError(error) {
327
- const message = error.message.toLowerCase();
328
- return message.includes("invalid sdk channel") || message.includes("sdk channel not found") || message.includes("sdk channel expired") || // Backward compatibility
329
- message === "invalid session";
330
- }
331
- async function signDigestWithMpc(userId, digest32, userOpDetails) {
332
- const MAX_RETRIES = 1;
333
- const startTime = performance.now();
334
- currentSigningStats = {
335
- startTime,
336
- rounds: []
337
- };
338
- let lastError;
339
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
340
- try {
341
- const iframeManager = getIframeManager();
342
- const { jwtTokenManager: jwtTokenManager3 } = await import("./auth-GP4VPOSM.js");
343
- const accessToken = jwtTokenManager3.getAccessToken();
344
- if (!accessToken) {
345
- throw new Error("No access token available for signing");
346
- }
347
- const batchOperations = userOpDetails?.operations || [];
348
- const firstBatchOperation = batchOperations[0];
349
- const batchValue = batchOperations.length > 0 ? batchOperations.reduce((total, operation) => total + BigInt(operation.value || "0"), 0n).toString() : void 0;
350
- const transaction = {
351
- to: userOpDetails?.callTarget || firstBatchOperation?.to || "0x0000000000000000000000000000000000000000",
352
- value: userOpDetails?.value || batchValue || "0",
353
- data: userOpDetails?.callData || firstBatchOperation?.data || "0x",
354
- digest32,
355
- // Pre-computed digest - DO NOT recompute!
356
- // Additional UserOp fields for display in confirmation modal
357
- userOpDetails
358
- };
359
- const signature = await iframeManager.signTransaction(userId, transaction, accessToken);
360
- const endTime = performance.now();
361
- currentSigningStats.endTime = endTime;
362
- currentSigningStats.totalDurationMs = endTime - startTime;
363
- return signature;
364
- } catch (error) {
365
- lastError = error instanceof Error ? error : new Error("MPC signing failed");
366
- if (isChannelError(lastError) && attempt < MAX_RETRIES) {
367
- console.warn(`[MPC] SDK channel error, reconnecting and retrying (attempt ${attempt + 1})...`);
368
- try {
369
- await getIframeManager().reconnect();
370
- continue;
371
- } catch (reconnectError) {
372
- console.error("[MPC] Reconnect failed:", reconnectError);
373
- }
374
- }
375
- logSdkError(lastError, { userId, hasUserOpDetails: !!userOpDetails, attempt }, "iframe-mpc");
376
- const endTime = performance.now();
377
- if (currentSigningStats) {
378
- currentSigningStats.endTime = endTime;
379
- currentSigningStats.totalDurationMs = endTime - startTime;
380
- }
381
- if (lastError instanceof AccountAbstractionError) {
382
- throw lastError;
383
- }
384
- throw new AccountAbstractionError(lastError.message, ErrorCodes.MPC_SIGNING_ERROR);
385
- }
386
- }
387
- throw lastError || new Error("MPC signing failed after retries");
388
- }
389
- async function signTypedDataWithMpc(userId, digest32, typedData) {
390
- const startTime = performance.now();
391
- currentSigningStats = {
392
- startTime,
393
- rounds: []
394
- };
395
- try {
396
- console.log("[signTypedDataWithMpc] Starting EIP712 signature request:", {
397
- userId,
398
- primaryType: typedData?.primaryType,
399
- digest32
400
- });
401
- const iframeManager = getIframeManager();
402
- const { jwtTokenManager: jwtTokenManager3 } = await import("./auth-GP4VPOSM.js");
403
- const accessToken = jwtTokenManager3.getAccessToken();
404
- if (!accessToken) {
405
- console.error("[signTypedDataWithMpc] No access token available");
406
- throw new Error("No access token available for signing");
407
- }
408
- console.log("[signTypedDataWithMpc] Calling iframeManager.signTypedData...");
409
- const signature = await iframeManager.signTypedData(userId, typedData, digest32, accessToken);
410
- console.log("[signTypedDataWithMpc] Signature received:", signature);
411
- const endTime = performance.now();
412
- currentSigningStats.endTime = endTime;
413
- currentSigningStats.totalDurationMs = endTime - startTime;
414
- return signature;
415
- } catch (error) {
416
- console.error("[signTypedDataWithMpc] Error occurred:", error);
417
- logSdkError(
418
- error instanceof Error ? error : new Error("EIP712 MPC signing failed"),
419
- { userId, primaryType: typedData?.primaryType },
420
- "iframe-mpc"
421
- );
422
- const endTime = performance.now();
423
- if (currentSigningStats) {
424
- currentSigningStats.endTime = endTime;
425
- currentSigningStats.totalDurationMs = endTime - startTime;
426
- }
427
- if (error instanceof AccountAbstractionError) {
428
- throw error;
429
- }
430
- throw new AccountAbstractionError(
431
- error instanceof Error ? error.message : "EIP712 MPC signing failed",
432
- ErrorCodes.MPC_SIGNING_ERROR
433
- );
434
- }
435
- }
436
- async function checkKeyshare(userId) {
437
- try {
438
- const iframeManager = getIframeManager();
439
- return await iframeManager.checkKeyshare(userId);
440
- } catch (error) {
441
- console.error("[IframeMPC] Error checking keyshare:", error);
442
- return { hasKeyshare: false };
443
- }
444
- }
445
-
446
- // src/internal/auth/keyshare.ts
447
- async function checkKeyshareStatusWithSync(userId) {
448
- const serverHasKeyshare = await syncKeyshareStatus();
449
- return checkKeyshareStatus(userId, serverHasKeyshare);
450
- }
451
- async function checkKeyshareStatus(userId, serverHasKeyshare) {
452
- const keyshareInfo = await checkKeyshare(userId);
453
- const hasLocalKeyshare = keyshareInfo.hasKeyshare;
454
- const localOwnerAddress = keyshareInfo.address;
455
- console.log("[checkKeyshareStatus] Checking via iframe:", {
456
- userId,
457
- serverHasKeyshare,
458
- hasLocalKeyshare,
459
- ownerAddress: localOwnerAddress
460
- });
461
- let needsDkg = false;
462
- let needsRecovery = false;
463
- if (!serverHasKeyshare && !hasLocalKeyshare) needsDkg = true;
464
- else if (serverHasKeyshare && !hasLocalKeyshare) needsRecovery = true;
465
- else if (!serverHasKeyshare && hasLocalKeyshare) {
466
- needsDkg = true;
467
- }
468
- const result = {
469
- hasServerKeyshare: serverHasKeyshare,
470
- hasLocalKeyshare,
471
- needsDkg,
472
- needsRecovery,
473
- ownerAddress: localOwnerAddress
474
- };
475
- console.log("[checkKeyshareStatus] Result:", result);
476
- return result;
477
- }
478
- async function ensureKeyshareForNewUser(userId, onProgress) {
479
- onProgress?.("Setting up secure key management...");
480
- const result = await ensureDkgAndGetOwner(userId);
481
- if (!result.ownerAddress) throw new Error("DKG completed but no owner address received");
482
- await syncKeyshareStatus();
483
- onProgress?.("Key management setup complete");
484
- return { ownerAddress: result.ownerAddress };
485
- }
486
- async function ensureKeyshare(userId, serverHasKeyshare, onProgress, isNewUser) {
487
- console.log("[ensureKeyshare] Called with:", { userId, serverHasKeyshare, isNewUser });
488
- const status = await checkKeyshareStatus(userId, serverHasKeyshare);
489
- if (!status.needsDkg && !status.needsRecovery && status.ownerAddress) {
490
- console.log("[ensureKeyshare] Keyshare already ready, returning");
491
- onProgress?.("Keyshare ready");
492
- return { ownerAddress: status.ownerAddress };
493
- }
494
- if (status.needsRecovery) {
495
- console.log("[ensureKeyshare] Recovery needed, checking backups...");
496
- onProgress?.("Checking backup availability...");
497
- const { checkServerBackupAvailability, getBackupStatus } = await import("./vaultClient-MWKJKXZC.js");
498
- const localBackupStatus = getBackupStatus(userId);
499
- const serverBackupResult = await checkServerBackupAvailability();
500
- const hasLocalBackup = localBackupStatus.local.enabled && localBackupStatus.local.lastBackup;
501
- const hasCloudBackup = localBackupStatus.cloud.enabled && localBackupStatus.cloud.lastBackup;
502
- const hasAnyBackup = serverBackupResult.hasBackup || hasLocalBackup || hasCloudBackup;
503
- if (!serverBackupResult.serviceAvailable) {
504
- if (!hasLocalBackup && !hasCloudBackup) {
505
- const e = new Error("Your account exists but backup verification failed.\n\nThe backup server is currently unavailable.");
506
- e.code = "BACKUP_SERVICE_UNAVAILABLE";
507
- e.userId = userId;
508
- e.serverHasKeyshare = true;
509
- throw e;
510
- }
511
- } else if (!hasAnyBackup) {
512
- const noBackupError = new Error("Your account exists but no backups are available for recovery.");
513
- noBackupError.code = "NO_BACKUP_AVAILABLE";
514
- noBackupError.userId = userId;
515
- noBackupError.serverHasKeyshare = true;
516
- throw noBackupError;
517
- }
518
- onProgress?.("Backup found - restoration required");
519
- const recoveryError = new Error("Account exists on server but keyshare missing locally. Please restore from backup to access your account.");
520
- recoveryError.code = "KEYSHARE_RECOVERY_NEEDED";
521
- recoveryError.userId = userId;
522
- recoveryError.serverHasKeyshare = true;
523
- recoveryError.availableBackups = { server: serverBackupResult.hasBackup, local: hasLocalBackup, cloud: hasCloudBackup };
524
- throw recoveryError;
525
- }
526
- if (status.needsDkg) {
527
- onProgress?.("Setting up secure key management...");
528
- } else {
529
- throw new Error("Invalid keyshare state - neither DKG nor recovery needed but keyshare missing");
530
- }
531
- return ensureKeyshareForNewUser(userId, onProgress);
532
- }
533
- async function clearLocalKeyshare(userId) {
534
- console.log("[clearLocalKeyshare] Keyshares are now managed by secure iframe");
535
- console.log("[clearLocalKeyshare] To clear keyshares, user must revoke authorization in iframe");
536
- if (typeof window !== "undefined" && window.localStorage) {
537
- const keys = [
538
- `tss.${userId}.keyshare`,
539
- `tss.${userId}.ownerAddress`,
540
- `tss.${userId}.sessionId`,
541
- ...Object.keys(window.localStorage).filter((key) => key.startsWith(`tss.${userId}.dkg.`))
542
- ];
543
- keys.forEach((key) => window.localStorage.removeItem(key));
544
- console.log("[clearLocalKeyshare] Cleared old localStorage keys for migration");
545
- }
546
- }
547
- async function getKeyshareInfo(userId) {
548
- const info = await checkKeyshare(userId);
549
- return {
550
- hasKeyshare: info.hasKeyshare,
551
- ownerAddress: info.address,
552
- sessionId: "iframe-session",
553
- // Session managed by iframe
554
- keyshareSize: void 0
555
- // Size not exposed for security
556
- };
557
- }
558
-
559
- // src/internal/auth/providers/types.ts
560
- init_assets();
561
- init_initial();
562
- import { Key, Mail, Wallet2 } from "lucide-react";
563
- function getTssUrl2() {
564
- return getServiceUrls().tssUrl;
565
- }
566
- var PROVIDERS_META = {
567
- passkey: { name: "Passkey", icon: Key, description: "Biometric authentication" },
568
- email: { name: "Email", icon: Mail, description: "Email verification" },
569
- telegram: { name: "Telegram", icon: TelegramIcon, description: "Telegram account" },
570
- google: { name: "Google", icon: GoogleIcon, description: "Google account" },
571
- discord: { name: "Discord", icon: DiscordIcon, description: "Discord account" },
572
- twitter: { name: "X", icon: TwitterIcon, description: "X (Twitter) account" },
573
- x: { name: "X", icon: TwitterIcon, description: "X (Twitter) account" },
574
- // Alias for twitter (API uses 'x')
575
- wallet: { name: "Wallet", icon: Wallet2, description: "External wallet (EOA)" }
576
- };
577
- var UNKNOWN_PROVIDER = { name: "Unknown", icon: Key, description: "Unknown provider" };
578
- function getProviderDisplayInfo(provider) {
579
- return PROVIDERS_META[provider] || UNKNOWN_PROVIDER;
580
- }
581
- function formatDate(dateString) {
582
- if (!dateString) return "Never";
583
- try {
584
- const date = new Date(dateString);
585
- return `${date.toLocaleDateString()} ${date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}`;
586
- } catch {
587
- return "Invalid date";
588
- }
589
- }
590
-
591
- // src/internal/auth/providers/common.ts
592
- async function getLinkedProviders() {
593
- const hasValidToken = await ensureValidToken();
594
- if (!hasValidToken) throw new Error("No authentication token available");
595
- const response = await authenticatedFetch(`${getTssUrl2()}/api/auth/providers`, { method: "GET" });
596
- if (!response.ok) {
597
- const errorData = await response.json().catch(() => ({}));
598
- throw new Error(errorData.message || `Failed to fetch providers: ${response.statusText}`);
599
- }
600
- const data = await response.json();
601
- return data.providers;
602
- }
603
- async function unlinkProvider(providerType, externalId) {
604
- const hasValidToken = await ensureValidToken();
605
- if (!hasValidToken) throw new Error("No authentication token available");
606
- let url = `${getTssUrl2()}/api/auth/unlink/${providerType}`;
607
- if (externalId) url += `?externalId=${encodeURIComponent(externalId)}`;
608
- const response = await authenticatedFetch(url, { method: "DELETE" });
609
- if (!response.ok) {
610
- const errorData = await response.json().catch(() => ({}));
611
- throw new Error(errorData.message || `Failed to unlink provider: ${response.statusText}`);
612
- }
613
- try {
614
- const data = await response.json();
615
- if (data?.accessToken && data?.refreshToken && data?.expiresIn) {
616
- jwtTokenManager2.setTokens({
617
- accessToken: data.accessToken,
618
- refreshToken: data.refreshToken,
619
- userId: jwtTokenManager2.getUserId() || "",
620
- expiresIn: data.expiresIn,
621
- hasKeyshare: jwtTokenManager2.getHasKeyshare() ?? false
622
- });
623
- }
624
- } catch {
625
- }
626
- }
627
-
628
- // src/internal/auth/providers/email.ts
629
- async function sendEmailLinkCode(email) {
630
- const hasValidToken = await ensureValidToken();
631
- if (!hasValidToken) throw new Error("No authentication token available");
632
- const response = await authenticatedFetch(`${getTssUrl2()}/api/auth/link/email/send-code`, {
633
- method: "POST",
634
- body: JSON.stringify({ email })
635
- });
636
- if (!response.ok) {
637
- const errorData = await response.json().catch(() => ({}));
638
- throw new Error(errorData.message || `Failed to send email verification code: ${response.statusText}`);
639
- }
640
- }
641
- async function verifyEmailLinkCode(email, code) {
642
- const hasValidToken = await ensureValidToken();
643
- if (!hasValidToken) throw new Error("No authentication token available");
644
- const response = await authenticatedFetch(`${getTssUrl2()}/api/auth/link/email/verify-code`, {
645
- method: "POST",
646
- credentials: "include",
647
- body: JSON.stringify({ email, code })
648
- });
649
- if (!response.ok) {
650
- const errorData = await response.json().catch(() => ({}));
651
- throw new Error(errorData.message || `Failed to verify email and link provider: ${response.statusText}`);
652
- }
653
- }
654
-
655
- // src/internal/auth/providers/passkey.ts
656
- async function completePasskeyLinking(payload) {
657
- const hasValidToken = await ensureValidToken();
658
- if (!hasValidToken) throw new Error("No authentication token available");
659
- const response = await authenticatedFetch(`${getTssUrl2()}/api/auth/link/passkey/complete`, {
660
- method: "POST",
661
- body: JSON.stringify(payload)
662
- });
663
- if (!response.ok) {
664
- const errorData = await response.json().catch(() => ({}));
665
- throw new Error(errorData.message || `Failed to link passkey: ${response.statusText}`);
666
- }
667
- }
668
- async function beginPasskeyLinking() {
669
- const hasValidToken = await ensureValidToken();
670
- if (!hasValidToken) throw new Error("No authentication token available");
671
- let res = await authenticatedFetch(`${getTssUrl2()}/api/auth/link/passkey/begin`, { method: "POST" });
672
- if (res.ok) {
673
- const begin2 = await res.json();
674
- const options2 = {
675
- rp: begin2.rp,
676
- user: { id: base64urlToUint8Array(begin2.user.id), name: begin2.user.name, displayName: begin2.user.displayName },
677
- challenge: base64urlToUint8Array(begin2.challenge),
678
- pubKeyCredParams: begin2.pubKeyCredParams,
679
- timeout: begin2.timeout,
680
- attestation: begin2.attestation,
681
- authenticatorSelection: { ...begin2.authenticatorSelection, residentKey: begin2.authenticatorSelection?.residentKey ?? "preferred", requireResidentKey: begin2.authenticatorSelection?.requireResidentKey ?? false, userVerification: begin2.authenticatorSelection?.userVerification ?? "preferred" },
682
- excludeCredentials: begin2.excludeCredentials?.map((cred) => ({ type: cred.type, id: base64urlToUint8Array(cred.id), transports: cred.transports })) || void 0
683
- };
684
- return { challengeId: begin2.challengeId, options: options2 };
685
- }
686
- res = await authenticatedFetch(`${getTssUrl2()}/api/auth/link/passkey/options`, { method: "GET" });
687
- if (!res.ok) throw new Error("Failed to get passkey linking options");
688
- const begin = await res.json();
689
- const options = {
690
- rp: begin.rp,
691
- user: { id: base64urlToUint8Array(begin.user.id), name: begin.user.name, displayName: begin.user.displayName },
692
- challenge: base64urlToUint8Array(begin.challenge),
693
- pubKeyCredParams: begin.pubKeyCredParams,
694
- timeout: begin.timeout,
695
- attestation: begin.attestation,
696
- authenticatorSelection: { ...begin.authenticatorSelection, residentKey: "preferred", requireResidentKey: false, userVerification: "preferred" },
697
- excludeCredentials: begin.excludeCredentials?.map((cred) => ({ type: cred.type, id: base64urlToUint8Array(cred.id), transports: cred.transports })) || void 0
698
- };
699
- return { challengeId: begin.challengeId, options };
700
- }
701
- async function linkPasskeyWithWebAuthn(optionsOverride) {
702
- if (!("credentials" in navigator) || !("create" in navigator.credentials)) {
703
- throw new Error("WebAuthn not supported in this browser");
704
- }
705
- const userId = jwtTokenManager2.getUserId();
706
- if (!userId) throw new Error("No authenticated user");
707
- let challengeId = null;
708
- let publicKeyOptions = null;
709
- try {
710
- const begin = await beginPasskeyLinking();
711
- challengeId = begin.challengeId;
712
- publicKeyOptions = begin.options;
713
- } catch {
714
- }
715
- if (!publicKeyOptions) {
716
- const challenge = new Uint8Array(32);
717
- crypto.getRandomValues(challenge);
718
- publicKeyOptions = {
719
- rp: { name: window.location.hostname || "EmbarkAI Wallet" },
720
- user: {
721
- id: new TextEncoder().encode(userId),
722
- name: userId,
723
- displayName: userId
724
- },
725
- challenge,
726
- pubKeyCredParams: [{ type: "public-key", alg: -7 }],
727
- attestation: "none",
728
- authenticatorSelection: { residentKey: "preferred", userVerification: "preferred" },
729
- timeout: 6e4
730
- };
731
- }
732
- try {
733
- const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
734
- const friendlyDisplay = `EmbarkAI Wallet (${ts})`;
735
- const friendlyName = `lumia-passport.${ts}`;
736
- const originalUser = publicKeyOptions.user;
737
- publicKeyOptions = {
738
- ...publicKeyOptions,
739
- user: {
740
- ...originalUser,
741
- name: friendlyName,
742
- displayName: friendlyDisplay
743
- }
744
- };
745
- } catch {
746
- }
747
- if (!(window.isSecureContext || window.location.hostname === "localhost")) {
748
- throw new Error("Passkey requires secure context (https or localhost)");
749
- }
750
- try {
751
- const originHost = window.location.hostname;
752
- const rpId = publicKeyOptions.rp?.id;
753
- const suffixMatches = (host, rp) => host === rp || host.endsWith(`.${rp}`);
754
- if (rpId && !suffixMatches(originHost, rpId)) {
755
- console.warn("[PasskeyLink] Adjusting rp.id to origin host for WebAuthn", { rpId, originHost });
756
- publicKeyOptions = { ...publicKeyOptions, rp: { ...publicKeyOptions.rp, id: originHost } };
757
- }
758
- } catch {
759
- }
760
- console.log("[PasskeyLink] Calling navigator.credentials.create", {
761
- rp: publicKeyOptions.rp,
762
- timeout: publicKeyOptions.timeout,
763
- attestation: publicKeyOptions.attestation
764
- });
765
- const credential = await navigator.credentials.create({ publicKey: { ...publicKeyOptions, ...optionsOverride } });
766
- if (!credential) throw new Error("Passkey creation was cancelled");
767
- const attestationPayload = credentialToAttestationPayload(credential);
768
- const cid = challengeId || "local-" + Date.now();
769
- await completePasskeyLinking({ challengeId: cid, credential: attestationPayload });
770
- const rawIdB64 = btoa(String.fromCharCode(...new Uint8Array(credential.rawId)));
771
- return { credentialId: credential.id, rawId: rawIdB64 };
772
- }
773
-
774
- // src/internal/auth/providers/telegram.ts
775
- async function linkTelegram(telegramData) {
776
- const hasValidToken = await ensureValidToken();
777
- if (!hasValidToken) throw new Error("No authentication token available");
778
- const formattedData = {
779
- id: telegramData.id,
780
- first_name: telegramData.first_name,
781
- auth_date: telegramData.auth_date,
782
- hash: telegramData.hash
783
- };
784
- if (telegramData.last_name) formattedData.last_name = telegramData.last_name;
785
- if (telegramData.username) formattedData.username = telegramData.username;
786
- if (telegramData.photo_url) formattedData.photo_url = telegramData.photo_url;
787
- const response = await authenticatedFetch(`${getTssUrl2()}/api/auth/link/telegram`, {
788
- method: "POST",
789
- body: JSON.stringify(formattedData)
790
- });
791
- if (!response.ok) {
792
- const errorData = await response.json().catch(() => ({}));
793
- throw new Error(errorData.message || `Failed to link Telegram: ${response.statusText}`);
794
- }
795
- }
796
- function mountTelegramLoginWidget(container, botUsername, onAuth, options) {
797
- const scriptId = "telegram-login-widget";
798
- if (!document.getElementById(scriptId)) {
799
- const s = document.createElement("script");
800
- s.id = scriptId;
801
- s.src = "https://telegram.org/js/telegram-widget.js?22";
802
- s.async = true;
803
- s.defer = true;
804
- container.parentElement?.appendChild(s);
805
- }
806
- const btn = document.createElement("div");
807
- btn.setAttribute("class", "tg-login-button");
808
- btn.setAttribute("data-telegram-login", botUsername);
809
- btn.setAttribute("data-size", "large");
810
- if (options?.requestAccess) btn.setAttribute("data-request-access", options.requestAccess);
811
- const callbackName = `__lumia_tg_auth_cb_${Math.random().toString(36).slice(2)}`;
812
- window[callbackName] = (user) => onAuth(user);
813
- btn.setAttribute("data-onauth", callbackName);
814
- container.innerHTML = "";
815
- container.appendChild(btn);
816
- }
817
-
818
- // src/internal/auth/providers/wallet.ts
819
- async function walletLogin(walletData) {
820
- const response = await fetch(addProjectIdToUrl(`${getTssUrl2()}/api/auth/wallet/login`), {
821
- method: "POST",
822
- headers: { "Content-Type": "application/json" },
823
- credentials: "include",
824
- body: JSON.stringify(walletData)
825
- });
826
- if (!response.ok) {
827
- const errorData = await response.json().catch(() => ({}));
828
- throw new Error(errorData.message || `Wallet login failed: ${response.statusText}`);
829
- }
830
- return response.json();
831
- }
832
- async function linkWallet(walletData) {
833
- const hasValidToken = await ensureValidToken();
834
- if (!hasValidToken) throw new Error("No authentication token available");
835
- const response = await authenticatedFetch(`${getTssUrl2()}/api/auth/link/wallet`, {
836
- method: "POST",
837
- body: JSON.stringify(walletData)
838
- });
839
- if (!response.ok) {
840
- const errorData = await response.json().catch(() => ({}));
841
- throw new Error(errorData.message || `Failed to link wallet: ${response.statusText}`);
842
- }
843
- }
844
- async function unlinkWallet(address) {
845
- const hasValidToken = await ensureValidToken();
846
- if (!hasValidToken) throw new Error("No authentication token available");
847
- const response = await authenticatedFetch(
848
- `${getTssUrl2()}/api/auth/unlink/wallet?address=${encodeURIComponent(address)}`,
849
- {
850
- method: "DELETE"
851
- }
852
- );
853
- if (!response.ok) {
854
- const errorData = await response.json().catch(() => ({}));
855
- throw new Error(errorData.message || `Failed to unlink wallet: ${response.statusText}`);
856
- }
857
- }
858
- var METADATA_API_URL = "https://dashboard.lumiapassport.com/api/public/project";
859
- var METADATA_CACHE_TTL = 36e5;
860
- var metadataCache = null;
861
- async function fetchProjectName(projectId) {
862
- const now = Date.now();
863
- if (metadataCache && now - metadataCache.timestamp < METADATA_CACHE_TTL) {
864
- return metadataCache.data.name;
865
- }
866
- try {
867
- const response = await fetch(`${METADATA_API_URL}/${projectId}/metadata`);
868
- if (!response.ok) return "EmbarkAI";
869
- const metadata = await response.json();
870
- metadataCache = { data: metadata, timestamp: now };
871
- return metadata.name;
872
- } catch {
873
- return "EmbarkAI";
874
- }
875
- }
876
- function createSignatureMessage(address, projectName, nonce) {
877
- const timestamp = Date.now();
878
- const nonceValue = nonce || Math.random().toString(36).substring(2, 15);
879
- return `${projectName} Wallet Link
880
-
881
- Address: ${address}
882
- Nonce: ${nonceValue}
883
- Timestamp: ${timestamp}
884
-
885
- Sign this message to link your wallet to ${projectName} Wallet`;
886
- }
887
- function createLoginMessage(address, projectName) {
888
- const nonce = crypto.randomUUID();
889
- const timestamp = Date.now();
890
- return [
891
- `${projectName} Wallet Login`,
892
- "",
893
- `Address: ${address}`,
894
- `Nonce: ${nonce}`,
895
- `Timestamp: ${timestamp}`,
896
- "",
897
- `Sign this message to login your wallet to ${projectName}`
898
- ].join("\n");
899
- }
900
-
901
- // src/internal/auth/providers/x.ts
902
- async function linkX() {
903
- const hasValidToken = await ensureValidToken();
904
- if (!hasValidToken) throw new Error("No authentication token available");
905
- throw new Error('Use openSocialAuthPopup("x") to link X account');
906
- }
907
- async function loginWithX() {
908
- throw new Error('Use openSocialAuthPopup("x") to login with X account');
909
- }
910
- async function unlinkX(externalId) {
911
- const hasValidToken = await ensureValidToken();
912
- if (!hasValidToken) throw new Error("No authentication token available");
913
- const url = externalId ? `${getTssUrl2()}/api/auth/unlink/x?externalId=${encodeURIComponent(externalId)}` : `${getTssUrl2()}/api/auth/unlink/x`;
914
- const response = await authenticatedFetch(url, {
915
- method: "DELETE"
916
- });
917
- if (!response.ok) {
918
- const errorData = await response.json().catch(() => ({}));
919
- throw new Error(errorData.message || `Failed to unlink X account: ${response.statusText}`);
920
- }
921
- }
922
-
923
- // src/internal/auth/index.ts
924
- var createInitialAuthState = () => ({ isAuthenticated: false });
925
-
926
- // src/internal/auth/passkey.ts
927
- var activeWebAuthnOperation = null;
928
- var conditionalUIStarting = false;
929
- function setGlobalConditionalUI(active) {
930
- if (typeof window !== "undefined") window.__EMBARK_CONDITIONAL_UI_ACTIVE__ = active;
931
- }
932
- function resetWebAuthnFlags() {
933
- activeWebAuthnOperation = null;
934
- conditionalUIStarting = false;
935
- setGlobalConditionalUI(false);
936
- }
937
- function generatePasskeyUsername() {
938
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
939
- return `lumia-aa.${DAPP_NAME}-${timestamp}`;
940
- }
941
- function createPasskeyHelpers(mpcUserId) {
942
- const getPasskeyKey = (key) => `passkey.${mpcUserId}.${key}`;
943
- return {
944
- getPasskeyKey,
945
- getCredId: () => localStorage.getItem(getPasskeyKey("credId")),
946
- getRawId: () => localStorage.getItem(getPasskeyKey("rawId")),
947
- getOwnerPk: () => localStorage.getItem(getPasskeyKey("ownerPk")),
948
- setCredId: (credId) => localStorage.setItem(getPasskeyKey("credId"), credId),
949
- setRawId: (rawId) => localStorage.setItem(getPasskeyKey("rawId"), rawId),
950
- setOwnerPk: (ownerPk) => localStorage.setItem(getPasskeyKey("ownerPk"), ownerPk),
951
- clear: () => {
952
- localStorage.removeItem(getPasskeyKey("credId"));
953
- localStorage.removeItem(getPasskeyKey("rawId"));
954
- localStorage.removeItem(getPasskeyKey("ownerPk"));
955
- },
956
- hasCredentials: () => !!(localStorage.getItem(getPasskeyKey("credId")) || localStorage.getItem(getPasskeyKey("rawId")))
957
- };
958
- }
959
- function isWebAuthnSupported() {
960
- return "credentials" in navigator && "create" in navigator.credentials && "get" in navigator.credentials;
961
- }
962
- async function hasAvailablePasskeys() {
963
- if (!isWebAuthnSupported()) return false;
964
- try {
965
- const isAvailable = await Promise.race([
966
- PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
967
- new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), 3e3))
968
- ]);
969
- if (!isAvailable) return false;
970
- try {
971
- const credential = await Promise.race([
972
- navigator.credentials.get({ publicKey: { challenge: new Uint8Array(32), timeout: 5e3, userVerification: "preferred" }, mediation: "silent" }),
973
- new Promise((_, reject) => setTimeout(() => reject(new Error("Detection timeout")), 2e3))
974
- ]);
975
- return !!credential;
976
- } catch {
977
- return false;
978
- }
979
- } catch {
980
- return false;
981
- }
982
- }
983
- async function registerPasskey(mpcUserId, onProgress, options) {
984
- if (!isWebAuthnSupported()) throw new Error("WebAuthn not supported in this browser");
985
- const helpers = createPasskeyHelpers(mpcUserId);
986
- onProgress?.("Starting passkey registration...");
987
- const passkeyUsername = generatePasskeyUsername();
988
- onProgress?.("Getting registration challenge...");
989
- const { challengeId, options: credOptions } = await beginPasskeyRegistration(passkeyUsername);
990
- onProgress?.("Creating passkey credential...");
991
- const credential = await navigator.credentials.create({ publicKey: credOptions });
992
- if (!credential) throw new Error("Failed to create passkey credential");
993
- onProgress?.("Verifying passkey with server...");
994
- const loginResponse = await completePasskeyRegistration(challengeId, credential, options);
995
- const rawIdB64 = btoa(String.fromCharCode(...new Uint8Array(credential.rawId)));
996
- const derivedOwnerPk = `0x${"0".repeat(40)}${credential.id.slice(-24)}`;
997
- helpers.setCredId(credential.id);
998
- helpers.setRawId(rawIdB64);
999
- helpers.setOwnerPk(derivedOwnerPk);
1000
- onProgress?.("Passkey registered successfully!");
1001
- return {
1002
- credential: { id: credential.id, rawId: rawIdB64, ownerPublicKey: derivedOwnerPk },
1003
- loginResponse
1004
- };
1005
- }
1006
- async function authenticateWithPasskey(_username, onProgress, options) {
1007
- if (!isWebAuthnSupported()) throw new Error("WebAuthn not supported in this browser");
1008
- onProgress?.("Starting passkey authentication...");
1009
- const { challengeId, options: beginOptions } = await beginPasskeyAuthentication();
1010
- const getOptions = { ...beginOptions };
1011
- if (getOptions.allowCredentials && getOptions.allowCredentials.length === 0) delete getOptions.allowCredentials;
1012
- const assertion = await navigator.credentials.get({ publicKey: getOptions });
1013
- if (!assertion) throw new Error("Passkey authentication failed - no credential returned");
1014
- onProgress?.("Verifying passkey with server...");
1015
- const loginResponse = await completePasskeyAuthentication(challengeId, assertion, options);
1016
- const userHelpers = createPasskeyHelpers(loginResponse.userId);
1017
- const rawIdB64 = btoa(String.fromCharCode(...new Uint8Array(assertion.rawId)));
1018
- const derivedOwnerPk = `0x${"0".repeat(40)}${assertion.id.slice(-24)}`;
1019
- userHelpers.setCredId(assertion.id);
1020
- userHelpers.setRawId(rawIdB64);
1021
- userHelpers.setOwnerPk(derivedOwnerPk);
1022
- onProgress?.("Authentication complete!");
1023
- return {
1024
- credential: { id: assertion.id, rawId: rawIdB64, ownerPublicKey: derivedOwnerPk },
1025
- mpcUserId: loginResponse.userId,
1026
- loginResponse
1027
- };
1028
- }
1029
-
1030
- export {
1031
- addProjectIdToUrl,
1032
- getProjectId,
1033
- beginPasskeyAuthentication,
1034
- completePasskeyAuthentication,
1035
- beginPasskeyRegistration,
1036
- completePasskeyRegistration,
1037
- deriveDemoPrivateKey,
1038
- initTelegramWidget,
1039
- hideTelegramWidget,
1040
- showTelegramWidget,
1041
- resetWebAuthnFlags,
1042
- createPasskeyHelpers,
1043
- isWebAuthnSupported,
1044
- hasAvailablePasskeys,
1045
- registerPasskey,
1046
- authenticateWithPasskey,
1047
- ensureDkgAndGetOwner,
1048
- signDigestWithMpc,
1049
- signTypedDataWithMpc,
1050
- getTssUrl2 as getTssUrl,
1051
- getProviderDisplayInfo,
1052
- formatDate,
1053
- completePasskeyLinking,
1054
- beginPasskeyLinking,
1055
- linkPasskeyWithWebAuthn,
1056
- getLinkedProviders,
1057
- unlinkProvider,
1058
- sendEmailLinkCode,
1059
- verifyEmailLinkCode,
1060
- linkTelegram,
1061
- mountTelegramLoginWidget,
1062
- walletLogin,
1063
- linkWallet,
1064
- unlinkWallet,
1065
- fetchProjectName,
1066
- createSignatureMessage,
1067
- createLoginMessage,
1068
- checkKeyshareStatusWithSync,
1069
- checkKeyshareStatus,
1070
- ensureKeyshare,
1071
- clearLocalKeyshare,
1072
- getKeyshareInfo,
1073
- linkX,
1074
- loginWithX,
1075
- unlinkX,
1076
- createInitialAuthState,
1077
- JwtTokenManager,
1078
- createJwtTokenManager,
1079
- jwtTokenManager2 as jwtTokenManager,
1080
- configureJwtModule,
1081
- logout,
1082
- verifyToken,
1083
- ensureValidToken,
1084
- getValidTokens,
1085
- authenticatedFetch,
1086
- loginWithUserId,
1087
- loginWithEmail,
1088
- loginWithTelegram,
1089
- syncKeyshareStatus
1090
- };
1091
- //# sourceMappingURL=chunk-7G3OIJGJ.js.map