@lumiapassport/ui-kit 1.15.10 → 1.15.11

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.
@@ -15,7 +15,7 @@
15
15
  <meta http-equiv="X-Content-Type-Options" content="nosniff" />
16
16
  <meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin" />
17
17
 
18
- <title>Lumia Passport Secure Wallet - iframe version 1.15.10</title>
18
+ <title>Lumia Passport Secure Wallet - iframe version 1.15.11</title>
19
19
 
20
20
  <!-- Styles will be injected by build process -->
21
21
  <style>
@@ -4403,7 +4403,7 @@ var SigningManager = class extends TokenRefreshApiClient {
4403
4403
  };
4404
4404
 
4405
4405
  // src/iframe/main.ts
4406
- var IFRAME_VERSION = "1.15.10";
4406
+ var IFRAME_VERSION = "1.15.11";
4407
4407
  var IframeWallet = class {
4408
4408
  constructor() {
4409
4409
  console.log("=".repeat(60));
package/dist/index.cjs CHANGED
@@ -111,7 +111,7 @@ function getServiceUrls() {
111
111
  }
112
112
  function getIframeUrl() {
113
113
  const config = DEFAULT_LUMIA_PASSPORT_CONFIG;
114
- const buildIframeUrl = "https://auth.lumiapassport.com";
114
+ const buildIframeUrl = "http://localhost:5173/iframe/index.html";
115
115
  const iframeUrl = buildIframeUrl || config.services.iframeUrl || "https://auth.lumiapassport.com";
116
116
  return iframeUrl;
117
117
  }
@@ -552,6 +552,15 @@ var init_site = __esm({
552
552
  });
553
553
 
554
554
  // src/internal/auth/passkey.ts
555
+ var passkey_exports = {};
556
+ __export(passkey_exports, {
557
+ authenticateWithPasskey: () => authenticateWithPasskey,
558
+ createPasskeyHelpers: () => createPasskeyHelpers,
559
+ hasAvailablePasskeys: () => hasAvailablePasskeys,
560
+ isWebAuthnSupported: () => isWebAuthnSupported,
561
+ registerPasskey: () => registerPasskey,
562
+ resetWebAuthnFlags: () => resetWebAuthnFlags
563
+ });
555
564
  function setGlobalConditionalUI(active) {
556
565
  if (typeof window !== "undefined") window.__LUMIA_CONDITIONAL_UI_ACTIVE__ = active;
557
566
  }
@@ -2244,6 +2253,12 @@ var init_email = __esm({
2244
2253
  });
2245
2254
 
2246
2255
  // src/internal/auth/providers/passkey.ts
2256
+ var passkey_exports2 = {};
2257
+ __export(passkey_exports2, {
2258
+ beginPasskeyLinking: () => beginPasskeyLinking,
2259
+ completePasskeyLinking: () => completePasskeyLinking,
2260
+ linkPasskeyWithWebAuthn: () => linkPasskeyWithWebAuthn
2261
+ });
2247
2262
  async function completePasskeyLinking(payload) {
2248
2263
  const hasValidToken = await (0, import_auth3.ensureValidToken)();
2249
2264
  if (!hasValidToken) throw new Error("No authentication token available");
@@ -2322,8 +2337,8 @@ async function linkPasskeyWithWebAuthn(optionsOverride) {
2322
2337
  }
2323
2338
  try {
2324
2339
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2325
- const friendlyDisplay = `Lumia User (${ts})`;
2326
- const friendlyName = `lumia-link.${ts}`;
2340
+ const friendlyDisplay = `Lumia Passport (${ts})`;
2341
+ const friendlyName = `lumia-passport.${ts}`;
2327
2342
  const originalUser = publicKeyOptions.user;
2328
2343
  publicKeyOptions = {
2329
2344
  ...publicKeyOptions,
@@ -2358,6 +2373,8 @@ async function linkPasskeyWithWebAuthn(optionsOverride) {
2358
2373
  const attestationPayload = credentialToAttestationPayload(credential);
2359
2374
  const cid = challengeId || "local-" + Date.now();
2360
2375
  await completePasskeyLinking({ challengeId: cid, credential: attestationPayload });
2376
+ const rawIdB64 = btoa(String.fromCharCode(...new Uint8Array(credential.rawId)));
2377
+ return { credentialId: credential.id, rawId: rawIdB64 };
2361
2378
  }
2362
2379
  var init_passkey2 = __esm({
2363
2380
  "src/internal/auth/providers/passkey.ts"() {
@@ -5553,7 +5570,7 @@ function Header() {
5553
5570
  // package.json
5554
5571
  var package_default = {
5555
5572
  name: "@lumiapassport/ui-kit",
5556
- version: "1.15.10",
5573
+ version: "1.15.11",
5557
5574
  description: "React UI components and hooks for Lumia Passport authentication and Account Abstraction",
5558
5575
  type: "module",
5559
5576
  main: "./dist/index.cjs",
@@ -8459,6 +8476,7 @@ var useRestoreStore = (0, import_zustand4.create)((set) => ({
8459
8476
  restoreFile: null,
8460
8477
  checkingBackup: false,
8461
8478
  hasServerBackup: false,
8479
+ isCreatingPasskey: false,
8462
8480
  selectedCloudProvider: null,
8463
8481
  error: null,
8464
8482
  success: null,
@@ -8470,6 +8488,7 @@ var useRestoreStore = (0, import_zustand4.create)((set) => ({
8470
8488
  setRestoreFile: (restoreFile) => set({ restoreFile }),
8471
8489
  setCheckingBackup: (checkingBackup) => set({ checkingBackup }),
8472
8490
  setHasServerBackup: (hasServerBackup) => set({ hasServerBackup }),
8491
+ setIsCreatingPasskey: (isCreatingPasskey) => set({ isCreatingPasskey }),
8473
8492
  setSelectedCloudProvider: (providerId) => set({ selectedCloudProvider: providerId }),
8474
8493
  setError: (error) => set({ error }),
8475
8494
  setSuccess: (success) => set({ success })
@@ -8594,7 +8613,7 @@ function useCreateBackup() {
8594
8613
  const address = useLumiaPassportSession((st) => st.address);
8595
8614
  const hasServerVault = useLumiaPassportSession((st) => st.hasServerVault);
8596
8615
  const setIsDialogForced = useLayoutStore((st) => st.setIsDialogForced);
8597
- const { usePasskey, restorePassword, selectedCloudProvider, setSuccess, setError, setMethod } = useRestoreStore();
8616
+ const { usePasskey, restorePassword, selectedCloudProvider, setSuccess, setError, setMethod, setIsCreatingPasskey } = useRestoreStore();
8598
8617
  (0, import_react26.useEffect)(() => {
8599
8618
  if (!hasServerVault) {
8600
8619
  setMethod("server");
@@ -8613,12 +8632,13 @@ function useCreateBackup() {
8613
8632
  if (!usePasskey && !restorePassword) {
8614
8633
  throw new Error("Please provide a password for the backup");
8615
8634
  }
8635
+ const password = !usePasskey ? restorePassword : void 0;
8616
8636
  const navigateToMainMenu = jwt.isNewUser || !hasServerVault;
8617
- console.log("[BACKUP STATUS] is new user:", jwt.isNewUser, !hasServerVault);
8637
+ console.log("[BACKUP STATUS] is new user:", jwt.isNewUser, !hasServerVault, "usePasskey:", usePasskey);
8618
8638
  return {
8619
8639
  response: await iframeManager.createBackup(
8620
8640
  passportUserId,
8621
- { method: "server", password: restorePassword },
8641
+ { method: "server", password },
8622
8642
  jwt.accessToken
8623
8643
  ),
8624
8644
  navigateToMainMenu
@@ -8642,7 +8662,11 @@ function useCreateBackup() {
8642
8662
  setIsDialogForced(false);
8643
8663
  },
8644
8664
  onError: async (error) => {
8645
- setError(error?.message || "Backup creation failed");
8665
+ if (error?.name === "NotAllowedError" || error?.message?.includes("timed out or was not allowed")) {
8666
+ setError("Passkey selection was cancelled. Please try again or create a new passkey.");
8667
+ } else {
8668
+ setError(error?.message || "Backup creation failed");
8669
+ }
8646
8670
  qc.invalidateQueries({ queryKey: [CHECK_BACKUP_QUERY_KEY, address] });
8647
8671
  }
8648
8672
  });
@@ -8680,6 +8704,31 @@ function useCreateBackup() {
8680
8704
  qc.invalidateQueries({ queryKey: [CHECK_BACKUP_QUERY_KEY, address] });
8681
8705
  }
8682
8706
  });
8707
+ const { mutate: createPasskey, isPending: isPasskeyCreating } = (0, import_react_query12.useMutation)({
8708
+ mutationFn: async () => {
8709
+ setIsCreatingPasskey(true);
8710
+ const { linkPasskeyWithWebAuthn: linkPasskeyWithWebAuthn2 } = await Promise.resolve().then(() => (init_passkey2(), passkey_exports2));
8711
+ const { createPasskeyHelpers: createPasskeyHelpers2 } = await Promise.resolve().then(() => (init_passkey(), passkey_exports));
8712
+ const { credentialId, rawId } = await linkPasskeyWithWebAuthn2();
8713
+ const helpers = createPasskeyHelpers2(passportUserId);
8714
+ helpers.setCredId(credentialId);
8715
+ helpers.setRawId(rawId);
8716
+ return { credentialId, rawId };
8717
+ },
8718
+ onSuccess: async () => {
8719
+ setIsCreatingPasskey(false);
8720
+ setError(null);
8721
+ setSuccess("Passkey created successfully. You can now create a backup.");
8722
+ },
8723
+ onError: async (error) => {
8724
+ setIsCreatingPasskey(false);
8725
+ if (error.name === "NotAllowedError") {
8726
+ setError("Passkey creation cancelled. Please try again.");
8727
+ } else {
8728
+ setError(error?.message || "Failed to create passkey");
8729
+ }
8730
+ }
8731
+ });
8683
8732
  const { mutate: createCloudBackup, isPending: isCloudBackupCreating } = (0, import_react_query12.useMutation)({
8684
8733
  mutationFn: async () => {
8685
8734
  const iframeManager = getIframeManager();
@@ -8726,7 +8775,9 @@ function useCreateBackup() {
8726
8775
  isCloudBackupCreating,
8727
8776
  createCloudBackup,
8728
8777
  isLocalBackupCreating,
8729
- createLocalBackup
8778
+ createLocalBackup,
8779
+ isPasskeyCreating,
8780
+ createPasskey
8730
8781
  };
8731
8782
  }
8732
8783
 
@@ -8954,7 +9005,8 @@ function PasswordPasskey(props) {
8954
9005
  isLoading,
8955
9006
  disabled,
8956
9007
  isEncryptionMethod,
8957
- actionHandler
9008
+ actionHandler,
9009
+ onCreatePasskey
8958
9010
  } = props;
8959
9011
  const hasServerVault = useLumiaPassportSession((st) => st.hasServerVault);
8960
9012
  const actionRef = (0, import_react29.useRef)(null);
@@ -8963,6 +9015,7 @@ function PasswordPasskey(props) {
8963
9015
  restorePassword,
8964
9016
  usePasskey,
8965
9017
  error,
9018
+ isCreatingPasskey,
8966
9019
  setRestorePassword,
8967
9020
  setShowPassword,
8968
9021
  setUsePasskey,
@@ -9059,22 +9112,41 @@ function PasswordPasskey(props) {
9059
9112
  children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react20.Loader, { className: "animate-spin h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react20.ChevronRight, { className: "h-4 w-4" })
9060
9113
  }
9061
9114
  )
9062
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
9063
- Button,
9064
- {
9065
- ref: actionRef,
9066
- size: "large",
9067
- variant: "default",
9068
- title: actionCaption,
9069
- onClick: actionHandler,
9070
- disabled: isLoading || disabled || !!error || !usePasskey && !restorePassword,
9071
- className: "w-full",
9072
- children: [
9073
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react20.Loader, { className: "animate-spin h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ActionIcon, { className: "h-4 w-4" }),
9074
- !isLoading && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: actionCaption })
9075
- ]
9076
- }
9077
- ),
9115
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "w-full flex flex-col gap-[var(--l-pass-gap)]", children: [
9116
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
9117
+ Button,
9118
+ {
9119
+ ref: actionRef,
9120
+ size: "large",
9121
+ variant: "default",
9122
+ title: actionCaption,
9123
+ onClick: actionHandler,
9124
+ disabled: isLoading || disabled || !usePasskey && !restorePassword,
9125
+ className: "w-full",
9126
+ children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
9127
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react20.Loader, { className: "animate-spin h-4 w-4" }),
9128
+ isCreatingPasskey && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: "Creating Passkey..." })
9129
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
9130
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ActionIcon, { className: "h-4 w-4" }),
9131
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: actionCaption })
9132
+ ] })
9133
+ }
9134
+ ),
9135
+ mode === "backup" && onCreatePasskey && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
9136
+ Button,
9137
+ {
9138
+ size: "medium",
9139
+ variant: "outline",
9140
+ onClick: onCreatePasskey,
9141
+ disabled: isLoading || disabled,
9142
+ className: "w-full",
9143
+ children: [
9144
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react20.Plus, { className: "h-4 w-4" }),
9145
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: "Create new Passkey" })
9146
+ ]
9147
+ }
9148
+ )
9149
+ ] }),
9078
9150
  !isEncryptionMethod && !!usePasskey && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Highlight, { type: "info", className: "w-full flex flex-col gap-[var(--l-pass-gap)] text-[10px]", children: mode === "backup" && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex gap-[var(--l-pass-gap)]", children: [
9079
9151
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react20.Info, { className: "h-4 w-4 flex-shrink-0" }),
9080
9152
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "text-[var(--l-pass-fg-muted)] block flex-1", children: [
@@ -9228,7 +9300,7 @@ var import_lucide_react23 = require("lucide-react");
9228
9300
  var import_react30 = require("react");
9229
9301
  var import_jsx_runtime42 = require("react/jsx-runtime");
9230
9302
  function Server(props) {
9231
- const { isLoading, mode = "restore", serverHandler } = props;
9303
+ const { isLoading, mode = "restore", serverHandler, createPasskeyHandler } = props;
9232
9304
  const qc = (0, import_react_query14.useQueryClient)();
9233
9305
  const address = useLumiaPassportSession((st) => st.address);
9234
9306
  const setUsePasskey = useRestoreStore((st) => st.setUsePasskey);
@@ -9247,7 +9319,8 @@ function Server(props) {
9247
9319
  isLoading,
9248
9320
  actionCaption: mode === "backup" ? "Create Vault Backup" : "Restore from Vault",
9249
9321
  actionIcon: mode === "backup" ? import_lucide_react23.Upload : import_lucide_react23.Download,
9250
- actionHandler: () => serverHandler()
9322
+ actionHandler: () => serverHandler(),
9323
+ onCreatePasskey: createPasskeyHandler
9251
9324
  }
9252
9325
  ),
9253
9326
  !!serverRecoveryStatus?.created?.at && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(Highlight, { type: "success", className: "flex gap-[var(--l-pass-gap)]", children: [
@@ -9709,7 +9782,9 @@ function KeyshareBackupMenu() {
9709
9782
  isCloudBackupCreating,
9710
9783
  createCloudBackup,
9711
9784
  isLocalBackupCreating,
9712
- createLocalBackup
9785
+ createLocalBackup,
9786
+ isPasskeyCreating,
9787
+ createPasskey
9713
9788
  } = useCreateBackup();
9714
9789
  const BackupComponent = !!currentBackupMethod ? COMPONENTS[currentBackupMethod] : null;
9715
9790
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
@@ -9771,10 +9846,11 @@ function KeyshareBackupMenu() {
9771
9846
  BackupComponent,
9772
9847
  {
9773
9848
  mode: "backup",
9774
- isLoading: isPasswordBackupCreating || isCloudBackupCreating || isLocalBackupCreating,
9849
+ isLoading: isPasswordBackupCreating || isCloudBackupCreating || isLocalBackupCreating || isPasskeyCreating,
9775
9850
  fileHandler: createLocalBackup,
9776
9851
  serverHandler: createPasswordBackup,
9777
- cloudHandler: createCloudBackup
9852
+ cloudHandler: createCloudBackup,
9853
+ createPasskeyHandler: createPasskey
9778
9854
  }
9779
9855
  ) }),
9780
9856
  !isRecoveryLoading && !currentBackupMethod && !hasRecoveryData && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(Highlight, { type: "warning", className: "flex gap-[var(--l-pass-gap)]", children: [