@openfort/react 1.0.7 → 1.0.9

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.
Files changed (27) hide show
  1. package/build/assets/icons.js +1 -1
  2. package/build/components/Common/ConnectorList/index.js +4 -5
  3. package/build/components/Common/ConnectorList/index.js.map +1 -1
  4. package/build/components/ConnectModal/ConnectWithQRCode.js +5 -1
  5. package/build/components/ConnectModal/ConnectWithQRCode.js.map +1 -1
  6. package/build/components/ConnectModal/index.js +3 -3
  7. package/build/components/Openfort/OpenfortProvider.js +16 -15
  8. package/build/components/Openfort/OpenfortProvider.js.map +1 -1
  9. package/build/components/Pages/Connected/EthereumConnected.js +7 -4
  10. package/build/components/Pages/Connected/EthereumConnected.js.map +1 -1
  11. package/build/components/Pages/Connected/SolanaConnected.js +1 -1
  12. package/build/components/Pages/SelectWalletToRecover/index.js +7 -1
  13. package/build/components/Pages/SelectWalletToRecover/index.js.map +1 -1
  14. package/build/ethereum/hooks/useEthereumEmbeddedWallet.js +5 -1
  15. package/build/ethereum/hooks/useEthereumEmbeddedWallet.js.map +1 -1
  16. package/build/hooks/useWalletConnectModal.d.ts +2 -2
  17. package/build/hooks/useWalletConnectModal.js +50 -45
  18. package/build/hooks/useWalletConnectModal.js.map +1 -1
  19. package/build/openfort/CoreOpenfortProvider.js +1 -0
  20. package/build/openfort/CoreOpenfortProvider.js.map +1 -1
  21. package/build/openfort/hooks/useActiveAddressSync.d.ts +7 -3
  22. package/build/openfort/hooks/useActiveAddressSync.js +37 -7
  23. package/build/openfort/hooks/useActiveAddressSync.js.map +1 -1
  24. package/build/solana/hooks/useSolanaEmbeddedWallet.js +1 -1
  25. package/build/version.d.ts +1 -1
  26. package/build/version.js +1 -1
  27. package/package.json +2 -3
@@ -1,4 +1,4 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
 
3
3
  const SendIcon = ({ ...props }) => (jsxs("svg", { "aria-hidden": "true", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [jsx("path", { d: "M5 19L19 5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M9 5H19V15", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })] }));
