@embarkai/ui-kit 0.2.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -618,6 +618,7 @@ declare class IframeManager {
618
618
  private isReady;
619
619
  private readyPromise;
620
620
  private readyResolve;
621
+ private initPromise;
621
622
  private onWalletReadyCallback?;
622
623
  private pendingRequests;
623
624
  private usedNonces;
@@ -639,6 +640,7 @@ declare class IframeManager {
639
640
  * Initialize iframe and wait for it to be ready
640
641
  */
641
642
  initialize(): Promise<void>;
643
+ private doInitialize;
642
644
  /**
643
645
  * Set the onWalletReady callback
644
646
  */
package/dist/index.d.ts CHANGED
@@ -618,6 +618,7 @@ declare class IframeManager {
618
618
  private isReady;
619
619
  private readyPromise;
620
620
  private readyResolve;
621
+ private initPromise;
621
622
  private onWalletReadyCallback?;
622
623
  private pendingRequests;
623
624
  private usedNonces;
@@ -639,6 +640,7 @@ declare class IframeManager {
639
640
  * Initialize iframe and wait for it to be ready
640
641
  */
641
642
  initialize(): Promise<void>;
643
+ private doInitialize;
642
644
  /**
643
645
  * Set the onWalletReady callback
644
646
  */
package/dist/index.js CHANGED
@@ -866,6 +866,7 @@ var init_useLayoutDataStore = __esm({
866
866
  transitionPageHeight: DEFAULT_MAIN_MENU_HEIGHT,
867
867
  settingsNotifications: [],
868
868
  isWalletLinking: false,
869
+ pendingWalletLogin: null,
869
870
  setPageParams: (pageOptions) => set({ pageParams: pageOptions }),
870
871
  setPage: (page) => set((prev) => ({
871
872
  page,
@@ -887,7 +888,8 @@ var init_useLayoutDataStore = __esm({
887
888
  const filtered = prev.settingsNotifications.filter((n) => n.id !== notification.id);
888
889
  return { settingsNotifications: filtered };
889
890
  }),
890
- setIsWalletLinking: (isWalletLinking) => set({ isWalletLinking })
891
+ setIsWalletLinking: (isWalletLinking) => set({ isWalletLinking }),
892
+ setPendingWalletLogin: (pendingWalletLogin) => set({ pendingWalletLogin })
891
893
  }));
892
894
  }
893
895
  });
@@ -2564,6 +2566,8 @@ function useAutoConnect() {
2564
2566
  }
2565
2567
  } catch (e) {
2566
2568
  if (e?.code === "KEYSHARE_RECOVERY_NEEDED") {
2569
+ setSession(null);
2570
+ setAddress(null);
2567
2571
  setRecoveryUserId(userId);
2568
2572
  setError(null);
2569
2573
  setStatus("recovery_needed");
@@ -5057,6 +5061,8 @@ function useAuthMenuHandlers() {
5057
5061
  console.warn("[AuthMenu] Keyshare recovery needed for user:", userId);
5058
5062
  pendingLoginResponseRef.current = null;
5059
5063
  setError(null);
5064
+ setSession(null);
5065
+ setAddress(null);
5060
5066
  setRecoveryUserId(userId);
5061
5067
  setStatus("recovery_needed");
5062
5068
  setTimeout(() => {
@@ -5462,6 +5468,7 @@ var AuthMenu;
5462
5468
  var init_AuthMenu = __esm({
5463
5469
  "src/internal/components/AuthMenu/AuthMenu.tsx"() {
5464
5470
  init_SessionContext();
5471
+ init_auth();
5465
5472
  init_constants();
5466
5473
  init_useLayoutDataStore();
5467
5474
  init_useLayoutStore();
@@ -5478,8 +5485,20 @@ var init_AuthMenu = __esm({
5478
5485
  const isIframeReady = useSession((st) => st.isIframeReady);
5479
5486
  const maxScrollHeight = useLayoutStore((st) => st.maxScrollHeight);
5480
5487
  const setTransitionPageHeight = useLayoutDataStore((st) => st.setTransitionPageHeight);
5488
+ const pendingWalletLogin = useLayoutDataStore((st) => st.pendingWalletLogin);
5489
+ const setPendingWalletLogin = useLayoutDataStore((st) => st.setPendingWalletLogin);
5481
5490
  const { step, alert: alert2, setStep, setPasskeyStatus, setEmail, setAlert } = useAuthStore();
5482
5491
  const { pendingLoginResponseRef, onAuthSuccess, goBackToSignIn } = useAuthMenuHandlers();
5492
+ useEffect10(() => {
5493
+ if (!pendingWalletLogin) return;
5494
+ const loginResponse = pendingWalletLogin;
5495
+ setPendingWalletLogin(null);
5496
+ console.log("[AuthMenu] Processing wallet login response:", loginResponse);
5497
+ jwtTokenManager2.clearTokens().then(() => {
5498
+ pendingLoginResponseRef.current = loginResponse;
5499
+ onAuthSuccess();
5500
+ });
5501
+ }, [pendingWalletLogin]);
5483
5502
  useEffect10(() => {
5484
5503
  setTransitionPageHeight(DEFAULT_AUTH_MENU_HEIGHT);
5485
5504
  return () => {
@@ -7967,7 +7986,8 @@ function useCreateBackup() {
7967
7986
  setIsDialogForced(true);
7968
7987
  }
7969
7988
  }, [hasServerVault, setIsDialogForced, setMethod]);
7970
- const passportUserId = session?.mpcUserId || "";
7989
+ const recoveryUserId = useSession((st) => st.recoveryUserId);
7990
+ const passportUserId = session?.mpcUserId || recoveryUserId || "";
7971
7991
  const onBackupSuccess = () => console.log("[ConnectWalletButton] Backup created successfully");
7972
7992
  const { mutate: createPasswordBackup, isPending: isPasswordBackupCreating } = useMutation7({
7973
7993
  mutationFn: async () => {
@@ -15479,7 +15499,7 @@ var init_package = __esm({
15479
15499
  "package.json"() {
15480
15500
  package_default = {
15481
15501
  name: "@embarkai/ui-kit",
15482
- version: "0.2.7",
15502
+ version: "0.3.0",
15483
15503
  description: "React UI components and hooks for EmbarkAI authentication and Account Abstraction",
15484
15504
  type: "module",
15485
15505
  main: "./dist/index.cjs",
@@ -15517,51 +15537,52 @@ var init_package = __esm({
15517
15537
  },
15518
15538
  peerDependencies: {
15519
15539
  "@tanstack/react-query": ">=5.0.0",
15540
+ i18next: "^25.8.0",
15520
15541
  react: ">=18",
15521
15542
  "react-dom": ">=18",
15522
- "tailwind-merge": ">=2.2.0",
15523
- i18next: "^25.8.0",
15524
- "react-i18next": "^16.5.3"
15543
+ "react-i18next": "^16.5.3",
15544
+ "tailwind-merge": ">=2.2.0"
15525
15545
  },
15526
15546
  dependencies: {
15527
- "@radix-ui/react-slot": ">=1.2.4",
15547
+ "@embarkai/core": "workspace:*",
15528
15548
  "@radix-ui/react-checkbox": ">=1.3.3",
15529
- "@radix-ui/react-select": ">=2.2.6",
15530
15549
  "@radix-ui/react-dialog": ">=1.1.15",
15531
- "@embarkai/core": "workspace:*",
15550
+ "@radix-ui/react-select": ">=2.2.6",
15551
+ "@radix-ui/react-slot": ">=1.2.4",
15532
15552
  "@rainbow-me/rainbowkit": "^2.2.10",
15533
15553
  "@sentry/browser": "^10.22.0",
15534
15554
  "class-variance-authority": "^0.7.0",
15535
- "lodash-es": "^4.17.21",
15536
15555
  clsx: "^2.1.1",
15556
+ dayjs: "^1.11.9",
15537
15557
  "dkls23-wasm": "^0.1.0",
15558
+ "framer-motion": "^12.23.24",
15559
+ "lodash-es": "^4.17.21",
15538
15560
  "lucide-react": "^0.454.0",
15539
15561
  qrcode: "^1.5.0",
15540
- zustand: "^5.0.8",
15541
15562
  viem: "^2.38.0",
15542
15563
  wagmi: "^2.17.5",
15543
- dayjs: "^1.11.9",
15544
- "framer-motion": "^12.23.24"
15564
+ zustand: "^5.0.8"
15545
15565
  },
15546
15566
  devDependencies: {
15547
15567
  "@tailwindcss/typography": "^0.5.16",
15548
15568
  "@tanstack/react-query": "^5.90.2",
15569
+ "@types/lodash-es": "^4.17.12",
15549
15570
  "@types/qrcode": "^1.5.0",
15550
15571
  "@types/react": "^18.3.3",
15551
15572
  "@types/react-dom": "^18.3.0",
15552
15573
  autoprefixer: "^10.4.20",
15553
15574
  dotenv: "^17.2.3",
15575
+ i18next: "^25.8.0",
15554
15576
  postcss: "^8.4.47",
15555
15577
  react: "^18.3.1",
15556
15578
  "react-dom": "^18.3.1",
15579
+ "react-i18next": "^16.5.3",
15557
15580
  "tailwind-merge": "^2.2.0",
15558
- "@types/lodash-es": "^4.17.12",
15559
15581
  tailwindcss: "^3.4.10",
15560
15582
  tsup: "^8.5.0",
15561
15583
  typescript: "^5.4.5",
15562
15584
  vite: "^5.0.0",
15563
- i18next: "^25.8.0",
15564
- "react-i18next": "^16.5.3"
15585
+ vitest: "^4.0.18"
15565
15586
  },
15566
15587
  repository: {
15567
15588
  type: "git",
@@ -16160,6 +16181,19 @@ var init_TssManager = __esm({
16160
16181
  });
16161
16182
 
16162
16183
  // src/internal/auth/providers/wallet.ts
16184
+ async function walletLogin(walletData) {
16185
+ const response = await fetch(addProjectIdToUrl(`${getTssUrl3()}/api/auth/wallet/login`), {
16186
+ method: "POST",
16187
+ headers: { "Content-Type": "application/json" },
16188
+ credentials: "include",
16189
+ body: JSON.stringify(walletData)
16190
+ });
16191
+ if (!response.ok) {
16192
+ const errorData = await response.json().catch(() => ({}));
16193
+ throw new Error(errorData.message || `Wallet login failed: ${response.statusText}`);
16194
+ }
16195
+ return response.json();
16196
+ }
16163
16197
  async function linkWallet(walletData) {
16164
16198
  const hasValidToken = await ensureValidToken();
16165
16199
  if (!hasValidToken) throw new Error("No authentication token available");
@@ -16212,9 +16246,23 @@ Timestamp: ${timestamp}
16212
16246
 
16213
16247
  Sign this message to link your wallet to ${projectName} Wallet`;
16214
16248
  }
16249
+ function createLoginMessage(address, projectName) {
16250
+ const nonce = crypto.randomUUID();
16251
+ const timestamp = Date.now();
16252
+ return [
16253
+ `${projectName} Wallet Login`,
16254
+ "",
16255
+ `Address: ${address}`,
16256
+ `Nonce: ${nonce}`,
16257
+ `Timestamp: ${timestamp}`,
16258
+ "",
16259
+ `Sign this message to login your wallet to ${projectName}`
16260
+ ].join("\n");
16261
+ }
16215
16262
  var METADATA_API_URL, METADATA_CACHE_TTL, metadataCache;
16216
16263
  var init_wallet = __esm({
16217
16264
  "src/internal/auth/providers/wallet.ts"() {
16265
+ init_projectId();
16218
16266
  init_auth();
16219
16267
  init_types();
16220
16268
  METADATA_API_URL = "https://dashboard.lumiapassport.com/api/public/project";
@@ -16278,6 +16326,7 @@ function WalletConnectHandler() {
16278
16326
  const walletMode = providerConfig?.wallet?.mode || "linked";
16279
16327
  const projectId = providerConfig?.projectId;
16280
16328
  const setExternalWallet = useExternalWalletStore((st) => st.setExternalWallet);
16329
+ const setPendingWalletLogin = useLayoutDataStore((st) => st.setPendingWalletLogin);
16281
16330
  const onLinkingComplete = useCallback23(
16282
16331
  async (success) => {
16283
16332
  setIsWalletLinking(false);
@@ -16366,12 +16415,14 @@ function WalletConnectHandler() {
16366
16415
  if (isWalletLinking) {
16367
16416
  const timeout = setTimeout(() => {
16368
16417
  console.warn("[WalletConnectHandler] Wallet linking timed out, resetting state");
16418
+ disconnect();
16369
16419
  setIsWalletLinking(false);
16370
16420
  setHasStartedLinking(false);
16371
16421
  }, 12e4);
16372
16422
  return () => clearTimeout(timeout);
16373
16423
  }
16374
- }, [isWalletLinking, setIsWalletLinking]);
16424
+ }, [isWalletLinking, setIsWalletLinking, disconnect]);
16425
+ const isAuthFlow = !passportWalletAddress;
16375
16426
  const { mutate: handleWalletSign, isPending: isWalletSigning } = useMutation16({
16376
16427
  mutationFn: async (payload) => {
16377
16428
  const { chainId, signingWalletAddress } = payload;
@@ -16390,24 +16441,45 @@ function WalletConnectHandler() {
16390
16441
  }
16391
16442
  setLinkIsLoading(true);
16392
16443
  const projectName = projectId ? await fetchProjectName(projectId) : "EmbarkAI";
16393
- const message = createSignatureMessage(signingWalletAddress, projectName);
16394
- const signature = await signMessageAsync({ message, account: signingWalletAddress });
16444
+ const message = isAuthFlow ? createLoginMessage(signingWalletAddress, projectName) : createSignatureMessage(signingWalletAddress, projectName);
16445
+ const signature = await Promise.race([
16446
+ signMessageAsync({ message, account: signingWalletAddress }),
16447
+ new Promise(
16448
+ (_, reject) => setTimeout(() => reject(new Error("Signature request timed out. Please try again.")), 6e4)
16449
+ )
16450
+ ]);
16395
16451
  if (!signature) {
16396
16452
  throw new Error("Failed to get signature");
16397
16453
  }
16398
16454
  const walletName = connector?.name || "Unknown Wallet";
16399
16455
  const walletType = connector?.id || "unknown";
16400
- return await linkWallet({
16401
- // chainId: chain.id,
16456
+ const walletData = {
16402
16457
  chainId,
16403
16458
  address: signingWalletAddress,
16404
16459
  signature,
16405
16460
  message,
16406
16461
  walletName,
16407
16462
  walletType
16408
- });
16463
+ };
16464
+ if (isAuthFlow) {
16465
+ const loginResponse = await walletLogin(walletData);
16466
+ return loginResponse;
16467
+ } else {
16468
+ await linkWallet(walletData);
16469
+ return void 0;
16470
+ }
16409
16471
  },
16410
- onSuccess: () => {
16472
+ onSuccess: (data) => {
16473
+ if (isAuthFlow && data) {
16474
+ console.log("[WalletConnectHandler] Wallet login successful, passing to AuthMenu");
16475
+ disconnect();
16476
+ setPendingWalletLogin(data);
16477
+ setIsWalletLinking(false);
16478
+ setHasStartedLinking(false);
16479
+ setLinkIsLoading(false);
16480
+ setPage("auth" /* AUTH */);
16481
+ return;
16482
+ }
16411
16483
  const shouldKeepConnected = walletMode === "direct" || walletMode === "both";
16412
16484
  if (shouldKeepConnected && walletAddress && chain?.id && connector) {
16413
16485
  setExternalWallet({
@@ -16428,7 +16500,7 @@ function WalletConnectHandler() {
16428
16500
  onLinkingComplete(false);
16429
16501
  setHasStartedLinking(false);
16430
16502
  setLinkIsLoading(false);
16431
- const errorMsg = err?.message || "Failed to link wallet";
16503
+ const errorMsg = err?.message || (isAuthFlow ? "Wallet login failed" : "Failed to link wallet");
16432
16504
  if (errorMsg.includes("User rejected") || errorMsg.includes("User denied")) {
16433
16505
  if (passportWalletAddress) {
16434
16506
  setManageWalletLinkError("Signature request was cancelled");
@@ -17651,6 +17723,7 @@ __export(auth_exports, {
17651
17723
  configureJwtModule: () => configureJwtModule,
17652
17724
  createInitialAuthState: () => createInitialAuthState,
17653
17725
  createJwtTokenManager: () => createJwtTokenManager,
17726
+ createLoginMessage: () => createLoginMessage,
17654
17727
  createPasskeyHelpers: () => createPasskeyHelpers,
17655
17728
  createSignatureMessage: () => createSignatureMessage,
17656
17729
  deriveDemoPrivateKey: () => deriveDemoPrivateKey,
@@ -17687,7 +17760,8 @@ __export(auth_exports, {
17687
17760
  unlinkWallet: () => unlinkWallet,
17688
17761
  unlinkX: () => unlinkX,
17689
17762
  verifyEmailLinkCode: () => verifyEmailLinkCode,
17690
- verifyToken: () => verifyToken
17763
+ verifyToken: () => verifyToken,
17764
+ walletLogin: () => walletLogin
17691
17765
  });
17692
17766
  import {
17693
17767
  JwtTokenManager,
@@ -17754,6 +17828,7 @@ var init_iframe_manager = __esm({
17754
17828
  this.iframe = null;
17755
17829
  this.channelToken = null;
17756
17830
  this.isReady = false;
17831
+ this.initPromise = null;
17757
17832
  // Message handling
17758
17833
  this.pendingRequests = /* @__PURE__ */ new Map();
17759
17834
  this.usedNonces = /* @__PURE__ */ new Set();
@@ -17791,9 +17866,13 @@ var init_iframe_manager = __esm({
17791
17866
  * Initialize iframe and wait for it to be ready
17792
17867
  */
17793
17868
  async initialize() {
17794
- if (this.iframe) {
17795
- return this.readyPromise;
17869
+ if (this.initPromise) {
17870
+ return this.initPromise;
17796
17871
  }
17872
+ this.initPromise = this.doInitialize();
17873
+ return this.initPromise;
17874
+ }
17875
+ async doInitialize() {
17797
17876
  this.iframe = document.createElement("iframe");
17798
17877
  let iframeUrl = this.iframeUrl;
17799
17878
  this.iframe.src = iframeUrl;
@@ -18063,9 +18142,15 @@ var init_iframe_manager = __esm({
18063
18142
  * Send secure message to iframe
18064
18143
  */
18065
18144
  async sendMessage(type, data) {
18145
+ if (this.initPromise && type !== "SDK_AUTH") {
18146
+ await this.initPromise;
18147
+ }
18066
18148
  if (!this.iframe || !this.iframe.contentWindow) {
18067
18149
  throw new Error("Iframe not initialized");
18068
18150
  }
18151
+ if (!this.channelToken && type !== "SDK_AUTH") {
18152
+ throw createAccountAbstractionError({ message: "SDK channel not established. Initialize iframe first." });
18153
+ }
18069
18154
  const messageId = this.generateMessageId();
18070
18155
  const nonce = this.generateNonce();
18071
18156
  const timestamp = Date.now();
@@ -18929,6 +19014,10 @@ var init_iframe_manager = __esm({
18929
19014
  this.iframe = null;
18930
19015
  this.isReady = false;
18931
19016
  this.channelToken = null;
19017
+ this.initPromise = null;
19018
+ this.readyPromise = new Promise((resolve) => {
19019
+ this.readyResolve = resolve;
19020
+ });
18932
19021
  this.log("[IframeManager] \u2705 Destroyed");
18933
19022
  }
18934
19023
  /**
@@ -18949,7 +19038,6 @@ var init_iframe_manager = __esm({
18949
19038
  });
18950
19039
 
18951
19040
  // src/config/rainbowkit.ts
18952
- import { lumiaMainnetChain as lumiaMainnetChain2, lumiaTestnetChain as lumiaTestnetChain2 } from "@embarkai/core/read";
18953
19041
  import { getDefaultConfig } from "@rainbow-me/rainbowkit";
18954
19042
  import {
18955
19043
  coinbaseWallet,
@@ -18979,7 +19067,7 @@ var init_rainbowkit = __esm({
18979
19067
  const config = {
18980
19068
  appName: "EmbarkAI Wallet",
18981
19069
  projectId: getProjectId(opts.projectId),
18982
- chains: [lumiaMainnetChain2, lumiaTestnetChain2, mainnet, polygon, bsc, arbitrum, optimism, avalanche, base, zora],
19070
+ chains: [mainnet, polygon, bsc, arbitrum, optimism, avalanche, base, zora],
18983
19071
  ssr: false
18984
19072
  };
18985
19073
  if (opts.allowedWallets && opts.allowedWallets.length > 0) {
@@ -19239,7 +19327,7 @@ var init_utils8 = __esm({
19239
19327
  });
19240
19328
 
19241
19329
  // src/config/wagmi.ts
19242
- import { lumiaMainnetChain as lumiaMainnetChain3, lumiaTestnetChain as lumiaTestnetChain3 } from "@embarkai/core/read";
19330
+ import { lumiaMainnetChain as lumiaMainnetChain2, lumiaTestnetChain as lumiaTestnetChain2 } from "@embarkai/core/read";
19243
19331
  import { fallback } from "viem";
19244
19332
  import { createConfig, http as http4 } from "wagmi";
19245
19333
  function buildTransport(urls) {
@@ -19264,10 +19352,10 @@ var wagmiConfig;
19264
19352
  var init_wagmi = __esm({
19265
19353
  "src/config/wagmi.ts"() {
19266
19354
  wagmiConfig = createConfig({
19267
- chains: [lumiaMainnetChain3, lumiaTestnetChain3],
19355
+ chains: [lumiaMainnetChain2, lumiaTestnetChain2],
19268
19356
  transports: {
19269
- [lumiaTestnetChain3.id]: buildTransport(lumiaTestnetChain3.rpcUrls.default.http),
19270
- [lumiaMainnetChain3.id]: buildTransport(lumiaMainnetChain3.rpcUrls.default.http)
19357
+ [lumiaTestnetChain2.id]: buildTransport(lumiaTestnetChain2.rpcUrls.default.http),
19358
+ [lumiaMainnetChain2.id]: buildTransport(lumiaMainnetChain2.rpcUrls.default.http)
19271
19359
  }
19272
19360
  });
19273
19361
  }