@abstraxn/signer-react 1.0.14 → 1.0.16
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 +13 -0
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js +115 -9
- package/dist/src/components/AbstraxnProvider/AbstraxnProviderInner.js.map +1 -1
- package/dist/src/components/OnboardingUI/OnboardingUI.css +4 -0
- package/dist/src/components/OnboardingUI/OnboardingUIReact.js +16 -2
- package/dist/src/components/OnboardingUI/OnboardingUIReact.js.map +1 -1
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.d.ts +7 -0
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.js +17 -1
- package/dist/src/components/OnboardingUI/OnboardingUIWeb.js.map +1 -1
- package/dist/src/components/OnboardingUI/components/EmailForm.d.ts +2 -0
- package/dist/src/components/OnboardingUI/components/EmailForm.js +2 -2
- package/dist/src/components/OnboardingUI/components/EmailForm.js.map +1 -1
- package/dist/src/hooks.d.ts +14 -0
- package/dist/src/hooks.js +17 -0
- package/dist/src/hooks.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types.d.ts +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.16] - 2026-02-23
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **External wallet disconnect from extension** – When the user disconnects from an external wallet (e.g. MetaMask) via the extension ("Disconnect this site"), the app now updates `isConnected` to false immediately without requiring a page refresh. Previously the sync effect returned early when the user had explicitly connected, so state was never reset until refresh. The fix: (1) allow the sync effect to run the existing reset when wagmi reports disconnected; (2) use wagmi’s `useConnectionEffect(onDisconnect)` to clear external wallet state as soon as wagmi reports disconnect; (3) subscribe to the connector provider’s `accountsChanged` and `disconnect` events so state clears even if wagmi is slow or stale.
|
|
13
|
+
|
|
14
|
+
## [1.0.15] - 2026-02-20
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **`useEmailForOtp` hook** – Hook to get and set the email used to pre-fill the email-OTP form in onboarding. When the app calls `setEmailForOtp(email)`, the onboarding email field shows that value and is read-only (user cannot edit it). The same prefill and read-only behavior applies in both React onboarding (OnboardingUIReact) and Web onboarding (OnboardingUIWeb), including when opening the modal via ConnectButton. Exported from the package as `useEmailForOtp`.
|
|
19
|
+
- **Pre-fill email context** – Provider now exposes `emailForOtp` and `setEmailForOtp` on context. When `emailForOtp` is set, the email input is read-only and shows `cursor: not-allowed` for clearer UX.
|
|
20
|
+
|
|
8
21
|
## [1.0.14] - 2026-02-20
|
|
9
22
|
|
|
10
23
|
### Fixed
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* AbstraxnProviderInner - Core provider logic
|
|
4
4
|
* This component contains all the wallet state management and operations
|
|
@@ -6,15 +6,22 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
6
6
|
import { useEffect, useState, useRef, useCallback, useMemo, } from "react";
|
|
7
7
|
import { AbstraxnWallet, AuthenticationError, } from "@abstraxn/signer-core";
|
|
8
8
|
import { OnboardingUIWeb } from "../OnboardingUI";
|
|
9
|
+
import { useConnectionEffect, } from "wagmi";
|
|
9
10
|
import { parseEther, createPublicClient, http } from "viem";
|
|
10
11
|
import { ExternalWalletButtons } from "../../ExternalWalletButtons";
|
|
11
12
|
import { EVM_CHAINS, SOLANA_CHAINS, getChainById, toCoreChain, } from "../../chains";
|
|
12
13
|
import { AbstraxnContext } from "./context";
|
|
14
|
+
/** Syncs wagmi disconnect to external wallet state; only rendered when wagmi is available (under WagmiProvider). */
|
|
15
|
+
function WagmiConnectionEffectSync({ onDisconnect, }) {
|
|
16
|
+
useConnectionEffect({ onDisconnect });
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
13
19
|
export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
14
20
|
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;
|
|
15
21
|
const externalWalletsEnabled = config.externalWallets?.enabled ?? false;
|
|
16
22
|
// Keep a ref to avoid re-creating callbacks when toggling config (prevents flicker)
|
|
17
23
|
const externalWalletsEnabledRef = useRef(externalWalletsEnabled);
|
|
24
|
+
const isExternalWalletConnectedRef = useRef(false);
|
|
18
25
|
useEffect(() => {
|
|
19
26
|
externalWalletsEnabledRef.current = externalWalletsEnabled;
|
|
20
27
|
}, [externalWalletsEnabled]);
|
|
@@ -34,8 +41,12 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
34
41
|
// Connection type tracking: 'google' | 'email' | 'discord' | 'x' | 'passkey' | 'metamask' | 'walletconnect' | 'coinbase' | 'phantom' | 'injected' | null
|
|
35
42
|
const [connectionType, setConnectionType] = useState(null);
|
|
36
43
|
const [disconnecting, setDisconnecting] = useState(false);
|
|
44
|
+
const [emailForOtp, setEmailForOtpState] = useState("");
|
|
37
45
|
const explicitConnectionRef = useRef(false);
|
|
38
46
|
const autoDisconnectHandledRef = useRef(false);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
isExternalWalletConnectedRef.current = isExternalWalletConnected;
|
|
49
|
+
}, [isExternalWalletConnected]);
|
|
39
50
|
// Track when we last connected to prevent premature reset
|
|
40
51
|
const lastConnectionTimeRef = useRef(0);
|
|
41
52
|
// Refs to track previous values and prevent unnecessary updates
|
|
@@ -1016,6 +1027,9 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1016
1027
|
onboarding.modalOverlay.classList.add("onboarding-modal-open");
|
|
1017
1028
|
onboarding.modalOverlay.style.display = "flex";
|
|
1018
1029
|
document.body.style.overflow = "hidden";
|
|
1030
|
+
if (emailForOtp && typeof onboarding.setPreFillEmail === "function") {
|
|
1031
|
+
onboarding.setPreFillEmail(emailForOtp, { readOnly: true });
|
|
1032
|
+
}
|
|
1019
1033
|
// Ensure external wallet container is visible when modal opens
|
|
1020
1034
|
if (externalWalletsEnabledRef.current &&
|
|
1021
1035
|
onboarding.externalWalletContainer) {
|
|
@@ -1078,6 +1092,9 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1078
1092
|
onboarding.rootElement.style.display = "";
|
|
1079
1093
|
}
|
|
1080
1094
|
document.body.style.overflow = "hidden";
|
|
1095
|
+
if (emailForOtp && typeof onboarding.setPreFillEmail === "function") {
|
|
1096
|
+
onboarding.setPreFillEmail(emailForOtp, { readOnly: true });
|
|
1097
|
+
}
|
|
1081
1098
|
// If on OTP screen, ensure all login elements (social buttons, etc.) are hidden
|
|
1082
1099
|
if (isOtpScreen) {
|
|
1083
1100
|
// On OTP screen - ensure all login elements are hidden
|
|
@@ -1155,7 +1172,7 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1155
1172
|
}
|
|
1156
1173
|
}
|
|
1157
1174
|
// Note: externalWalletsEnabled is accessed via ref to keep this callback stable
|
|
1158
|
-
}, []);
|
|
1175
|
+
}, [emailForOtp]);
|
|
1159
1176
|
// Initialize IndexedDB
|
|
1160
1177
|
const init = useCallback(async () => {
|
|
1161
1178
|
if (!walletRef.current || isInitialized)
|
|
@@ -1977,12 +1994,6 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
1977
1994
|
isUpdatingRef.current = false;
|
|
1978
1995
|
return;
|
|
1979
1996
|
}
|
|
1980
|
-
// If we're not connected but explicitConnectionRef is true, it means we're trying to reconnect
|
|
1981
|
-
// Don't reset state in this case - wait for the connection to complete
|
|
1982
|
-
if (!wagmiAccount.isConnected && explicitConnectionRef.current) {
|
|
1983
|
-
// Connection is in progress, don't interfere
|
|
1984
|
-
return;
|
|
1985
|
-
}
|
|
1986
1997
|
}
|
|
1987
1998
|
// Check if external wallet is connected
|
|
1988
1999
|
if (wagmiAccount.isConnected && wagmiAccount.address) {
|
|
@@ -2476,6 +2487,95 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2476
2487
|
setLoading(false);
|
|
2477
2488
|
}
|
|
2478
2489
|
}, [externalWalletsEnabled, wagmiDisconnect, wagmiAccount?.connector]);
|
|
2490
|
+
// When wagmi reports disconnect (e.g. user disconnected in extension), clear external wallet state immediately
|
|
2491
|
+
const handleWagmiDisconnect = useCallback(() => {
|
|
2492
|
+
if (!externalWalletsEnabledRef.current)
|
|
2493
|
+
return;
|
|
2494
|
+
setIsExternalWalletConnected(false);
|
|
2495
|
+
setExternalWalletAddress(null);
|
|
2496
|
+
setExternalWalletChainId(null);
|
|
2497
|
+
setConnectionType(null);
|
|
2498
|
+
try {
|
|
2499
|
+
localStorage.removeItem("abstraxn_connection_type");
|
|
2500
|
+
}
|
|
2501
|
+
catch (e) {
|
|
2502
|
+
// Ignore
|
|
2503
|
+
}
|
|
2504
|
+
explicitConnectionRef.current = false;
|
|
2505
|
+
lastConnectionTimeRef.current = 0;
|
|
2506
|
+
lastAddressRef.current = null;
|
|
2507
|
+
lastChainIdRef.current = null;
|
|
2508
|
+
if (!walletRef.current?.isConnected) {
|
|
2509
|
+
setIsConnected(false);
|
|
2510
|
+
setAddress(null);
|
|
2511
|
+
setChainId(null);
|
|
2512
|
+
}
|
|
2513
|
+
}, [
|
|
2514
|
+
setIsExternalWalletConnected,
|
|
2515
|
+
setExternalWalletAddress,
|
|
2516
|
+
setExternalWalletChainId,
|
|
2517
|
+
setConnectionType,
|
|
2518
|
+
setIsConnected,
|
|
2519
|
+
setAddress,
|
|
2520
|
+
setChainId,
|
|
2521
|
+
]);
|
|
2522
|
+
// When user disconnects in the extension, provider may emit before wagmi updates; listen so we clear state even if wagmi is stale
|
|
2523
|
+
const providerListenerCleanupRef = useRef(null);
|
|
2524
|
+
useEffect(() => {
|
|
2525
|
+
if (!externalWalletsEnabled ||
|
|
2526
|
+
!isExternalWalletConnected ||
|
|
2527
|
+
!wagmiAccount?.connector) {
|
|
2528
|
+
return;
|
|
2529
|
+
}
|
|
2530
|
+
const connector = wagmiAccount.connector;
|
|
2531
|
+
let mounted = true;
|
|
2532
|
+
const setup = async () => {
|
|
2533
|
+
try {
|
|
2534
|
+
const getProvider = connector.getProvider ?? connector.getEthereumProvider;
|
|
2535
|
+
if (typeof getProvider !== "function")
|
|
2536
|
+
return;
|
|
2537
|
+
const p = await getProvider();
|
|
2538
|
+
if (!mounted || !p)
|
|
2539
|
+
return;
|
|
2540
|
+
const onDisconnectFromProvider = () => {
|
|
2541
|
+
if (!isExternalWalletConnectedRef.current)
|
|
2542
|
+
return;
|
|
2543
|
+
handleWagmiDisconnect();
|
|
2544
|
+
};
|
|
2545
|
+
const onAccountsChanged = (accounts) => {
|
|
2546
|
+
const list = Array.isArray(accounts) ? accounts : [];
|
|
2547
|
+
if (list.length === 0)
|
|
2548
|
+
onDisconnectFromProvider();
|
|
2549
|
+
};
|
|
2550
|
+
p.on?.("accountsChanged", onAccountsChanged);
|
|
2551
|
+
p.on?.("disconnect", onDisconnectFromProvider);
|
|
2552
|
+
return () => {
|
|
2553
|
+
p.removeListener?.("accountsChanged", onAccountsChanged);
|
|
2554
|
+
p.removeListener?.("disconnect", onDisconnectFromProvider);
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
catch {
|
|
2558
|
+
// Connector may not support getProvider (e.g. some injected)
|
|
2559
|
+
return undefined;
|
|
2560
|
+
}
|
|
2561
|
+
};
|
|
2562
|
+
setup().then((cleanup) => {
|
|
2563
|
+
if (mounted)
|
|
2564
|
+
providerListenerCleanupRef.current = cleanup ?? null;
|
|
2565
|
+
});
|
|
2566
|
+
return () => {
|
|
2567
|
+
mounted = false;
|
|
2568
|
+
const cleanup = providerListenerCleanupRef.current;
|
|
2569
|
+
providerListenerCleanupRef.current = null;
|
|
2570
|
+
if (typeof cleanup === "function")
|
|
2571
|
+
cleanup();
|
|
2572
|
+
};
|
|
2573
|
+
}, [
|
|
2574
|
+
externalWalletsEnabled,
|
|
2575
|
+
isExternalWalletConnected,
|
|
2576
|
+
wagmiAccount?.connector,
|
|
2577
|
+
handleWagmiDisconnect,
|
|
2578
|
+
]);
|
|
2479
2579
|
// Helper function to get network name from chain ID
|
|
2480
2580
|
const getNetworkName = useCallback((chainId) => {
|
|
2481
2581
|
const chainNames = {
|
|
@@ -2728,6 +2828,9 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2728
2828
|
setLoading(false);
|
|
2729
2829
|
}
|
|
2730
2830
|
}, [isExternalWalletConnected, wagmiSwitchChain, switchChain, availableChains]);
|
|
2831
|
+
const setEmailForOtp = useCallback((email) => {
|
|
2832
|
+
setEmailForOtpState(email);
|
|
2833
|
+
}, []);
|
|
2731
2834
|
const value = {
|
|
2732
2835
|
wallet: walletRef.current,
|
|
2733
2836
|
isInitialized,
|
|
@@ -2800,6 +2903,9 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
2800
2903
|
walletBalance: !isExternalWalletConnected ? walletBalance : undefined,
|
|
2801
2904
|
// Connection type
|
|
2802
2905
|
connectionType,
|
|
2906
|
+
// Pre-fill email for email-OTP flow
|
|
2907
|
+
emailForOtp,
|
|
2908
|
+
setEmailForOtp: setEmailForOtp,
|
|
2803
2909
|
};
|
|
2804
2910
|
// Ref to store latest value to avoid dependency issues (defined after value)
|
|
2805
2911
|
const valueRef = useRef(value);
|
|
@@ -3338,6 +3444,6 @@ export function AbstraxnProviderInner({ config, children, base, wagmi, }) {
|
|
|
3338
3444
|
console.warn("Failed to update ExternalWalletButtons:", error);
|
|
3339
3445
|
}
|
|
3340
3446
|
}, [value, externalWalletsEnabled]);
|
|
3341
|
-
return (
|
|
3447
|
+
return (_jsxs(AbstraxnContext.Provider, { value: value, children: [wagmi ? (_jsx(WagmiConnectionEffectSync, { onDisconnect: handleWagmiDisconnect })) : null, children] }));
|
|
3342
3448
|
}
|
|
3343
3449
|
//# sourceMappingURL=AbstraxnProviderInner.js.map
|