@abstraxn/signer-react 3.3.10 → 4.0.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/CHANGELOG.md +33 -0
- package/dist/src/ConnectButton.css.d.ts +2 -0
- package/dist/src/ConnectButton.css.js +1 -0
- package/dist/src/ConnectButton.d.ts +0 -1
- package/dist/src/ConnectButton.js +7 -6
- package/dist/src/ExternalWalletButtons.css.d.ts +2 -0
- package/dist/src/ExternalWalletButtons.css.js +1 -0
- package/dist/src/ExternalWalletButtons.d.ts +4 -1
- package/dist/src/ExternalWalletButtons.js +6 -1
- package/dist/src/WalletModal.css +2 -0
- package/dist/src/WalletModal.css.d.ts +2 -0
- package/dist/src/WalletModal.css.js +1 -0
- package/dist/src/WalletModal.d.ts +2 -2
- package/dist/src/WalletModal.js +113 -59
- package/dist/src/components/AbstraxnLogo.d.ts +17 -0
- package/dist/src/components/AbstraxnLogo.js +29 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +406 -338
- package/dist/src/components/AbstraxnProvider/useAbstraxnProviderBase.d.ts +7 -0
- package/dist/src/components/AbstraxnProvider/useAbstraxnProviderBase.js +9 -0
- package/dist/src/components/AbstraxnProvider/useWalletInitialization.js +41 -6
- package/dist/src/components/OnboardingUI/OnboardingUI.css +99 -4
- package/dist/src/components/OnboardingUI/OnboardingUI.css.d.ts +2 -0
- package/dist/src/components/OnboardingUI/OnboardingUI.css.js +1 -0
- package/dist/src/components/OnboardingUI/OnboardingUIReact.d.ts +0 -1
- package/dist/src/components/OnboardingUI/OnboardingUIReact.js +46 -19
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.d.ts +24 -1
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.js +348 -160
- package/dist/src/components/OnboardingUI/components/Divider.d.ts +7 -0
- package/dist/src/components/OnboardingUI/components/Divider.js +9 -0
- package/dist/src/components/OnboardingUI/components/EmailForm.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/EmailForm.js +1 -2
- package/dist/src/components/OnboardingUI/components/MfaForm.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/MfaForm.js +2 -3
- package/dist/src/components/OnboardingUI/components/Modal.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/Modal.js +12 -4
- package/dist/src/components/OnboardingUI/components/OtpForm.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/OtpForm.js +2 -3
- package/dist/src/components/OnboardingUI/components/PasskeyButton.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/PasskeyButton.js +2 -2
- package/dist/src/components/OnboardingUI/components/SocialButtons.d.ts +0 -1
- package/dist/src/components/OnboardingUI/components/SocialButtons.js +3 -3
- package/dist/src/components/OnboardingUI/onboardingShadowContainer.d.ts +9 -0
- package/dist/src/components/OnboardingUI/onboardingShadowContainer.js +36 -0
- package/dist/src/components/ShadowHost/ShadowHost.d.ts +18 -0
- package/dist/src/components/ShadowHost/ShadowHost.js +123 -0
- package/dist/src/components/ShadowHost/ShadowHostContext.d.ts +10 -0
- package/dist/src/components/ShadowHost/ShadowHostContext.js +14 -0
- package/dist/src/components/ShadowHost/index.d.ts +2 -0
- package/dist/src/components/ShadowHost/index.js +3 -0
- package/dist/src/components/WalletModal/components/ChainSelector.css +9 -0
- package/dist/src/components/WalletModal/components/ChainSelector.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ChainSelector.css.js +1 -0
- package/dist/src/components/WalletModal/components/ChainSelector.d.ts +0 -1
- package/dist/src/components/WalletModal/components/ChainSelector.js +78 -23
- package/dist/src/components/WalletModal/components/CodeInput.d.ts +12 -0
- package/dist/src/components/WalletModal/components/CodeInput.js +39 -0
- package/dist/src/components/WalletModal/components/ExportKeyModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ExportKeyModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ExportKeyModal.d.ts +0 -2
- package/dist/src/components/WalletModal/components/ExportKeyModal.js +2 -4
- package/dist/src/components/WalletModal/components/ExportWarningModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ExportWarningModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ExportWarningModal.d.ts +0 -2
- package/dist/src/components/WalletModal/components/ExportWarningModal.js +2 -4
- package/dist/src/components/WalletModal/components/ManageWalletModal.css +27 -1
- package/dist/src/components/WalletModal/components/ManageWalletModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ManageWalletModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ManageWalletModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/ManageWalletModal.js +66 -148
- package/dist/src/components/WalletModal/components/MfaVerifyModal.d.ts +15 -0
- package/dist/src/components/WalletModal/components/MfaVerifyModal.js +98 -0
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.css +2 -12
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/PreviewTransactionModal.js +0 -1
- package/dist/src/components/WalletModal/components/ReceiveModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/ReceiveModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/ReceiveModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/ReceiveModal.js +2 -2
- package/dist/src/components/WalletModal/components/SendModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/SendModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/SendModal.d.ts +5 -2
- package/dist/src/components/WalletModal/components/SendModal.js +25 -82
- package/dist/src/components/WalletModal/components/SignMfaModalHost.d.ts +1 -0
- package/dist/src/components/WalletModal/components/SignMfaModalHost.js +50 -0
- package/dist/src/components/WalletModal/components/SuccessModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/SuccessModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/SuccessModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/SuccessModal.js +0 -1
- package/dist/src/components/WalletModal/components/TokenSelectorModal.css.d.ts +2 -0
- package/dist/src/components/WalletModal/components/TokenSelectorModal.css.js +1 -0
- package/dist/src/components/WalletModal/components/TokenSelectorModal.d.ts +0 -1
- package/dist/src/components/WalletModal/components/TokenSelectorModal.js +0 -1
- package/dist/src/components/WalletModal/components/UserAvatar.js +2 -1
- package/dist/src/components/WalletModal/components/index.d.ts +3 -0
- package/dist/src/components/WalletModal/components/index.js +2 -0
- package/dist/src/components/WalletModal/hooks/useSendTransaction.js +18 -6
- package/dist/src/components/icons.d.ts +2 -0
- package/dist/src/components/icons.js +4 -0
- package/dist/src/hooks.d.ts +58 -3
- package/dist/src/hooks.js +172 -30
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/signMfaBridge.d.ts +7 -0
- package/dist/src/signMfaBridge.js +20 -0
- package/dist/src/types.d.ts +4 -0
- package/dist/src/utils/shadowFocus.d.ts +8 -0
- package/dist/src/utils/shadowFocus.js +15 -0
- package/dist/src/utils/shadowRegistry.d.ts +23 -0
- package/dist/src/utils/shadowRegistry.js +36 -0
- package/package.json +9 -4
|
@@ -4,22 +4,154 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
* This component contains all the wallet state management and operations
|
|
5
5
|
*/
|
|
6
6
|
import { useEffect, useState, useRef, useCallback, useMemo, } from "react";
|
|
7
|
-
import { AbstraxnWallet, AuthenticationError, } from "@abstraxn/signer-core";
|
|
7
|
+
import { AbstraxnWallet, AuthenticationError, SignMfaRequiredError, TURNKEY_SUPPORTED_CAIP2, NATIVE_ASSET_SENTINEL, chainIdToCaip2, isNativeAssetEntry, extractAssetAddress, } from "@abstraxn/signer-core";
|
|
8
8
|
import { OnboardingUIWeb } from "../OnboardingUI";
|
|
9
|
+
import { requestSignMfaCode } from "../../signMfaBridge";
|
|
9
10
|
import { useConnectionEffect, } from "wagmi";
|
|
10
11
|
import { parseEther, createPublicClient, http } from "viem";
|
|
11
|
-
import { ExternalWalletButtons, resetExternalWalletViewState, } from "../../ExternalWalletButtons";
|
|
12
|
+
import { ExternalWalletButtons, resetExternalWalletViewState, isExternalWalletListOpen, } from "../../ExternalWalletButtons";
|
|
12
13
|
import { EVM_CHAINS, SOLANA_CHAINS, getChainById, toCoreChain, } from "../../chains";
|
|
13
14
|
import { AbstraxnContext } from "./context";
|
|
14
15
|
import { isLinkAuthCallback } from "./utils";
|
|
15
16
|
import { hasActiveWalletConnectSession, hasPendingWalletConnectApproval, isWalletConnectConnector, patchWalletConnectProviderForMobile, rememberCurrentPageForWalletReturn, resumeWalletConnectRelayer, subscribeWalletConnectForegroundResume, syncWalletConnectDappRedirect, } from "../../walletConnectMobile";
|
|
17
|
+
import { SignMfaModalHost } from "../WalletModal/components/SignMfaModalHost";
|
|
16
18
|
/** Syncs wagmi disconnect to external wallet state; only rendered when wagmi is available (under WagmiProvider). */
|
|
17
19
|
function WagmiConnectionEffectSync({ onDisconnect, }) {
|
|
18
20
|
useConnectionEffect({ onDisconnect });
|
|
19
21
|
return null;
|
|
20
22
|
}
|
|
21
23
|
export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }) {
|
|
22
|
-
const { isInitialized, setIsInitialized, isConnected, setIsConnected, address, setAddress, user, setUser, whoami, setWhoami, chainId, setChainId, error, setError, loading, setLoading, resending, setResending, walletBalance, setWalletBalance, onboardingRef, otpIdRef, walletRef, googleCallbackHandledRef, twitterCallbackHandledRef, discordCallbackHandledRef, } = base;
|
|
24
|
+
const { isInitialized, setIsInitialized, isConnected, setIsConnected, address, setAddress, user, setUser, whoami, setWhoami, chainId, setChainId, error, setError, loading, setLoading, resending, setResending, walletBalance, setWalletBalance, tokenBalances, setTokenBalances, tokenBalancesLoading, setTokenBalancesLoading, tokenBalancesError, setTokenBalancesError, onboardingRef, otpIdRef, walletRef, googleCallbackHandledRef, twitterCallbackHandledRef, discordCallbackHandledRef, } = base;
|
|
25
|
+
const handleShowMoreWallets = useCallback(() => {
|
|
26
|
+
// Hide email and Google sections when "More wallets" is clicked
|
|
27
|
+
const onboardingAny = onboardingRef.current;
|
|
28
|
+
if (onboardingAny?.emailForm) {
|
|
29
|
+
onboardingAny.emailForm.style.display = "none";
|
|
30
|
+
}
|
|
31
|
+
if (onboardingAny?.googleButton) {
|
|
32
|
+
onboardingAny.googleButton.style.display = "none";
|
|
33
|
+
}
|
|
34
|
+
// Hide Discord and X (Twitter) buttons when wallet selection screen is shown
|
|
35
|
+
if (onboardingAny?.discordButton) {
|
|
36
|
+
onboardingAny.discordButton.style.display = "none";
|
|
37
|
+
}
|
|
38
|
+
if (onboardingAny?.twitterButton) {
|
|
39
|
+
onboardingAny.twitterButton.style.display = "none";
|
|
40
|
+
}
|
|
41
|
+
// Hide social grid if it exists
|
|
42
|
+
if (onboardingAny?.socialGrid) {
|
|
43
|
+
onboardingAny.socialGrid.style.display = "none";
|
|
44
|
+
}
|
|
45
|
+
// Extra guard: hide any social icon buttons by class
|
|
46
|
+
if (onboardingAny?.rootElement) {
|
|
47
|
+
onboardingAny.rootElement
|
|
48
|
+
.querySelectorAll(".onboarding-button-social-icon, .onboarding-button-social")
|
|
49
|
+
.forEach((el) => {
|
|
50
|
+
el.style.display = "none";
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Hide all passkey elements when wallet selection screen is shown
|
|
54
|
+
if (onboardingAny?.passkeyLoginButton) {
|
|
55
|
+
onboardingAny.passkeyLoginButton.style.display = "none";
|
|
56
|
+
}
|
|
57
|
+
if (onboardingAny?.passkeySignupLink) {
|
|
58
|
+
onboardingAny.passkeySignupLink.style.display = "none";
|
|
59
|
+
}
|
|
60
|
+
if (onboardingAny?.passkeyErrorElement) {
|
|
61
|
+
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
62
|
+
}
|
|
63
|
+
if (onboardingAny?.passkeyDivider) {
|
|
64
|
+
onboardingAny.passkeyDivider.style.display = "none";
|
|
65
|
+
}
|
|
66
|
+
if (onboardingAny?.externalWalletDivider) {
|
|
67
|
+
onboardingAny.externalWalletDivider.style.display = "none";
|
|
68
|
+
}
|
|
69
|
+
// Also hide the divider between email and Google if it exists
|
|
70
|
+
if (onboardingAny?.divider) {
|
|
71
|
+
onboardingAny.divider.style.display = "none";
|
|
72
|
+
}
|
|
73
|
+
}, [onboardingRef]);
|
|
74
|
+
const handleHideMoreWallets = useCallback(() => {
|
|
75
|
+
// Show email and Google sections when back is clicked
|
|
76
|
+
const onboardingAny = onboardingRef.current;
|
|
77
|
+
const authMethods = onboardingAny?.config?.authMethods || [
|
|
78
|
+
"otp",
|
|
79
|
+
"google",
|
|
80
|
+
];
|
|
81
|
+
const showEmail = authMethods.includes("otp");
|
|
82
|
+
const showGoogle = authMethods.includes("google");
|
|
83
|
+
const showTwitter = authMethods.includes("twitter");
|
|
84
|
+
const showDiscord = authMethods.includes("discord");
|
|
85
|
+
const showPasskey = authMethods.includes("passkey");
|
|
86
|
+
if (onboardingAny?.emailForm) {
|
|
87
|
+
onboardingAny.emailForm.style.display = showEmail ? "" : "none";
|
|
88
|
+
}
|
|
89
|
+
if (onboardingAny?.googleButton) {
|
|
90
|
+
onboardingAny.googleButton.style.display = showGoogle
|
|
91
|
+
? ""
|
|
92
|
+
: "none";
|
|
93
|
+
}
|
|
94
|
+
// Show Discord and X (Twitter) buttons if enabled
|
|
95
|
+
if (onboardingAny?.discordButton) {
|
|
96
|
+
onboardingAny.discordButton.style.display = showDiscord
|
|
97
|
+
? ""
|
|
98
|
+
: "none";
|
|
99
|
+
}
|
|
100
|
+
if (onboardingAny?.twitterButton) {
|
|
101
|
+
onboardingAny.twitterButton.style.display = showTwitter
|
|
102
|
+
? ""
|
|
103
|
+
: "none";
|
|
104
|
+
}
|
|
105
|
+
// Show social grid if it exists and social methods are enabled
|
|
106
|
+
if (onboardingAny?.socialGrid) {
|
|
107
|
+
const hasSocialMethods = showGoogle || showTwitter || showDiscord;
|
|
108
|
+
onboardingAny.socialGrid.style.display = hasSocialMethods
|
|
109
|
+
? ""
|
|
110
|
+
: "none";
|
|
111
|
+
}
|
|
112
|
+
// Extra guard: restore social icon buttons by class based on flags
|
|
113
|
+
if (onboardingAny?.rootElement) {
|
|
114
|
+
const hasSocialMethods = showGoogle || showTwitter || showDiscord;
|
|
115
|
+
onboardingAny.rootElement
|
|
116
|
+
.querySelectorAll(".onboarding-button-social-icon, .onboarding-button-social")
|
|
117
|
+
.forEach((el) => {
|
|
118
|
+
el.style.display = hasSocialMethods
|
|
119
|
+
? ""
|
|
120
|
+
: "none";
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// Show passkey controls if enabled
|
|
124
|
+
if (onboardingAny?.passkeyLoginButton) {
|
|
125
|
+
onboardingAny.passkeyLoginButton.style.display = showPasskey
|
|
126
|
+
? ""
|
|
127
|
+
: "none";
|
|
128
|
+
}
|
|
129
|
+
if (onboardingAny?.passkeySignupLink) {
|
|
130
|
+
onboardingAny.passkeySignupLink.style.display = showPasskey
|
|
131
|
+
? ""
|
|
132
|
+
: "none";
|
|
133
|
+
}
|
|
134
|
+
if (onboardingAny?.passkeyErrorElement) {
|
|
135
|
+
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
136
|
+
}
|
|
137
|
+
// Show passkey divider if passkey is enabled and there are other auth methods
|
|
138
|
+
if (onboardingAny?.passkeyDivider) {
|
|
139
|
+
onboardingAny.passkeyDivider.style.display =
|
|
140
|
+
showPasskey &&
|
|
141
|
+
(showEmail || showGoogle || showTwitter || showDiscord)
|
|
142
|
+
? ""
|
|
143
|
+
: "none";
|
|
144
|
+
}
|
|
145
|
+
// Show divider between email and social methods if both are enabled
|
|
146
|
+
if (onboardingAny?.divider) {
|
|
147
|
+
const hasSocialMethods = showGoogle || showTwitter || showDiscord;
|
|
148
|
+
onboardingAny.divider.style.display =
|
|
149
|
+
showEmail && hasSocialMethods ? "" : "none";
|
|
150
|
+
}
|
|
151
|
+
if (onboardingAny?.externalWalletDivider) {
|
|
152
|
+
onboardingAny.externalWalletDivider.style.display = "";
|
|
153
|
+
}
|
|
154
|
+
}, [onboardingRef]);
|
|
23
155
|
const externalWalletsEnabled = config.externalWallets?.enabled ?? false;
|
|
24
156
|
// Keep a ref to avoid re-creating callbacks when toggling config (prevents flicker)
|
|
25
157
|
const externalWalletsEnabledRef = useRef(externalWalletsEnabled);
|
|
@@ -249,7 +381,13 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
249
381
|
const showEmail = authMethods.includes("otp");
|
|
250
382
|
const showGoogle = authMethods.includes("google");
|
|
251
383
|
const hasEmailOrGoogle = showEmail || showGoogle;
|
|
252
|
-
|
|
384
|
+
// Wallet list open: email is hidden — never re-show the "or" divider.
|
|
385
|
+
if (isExternalWalletListOpen()) {
|
|
386
|
+
if (onboardingAny.externalWalletDivider) {
|
|
387
|
+
onboardingAny.externalWalletDivider.style.display = "none";
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else if (onboardingAny.externalWalletDivider && hasEmailOrGoogle) {
|
|
253
391
|
onboardingAny.externalWalletDivider.style.display = "";
|
|
254
392
|
}
|
|
255
393
|
else if (onboardingAny.externalWalletDivider) {
|
|
@@ -375,9 +513,30 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
375
513
|
]); // Re-run if wagmi state changes
|
|
376
514
|
// Initialize wallet
|
|
377
515
|
useEffect(() => {
|
|
378
|
-
// If wallet already exists (from previous mount), reuse it to prevent flicker
|
|
516
|
+
// If wallet already exists (from previous mount), reuse it to prevent flicker.
|
|
517
|
+
// StrictMode still destroys OnboardingUIWeb in cleanup — rebuild its shadow
|
|
518
|
+
// tree here so the OAuth success loader can paint again while Mount1's
|
|
519
|
+
// in-flight callback finishes.
|
|
379
520
|
if (walletRef.current) {
|
|
380
|
-
|
|
521
|
+
const onboarding = onboardingRef.current;
|
|
522
|
+
if (onboarding && !onboarding.hasLiveShadow()) {
|
|
523
|
+
onboarding.init();
|
|
524
|
+
if (typeof window !== "undefined") {
|
|
525
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
526
|
+
const hasSuccess = urlParams.get("success") === "true";
|
|
527
|
+
const mfaRequired = urlParams.get("mfaRequired") === "true";
|
|
528
|
+
if (hasSuccess &&
|
|
529
|
+
!mfaRequired &&
|
|
530
|
+
!isLinkAuthCallback(urlParams)) {
|
|
531
|
+
onboarding.showLoadingModal();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return () => {
|
|
536
|
+
if (onboardingRef.current) {
|
|
537
|
+
onboardingRef.current.destroy();
|
|
538
|
+
}
|
|
539
|
+
};
|
|
381
540
|
}
|
|
382
541
|
// Compute supported chains from chain config (outside useMemo since we're in useEffect)
|
|
383
542
|
// This should include ALL chains that might be shown in the UI (availableChains)
|
|
@@ -545,10 +704,21 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
545
704
|
walletInstance.on("chainChanged", (newChainId) => {
|
|
546
705
|
setChainId(newChainId);
|
|
547
706
|
});
|
|
548
|
-
// Initialize OnboardingUI only if not already created (prevents flicker on config change)
|
|
549
|
-
|
|
707
|
+
// Initialize OnboardingUI only if not already created (prevents flicker on config change).
|
|
708
|
+
// A destroyed StrictMode instance leaves a non-null ref with no live shadow — treat that
|
|
709
|
+
// as "not created" so we rebuild instead of skipping OAuth loader setup.
|
|
710
|
+
if (onboardingRef.current?.hasLiveShadow()) {
|
|
550
711
|
return;
|
|
551
712
|
}
|
|
713
|
+
if (onboardingRef.current) {
|
|
714
|
+
try {
|
|
715
|
+
onboardingRef.current.destroy();
|
|
716
|
+
}
|
|
717
|
+
catch {
|
|
718
|
+
// Ignore — instance may already be partially torn down.
|
|
719
|
+
}
|
|
720
|
+
onboardingRef.current = null;
|
|
721
|
+
}
|
|
552
722
|
const uiConfig = config.ui || {};
|
|
553
723
|
const onboarding = new OnboardingUIWeb({
|
|
554
724
|
logo: uiConfig.logo,
|
|
@@ -889,16 +1059,10 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
889
1059
|
resetExternalWalletViewState();
|
|
890
1060
|
},
|
|
891
1061
|
}, externalWalletsEnabled); // Pass externalWalletsEnabled as second parameter
|
|
892
|
-
//
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
const style = document.createElement("style");
|
|
897
|
-
style.id = styleId;
|
|
898
|
-
style.textContent = uiConfig.customCSS;
|
|
899
|
-
document.head.appendChild(style);
|
|
900
|
-
}
|
|
901
|
-
}
|
|
1062
|
+
// Note: customCSS is injected by OnboardingUIWeb itself (already threaded
|
|
1063
|
+
// into its constructor config above as `customCSS: uiConfig.customCSS`),
|
|
1064
|
+
// inside its own shadow container — this used to be duplicated here via
|
|
1065
|
+
// a separate document.head injection, which is now redundant and removed.
|
|
902
1066
|
const hasAuthParams = (params) => params.get("success") === "true" ||
|
|
903
1067
|
params.get("error") ||
|
|
904
1068
|
params.get("code") ||
|
|
@@ -932,6 +1096,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
932
1096
|
// Hide immediately - use synchronous approach to prevent flicker
|
|
933
1097
|
// Only hide if NOT handling a callback
|
|
934
1098
|
const onboardingAny = onboarding;
|
|
1099
|
+
let oauthLoaderTimeout = null;
|
|
935
1100
|
if (!shouldKeepOpen && onboardingAny.modalOverlay) {
|
|
936
1101
|
// Hide immediately without delay to prevent flicker
|
|
937
1102
|
onboardingAny.modalOverlay.classList.remove("onboarding-modal-open");
|
|
@@ -943,9 +1108,9 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
943
1108
|
// Skip when mfaRequired=true so MFA verification screen can show instead.
|
|
944
1109
|
const mfaRequired = urlParams.get("mfaRequired") === "true";
|
|
945
1110
|
if (!mfaRequired) {
|
|
946
|
-
setTimeout(() => {
|
|
1111
|
+
oauthLoaderTimeout = setTimeout(() => {
|
|
947
1112
|
const onboardingInstance = onboardingRef.current;
|
|
948
|
-
if (onboardingInstance
|
|
1113
|
+
if (onboardingInstance) {
|
|
949
1114
|
onboardingInstance.showLoadingModal();
|
|
950
1115
|
}
|
|
951
1116
|
}, 150);
|
|
@@ -1283,8 +1448,14 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1283
1448
|
});
|
|
1284
1449
|
}
|
|
1285
1450
|
return () => {
|
|
1451
|
+
if (oauthLoaderTimeout !== null) {
|
|
1452
|
+
clearTimeout(oauthLoaderTimeout);
|
|
1453
|
+
}
|
|
1286
1454
|
if (onboardingRef.current) {
|
|
1287
1455
|
onboardingRef.current.destroy();
|
|
1456
|
+
// Keep the instance in the ref so StrictMode remount can call init() on the
|
|
1457
|
+
// same object (preserving auth callbacks / config). destroy() already clears
|
|
1458
|
+
// the shadow tree; the walletRef early-return path re-inits it.
|
|
1288
1459
|
}
|
|
1289
1460
|
};
|
|
1290
1461
|
}, []); // Only run once on mount
|
|
@@ -1312,9 +1483,16 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1312
1483
|
}
|
|
1313
1484
|
if (onboardingRef.current) {
|
|
1314
1485
|
const onboarding = onboardingRef.current;
|
|
1315
|
-
// Re-initialize if destroyed
|
|
1486
|
+
// Re-initialize if destroyed.
|
|
1487
|
+
// Uses `.isConnected`, not `document.body.contains(...)`: the modal
|
|
1488
|
+
// overlay now lives inside a shadow root, and `contains()` walks the
|
|
1489
|
+
// tree via `parentNode` — a ShadowRoot's `parentNode` is always null,
|
|
1490
|
+
// so `contains()` would report "not attached" even when the modal is
|
|
1491
|
+
// genuinely still live, forcing a needless re-init on every call.
|
|
1492
|
+
// `isConnected` is defined in terms of the shadow-including root, so it
|
|
1493
|
+
// correctly reports true across shadow boundaries.
|
|
1316
1494
|
if (!onboarding.modalOverlay ||
|
|
1317
|
-
!
|
|
1495
|
+
!onboarding.modalOverlay.isConnected) {
|
|
1318
1496
|
onboarding.init();
|
|
1319
1497
|
// Wait for init to complete
|
|
1320
1498
|
setTimeout(() => {
|
|
@@ -1349,7 +1527,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1349
1527
|
const showEmail = authMethods.includes("otp");
|
|
1350
1528
|
const showGoogle = authMethods.includes("google");
|
|
1351
1529
|
const hasEmailOrGoogle = showEmail || showGoogle;
|
|
1352
|
-
if (
|
|
1530
|
+
if (isExternalWalletListOpen()) {
|
|
1531
|
+
if (onboarding.externalWalletDivider) {
|
|
1532
|
+
onboarding.externalWalletDivider.style.display = "none";
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
else if (onboarding.externalWalletDivider && hasEmailOrGoogle) {
|
|
1353
1536
|
onboarding.externalWalletDivider.style.display = "";
|
|
1354
1537
|
}
|
|
1355
1538
|
else if (onboarding.externalWalletDivider) {
|
|
@@ -1444,7 +1627,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
1444
1627
|
const showEmail = authMethods.includes("otp");
|
|
1445
1628
|
const showGoogle = authMethods.includes("google");
|
|
1446
1629
|
const hasEmailOrGoogle = showEmail || showGoogle;
|
|
1447
|
-
if (
|
|
1630
|
+
if (isExternalWalletListOpen()) {
|
|
1631
|
+
if (onboarding.externalWalletDivider) {
|
|
1632
|
+
onboarding.externalWalletDivider.style.display = "none";
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
else if (onboarding.externalWalletDivider && hasEmailOrGoogle) {
|
|
1448
1636
|
onboarding.externalWalletDivider.style.display = "";
|
|
1449
1637
|
}
|
|
1450
1638
|
else if (onboarding.externalWalletDivider) {
|
|
@@ -2491,7 +2679,27 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
2491
2679
|
if (!walletRef.current?.isConnected) {
|
|
2492
2680
|
throw new Error("Wallet not connected");
|
|
2493
2681
|
}
|
|
2494
|
-
|
|
2682
|
+
const performDisable = () => walletRef.current.disableMfaWithSignedPayload();
|
|
2683
|
+
try {
|
|
2684
|
+
return await performDisable();
|
|
2685
|
+
}
|
|
2686
|
+
catch (error) {
|
|
2687
|
+
// Safety net: if sign MFA was not cleared (or expired between verify and confirm),
|
|
2688
|
+
// open the shared sign-MFA modal, verify-sign, then retry once.
|
|
2689
|
+
const isSignMfaRequired = error instanceof SignMfaRequiredError ||
|
|
2690
|
+
error?.code === "SIGN_MFA_REQUIRED" ||
|
|
2691
|
+
(typeof error?.message === "string" &&
|
|
2692
|
+
error.message.includes("SIGN_MFA_REQUIRED"));
|
|
2693
|
+
if (!isSignMfaRequired) {
|
|
2694
|
+
throw error;
|
|
2695
|
+
}
|
|
2696
|
+
const code = await requestSignMfaCode();
|
|
2697
|
+
const verifyResponse = await walletRef.current.verifySignMfa(code);
|
|
2698
|
+
if (!verifyResponse?.verified) {
|
|
2699
|
+
throw new Error("Incorrect MFA code. Please try again.");
|
|
2700
|
+
}
|
|
2701
|
+
return await performDisable();
|
|
2702
|
+
}
|
|
2495
2703
|
}, []);
|
|
2496
2704
|
const [mfaStatus, setMfaStatus] = useState(null);
|
|
2497
2705
|
const [mfaStatusLoading, setMfaStatusLoading] = useState(false);
|
|
@@ -3392,44 +3600,153 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3392
3600
|
}
|
|
3393
3601
|
return map;
|
|
3394
3602
|
}, [config.chains]);
|
|
3395
|
-
//
|
|
3603
|
+
// Guards against overlapping concurrent fetches for the same address+chain (e.g. if
|
|
3604
|
+
// multiple callers trigger a refetch in quick succession) - a defense-in-depth measure
|
|
3605
|
+
// on top of the effect triggers being keyed off primitives rather than callback identity.
|
|
3606
|
+
const balanceFetchInFlightKeyRef = useRef(null);
|
|
3607
|
+
// Fetch native balance + full token list for the Abstraxn wallet (not external wallet)
|
|
3608
|
+
// in one combined refresh - reusable for on-demand refetch. Turnkey is called at most
|
|
3609
|
+
// once per refresh; native-balance extraction and token-list mapping are independently
|
|
3610
|
+
// try/caught so a failure in one cannot corrupt the other (see plan review point D).
|
|
3396
3611
|
const refetchWalletBalance = useCallback(async () => {
|
|
3397
3612
|
if (isExternalWalletConnected || !address || !currentChainId) {
|
|
3398
3613
|
setWalletBalance(null);
|
|
3614
|
+
setTokenBalances([]);
|
|
3615
|
+
setTokenBalancesError(null);
|
|
3616
|
+
return;
|
|
3617
|
+
}
|
|
3618
|
+
const fetchKey = `${address}:${currentChainId}`;
|
|
3619
|
+
if (balanceFetchInFlightKeyRef.current === fetchKey) {
|
|
3399
3620
|
return;
|
|
3400
3621
|
}
|
|
3622
|
+
balanceFetchInFlightKeyRef.current = fetchKey;
|
|
3401
3623
|
try {
|
|
3402
3624
|
const currentChain = getChainById(currentChainId) || customChainsById.get(currentChainId);
|
|
3403
3625
|
if (!currentChain || currentChain.type !== "evm") {
|
|
3404
3626
|
setWalletBalance(null);
|
|
3627
|
+
setTokenBalances([]);
|
|
3628
|
+
setTokenBalancesError(null);
|
|
3405
3629
|
return;
|
|
3406
3630
|
}
|
|
3407
|
-
const
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3631
|
+
const fetchRpcNativeBalance = async () => {
|
|
3632
|
+
const publicClient = createPublicClient({
|
|
3633
|
+
chain: {
|
|
3634
|
+
id: currentChain.id,
|
|
3635
|
+
name: currentChain.name,
|
|
3636
|
+
nativeCurrency: currentChain.nativeCurrency,
|
|
3637
|
+
rpcUrls: {
|
|
3638
|
+
default: {
|
|
3639
|
+
http: [currentChain.rpcUrl],
|
|
3640
|
+
},
|
|
3415
3641
|
},
|
|
3416
3642
|
},
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3643
|
+
transport: http(currentChain.rpcUrl),
|
|
3644
|
+
});
|
|
3645
|
+
return await publicClient.getBalance({ address: address });
|
|
3646
|
+
};
|
|
3647
|
+
const caip2 = chainIdToCaip2(currentChainId, TURNKEY_SUPPORTED_CAIP2);
|
|
3648
|
+
const wallet = walletRef.current;
|
|
3649
|
+
if (caip2 && wallet) {
|
|
3650
|
+
setTokenBalancesLoading(true);
|
|
3651
|
+
let entries = [];
|
|
3652
|
+
let turnkeyCallFailed = false;
|
|
3653
|
+
try {
|
|
3654
|
+
entries = await wallet.getTurnkeyBalances(caip2, address);
|
|
3655
|
+
}
|
|
3656
|
+
catch (error) {
|
|
3657
|
+
turnkeyCallFailed = true;
|
|
3658
|
+
console.warn("Turnkey balance fetch failed, falling back to RPC:", error);
|
|
3659
|
+
}
|
|
3660
|
+
if (!turnkeyCallFailed) {
|
|
3661
|
+
// Native balance extraction - its own try/catch, independent of the token list.
|
|
3662
|
+
try {
|
|
3663
|
+
const nativeEntry = entries.find((entry) => isNativeAssetEntry({ caip19: entry.caip19, symbol: entry.symbol, decimals: entry.decimals }, currentChain.nativeCurrency));
|
|
3664
|
+
setWalletBalance(nativeEntry?.balance !== undefined ? BigInt(nativeEntry.balance) : null);
|
|
3665
|
+
}
|
|
3666
|
+
catch (error) {
|
|
3667
|
+
console.error("Failed to extract native balance from Turnkey response:", error);
|
|
3668
|
+
setWalletBalance(null);
|
|
3669
|
+
}
|
|
3670
|
+
// Token list mapping - its own try/catch, per-entry skip on parse failure.
|
|
3671
|
+
try {
|
|
3672
|
+
const tokens = [];
|
|
3673
|
+
for (const entry of entries) {
|
|
3674
|
+
try {
|
|
3675
|
+
const isNative = isNativeAssetEntry({ caip19: entry.caip19, symbol: entry.symbol, decimals: entry.decimals }, currentChain.nativeCurrency);
|
|
3676
|
+
const tokenAddress = isNative
|
|
3677
|
+
? NATIVE_ASSET_SENTINEL
|
|
3678
|
+
: extractAssetAddress({ caip19: entry.caip19 });
|
|
3679
|
+
if (!isNative && tokenAddress === undefined) {
|
|
3680
|
+
console.warn("Skipping unrecognized asset in balance list:", entry.caip19);
|
|
3681
|
+
continue;
|
|
3682
|
+
}
|
|
3683
|
+
tokens.push({
|
|
3684
|
+
address: tokenAddress,
|
|
3685
|
+
symbol: entry.symbol ?? "",
|
|
3686
|
+
name: entry.name ?? entry.symbol ?? "",
|
|
3687
|
+
decimals: entry.decimals ?? 18,
|
|
3688
|
+
balance: entry.balance !== undefined ? BigInt(entry.balance) : 0n,
|
|
3689
|
+
isNative,
|
|
3690
|
+
});
|
|
3691
|
+
}
|
|
3692
|
+
catch (entryError) {
|
|
3693
|
+
console.warn("Skipping malformed balance entry:", entryError);
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
setTokenBalances(tokens);
|
|
3697
|
+
setTokenBalancesError(null);
|
|
3698
|
+
}
|
|
3699
|
+
catch (error) {
|
|
3700
|
+
setTokenBalancesError(error instanceof Error ? error : new Error("Failed to load token balances"));
|
|
3701
|
+
}
|
|
3702
|
+
finally {
|
|
3703
|
+
setTokenBalancesLoading(false);
|
|
3704
|
+
}
|
|
3705
|
+
return;
|
|
3706
|
+
}
|
|
3707
|
+
setTokenBalancesLoading(false);
|
|
3708
|
+
}
|
|
3709
|
+
// Not Turnkey-covered, or the Turnkey call itself failed - fall back to RPC for
|
|
3710
|
+
// native balance, and mirror it as a single native-only token list entry so both
|
|
3711
|
+
// stay consistent with each other.
|
|
3712
|
+
try {
|
|
3713
|
+
const balance = await fetchRpcNativeBalance();
|
|
3714
|
+
setWalletBalance(balance);
|
|
3715
|
+
setTokenBalances([
|
|
3716
|
+
{
|
|
3717
|
+
address: NATIVE_ASSET_SENTINEL,
|
|
3718
|
+
symbol: currentChain.nativeCurrency.symbol,
|
|
3719
|
+
name: currentChain.nativeCurrency.name,
|
|
3720
|
+
decimals: currentChain.nativeCurrency.decimals,
|
|
3721
|
+
balance,
|
|
3722
|
+
isNative: true,
|
|
3723
|
+
},
|
|
3724
|
+
]);
|
|
3725
|
+
setTokenBalancesError(null);
|
|
3726
|
+
}
|
|
3727
|
+
catch (error) {
|
|
3728
|
+
console.error("Failed to fetch balance:", error);
|
|
3729
|
+
setWalletBalance(null);
|
|
3730
|
+
setTokenBalancesError(error instanceof Error ? error : new Error("Failed to load balance"));
|
|
3731
|
+
}
|
|
3428
3732
|
}
|
|
3429
|
-
|
|
3733
|
+
finally {
|
|
3734
|
+
if (balanceFetchInFlightKeyRef.current === fetchKey) {
|
|
3735
|
+
balanceFetchInFlightKeyRef.current = null;
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
}, [address, currentChainId, isExternalWalletConnected, customChainsById, walletRef]);
|
|
3739
|
+
const refetchTokenBalances = refetchWalletBalance;
|
|
3740
|
+
// Trigger on the actual primitives that should cause a refetch - not on
|
|
3741
|
+
// refetchWalletBalance's own identity, which can churn on unrelated re-renders
|
|
3742
|
+
// (e.g. if the consuming app passes `config` as a fresh object/array literal every
|
|
3743
|
+
// render, customChainsById's memo recomputes and gives this callback a new identity
|
|
3744
|
+
// even though nothing relevant changed). Depending on the callback there caused a
|
|
3745
|
+
// continuous refetch loop instead of "once per real change".
|
|
3746
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3430
3747
|
useEffect(() => {
|
|
3431
3748
|
refetchWalletBalance();
|
|
3432
|
-
}, [
|
|
3749
|
+
}, [address, currentChainId, isExternalWalletConnected]);
|
|
3433
3750
|
// Single refetch for UI: Abstraxn wallet = RPC call, external wallet = wagmi refetch
|
|
3434
3751
|
const refetchBalance = useCallback(async () => {
|
|
3435
3752
|
if (isExternalWalletConnected && wagmiBalance?.refetch) {
|
|
@@ -3521,15 +3838,19 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3521
3838
|
}, [currentChainId, customChainsById]);
|
|
3522
3839
|
// Enhanced switchChain that works for both EVM and Solana
|
|
3523
3840
|
const switchChainEnhanced = useCallback(async (targetChainId) => {
|
|
3841
|
+
console.log("[switchChainEnhanced] called with", targetChainId);
|
|
3524
3842
|
if (!walletRef.current) {
|
|
3843
|
+
console.log("[switchChainEnhanced] aborting: wallet not initialized");
|
|
3525
3844
|
throw new Error("Wallet not initialized");
|
|
3526
3845
|
}
|
|
3527
3846
|
// Check if chain is in availableChains (user-configured chains)
|
|
3528
3847
|
const targetChainInAvailable = availableChains?.find((c) => c.id === targetChainId);
|
|
3848
|
+
console.log("[switchChainEnhanced] targetChainInAvailable:", targetChainInAvailable, "availableChains ids:", availableChains?.map((c) => c.id));
|
|
3529
3849
|
if (!targetChainInAvailable) {
|
|
3530
3850
|
throw new Error(`Chain with ID ${targetChainId} is not available. Please configure it in your SDK setup.`);
|
|
3531
3851
|
}
|
|
3532
3852
|
const targetChain = getChainById(targetChainId) || customChainsById.get(targetChainId);
|
|
3853
|
+
console.log("[switchChainEnhanced] resolved targetChain:", targetChain);
|
|
3533
3854
|
if (!targetChain) {
|
|
3534
3855
|
throw new Error(`Chain with ID ${targetChainId} is not supported`);
|
|
3535
3856
|
}
|
|
@@ -3539,21 +3860,27 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3539
3860
|
if (targetChain.type === "evm") {
|
|
3540
3861
|
// For EVM chains, use the existing switchChain
|
|
3541
3862
|
if (isExternalWalletConnected && wagmiSwitchChain) {
|
|
3863
|
+
console.log("[switchChainEnhanced] external wallet path - calling wagmi switchChainAsync");
|
|
3542
3864
|
// External wallet - use wagmi switchChain
|
|
3543
3865
|
await wagmiSwitchChain.switchChainAsync({ chainId: targetChainId });
|
|
3544
3866
|
setExternalWalletChainId(targetChainId);
|
|
3867
|
+
console.log("[switchChainEnhanced] wagmi switchChainAsync resolved");
|
|
3545
3868
|
}
|
|
3546
3869
|
else {
|
|
3870
|
+
console.log("[switchChainEnhanced] embedded wallet path - calling switchChain()");
|
|
3547
3871
|
// Abstraxn wallet - try to switch, but if chain is not in wallet's supportedChains,
|
|
3548
3872
|
// we'll update the state directly (for chains that are in availableChains but not in wallet config)
|
|
3549
3873
|
try {
|
|
3550
3874
|
await switchChain(targetChainId);
|
|
3875
|
+
console.log("[switchChainEnhanced] switchChain() resolved without throwing");
|
|
3551
3876
|
}
|
|
3552
3877
|
catch (switchErr) {
|
|
3878
|
+
console.log("[switchChainEnhanced] switchChain() threw:", switchErr?.message, switchErr);
|
|
3553
3879
|
// If the wallet doesn't support this chain, but it's in availableChains,
|
|
3554
3880
|
// we can still update the state to allow UI to work
|
|
3555
3881
|
if (switchErr?.message?.includes("not supported") &&
|
|
3556
3882
|
targetChainInAvailable) {
|
|
3883
|
+
console.log("[switchChainEnhanced] recovering via direct setChainId fallback");
|
|
3557
3884
|
// Update chainId state directly for chains in availableChains
|
|
3558
3885
|
setChainId(targetChainId);
|
|
3559
3886
|
// Emit chainChanged event if wallet supports it
|
|
@@ -3563,6 +3890,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3563
3890
|
}
|
|
3564
3891
|
}
|
|
3565
3892
|
else {
|
|
3893
|
+
console.log("[switchChainEnhanced] NOT recovering - rethrowing");
|
|
3566
3894
|
throw switchErr;
|
|
3567
3895
|
}
|
|
3568
3896
|
}
|
|
@@ -3576,10 +3904,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3576
3904
|
}
|
|
3577
3905
|
// Update chainId state
|
|
3578
3906
|
if (!isExternalWalletConnected) {
|
|
3907
|
+
console.log("[switchChainEnhanced] final setChainId call with", targetChainId);
|
|
3579
3908
|
setChainId(targetChainId);
|
|
3580
3909
|
}
|
|
3581
3910
|
}
|
|
3582
3911
|
catch (err) {
|
|
3912
|
+
console.log("[switchChainEnhanced] caught at top level:", err);
|
|
3583
3913
|
const error = err instanceof Error
|
|
3584
3914
|
? err
|
|
3585
3915
|
: new Error(`Failed to switch to chain ${targetChainId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -3800,6 +4130,10 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3800
4130
|
// Balance (for Abstraxn wallet)
|
|
3801
4131
|
walletBalance: !isExternalWalletConnected ? walletBalance : undefined,
|
|
3802
4132
|
refetchBalance,
|
|
4133
|
+
tokenBalances: !isExternalWalletConnected ? tokenBalances : [],
|
|
4134
|
+
tokenBalancesLoading,
|
|
4135
|
+
tokenBalancesError,
|
|
4136
|
+
refetchTokenBalances,
|
|
3803
4137
|
// Connection type
|
|
3804
4138
|
connectionType,
|
|
3805
4139
|
// Pre-fill email for email-OTP flow
|
|
@@ -3846,7 +4180,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3846
4180
|
const showEmail = authMethods.includes("otp");
|
|
3847
4181
|
const showGoogle = authMethods.includes("google");
|
|
3848
4182
|
const hasEmailOrGoogle = showEmail || showGoogle;
|
|
3849
|
-
if (
|
|
4183
|
+
if (isExternalWalletListOpen()) {
|
|
4184
|
+
if (onboardingAny.externalWalletDivider) {
|
|
4185
|
+
onboardingAny.externalWalletDivider.style.display = "none";
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4188
|
+
else if (onboardingAny.externalWalletDivider && hasEmailOrGoogle) {
|
|
3850
4189
|
onboardingAny.externalWalletDivider.style.display = "";
|
|
3851
4190
|
}
|
|
3852
4191
|
else if (onboardingAny.externalWalletDivider) {
|
|
@@ -3866,84 +4205,13 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3866
4205
|
// Check if the container is the same as the one we created the root for
|
|
3867
4206
|
const isSameContainer = externalWalletContainerRef.current === container;
|
|
3868
4207
|
const rootStillValid = externalWalletRootRef.current && containerInDOM && isSameContainer;
|
|
3869
|
-
const renderExternalWalletButtons = () => (_jsx(AbstraxnContext.Provider, { value: valueRef.current, children: _jsx(ExternalWalletButtons, { onConnect: async () => { }, onShowMoreWallets:
|
|
3870
|
-
const onboardingAny = onboardingRef.current;
|
|
3871
|
-
if (onboardingAny?.emailForm) {
|
|
3872
|
-
onboardingAny.emailForm.style.display = "none";
|
|
3873
|
-
}
|
|
3874
|
-
if (onboardingAny?.googleButton) {
|
|
3875
|
-
onboardingAny.googleButton.style.display = "none";
|
|
3876
|
-
}
|
|
3877
|
-
// Hide all passkey elements when wallet selection screen is shown
|
|
3878
|
-
if (onboardingAny?.passkeyLoginButton) {
|
|
3879
|
-
onboardingAny.passkeyLoginButton.style.display = "none";
|
|
3880
|
-
}
|
|
3881
|
-
if (onboardingAny?.passkeySignupLink) {
|
|
3882
|
-
onboardingAny.passkeySignupLink.style.display = "none";
|
|
3883
|
-
}
|
|
3884
|
-
if (onboardingAny?.passkeyErrorElement) {
|
|
3885
|
-
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
3886
|
-
}
|
|
3887
|
-
if (onboardingAny?.passkeyDivider) {
|
|
3888
|
-
onboardingAny.passkeyDivider.style.display = "none";
|
|
3889
|
-
}
|
|
3890
|
-
if (onboardingAny?.externalWalletDivider) {
|
|
3891
|
-
onboardingAny.externalWalletDivider.style.display = "none";
|
|
3892
|
-
}
|
|
3893
|
-
if (onboardingAny?.divider) {
|
|
3894
|
-
onboardingAny.divider.style.display = "none";
|
|
3895
|
-
}
|
|
3896
|
-
}, onHideMoreWallets: () => {
|
|
3897
|
-
const onboardingAny = onboardingRef.current;
|
|
3898
|
-
const authMethods = onboardingAny?.config?.authMethods || [
|
|
3899
|
-
"otp",
|
|
3900
|
-
"google",
|
|
3901
|
-
];
|
|
3902
|
-
const showEmail = authMethods.includes("otp");
|
|
3903
|
-
const showGoogle = authMethods.includes("google");
|
|
3904
|
-
const showPasskey = authMethods.includes("passkey");
|
|
3905
|
-
if (onboardingAny?.emailForm) {
|
|
3906
|
-
onboardingAny.emailForm.style.display = showEmail ? "" : "none";
|
|
3907
|
-
}
|
|
3908
|
-
if (onboardingAny?.googleButton) {
|
|
3909
|
-
onboardingAny.googleButton.style.display = showGoogle
|
|
3910
|
-
? ""
|
|
3911
|
-
: "none";
|
|
3912
|
-
}
|
|
3913
|
-
// Show passkey controls if enabled
|
|
3914
|
-
if (onboardingAny?.passkeyLoginButton) {
|
|
3915
|
-
onboardingAny.passkeyLoginButton.style.display = showPasskey
|
|
3916
|
-
? ""
|
|
3917
|
-
: "none";
|
|
3918
|
-
}
|
|
3919
|
-
if (onboardingAny?.passkeySignupLink) {
|
|
3920
|
-
onboardingAny.passkeySignupLink.style.display = showPasskey
|
|
3921
|
-
? ""
|
|
3922
|
-
: "none";
|
|
3923
|
-
}
|
|
3924
|
-
if (onboardingAny?.passkeyErrorElement) {
|
|
3925
|
-
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
3926
|
-
}
|
|
3927
|
-
// Show passkey divider if passkey is enabled and there are other auth methods
|
|
3928
|
-
if (onboardingAny?.passkeyDivider) {
|
|
3929
|
-
onboardingAny.passkeyDivider.style.display =
|
|
3930
|
-
showPasskey && (showEmail || showGoogle) ? "" : "none";
|
|
3931
|
-
}
|
|
3932
|
-
if (onboardingAny?.divider) {
|
|
3933
|
-
onboardingAny.divider.style.display =
|
|
3934
|
-
showEmail && showGoogle ? "" : "none";
|
|
3935
|
-
}
|
|
3936
|
-
const hasEmailOrGoogle = showEmail || showGoogle;
|
|
3937
|
-
if (onboardingAny?.externalWalletDivider && hasEmailOrGoogle) {
|
|
3938
|
-
onboardingAny.externalWalletDivider.style.display = "";
|
|
3939
|
-
}
|
|
3940
|
-
else if (onboardingAny?.externalWalletDivider) {
|
|
3941
|
-
onboardingAny.externalWalletDivider.style.display = "none";
|
|
3942
|
-
}
|
|
3943
|
-
} }) }));
|
|
4208
|
+
const renderExternalWalletButtons = () => (_jsx(AbstraxnContext.Provider, { value: valueRef.current, children: _jsx(ExternalWalletButtons, { onConnect: async () => { }, onShowMoreWallets: handleShowMoreWallets, onHideMoreWallets: handleHideMoreWallets }) }));
|
|
3944
4209
|
if (rootStillValid) {
|
|
3945
4210
|
externalWalletRootRef.current.render(renderExternalWalletButtons());
|
|
3946
4211
|
externalWalletMountedRef.current = true;
|
|
4212
|
+
if (isExternalWalletListOpen()) {
|
|
4213
|
+
handleShowMoreWallets();
|
|
4214
|
+
}
|
|
3947
4215
|
}
|
|
3948
4216
|
else {
|
|
3949
4217
|
try {
|
|
@@ -3965,6 +4233,9 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
3965
4233
|
externalWalletContainerRef.current = container; // Track the container
|
|
3966
4234
|
rootInstance.render(renderExternalWalletButtons());
|
|
3967
4235
|
externalWalletMountedRef.current = true;
|
|
4236
|
+
if (isExternalWalletListOpen()) {
|
|
4237
|
+
handleShowMoreWallets();
|
|
4238
|
+
}
|
|
3968
4239
|
}
|
|
3969
4240
|
catch (error) {
|
|
3970
4241
|
externalWalletMountedRef.current = false;
|
|
@@ -4037,7 +4308,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
4037
4308
|
const showEmail = authMethods.includes("otp");
|
|
4038
4309
|
const showGoogle = authMethods.includes("google");
|
|
4039
4310
|
const hasEmailOrGoogle = showEmail || showGoogle;
|
|
4040
|
-
if (
|
|
4311
|
+
if (isExternalWalletListOpen()) {
|
|
4312
|
+
if (onboardingAny.externalWalletDivider) {
|
|
4313
|
+
onboardingAny.externalWalletDivider.style.display = "none";
|
|
4314
|
+
}
|
|
4315
|
+
}
|
|
4316
|
+
else if (onboardingAny.externalWalletDivider && hasEmailOrGoogle) {
|
|
4041
4317
|
onboardingAny.externalWalletDivider.style.display = "";
|
|
4042
4318
|
}
|
|
4043
4319
|
else if (onboardingAny.externalWalletDivider) {
|
|
@@ -4088,91 +4364,11 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
4088
4364
|
rootInstance.render(_jsx(AbstraxnContext.Provider, { value: valueRef.current, children: _jsx(ExternalWalletButtons, { onConnect: async (_connectorId, _address) => {
|
|
4089
4365
|
// console.log('External wallet connected:', connectorId, address);
|
|
4090
4366
|
// Modal will be closed automatically by the useEffect that watches wagmiAccount
|
|
4091
|
-
}, onShowMoreWallets:
|
|
4092
|
-
// Hide email and Google sections when "More wallets" is clicked
|
|
4093
|
-
const onboardingAny = onboardingRef.current;
|
|
4094
|
-
if (onboardingAny?.emailForm) {
|
|
4095
|
-
onboardingAny.emailForm.style.display = "none";
|
|
4096
|
-
}
|
|
4097
|
-
if (onboardingAny?.googleButton) {
|
|
4098
|
-
onboardingAny.googleButton.style.display = "none";
|
|
4099
|
-
}
|
|
4100
|
-
// Hide all passkey elements when wallet selection screen is shown
|
|
4101
|
-
if (onboardingAny?.passkeyLoginButton) {
|
|
4102
|
-
onboardingAny.passkeyLoginButton.style.display = "none";
|
|
4103
|
-
}
|
|
4104
|
-
if (onboardingAny?.passkeySignupLink) {
|
|
4105
|
-
onboardingAny.passkeySignupLink.style.display = "none";
|
|
4106
|
-
}
|
|
4107
|
-
if (onboardingAny?.passkeyErrorElement) {
|
|
4108
|
-
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
4109
|
-
}
|
|
4110
|
-
if (onboardingAny?.passkeyDivider) {
|
|
4111
|
-
onboardingAny.passkeyDivider.style.display = "none";
|
|
4112
|
-
}
|
|
4113
|
-
if (onboardingAny?.externalWalletDivider) {
|
|
4114
|
-
onboardingAny.externalWalletDivider.style.display = "none";
|
|
4115
|
-
}
|
|
4116
|
-
// Also hide the divider between email and Google if it exists
|
|
4117
|
-
if (onboardingAny?.divider) {
|
|
4118
|
-
onboardingAny.divider.style.display = "none";
|
|
4119
|
-
}
|
|
4120
|
-
}, onHideMoreWallets: () => {
|
|
4121
|
-
// Show email and Google sections when back is clicked (restore initial screen)
|
|
4122
|
-
const onboardingAny = onboardingRef.current;
|
|
4123
|
-
const authMethods = onboardingAny?.config?.authMethods || [
|
|
4124
|
-
"otp",
|
|
4125
|
-
"google",
|
|
4126
|
-
];
|
|
4127
|
-
const showEmail = authMethods.includes("otp");
|
|
4128
|
-
const showGoogle = authMethods.includes("google");
|
|
4129
|
-
const showPasskey = authMethods.includes("passkey");
|
|
4130
|
-
// Show email form if enabled
|
|
4131
|
-
if (onboardingAny?.emailForm) {
|
|
4132
|
-
onboardingAny.emailForm.style.display = showEmail
|
|
4133
|
-
? ""
|
|
4134
|
-
: "none";
|
|
4135
|
-
}
|
|
4136
|
-
// Show Google button if enabled
|
|
4137
|
-
if (onboardingAny?.googleButton) {
|
|
4138
|
-
onboardingAny.googleButton.style.display = showGoogle
|
|
4139
|
-
? ""
|
|
4140
|
-
: "none";
|
|
4141
|
-
}
|
|
4142
|
-
// Show passkey controls if enabled
|
|
4143
|
-
if (onboardingAny?.passkeyLoginButton) {
|
|
4144
|
-
onboardingAny.passkeyLoginButton.style.display = showPasskey
|
|
4145
|
-
? ""
|
|
4146
|
-
: "none";
|
|
4147
|
-
}
|
|
4148
|
-
if (onboardingAny?.passkeySignupLink) {
|
|
4149
|
-
onboardingAny.passkeySignupLink.style.display = showPasskey
|
|
4150
|
-
? ""
|
|
4151
|
-
: "none";
|
|
4152
|
-
}
|
|
4153
|
-
if (onboardingAny?.passkeyErrorElement) {
|
|
4154
|
-
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
4155
|
-
}
|
|
4156
|
-
// Show passkey divider if passkey is enabled and there are other auth methods
|
|
4157
|
-
if (onboardingAny?.passkeyDivider) {
|
|
4158
|
-
onboardingAny.passkeyDivider.style.display =
|
|
4159
|
-
showPasskey && (showEmail || showGoogle) ? "" : "none";
|
|
4160
|
-
}
|
|
4161
|
-
// Show divider between email and Google if both are enabled
|
|
4162
|
-
if (onboardingAny?.divider) {
|
|
4163
|
-
onboardingAny.divider.style.display =
|
|
4164
|
-
showEmail && showGoogle ? "" : "none";
|
|
4165
|
-
}
|
|
4166
|
-
// Show the "or" divider before external wallets only if email/Google are visible
|
|
4167
|
-
const hasEmailOrGoogle = showEmail || showGoogle;
|
|
4168
|
-
if (onboardingAny?.externalWalletDivider && hasEmailOrGoogle) {
|
|
4169
|
-
onboardingAny.externalWalletDivider.style.display = "";
|
|
4170
|
-
}
|
|
4171
|
-
else if (onboardingAny?.externalWalletDivider) {
|
|
4172
|
-
onboardingAny.externalWalletDivider.style.display = "none";
|
|
4173
|
-
}
|
|
4174
|
-
} }) }));
|
|
4367
|
+
}, onShowMoreWallets: handleShowMoreWallets, onHideMoreWallets: handleHideMoreWallets }) }));
|
|
4175
4368
|
externalWalletMountedRef.current = true;
|
|
4369
|
+
if (isExternalWalletListOpen()) {
|
|
4370
|
+
handleShowMoreWallets();
|
|
4371
|
+
}
|
|
4176
4372
|
}
|
|
4177
4373
|
catch (error) {
|
|
4178
4374
|
console.error("Failed to mount ExternalWalletButtons:", error);
|
|
@@ -4216,140 +4412,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, solana, }
|
|
|
4216
4412
|
try {
|
|
4217
4413
|
externalWalletRootRef.current.render(_jsx(AbstraxnContext.Provider, { value: valueRef.current, children: _jsx(ExternalWalletButtons, { onConnect: async (_connectorId, _address) => {
|
|
4218
4414
|
// console.log('External wallet connected:', connectorId, address);
|
|
4219
|
-
}, onShowMoreWallets:
|
|
4220
|
-
// Hide email and Google sections when "More wallets" is clicked
|
|
4221
|
-
const onboardingAny = onboardingRef.current;
|
|
4222
|
-
if (onboardingAny?.emailForm) {
|
|
4223
|
-
onboardingAny.emailForm.style.display = "none";
|
|
4224
|
-
}
|
|
4225
|
-
if (onboardingAny?.googleButton) {
|
|
4226
|
-
onboardingAny.googleButton.style.display = "none";
|
|
4227
|
-
}
|
|
4228
|
-
// Hide Discord and X (Twitter) buttons when wallet selection screen is shown
|
|
4229
|
-
if (onboardingAny?.discordButton) {
|
|
4230
|
-
onboardingAny.discordButton.style.display = "none";
|
|
4231
|
-
}
|
|
4232
|
-
if (onboardingAny?.twitterButton) {
|
|
4233
|
-
onboardingAny.twitterButton.style.display = "none";
|
|
4234
|
-
}
|
|
4235
|
-
// Hide social grid if it exists
|
|
4236
|
-
if (onboardingAny?.socialGrid) {
|
|
4237
|
-
onboardingAny.socialGrid.style.display = "none";
|
|
4238
|
-
}
|
|
4239
|
-
// Extra guard: hide any social icon buttons by class
|
|
4240
|
-
if (onboardingAny?.rootElement) {
|
|
4241
|
-
onboardingAny.rootElement
|
|
4242
|
-
.querySelectorAll(".onboarding-button-social-icon, .onboarding-button-social")
|
|
4243
|
-
.forEach((el) => {
|
|
4244
|
-
el.style.display = "none";
|
|
4245
|
-
});
|
|
4246
|
-
}
|
|
4247
|
-
// Hide all passkey elements when wallet selection screen is shown
|
|
4248
|
-
if (onboardingAny?.passkeyLoginButton) {
|
|
4249
|
-
onboardingAny.passkeyLoginButton.style.display = "none";
|
|
4250
|
-
}
|
|
4251
|
-
if (onboardingAny?.passkeySignupLink) {
|
|
4252
|
-
onboardingAny.passkeySignupLink.style.display = "none";
|
|
4253
|
-
}
|
|
4254
|
-
if (onboardingAny?.passkeyErrorElement) {
|
|
4255
|
-
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
4256
|
-
}
|
|
4257
|
-
if (onboardingAny?.passkeyDivider) {
|
|
4258
|
-
onboardingAny.passkeyDivider.style.display = "none";
|
|
4259
|
-
}
|
|
4260
|
-
if (onboardingAny?.externalWalletDivider) {
|
|
4261
|
-
onboardingAny.externalWalletDivider.style.display = "none";
|
|
4262
|
-
}
|
|
4263
|
-
// Also hide the divider between email and Google if it exists
|
|
4264
|
-
if (onboardingAny?.divider) {
|
|
4265
|
-
onboardingAny.divider.style.display = "none";
|
|
4266
|
-
}
|
|
4267
|
-
}, onHideMoreWallets: () => {
|
|
4268
|
-
// Show email and Google sections when back is clicked
|
|
4269
|
-
const onboardingAny = onboardingRef.current;
|
|
4270
|
-
const authMethods = onboardingAny?.config?.authMethods || [
|
|
4271
|
-
"otp",
|
|
4272
|
-
"google",
|
|
4273
|
-
];
|
|
4274
|
-
const showEmail = authMethods.includes("otp");
|
|
4275
|
-
const showGoogle = authMethods.includes("google");
|
|
4276
|
-
const showTwitter = authMethods.includes("twitter");
|
|
4277
|
-
const showDiscord = authMethods.includes("discord");
|
|
4278
|
-
const showPasskey = authMethods.includes("passkey");
|
|
4279
|
-
if (onboardingAny?.emailForm) {
|
|
4280
|
-
onboardingAny.emailForm.style.display = showEmail ? "" : "none";
|
|
4281
|
-
}
|
|
4282
|
-
if (onboardingAny?.googleButton) {
|
|
4283
|
-
onboardingAny.googleButton.style.display = showGoogle
|
|
4284
|
-
? ""
|
|
4285
|
-
: "none";
|
|
4286
|
-
}
|
|
4287
|
-
// Show Discord and X (Twitter) buttons if enabled
|
|
4288
|
-
if (onboardingAny?.discordButton) {
|
|
4289
|
-
onboardingAny.discordButton.style.display = showDiscord
|
|
4290
|
-
? ""
|
|
4291
|
-
: "none";
|
|
4292
|
-
}
|
|
4293
|
-
if (onboardingAny?.twitterButton) {
|
|
4294
|
-
onboardingAny.twitterButton.style.display = showTwitter
|
|
4295
|
-
? ""
|
|
4296
|
-
: "none";
|
|
4297
|
-
}
|
|
4298
|
-
// Show social grid if it exists and social methods are enabled
|
|
4299
|
-
if (onboardingAny?.socialGrid) {
|
|
4300
|
-
const hasSocialMethods = showGoogle || showTwitter || showDiscord;
|
|
4301
|
-
onboardingAny.socialGrid.style.display = hasSocialMethods
|
|
4302
|
-
? ""
|
|
4303
|
-
: "none";
|
|
4304
|
-
}
|
|
4305
|
-
// Extra guard: restore social icon buttons by class based on flags
|
|
4306
|
-
if (onboardingAny?.rootElement) {
|
|
4307
|
-
const hasSocialMethods = showGoogle || showTwitter || showDiscord;
|
|
4308
|
-
onboardingAny.rootElement
|
|
4309
|
-
.querySelectorAll(".onboarding-button-social-icon, .onboarding-button-social")
|
|
4310
|
-
.forEach((el) => {
|
|
4311
|
-
el.style.display = hasSocialMethods
|
|
4312
|
-
? ""
|
|
4313
|
-
: "none";
|
|
4314
|
-
});
|
|
4315
|
-
}
|
|
4316
|
-
// Show passkey controls if enabled
|
|
4317
|
-
if (onboardingAny?.passkeyLoginButton) {
|
|
4318
|
-
onboardingAny.passkeyLoginButton.style.display = showPasskey
|
|
4319
|
-
? ""
|
|
4320
|
-
: "none";
|
|
4321
|
-
}
|
|
4322
|
-
if (onboardingAny?.passkeySignupLink) {
|
|
4323
|
-
onboardingAny.passkeySignupLink.style.display = showPasskey
|
|
4324
|
-
? ""
|
|
4325
|
-
: "none";
|
|
4326
|
-
}
|
|
4327
|
-
if (onboardingAny?.passkeyErrorElement) {
|
|
4328
|
-
onboardingAny.passkeyErrorElement.style.display = "none";
|
|
4329
|
-
}
|
|
4330
|
-
// Show passkey divider if passkey is enabled and there are other auth methods
|
|
4331
|
-
if (onboardingAny?.passkeyDivider) {
|
|
4332
|
-
onboardingAny.passkeyDivider.style.display =
|
|
4333
|
-
showPasskey &&
|
|
4334
|
-
(showEmail || showGoogle || showTwitter || showDiscord)
|
|
4335
|
-
? ""
|
|
4336
|
-
: "none";
|
|
4337
|
-
}
|
|
4338
|
-
// Show divider between email and social methods if both are enabled
|
|
4339
|
-
if (onboardingAny?.divider) {
|
|
4340
|
-
const hasSocialMethods = showGoogle || showTwitter || showDiscord;
|
|
4341
|
-
onboardingAny.divider.style.display =
|
|
4342
|
-
showEmail && hasSocialMethods ? "" : "none";
|
|
4343
|
-
}
|
|
4344
|
-
if (onboardingAny?.externalWalletDivider) {
|
|
4345
|
-
onboardingAny.externalWalletDivider.style.display = "";
|
|
4346
|
-
}
|
|
4347
|
-
} }) }));
|
|
4415
|
+
}, onShowMoreWallets: handleShowMoreWallets, onHideMoreWallets: handleHideMoreWallets }) }));
|
|
4348
4416
|
}
|
|
4349
4417
|
catch (error) {
|
|
4350
4418
|
console.warn("Failed to update ExternalWalletButtons:", error);
|
|
4351
4419
|
}
|
|
4352
4420
|
}, [value, externalWalletsEnabled]);
|
|
4353
|
-
return (_jsxs(AbstraxnContext.Provider, { value: value, children: [wagmi ? (_jsx(WagmiConnectionEffectSync, { onDisconnect: handleWagmiDisconnect })) : null, children] }));
|
|
4421
|
+
return (_jsxs(AbstraxnContext.Provider, { value: value, children: [wagmi ? (_jsx(WagmiConnectionEffectSync, { onDisconnect: handleWagmiDisconnect })) : null, children, _jsx(SignMfaModalHost, {})] }));
|
|
4354
4422
|
}
|
|
4355
4423
|
//# sourceMappingURL=AbstraxnProviderInner.js.map
|