decane-connect-kit 2.2.5 → 2.2.7

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.cjs CHANGED
@@ -2619,9 +2619,6 @@ function validatePin(pin) {
2619
2619
  // src/social/crypto/passkey.ts
2620
2620
  var import_browser2 = require("@simplewebauthn/browser");
2621
2621
  init_errors();
2622
- function b64u(u) {
2623
- return btoa(String.fromCharCode(...u)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
2624
- }
2625
2622
  function fromB64u(s) {
2626
2623
  return Uint8Array.from(atob(s.replace(/-/g, "+").replace(/_/g, "/")), (c) => c.charCodeAt(0));
2627
2624
  }
@@ -2656,7 +2653,7 @@ async function authenticateWithPasskey(opts) {
2656
2653
  ...opts.optionsJSON,
2657
2654
  extensions: {
2658
2655
  ...opts.optionsJSON.extensions,
2659
- prf: { eval: { first: b64u(opts.prfSalt) } }
2656
+ prf: { eval: { first: buf3(opts.prfSalt) } }
2660
2657
  }
2661
2658
  };
2662
2659
  let response;
@@ -3039,7 +3036,7 @@ function formatBalanceDisplay(value) {
3039
3036
  // src/social/client.ts
3040
3037
  var DEFAULT_API_BASE = "https://backend.decane.app";
3041
3038
  var DEFAULT_TEE_URL = "https://4405742df08d19abc549a05ade2a7154d98bd87f-8443.dstack-pha-prod9.phala.network";
3042
- var DEFAULT_SESSION_MINUTES = 30;
3039
+ var DEFAULT_SESSION_MINUTES = 120;
3043
3040
  function makePersistKey(apiKey) {
3044
3041
  return `decane:social:${apiKey.slice(0, 20)}`;
3045
3042
  }
@@ -3339,6 +3336,7 @@ async function createDecaneConnect(config) {
3339
3336
  }
3340
3337
  async function passkeyLogin(stored) {
3341
3338
  const userId = stored.userId;
3339
+ events.emit("wallet-unlocking");
3342
3340
  const options = await api.getWebAuthnLoginOptions(userId, rpId);
3343
3341
  if (!options) {
3344
3342
  throw new NewDeviceError();
@@ -3372,8 +3370,10 @@ async function createDecaneConnect(config) {
3372
3370
  async function handleAuthResult(result) {
3373
3371
  let addresses;
3374
3372
  if (!result.hasShare) {
3373
+ events.emit("wallet-creating");
3375
3374
  addresses = await firstTimeSetup(result.userId, result.jwt);
3376
3375
  } else {
3376
+ events.emit("wallet-unlocking");
3377
3377
  addresses = await returningUserUnlock(result.userId, result.jwt);
3378
3378
  }
3379
3379
  auth = { jwt: result.jwt, userId: result.userId, addresses };
@@ -3712,8 +3712,8 @@ async function createDecaneConnect(config) {
3712
3712
  function bufferToB64u(buf6) {
3713
3713
  return btoa(String.fromCharCode(...buf6)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
3714
3714
  }
3715
- function b64uToBuffer(b64u2) {
3716
- const b644 = b64u2.replace(/-/g, "+").replace(/_/g, "/");
3715
+ function b64uToBuffer(b64u) {
3716
+ const b644 = b64u.replace(/-/g, "+").replace(/_/g, "/");
3717
3717
  return Uint8Array.from(atob(b644), (c) => c.charCodeAt(0));
3718
3718
  }
3719
3719
  function toHex(bytes) {
@@ -5439,16 +5439,98 @@ function SocialWalletModal({
5439
5439
  }
5440
5440
 
5441
5441
  // src/ui/context.tsx
5442
+ var import_react5 = __toESM(require("react"), 1);
5443
+
5444
+ // src/ui/StatusOverlay.tsx
5442
5445
  var import_react4 = __toESM(require("react"), 1);
5446
+ var import_react_dom3 = require("react-dom");
5447
+ function injectTokens3(theme) {
5448
+ if (typeof document === "undefined") return;
5449
+ const resolved = theme === "auto" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
5450
+ let el = document.getElementById("decane-tokens");
5451
+ if (!el) {
5452
+ el = document.createElement("style");
5453
+ el.id = "decane-tokens";
5454
+ document.head.appendChild(el);
5455
+ }
5456
+ el.textContent = `:root { ${CSS_VARS[resolved]} }`;
5457
+ }
5458
+ function WalletStatusOverlay({
5459
+ phase,
5460
+ theme = "auto"
5461
+ }) {
5462
+ (0, import_react4.useEffect)(() => {
5463
+ if (!phase) return;
5464
+ injectTokens3(theme);
5465
+ if (theme !== "auto") return;
5466
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
5467
+ const h = () => injectTokens3("auto");
5468
+ mq.addEventListener("change", h);
5469
+ return () => mq.removeEventListener("change", h);
5470
+ }, [phase, theme]);
5471
+ if (!phase || typeof document === "undefined") return null;
5472
+ const title = phase === "creating" ? "Creating your wallet" : "Unlocking your wallet";
5473
+ const sub = phase === "creating" ? "Generating your keys and splitting them across three shares so no single party ever holds your wallet. This takes a few seconds \u2014 please keep this tab open." : "Reopening your secure session\u2026";
5474
+ return (0, import_react_dom3.createPortal)(
5475
+ /* @__PURE__ */ import_react4.default.createElement(
5476
+ "div",
5477
+ {
5478
+ role: "dialog",
5479
+ "aria-modal": "true",
5480
+ "aria-label": title,
5481
+ style: {
5482
+ position: "fixed",
5483
+ inset: 0,
5484
+ zIndex: 1e4,
5485
+ display: "flex",
5486
+ alignItems: "center",
5487
+ justifyContent: "center",
5488
+ padding: 16,
5489
+ fontFamily: "var(--dc-font-sans, system-ui, sans-serif)"
5490
+ }
5491
+ },
5492
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: {
5493
+ position: "absolute",
5494
+ inset: 0,
5495
+ background: "var(--dc-bg-overlay, rgba(0,0,0,0.75))",
5496
+ backdropFilter: "blur(8px)",
5497
+ WebkitBackdropFilter: "blur(8px)"
5498
+ } }),
5499
+ /* @__PURE__ */ import_react4.default.createElement("div", { style: {
5500
+ position: "relative",
5501
+ background: "var(--dc-bg, #0D0D0B)",
5502
+ border: "1px solid var(--dc-border, #3D3C39)",
5503
+ borderRadius: 20,
5504
+ width: "100%",
5505
+ maxWidth: 340,
5506
+ padding: "30px 26px",
5507
+ textAlign: "center",
5508
+ boxShadow: "0 24px 64px rgba(0,0,0,0.6)"
5509
+ } }, /* @__PURE__ */ import_react4.default.createElement("div", { style: { display: "flex", justifyContent: "center", marginBottom: 18 } }, /* @__PURE__ */ import_react4.default.createElement("div", { style: { position: "relative", width: 60, height: 60, display: "flex", alignItems: "center", justifyContent: "center" } }, /* @__PURE__ */ import_react4.default.createElement("span", { style: {
5510
+ position: "absolute",
5511
+ inset: 0,
5512
+ borderRadius: "50%",
5513
+ border: "2px solid var(--dc-border, #3D3C39)",
5514
+ borderTopColor: "var(--dc-accent, #F5C800)",
5515
+ animation: "dc-status-spin 0.8s linear infinite"
5516
+ } }), /* @__PURE__ */ import_react4.default.createElement(DecaneMark, { size: 32 }))), /* @__PURE__ */ import_react4.default.createElement("div", { style: { fontSize: 16, fontWeight: 800, color: "var(--dc-text, #F9F9F7)", letterSpacing: "-0.02em", marginBottom: 7 } }, title), /* @__PURE__ */ import_react4.default.createElement("div", { style: { fontSize: 12, color: "var(--dc-text-muted, #8A8884)", lineHeight: 1.55 } }, sub), /* @__PURE__ */ import_react4.default.createElement("div", { style: { marginTop: 20, paddingTop: 14, borderTop: "1px solid var(--dc-border, #3D3C39)", display: "flex", alignItems: "center", justifyContent: "center", gap: 6 } }, /* @__PURE__ */ import_react4.default.createElement(DecaneMark, { size: 13, muted: true }), /* @__PURE__ */ import_react4.default.createElement(DecaneWordmark, { size: 11, muted: true }))),
5517
+ /* @__PURE__ */ import_react4.default.createElement("style", null, `@keyframes dc-status-spin { to { transform: rotate(360deg); } }`)
5518
+ ),
5519
+ document.body
5520
+ );
5521
+ }
5522
+
5523
+ // src/ui/context.tsx
5443
5524
  var DEFAULT_SOCIAL = {
5444
5525
  addresses: null,
5445
5526
  isNewUser: false,
5446
5527
  isUnlocked: false,
5447
5528
  sessionExpiresAt: null,
5448
5529
  needsReconnect: false,
5449
- canUsePasskey: false
5530
+ canUsePasskey: false,
5531
+ phase: null
5450
5532
  };
5451
- var DecaneContext = (0, import_react4.createContext)(null);
5533
+ var DecaneContext = (0, import_react5.createContext)(null);
5452
5534
  function hasSocial(mode) {
5453
5535
  return mode === "all" || mode === "social" || mode === "evm+social" || mode === "solana+social" || mode === "tron+social" || mode === "evm+tron+social";
5454
5536
  }
@@ -5471,19 +5553,19 @@ function DecaneKit({ config, children }) {
5471
5553
  `DecaneKit: config.social.apiKey is required for social sign-in (mode "${mode}"). Create an API key for this project in the dashboard.`
5472
5554
  );
5473
5555
  }
5474
- const walletRef = (0, import_react4.useRef)(null);
5556
+ const walletRef = (0, import_react5.useRef)(null);
5475
5557
  if (!walletRef.current) walletRef.current = createDecane(config);
5476
- const socialRef = (0, import_react4.useRef)(null);
5477
- const socialInitialized = (0, import_react4.useRef)(false);
5478
- const [selectorOpen, setSelectorOpen] = (0, import_react4.useState)(false);
5479
- const [socialModalOpen, setSocialModalOpen] = (0, import_react4.useState)(false);
5480
- const [theme, setTheme] = (0, import_react4.useState)(config?.theme ?? "auto");
5481
- const [socialAuth, setSocialAuth] = (0, import_react4.useState)(DEFAULT_SOCIAL);
5482
- const openSelector = (0, import_react4.useCallback)(() => setSelectorOpen(true), []);
5483
- const closeSelector = (0, import_react4.useCallback)(() => setSelectorOpen(false), []);
5484
- const openSocialModal = (0, import_react4.useCallback)(() => setSocialModalOpen(true), []);
5485
- const closeSocialModal = (0, import_react4.useCallback)(() => setSocialModalOpen(false), []);
5486
- (0, import_react4.useEffect)(() => {
5558
+ const socialRef = (0, import_react5.useRef)(null);
5559
+ const socialInitialized = (0, import_react5.useRef)(false);
5560
+ const [selectorOpen, setSelectorOpen] = (0, import_react5.useState)(false);
5561
+ const [socialModalOpen, setSocialModalOpen] = (0, import_react5.useState)(false);
5562
+ const [theme, setTheme] = (0, import_react5.useState)(config?.theme ?? "auto");
5563
+ const [socialAuth, setSocialAuth] = (0, import_react5.useState)(DEFAULT_SOCIAL);
5564
+ const openSelector = (0, import_react5.useCallback)(() => setSelectorOpen(true), []);
5565
+ const closeSelector = (0, import_react5.useCallback)(() => setSelectorOpen(false), []);
5566
+ const openSocialModal = (0, import_react5.useCallback)(() => setSocialModalOpen(true), []);
5567
+ const closeSocialModal = (0, import_react5.useCallback)(() => setSocialModalOpen(false), []);
5568
+ (0, import_react5.useEffect)(() => {
5487
5569
  if (!socialAuth.isUnlocked) return;
5488
5570
  const id = setInterval(() => {
5489
5571
  const sdk = socialRef.current;
@@ -5496,7 +5578,7 @@ function DecaneKit({ config, children }) {
5496
5578
  }, 1e4);
5497
5579
  return () => clearInterval(id);
5498
5580
  }, [socialAuth.isUnlocked]);
5499
- (0, import_react4.useEffect)(() => {
5581
+ (0, import_react5.useEffect)(() => {
5500
5582
  if (!hasSocial(mode) || !config?.social || socialInitialized.current) return;
5501
5583
  socialInitialized.current = true;
5502
5584
  const {
@@ -5524,6 +5606,9 @@ function DecaneKit({ config, children }) {
5524
5606
  () => setSocialAuth((p) => ({ ...p, isUnlocked: false, sessionExpiresAt: null }))
5525
5607
  );
5526
5608
  sdk.on("disconnected", () => setSocialAuth(DEFAULT_SOCIAL));
5609
+ sdk.on("wallet-creating", () => setSocialAuth((p) => ({ ...p, phase: "creating" })));
5610
+ sdk.on("wallet-unlocking", () => setSocialAuth((p) => ({ ...p, phase: "unlocking" })));
5611
+ sdk.on("connected", () => setSocialAuth((p) => ({ ...p, phase: null })));
5527
5612
  const saved = sdk.getAddresses();
5528
5613
  if (saved) {
5529
5614
  setSocialAuth((p) => ({ ...p, addresses: saved, isUnlocked: false, needsReconnect: true }));
@@ -5532,7 +5617,10 @@ function DecaneKit({ config, children }) {
5532
5617
  });
5533
5618
  const params = new URLSearchParams(window.location.search);
5534
5619
  if (params.has("decane_jwt") || params.has("decane_error")) {
5535
- sdk.connectWithGoogle().then(applyResult).catch(console.error);
5620
+ sdk.connectWithGoogle().then(applyResult).catch((e) => {
5621
+ setSocialAuth((p) => p.phase ? { ...p, phase: null } : p);
5622
+ console.error(e);
5623
+ });
5536
5624
  }
5537
5625
  }).catch(console.error);
5538
5626
  }, []);
@@ -5544,129 +5632,153 @@ function DecaneKit({ config, children }) {
5544
5632
  isUnlocked: sdk?.isUnlocked() ?? false,
5545
5633
  sessionExpiresAt: sdk?.sessionExpiresAt() ?? null,
5546
5634
  needsReconnect: false,
5547
- canUsePasskey: false
5635
+ canUsePasskey: false,
5636
+ phase: null
5548
5637
  });
5549
5638
  sdk?.canSignInWithPasskey().then((can) => setSocialAuth((p) => ({ ...p, canUsePasskey: can }))).catch(() => {
5550
5639
  });
5551
5640
  }
5552
- const signInWithPasskey = (0, import_react4.useCallback)(async () => {
5641
+ const clearPhase = (0, import_react5.useCallback)(() => setSocialAuth((p) => p.phase ? { ...p, phase: null } : p), []);
5642
+ const signInWithPasskey = (0, import_react5.useCallback)(async () => {
5553
5643
  const sdk = socialRef.current;
5554
5644
  if (!sdk) throw new Error("Social sign-in not configured");
5555
- const result = await sdk.signInWithPasskey();
5556
- applyResult(result);
5557
- setSelectorOpen(false);
5558
- return result;
5559
- }, []);
5560
- const connectWithGoogle = (0, import_react4.useCallback)(async () => {
5645
+ try {
5646
+ const result = await sdk.signInWithPasskey();
5647
+ applyResult(result);
5648
+ setSelectorOpen(false);
5649
+ return result;
5650
+ } catch (e) {
5651
+ clearPhase();
5652
+ throw e;
5653
+ }
5654
+ }, [clearPhase]);
5655
+ const connectWithGoogle = (0, import_react5.useCallback)(async () => {
5561
5656
  const sdk = socialRef.current;
5562
5657
  if (!sdk) throw new Error("Social sign-in not configured");
5563
5658
  await sdk.connectWithGoogle();
5564
5659
  }, []);
5565
- const connectWithEmail = (0, import_react4.useCallback)(async (email) => {
5660
+ const connectWithEmail = (0, import_react5.useCallback)(async (email) => {
5566
5661
  const sdk = socialRef.current;
5567
5662
  if (!sdk) throw new Error("Social sign-in not configured");
5568
5663
  return sdk.connectWithEmail(email);
5569
5664
  }, []);
5570
- const verifyEmailCode2 = (0, import_react4.useCallback)(async (email, code) => {
5665
+ const verifyEmailCode2 = (0, import_react5.useCallback)(async (email, code) => {
5571
5666
  const sdk = socialRef.current;
5572
5667
  if (!sdk) throw new Error("Social sign-in not configured");
5573
- const result = await sdk.verifyEmailCode(email, code);
5574
- applyResult(result);
5575
- setSelectorOpen(false);
5576
- }, []);
5577
- const connectWithToken = (0, import_react4.useCallback)(async (token, opts) => {
5668
+ try {
5669
+ const result = await sdk.verifyEmailCode(email, code);
5670
+ applyResult(result);
5671
+ setSelectorOpen(false);
5672
+ } catch (e) {
5673
+ clearPhase();
5674
+ throw e;
5675
+ }
5676
+ }, [clearPhase]);
5677
+ const connectWithToken = (0, import_react5.useCallback)(async (token, opts) => {
5578
5678
  const sdk = socialRef.current;
5579
5679
  if (!sdk) throw new Error("Social sign-in not configured");
5580
- const result = await sdk.connectWithToken(token, opts);
5581
- applyResult(result);
5582
- setSelectorOpen(false);
5583
- }, []);
5680
+ try {
5681
+ const result = await sdk.connectWithToken(token, opts);
5682
+ applyResult(result);
5683
+ setSelectorOpen(false);
5684
+ } catch (e) {
5685
+ clearPhase();
5686
+ throw e;
5687
+ }
5688
+ }, [clearPhase]);
5584
5689
  const customAuthConfig = config?.social?.customAuth;
5585
- const connectWithCustomAuth = (0, import_react4.useCallback)(async () => {
5690
+ const connectWithCustomAuth = (0, import_react5.useCallback)(async () => {
5586
5691
  if (!customAuthConfig) throw new Error("Custom auth not configured");
5587
5692
  const token = await customAuthConfig.getToken();
5588
5693
  await connectWithToken(token, customAuthConfig.providerId ? { providerId: customAuthConfig.providerId } : void 0);
5589
5694
  }, [customAuthConfig, connectWithToken]);
5590
- const socialUnlock = (0, import_react4.useCallback)(async () => {
5695
+ const socialUnlock = (0, import_react5.useCallback)(async () => {
5591
5696
  const sdk = socialRef.current;
5592
5697
  if (!sdk) return;
5593
- await sdk.unlock();
5594
- setSocialAuth((p) => ({
5595
- ...p,
5596
- isUnlocked: sdk.isUnlocked(),
5597
- sessionExpiresAt: sdk.sessionExpiresAt(),
5598
- needsReconnect: false
5599
- }));
5600
- }, []);
5601
- const socialDisconnect = (0, import_react4.useCallback)(async () => {
5698
+ setSocialAuth((p) => ({ ...p, phase: "unlocking" }));
5699
+ try {
5700
+ await sdk.unlock();
5701
+ setSocialAuth((p) => ({
5702
+ ...p,
5703
+ isUnlocked: sdk.isUnlocked(),
5704
+ sessionExpiresAt: sdk.sessionExpiresAt(),
5705
+ needsReconnect: false,
5706
+ phase: null
5707
+ }));
5708
+ } catch (e) {
5709
+ clearPhase();
5710
+ throw e;
5711
+ }
5712
+ }, [clearPhase]);
5713
+ const socialDisconnect = (0, import_react5.useCallback)(async () => {
5602
5714
  const sdk = socialRef.current;
5603
5715
  if (!sdk) return;
5604
5716
  await sdk.disconnect();
5605
5717
  setSocialAuth(DEFAULT_SOCIAL);
5606
5718
  }, []);
5607
- const socialSignMessage = (0, import_react4.useCallback)(async (chain, message) => {
5719
+ const socialSignMessage = (0, import_react5.useCallback)(async (chain, message) => {
5608
5720
  const sdk = socialRef.current;
5609
5721
  if (!sdk) throw new Error("Social wallet not connected");
5610
5722
  return sdk.signMessage({ chain, message });
5611
5723
  }, []);
5612
- const socialSendTransaction = (0, import_react4.useCallback)(async (req) => {
5724
+ const socialSendTransaction = (0, import_react5.useCallback)(async (req) => {
5613
5725
  const sdk = socialRef.current;
5614
5726
  if (!sdk) throw new Error("Social wallet not connected");
5615
5727
  return sdk.sendTransaction({ ...req, chain: req.chain });
5616
5728
  }, []);
5617
- const socialSignSolanaTransaction = (0, import_react4.useCallback)(async (tx) => {
5729
+ const socialSignSolanaTransaction = (0, import_react5.useCallback)(async (tx) => {
5618
5730
  const sdk = socialRef.current;
5619
5731
  if (!sdk) throw new Error("Social wallet not connected");
5620
5732
  return sdk.signSolanaTransaction(tx);
5621
5733
  }, []);
5622
- const socialSignTypedData = (0, import_react4.useCallback)(async (req) => {
5734
+ const socialSignTypedData = (0, import_react5.useCallback)(async (req) => {
5623
5735
  const sdk = socialRef.current;
5624
5736
  if (!sdk) throw new Error("Social wallet not connected");
5625
5737
  return sdk.signTypedData({ ...req, chain: req.chain });
5626
5738
  }, []);
5627
- const socialGetBalance = (0, import_react4.useCallback)(async (chain) => {
5739
+ const socialGetBalance = (0, import_react5.useCallback)(async (chain) => {
5628
5740
  const sdk = socialRef.current;
5629
5741
  if (!sdk) throw new Error("Social wallet not connected");
5630
5742
  return sdk.getBalance(chain);
5631
5743
  }, []);
5632
- const socialGetBalances = (0, import_react4.useCallback)(async () => {
5744
+ const socialGetBalances = (0, import_react5.useCallback)(async () => {
5633
5745
  const sdk = socialRef.current;
5634
5746
  if (!sdk) throw new Error("Social wallet not connected");
5635
5747
  return sdk.getBalances();
5636
5748
  }, []);
5637
- const socialRotateShares = (0, import_react4.useCallback)(async (opts) => {
5749
+ const socialRotateShares = (0, import_react5.useCallback)(async (opts) => {
5638
5750
  const sdk = socialRef.current;
5639
5751
  if (!sdk) throw new Error("Social wallet not connected");
5640
5752
  return sdk.rotateShares(opts);
5641
5753
  }, []);
5642
- const socialExportPortableBackup = (0, import_react4.useCallback)(async (opts) => {
5754
+ const socialExportPortableBackup = (0, import_react5.useCallback)(async (opts) => {
5643
5755
  const sdk = socialRef.current;
5644
5756
  if (!sdk) throw new Error("Social wallet not connected");
5645
5757
  return sdk.exportPortableBackup(opts);
5646
5758
  }, []);
5647
- const socialHasRecoveryShare = (0, import_react4.useCallback)(async () => {
5759
+ const socialHasRecoveryShare = (0, import_react5.useCallback)(async () => {
5648
5760
  const sdk = socialRef.current;
5649
5761
  if (!sdk) throw new Error("Social wallet not connected");
5650
5762
  return sdk.hasRecoveryShare();
5651
5763
  }, []);
5652
- const socialShouldPromptRecovery = (0, import_react4.useCallback)(async () => {
5764
+ const socialShouldPromptRecovery = (0, import_react5.useCallback)(async () => {
5653
5765
  const sdk = socialRef.current;
5654
5766
  if (!sdk) throw new Error("Social wallet not connected");
5655
5767
  return sdk.shouldPromptRecovery();
5656
5768
  }, []);
5657
- const socialDismissRecoveryPrompt = (0, import_react4.useCallback)(async () => {
5769
+ const socialDismissRecoveryPrompt = (0, import_react5.useCallback)(async () => {
5658
5770
  const sdk = socialRef.current;
5659
5771
  if (!sdk) throw new Error("Social wallet not connected");
5660
5772
  return sdk.dismissRecoveryPrompt();
5661
5773
  }, []);
5662
- const handleWalletConnect = (0, import_react4.useCallback)(
5774
+ const handleWalletConnect = (0, import_react5.useCallback)(
5663
5775
  (wallet, preference) => {
5664
5776
  walletRef.current.connect(wallet, preference).catch(console.error);
5665
5777
  },
5666
5778
  []
5667
5779
  );
5668
5780
  const networks = deriveNetworks(mode, config?.networks);
5669
- return /* @__PURE__ */ import_react4.default.createElement(
5781
+ return /* @__PURE__ */ import_react5.default.createElement(
5670
5782
  DecaneContext.Provider,
5671
5783
  {
5672
5784
  value: {
@@ -5704,7 +5816,7 @@ function DecaneKit({ config, children }) {
5704
5816
  }
5705
5817
  },
5706
5818
  children,
5707
- /* @__PURE__ */ import_react4.default.createElement(
5819
+ /* @__PURE__ */ import_react5.default.createElement(
5708
5820
  WalletSelector,
5709
5821
  {
5710
5822
  provider: walletRef.current,
@@ -5725,7 +5837,7 @@ function DecaneKit({ config, children }) {
5725
5837
  onCustomAuthSignIn: customAuthConfig ? connectWithCustomAuth : void 0
5726
5838
  }
5727
5839
  ),
5728
- /* @__PURE__ */ import_react4.default.createElement(
5840
+ /* @__PURE__ */ import_react5.default.createElement(
5729
5841
  SocialWalletModal,
5730
5842
  {
5731
5843
  open: socialModalOpen,
@@ -5748,11 +5860,12 @@ function DecaneKit({ config, children }) {
5748
5860
  rpcUrls: config?.social?.rpcUrls,
5749
5861
  chains: config?.social?.chains
5750
5862
  }
5751
- )
5863
+ ),
5864
+ /* @__PURE__ */ import_react5.default.createElement(WalletStatusOverlay, { phase: socialAuth.phase, theme })
5752
5865
  );
5753
5866
  }
5754
5867
  function useDecaneContext() {
5755
- const ctx = (0, import_react4.useContext)(DecaneContext);
5868
+ const ctx = (0, import_react5.useContext)(DecaneContext);
5756
5869
  if (!ctx) {
5757
5870
  throw new Error(
5758
5871
  "Decane hooks must be called inside <DecaneKit>. Wrap your app: <DecaneKit config={...}><App /></DecaneKit>"
@@ -5762,7 +5875,7 @@ function useDecaneContext() {
5762
5875
  }
5763
5876
 
5764
5877
  // src/ui/hooks.ts
5765
- var import_react5 = require("react");
5878
+ var import_react6 = require("react");
5766
5879
  function useSocialAuth() {
5767
5880
  const {
5768
5881
  socialAuth,
@@ -5776,12 +5889,12 @@ function useSocialAuth() {
5776
5889
  socialUnlock,
5777
5890
  socialDisconnect
5778
5891
  } = useDecaneContext();
5779
- const [googleLoading, setGoogleLoading] = (0, import_react5.useState)(false);
5780
- const [emailLoading, setEmailLoading] = (0, import_react5.useState)(false);
5781
- const [tokenLoading, setTokenLoading] = (0, import_react5.useState)(false);
5782
- const [customLoading, setCustomLoading] = (0, import_react5.useState)(false);
5783
- const [error, setError] = (0, import_react5.useState)(null);
5784
- const signInWithGoogle = (0, import_react5.useCallback)(async () => {
5892
+ const [googleLoading, setGoogleLoading] = (0, import_react6.useState)(false);
5893
+ const [emailLoading, setEmailLoading] = (0, import_react6.useState)(false);
5894
+ const [tokenLoading, setTokenLoading] = (0, import_react6.useState)(false);
5895
+ const [customLoading, setCustomLoading] = (0, import_react6.useState)(false);
5896
+ const [error, setError] = (0, import_react6.useState)(null);
5897
+ const signInWithGoogle = (0, import_react6.useCallback)(async () => {
5785
5898
  setGoogleLoading(true);
5786
5899
  setError(null);
5787
5900
  try {
@@ -5791,7 +5904,7 @@ function useSocialAuth() {
5791
5904
  setGoogleLoading(false);
5792
5905
  }
5793
5906
  }, [connectWithGoogle]);
5794
- const sendEmailCode = (0, import_react5.useCallback)(async (email) => {
5907
+ const sendEmailCode = (0, import_react6.useCallback)(async (email) => {
5795
5908
  setEmailLoading(true);
5796
5909
  setError(null);
5797
5910
  try {
@@ -5804,7 +5917,7 @@ function useSocialAuth() {
5804
5917
  setEmailLoading(false);
5805
5918
  }
5806
5919
  }, [connectWithEmail]);
5807
- const confirmEmailCode = (0, import_react5.useCallback)(async (email, code) => {
5920
+ const confirmEmailCode = (0, import_react6.useCallback)(async (email, code) => {
5808
5921
  setEmailLoading(true);
5809
5922
  setError(null);
5810
5923
  try {
@@ -5816,7 +5929,7 @@ function useSocialAuth() {
5816
5929
  setEmailLoading(false);
5817
5930
  }
5818
5931
  }, [verifyEmailCode2]);
5819
- const signInWithToken = (0, import_react5.useCallback)(async (token, opts) => {
5932
+ const signInWithToken = (0, import_react6.useCallback)(async (token, opts) => {
5820
5933
  setTokenLoading(true);
5821
5934
  setError(null);
5822
5935
  try {
@@ -5828,7 +5941,7 @@ function useSocialAuth() {
5828
5941
  setTokenLoading(false);
5829
5942
  }
5830
5943
  }, [connectWithToken]);
5831
- const signInWithCustomAuth = (0, import_react5.useCallback)(async () => {
5944
+ const signInWithCustomAuth = (0, import_react6.useCallback)(async () => {
5832
5945
  if (!connectWithCustomAuth) throw new Error("Custom auth not configured");
5833
5946
  setCustomLoading(true);
5834
5947
  setError(null);
@@ -5841,7 +5954,7 @@ function useSocialAuth() {
5841
5954
  setCustomLoading(false);
5842
5955
  }
5843
5956
  }, [connectWithCustomAuth]);
5844
- const signInWithPasskey = (0, import_react5.useCallback)(async () => {
5957
+ const signInWithPasskey = (0, import_react6.useCallback)(async () => {
5845
5958
  setError(null);
5846
5959
  try {
5847
5960
  await ctxSignInWithPasskey();
@@ -5850,7 +5963,7 @@ function useSocialAuth() {
5850
5963
  throw e;
5851
5964
  }
5852
5965
  }, [ctxSignInWithPasskey]);
5853
- const unlock = (0, import_react5.useCallback)(async () => {
5966
+ const unlock = (0, import_react6.useCallback)(async () => {
5854
5967
  setError(null);
5855
5968
  try {
5856
5969
  await socialUnlock();
@@ -5859,7 +5972,7 @@ function useSocialAuth() {
5859
5972
  throw e;
5860
5973
  }
5861
5974
  }, [socialUnlock]);
5862
- const disconnect = (0, import_react5.useCallback)(async () => {
5975
+ const disconnect = (0, import_react6.useCallback)(async () => {
5863
5976
  setError(null);
5864
5977
  try {
5865
5978
  await socialDisconnect();
@@ -5876,6 +5989,9 @@ function useSocialAuth() {
5876
5989
  sessionExpiresAt: socialAuth.sessionExpiresAt,
5877
5990
  // True when this device can skip the full sign-in and resume with a passkey.
5878
5991
  canUsePasskey: socialAuth.canUsePasskey,
5992
+ // Long-running work in progress, for driving your own status UI.
5993
+ phase: socialAuth.phase,
5994
+ isCreatingWallet: socialAuth.phase === "creating",
5879
5995
  // True when addresses are known (from a previous visit) but there's no
5880
5996
  // live session — unlock() will always throw in this state (every
5881
5997
  // unlock requires a fresh JWT, and JWTs are never persisted). Route
@@ -5918,8 +6034,8 @@ function useSocialWallet() {
5918
6034
  closeSocialModal,
5919
6035
  socialModalOpen
5920
6036
  } = useDecaneContext();
5921
- const [loading, setLoading] = (0, import_react5.useState)(false);
5922
- const [error, setError] = (0, import_react5.useState)(null);
6037
+ const [loading, setLoading] = (0, import_react6.useState)(false);
6038
+ const [error, setError] = (0, import_react6.useState)(null);
5923
6039
  async function run(fn) {
5924
6040
  setLoading(true);
5925
6041
  setError(null);
@@ -5933,31 +6049,31 @@ function useSocialWallet() {
5933
6049
  setLoading(false);
5934
6050
  }
5935
6051
  }
5936
- const signMessage = (0, import_react5.useCallback)(
6052
+ const signMessage = (0, import_react6.useCallback)(
5937
6053
  (chain, message) => run(() => socialSignMessage(chain, message)),
5938
6054
  [socialSignMessage]
5939
6055
  );
5940
- const sendTransaction = (0, import_react5.useCallback)(
6056
+ const sendTransaction = (0, import_react6.useCallback)(
5941
6057
  (req) => run(() => socialSendTransaction(req)),
5942
6058
  [socialSendTransaction]
5943
6059
  );
5944
- const signSolanaTransaction2 = (0, import_react5.useCallback)(
6060
+ const signSolanaTransaction2 = (0, import_react6.useCallback)(
5945
6061
  (tx) => run(() => socialSignSolanaTransaction(tx)),
5946
6062
  [socialSignSolanaTransaction]
5947
6063
  );
5948
- const signTypedData = (0, import_react5.useCallback)(
6064
+ const signTypedData = (0, import_react6.useCallback)(
5949
6065
  (req) => run(() => socialSignTypedData(req)),
5950
6066
  [socialSignTypedData]
5951
6067
  );
5952
- const getBalance = (0, import_react5.useCallback)(
6068
+ const getBalance = (0, import_react6.useCallback)(
5953
6069
  (chain) => run(() => socialGetBalance(chain)),
5954
6070
  [socialGetBalance]
5955
6071
  );
5956
- const getBalances = (0, import_react5.useCallback)(
6072
+ const getBalances = (0, import_react6.useCallback)(
5957
6073
  () => run(() => socialGetBalances()),
5958
6074
  [socialGetBalances]
5959
6075
  );
5960
- const unlock = (0, import_react5.useCallback)(async () => {
6076
+ const unlock = (0, import_react6.useCallback)(async () => {
5961
6077
  setError(null);
5962
6078
  try {
5963
6079
  await socialUnlock();
@@ -5966,7 +6082,7 @@ function useSocialWallet() {
5966
6082
  throw e;
5967
6083
  }
5968
6084
  }, [socialUnlock]);
5969
- const disconnect = (0, import_react5.useCallback)(async () => {
6085
+ const disconnect = (0, import_react6.useCallback)(async () => {
5970
6086
  setError(null);
5971
6087
  try {
5972
6088
  await socialDisconnect();
@@ -5975,23 +6091,23 @@ function useSocialWallet() {
5975
6091
  throw e;
5976
6092
  }
5977
6093
  }, [socialDisconnect]);
5978
- const rotateShares = (0, import_react5.useCallback)(
6094
+ const rotateShares = (0, import_react6.useCallback)(
5979
6095
  (opts) => run(() => socialRotateShares(opts)),
5980
6096
  [socialRotateShares]
5981
6097
  );
5982
- const exportPortableBackup = (0, import_react5.useCallback)(
6098
+ const exportPortableBackup = (0, import_react6.useCallback)(
5983
6099
  (opts) => run(() => socialExportPortableBackup(opts)),
5984
6100
  [socialExportPortableBackup]
5985
6101
  );
5986
- const hasRecoveryShare = (0, import_react5.useCallback)(
6102
+ const hasRecoveryShare = (0, import_react6.useCallback)(
5987
6103
  () => run(() => socialHasRecoveryShare()),
5988
6104
  [socialHasRecoveryShare]
5989
6105
  );
5990
- const shouldPromptRecovery = (0, import_react5.useCallback)(
6106
+ const shouldPromptRecovery = (0, import_react6.useCallback)(
5991
6107
  () => run(() => socialShouldPromptRecovery()),
5992
6108
  [socialShouldPromptRecovery]
5993
6109
  );
5994
- const dismissRecoveryPrompt = (0, import_react5.useCallback)(
6110
+ const dismissRecoveryPrompt = (0, import_react6.useCallback)(
5995
6111
  () => run(() => socialDismissRecoveryPrompt()),
5996
6112
  [socialDismissRecoveryPrompt]
5997
6113
  );
@@ -6007,6 +6123,10 @@ function useSocialWallet() {
6007
6123
  // unlock requires a fresh JWT, and JWTs are never persisted). Route
6008
6124
  // this into a real reconnect (signInWithGoogle / sendEmailCode), not unlock().
6009
6125
  needsReconnect: socialAuth.needsReconnect,
6126
+ // Long-running work in progress ('creating' | 'unlocking' | null), for
6127
+ // driving your own status UI in addition to the SDK's built-in overlay.
6128
+ phase: socialAuth.phase,
6129
+ isCreatingWallet: socialAuth.phase === "creating",
6010
6130
  // Modal
6011
6131
  modalOpen: socialModalOpen,
6012
6132
  openModal: openSocialModal,
@@ -6035,11 +6155,11 @@ function useSocialWallet() {
6035
6155
  }
6036
6156
  function useSocialBalance(chain) {
6037
6157
  const { socialAuth, socialGetBalance } = useDecaneContext();
6038
- const [balance, setBalance] = (0, import_react5.useState)(null);
6039
- const [loading, setLoading] = (0, import_react5.useState)(false);
6040
- const [error, setError] = (0, import_react5.useState)(null);
6158
+ const [balance, setBalance] = (0, import_react6.useState)(null);
6159
+ const [loading, setLoading] = (0, import_react6.useState)(false);
6160
+ const [error, setError] = (0, import_react6.useState)(null);
6041
6161
  const addrKey = `${socialAuth.addresses?.evm ?? ""}|${socialAuth.addresses?.solana ?? ""}`;
6042
- const refetch = (0, import_react5.useCallback)(async () => {
6162
+ const refetch = (0, import_react6.useCallback)(async () => {
6043
6163
  if (!socialAuth.addresses) {
6044
6164
  setBalance(null);
6045
6165
  return;
@@ -6055,7 +6175,7 @@ function useSocialBalance(chain) {
6055
6175
  setLoading(false);
6056
6176
  }
6057
6177
  }, [socialGetBalance, chain, socialAuth.addresses]);
6058
- (0, import_react5.useEffect)(() => {
6178
+ (0, import_react6.useEffect)(() => {
6059
6179
  let cancelled = false;
6060
6180
  if (!socialAuth.addresses) {
6061
6181
  setBalance(null);
@@ -6086,8 +6206,8 @@ function toDecaneError(err) {
6086
6206
  }
6087
6207
  function useDecane() {
6088
6208
  const { provider, theme, setTheme } = useDecaneContext();
6089
- const [, forceUpdate] = (0, import_react5.useState)(0);
6090
- (0, import_react5.useEffect)(() => {
6209
+ const [, forceUpdate] = (0, import_react6.useState)(0);
6210
+ (0, import_react6.useEffect)(() => {
6091
6211
  const refresh = () => forceUpdate((n) => n + 1);
6092
6212
  const events = [
6093
6213
  "connect",
@@ -6126,10 +6246,10 @@ function useWalletSelector() {
6126
6246
  }
6127
6247
  function useChainSwitch() {
6128
6248
  const { provider } = useDecaneContext();
6129
- const [, forceUpdate] = (0, import_react5.useState)(0);
6130
- const [loading, setLoading] = (0, import_react5.useState)(false);
6131
- const [error, setError] = (0, import_react5.useState)(null);
6132
- (0, import_react5.useEffect)(() => {
6249
+ const [, forceUpdate] = (0, import_react6.useState)(0);
6250
+ const [loading, setLoading] = (0, import_react6.useState)(false);
6251
+ const [error, setError] = (0, import_react6.useState)(null);
6252
+ (0, import_react6.useEffect)(() => {
6133
6253
  const refresh = () => forceUpdate((n) => n + 1);
6134
6254
  provider.on("connect", refresh);
6135
6255
  provider.on("disconnect", refresh);
@@ -6138,7 +6258,7 @@ function useChainSwitch() {
6138
6258
  provider.off("disconnect", refresh);
6139
6259
  };
6140
6260
  }, [provider]);
6141
- const switchChain = (0, import_react5.useCallback)(
6261
+ const switchChain = (0, import_react6.useCallback)(
6142
6262
  async (chainId) => {
6143
6263
  setLoading(true);
6144
6264
  setError(null);
@@ -6192,10 +6312,10 @@ function resolveScope(provider, chainId, account) {
6192
6312
  }
6193
6313
  function useSignMessage() {
6194
6314
  const { provider } = useDecaneContext();
6195
- const [signature, setSignature] = (0, import_react5.useState)(null);
6196
- const [loading, setLoading] = (0, import_react5.useState)(false);
6197
- const [error, setError] = (0, import_react5.useState)(null);
6198
- const signMessage = (0, import_react5.useCallback)(
6315
+ const [signature, setSignature] = (0, import_react6.useState)(null);
6316
+ const [loading, setLoading] = (0, import_react6.useState)(false);
6317
+ const [error, setError] = (0, import_react6.useState)(null);
6318
+ const signMessage = (0, import_react6.useCallback)(
6199
6319
  async (message, options) => {
6200
6320
  const { chain, account } = resolveScope(
6201
6321
  provider,
@@ -6221,7 +6341,7 @@ function useSignMessage() {
6221
6341
  },
6222
6342
  [provider]
6223
6343
  );
6224
- const reset = (0, import_react5.useCallback)(() => {
6344
+ const reset = (0, import_react6.useCallback)(() => {
6225
6345
  setSignature(null);
6226
6346
  setError(null);
6227
6347
  }, []);
@@ -6229,10 +6349,10 @@ function useSignMessage() {
6229
6349
  }
6230
6350
  function useSendTransaction() {
6231
6351
  const { provider } = useDecaneContext();
6232
- const [txHash, setTxHash] = (0, import_react5.useState)(null);
6233
- const [loading, setLoading] = (0, import_react5.useState)(false);
6234
- const [error, setError] = (0, import_react5.useState)(null);
6235
- const sendTransaction = (0, import_react5.useCallback)(
6352
+ const [txHash, setTxHash] = (0, import_react6.useState)(null);
6353
+ const [loading, setLoading] = (0, import_react6.useState)(false);
6354
+ const [error, setError] = (0, import_react6.useState)(null);
6355
+ const sendTransaction = (0, import_react6.useCallback)(
6236
6356
  async (tx, options) => {
6237
6357
  const { chain, account } = resolveScope(
6238
6358
  provider,
@@ -6259,7 +6379,7 @@ function useSendTransaction() {
6259
6379
  },
6260
6380
  [provider]
6261
6381
  );
6262
- const reset = (0, import_react5.useCallback)(() => {
6382
+ const reset = (0, import_react6.useCallback)(() => {
6263
6383
  setTxHash(null);
6264
6384
  setError(null);
6265
6385
  }, []);
@@ -6267,10 +6387,10 @@ function useSendTransaction() {
6267
6387
  }
6268
6388
  function useSignTypedData() {
6269
6389
  const { provider } = useDecaneContext();
6270
- const [signature, setSignature] = (0, import_react5.useState)(null);
6271
- const [loading, setLoading] = (0, import_react5.useState)(false);
6272
- const [error, setError] = (0, import_react5.useState)(null);
6273
- const signTypedData = (0, import_react5.useCallback)(
6390
+ const [signature, setSignature] = (0, import_react6.useState)(null);
6391
+ const [loading, setLoading] = (0, import_react6.useState)(false);
6392
+ const [error, setError] = (0, import_react6.useState)(null);
6393
+ const signTypedData = (0, import_react6.useCallback)(
6274
6394
  async (typedData, options) => {
6275
6395
  const { chain, account } = resolveScope(
6276
6396
  provider,
@@ -6296,7 +6416,7 @@ function useSignTypedData() {
6296
6416
  },
6297
6417
  [provider]
6298
6418
  );
6299
- const reset = (0, import_react5.useCallback)(() => {
6419
+ const reset = (0, import_react6.useCallback)(() => {
6300
6420
  setSignature(null);
6301
6421
  setError(null);
6302
6422
  }, []);