@rango-dev/widget-embedded 0.1.10-next.99 → 0.1.11-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.d.ts.map +1 -1
- package/dist/QueueManager.d.ts.map +1 -1
- package/dist/components/AppRouter.d.ts +6 -1
- package/dist/components/AppRouter.d.ts.map +1 -1
- package/dist/components/AppRoutes.d.ts.map +1 -1
- package/dist/components/HeaderButtons.d.ts +4 -1
- package/dist/components/HeaderButtons.d.ts.map +1 -1
- package/dist/components/Layout.d.ts.map +1 -1
- package/dist/components/PercentageChange.d.ts +9 -0
- package/dist/components/PercentageChange.d.ts.map +1 -0
- package/dist/components/SwapDetailsPlaceholder.d.ts +9 -0
- package/dist/components/SwapDetailsPlaceholder.d.ts.map +1 -0
- package/dist/components/TokenInfo.d.ts.map +1 -1
- package/dist/components/TokenPreview.d.ts +3 -2
- package/dist/components/TokenPreview.d.ts.map +1 -1
- package/dist/components/UpdateUrl.d.ts.map +1 -1
- package/dist/components/warnings/BalanceWarnings.d.ts.map +1 -1
- package/dist/components/warnings/MinRequiredSlippage.d.ts +1 -1
- package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -1
- package/dist/constants/navigationRoutes.d.ts +0 -1
- package/dist/constants/navigationRoutes.d.ts.map +1 -1
- package/dist/globalStyles.d.ts.map +1 -1
- package/dist/hooks/useConfirmSwap.d.ts.map +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
- package/dist/pages/HistoryPage.d.ts.map +1 -1
- package/dist/pages/Home.d.ts.map +1 -1
- package/dist/pages/LiquiditySourcesPage.d.ts.map +1 -1
- package/dist/pages/SelectTokenPage.d.ts.map +1 -1
- package/dist/pages/SettingsPage.d.ts.map +1 -1
- package/dist/pages/SwapDetailsPage.d.ts.map +1 -1
- package/dist/pages/WalletsPage.d.ts +1 -0
- package/dist/pages/WalletsPage.d.ts.map +1 -1
- package/dist/store/bestRoute.d.ts +3 -0
- package/dist/store/bestRoute.d.ts.map +1 -1
- package/dist/store/ui.d.ts.map +1 -1
- package/dist/store/wallets.d.ts +14 -0
- package/dist/store/wallets.d.ts.map +1 -1
- package/dist/types/routing.d.ts +15 -2
- package/dist/types/routing.d.ts.map +1 -1
- package/dist/types/swap.d.ts +6 -0
- package/dist/types/swap.d.ts.map +1 -1
- package/dist/utils/common.d.ts +1 -0
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/date.d.ts +3 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/routing.d.ts +3 -2
- package/dist/utils/routing.d.ts.map +1 -1
- package/dist/utils/swap.d.ts +16 -5
- package/dist/utils/swap.d.ts.map +1 -1
- package/dist/utils/time.d.ts +4 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/wallets.d.ts +1 -1
- package/dist/utils/wallets.d.ts.map +1 -1
- package/dist/widget-embedded.cjs.development.js +1122 -719
- package/dist/widget-embedded.cjs.development.js.map +1 -1
- package/dist/widget-embedded.cjs.production.min.js +1122 -719
- package/dist/widget-embedded.cjs.production.min.js.map +1 -1
- package/dist/widget-embedded.esm.js +1131 -728
- package/dist/widget-embedded.esm.js.map +1 -1
- package/package.json +12 -11
- package/readme.md +1 -2
- package/src/App.tsx +30 -5
- package/src/QueueManager.tsx +5 -2
- package/src/components/AppRouter.tsx +24 -13
- package/src/components/AppRoutes.tsx +15 -12
- package/src/components/HeaderButtons.tsx +9 -2
- package/src/components/Layout.tsx +37 -5
- package/src/components/PercentageChange.tsx +33 -0
- package/src/components/SwapDetailsPlaceholder.tsx +32 -0
- package/src/components/TokenInfo.tsx +20 -4
- package/src/components/TokenPreview.tsx +17 -6
- package/src/components/UpdateUrl.tsx +1 -3
- package/src/components/warnings/BalanceWarnings.tsx +1 -0
- package/src/components/warnings/MinRequiredSlippage.tsx +9 -4
- package/src/constants/navigationRoutes.ts +0 -1
- package/src/globalStyles.ts +2 -1
- package/src/hooks/useConfirmSwap.ts +2 -1
- package/src/hooks/useNavigateBack.ts +3 -3
- package/src/lib.tsx +25 -3
- package/src/pages/ConfirmSwapPage.tsx +133 -20
- package/src/pages/HistoryPage.tsx +4 -4
- package/src/pages/Home.tsx +27 -22
- package/src/pages/LiquiditySourcesPage.tsx +2 -0
- package/src/pages/SelectTokenPage.tsx +3 -1
- package/src/pages/SettingsPage.tsx +3 -0
- package/src/pages/SwapDetailsPage.tsx +142 -6
- package/src/pages/WalletsPage.tsx +47 -11
- package/src/store/bestRoute.ts +143 -16
- package/src/store/ui.ts +4 -0
- package/src/store/wallets.ts +4 -1
- package/src/types/routing.ts +18 -2
- package/src/types/swap.ts +7 -0
- package/src/utils/common.ts +14 -0
- package/src/utils/date.ts +62 -0
- package/src/utils/routing.ts +36 -20
- package/src/utils/swap.ts +103 -11
- package/src/utils/time.ts +52 -0
- package/src/utils/wallets.ts +13 -4
- package/dist/components/Header.d.ts +0 -10
- package/dist/components/Header.d.ts.map +0 -1
- package/dist/pages/ConfirmWalletsPage.d.ts +0 -3
- package/dist/pages/ConfirmWalletsPage.d.ts.map +0 -1
- package/src/components/Header.tsx +0 -37
- package/src/pages/ConfirmWalletsPage.tsx +0 -127
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
3
3
|
import useCopyToClipboard from '../hooks/useCopyToClipboard';
|
|
4
4
|
import { useManager } from '@rango-dev/queue-manager-react';
|
|
@@ -6,33 +6,169 @@ import { useNavigateBack } from '../hooks/useNavigateBack';
|
|
|
6
6
|
import { getPendingSwaps } from '../utils/queue';
|
|
7
7
|
import { SwapHistory } from '@rango-dev/ui';
|
|
8
8
|
import { useUiStore } from '../store/ui';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
cancelSwap,
|
|
11
|
+
PendingSwapNetworkStatus,
|
|
12
|
+
} from '@rango-dev/queue-manager-rango-preset';
|
|
13
|
+
import { useWallets } from '@rango-dev/wallets-core';
|
|
14
|
+
import {
|
|
15
|
+
getCurrentBlockchainOfOrNull,
|
|
16
|
+
getCurrentStep,
|
|
17
|
+
getRelatedWalletOrNull,
|
|
18
|
+
} from '@rango-dev/queue-manager-rango-preset';
|
|
19
|
+
import { getSwapDate } from '../utils/time';
|
|
20
|
+
import { useNavigate } from 'react-router-dom';
|
|
21
|
+
import { useBestRouteStore } from '../store/bestRoute';
|
|
22
|
+
import {
|
|
23
|
+
getLastConvertedTokenInFailedSwap,
|
|
24
|
+
getSwapMessages,
|
|
25
|
+
isNetworkStatusInWarningState,
|
|
26
|
+
shouldRetrySwap,
|
|
27
|
+
} from '../utils/swap';
|
|
28
|
+
import { TokenPreview } from '../components/TokenPreview';
|
|
29
|
+
import { Spacer } from '@rango-dev/ui';
|
|
30
|
+
import { numberToString } from '../utils/numbers';
|
|
31
|
+
//@ts-ignore
|
|
32
|
+
import { t } from 'i18next';
|
|
33
|
+
import { SwapDetailsPlaceholder } from '../components/SwapDetailsPlaceholder';
|
|
10
34
|
|
|
11
35
|
export function SwapDetailsPage() {
|
|
12
36
|
const selectedSwapRequestId = useUiStore.use.selectedSwapRequestId();
|
|
37
|
+
const { canSwitchNetworkTo, connect } = useWallets();
|
|
38
|
+
const retry = useBestRouteStore.use.retry();
|
|
39
|
+
const navigate = useNavigate();
|
|
13
40
|
const { navigateBackFrom } = useNavigateBack();
|
|
14
|
-
const { manager } = useManager();
|
|
15
41
|
const [isCopied, handleCopy] = useCopyToClipboard(2000);
|
|
42
|
+
const { manager } = useManager();
|
|
43
|
+
|
|
44
|
+
const [loading, setLoading] = useState(true);
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
setLoading(false);
|
|
49
|
+
}, 5000);
|
|
50
|
+
}, []);
|
|
16
51
|
|
|
17
52
|
const pendingSwaps = getPendingSwaps(manager);
|
|
18
53
|
const selectedSwap = pendingSwaps.find(
|
|
19
54
|
({ swap }) => swap.requestId === selectedSwapRequestId
|
|
20
55
|
);
|
|
21
56
|
|
|
22
|
-
//TODO: implement swap cancellation (move queueManager logic to queueManager/rango-preset)
|
|
23
57
|
const onCancel = () => {
|
|
24
|
-
const swap =
|
|
58
|
+
const swap = manager?.get(selectedSwap?.id!);
|
|
25
59
|
if (swap) cancelSwap(swap);
|
|
26
60
|
};
|
|
61
|
+
const swap = selectedSwap?.swap;
|
|
62
|
+
|
|
63
|
+
if (!swap)
|
|
64
|
+
return (
|
|
65
|
+
<SwapDetailsPlaceholder
|
|
66
|
+
requestId={selectedSwapRequestId || ''}
|
|
67
|
+
loading={loading}
|
|
68
|
+
onBack={navigateBackFrom.bind(null, navigationRoutes.swapDetails)}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const firstStep = swap.steps[0];
|
|
73
|
+
const lastStep = swap.steps[swap.steps.length - 1];
|
|
74
|
+
const fromAmount = numberToString(swap.inputAmount);
|
|
75
|
+
const toAmount = numberToString(swap.simulationResult.outputAmount);
|
|
76
|
+
|
|
77
|
+
const currentStep = getCurrentStep(swap);
|
|
78
|
+
|
|
79
|
+
const currentStepBlockchain = currentStep
|
|
80
|
+
? getCurrentBlockchainOfOrNull(swap, currentStep)
|
|
81
|
+
: null;
|
|
82
|
+
const currentStepWallet = currentStep
|
|
83
|
+
? getRelatedWalletOrNull(swap, currentStep)
|
|
84
|
+
: null;
|
|
85
|
+
const currentStepNetworkStatus = currentStep?.networkStatus;
|
|
86
|
+
|
|
87
|
+
const swapMessages = getSwapMessages(swap, currentStep);
|
|
88
|
+
|
|
89
|
+
const networkWarningState = isNetworkStatusInWarningState(currentStep);
|
|
90
|
+
|
|
91
|
+
const swapDate = getSwapDate(swap);
|
|
92
|
+
|
|
93
|
+
const shouldRetry = shouldRetrySwap(swap);
|
|
94
|
+
|
|
95
|
+
const switchNetwork =
|
|
96
|
+
!!currentStepBlockchain &&
|
|
97
|
+
!!currentStepWallet?.walletType &&
|
|
98
|
+
currentStepNetworkStatus ===
|
|
99
|
+
PendingSwapNetworkStatus.WaitingForNetworkChange &&
|
|
100
|
+
canSwitchNetworkTo(currentStepWallet?.walletType, currentStepBlockchain)
|
|
101
|
+
? connect.bind(null, currentStepWallet.walletType, currentStepBlockchain)
|
|
102
|
+
: undefined;
|
|
103
|
+
|
|
104
|
+
const lastConvertedTokenInFailedSwap =
|
|
105
|
+
getLastConvertedTokenInFailedSwap(swap);
|
|
106
|
+
|
|
27
107
|
return (
|
|
28
108
|
<SwapHistory
|
|
29
109
|
onBack={navigateBackFrom.bind(null, navigationRoutes.swapDetails)}
|
|
110
|
+
previewInputs={
|
|
111
|
+
<>
|
|
112
|
+
<TokenPreview
|
|
113
|
+
chain={{
|
|
114
|
+
displayName: firstStep?.fromBlockchain || '',
|
|
115
|
+
// @ts-ignore
|
|
116
|
+
logo: firstStep?.fromBlockchainLogo || '',
|
|
117
|
+
}}
|
|
118
|
+
token={{
|
|
119
|
+
symbol: firstStep?.fromSymbol || '',
|
|
120
|
+
image: firstStep?.fromLogo || '',
|
|
121
|
+
}}
|
|
122
|
+
amount={fromAmount}
|
|
123
|
+
label={t('From')}
|
|
124
|
+
loadingStatus={'success'}
|
|
125
|
+
/>
|
|
126
|
+
<Spacer size={12} direction="vertical" />
|
|
127
|
+
<TokenPreview
|
|
128
|
+
chain={{
|
|
129
|
+
displayName: lastStep?.toBlockchain || '',
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
logo: lastStep?.toBlockchainLogo || '',
|
|
132
|
+
}}
|
|
133
|
+
token={{
|
|
134
|
+
symbol: lastStep?.toSymbol || '',
|
|
135
|
+
image: lastStep?.toLogo || '',
|
|
136
|
+
}}
|
|
137
|
+
amount={toAmount}
|
|
138
|
+
label={t('To')}
|
|
139
|
+
loadingStatus={'success'}
|
|
140
|
+
/>
|
|
141
|
+
</>
|
|
142
|
+
}
|
|
30
143
|
//todo: move PendingSwap type to rango-types
|
|
31
144
|
//@ts-ignore
|
|
32
|
-
pendingSwap={
|
|
145
|
+
pendingSwap={swap}
|
|
33
146
|
onCopy={handleCopy}
|
|
34
147
|
isCopied={isCopied}
|
|
35
148
|
onCancel={onCancel}
|
|
149
|
+
shortMessage={swapMessages.shortMessage}
|
|
150
|
+
detailedMessage={swapMessages.detailedMessage}
|
|
151
|
+
currentStepBlockchain={currentStepBlockchain || ''}
|
|
152
|
+
switchNetwork={switchNetwork}
|
|
153
|
+
type={
|
|
154
|
+
networkWarningState ? 'warning' : swap.extraMessageSeverity || undefined
|
|
155
|
+
}
|
|
156
|
+
date={swapDate}
|
|
157
|
+
{...(shouldRetry && {
|
|
158
|
+
onRetry: () => {
|
|
159
|
+
retry(swap);
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
navigate(navigationRoutes.home);
|
|
162
|
+
}, 0);
|
|
163
|
+
},
|
|
164
|
+
})}
|
|
165
|
+
{...(lastConvertedTokenInFailedSwap && {
|
|
166
|
+
lastConvertedTokenInFailedSwap: {
|
|
167
|
+
blockchain: lastConvertedTokenInFailedSwap.blockchain,
|
|
168
|
+
outputAmount: lastConvertedTokenInFailedSwap.outputAmount || '',
|
|
169
|
+
symbol: lastConvertedTokenInFailedSwap.symbol,
|
|
170
|
+
},
|
|
171
|
+
})}
|
|
36
172
|
/>
|
|
37
173
|
);
|
|
38
174
|
}
|
|
@@ -4,8 +4,9 @@ import {
|
|
|
4
4
|
styled,
|
|
5
5
|
Wallet,
|
|
6
6
|
WalletState,
|
|
7
|
+
WalletInfo,
|
|
7
8
|
} from '@rango-dev/ui';
|
|
8
|
-
import React, { useEffect, useState } from 'react';
|
|
9
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
9
10
|
import { getlistWallet, sortWalletsBasedOnState } from '../utils/wallets';
|
|
10
11
|
import { WalletType, detectMobileScreens } from '@rango-dev/wallets-shared';
|
|
11
12
|
import { useWallets } from '@rango-dev/wallets-core';
|
|
@@ -14,6 +15,9 @@ import { useUiStore } from '../store/ui';
|
|
|
14
15
|
import { useNavigateBack } from '../hooks/useNavigateBack';
|
|
15
16
|
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
16
17
|
import { useTranslation } from 'react-i18next';
|
|
18
|
+
import { useMetaStore } from '../store/meta';
|
|
19
|
+
import { Spinner } from '@rango-dev/ui';
|
|
20
|
+
import { LoadingFailedAlert } from '@rango-dev/ui';
|
|
17
21
|
|
|
18
22
|
interface PropTypes {
|
|
19
23
|
supportedWallets: 'all' | WalletType[];
|
|
@@ -24,9 +28,17 @@ const ListContainer = styled('div', {
|
|
|
24
28
|
display: 'grid',
|
|
25
29
|
gap: '.5rem',
|
|
26
30
|
gridTemplateColumns: ' repeat(2, minmax(0, 1fr))',
|
|
27
|
-
height: '450px',
|
|
28
31
|
alignContent: 'baseline',
|
|
29
32
|
padding: '0.5rem',
|
|
33
|
+
overflowY: 'auto',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const LoaderContainer = styled('div', {
|
|
37
|
+
display: 'flex',
|
|
38
|
+
justifyContent: 'center',
|
|
39
|
+
width: '100%',
|
|
40
|
+
position: 'absolute',
|
|
41
|
+
top: '50%',
|
|
30
42
|
});
|
|
31
43
|
|
|
32
44
|
const AlertContainer = styled('div', {
|
|
@@ -40,6 +52,7 @@ export function WalletsPage({ supportedWallets, multiWallets }: PropTypes) {
|
|
|
40
52
|
getWalletInfo,
|
|
41
53
|
supportedWallets === 'all' ? Object.values(WalletType) : supportedWallets
|
|
42
54
|
);
|
|
55
|
+
const walletsRef = useRef<WalletInfo[]>();
|
|
43
56
|
|
|
44
57
|
let sortedWallets = detectMobileScreens()
|
|
45
58
|
? wallets.filter((wallet) => wallet.showOnMobile)
|
|
@@ -48,6 +61,7 @@ export function WalletsPage({ supportedWallets, multiWallets }: PropTypes) {
|
|
|
48
61
|
const [walletErrorMessage, setWalletErrorMessage] = useState('');
|
|
49
62
|
const toggleConnectWalletsButton =
|
|
50
63
|
useUiStore.use.toggleConnectWalletsButton();
|
|
64
|
+
const loadingMetaStatus = useMetaStore.use.loadingStatus();
|
|
51
65
|
const { t } = useTranslation();
|
|
52
66
|
|
|
53
67
|
const onSelectWallet = async (type: WalletType) => {
|
|
@@ -69,12 +83,27 @@ export function WalletsPage({ supportedWallets, multiWallets }: PropTypes) {
|
|
|
69
83
|
setWalletErrorMessage('Error: ' + (e as any)?.message);
|
|
70
84
|
}
|
|
71
85
|
};
|
|
72
|
-
|
|
86
|
+
const disconnectConnectingWallets = () => {
|
|
87
|
+
const connectingWallets =
|
|
88
|
+
walletsRef.current?.filter(
|
|
89
|
+
(wallet) => wallet.state === WalletState.CONNECTING
|
|
90
|
+
) || [];
|
|
91
|
+
for (const wallet of connectingWallets) {
|
|
92
|
+
disconnect(wallet.type);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
73
95
|
useEffect(() => {
|
|
74
96
|
toggleConnectWalletsButton();
|
|
75
|
-
return () =>
|
|
97
|
+
return () => {
|
|
98
|
+
disconnectConnectingWallets();
|
|
99
|
+
toggleConnectWalletsButton();
|
|
100
|
+
};
|
|
76
101
|
}, []);
|
|
77
102
|
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
walletsRef.current = wallets;
|
|
105
|
+
}, [wallets]);
|
|
106
|
+
|
|
78
107
|
return (
|
|
79
108
|
<SecondaryPage
|
|
80
109
|
title={t('Select Wallet') || ''}
|
|
@@ -87,14 +116,21 @@ export function WalletsPage({ supportedWallets, multiWallets }: PropTypes) {
|
|
|
87
116
|
<Alert type="error">{walletErrorMessage}</Alert>
|
|
88
117
|
</AlertContainer>
|
|
89
118
|
)}
|
|
119
|
+
{loadingMetaStatus === 'loading' && (
|
|
120
|
+
<LoaderContainer className="loader">
|
|
121
|
+
<Spinner size={24} />
|
|
122
|
+
</LoaderContainer>
|
|
123
|
+
)}
|
|
124
|
+
{loadingMetaStatus === 'failed' && <LoadingFailedAlert />}
|
|
90
125
|
<ListContainer>
|
|
91
|
-
{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
126
|
+
{loadingMetaStatus === 'success' &&
|
|
127
|
+
sortedWallets.map((wallet, index) => (
|
|
128
|
+
<Wallet
|
|
129
|
+
{...wallet}
|
|
130
|
+
key={`${index}-${wallet.type}`}
|
|
131
|
+
onClick={onSelectWallet}
|
|
132
|
+
/>
|
|
133
|
+
))}
|
|
98
134
|
</ListContainer>
|
|
99
135
|
</>
|
|
100
136
|
</SecondaryPage>
|
package/src/store/bestRoute.ts
CHANGED
|
@@ -13,10 +13,15 @@ import { httpService } from '../services/httpService';
|
|
|
13
13
|
import { useSettingsStore } from './settings';
|
|
14
14
|
import { calcOutputUsdValue, createBestRouteRequestBody } from '../utils/swap';
|
|
15
15
|
import { useMetaStore } from './meta';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
getDefaultToken,
|
|
18
|
+
getSortedTokens,
|
|
19
|
+
tokensAreEqual,
|
|
20
|
+
} from '../utils/wallets';
|
|
17
21
|
import { useWalletsStore } from './wallets';
|
|
18
22
|
import { TokenWithBalance } from '../pages/SelectTokenPage';
|
|
19
|
-
|
|
23
|
+
import { PendingSwap } from '@rango-dev/queue-manager-rango-preset/dist/shared';
|
|
24
|
+
import { debounce } from '../utils/common';
|
|
20
25
|
const getUsdValue = (token: Token | null, amount: string) =>
|
|
21
26
|
new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0);
|
|
22
27
|
|
|
@@ -43,6 +48,8 @@ export interface RouteState {
|
|
|
43
48
|
setInputAmount: (amount: string) => void;
|
|
44
49
|
bestRoute: BestRouteResponse | null;
|
|
45
50
|
setBestRoute: (bestRoute: BestRouteResponse | null) => void;
|
|
51
|
+
retry: (pendingSwap: PendingSwap) => void;
|
|
52
|
+
switchFromAndTo: () => void;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
export const useBestRouteStore = createSelectors(
|
|
@@ -65,6 +72,7 @@ export const useBestRouteStore = createSelectors(
|
|
|
65
72
|
set((state) => {
|
|
66
73
|
let outputAmount: BigNumber | null = null;
|
|
67
74
|
let outputUsdValue: BigNumber = ZERO;
|
|
75
|
+
if (!state.inputAmount || state.inputAmount === '0') return {};
|
|
68
76
|
if (!!bestRoute) {
|
|
69
77
|
outputAmount = !!bestRoute.result?.outputAmount
|
|
70
78
|
? new BigNumber(bestRoute.result?.outputAmount)
|
|
@@ -151,6 +159,85 @@ export const useBestRouteStore = createSelectors(
|
|
|
151
159
|
}),
|
|
152
160
|
}));
|
|
153
161
|
},
|
|
162
|
+
retry: (pendingSwap) => {
|
|
163
|
+
const { tokens, blockchains } = useMetaStore.getState().meta;
|
|
164
|
+
const balances = useWalletsStore.getState().balances;
|
|
165
|
+
const failedIndex =
|
|
166
|
+
pendingSwap.status === 'failed'
|
|
167
|
+
? pendingSwap.steps.findIndex((s) => s.status === 'failed')
|
|
168
|
+
: null;
|
|
169
|
+
|
|
170
|
+
if (failedIndex === null || failedIndex < 0) return;
|
|
171
|
+
|
|
172
|
+
const firstStep = pendingSwap.steps[0];
|
|
173
|
+
const lastStep = pendingSwap.steps[pendingSwap.steps.length - 1];
|
|
174
|
+
const fromChain =
|
|
175
|
+
blockchains.find(
|
|
176
|
+
(blockchain) => blockchain.name === firstStep.fromBlockchain
|
|
177
|
+
) || null;
|
|
178
|
+
const toChain =
|
|
179
|
+
blockchains.find(
|
|
180
|
+
(blockchain) => blockchain.name === lastStep.toBlockchain
|
|
181
|
+
) || null;
|
|
182
|
+
|
|
183
|
+
const fromToken = tokens.find((token) =>
|
|
184
|
+
tokensAreEqual(token, {
|
|
185
|
+
blockchain: firstStep.fromBlockchain,
|
|
186
|
+
symbol: firstStep.fromSymbol,
|
|
187
|
+
address: firstStep.fromSymbolAddress,
|
|
188
|
+
})
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const toToken = tokens.find((token) =>
|
|
192
|
+
tokensAreEqual(token, {
|
|
193
|
+
blockchain: lastStep.toBlockchain,
|
|
194
|
+
symbol: lastStep.toSymbol,
|
|
195
|
+
address: lastStep.toSymbolAddress,
|
|
196
|
+
})
|
|
197
|
+
);
|
|
198
|
+
const sortedSourceTokens = getSortedTokens(
|
|
199
|
+
fromChain,
|
|
200
|
+
tokens,
|
|
201
|
+
balances,
|
|
202
|
+
[]
|
|
203
|
+
);
|
|
204
|
+
const sortedDestinationTokens = getSortedTokens(
|
|
205
|
+
toChain,
|
|
206
|
+
tokens,
|
|
207
|
+
balances,
|
|
208
|
+
[]
|
|
209
|
+
);
|
|
210
|
+
const inputAmount = pendingSwap.inputAmount;
|
|
211
|
+
set({
|
|
212
|
+
fromChain,
|
|
213
|
+
fromToken,
|
|
214
|
+
inputAmount,
|
|
215
|
+
outputAmount: null,
|
|
216
|
+
inputUsdValue: getUsdValue(fromToken || null, inputAmount),
|
|
217
|
+
outputUsdValue: new BigNumber(0),
|
|
218
|
+
toChain,
|
|
219
|
+
toToken,
|
|
220
|
+
bestRoute: null,
|
|
221
|
+
loading: false,
|
|
222
|
+
error: '',
|
|
223
|
+
sourceTokens: sortedSourceTokens,
|
|
224
|
+
destinationTokens: sortedDestinationTokens,
|
|
225
|
+
});
|
|
226
|
+
},
|
|
227
|
+
switchFromAndTo: () =>
|
|
228
|
+
set((state) => ({
|
|
229
|
+
fromChain: state.toChain,
|
|
230
|
+
fromToken: state.toToken,
|
|
231
|
+
toChain: state.fromChain,
|
|
232
|
+
toToken: state.fromToken,
|
|
233
|
+
sourceTokens: state.destinationTokens,
|
|
234
|
+
destinationTokens: state.sourceTokens,
|
|
235
|
+
inputAmount: state.outputAmount?.toString() || '',
|
|
236
|
+
inputUsdValue: getUsdValue(
|
|
237
|
+
state.toToken,
|
|
238
|
+
state.outputAmount?.toString() || ''
|
|
239
|
+
),
|
|
240
|
+
})),
|
|
154
241
|
}))
|
|
155
242
|
)
|
|
156
243
|
);
|
|
@@ -164,7 +251,7 @@ const bestRoute = (
|
|
|
164
251
|
const { fromToken, toToken, inputAmount } = bestRouteStore.getState();
|
|
165
252
|
const { slippage, customSlippage, disabledLiquiditySources } =
|
|
166
253
|
settingsStore.getState();
|
|
167
|
-
if (!fromToken || !toToken || !inputAmount) return;
|
|
254
|
+
if (!fromToken || !toToken || !inputAmount || inputAmount === '0') return;
|
|
168
255
|
abortController?.abort();
|
|
169
256
|
abortController = new AbortController();
|
|
170
257
|
const userSlippage = !!customSlippage ? customSlippage : slippage;
|
|
@@ -178,12 +265,13 @@ const bestRoute = (
|
|
|
178
265
|
userSlippage,
|
|
179
266
|
false
|
|
180
267
|
);
|
|
181
|
-
bestRouteStore.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
268
|
+
if (!bestRouteStore.getState().loading)
|
|
269
|
+
bestRouteStore.setState({
|
|
270
|
+
loading: true,
|
|
271
|
+
bestRoute: null,
|
|
272
|
+
outputAmount: null,
|
|
273
|
+
outputUsdValue: new BigNumber(0),
|
|
274
|
+
});
|
|
187
275
|
httpService
|
|
188
276
|
.getBestRoute(requestBody, {
|
|
189
277
|
signal: abortController.signal,
|
|
@@ -203,6 +291,31 @@ const bestRoute = (
|
|
|
203
291
|
});
|
|
204
292
|
};
|
|
205
293
|
|
|
294
|
+
const debouncedFetchBestRoute = debounce(fetchBestRoute, 600);
|
|
295
|
+
|
|
296
|
+
const bestRouteParamsListener = () => {
|
|
297
|
+
const { fromToken, toToken, inputAmount, inputUsdValue } =
|
|
298
|
+
useBestRouteStore.getState();
|
|
299
|
+
if (!inputAmount || inputAmount === '0' || inputUsdValue.eq(0)) return;
|
|
300
|
+
|
|
301
|
+
if (tokensAreEqual(fromToken, toToken))
|
|
302
|
+
return bestRouteStore.setState({
|
|
303
|
+
loading: false,
|
|
304
|
+
bestRoute: null,
|
|
305
|
+
outputAmount: new BigNumber(inputAmount),
|
|
306
|
+
outputUsdValue: inputUsdValue,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
if (!bestRouteStore.getState().loading)
|
|
310
|
+
bestRouteStore.setState({
|
|
311
|
+
loading: true,
|
|
312
|
+
bestRoute: null,
|
|
313
|
+
outputAmount: null,
|
|
314
|
+
outputUsdValue: new BigNumber(0),
|
|
315
|
+
});
|
|
316
|
+
debouncedFetchBestRoute();
|
|
317
|
+
};
|
|
318
|
+
|
|
206
319
|
useBestRouteStore.subscribe(
|
|
207
320
|
(state) => ({
|
|
208
321
|
fromChain: state.fromChain,
|
|
@@ -211,11 +324,17 @@ const bestRoute = (
|
|
|
211
324
|
toToken: state.toToken,
|
|
212
325
|
inputAmount: state.inputAmount,
|
|
213
326
|
}),
|
|
214
|
-
|
|
215
|
-
fetchBestRoute.bind(null),
|
|
327
|
+
bestRouteParamsListener,
|
|
216
328
|
{
|
|
217
|
-
equalityFn: (prevState,
|
|
218
|
-
if (
|
|
329
|
+
equalityFn: (prevState, currentState) => {
|
|
330
|
+
if (
|
|
331
|
+
isRouteParametersChanged({
|
|
332
|
+
store: 'bestRoute',
|
|
333
|
+
prevState,
|
|
334
|
+
currentState,
|
|
335
|
+
})
|
|
336
|
+
)
|
|
337
|
+
return false;
|
|
219
338
|
else return true;
|
|
220
339
|
},
|
|
221
340
|
}
|
|
@@ -226,11 +345,19 @@ const bestRoute = (
|
|
|
226
345
|
slippage: state.slippage,
|
|
227
346
|
customSlippage: state.customSlippage,
|
|
228
347
|
disabledLiquiditySources: state.disabledLiquiditySources,
|
|
348
|
+
infiniteApprove: state.infiniteApprove,
|
|
229
349
|
}),
|
|
230
|
-
|
|
350
|
+
bestRouteParamsListener,
|
|
231
351
|
{
|
|
232
|
-
equalityFn: (prevState,
|
|
233
|
-
if (
|
|
352
|
+
equalityFn: (prevState, currentState) => {
|
|
353
|
+
if (
|
|
354
|
+
isRouteParametersChanged({
|
|
355
|
+
store: 'settings',
|
|
356
|
+
prevState,
|
|
357
|
+
currentState,
|
|
358
|
+
})
|
|
359
|
+
)
|
|
360
|
+
return false;
|
|
234
361
|
else return true;
|
|
235
362
|
},
|
|
236
363
|
}
|
package/src/store/ui.ts
CHANGED
|
@@ -4,18 +4,22 @@ import createSelectors from './selectors';
|
|
|
4
4
|
interface UiState {
|
|
5
5
|
connectWalletsButtonDisabled: boolean;
|
|
6
6
|
selectedSwapRequestId: string | null;
|
|
7
|
+
currentPage: string;
|
|
7
8
|
toggleConnectWalletsButton: () => void;
|
|
8
9
|
setSelectedSwap: (requestId: string | null) => void;
|
|
10
|
+
setCurrentPage: (path: string) => void;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export const useUiStore = createSelectors(
|
|
12
14
|
create<UiState>()((set) => ({
|
|
13
15
|
connectWalletsButtonDisabled: false,
|
|
14
16
|
selectedSwapRequestId: null,
|
|
17
|
+
currentPage: '',
|
|
15
18
|
toggleConnectWalletsButton: () =>
|
|
16
19
|
set((state) => ({
|
|
17
20
|
connectWalletsButtonDisabled: !state.connectWalletsButtonDisabled,
|
|
18
21
|
})),
|
|
19
22
|
setSelectedSwap: (requestId) => set({ selectedSwapRequestId: requestId }),
|
|
23
|
+
setCurrentPage: (path) => set({ currentPage: path }),
|
|
20
24
|
}))
|
|
21
25
|
);
|
package/src/store/wallets.ts
CHANGED
|
@@ -142,7 +142,7 @@ export const useWalletsStore = createSelectors(
|
|
|
142
142
|
}
|
|
143
143
|
});
|
|
144
144
|
return {
|
|
145
|
-
selectedWallets:
|
|
145
|
+
selectedWallets: selectedWallets,
|
|
146
146
|
};
|
|
147
147
|
}),
|
|
148
148
|
setSelectedWallet: (wallet) =>
|
|
@@ -188,3 +188,6 @@ useWalletsStore.subscribe(
|
|
|
188
188
|
equalityFn: shallow,
|
|
189
189
|
}
|
|
190
190
|
);
|
|
191
|
+
|
|
192
|
+
export const fetchingBalanceSelector = (state: WalletsStore) =>
|
|
193
|
+
!!state.balances.find((wallet) => wallet.loading);
|
package/src/types/routing.ts
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { RouteState } from '../store/bestRoute';
|
|
2
2
|
import { SettingsState } from '../store/settings';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
interface BestRouteStoreParams {
|
|
5
5
|
fromChain?: RouteState['fromChain'];
|
|
6
6
|
toChain?: RouteState['toChain'];
|
|
7
7
|
fromToken?: RouteState['fromToken'];
|
|
8
8
|
toToken?: RouteState['toToken'];
|
|
9
9
|
inputAmount?: RouteState['inputAmount'];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface SettingsStoreParams {
|
|
10
13
|
slippage?: SettingsState['slippage'];
|
|
11
14
|
customSlippage?: SettingsState['customSlippage'];
|
|
12
15
|
disabledLiquiditySources?: SettingsState['disabledLiquiditySources'];
|
|
16
|
+
infiniteApprove?: SettingsState['infiniteApprove'];
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
export type BestRouteEqualityParams =
|
|
20
|
+
| {
|
|
21
|
+
store: 'bestRoute';
|
|
22
|
+
prevState: BestRouteStoreParams;
|
|
23
|
+
currentState: BestRouteStoreParams;
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
store: 'settings';
|
|
27
|
+
prevState: SettingsStoreParams;
|
|
28
|
+
currentState: SettingsStoreParams;
|
|
29
|
+
};
|
|
30
|
+
|
|
15
31
|
export enum ConfirmSwapErrorTypes {
|
|
16
32
|
NO_ROUTE,
|
|
17
33
|
ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS,
|
|
@@ -26,7 +42,7 @@ export type ConfirmSwapError =
|
|
|
26
42
|
}
|
|
27
43
|
| {
|
|
28
44
|
type: ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE;
|
|
29
|
-
minRequiredSlippage:
|
|
45
|
+
minRequiredSlippage: string | null;
|
|
30
46
|
}
|
|
31
47
|
| {
|
|
32
48
|
type: Exclude<
|
package/src/types/swap.ts
CHANGED
package/src/utils/common.ts
CHANGED
|
@@ -33,3 +33,17 @@ export function shadeColor(color: string, percent: number) {
|
|
|
33
33
|
|
|
34
34
|
return '#' + RR + GG + BB;
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
export function debounce(fn: Function, time: number) {
|
|
38
|
+
let timeoutId: ReturnType<typeof setTimeout> | null;
|
|
39
|
+
return wrapper;
|
|
40
|
+
function wrapper(...args: any) {
|
|
41
|
+
if (timeoutId) {
|
|
42
|
+
clearTimeout(timeoutId);
|
|
43
|
+
}
|
|
44
|
+
timeoutId = setTimeout(() => {
|
|
45
|
+
timeoutId = null;
|
|
46
|
+
fn(...args);
|
|
47
|
+
}, time);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { PendingSwap } from '@rango-dev/queue-manager-rango-preset';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import { GroupBy } from '@rango-dev/ui';
|
|
4
|
+
|
|
5
|
+
export const groupSwapsByDate: GroupBy = swaps => {
|
|
6
|
+
const output: Map<
|
|
7
|
+
string,
|
|
8
|
+
{
|
|
9
|
+
title: string;
|
|
10
|
+
swaps: PendingSwap[];
|
|
11
|
+
}
|
|
12
|
+
> = new Map([
|
|
13
|
+
[
|
|
14
|
+
'today',
|
|
15
|
+
{
|
|
16
|
+
title: 'Today',
|
|
17
|
+
swaps: [],
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
'week',
|
|
22
|
+
{
|
|
23
|
+
title: 'This week',
|
|
24
|
+
swaps: [],
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
'month',
|
|
29
|
+
{
|
|
30
|
+
title: 'This month',
|
|
31
|
+
swaps: [],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
'year',
|
|
36
|
+
{
|
|
37
|
+
title: 'This year',
|
|
38
|
+
swaps: [],
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
'history',
|
|
43
|
+
{
|
|
44
|
+
title: 'History',
|
|
45
|
+
swaps: [],
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
const now = dayjs();
|
|
51
|
+
swaps.forEach(swap => {
|
|
52
|
+
const swapDate = dayjs(Number(swap.creationTime));
|
|
53
|
+
if (now.isSame(swapDate, 'day')) output.get('today')?.swaps.push(swap);
|
|
54
|
+
else if (now.isSame(swapDate, 'week')) output.get('week')?.swaps.push(swap);
|
|
55
|
+
else if (now.isSame(swapDate, 'month'))
|
|
56
|
+
output.get('month')?.swaps.push(swap);
|
|
57
|
+
else if (now.isSame(swapDate, 'year')) output.get('year')?.swaps.push(swap);
|
|
58
|
+
else output.get('history')?.swaps.push(swap);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return Array.from(output.values());
|
|
62
|
+
};
|