@openfort/react 1.1.2 → 1.1.4
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/build/components/Common/ErrorFallbackPage/index.d.ts +7 -0
- package/build/components/Common/ErrorFallbackPage/index.js +17 -0
- package/build/components/Common/ErrorFallbackPage/index.js.map +1 -0
- package/build/components/Common/NotFoundFallback/index.d.ts +6 -0
- package/build/components/Common/NotFoundFallback/index.js +11 -0
- package/build/components/Common/NotFoundFallback/index.js.map +1 -0
- package/build/components/Common/WalletConnectNotConfigured/index.d.ts +9 -0
- package/build/components/Common/WalletConnectNotConfigured/index.js +26 -0
- package/build/components/Common/WalletConnectNotConfigured/index.js.map +1 -0
- package/build/components/ConnectModal/ConnectWithMobile.js +5 -1
- package/build/components/ConnectModal/ConnectWithMobile.js.map +1 -1
- package/build/components/ConnectModal/ConnectWithQRCode.js +7 -1
- package/build/components/ConnectModal/ConnectWithQRCode.js.map +1 -1
- package/build/components/Pages/LoadWallets/index.js +9 -0
- package/build/components/Pages/LoadWallets/index.js.map +1 -1
- package/build/components/Pages/Loading/index.js +8 -0
- package/build/components/Pages/Loading/index.js.map +1 -1
- package/build/components/Pages/MobileConnectors/index.js +5 -0
- package/build/components/Pages/MobileConnectors/index.js.map +1 -1
- package/build/components/Pages/SendConfirmation/index.js +16 -4
- package/build/components/Pages/SendConfirmation/index.js.map +1 -1
- package/build/hooks/openfort/useUI.js +16 -20
- package/build/hooks/openfort/useUI.js.map +1 -1
- package/build/hooks/useTimedOut.d.ts +2 -0
- package/build/hooks/useTimedOut.js +14 -0
- package/build/hooks/useTimedOut.js.map +1 -0
- package/build/version.d.ts +1 -1
- package/build/version.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type ErrorFallbackPageProps = {
|
|
2
|
+
header: string;
|
|
3
|
+
description: string;
|
|
4
|
+
};
|
|
5
|
+
/** Shared error page with a single way out: back to the providers (sign-in) screen. */
|
|
6
|
+
declare const ErrorFallbackPage: ({ header, description }: ErrorFallbackPageProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default ErrorFallbackPage;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
|
|
3
|
+
import { routes } from '../../Openfort/types.js';
|
|
4
|
+
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
5
|
+
import { PageContent } from '../../PageContent/index.js';
|
|
6
|
+
import Button from '../Button/index.js';
|
|
7
|
+
import Loader from '../Loading/index.js';
|
|
8
|
+
|
|
9
|
+
/** Shared error page with a single way out: back to the providers (sign-in) screen. */
|
|
10
|
+
const ErrorFallbackPage = ({ header, description }) => {
|
|
11
|
+
const { setRoute } = useOpenfort();
|
|
12
|
+
const { user } = useOpenfortCore();
|
|
13
|
+
return (jsxs(PageContent, { onBack: routes.PROVIDERS, children: [jsx(Loader, { header: header, isError: true, description: description }), jsx(Button, { onClick: () => setRoute(routes.PROVIDERS), children: user ? 'Go back' : 'Back to sign in' })] }));
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { ErrorFallbackPage as default };
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import ErrorFallbackPage from '../ErrorFallbackPage/index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Catch-all page for flows that would otherwise spin forever
|
|
6
|
+
* (loading watchdog timeouts, unreachable states).
|
|
7
|
+
*/
|
|
8
|
+
const NotFoundFallback = () => (jsx(ErrorFallbackPage, { header: "This is taking longer than expected", description: "We couldn't load this screen. Go back and try again." }));
|
|
9
|
+
|
|
10
|
+
export { NotFoundFallback as default };
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** True when a WalletConnect connector is configured (i.e. a projectId was provided). */
|
|
2
|
+
export declare function useHasWalletConnect(): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Shown when a WalletConnect-dependent flow is opened but no WalletConnect
|
|
5
|
+
* projectId was configured. End users get neutral copy; the actionable
|
|
6
|
+
* config hint goes to the developer console.
|
|
7
|
+
*/
|
|
8
|
+
declare const WalletConnectNotConfigured: () => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default WalletConnectNotConfigured;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { useEthereumBridge } from '../../../ethereum/OpenfortEthereumBridgeContext.js';
|
|
4
|
+
import { isWalletConnectConnector } from '../../../utils/index.js';
|
|
5
|
+
import ErrorFallbackPage from '../ErrorFallbackPage/index.js';
|
|
6
|
+
|
|
7
|
+
/** True when a WalletConnect connector is configured (i.e. a projectId was provided). */
|
|
8
|
+
function useHasWalletConnect() {
|
|
9
|
+
const bridge = useEthereumBridge();
|
|
10
|
+
return !!(bridge === null || bridge === void 0 ? void 0 : bridge.connectors.some((c) => isWalletConnectConnector(c.id)));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Shown when a WalletConnect-dependent flow is opened but no WalletConnect
|
|
14
|
+
* projectId was configured. End users get neutral copy; the actionable
|
|
15
|
+
* config hint goes to the developer console.
|
|
16
|
+
*/
|
|
17
|
+
const WalletConnectNotConfigured = () => {
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
// biome-ignore lint/suspicious/noConsole: config error must reach developers without debug mode
|
|
20
|
+
console.warn('[Openfort-React] WalletConnect is not configured: pass walletConnectProjectId to getDefaultConnectors (e.g. via your WalletConnect env variable) to enable external wallet connections.');
|
|
21
|
+
}, []);
|
|
22
|
+
return (jsx(ErrorFallbackPage, { header: "Wallet connections unavailable", description: "External wallet connections aren't available right now. Please use another sign-in method." }));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { WalletConnectNotConfigured as default, useHasWalletConnect };
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { embeddedWalletId } from '../../constants/openfort.js';
|
|
4
4
|
import { useEthereumBridge } from '../../ethereum/OpenfortEthereumBridgeContext.js';
|
|
@@ -11,6 +11,7 @@ import { walletConfigs } from '../../wallets/walletConfigs.js';
|
|
|
11
11
|
import Button from '../Common/Button/index.js';
|
|
12
12
|
import FitText from '../Common/FitText/index.js';
|
|
13
13
|
import Loader from '../Common/Loading/index.js';
|
|
14
|
+
import WalletConnectNotConfigured, { useHasWalletConnect } from '../Common/WalletConnectNotConfigured/index.js';
|
|
14
15
|
import { routes } from '../Openfort/types.js';
|
|
15
16
|
import { useOpenfort } from '../Openfort/useOpenfort.js';
|
|
16
17
|
import { PageContent } from '../PageContent/index.js';
|
|
@@ -36,6 +37,7 @@ const ConnectWithMobile = () => {
|
|
|
36
37
|
.indexOf(connector.id) !== -1);
|
|
37
38
|
const wallet = useExternalConnector(connector.id) || (walletId && walletConfigs[walletId]) || {};
|
|
38
39
|
const bridge = useEthereumBridge();
|
|
40
|
+
const hasWalletConnect = useHasWalletConnect();
|
|
39
41
|
// Only consider external wallets as "connected" — ignore the embedded wallet connector
|
|
40
42
|
const isExternalConnected = (_d = (((_a = bridge === null || bridge === void 0 ? void 0 : bridge.account) === null || _a === void 0 ? void 0 : _a.isConnected) && ((_c = (_b = bridge === null || bridge === void 0 ? void 0 : bridge.account) === null || _b === void 0 ? void 0 : _b.connector) === null || _c === void 0 ? void 0 : _c.id) !== embeddedWalletId)) !== null && _d !== void 0 ? _d : false;
|
|
41
43
|
const [status, setStatus] = useState(isExternalConnected ? states.CONNECTING : states.INIT);
|
|
@@ -87,6 +89,8 @@ const ConnectWithMobile = () => {
|
|
|
87
89
|
break;
|
|
88
90
|
}
|
|
89
91
|
}, [status]);
|
|
92
|
+
if (!hasWalletConnect)
|
|
93
|
+
return jsx(WalletConnectNotConfigured, {});
|
|
90
94
|
return (jsxs(PageContent, { children: [jsx(Loader, { header: `Connecting with ${connector.id.split(',')[0]}`, icon: wallet === null || wallet === void 0 ? void 0 : wallet.icon, isError: status === states.ERROR, description: description, onRetry: () => {
|
|
91
95
|
setStatus(isExternalConnected ? states.CONNECTING : states.INIT);
|
|
92
96
|
setDescription('');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConnectWithMobile.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ConnectWithMobile.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -9,6 +9,7 @@ import { useExternalConnector } from '../../wallets/useExternalConnectors.js';
|
|
|
9
9
|
import { CopyText } from '../Common/CopyToClipboard/CopyText.js';
|
|
10
10
|
import Loader from '../Common/Loading/index.js';
|
|
11
11
|
import { ModalBody } from '../Common/Modal/styles.js';
|
|
12
|
+
import WalletConnectNotConfigured, { useHasWalletConnect } from '../Common/WalletConnectNotConfigured/index.js';
|
|
12
13
|
import { routes } from '../Openfort/types.js';
|
|
13
14
|
import { useOpenfort } from '../Openfort/useOpenfort.js';
|
|
14
15
|
import { PageContent } from '../PageContent/index.js';
|
|
@@ -45,6 +46,7 @@ const ConnectWithWalletConnect = () => {
|
|
|
45
46
|
const { connector } = useOpenfort();
|
|
46
47
|
const wallet = useExternalConnector(connector.id);
|
|
47
48
|
const { open: openWalletConnectModal } = useWalletConnectModal();
|
|
49
|
+
const hasWalletConnect = useHasWalletConnect();
|
|
48
50
|
const [error, setError] = useState(undefined);
|
|
49
51
|
const hasOpenedRef = useRef(false);
|
|
50
52
|
const openModal = useCallback(async () => {
|
|
@@ -54,11 +56,15 @@ const ConnectWithWalletConnect = () => {
|
|
|
54
56
|
setError(error);
|
|
55
57
|
}, [openWalletConnectModal]);
|
|
56
58
|
useEffect(() => {
|
|
59
|
+
if (!hasWalletConnect)
|
|
60
|
+
return;
|
|
57
61
|
if (hasOpenedRef.current)
|
|
58
62
|
return;
|
|
59
63
|
hasOpenedRef.current = true;
|
|
60
64
|
openModal();
|
|
61
|
-
}, [openModal]);
|
|
65
|
+
}, [openModal, hasWalletConnect]);
|
|
66
|
+
if (!hasWalletConnect)
|
|
67
|
+
return jsx(WalletConnectNotConfigured, {});
|
|
62
68
|
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 }) }));
|
|
63
69
|
};
|
|
64
70
|
const ConnectWithQRCode = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConnectWithQRCode.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ConnectWithQRCode.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,10 +3,12 @@ import { ChainTypeEnum, RecoveryMethod } from '@openfort/openfort-js';
|
|
|
3
3
|
import { useState, useEffect } from 'react';
|
|
4
4
|
import { useEthereumEmbeddedWallet } from '../../../ethereum/hooks/useEthereumEmbeddedWallet.js';
|
|
5
5
|
import { toSolanaUserWallet } from '../../../hooks/openfort/walletTypes.js';
|
|
6
|
+
import { useTimedOut } from '../../../hooks/useTimedOut.js';
|
|
6
7
|
import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
|
|
7
8
|
import { useSolanaEmbeddedWallet } from '../../../solana/hooks/useSolanaEmbeddedWallet.js';
|
|
8
9
|
import { logger } from '../../../utils/logger.js';
|
|
9
10
|
import Loader from '../../Common/Loading/index.js';
|
|
11
|
+
import NotFoundFallback from '../../Common/NotFoundFallback/index.js';
|
|
10
12
|
import { createRoute, recoverRoute } from '../../Openfort/routeHelpers.js';
|
|
11
13
|
import { routes } from '../../Openfort/types.js';
|
|
12
14
|
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
@@ -32,6 +34,9 @@ const errorForChainRegistry = {
|
|
|
32
34
|
message: (errorWallets === null || errorWallets === void 0 ? void 0 : errorWallets.message) || 'There was an error loading wallets',
|
|
33
35
|
}),
|
|
34
36
|
};
|
|
37
|
+
// Watchdog: if wallet loading never settles (hung fetch, unreachable state),
|
|
38
|
+
// bail out to the not-found fallback instead of spinning forever.
|
|
39
|
+
const LOADING_TIMEOUT_MS = 10000;
|
|
35
40
|
const LoadWallets = () => {
|
|
36
41
|
var _a;
|
|
37
42
|
const { chainType, user, isLoadingAccounts } = useOpenfortCore();
|
|
@@ -41,6 +46,7 @@ const LoadWallets = () => {
|
|
|
41
46
|
const embeddedWallet = chainType === ChainTypeEnum.EVM ? ethereumWallet : solanaWallet;
|
|
42
47
|
const connectOnLogin = (_a = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.connectOnLogin) !== null && _a !== void 0 ? _a : true;
|
|
43
48
|
const [loadingUX, setLoadingUX] = useState(true);
|
|
49
|
+
const timedOut = useTimedOut(LOADING_TIMEOUT_MS);
|
|
44
50
|
const wallets = embeddedWallet.wallets;
|
|
45
51
|
const isLoadingWallets = embeddedWallet.status === 'fetching-wallets' ||
|
|
46
52
|
embeddedWallet.status === 'connecting' ||
|
|
@@ -98,6 +104,9 @@ const LoadWallets = () => {
|
|
|
98
104
|
const { isError: isErrorFromChain, message: errorMessageFromChain } = errorForChainRegistry[chainType](errorWallets);
|
|
99
105
|
const isError = !user || isErrorFromChain;
|
|
100
106
|
const errorMessage = !user ? undefined : errorMessageFromChain;
|
|
107
|
+
// Only fall back while still spinning — real errors keep their own message
|
|
108
|
+
if (timedOut && !isError)
|
|
109
|
+
return jsx(NotFoundFallback, {});
|
|
101
110
|
return (jsx(PageContent, { onBack: !user ? 'back' : null, children: jsx(Loader, { header: "Setting up wallet", isError: isError, description: isError ? errorMessage : 'Setting up wallets' }) }));
|
|
102
111
|
};
|
|
103
112
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,13 +3,18 @@ import { ChainTypeEnum, EmbeddedState } from '@openfort/openfort-js';
|
|
|
3
3
|
import React, { useEffect } from 'react';
|
|
4
4
|
import { useEthereumEmbeddedWallet } from '../../../ethereum/hooks/useEthereumEmbeddedWallet.js';
|
|
5
5
|
import { useEthereumBridge } from '../../../ethereum/OpenfortEthereumBridgeContext.js';
|
|
6
|
+
import { useTimedOut } from '../../../hooks/useTimedOut.js';
|
|
6
7
|
import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
|
|
7
8
|
import { useSolanaEmbeddedWallet } from '../../../solana/hooks/useSolanaEmbeddedWallet.js';
|
|
8
9
|
import Loader from '../../Common/Loading/index.js';
|
|
10
|
+
import NotFoundFallback from '../../Common/NotFoundFallback/index.js';
|
|
9
11
|
import { routes } from '../../Openfort/types.js';
|
|
10
12
|
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
11
13
|
import { PageContent } from '../../PageContent/index.js';
|
|
12
14
|
|
|
15
|
+
// Watchdog: if no state transition routes us away within this window, the modal
|
|
16
|
+
// would otherwise spin forever (e.g. opened while signed out, or a misconfigured SDK).
|
|
17
|
+
const LOADING_TIMEOUT_MS = 10000;
|
|
13
18
|
const Loading = () => {
|
|
14
19
|
const { setRoute, walletConfig } = useOpenfort();
|
|
15
20
|
const { user, isLoadingAccounts, isLoading, needsRecovery, embeddedState } = useOpenfortCore();
|
|
@@ -25,6 +30,7 @@ const Loading = () => {
|
|
|
25
30
|
const address = embeddedConnected ? wallet.address : bridgeConnected ? bridge === null || bridge === void 0 ? void 0 : bridge.account.address : undefined;
|
|
26
31
|
const [isFirstFrame, setIsFirstFrame] = React.useState(true);
|
|
27
32
|
const [retryCount, setRetryCount] = React.useState(0);
|
|
33
|
+
const timedOut = useTimedOut(LOADING_TIMEOUT_MS);
|
|
28
34
|
useEffect(() => {
|
|
29
35
|
if (isFirstFrame)
|
|
30
36
|
return;
|
|
@@ -65,6 +71,8 @@ const Loading = () => {
|
|
|
65
71
|
// UX: Wait a bit before showing the next page
|
|
66
72
|
setTimeout(() => setIsFirstFrame(false), 400);
|
|
67
73
|
}, []);
|
|
74
|
+
if (timedOut)
|
|
75
|
+
return jsx(NotFoundFallback, {});
|
|
68
76
|
return (jsx(PageContent, { children: jsx(Loader, { header: "Redirecting" }) }));
|
|
69
77
|
};
|
|
70
78
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -7,6 +7,7 @@ import { CopyButton } from '../../Common/CopyToClipboard/CopyButton.js';
|
|
|
7
7
|
import { ModalContent } from '../../Common/Modal/styles.js';
|
|
8
8
|
import { ScrollArea } from '../../Common/ScrollArea/index.js';
|
|
9
9
|
import { Spinner } from '../../Common/Spinner/index.js';
|
|
10
|
+
import WalletConnectNotConfigured, { useHasWalletConnect } from '../../Common/WalletConnectNotConfigured/index.js';
|
|
10
11
|
import { routes } from '../../Openfort/types.js';
|
|
11
12
|
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
12
13
|
import { PageContent } from '../../PageContent/index.js';
|
|
@@ -19,6 +20,7 @@ const MobileConnectors = () => {
|
|
|
19
20
|
const locales = useLocales();
|
|
20
21
|
const { open: openW3M, isOpen: isOpenW3M } = useWalletConnectModal();
|
|
21
22
|
const wallets = useExternalConnectors();
|
|
23
|
+
const hasWalletConnect = useHasWalletConnect();
|
|
22
24
|
// filter out installed wallets
|
|
23
25
|
const walletsIdsToDisplay = (_a = Object.keys(walletConfigs).filter((walletId) => {
|
|
24
26
|
const wallet = walletConfigs[walletId];
|
|
@@ -32,6 +34,9 @@ const MobileConnectors = () => {
|
|
|
32
34
|
context.setRoute(routes.CONNECT_WITH_MOBILE);
|
|
33
35
|
context.setConnector({ id: walletId });
|
|
34
36
|
};
|
|
37
|
+
// Every wallet on this page connects through WalletConnect deeplinks
|
|
38
|
+
if (!hasWalletConnect)
|
|
39
|
+
return jsx(WalletConnectNotConfigured, {});
|
|
35
40
|
return (jsx(PageContent, { width: 312, onBack: routes.PROVIDERS, children: jsxs(Container, { children: [jsx(ModalContent, { style: { paddingBottom: 0 }, children: jsx(ScrollArea, { height: 340, children: jsxs(WalletList, { children: [walletsIdsToDisplay
|
|
36
41
|
.sort(
|
|
37
42
|
// sort by name
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -256,7 +256,10 @@ const SendConfirmation = () => {
|
|
|
256
256
|
}
|
|
257
257
|
}, [isPollingBalance, currentBalance]);
|
|
258
258
|
const handleConfirm = async () => {
|
|
259
|
-
|
|
259
|
+
// Block re-entry while submitting, and never submit when a tx already
|
|
260
|
+
// exists for this send — a second `eth_sendTransaction` is the duplicate
|
|
261
|
+
// transaction the customer hit after the wallet was slow to respond.
|
|
262
|
+
if (submittingRef.current || transactionHash)
|
|
260
263
|
return;
|
|
261
264
|
if (!recipientAddress || !parsedAmount || parsedAmount <= BigInt(0) || insufficientBalance)
|
|
262
265
|
return;
|
|
@@ -279,8 +282,10 @@ const SendConfirmation = () => {
|
|
|
279
282
|
});
|
|
280
283
|
}
|
|
281
284
|
}
|
|
282
|
-
catch
|
|
283
|
-
//
|
|
285
|
+
catch {
|
|
286
|
+
// The error is already recorded in nativeError/erc20Error (which drive
|
|
287
|
+
// firstError and the error UI) before being re-thrown — we only catch
|
|
288
|
+
// here to stop it becoming an unhandled rejection.
|
|
284
289
|
}
|
|
285
290
|
finally {
|
|
286
291
|
submittingRef.current = false;
|
|
@@ -331,7 +336,14 @@ const SendConfirmation = () => {
|
|
|
331
336
|
width: '100%',
|
|
332
337
|
color: 'var(--ck-body-color-valid)',
|
|
333
338
|
fontSize: '12px',
|
|
334
|
-
}, children: "Sponsored transaction" }))] })] }), insufficientBalance && !isSuccess && (jsx(StatusMessage, { "$status": "error", children: "Insufficient balance for this transfer." })), errorDetails && (jsxs(ErrorContainer, { children: [jsx(ErrorTitle, { children: errorDetails.title }), jsx(ErrorMessage, { children: errorDetails.message }), errorDetails.action && jsx(ErrorAction, { children: errorDetails.action })] })), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: isSuccess ? handleOpenBlockExplorer : handleConfirm, disabled: isSuccess
|
|
339
|
+
}, children: "Sponsored transaction" }))] })] }), insufficientBalance && !isSuccess && (jsx(StatusMessage, { "$status": "error", children: "Insufficient balance for this transfer." })), errorDetails && (jsxs(ErrorContainer, { children: [jsx(ErrorTitle, { children: errorDetails.title }), jsx(ErrorMessage, { children: errorDetails.message }), errorDetails.action && jsx(ErrorAction, { children: errorDetails.action })] })), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: isSuccess ? handleOpenBlockExplorer : handleConfirm, disabled: isSuccess
|
|
340
|
+
? false
|
|
341
|
+
: isLoading ||
|
|
342
|
+
Boolean(transactionHash) ||
|
|
343
|
+
!recipientAddress ||
|
|
344
|
+
!parsedAmount ||
|
|
345
|
+
parsedAmount <= BigInt(0) ||
|
|
346
|
+
insufficientBalance, waiting: isLoading, icon: isSuccess ? jsx(TickIcon, { style: { width: 18, height: 18 } }) : undefined, children: isSuccess ? 'Confirmed' : isLoading ? 'Confirming...' : 'Confirm' }), isSuccess ? (jsx(Button, { variant: "secondary", onClick: handleFinish, children: "Back to profile" })) : (jsx(Button, { variant: "secondary", onClick: handleCancel, disabled: isLoading, children: "Cancel" }))] })] }));
|
|
335
347
|
};
|
|
336
348
|
|
|
337
349
|
export { SendConfirmation as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -22,7 +22,12 @@ const safeRoutes = {
|
|
|
22
22
|
routes.PROVIDERS,
|
|
23
23
|
],
|
|
24
24
|
};
|
|
25
|
-
|
|
25
|
+
/** Route can be selected by string (route name) or by object with `route` property */
|
|
26
|
+
function routeMatches(a, b) {
|
|
27
|
+
const aRoute = typeof a === 'object' && a !== null && 'route' in a ? a.route : a;
|
|
28
|
+
const bRoute = typeof b === 'object' && b !== null && 'route' in b ? b.route : b;
|
|
29
|
+
return aRoute === bRoute;
|
|
30
|
+
}
|
|
26
31
|
/** Connector id must be a connector (e.g. injected, walletConnect), not an Openfort account id. */
|
|
27
32
|
function isAccountId(id) {
|
|
28
33
|
return id.startsWith('acc_');
|
|
@@ -84,27 +89,18 @@ function useUI() {
|
|
|
84
89
|
setRoute(routes.CONNECTED);
|
|
85
90
|
}
|
|
86
91
|
const gotoAndOpen = (route) => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (!safeRoutes.connected.includes(route)) {
|
|
95
|
-
validRoute = routes.CONNECTED;
|
|
96
|
-
logger.log(`Route ${route} is not a valid route when connected, navigating to ${validRoute} instead.`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
if (!safeRoutes.disconnected.includes(route)) {
|
|
101
|
-
validRoute = routes.PROVIDERS;
|
|
102
|
-
logger.log(`Route ${route} is not a valid route when disconnected, navigating to ${validRoute} instead.`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
92
|
+
const safeList = isConnected ? safeRoutes.connected : safeRoutes.disconnected;
|
|
93
|
+
const fallback = isConnected ? routes.CONNECTED : routes.PROVIDERS;
|
|
94
|
+
// Navigate using the allowlisted spec so vetted options (e.g. connectType) are enforced,
|
|
95
|
+
// not whatever the caller passed alongside a matching route name.
|
|
96
|
+
const match = safeList.find((r) => routeMatches(r, route));
|
|
97
|
+
if (!match) {
|
|
98
|
+
logger.log(`Route ${JSON.stringify(route)} is not valid when ${isConnected ? 'connected' : 'disconnected'}, navigating to ${fallback} instead.`);
|
|
105
99
|
}
|
|
106
|
-
|
|
100
|
+
// setOpen(true) resets route/history/connector for a clean session, so it MUST run
|
|
101
|
+
// before setRoute — otherwise it clobbers the requested route back to LOADING.
|
|
107
102
|
setOpen(true);
|
|
103
|
+
setRoute(match !== null && match !== void 0 ? match : fallback);
|
|
108
104
|
};
|
|
109
105
|
return {
|
|
110
106
|
isOpen: open,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUI.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useUI.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
/** Returns true once `ms` milliseconds have elapsed since mount. */
|
|
4
|
+
function useTimedOut(ms) {
|
|
5
|
+
const [timedOut, setTimedOut] = useState(false);
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const timeout = setTimeout(() => setTimedOut(true), ms);
|
|
8
|
+
return () => clearTimeout(timeout);
|
|
9
|
+
}, [ms]);
|
|
10
|
+
return timedOut;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { useTimedOut };
|
|
14
|
+
//# sourceMappingURL=useTimedOut.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTimedOut.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
|
package/build/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const OPENFORT_VERSION = "1.1.
|
|
1
|
+
export declare const OPENFORT_VERSION = "1.1.4";
|
package/build/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfort/react",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
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.",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"react"
|
|
66
66
|
],
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@openfort/openfort-js": "^1.3.
|
|
68
|
+
"@openfort/openfort-js": "^1.3.9",
|
|
69
69
|
"buffer": "^6.0.3",
|
|
70
70
|
"detect-browser": "^5.3.0",
|
|
71
71
|
"fast-password-entropy": "^1.1.1",
|