4
4
  const ReceiveIcon = ({ ...props }) => (jsxs("svg", { "aria-hidden": "true", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [jsx("path", { d: "M19 5L5 19", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M15 19H5V9", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })] }));
@@ -14,7 +14,6 @@ import { ConnectorsContainer, ConnectorButton, ConnectorIcon, ConnectorLabel, Re
14
14
 
15
15
  const ConnectorList = () => {
16
16
  const context = useOpenfort();
17
- const isMobile = useIsMobile();
18
17
  const wallets = useExternalConnectors();
19
18
  const { lastConnectorId } = useLastConnector();
20
19
  const familyConnector = useFamilyConnector();
@@ -31,7 +30,7 @@ const ConnectorList = () => {
31
30
  ...wallets.filter((wallet) => lastConnectorId === wallet.connector.id && wallet.id !== embeddedWalletId),
32
31
  ...wallets.filter((wallet) => lastConnectorId !== wallet.connector.id && wallet.id !== embeddedWalletId),
33
32
  ];
34
- return (jsxs(ScrollArea, { mobileDirection: 'horizontal', children: [filteredWallets.length === 0 && jsx(Alert, { error: true, children: "No connectors found in Openfort config." }), filteredWallets.length > 0 && (jsx(ConnectorsContainer, { "$mobile": isMobile, "$totalResults": walletsToDisplay.length, children: filteredWallets.map((wallet) => (jsx(ConnectorItem, { wallet: wallet, isRecent: wallet.id === lastConnectorId }, wallet.id))) }))] }));
33
+ return (jsxs(ScrollArea, { mobileDirection: 'horizontal', children: [filteredWallets.length === 0 && jsx(Alert, { error: true, children: "No connectors found in Openfort config." }), filteredWallets.length > 0 && (jsx(ConnectorsContainer, { "$mobile": false, "$totalResults": walletsToDisplay.length, children: filteredWallets.map((wallet) => (jsx(ConnectorItem, { wallet: wallet, isRecent: wallet.id === lastConnectorId }, wallet.id))) }))] }));
35
34
  };
36
35
  const ConnectorItem = ({ wallet, isRecent }) => {
37
36
  var _a;
@@ -44,9 +43,9 @@ const ConnectorItem = ({ wallet, isRecent }) => {
44
43
  return (jsxs(Fragment, { children: [jsx(ConnectorIcon, { "data-small": wallet.iconShouldShrink, "data-shape": wallet.iconShape, children: (_a = wallet.iconConnector) !== null && _a !== void 0 ? _a : wallet.icon }), jsxs(ConnectorLabel, { children: [isMobile ? ((_b = wallet.shortName) !== null && _b !== void 0 ? _b : wallet.name) : wallet.name, !context.uiConfig.hideRecentBadge && isRecent && (jsx(RecentlyUsedTag, { children: jsx("span", { children: "Recent" }) }))] })] }));
45
44
  };
46
45
  return (jsx(ConnectorButton, { type: "button", onClick: async () => {
47
- // Disconnect if the same connector is selected, otherwise wagmi won't trigger the connection flow
48
- // Disconnect for wallet connect to work
49
- if (bridge && (wallet.id === 'walletConnect' || wallet.id === (connector === null || connector === void 0 ? void 0 : connector.id))) {
46
+ var _a;
47
+ // Only disconnect if actually connected and switching connectors or reconnecting WC
48
+ if (((_a = bridge === null || bridge === void 0 ? void 0 : bridge.account) === null || _a === void 0 ? void 0 : _a.isConnected) && (wallet.id === 'walletConnect' || wallet.id === (connector === null || connector === void 0 ? void 0 : connector.id))) {
50
49
  await bridge.disconnect();
51
50
  }
52
51
  context.setRoute({ route: routes.CONNECT, connectType: 'linkIfUserConnectIfNoUser' });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { useEffect, useState, useCallback } from 'react';
2
+ import { useEffect, useState, useCallback, useRef } from 'react';
3
3
  import { useEthereumBridge } from '../../ethereum/OpenfortEthereumBridgeContext.js';
4
4
  import { useWalletConnectModal } from '../../hooks/useWalletConnectModal.js';
5
5
  import 'detect-browser';
@@ -46,6 +46,7 @@ const ConnectWithWalletConnect = () => {
46
46
  const wallet = useExternalConnector(connector.id);
47
47
  const { open: openWalletConnectModal } = useWalletConnectModal();
48
48
  const [error, setError] = useState(undefined);
49
+ const hasOpenedRef = useRef(false);
49
50
  const openModal = useCallback(async () => {
50
51
  setError(undefined);
51
52
  const { error } = await openWalletConnectModal();
@@ -53,6 +54,9 @@ const ConnectWithWalletConnect = () => {
53
54
  setError(error);
54
55
  }, [openWalletConnectModal]);
55
56
  useEffect(() => {
57
+ if (hasOpenedRef.current)
58
+ return;
59
+ hasOpenedRef.current = true;
56
60
  openModal();
57
61
  }, [openModal]);
58
62
  return (jsx(PageContent, { children: jsx(Loader, { header: error ? 'Error connecting wallet.' : `Connecting...`, icon: wallet === null || wallet === void 0 ? void 0 : wallet.icon, isError: !!error, description: error, onRetry: openModal }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectWithQRCode.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"ConnectWithQRCode.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,10 +1,9 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { ChainTypeEnum, OAuthProvider } from '@openfort/openfort-js';
3
- import { useMemo, useRef, useEffect } from 'react';
3
+ import { lazy, Suspense, useMemo, useRef, useEffect } from 'react';
4
4
  import { useConnectionStrategy } from '../../core/ConnectionStrategyContext.js';
5
5
  import { useOpenfortCore } from '../../openfort/useOpenfort.js';
6
6
  import { logger } from '../../utils/logger.js';
7
- import SwitchNetworks from '../../wagmi/components/SwitchNetworks/index.js';
8
7
  import Modal from '../Common/Modal/index.js';
9
8
  import { ConnectKitThemeProvider } from '../ConnectKitThemeProvider/ConnectKitThemeProvider.js';
10
9
  import { routes } from '../Openfort/types.js';
@@ -49,6 +48,7 @@ import SocialProviders from '../Pages/SocialProviders/index.js';
49
48
  import ConnectUsing from './ConnectUsing.js';
50
49
  import ConnectWithMobile from './ConnectWithMobile.js';
51
50
 
51
+ const LazySwitchNetworks = lazy(() => import('../../wagmi/components/SwitchNetworks/index.js'));
52
52
  function buildSharedPages() {
53
53
  return {
54
54
  onboarding: jsx(Introduction, {}),
@@ -99,7 +99,7 @@ const CHAIN_PREFIXED_PAGES = {
99
99
  'eth:connected': jsx(Connected, {}),
100
100
  'eth:createWallet': jsx(CreateWallet, {}),
101
101
  'eth:recoverWallet': jsx(RecoverPage, {}),
102
- 'eth:switchNetworks': jsx(SwitchNetworks, {}),
102
+ 'eth:switchNetworks': (jsx(Suspense, { fallback: null, children: jsx(LazySwitchNetworks, {}) })),
103
103
  'eth:send': jsx(Send, {}),
104
104
  'eth:receive': jsx(Receive, {}),
105
105
  'eth:buy': jsx(Buy, {}),
@@ -32,9 +32,10 @@ let openfortProviderWarnedNoWagmi = false;
32
32
  * ```
33
33
  */
34
34
  const OpenfortProvider = ({ children, uiConfig, onConnect, onDisconnect, debugMode, publishableKey, walletConfig, overrides, thirdPartyAuth, }) => {
35
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
35
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
36
36
  const bridge = useContext(OpenfortEthereumBridgeContext);
37
37
  const hasWagmi = !!bridge;
38
+ const hasExternalWallets = (_b = (_a = bridge === null || bridge === void 0 ? void 0 : bridge.connectors) === null || _a === void 0 ? void 0 : _a.some((c) => c.id === 'walletConnect')) !== null && _b !== void 0 ? _b : false;
38
39
  const hasSolana = !!(walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.solana);
39
40
  // Only allow for mounting OpenfortProvider once, so we avoid weird global
40
41
  // state collisions.
@@ -61,7 +62,7 @@ const OpenfortProvider = ({ children, uiConfig, onConnect, onDisconnect, debugMo
61
62
  logger.enabled = result.openfortReactDebugMode;
62
63
  return result;
63
64
  }, [debugMode]);
64
- const injectedConnector = (_a = bridge === null || bridge === void 0 ? void 0 : bridge.connectors) === null || _a === void 0 ? void 0 : _a.find((c) => c.id === 'injected');
65
+ const injectedConnector = (_c = bridge === null || bridge === void 0 ? void 0 : bridge.connectors) === null || _c === void 0 ? void 0 : _c.find((c) => c.id === 'injected');
65
66
  const allowAutomaticRecovery = !!((walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.createEncryptedSessionEndpoint) || (walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.getEncryptionSession));
66
67
  const defaultUIOptions = useMemo(() => ({
67
68
  appName: 'Openfort',
@@ -93,19 +94,19 @@ const OpenfortProvider = ({ children, uiConfig, onConnect, onDisconnect, debugMo
93
94
  allowedMethods: [RecoveryMethod.PASSWORD, ...(allowAutomaticRecovery ? [RecoveryMethod.AUTOMATIC] : [])],
94
95
  defaultMethod: allowAutomaticRecovery ? RecoveryMethod.AUTOMATIC : RecoveryMethod.PASSWORD,
95
96
  },
96
- authProviders: hasWagmi
97
+ authProviders: hasExternalWallets
97
98
  ? [UIAuthProvider.GUEST, UIAuthProvider.EMAIL_OTP, UIAuthProvider.WALLET, UIAuthProvider.GOOGLE]
98
99
  : [UIAuthProvider.GUEST, UIAuthProvider.EMAIL_OTP, UIAuthProvider.GOOGLE],
99
- }), [allowAutomaticRecovery, hasWagmi]);
100
+ }), [allowAutomaticRecovery, hasExternalWallets]);
100
101
  const safeUiConfig = useMemo(() => {
101
102
  var _a, _b, _c, _d, _e;
102
103
  const merged = { ...defaultUIOptions, ...uiConfig };
103
104
  let authProviders = (_a = merged.authProviders) !== null && _a !== void 0 ? _a : defaultUIOptions.authProviders;
104
- if (!hasWagmi && authProviders.includes(UIAuthProvider.WALLET)) {
105
+ if (!hasExternalWallets && authProviders.includes(UIAuthProvider.WALLET)) {
105
106
  authProviders = authProviders.filter((p) => p !== UIAuthProvider.WALLET);
106
107
  if (process.env.NODE_ENV === 'development' && !openfortProviderWarnedNoWagmi) {
107
108
  openfortProviderWarnedNoWagmi = true;
108
- logger.warn('[@openfort/react] UIAuthProvider.WALLET was removed from authProviders because no Wagmi bridge is present. Add OpenfortWagmiBridge to enable external wallet sign-in.');
109
+ logger.warn('[@openfort/react] UIAuthProvider.WALLET was removed from authProviders because no WalletConnect connector is present. Pass walletConnectProjectId to getDefaultConfig/getDefaultConnectors to enable external wallet sign-in.');
109
110
  }
110
111
  }
111
112
  const walletRecovery = {
@@ -117,15 +118,15 @@ const OpenfortProvider = ({ children, uiConfig, onConnect, onDisconnect, debugMo
117
118
  logger.warn('Automatic recovery method was removed from allowedMethods because no recovery options are configured in the walletConfig. Please provide either createEncryptedSessionEndpoint or getEncryptionSession to enable automatic recovery.');
118
119
  }
119
120
  return { ...merged, authProviders, walletRecovery };
120
- }, [defaultUIOptions, uiConfig, hasWagmi, allowAutomaticRecovery]);
121
+ }, [defaultUIOptions, uiConfig, hasExternalWallets, allowAutomaticRecovery]);
121
122
  useEffect(() => {
122
123
  if (typeof window !== 'undefined' && safeUiConfig.bufferPolyfill && !window.Buffer) {
123
124
  window.Buffer = Buffer;
124
125
  }
125
126
  }, [safeUiConfig.bufferPolyfill]);
126
- const [ckTheme, setTheme] = useState((_b = safeUiConfig.theme) !== null && _b !== void 0 ? _b : 'auto');
127
- const [ckMode, setMode] = useState((_c = safeUiConfig.mode) !== null && _c !== void 0 ? _c : 'auto');
128
- const [ckCustomTheme, setCustomTheme] = useState((_d = safeUiConfig.customTheme) !== null && _d !== void 0 ? _d : {});
127
+ const [ckTheme, setTheme] = useState((_d = safeUiConfig.theme) !== null && _d !== void 0 ? _d : 'auto');
128
+ const [ckMode, setMode] = useState((_e = safeUiConfig.mode) !== null && _e !== void 0 ? _e : 'auto');
129
+ const [ckCustomTheme, setCustomTheme] = useState((_f = safeUiConfig.customTheme) !== null && _f !== void 0 ? _f : {});
129
130
  const [ckLang, setLang] = useState('en-US');
130
131
  const [open, setOpenWithoutHistory] = useState(false);
131
132
  const initialConnector = { id: '' };
@@ -138,7 +139,7 @@ const OpenfortProvider = ({ children, uiConfig, onConnect, onDisconnect, debugMo
138
139
  const [sendForm, setSendForm] = useState(defaultSendFormState);
139
140
  const [buyForm, setBuyForm] = useState(defaultBuyFormState);
140
141
  const [headerLeftSlot, setHeaderLeftSlot] = useState(null);
141
- const [chainType, setChainType] = useState((_e = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.chainType) !== null && _e !== void 0 ? _e : ChainTypeEnum.EVM);
142
+ const [chainType, setChainType] = useState((_g = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.chainType) !== null && _g !== void 0 ? _g : ChainTypeEnum.EVM);
142
143
  const setOpen = useCallback((value) => {
143
144
  if (value) {
144
145
  setRouteHistory([]);
@@ -170,10 +171,10 @@ const OpenfortProvider = ({ children, uiConfig, onConnect, onDisconnect, debugMo
170
171
  return chainIds.map((id) => buildChainFromConfig(id, rpcUrls));
171
172
  }
172
173
  return [];
173
- }, [(_f = bridge === null || bridge === void 0 ? void 0 : bridge.switchChain) === null || _f === void 0 ? void 0 : _f.chains, (_g = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _g === void 0 ? void 0 : _g.rpcUrls, (_h = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _h === void 0 ? void 0 : _h.chainId]);
174
+ }, [(_h = bridge === null || bridge === void 0 ? void 0 : bridge.switchChain) === null || _h === void 0 ? void 0 : _h.chains, (_j = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _j === void 0 ? void 0 : _j.rpcUrls, (_k = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _k === void 0 ? void 0 : _k.chainId]);
174
175
  const chain = bridge === null || bridge === void 0 ? void 0 : bridge.account.chain;
175
- const isConnected = (_j = bridge === null || bridge === void 0 ? void 0 : bridge.account.isConnected) !== null && _j !== void 0 ? _j : false;
176
- const isChainSupported = !(chain === null || chain === void 0 ? void 0 : chain.id) || ((_l = (_k = bridge === null || bridge === void 0 ? void 0 : bridge.config.chains) === null || _k === void 0 ? void 0 : _k.some((c) => c.id === chain.id)) !== null && _l !== void 0 ? _l : false);
176
+ const isConnected = (_l = bridge === null || bridge === void 0 ? void 0 : bridge.account.isConnected) !== null && _l !== void 0 ? _l : false;
177
+ const isChainSupported = !(chain === null || chain === void 0 ? void 0 : chain.id) || ((_o = (_m = bridge === null || bridge === void 0 ? void 0 : bridge.config.chains) === null || _m === void 0 ? void 0 : _m.some((c) => c.id === chain.id)) !== null && _o !== void 0 ? _o : false);
177
178
  useEffect(() => {
178
179
  if (hasWagmi && isConnected && safeUiConfig.enforceSupportedChains && !isChainSupported) {
179
180
  setOpen(true);
@@ -335,7 +336,7 @@ const OpenfortProvider = ({ children, uiConfig, onConnect, onDisconnect, debugMo
335
336
  }, children: JSON.stringify(routeHistory.map((item) => Object.fromEntries(Object.entries(item).map(([key, value]) => [
336
337
  key,
337
338
  typeof value === 'object' && value !== null ? '[object]' : value,
338
- ]))), null, 2) })), children, jsx(Suspense, { fallback: null, children: jsx(LazyConnectKitModal, { lang: ckLang, theme: ckTheme, mode: (_m = safeUiConfig.mode) !== null && _m !== void 0 ? _m : ckMode, customTheme: ckCustomTheme }) })] }));
339
+ ]))), null, 2) })), children, jsx(Suspense, { fallback: null, children: jsx(LazyConnectKitModal, { lang: ckLang, theme: ckTheme, mode: (_p = safeUiConfig.mode) !== null && _p !== void 0 ? _p : ckMode, customTheme: ckCustomTheme }) })] }));
339
340
  return (jsx(UIContext.Provider, { value: connectUIValue, children: jsx(OpenfortContext.Provider, { value: value, children: jsx(CoreOpenfortProvider, { openfortConfig: {
340
341
  baseConfiguration: { publishableKey },
341
342
  shieldConfiguration: walletConfig
@@ -1 +1 @@
1
- {"version":3,"file":"OpenfortProvider.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"OpenfortProvider.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,20 +1,21 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { ChainTypeEnum } from '@openfort/openfort-js';
3
3
  import { AnimatePresence, motion } from 'framer-motion';
4
- import { useEffect, useMemo, useState } from 'react';
4
+ import { lazy, useEffect, useMemo, useState, Suspense } from 'react';
5
5
  import { formatUnits } from 'viem';
6
6
  import { UserRoundIcon, SendIcon, ReceiveIcon, BuyIcon } from '../../../assets/icons.js';
7
7
  import { useEthereumEmbeddedWallet } from '../../../ethereum/hooks/useEthereumEmbeddedWallet.js';
8
8
  import { useEthereumWalletAssets } from '../../../ethereum/hooks/useEthereumWalletAssets.js';
9
+ import { useEthereumBridge } from '../../../ethereum/OpenfortEthereumBridgeContext.js';
9
10
  import useLocales from '../../../hooks/useLocales.js';
10
11
  import { useResolvedIdentity } from '../../../hooks/useResolvedIdentity.js';
11
12
  import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
12
13
  import { nFormatter } from '../../../utils/index.js';
13
14
  import { logger } from '../../../utils/logger.js';
14
- import ChainSelector from '../../../wagmi/components/ChainSelect/index.js';
15
15
  import Avatar from '../../Common/Avatar/index.js';
16
16
  import Button from '../../Common/Button/index.js';
17
17
  import { TextLinkButton } from '../../Common/Button/styles.js';
18
+ import Chain from '../../Common/Chain/index.js';
18
19
  import { CopyText } from '../../Common/CopyToClipboard/CopyText.js';
19
20
  import { ModalBody } from '../../Common/Modal/styles.js';
20
21
  import { useThemeContext } from '../../ConnectKitThemeProvider/ConnectKitThemeProvider.js';
@@ -26,6 +27,7 @@ import { ConnectedPageLayout } from './ConnectedPageLayout.js';
26
27
  import { LinkedProvidersToggle, Balance, Unsupported, ChainSelectorContainer, ActionButton } from './styles.js';
27
28
  import { truncateEthAddress } from '../../../utils/format.js';
28
29
 
30
+ const LazyChainSelector = lazy(() => import('../../../wagmi/components/ChainSelect/index.js'));
29
31
  function getFirstBalanceAsset(assets) {
30
32
  return assets === null || assets === void 0 ? void 0 : assets.find((a) => a.balance && a.balance > BigInt(0));
31
33
  }
@@ -34,6 +36,7 @@ const EthereumConnected = () => {
34
36
  const context = useOpenfort();
35
37
  const { setHeaderLeftSlot, setRoute, chains } = context;
36
38
  const themeContext = useThemeContext();
39
+ const bridge = useEthereumBridge();
37
40
  const wallet = useEthereumEmbeddedWallet();
38
41
  const { embeddedAccounts } = useOpenfortCore();
39
42
  const hasEthereumWallets = ((_a = embeddedAccounts === null || embeddedAccounts === void 0 ? void 0 : embeddedAccounts.filter((a) => a.chainType === ChainTypeEnum.EVM)) !== null && _a !== void 0 ? _a : []).length > 0;
@@ -117,8 +120,8 @@ const EthereumConnected = () => {
117
120
  }
118
121
  setRoute(routes.ASSET_INVENTORY);
119
122
  }, children: jsxs(Balance, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, children: ["$", nFormatter(totalBalanceUsd)] }, `chain-${chain === null || chain === void 0 ? void 0 : chain.id}`) })) : null;
120
- const noWalletFallback = hasEthereumWallets ? (jsx(Button, { onClick: () => context.setRoute(routes.LOAD_WALLETS), children: "Manage wallets" })) : (jsx(Button, { onClick: () => context.setRoute({ route: routes.CONNECTORS, connectType: 'link' }), icon: jsx(Unsupported, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: jsxs("svg", { width: "130", height: "120", viewBox: "0 0 13 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("title", { children: "Unsupported wallet icon" }), jsx("path", { d: "M2.61317 11.2501H9.46246C10.6009 11.2501 11.3256 10.3506 11.3256 9.3549C11.3256 9.05145 11.255 8.73244 11.0881 8.43303L7.65903 2.14708C7.659 2.14702 7.65897 2.14696 7.65893 2.1469C7.65889 2.14682 7.65884 2.14673 7.65879 2.14664C7.31045 1.50746 6.6741 1.17871 6.04 1.17871C5.41478 1.17871 4.763 1.50043 4.41518 2.14968L0.993416 8.43476C0.828865 8.72426 0.75 9.04297 0.75 9.3549C0.75 10.3506 1.47471 11.2501 2.61317 11.2501Z", fill: "currentColor", stroke: "var(--ck-body-background, #fff)", strokeWidth: "1.5" }), jsx("path", { d: "M6.03258 7.43916C5.77502 7.43916 5.63096 7.29153 5.62223 7.02311L5.55675 4.96973C5.54802 4.69684 5.74446 4.5 6.02821 4.5C6.3076 4.5 6.51277 4.70131 6.50404 4.9742L6.43856 7.01864C6.42546 7.29153 6.2814 7.43916 6.03258 7.43916ZM6.03258 9.11676C5.7401 9.11676 5.5 8.9065 5.5 8.60677C5.5 8.30704 5.7401 8.09678 6.03258 8.09678C6.32506 8.09678 6.56515 8.30256 6.56515 8.60677C6.56515 8.91097 6.32069 9.11676 6.03258 9.11676Z", fill: "white" })] }) }), children: "Connect wallet" }));
121
- return (jsx(PageContent, { onBack: null, header: locales.profileScreen_heading, children: jsx(ConnectedPageLayout, { address: address !== null && address !== void 0 ? address : '', displayName: jsx(CopyText, { value: address !== null && address !== void 0 ? address : '', children: ensName !== null && ensName !== void 0 ? ensName : truncateEthAddress(address !== null && address !== void 0 ? address : '', separator) }), avatar: address ? jsx(Avatar, { address: address }) : jsx("span", {}), beforeAvatar: jsx(ChainSelectorContainer, { initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.2 }, children: jsx(ChainSelector, {}) }, chainId !== null && chainId !== void 0 ? chainId : 'loading'), balance: balanceNode, actions: jsxs(Fragment, { children: [jsx(ActionButton, { icon: jsx(SendIcon, {}), onClick: () => {
123
+ const noWalletFallback = hasEthereumWallets ? (jsx(Button, { onClick: () => context.setRoute(routes.SELECT_WALLET_TO_RECOVER), children: "Manage wallets" })) : (jsx(Button, { onClick: () => context.setRoute({ route: routes.CONNECTORS, connectType: 'link' }), icon: jsx(Unsupported, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, children: jsxs("svg", { width: "130", height: "120", viewBox: "0 0 13 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("title", { children: "Unsupported wallet icon" }), jsx("path", { d: "M2.61317 11.2501H9.46246C10.6009 11.2501 11.3256 10.3506 11.3256 9.3549C11.3256 9.05145 11.255 8.73244 11.0881 8.43303L7.65903 2.14708C7.659 2.14702 7.65897 2.14696 7.65893 2.1469C7.65889 2.14682 7.65884 2.14673 7.65879 2.14664C7.31045 1.50746 6.6741 1.17871 6.04 1.17871C5.41478 1.17871 4.763 1.50043 4.41518 2.14968L0.993416 8.43476C0.828865 8.72426 0.75 9.04297 0.75 9.3549C0.75 10.3506 1.47471 11.2501 2.61317 11.2501Z", fill: "currentColor", stroke: "var(--ck-body-background, #fff)", strokeWidth: "1.5" }), jsx("path", { d: "M6.03258 7.43916C5.77502 7.43916 5.63096 7.29153 5.62223 7.02311L5.55675 4.96973C5.54802 4.69684 5.74446 4.5 6.02821 4.5C6.3076 4.5 6.51277 4.70131 6.50404 4.9742L6.43856 7.01864C6.42546 7.29153 6.2814 7.43916 6.03258 7.43916ZM6.03258 9.11676C5.7401 9.11676 5.5 8.9065 5.5 8.60677C5.5 8.30704 5.7401 8.09678 6.03258 8.09678C6.32506 8.09678 6.56515 8.30256 6.56515 8.60677C6.56515 8.91097 6.32069 9.11676 6.03258 9.11676Z", fill: "white" })] }) }), children: "Connect wallet" }));
124
+ return (jsx(PageContent, { onBack: null, header: locales.profileScreen_heading, children: jsx(ConnectedPageLayout, { address: address !== null && address !== void 0 ? address : '', displayName: jsx(CopyText, { value: address !== null && address !== void 0 ? address : '', children: ensName !== null && ensName !== void 0 ? ensName : truncateEthAddress(address !== null && address !== void 0 ? address : '', separator) }), avatar: address ? jsx(Avatar, { address: address }) : jsx("span", {}), beforeAvatar: jsx(ChainSelectorContainer, { initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.2 }, children: bridge ? (jsx(Suspense, { fallback: jsx(Chain, { id: chainId }), children: jsx(LazyChainSelector, {}) })) : (jsx(Chain, { id: chainId })) }, chainId !== null && chainId !== void 0 ? chainId : 'loading'), balance: balanceNode, actions: jsxs(Fragment, { children: [jsx(ActionButton, { icon: jsx(SendIcon, {}), onClick: () => {
122
125
  const firstBalanceAsset = getFirstBalanceAsset(assets);
123
126
  if (!firstBalanceAsset) {
124
127
  setRoute(routes.NO_ASSETS_AVAILABLE);
@@ -1 +1 @@
1
- {"version":3,"file":"EthereumConnected.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"EthereumConnected.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -89,7 +89,7 @@ const SolanaConnected = () => {
89
89
  : undefined;
90
90
  const avatar = address ? CustomAvatar ? jsx(CustomAvatar, { address: address }) : jsx(Avatar, { address: address }) : jsx("span", {});
91
91
  const balanceNode = balanceSol != null && !isBalanceLoading ? (jsxs(Balance, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, children: [nFormatter(Number(balanceSol)), " SOL"] }, "solana-balance")) : null;
92
- return (jsx(PageContent, { onBack: null, header: locales.profileScreen_heading, children: jsx(ConnectedPageLayout, { address: address !== null && address !== void 0 ? address : '', displayName: jsx(CopyText, { value: address !== null && address !== void 0 ? address : '', children: truncateSolanaAddress(address !== null && address !== void 0 ? address : '', separator) }), avatar: avatar, balance: balanceNode, actions: jsx(ActionButton, { icon: jsx(ReceiveIcon, {}), onClick: () => context.setRoute(routes.SOL_RECEIVE), children: "Get" }), hideBalance: context === null || context === void 0 ? void 0 : context.uiConfig.hideBalance, isBalanceLoading: isBalanceLoading, isAddressLoading: isAddressLoading, noWalletFallback: hasSolanaWallets ? (jsx(Button, { onClick: () => setRoute(routes.SOL_WALLETS), children: "Manage wallets" })) : (jsx(Button, { onClick: () => setRoute(routes.SOL_CREATE_WALLET), children: "Create Solana Wallet" })) }) }));
92
+ return (jsx(PageContent, { onBack: null, header: locales.profileScreen_heading, children: jsx(ConnectedPageLayout, { address: address !== null && address !== void 0 ? address : '', displayName: jsx(CopyText, { value: address !== null && address !== void 0 ? address : '', children: truncateSolanaAddress(address !== null && address !== void 0 ? address : '', separator) }), avatar: avatar, balance: balanceNode, actions: jsx(ActionButton, { icon: jsx(ReceiveIcon, {}), onClick: () => context.setRoute(routes.SOL_RECEIVE), children: "Get" }), hideBalance: context === null || context === void 0 ? void 0 : context.uiConfig.hideBalance, isBalanceLoading: isBalanceLoading, isAddressLoading: isAddressLoading, noWalletFallback: hasSolanaWallets ? (jsx(Button, { onClick: () => setRoute(routes.SELECT_WALLET_TO_RECOVER), children: "Manage wallets" })) : (jsx(Button, { onClick: () => setRoute(routes.SOL_CREATE_WALLET), children: "Create Solana Wallet" })) }) }));
93
93
  };
94
94
 
95
95
  export { SolanaConnected as default };
@@ -88,14 +88,20 @@ function WalletRow({ chainType, wallet, }) {
88
88
  const tag = wallet.recoveryMethod != null ? RECOVERY_METHOD_LABEL[wallet.recoveryMethod] : undefined;
89
89
  return (jsx(ProvidersButton, { children: jsxs(Button, { onClick: handleClick, children: [jsxs(ProviderLabel, { children: [display, tag && jsx(RecoveryTag, { children: tag })] }), jsx(ProviderIcon, { children: walletIcon() })] }) }));
90
90
  }
91
+ /** Connected-page routes that indicate the user navigated here from "Manage wallets" */
92
+ const CONNECTED_ROUTES = new Set([routes.CONNECTED, routes.ETH_CONNECTED, routes.SOL_CONNECTED]);
91
93
  function SelectWalletToRecover() {
92
94
  const { chainType } = useOpenfortCore();
95
+ const { previousRoute } = useOpenfort();
93
96
  const ethereumWallet = useEthereumEmbeddedWallet();
94
97
  const solanaWallet = useSolanaEmbeddedWallet();
95
98
  const embeddedWallet = chainType === ChainTypeEnum.EVM ? ethereumWallet : solanaWallet;
96
99
  const wallets = embeddedWallet.wallets;
97
100
  const list = wallets.map((wallet) => jsx(WalletRow, { chainType: chainType, wallet: wallet }, wallet.id));
98
- return (jsxs(PageContent, { onBack: routes.PROVIDERS, logoutOnBack: true, children: [jsx(ModalHeading, { children: "Select a wallet to recover" }), jsx(WalletListScroll, { children: list })] }));
101
+ // When arriving from a connected page (Manage wallets), go back there without logging out.
102
+ // When arriving from the login flow, go back to providers and log out.
103
+ const fromConnected = previousRoute != null && CONNECTED_ROUTES.has(previousRoute.route);
104
+ return (jsxs(PageContent, { onBack: fromConnected ? 'back' : routes.PROVIDERS, logoutOnBack: !fromConnected, children: [jsx(ModalHeading, { children: "Select a wallet" }), jsx(WalletListScroll, { children: list })] }));
99
105
  }
100
106
 
101
107
  export { SelectWalletToRecover as default };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -139,6 +139,11 @@ function useEthereumEmbeddedWallet(options) {
139
139
  ...(accountType !== DEFAULT_ACCOUNT_TYPE && { chainId: (_d = createOptions === null || createOptions === void 0 ? void 0 : createOptions.chainId) !== null && _d !== void 0 ? _d : creationChainId }),
140
140
  recoveryParams,
141
141
  });
142
+ // Set the address before fetching accounts or setting connected state.
143
+ // This prevents a race where the sync effect sees status='connected' but
144
+ // no activeEmbeddedAddress and disconnects (especially for the first wallet
145
+ // when embeddedAccounts is still empty).
146
+ setActiveEmbeddedAddress(account.address);
142
147
  await updateEmbeddedAccounts({ silent: true });
143
148
  const provider = await getEmbeddedEthereumProvider();
144
149
  const connectedWallet = buildConnectedWallet(account, 0, async () => provider, {
@@ -151,7 +156,6 @@ function useEthereumEmbeddedWallet(options) {
151
156
  provider,
152
157
  error: null,
153
158
  });
154
- setActiveEmbeddedAddress(account.address);
155
159
  (_e = createOptions === null || createOptions === void 0 ? void 0 : createOptions.onSuccess) === null || _e === void 0 ? void 0 : _e.call(createOptions, { account });
156
160
  return account;
157
161
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useEthereumEmbeddedWallet.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useEthereumEmbeddedWallet.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,8 +1,8 @@
1
1
  export declare function useWalletConnectModal(): {
2
2
  isOpen: boolean;
3
3
  open: () => Promise<{
4
- error: string;
5
- } | {
6
4
  error?: undefined;
5
+ } | {
6
+ error: string;
7
7
  }>;
8
8
  };
@@ -1,4 +1,4 @@
1
- import { useState } from 'react';
1
+ import { useState, useRef, useCallback } from 'react';
2
2
  import { useEthereumBridge } from '../ethereum/OpenfortEthereumBridgeContext.js';
3
3
  import { isWalletConnectConnector } from '../utils/index.js';
4
4
  import { logger } from '../utils/logger.js';
@@ -6,53 +6,58 @@ import { logger } from '../utils/logger.js';
6
6
  function useWalletConnectModal() {
7
7
  const bridge = useEthereumBridge();
8
8
  const [isOpen, setIsOpen] = useState(false);
9
- return {
10
- isOpen,
11
- open: async () => {
12
- var _a;
13
- const w3mcss = document.createElement('style');
14
- w3mcss.textContent = `w3m-modal, wcm-modal{ --wcm-z-index: 2147483647; --w3m-z-index:2147483647; }`;
15
- document.head.appendChild(w3mcss);
16
- const removeChild = () => {
17
- if (document.head.contains(w3mcss)) {
18
- document.head.removeChild(w3mcss);
19
- }
20
- };
21
- const connectors = (_a = bridge === null || bridge === void 0 ? void 0 : bridge.connectors) !== null && _a !== void 0 ? _a : [];
22
- const clientConnector = connectors.find((c) => isWalletConnectConnector(c.id));
23
- if (clientConnector && (bridge === null || bridge === void 0 ? void 0 : bridge.connectAsync)) {
24
- try {
25
- setIsOpen(true);
26
- try {
27
- await bridge.connectAsync({ connector: clientConnector });
28
- }
29
- catch (err) {
30
- logger.log('WalletConnect', err);
31
- return {
32
- error: 'Connection failed',
33
- };
34
- }
35
- setIsOpen(false);
36
- removeChild();
37
- return {};
38
- }
39
- catch (err) {
40
- logger.log('Could not get WalletConnect provider', err);
41
- removeChild();
42
- return {
43
- error: 'Could not get WalletConnect provider',
44
- };
45
- }
9
+ const bridgeRef = useRef(bridge);
10
+ bridgeRef.current = bridge;
11
+ const connectingRef = useRef(false);
12
+ const open = useCallback(async () => {
13
+ var _a;
14
+ if (connectingRef.current)
15
+ return {};
16
+ connectingRef.current = true;
17
+ const currentBridge = bridgeRef.current;
18
+ const w3mcss = document.createElement('style');
19
+ w3mcss.textContent = `w3m-modal, wcm-modal{ --wcm-z-index: 2147483647; --w3m-z-index:2147483647; }`;
20
+ document.head.appendChild(w3mcss);
21
+ const removeChild = () => {
22
+ if (document.head.contains(w3mcss)) {
23
+ document.head.removeChild(w3mcss);
46
24
  }
47
- else {
25
+ };
26
+ const connectors = (_a = currentBridge === null || currentBridge === void 0 ? void 0 : currentBridge.connectors) !== null && _a !== void 0 ? _a : [];
27
+ const clientConnector = connectors.find((c) => isWalletConnectConnector(c.id));
28
+ if (clientConnector && (currentBridge === null || currentBridge === void 0 ? void 0 : currentBridge.connectAsync)) {
29
+ try {
30
+ currentBridge.reset();
31
+ setIsOpen(true);
32
+ await currentBridge.connectAsync({ connector: clientConnector });
33
+ setIsOpen(false);
48
34
  removeChild();
49
- logger.log('Configuration error: Please provide a WalletConnect Project ID in your wagmi config.');
50
- return {
51
- error: 'Configuration error: Please provide a WalletConnect Project ID in your wagmi config.',
52
- };
35
+ connectingRef.current = false;
36
+ return {};
53
37
  }
54
- },
55
- };
38
+ catch (err) {
39
+ setIsOpen(false);
40
+ removeChild();
41
+ connectingRef.current = false;
42
+ const message = err instanceof Error ? err.message : String(err);
43
+ if (message.includes('Connection request reset')) {
44
+ currentBridge.reset();
45
+ return { error: 'Connection cancelled' };
46
+ }
47
+ logger.log('WalletConnect', err);
48
+ return { error: 'Connection failed' };
49
+ }
50
+ }
51
+ else {
52
+ removeChild();
53
+ connectingRef.current = false;
54
+ logger.log('Configuration error: Please provide a WalletConnect Project ID in your wagmi config.');
55
+ return {
56
+ error: 'Configuration error: Please provide a WalletConnect Project ID in your wagmi config.',
57
+ };
58
+ }
59
+ }, []);
60
+ return { isOpen, open };
56
61
  }
57
62
 
58
63
  export { useWalletConnectModal };
@@ -1 +1 @@
1
- {"version":3,"file":"useWalletConnectModal.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useWalletConnectModal.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -219,6 +219,7 @@ const CoreOpenfortProvider = ({ children, onConnect, onDisconnect, openfortConfi
219
219
  storeActiveEmbeddedAddress,
220
220
  chainType,
221
221
  store,
222
+ walletConfig,
222
223
  });
223
224
  // Current chain for EVM provider reconfiguration
224
225
  const evmChainId = (strategy === null || strategy === void 0 ? void 0 : strategy.chainType) === ChainTypeEnum.EVM ? (bridge ? bridge.chainId : strategy === null || strategy === void 0 ? void 0 : strategy.getChainId()) : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"CoreOpenfortProvider.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"CoreOpenfortProvider.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,6 @@
1
1
  import { type ChainTypeEnum, type Openfort } from '@openfort/openfort-js';
2
2
  import type { StoreApi } from 'zustand/vanilla';
3
+ import type { OpenfortWalletConfig } from '../../components/Openfort/types';
3
4
  import type { OpenfortStore } from '../store';
4
5
  type Params = {
5
6
  openfort: Openfort;
@@ -8,13 +9,16 @@ type Params = {
8
9
  storeActiveEmbeddedAddress: OpenfortStore['activeEmbeddedAddress'];
9
10
  chainType: ChainTypeEnum;
10
11
  store: StoreApi<OpenfortStore>;
12
+ walletConfig: OpenfortWalletConfig | undefined;
11
13
  };
12
14
  /**
13
15
  * Syncs the active embedded address into the store.
14
16
  *
15
17
  * - Clears address when there are no accounts or user is logged out.
16
- * - When READY: asks the SDK for its active wallet, falls back to the first
17
- * account for the current chain.
18
+ * - When connectOnLogin is false and the session went through
19
+ * EMBEDDED_SIGNER_NOT_CONFIGURED (login flow), skips auto-seeding at READY
20
+ * so the user must pick a wallet explicitly.
21
+ * - Returning sessions (SDK starts directly at READY) always auto-seed.
18
22
  */
19
- export declare function useActiveAddressSync({ openfort, storeEmbeddedAccounts, storeEmbeddedState, storeActiveEmbeddedAddress, chainType, store, }: Params): void;
23
+ export declare function useActiveAddressSync({ openfort, storeEmbeddedAccounts, storeEmbeddedState, storeActiveEmbeddedAddress, chainType, store, walletConfig, }: Params): void;
20
24
  export {};
@@ -1,18 +1,30 @@
1
1
  import { EmbeddedState } from '@openfort/openfort-js';
2
- import { useEffect } from 'react';
2
+ import { useRef, useEffect } from 'react';
3
3
  import { firstEmbeddedAddress } from '../../core/strategyUtils.js';
4
4
 
5
5
  /**
6
6
  * Syncs the active embedded address into the store.
7
7
  *
8
8
  * - Clears address when there are no accounts or user is logged out.
9
- * - When READY: asks the SDK for its active wallet, falls back to the first
10
- * account for the current chain.
9
+ * - When connectOnLogin is false and the session went through
10
+ * EMBEDDED_SIGNER_NOT_CONFIGURED (login flow), skips auto-seeding at READY
11
+ * so the user must pick a wallet explicitly.
12
+ * - Returning sessions (SDK starts directly at READY) always auto-seed.
11
13
  */
12
- function useActiveAddressSync({ openfort, storeEmbeddedAccounts, storeEmbeddedState, storeActiveEmbeddedAddress, chainType, store, }) {
14
+ function useActiveAddressSync({ openfort, storeEmbeddedAccounts, storeEmbeddedState, storeActiveEmbeddedAddress, chainType, store, walletConfig, }) {
15
+ var _a;
16
+ const connectOnLogin = (_a = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.connectOnLogin) !== null && _a !== void 0 ? _a : true;
17
+ // Track whether the current session went through EMBEDDED_SIGNER_NOT_CONFIGURED
18
+ // (i.e. a login flow, not a returning session). When connectOnLogin is false, we
19
+ // skip auto-seeding at READY only for login flows — returning sessions (where the
20
+ // SDK starts directly at READY with a configured signer) should always auto-seed.
21
+ const sawSignerNotConfiguredRef = useRef(false);
13
22
  useEffect(() => {
14
23
  if (!openfort || !(storeEmbeddedAccounts === null || storeEmbeddedAccounts === void 0 ? void 0 : storeEmbeddedAccounts.length)) {
15
- if (!(storeEmbeddedAccounts === null || storeEmbeddedAccounts === void 0 ? void 0 : storeEmbeddedAccounts.length)) {
24
+ // Only clear the address on genuine logout (no user). During wallet creation
25
+ // the accounts list is briefly empty while updateEmbeddedAccounts refetches —
26
+ // clearing here would undo the address that create() just set.
27
+ if (!(storeEmbeddedAccounts === null || storeEmbeddedAccounts === void 0 ? void 0 : storeEmbeddedAccounts.length) && !store.getState().user) {
16
28
  store.getState().setActiveEmbeddedAddress(undefined);
17
29
  }
18
30
  return;
@@ -23,13 +35,16 @@ function useActiveAddressSync({ openfort, storeEmbeddedAccounts, storeEmbeddedSt
23
35
  if (storeEmbeddedState === EmbeddedState.UNAUTHENTICATED || storeEmbeddedState === EmbeddedState.NONE) {
24
36
  if (!store.getState().user) {
25
37
  store.getState().setActiveEmbeddedAddress(undefined);
38
+ sawSignerNotConfiguredRef.current = false;
26
39
  }
27
40
  return;
28
41
  }
29
42
  // Bootstrap recovery: when signer is not yet configured and no address is set,
30
43
  // seed the active address so useAutoRecovery can trigger and drive state → READY.
44
+ // Skip when connectOnLogin is false — the user should explicitly choose a wallet.
31
45
  if (storeEmbeddedState === EmbeddedState.EMBEDDED_SIGNER_NOT_CONFIGURED) {
32
- if (storeActiveEmbeddedAddress === undefined) {
46
+ sawSignerNotConfiguredRef.current = true;
47
+ if (connectOnLogin && storeActiveEmbeddedAddress === undefined) {
33
48
  const first = firstEmbeddedAddress(storeEmbeddedAccounts, chainType);
34
49
  if (first)
35
50
  store.getState().setActiveEmbeddedAddress(first);
@@ -42,6 +57,13 @@ function useActiveAddressSync({ openfort, storeEmbeddedAccounts, storeEmbeddedSt
42
57
  // Already have an address — nothing to resolve
43
58
  if (storeActiveEmbeddedAddress !== undefined)
44
59
  return;
60
+ // Login flow with connectOnLogin=false: the session went through
61
+ // EMBEDDED_SIGNER_NOT_CONFIGURED, so don't auto-seed. The user must pick
62
+ // a wallet via the UI. create() and setActive() set the address directly,
63
+ // so they bypass this check.
64
+ if (!connectOnLogin && sawSignerNotConfiguredRef.current) {
65
+ return;
66
+ }
45
67
  // Priority 1: ask the SDK for its active wallet
46
68
  let cancelled = false;
47
69
  openfort.embeddedWallet
@@ -69,7 +91,15 @@ function useActiveAddressSync({ openfort, storeEmbeddedAccounts, storeEmbeddedSt
69
91
  return () => {
70
92
  cancelled = true;
71
93
  };
72
- }, [openfort, storeEmbeddedAccounts, storeEmbeddedState, storeActiveEmbeddedAddress, chainType, store]);
94
+ }, [
95
+ openfort,
96
+ storeEmbeddedAccounts,
97
+ storeEmbeddedState,
98
+ storeActiveEmbeddedAddress,
99
+ chainType,
100
+ store,
101
+ connectOnLogin,
102
+ ]);
73
103
  }
74
104
 
75
105
  export { useActiveAddressSync };
@@ -1 +1 @@
1
- {"version":3,"file":"useActiveAddressSync.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useActiveAddressSync.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -123,6 +123,7 @@ function useSolanaEmbeddedWallet(options) {
123
123
  accountType: AccountTypeEnum.EOA,
124
124
  recoveryParams,
125
125
  });
126
+ setActiveEmbeddedAddress(account.address);
126
127
  await updateEmbeddedAccounts({ silent: true });
127
128
  const provider = createProviderForAccount(account);
128
129
  const connectedWallet = {
@@ -139,7 +140,6 @@ function useSolanaEmbeddedWallet(options) {
139
140
  provider,
140
141
  error: null,
141
142
  });
142
- setActiveEmbeddedAddress(account.address);
143
143
  (_a = createOptions === null || createOptions === void 0 ? void 0 : createOptions.onSuccess) === null || _a === void 0 ? void 0 : _a.call(createOptions, { account });
144
144
  return account;
145
145
  }
@@ -1 +1 @@
1
- export declare const OPENFORT_VERSION = "1.0.7";
1
+ export declare const OPENFORT_VERSION = "1.0.9";
package/build/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const OPENFORT_VERSION = '1.0.7';
1
+ const OPENFORT_VERSION = '1.0.9';
2
2
 
3
3
  export { OPENFORT_VERSION };
4
4
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfort/react",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "author": "Openfort (https://www.openfort.io)",
5
5
  "license": "BSD-2-Clause license",
6
6
  "description": "The easiest way to integrate Openfort to your project.",
@@ -94,11 +94,10 @@
94
94
  "@types/styled-components": "^5.1.25",
95
95
  "@wagmi/connectors": "^6.2.0",
96
96
  "@wagmi/core": "^2.22.1",
97
- "happy-dom": "^20.8.3",
97
+ "happy-dom": "^20.8.9",
98
98
  "jsdom": "^28.1.0",
99
99
  "rollup-plugin-peer-deps-external": "^2.2.4",
100
100
  "rollup-plugin-typescript2": "^0.36.0",
101
- "styled-components": "^5.3.5",
102
101
  "typescript": "^5.0.4",
103
102
  "typescript-plugin-styled-components": "^2.0.0",
104
103
  "vitest": "^2.0.0",