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 +246 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +163 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -387,7 +387,7 @@ interface SignTypedDataRequest {
|
|
|
387
387
|
message: Record<string, unknown>;
|
|
388
388
|
primaryType?: string;
|
|
389
389
|
}
|
|
390
|
-
type SdkEvent = 'connected' | 'disconnected' | 'session-expired' | 'session-started';
|
|
390
|
+
type SdkEvent = 'connected' | 'disconnected' | 'session-expired' | 'session-started' | 'wallet-creating' | 'wallet-unlocking';
|
|
391
391
|
interface DecaneConnect {
|
|
392
392
|
connect(): Promise<ConnectResult>;
|
|
393
393
|
connectWithGoogle(): Promise<ConnectResult>;
|
|
@@ -730,6 +730,12 @@ interface SocialAuthState {
|
|
|
730
730
|
* user, so signing back in costs one passkey prompt and nothing else.
|
|
731
731
|
*/
|
|
732
732
|
canUsePasskey: boolean;
|
|
733
|
+
/**
|
|
734
|
+
* Long-running work in progress, so the UI can show a status screen instead
|
|
735
|
+
* of appearing frozen. 'creating' = first-time key generation (several
|
|
736
|
+
* seconds); 'unlocking' = reopening the TEE session for a returning user.
|
|
737
|
+
*/
|
|
738
|
+
phase: "creating" | "unlocking" | null;
|
|
733
739
|
}
|
|
734
740
|
interface DecaneKitProps {
|
|
735
741
|
config?: DecaneConfig;
|
|
@@ -791,6 +797,8 @@ declare function useSocialAuth(): {
|
|
|
791
797
|
} | null;
|
|
792
798
|
sessionExpiresAt: number | null;
|
|
793
799
|
canUsePasskey: boolean;
|
|
800
|
+
phase: "creating" | "unlocking" | null;
|
|
801
|
+
isCreatingWallet: boolean;
|
|
794
802
|
needsReconnect: boolean;
|
|
795
803
|
googleLoading: boolean;
|
|
796
804
|
emailLoading: boolean;
|
|
@@ -822,6 +830,8 @@ declare function useSocialWallet(): {
|
|
|
822
830
|
} | null;
|
|
823
831
|
sessionExpiresAt: number | null;
|
|
824
832
|
needsReconnect: boolean;
|
|
833
|
+
phase: "creating" | "unlocking" | null;
|
|
834
|
+
isCreatingWallet: boolean;
|
|
825
835
|
modalOpen: boolean;
|
|
826
836
|
openModal: () => void;
|
|
827
837
|
closeModal: () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -387,7 +387,7 @@ interface SignTypedDataRequest {
|
|
|
387
387
|
message: Record<string, unknown>;
|
|
388
388
|
primaryType?: string;
|
|
389
389
|
}
|
|
390
|
-
type SdkEvent = 'connected' | 'disconnected' | 'session-expired' | 'session-started';
|
|
390
|
+
type SdkEvent = 'connected' | 'disconnected' | 'session-expired' | 'session-started' | 'wallet-creating' | 'wallet-unlocking';
|
|
391
391
|
interface DecaneConnect {
|
|
392
392
|
connect(): Promise<ConnectResult>;
|
|
393
393
|
connectWithGoogle(): Promise<ConnectResult>;
|
|
@@ -730,6 +730,12 @@ interface SocialAuthState {
|
|
|
730
730
|
* user, so signing back in costs one passkey prompt and nothing else.
|
|
731
731
|
*/
|
|
732
732
|
canUsePasskey: boolean;
|
|
733
|
+
/**
|
|
734
|
+
* Long-running work in progress, so the UI can show a status screen instead
|
|
735
|
+
* of appearing frozen. 'creating' = first-time key generation (several
|
|
736
|
+
* seconds); 'unlocking' = reopening the TEE session for a returning user.
|
|
737
|
+
*/
|
|
738
|
+
phase: "creating" | "unlocking" | null;
|
|
733
739
|
}
|
|
734
740
|
interface DecaneKitProps {
|
|
735
741
|
config?: DecaneConfig;
|
|
@@ -791,6 +797,8 @@ declare function useSocialAuth(): {
|
|
|
791
797
|
} | null;
|
|
792
798
|
sessionExpiresAt: number | null;
|
|
793
799
|
canUsePasskey: boolean;
|
|
800
|
+
phase: "creating" | "unlocking" | null;
|
|
801
|
+
isCreatingWallet: boolean;
|
|
794
802
|
needsReconnect: boolean;
|
|
795
803
|
googleLoading: boolean;
|
|
796
804
|
emailLoading: boolean;
|
|
@@ -822,6 +830,8 @@ declare function useSocialWallet(): {
|
|
|
822
830
|
} | null;
|
|
823
831
|
sessionExpiresAt: number | null;
|
|
824
832
|
needsReconnect: boolean;
|
|
833
|
+
phase: "creating" | "unlocking" | null;
|
|
834
|
+
isCreatingWallet: boolean;
|
|
825
835
|
modalOpen: boolean;
|
|
826
836
|
openModal: () => void;
|
|
827
837
|
closeModal: () => void;
|
package/dist/index.js
CHANGED
|
@@ -2548,9 +2548,6 @@ function validatePin(pin) {
|
|
|
2548
2548
|
// src/social/crypto/passkey.ts
|
|
2549
2549
|
init_errors();
|
|
2550
2550
|
import { startRegistration, startAuthentication as startAuthentication2 } from "@simplewebauthn/browser";
|
|
2551
|
-
function b64u(u) {
|
|
2552
|
-
return btoa(String.fromCharCode(...u)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
2553
|
-
}
|
|
2554
2551
|
function fromB64u(s) {
|
|
2555
2552
|
return Uint8Array.from(atob(s.replace(/-/g, "+").replace(/_/g, "/")), (c) => c.charCodeAt(0));
|
|
2556
2553
|
}
|
|
@@ -2585,7 +2582,7 @@ async function authenticateWithPasskey(opts) {
|
|
|
2585
2582
|
...opts.optionsJSON,
|
|
2586
2583
|
extensions: {
|
|
2587
2584
|
...opts.optionsJSON.extensions,
|
|
2588
|
-
prf: { eval: { first:
|
|
2585
|
+
prf: { eval: { first: buf3(opts.prfSalt) } }
|
|
2589
2586
|
}
|
|
2590
2587
|
};
|
|
2591
2588
|
let response;
|
|
@@ -2968,7 +2965,7 @@ function formatBalanceDisplay(value) {
|
|
|
2968
2965
|
// src/social/client.ts
|
|
2969
2966
|
var DEFAULT_API_BASE = "https://backend.decane.app";
|
|
2970
2967
|
var DEFAULT_TEE_URL = "https://4405742df08d19abc549a05ade2a7154d98bd87f-8443.dstack-pha-prod9.phala.network";
|
|
2971
|
-
var DEFAULT_SESSION_MINUTES =
|
|
2968
|
+
var DEFAULT_SESSION_MINUTES = 120;
|
|
2972
2969
|
function makePersistKey(apiKey) {
|
|
2973
2970
|
return `decane:social:${apiKey.slice(0, 20)}`;
|
|
2974
2971
|
}
|
|
@@ -3268,6 +3265,7 @@ async function createDecaneConnect(config) {
|
|
|
3268
3265
|
}
|
|
3269
3266
|
async function passkeyLogin(stored) {
|
|
3270
3267
|
const userId = stored.userId;
|
|
3268
|
+
events.emit("wallet-unlocking");
|
|
3271
3269
|
const options = await api.getWebAuthnLoginOptions(userId, rpId);
|
|
3272
3270
|
if (!options) {
|
|
3273
3271
|
throw new NewDeviceError();
|
|
@@ -3301,8 +3299,10 @@ async function createDecaneConnect(config) {
|
|
|
3301
3299
|
async function handleAuthResult(result) {
|
|
3302
3300
|
let addresses;
|
|
3303
3301
|
if (!result.hasShare) {
|
|
3302
|
+
events.emit("wallet-creating");
|
|
3304
3303
|
addresses = await firstTimeSetup(result.userId, result.jwt);
|
|
3305
3304
|
} else {
|
|
3305
|
+
events.emit("wallet-unlocking");
|
|
3306
3306
|
addresses = await returningUserUnlock(result.userId, result.jwt);
|
|
3307
3307
|
}
|
|
3308
3308
|
auth = { jwt: result.jwt, userId: result.userId, addresses };
|
|
@@ -3641,8 +3641,8 @@ async function createDecaneConnect(config) {
|
|
|
3641
3641
|
function bufferToB64u(buf6) {
|
|
3642
3642
|
return btoa(String.fromCharCode(...buf6)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
3643
3643
|
}
|
|
3644
|
-
function b64uToBuffer(
|
|
3645
|
-
const b644 =
|
|
3644
|
+
function b64uToBuffer(b64u) {
|
|
3645
|
+
const b644 = b64u.replace(/-/g, "+").replace(/_/g, "/");
|
|
3646
3646
|
return Uint8Array.from(atob(b644), (c) => c.charCodeAt(0));
|
|
3647
3647
|
}
|
|
3648
3648
|
function toHex(bytes) {
|
|
@@ -5368,21 +5368,103 @@ function SocialWalletModal({
|
|
|
5368
5368
|
}
|
|
5369
5369
|
|
|
5370
5370
|
// src/ui/context.tsx
|
|
5371
|
-
import
|
|
5371
|
+
import React5, {
|
|
5372
5372
|
createContext,
|
|
5373
5373
|
useCallback as useCallback3,
|
|
5374
5374
|
useContext,
|
|
5375
|
-
useEffect as
|
|
5375
|
+
useEffect as useEffect4,
|
|
5376
5376
|
useRef,
|
|
5377
5377
|
useState as useState3
|
|
5378
5378
|
} from "react";
|
|
5379
|
+
|
|
5380
|
+
// src/ui/StatusOverlay.tsx
|
|
5381
|
+
import React4, { useEffect as useEffect3 } from "react";
|
|
5382
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
5383
|
+
function injectTokens3(theme) {
|
|
5384
|
+
if (typeof document === "undefined") return;
|
|
5385
|
+
const resolved = theme === "auto" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
|
|
5386
|
+
let el = document.getElementById("decane-tokens");
|
|
5387
|
+
if (!el) {
|
|
5388
|
+
el = document.createElement("style");
|
|
5389
|
+
el.id = "decane-tokens";
|
|
5390
|
+
document.head.appendChild(el);
|
|
5391
|
+
}
|
|
5392
|
+
el.textContent = `:root { ${CSS_VARS[resolved]} }`;
|
|
5393
|
+
}
|
|
5394
|
+
function WalletStatusOverlay({
|
|
5395
|
+
phase,
|
|
5396
|
+
theme = "auto"
|
|
5397
|
+
}) {
|
|
5398
|
+
useEffect3(() => {
|
|
5399
|
+
if (!phase) return;
|
|
5400
|
+
injectTokens3(theme);
|
|
5401
|
+
if (theme !== "auto") return;
|
|
5402
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
5403
|
+
const h = () => injectTokens3("auto");
|
|
5404
|
+
mq.addEventListener("change", h);
|
|
5405
|
+
return () => mq.removeEventListener("change", h);
|
|
5406
|
+
}, [phase, theme]);
|
|
5407
|
+
if (!phase || typeof document === "undefined") return null;
|
|
5408
|
+
const title = phase === "creating" ? "Creating your wallet" : "Unlocking your wallet";
|
|
5409
|
+
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";
|
|
5410
|
+
return createPortal3(
|
|
5411
|
+
/* @__PURE__ */ React4.createElement(
|
|
5412
|
+
"div",
|
|
5413
|
+
{
|
|
5414
|
+
role: "dialog",
|
|
5415
|
+
"aria-modal": "true",
|
|
5416
|
+
"aria-label": title,
|
|
5417
|
+
style: {
|
|
5418
|
+
position: "fixed",
|
|
5419
|
+
inset: 0,
|
|
5420
|
+
zIndex: 1e4,
|
|
5421
|
+
display: "flex",
|
|
5422
|
+
alignItems: "center",
|
|
5423
|
+
justifyContent: "center",
|
|
5424
|
+
padding: 16,
|
|
5425
|
+
fontFamily: "var(--dc-font-sans, system-ui, sans-serif)"
|
|
5426
|
+
}
|
|
5427
|
+
},
|
|
5428
|
+
/* @__PURE__ */ React4.createElement("div", { style: {
|
|
5429
|
+
position: "absolute",
|
|
5430
|
+
inset: 0,
|
|
5431
|
+
background: "var(--dc-bg-overlay, rgba(0,0,0,0.75))",
|
|
5432
|
+
backdropFilter: "blur(8px)",
|
|
5433
|
+
WebkitBackdropFilter: "blur(8px)"
|
|
5434
|
+
} }),
|
|
5435
|
+
/* @__PURE__ */ React4.createElement("div", { style: {
|
|
5436
|
+
position: "relative",
|
|
5437
|
+
background: "var(--dc-bg, #0D0D0B)",
|
|
5438
|
+
border: "1px solid var(--dc-border, #3D3C39)",
|
|
5439
|
+
borderRadius: 20,
|
|
5440
|
+
width: "100%",
|
|
5441
|
+
maxWidth: 340,
|
|
5442
|
+
padding: "30px 26px",
|
|
5443
|
+
textAlign: "center",
|
|
5444
|
+
boxShadow: "0 24px 64px rgba(0,0,0,0.6)"
|
|
5445
|
+
} }, /* @__PURE__ */ React4.createElement("div", { style: { display: "flex", justifyContent: "center", marginBottom: 18 } }, /* @__PURE__ */ React4.createElement("div", { style: { position: "relative", width: 60, height: 60, display: "flex", alignItems: "center", justifyContent: "center" } }, /* @__PURE__ */ React4.createElement("span", { style: {
|
|
5446
|
+
position: "absolute",
|
|
5447
|
+
inset: 0,
|
|
5448
|
+
borderRadius: "50%",
|
|
5449
|
+
border: "2px solid var(--dc-border, #3D3C39)",
|
|
5450
|
+
borderTopColor: "var(--dc-accent, #F5C800)",
|
|
5451
|
+
animation: "dc-status-spin 0.8s linear infinite"
|
|
5452
|
+
} }), /* @__PURE__ */ React4.createElement(DecaneMark, { size: 32 }))), /* @__PURE__ */ React4.createElement("div", { style: { fontSize: 16, fontWeight: 800, color: "var(--dc-text, #F9F9F7)", letterSpacing: "-0.02em", marginBottom: 7 } }, title), /* @__PURE__ */ React4.createElement("div", { style: { fontSize: 12, color: "var(--dc-text-muted, #8A8884)", lineHeight: 1.55 } }, sub), /* @__PURE__ */ React4.createElement("div", { style: { marginTop: 20, paddingTop: 14, borderTop: "1px solid var(--dc-border, #3D3C39)", display: "flex", alignItems: "center", justifyContent: "center", gap: 6 } }, /* @__PURE__ */ React4.createElement(DecaneMark, { size: 13, muted: true }), /* @__PURE__ */ React4.createElement(DecaneWordmark, { size: 11, muted: true }))),
|
|
5453
|
+
/* @__PURE__ */ React4.createElement("style", null, `@keyframes dc-status-spin { to { transform: rotate(360deg); } }`)
|
|
5454
|
+
),
|
|
5455
|
+
document.body
|
|
5456
|
+
);
|
|
5457
|
+
}
|
|
5458
|
+
|
|
5459
|
+
// src/ui/context.tsx
|
|
5379
5460
|
var DEFAULT_SOCIAL = {
|
|
5380
5461
|
addresses: null,
|
|
5381
5462
|
isNewUser: false,
|
|
5382
5463
|
isUnlocked: false,
|
|
5383
5464
|
sessionExpiresAt: null,
|
|
5384
5465
|
needsReconnect: false,
|
|
5385
|
-
canUsePasskey: false
|
|
5466
|
+
canUsePasskey: false,
|
|
5467
|
+
phase: null
|
|
5386
5468
|
};
|
|
5387
5469
|
var DecaneContext = createContext(null);
|
|
5388
5470
|
function hasSocial(mode) {
|
|
@@ -5419,7 +5501,7 @@ function DecaneKit({ config, children }) {
|
|
|
5419
5501
|
const closeSelector = useCallback3(() => setSelectorOpen(false), []);
|
|
5420
5502
|
const openSocialModal = useCallback3(() => setSocialModalOpen(true), []);
|
|
5421
5503
|
const closeSocialModal = useCallback3(() => setSocialModalOpen(false), []);
|
|
5422
|
-
|
|
5504
|
+
useEffect4(() => {
|
|
5423
5505
|
if (!socialAuth.isUnlocked) return;
|
|
5424
5506
|
const id = setInterval(() => {
|
|
5425
5507
|
const sdk = socialRef.current;
|
|
@@ -5432,7 +5514,7 @@ function DecaneKit({ config, children }) {
|
|
|
5432
5514
|
}, 1e4);
|
|
5433
5515
|
return () => clearInterval(id);
|
|
5434
5516
|
}, [socialAuth.isUnlocked]);
|
|
5435
|
-
|
|
5517
|
+
useEffect4(() => {
|
|
5436
5518
|
if (!hasSocial(mode) || !config?.social || socialInitialized.current) return;
|
|
5437
5519
|
socialInitialized.current = true;
|
|
5438
5520
|
const {
|
|
@@ -5460,6 +5542,9 @@ function DecaneKit({ config, children }) {
|
|
|
5460
5542
|
() => setSocialAuth((p) => ({ ...p, isUnlocked: false, sessionExpiresAt: null }))
|
|
5461
5543
|
);
|
|
5462
5544
|
sdk.on("disconnected", () => setSocialAuth(DEFAULT_SOCIAL));
|
|
5545
|
+
sdk.on("wallet-creating", () => setSocialAuth((p) => ({ ...p, phase: "creating" })));
|
|
5546
|
+
sdk.on("wallet-unlocking", () => setSocialAuth((p) => ({ ...p, phase: "unlocking" })));
|
|
5547
|
+
sdk.on("connected", () => setSocialAuth((p) => ({ ...p, phase: null })));
|
|
5463
5548
|
const saved = sdk.getAddresses();
|
|
5464
5549
|
if (saved) {
|
|
5465
5550
|
setSocialAuth((p) => ({ ...p, addresses: saved, isUnlocked: false, needsReconnect: true }));
|
|
@@ -5468,7 +5553,10 @@ function DecaneKit({ config, children }) {
|
|
|
5468
5553
|
});
|
|
5469
5554
|
const params = new URLSearchParams(window.location.search);
|
|
5470
5555
|
if (params.has("decane_jwt") || params.has("decane_error")) {
|
|
5471
|
-
sdk.connectWithGoogle().then(applyResult).catch(
|
|
5556
|
+
sdk.connectWithGoogle().then(applyResult).catch((e) => {
|
|
5557
|
+
setSocialAuth((p) => p.phase ? { ...p, phase: null } : p);
|
|
5558
|
+
console.error(e);
|
|
5559
|
+
});
|
|
5472
5560
|
}
|
|
5473
5561
|
}).catch(console.error);
|
|
5474
5562
|
}, []);
|
|
@@ -5480,19 +5568,26 @@ function DecaneKit({ config, children }) {
|
|
|
5480
5568
|
isUnlocked: sdk?.isUnlocked() ?? false,
|
|
5481
5569
|
sessionExpiresAt: sdk?.sessionExpiresAt() ?? null,
|
|
5482
5570
|
needsReconnect: false,
|
|
5483
|
-
canUsePasskey: false
|
|
5571
|
+
canUsePasskey: false,
|
|
5572
|
+
phase: null
|
|
5484
5573
|
});
|
|
5485
5574
|
sdk?.canSignInWithPasskey().then((can) => setSocialAuth((p) => ({ ...p, canUsePasskey: can }))).catch(() => {
|
|
5486
5575
|
});
|
|
5487
5576
|
}
|
|
5577
|
+
const clearPhase = useCallback3(() => setSocialAuth((p) => p.phase ? { ...p, phase: null } : p), []);
|
|
5488
5578
|
const signInWithPasskey = useCallback3(async () => {
|
|
5489
5579
|
const sdk = socialRef.current;
|
|
5490
5580
|
if (!sdk) throw new Error("Social sign-in not configured");
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5581
|
+
try {
|
|
5582
|
+
const result = await sdk.signInWithPasskey();
|
|
5583
|
+
applyResult(result);
|
|
5584
|
+
setSelectorOpen(false);
|
|
5585
|
+
return result;
|
|
5586
|
+
} catch (e) {
|
|
5587
|
+
clearPhase();
|
|
5588
|
+
throw e;
|
|
5589
|
+
}
|
|
5590
|
+
}, [clearPhase]);
|
|
5496
5591
|
const connectWithGoogle = useCallback3(async () => {
|
|
5497
5592
|
const sdk = socialRef.current;
|
|
5498
5593
|
if (!sdk) throw new Error("Social sign-in not configured");
|
|
@@ -5506,17 +5601,27 @@ function DecaneKit({ config, children }) {
|
|
|
5506
5601
|
const verifyEmailCode2 = useCallback3(async (email, code) => {
|
|
5507
5602
|
const sdk = socialRef.current;
|
|
5508
5603
|
if (!sdk) throw new Error("Social sign-in not configured");
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5604
|
+
try {
|
|
5605
|
+
const result = await sdk.verifyEmailCode(email, code);
|
|
5606
|
+
applyResult(result);
|
|
5607
|
+
setSelectorOpen(false);
|
|
5608
|
+
} catch (e) {
|
|
5609
|
+
clearPhase();
|
|
5610
|
+
throw e;
|
|
5611
|
+
}
|
|
5612
|
+
}, [clearPhase]);
|
|
5513
5613
|
const connectWithToken = useCallback3(async (token, opts) => {
|
|
5514
5614
|
const sdk = socialRef.current;
|
|
5515
5615
|
if (!sdk) throw new Error("Social sign-in not configured");
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5616
|
+
try {
|
|
5617
|
+
const result = await sdk.connectWithToken(token, opts);
|
|
5618
|
+
applyResult(result);
|
|
5619
|
+
setSelectorOpen(false);
|
|
5620
|
+
} catch (e) {
|
|
5621
|
+
clearPhase();
|
|
5622
|
+
throw e;
|
|
5623
|
+
}
|
|
5624
|
+
}, [clearPhase]);
|
|
5520
5625
|
const customAuthConfig = config?.social?.customAuth;
|
|
5521
5626
|
const connectWithCustomAuth = useCallback3(async () => {
|
|
5522
5627
|
if (!customAuthConfig) throw new Error("Custom auth not configured");
|
|
@@ -5526,14 +5631,21 @@ function DecaneKit({ config, children }) {
|
|
|
5526
5631
|
const socialUnlock = useCallback3(async () => {
|
|
5527
5632
|
const sdk = socialRef.current;
|
|
5528
5633
|
if (!sdk) return;
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5634
|
+
setSocialAuth((p) => ({ ...p, phase: "unlocking" }));
|
|
5635
|
+
try {
|
|
5636
|
+
await sdk.unlock();
|
|
5637
|
+
setSocialAuth((p) => ({
|
|
5638
|
+
...p,
|
|
5639
|
+
isUnlocked: sdk.isUnlocked(),
|
|
5640
|
+
sessionExpiresAt: sdk.sessionExpiresAt(),
|
|
5641
|
+
needsReconnect: false,
|
|
5642
|
+
phase: null
|
|
5643
|
+
}));
|
|
5644
|
+
} catch (e) {
|
|
5645
|
+
clearPhase();
|
|
5646
|
+
throw e;
|
|
5647
|
+
}
|
|
5648
|
+
}, [clearPhase]);
|
|
5537
5649
|
const socialDisconnect = useCallback3(async () => {
|
|
5538
5650
|
const sdk = socialRef.current;
|
|
5539
5651
|
if (!sdk) return;
|
|
@@ -5602,7 +5714,7 @@ function DecaneKit({ config, children }) {
|
|
|
5602
5714
|
[]
|
|
5603
5715
|
);
|
|
5604
5716
|
const networks = deriveNetworks(mode, config?.networks);
|
|
5605
|
-
return /* @__PURE__ */
|
|
5717
|
+
return /* @__PURE__ */ React5.createElement(
|
|
5606
5718
|
DecaneContext.Provider,
|
|
5607
5719
|
{
|
|
5608
5720
|
value: {
|
|
@@ -5640,7 +5752,7 @@ function DecaneKit({ config, children }) {
|
|
|
5640
5752
|
}
|
|
5641
5753
|
},
|
|
5642
5754
|
children,
|
|
5643
|
-
/* @__PURE__ */
|
|
5755
|
+
/* @__PURE__ */ React5.createElement(
|
|
5644
5756
|
WalletSelector,
|
|
5645
5757
|
{
|
|
5646
5758
|
provider: walletRef.current,
|
|
@@ -5661,7 +5773,7 @@ function DecaneKit({ config, children }) {
|
|
|
5661
5773
|
onCustomAuthSignIn: customAuthConfig ? connectWithCustomAuth : void 0
|
|
5662
5774
|
}
|
|
5663
5775
|
),
|
|
5664
|
-
/* @__PURE__ */
|
|
5776
|
+
/* @__PURE__ */ React5.createElement(
|
|
5665
5777
|
SocialWalletModal,
|
|
5666
5778
|
{
|
|
5667
5779
|
open: socialModalOpen,
|
|
@@ -5684,7 +5796,8 @@ function DecaneKit({ config, children }) {
|
|
|
5684
5796
|
rpcUrls: config?.social?.rpcUrls,
|
|
5685
5797
|
chains: config?.social?.chains
|
|
5686
5798
|
}
|
|
5687
|
-
)
|
|
5799
|
+
),
|
|
5800
|
+
/* @__PURE__ */ React5.createElement(WalletStatusOverlay, { phase: socialAuth.phase, theme })
|
|
5688
5801
|
);
|
|
5689
5802
|
}
|
|
5690
5803
|
function useDecaneContext() {
|
|
@@ -5698,7 +5811,7 @@ function useDecaneContext() {
|
|
|
5698
5811
|
}
|
|
5699
5812
|
|
|
5700
5813
|
// src/ui/hooks.ts
|
|
5701
|
-
import { useState as useState4, useEffect as
|
|
5814
|
+
import { useState as useState4, useEffect as useEffect5, useCallback as useCallback4 } from "react";
|
|
5702
5815
|
function useSocialAuth() {
|
|
5703
5816
|
const {
|
|
5704
5817
|
socialAuth,
|
|
@@ -5812,6 +5925,9 @@ function useSocialAuth() {
|
|
|
5812
5925
|
sessionExpiresAt: socialAuth.sessionExpiresAt,
|
|
5813
5926
|
// True when this device can skip the full sign-in and resume with a passkey.
|
|
5814
5927
|
canUsePasskey: socialAuth.canUsePasskey,
|
|
5928
|
+
// Long-running work in progress, for driving your own status UI.
|
|
5929
|
+
phase: socialAuth.phase,
|
|
5930
|
+
isCreatingWallet: socialAuth.phase === "creating",
|
|
5815
5931
|
// True when addresses are known (from a previous visit) but there's no
|
|
5816
5932
|
// live session — unlock() will always throw in this state (every
|
|
5817
5933
|
// unlock requires a fresh JWT, and JWTs are never persisted). Route
|
|
@@ -5943,6 +6059,10 @@ function useSocialWallet() {
|
|
|
5943
6059
|
// unlock requires a fresh JWT, and JWTs are never persisted). Route
|
|
5944
6060
|
// this into a real reconnect (signInWithGoogle / sendEmailCode), not unlock().
|
|
5945
6061
|
needsReconnect: socialAuth.needsReconnect,
|
|
6062
|
+
// Long-running work in progress ('creating' | 'unlocking' | null), for
|
|
6063
|
+
// driving your own status UI in addition to the SDK's built-in overlay.
|
|
6064
|
+
phase: socialAuth.phase,
|
|
6065
|
+
isCreatingWallet: socialAuth.phase === "creating",
|
|
5946
6066
|
// Modal
|
|
5947
6067
|
modalOpen: socialModalOpen,
|
|
5948
6068
|
openModal: openSocialModal,
|
|
@@ -5991,7 +6111,7 @@ function useSocialBalance(chain) {
|
|
|
5991
6111
|
setLoading(false);
|
|
5992
6112
|
}
|
|
5993
6113
|
}, [socialGetBalance, chain, socialAuth.addresses]);
|
|
5994
|
-
|
|
6114
|
+
useEffect5(() => {
|
|
5995
6115
|
let cancelled = false;
|
|
5996
6116
|
if (!socialAuth.addresses) {
|
|
5997
6117
|
setBalance(null);
|
|
@@ -6023,7 +6143,7 @@ function toDecaneError(err) {
|
|
|
6023
6143
|
function useDecane() {
|
|
6024
6144
|
const { provider, theme, setTheme } = useDecaneContext();
|
|
6025
6145
|
const [, forceUpdate] = useState4(0);
|
|
6026
|
-
|
|
6146
|
+
useEffect5(() => {
|
|
6027
6147
|
const refresh = () => forceUpdate((n) => n + 1);
|
|
6028
6148
|
const events = [
|
|
6029
6149
|
"connect",
|
|
@@ -6065,7 +6185,7 @@ function useChainSwitch() {
|
|
|
6065
6185
|
const [, forceUpdate] = useState4(0);
|
|
6066
6186
|
const [loading, setLoading] = useState4(false);
|
|
6067
6187
|
const [error, setError] = useState4(null);
|
|
6068
|
-
|
|
6188
|
+
useEffect5(() => {
|
|
6069
6189
|
const refresh = () => forceUpdate((n) => n + 1);
|
|
6070
6190
|
provider.on("connect", refresh);
|
|
6071
6191
|
provider.on("disconnect", refresh);
|