@rango-dev/widget-embedded 0.1.10-next.80 → 0.1.10-next.82
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/components/AppRouter.d.ts.map +1 -1
- package/dist/components/AppRoutes.d.ts.map +1 -1
- package/dist/components/ChangeSlippageButton.d.ts +2 -0
- package/dist/components/ChangeSlippageButton.d.ts.map +1 -0
- package/dist/components/ConfirmSwapErrors.d.ts +3 -0
- package/dist/components/ConfirmSwapErrors.d.ts.map +1 -0
- package/dist/components/ConfirmSwapWarnings.d.ts +3 -0
- package/dist/components/ConfirmSwapWarnings.d.ts.map +1 -0
- package/dist/components/Layout.d.ts.map +1 -1
- package/dist/components/UpdateUrl.d.ts.map +1 -1
- package/dist/components/warnings/BalanceWarnings.d.ts +6 -0
- package/dist/components/warnings/BalanceWarnings.d.ts.map +1 -0
- package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts +6 -0
- package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts.map +1 -0
- package/dist/components/warnings/HighSlippageWarning.d.ts +6 -0
- package/dist/components/warnings/HighSlippageWarning.d.ts.map +1 -0
- package/dist/components/warnings/MinRequiredSlippage.d.ts +6 -0
- package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -0
- package/dist/constants/swapSettings.d.ts +6 -0
- package/dist/constants/swapSettings.d.ts.map +1 -0
- package/dist/hooks/useNavigateBack.d.ts +4 -0
- package/dist/hooks/useNavigateBack.d.ts.map +1 -0
- package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
- package/dist/pages/ConfirmWalletsPage.d.ts +0 -5
- package/dist/pages/ConfirmWalletsPage.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/SelectChainPage.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.map +1 -1
- package/dist/store/bestRoute.d.ts +1 -0
- package/dist/store/bestRoute.d.ts.map +1 -1
- package/dist/store/confirmSwap.d.ts +35 -0
- package/dist/store/confirmSwap.d.ts.map +1 -0
- package/dist/store/settings.d.ts.map +1 -1
- package/dist/store/ui.d.ts +2 -0
- package/dist/store/ui.d.ts.map +1 -0
- package/dist/store/wallets.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/swap.d.ts +11 -0
- package/dist/types/swap.d.ts.map +1 -0
- package/dist/utils/common.d.ts +1 -0
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/numbers.d.ts +5 -0
- package/dist/utils/numbers.d.ts.map +1 -1
- package/dist/utils/routing.d.ts +5 -7
- package/dist/utils/routing.d.ts.map +1 -1
- package/dist/utils/swap.d.ts +31 -3
- package/dist/utils/swap.d.ts.map +1 -1
- package/dist/utils/wallets.d.ts +2 -3
- package/dist/utils/wallets.d.ts.map +1 -1
- package/dist/widget-embedded.cjs.development.js +1814 -1327
- package/dist/widget-embedded.cjs.development.js.map +1 -1
- package/dist/widget-embedded.cjs.production.min.js +1814 -1327
- package/dist/widget-embedded.cjs.production.min.js.map +1 -1
- package/dist/widget-embedded.esm.js +1818 -1331
- package/dist/widget-embedded.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AppRouter.tsx +38 -3
- package/src/components/AppRoutes.tsx +8 -2
- package/src/components/ChangeSlippageButton.tsx +23 -0
- package/src/components/ConfirmSwapErrors.tsx +38 -0
- package/src/components/ConfirmSwapWarnings.tsx +38 -0
- package/src/components/Layout.tsx +22 -6
- package/src/components/UpdateUrl.tsx +100 -18
- package/src/components/warnings/BalanceWarnings.tsx +16 -0
- package/src/components/warnings/ConfirmSwapExtraMessages.tsx +14 -0
- package/src/components/warnings/HighSlippageWarning.tsx +21 -0
- package/src/components/warnings/MinRequiredSlippage.tsx +18 -0
- package/src/constants/navigationRoutes.ts +2 -2
- package/src/constants/swapSettings.ts +9 -0
- package/src/hooks/useNavigateBack.ts +37 -0
- package/src/pages/ConfirmSwapPage.tsx +30 -8
- package/src/pages/ConfirmWalletsPage.tsx +30 -17
- package/src/pages/HistoryPage.tsx +4 -4
- package/src/pages/Home.tsx +79 -36
- package/src/pages/LiquiditySourcesPage.tsx +11 -8
- package/src/pages/SelectChainPage.tsx +9 -28
- package/src/pages/SelectTokenPage.tsx +38 -27
- package/src/pages/SettingsPage.tsx +26 -11
- package/src/pages/SwapDetailsPage.tsx +9 -3
- package/src/pages/WalletsPage.tsx +37 -22
- package/src/store/bestRoute.ts +147 -28
- package/src/store/confirmSwap.ts +327 -0
- package/src/store/settings.ts +44 -32
- package/src/store/ui.ts +15 -0
- package/src/store/wallets.ts +93 -80
- package/src/swapBox.tsx +5 -5
- package/src/types/index.ts +1 -0
- package/src/types/swap.ts +13 -0
- package/src/utils/common.ts +4 -0
- package/src/utils/numbers.ts +17 -0
- package/src/utils/routing.ts +28 -77
- package/src/utils/swap.ts +445 -67
- package/src/utils/wallets.ts +4 -19
- package/dist/hooks/useBestRoute.d.ts +0 -8
- package/dist/hooks/useBestRoute.d.ts.map +0 -1
- package/dist/hooks/useConfirmSwap.d.ts +0 -2
- package/dist/hooks/useConfirmSwap.d.ts.map +0 -1
- package/src/hooks/useBestRoute.ts +0 -70
- package/src/hooks/useConfirmSwap.ts +0 -268
package/package.json
CHANGED
|
@@ -1,10 +1,45 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
1
|
+
import React, { PropsWithChildren, useEffect, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
MemoryRouter,
|
|
4
|
+
useInRouterContext,
|
|
5
|
+
useLocation,
|
|
6
|
+
useNavigate,
|
|
7
|
+
} from 'react-router';
|
|
8
|
+
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
3
9
|
import { UpdateUrl } from './UpdateUrl';
|
|
10
|
+
import { Home } from '../pages/Home';
|
|
11
|
+
|
|
12
|
+
const Route: React.FC = (props: PropsWithChildren) => {
|
|
13
|
+
const location = useLocation();
|
|
14
|
+
const navigate = useNavigate();
|
|
15
|
+
const ref = useRef(true);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (
|
|
19
|
+
[navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(
|
|
20
|
+
location.pathname
|
|
21
|
+
) &&
|
|
22
|
+
ref.current
|
|
23
|
+
)
|
|
24
|
+
navigate(navigationRoutes.home + location.search, { state: 'redirect' });
|
|
25
|
+
|
|
26
|
+
ref.current = false;
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
if (
|
|
30
|
+
[navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(
|
|
31
|
+
location.pathname
|
|
32
|
+
) &&
|
|
33
|
+
ref.current
|
|
34
|
+
)
|
|
35
|
+
return <Home />;
|
|
36
|
+
|
|
37
|
+
return <> {props.children}</>;
|
|
38
|
+
};
|
|
4
39
|
|
|
5
40
|
export function AppRouter({ children }: PropsWithChildren) {
|
|
6
41
|
const isRouterInContext = useInRouterContext();
|
|
7
|
-
const Router = isRouterInContext ?
|
|
42
|
+
const Router = isRouterInContext ? Route : MemoryRouter;
|
|
8
43
|
|
|
9
44
|
return (
|
|
10
45
|
<>
|
|
@@ -15,9 +15,15 @@ import { SwapDetailsPage } from '../pages/SwapDetailsPage';
|
|
|
15
15
|
export const AppRoutes = () =>
|
|
16
16
|
useRoutes([
|
|
17
17
|
{ path: navigationRoutes.home, element: <Home /> },
|
|
18
|
-
{
|
|
18
|
+
{
|
|
19
|
+
path: navigationRoutes.fromChain,
|
|
20
|
+
element: <SelectChainPage type="from" />,
|
|
21
|
+
},
|
|
19
22
|
{ path: navigationRoutes.toChain, element: <SelectChainPage type="to" /> },
|
|
20
|
-
{
|
|
23
|
+
{
|
|
24
|
+
path: navigationRoutes.fromToken + '/*',
|
|
25
|
+
element: <SelectTokenPage type="from" />,
|
|
26
|
+
},
|
|
21
27
|
{ path: navigationRoutes.toToken, element: <SelectTokenPage type="to" /> },
|
|
22
28
|
{ path: navigationRoutes.settings, element: <SettingsPage /> },
|
|
23
29
|
{
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, styled } from '@rango-dev/ui';
|
|
3
|
+
import { useNavigate } from 'react-router-dom';
|
|
4
|
+
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
5
|
+
|
|
6
|
+
const StyledButton = styled(Button, {
|
|
7
|
+
marginTop: '$8',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export function ChangeSlippageButton() {
|
|
11
|
+
const navigate = useNavigate();
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<StyledButton
|
|
15
|
+
type="primary"
|
|
16
|
+
variant="contained"
|
|
17
|
+
size="small"
|
|
18
|
+
onClick={navigate.bind(null, navigationRoutes.settings)}
|
|
19
|
+
>
|
|
20
|
+
Change Slippage
|
|
21
|
+
</StyledButton>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Typography } from '@rango-dev/ui';
|
|
3
|
+
import { ConfirmSwapError, ConfirmSwapErrorTypes } from '../store/confirmSwap';
|
|
4
|
+
import { MinRequiredSlippage } from './warnings/MinRequiredSlippage';
|
|
5
|
+
|
|
6
|
+
export function ConfirmSwapErrors(errors: ConfirmSwapError[]) {
|
|
7
|
+
return errors.flatMap((error) => {
|
|
8
|
+
switch (error.type) {
|
|
9
|
+
case ConfirmSwapErrorTypes.NO_ROUTE:
|
|
10
|
+
return (
|
|
11
|
+
<Typography variant="body2">
|
|
12
|
+
No routes found. Please try again later.
|
|
13
|
+
</Typography>
|
|
14
|
+
);
|
|
15
|
+
case ConfirmSwapErrorTypes.REQUEST_FAILED:
|
|
16
|
+
return (
|
|
17
|
+
<Typography variant="body2">{`Failed to confirm swap ${
|
|
18
|
+
error.status ? `'status': ${error.status})` : ''
|
|
19
|
+
}, please try again.`}</Typography>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
|
|
23
|
+
return (
|
|
24
|
+
<Typography variant="body2">
|
|
25
|
+
Route updated and price impact is too high, try again later!
|
|
26
|
+
</Typography>
|
|
27
|
+
);
|
|
28
|
+
case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
|
|
29
|
+
return (
|
|
30
|
+
<MinRequiredSlippage
|
|
31
|
+
minRequiredSlippage={error.minRequiredSlippage}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
default:
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Typography } from '@rango-dev/ui';
|
|
3
|
+
import {
|
|
4
|
+
ConfirmSwapWarnings,
|
|
5
|
+
ConfirmSwapWarningTypes,
|
|
6
|
+
} from '../store/confirmSwap';
|
|
7
|
+
import { BalanceWarnings } from './warnings/BalanceWarnings';
|
|
8
|
+
|
|
9
|
+
export function ConfirmSwapWarnings(warnings: ConfirmSwapWarnings[]) {
|
|
10
|
+
return warnings.flatMap((warning) => {
|
|
11
|
+
switch (warning.type) {
|
|
12
|
+
case ConfirmSwapWarningTypes.ROUTE_UPDATED:
|
|
13
|
+
return <Typography variant="body2">Route has been updated.</Typography>;
|
|
14
|
+
case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
|
|
15
|
+
return (
|
|
16
|
+
<Typography variant="body2">{`Output amount changed to ${warning.newOutputAmount}
|
|
17
|
+
(${warning.percentageChange}% change).`}</Typography>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
|
|
21
|
+
return (
|
|
22
|
+
<Typography variant="body2">
|
|
23
|
+
Route swappers has been updated.
|
|
24
|
+
</Typography>
|
|
25
|
+
);
|
|
26
|
+
case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
|
|
27
|
+
return (
|
|
28
|
+
<Typography variant="body2">
|
|
29
|
+
Route internal coins has been updated.
|
|
30
|
+
</Typography>
|
|
31
|
+
);
|
|
32
|
+
case ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE:
|
|
33
|
+
return <BalanceWarnings messages={warning.messages} />;
|
|
34
|
+
default:
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -3,9 +3,14 @@ import React from 'react';
|
|
|
3
3
|
import { useNavigate } from 'react-router-dom';
|
|
4
4
|
import { useWallets } from '@rango-dev/wallets-core';
|
|
5
5
|
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
6
|
+
import { useUiStore } from '../store/ui';
|
|
6
7
|
import { AppRoutes } from './AppRoutes';
|
|
7
8
|
import { useWalletsStore } from '../store/wallets';
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
calculateWalletUsdValue,
|
|
11
|
+
getSelectableWallets,
|
|
12
|
+
} from '../utils/wallets';
|
|
13
|
+
import { removeDuplicateFrom } from '../utils/common';
|
|
9
14
|
|
|
10
15
|
const Header = styled('div', {
|
|
11
16
|
display: 'flex',
|
|
@@ -25,8 +30,15 @@ export function Layout() {
|
|
|
25
30
|
const navigate = useNavigate();
|
|
26
31
|
const { balances, accounts, selectedWallets } = useWalletsStore();
|
|
27
32
|
const { getWalletInfo } = useWallets();
|
|
28
|
-
const
|
|
33
|
+
const connectedWalletsImages = removeDuplicateFrom(
|
|
34
|
+
getSelectableWallets(accounts, selectedWallets, getWalletInfo).map(
|
|
35
|
+
(w) => w.image
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
|
|
29
39
|
const totalBalance = calculateWalletUsdValue(balances);
|
|
40
|
+
const connectWalletsButtonDisabled =
|
|
41
|
+
useUiStore.use.connectWalletsButtonDisabled();
|
|
30
42
|
|
|
31
43
|
return (
|
|
32
44
|
<>
|
|
@@ -36,10 +48,14 @@ export function Layout() {
|
|
|
36
48
|
suffix={<AddWalletIcon size={20} />}
|
|
37
49
|
variant="ghost"
|
|
38
50
|
flexContent
|
|
39
|
-
onClick={() =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
onClick={() => {
|
|
52
|
+
if (!connectWalletsButtonDisabled)
|
|
53
|
+
navigate(navigationRoutes.wallets);
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
{connectedWalletsImages?.length ? (
|
|
57
|
+
connectedWalletsImages.map((walletImage, index) => (
|
|
58
|
+
<WalletImage key={index} src={walletImage} />
|
|
43
59
|
))
|
|
44
60
|
) : (
|
|
45
61
|
<></>
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { Token } from 'rango-sdk';
|
|
2
2
|
import { useEffect, useRef } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createSearchParams,
|
|
5
|
+
useLocation,
|
|
6
|
+
useSearchParams,
|
|
7
|
+
} from 'react-router-dom';
|
|
4
8
|
import { useBestRouteStore } from '../store/bestRoute';
|
|
5
9
|
import { useMetaStore } from '../store/meta';
|
|
6
10
|
import { SearchParams } from '../constants/searchParams';
|
|
11
|
+
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
7
12
|
|
|
8
|
-
function searchParamsToToken(
|
|
13
|
+
function searchParamsToToken(
|
|
14
|
+
tokens: Token[],
|
|
15
|
+
searchParams: string | null
|
|
16
|
+
): Token | null {
|
|
9
17
|
return (
|
|
10
18
|
tokens.find((token) => {
|
|
11
19
|
const symbolAndAddress = searchParams?.split('--');
|
|
12
20
|
if (symbolAndAddress?.length === 1)
|
|
13
21
|
return token.symbol === symbolAndAddress[0] && token.address === null;
|
|
14
|
-
return
|
|
22
|
+
return (
|
|
23
|
+
token.symbol === symbolAndAddress?.[0] &&
|
|
24
|
+
token.address === symbolAndAddress?.[1]
|
|
25
|
+
);
|
|
15
26
|
}) || null
|
|
16
27
|
);
|
|
17
28
|
}
|
|
@@ -20,6 +31,18 @@ export function UpdateUrl() {
|
|
|
20
31
|
const firstRender = useRef(true);
|
|
21
32
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
22
33
|
const location = useLocation();
|
|
34
|
+
const firstRenderSearchParams = useRef(location.search);
|
|
35
|
+
const searchParamsRef = useRef<Record<string, string>>({});
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const params: Record<string, string> = {};
|
|
39
|
+
createSearchParams(firstRenderSearchParams.current).forEach(
|
|
40
|
+
(value, key) => {
|
|
41
|
+
params[key] = value;
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
searchParamsRef.current = params;
|
|
45
|
+
}, []);
|
|
23
46
|
|
|
24
47
|
const fromChain = useBestRouteStore.use.fromChain();
|
|
25
48
|
const toChain = useBestRouteStore.use.toChain();
|
|
@@ -35,26 +58,81 @@ export function UpdateUrl() {
|
|
|
35
58
|
const { blockchains, tokens } = useMetaStore.use.meta();
|
|
36
59
|
|
|
37
60
|
useEffect(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
61
|
+
let fromChainString = '',
|
|
62
|
+
fromTokenString = '',
|
|
63
|
+
toChainString = '',
|
|
64
|
+
toTokenString = '',
|
|
65
|
+
fromAmount = '';
|
|
66
|
+
if (
|
|
67
|
+
loadingStatus !== 'success' &&
|
|
68
|
+
![navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(
|
|
69
|
+
location.pathname
|
|
70
|
+
)
|
|
71
|
+
) {
|
|
72
|
+
fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
|
|
73
|
+
fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
|
|
74
|
+
toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
|
|
75
|
+
toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];
|
|
76
|
+
fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT];
|
|
47
77
|
setSearchParams(
|
|
48
78
|
{
|
|
49
|
-
...(fromChainString && {
|
|
50
|
-
|
|
79
|
+
...(fromChainString && {
|
|
80
|
+
[SearchParams.FROM_CHAIN]: fromChainString,
|
|
81
|
+
}),
|
|
82
|
+
...(fromTokenString && {
|
|
83
|
+
[SearchParams.FROM_TOKEN]: fromTokenString,
|
|
84
|
+
}),
|
|
51
85
|
...(toChainString && { [SearchParams.TO_CHAIN]: toChainString }),
|
|
52
86
|
...(toTokenString && { [SearchParams.TO_TOKEN]: toTokenString }),
|
|
53
|
-
...(fromAmount && {
|
|
87
|
+
...(fromAmount && {
|
|
88
|
+
[SearchParams.FROM_AMOUNT]: fromAmount.toString(),
|
|
89
|
+
}),
|
|
54
90
|
},
|
|
55
|
-
{ replace: true }
|
|
91
|
+
{ replace: true }
|
|
56
92
|
);
|
|
57
93
|
}
|
|
94
|
+
if (!firstRender.current) {
|
|
95
|
+
let fromChainString = '',
|
|
96
|
+
fromTokenString = '',
|
|
97
|
+
toChainString = '',
|
|
98
|
+
toTokenString = '',
|
|
99
|
+
fromAmount = '';
|
|
100
|
+
if (loadingStatus !== 'success') {
|
|
101
|
+
fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
|
|
102
|
+
fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
|
|
103
|
+
toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
|
|
104
|
+
toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];
|
|
105
|
+
fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT];
|
|
106
|
+
} else {
|
|
107
|
+
if (location.state === 'redirect') return;
|
|
108
|
+
fromChainString = fromChain?.name || '';
|
|
109
|
+
fromTokenString =
|
|
110
|
+
(fromToken?.symbol || '') +
|
|
111
|
+
(fromToken?.address ? `--${fromToken?.address}` : '');
|
|
112
|
+
toChainString = toChain?.name || '';
|
|
113
|
+
toTokenString =
|
|
114
|
+
(toToken?.symbol || '') +
|
|
115
|
+
(toToken?.address ? `--${toToken?.address}` : '');
|
|
116
|
+
fromAmount = inputAmount;
|
|
117
|
+
|
|
118
|
+
setSearchParams(
|
|
119
|
+
{
|
|
120
|
+
...(fromChainString && {
|
|
121
|
+
[SearchParams.FROM_CHAIN]: fromChainString,
|
|
122
|
+
}),
|
|
123
|
+
...(fromTokenString && {
|
|
124
|
+
[SearchParams.FROM_TOKEN]: fromTokenString,
|
|
125
|
+
}),
|
|
126
|
+
...(toChainString && { [SearchParams.TO_CHAIN]: toChainString }),
|
|
127
|
+
...(toTokenString && { [SearchParams.TO_TOKEN]: toTokenString }),
|
|
128
|
+
...(fromAmount && {
|
|
129
|
+
[SearchParams.FROM_AMOUNT]: fromAmount.toString(),
|
|
130
|
+
}),
|
|
131
|
+
},
|
|
132
|
+
{ replace: true }
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
58
136
|
firstRender.current = false;
|
|
59
137
|
}, [location.pathname, inputAmount]);
|
|
60
138
|
|
|
@@ -65,9 +143,13 @@ export function UpdateUrl() {
|
|
|
65
143
|
const toChainString = searchParams.get(SearchParams.TO_CHAIN);
|
|
66
144
|
const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
|
|
67
145
|
const fromAmount = searchParams.get(SearchParams.FROM_AMOUNT);
|
|
68
|
-
const fromChain = blockchains.find(
|
|
146
|
+
const fromChain = blockchains.find(
|
|
147
|
+
(blockchain) => blockchain.name === fronChainString
|
|
148
|
+
);
|
|
69
149
|
const fromToken = searchParamsToToken(tokens, fromTokenString);
|
|
70
|
-
const toChain = blockchains.find(
|
|
150
|
+
const toChain = blockchains.find(
|
|
151
|
+
(blockchain) => blockchain.name === toChainString
|
|
152
|
+
);
|
|
71
153
|
const toToken = searchParamsToToken(tokens, toTokenString);
|
|
72
154
|
if (!!fromChain) {
|
|
73
155
|
setFromChain(fromChain);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Typography } from '@rango-dev/ui';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
interface PropTypes {
|
|
5
|
+
messages: string[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function BalanceWarnings({ messages }: PropTypes) {
|
|
9
|
+
return (
|
|
10
|
+
<div>
|
|
11
|
+
{messages.map((warning) => (
|
|
12
|
+
<Typography variant="body2">{warning}</Typography>
|
|
13
|
+
))}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { HIGH_SLIPPAGE } from '../../constants/swapSettings';
|
|
3
|
+
import { HighSlippageWarning } from './HighSlippageWarning';
|
|
4
|
+
|
|
5
|
+
interface PropTypes {
|
|
6
|
+
selectedSlippage: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ConfirmSwapExtraMessages(props: PropTypes) {
|
|
10
|
+
const { selectedSlippage } = props;
|
|
11
|
+
const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
|
|
12
|
+
|
|
13
|
+
return <>{highSlippage && <HighSlippageWarning selectedSlippage={selectedSlippage} />}</>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Alert, Typography } from '@rango-dev/ui';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ChangeSlippageButton } from '../ChangeSlippageButton';
|
|
4
|
+
|
|
5
|
+
interface PropTypes {
|
|
6
|
+
selectedSlippage: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function HighSlippageWarning(props: PropTypes) {
|
|
10
|
+
const { selectedSlippage } = props;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<Alert type="warning">
|
|
14
|
+
<Typography variant="body2">
|
|
15
|
+
slippage is high=> Caution, your slippage is high (=
|
|
16
|
+
{selectedSlippage}). Your trade may be front run.
|
|
17
|
+
<ChangeSlippageButton />
|
|
18
|
+
</Typography>
|
|
19
|
+
</Alert>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Typography } from '@rango-dev/ui';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ChangeSlippageButton } from '../ChangeSlippageButton';
|
|
4
|
+
|
|
5
|
+
interface PropTypes {
|
|
6
|
+
minRequiredSlippage: number | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function MinRequiredSlippage({ minRequiredSlippage }: PropTypes) {
|
|
10
|
+
return (
|
|
11
|
+
<Typography variant="body2">
|
|
12
|
+
slippage is low => We recommend you to increase slippage to at least
|
|
13
|
+
{minRequiredSlippage}
|
|
14
|
+
for this route.
|
|
15
|
+
<ChangeSlippageButton />
|
|
16
|
+
</Typography>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -5,10 +5,10 @@ export const navigationRoutes = {
|
|
|
5
5
|
toChain: '/to-chain',
|
|
6
6
|
toToken: '/to-token',
|
|
7
7
|
settings: '/settings',
|
|
8
|
-
liquiditySources: '/liquidity-sources',
|
|
8
|
+
liquiditySources: '/settings/liquidity-sources',
|
|
9
9
|
history: '/history',
|
|
10
10
|
wallets: '/wallets',
|
|
11
11
|
confirmSwap: '/confirm-swap',
|
|
12
12
|
confirmWallets: '/confirm-wallets',
|
|
13
|
-
swapDetails: '/swap-details',
|
|
13
|
+
swapDetails: '/history/swap-details',
|
|
14
14
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useInRouterContext, useNavigate } from 'react-router-dom';
|
|
2
|
+
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
3
|
+
|
|
4
|
+
export function useNavigateBack() {
|
|
5
|
+
const isRouterInContext = useInRouterContext();
|
|
6
|
+
const navigate = useNavigate();
|
|
7
|
+
|
|
8
|
+
navigationRoutes;
|
|
9
|
+
|
|
10
|
+
const navigateBackFrom = (currentRoute: string) => {
|
|
11
|
+
if (
|
|
12
|
+
!isRouterInContext ||
|
|
13
|
+
(window.history.state && window.history.state.idx > 0)
|
|
14
|
+
)
|
|
15
|
+
navigate(-1);
|
|
16
|
+
else {
|
|
17
|
+
if (
|
|
18
|
+
[
|
|
19
|
+
navigationRoutes.fromChain,
|
|
20
|
+
navigationRoutes.fromToken,
|
|
21
|
+
navigationRoutes.toChain,
|
|
22
|
+
navigationRoutes.toToken,
|
|
23
|
+
navigationRoutes.settings,
|
|
24
|
+
navigationRoutes.wallets,
|
|
25
|
+
navigationRoutes.history,
|
|
26
|
+
].includes(currentRoute)
|
|
27
|
+
)
|
|
28
|
+
navigate(navigationRoutes.home, { replace: true });
|
|
29
|
+
else if (currentRoute === navigationRoutes.liquiditySources) {
|
|
30
|
+
navigate(navigationRoutes.settings, { replace: true });
|
|
31
|
+
} else if (currentRoute === navigationRoutes.swapDetails)
|
|
32
|
+
navigate(navigationRoutes.history, { replace: true });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return { navigateBackFrom };
|
|
37
|
+
}
|
|
@@ -1,24 +1,46 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ConfirmSwap } from '@rango-dev/ui';
|
|
3
|
-
import { useNavigate } from 'react-router-dom';
|
|
4
3
|
import { useBestRouteStore } from '../store/bestRoute';
|
|
5
|
-
import {
|
|
4
|
+
import { useSettingsStore } from '../store/settings';
|
|
5
|
+
import { ConfirmSwapExtraMessages } from '../components/warnings/ConfirmSwapExtraMessages';
|
|
6
|
+
import { useNavigateBack } from '../hooks/useNavigateBack';
|
|
7
|
+
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
8
|
+
import { confirmSwap, useConfirmSwapStore } from '../store/confirmSwap';
|
|
9
|
+
import { ConfirmSwapErrors } from '../components/ConfirmSwapErrors';
|
|
10
|
+
import { ConfirmSwapWarnings } from '../components/ConfirmSwapWarnings';
|
|
6
11
|
|
|
7
12
|
export function ConfirmSwapPage() {
|
|
8
|
-
const
|
|
13
|
+
const { navigateBackFrom } = useNavigateBack();
|
|
9
14
|
|
|
10
15
|
const bestRoute = useBestRouteStore.use.bestRoute();
|
|
11
16
|
|
|
12
|
-
const
|
|
17
|
+
const loading = useConfirmSwapStore.use.loading();
|
|
18
|
+
const warnings = useConfirmSwapStore.use.warnings();
|
|
19
|
+
const errors = useConfirmSwapStore.use.errors();
|
|
20
|
+
|
|
21
|
+
console.log('loading:', loading, 'warnings:', warnings, 'errors:', errors);
|
|
22
|
+
|
|
23
|
+
const slippage = useSettingsStore.use.slippage();
|
|
24
|
+
const customSlippage = useSettingsStore.use.customSlippage();
|
|
25
|
+
const selectedSlippage = customSlippage || slippage;
|
|
13
26
|
|
|
14
27
|
return (
|
|
15
28
|
<ConfirmSwap
|
|
16
|
-
onConfirm={
|
|
17
|
-
onBack={
|
|
29
|
+
onConfirm={confirmSwap.bind(null)}
|
|
30
|
+
onBack={navigateBackFrom.bind(null, navigationRoutes.confirmSwap)}
|
|
18
31
|
bestRoute={bestRoute}
|
|
19
32
|
loading={loading}
|
|
20
|
-
|
|
21
|
-
|
|
33
|
+
errors={ConfirmSwapErrors(errors)}
|
|
34
|
+
warnings={ConfirmSwapWarnings(warnings)}
|
|
35
|
+
extraMessages={
|
|
36
|
+
<ConfirmSwapExtraMessages selectedSlippage={selectedSlippage} />
|
|
37
|
+
}
|
|
38
|
+
confirmButtonTitle={
|
|
39
|
+
warnings.length > 0 || errors.length > 0
|
|
40
|
+
? 'Proceed anyway!'
|
|
41
|
+
: 'Confirm swap!'
|
|
42
|
+
}
|
|
43
|
+
confirmButtonDisabled={errors.length > 0}
|
|
22
44
|
/>
|
|
23
45
|
);
|
|
24
46
|
}
|
|
@@ -5,18 +5,21 @@ import { useBestRouteStore } from '../store/bestRoute';
|
|
|
5
5
|
import { useWalletsStore } from '../store/wallets';
|
|
6
6
|
import { useWallets } from '@rango-dev/wallets-core';
|
|
7
7
|
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getKeplrCompatibleConnectedWallets,
|
|
10
|
+
getRequiredChains,
|
|
11
|
+
getSelectableWallets,
|
|
12
|
+
isExperimentalChain,
|
|
13
|
+
} from '../utils/wallets';
|
|
9
14
|
import { requiredWallets } from '../utils/swap';
|
|
15
|
+
import { decimalNumber } from '../utils/numbers';
|
|
10
16
|
import { useMetaStore } from '../store/meta';
|
|
11
17
|
import { Network, WalletType } from '@rango-dev/wallets-shared';
|
|
12
|
-
|
|
13
|
-
export interface SelectableWallet extends SelectedWallet {
|
|
14
|
-
image: string;
|
|
15
|
-
selected: boolean;
|
|
16
|
-
}
|
|
18
|
+
import { useNavigateBack } from '../hooks/useNavigateBack';
|
|
17
19
|
|
|
18
20
|
export function ConfirmWalletsPage() {
|
|
19
21
|
const navigate = useNavigate();
|
|
22
|
+
const { navigateBackFrom } = useNavigateBack();
|
|
20
23
|
const bestRoute = useBestRouteStore.use.bestRoute();
|
|
21
24
|
|
|
22
25
|
const { blockchains } = useMetaStore.use.meta();
|
|
@@ -27,9 +30,15 @@ export function ConfirmWalletsPage() {
|
|
|
27
30
|
|
|
28
31
|
const { getWalletInfo, connect } = useWallets();
|
|
29
32
|
const confirmDisabled = !requiredWallets(bestRoute).every((chain) =>
|
|
30
|
-
selectedWallets.map((wallet) => wallet.chain).includes(chain)
|
|
33
|
+
selectedWallets.map((wallet) => wallet.chain).includes(chain)
|
|
31
34
|
);
|
|
32
35
|
|
|
36
|
+
const firstStep = bestRoute?.result?.swaps[0];
|
|
37
|
+
const lastStep =
|
|
38
|
+
bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
|
|
39
|
+
|
|
40
|
+
const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
|
|
41
|
+
const toAmount = decimalNumber(lastStep?.toAmount, 3);
|
|
33
42
|
useEffect(() => {
|
|
34
43
|
initSelectedWallets();
|
|
35
44
|
}, []);
|
|
@@ -37,29 +46,33 @@ export function ConfirmWalletsPage() {
|
|
|
37
46
|
const selectableWallets = getSelectableWallets(
|
|
38
47
|
accounts,
|
|
39
48
|
selectedWallets,
|
|
40
|
-
getWalletInfo
|
|
41
|
-
getRequiredChains(bestRoute),
|
|
49
|
+
getWalletInfo
|
|
42
50
|
);
|
|
43
51
|
|
|
44
52
|
const handleConnectChain = (wallet: string) => {
|
|
45
53
|
const network = wallet as Network;
|
|
46
54
|
getKeplrCompatibleConnectedWallets(selectableWallets).forEach(
|
|
47
|
-
(compatibleWallet: WalletType) =>
|
|
48
|
-
connect?.(compatibleWallet, network)
|
|
55
|
+
(compatibleWallet: WalletType) => connect?.(compatibleWallet, network)
|
|
49
56
|
);
|
|
50
|
-
}
|
|
51
|
-
|
|
57
|
+
};
|
|
58
|
+
|
|
52
59
|
return (
|
|
53
60
|
<ConfirmWallets
|
|
54
61
|
requiredWallets={getRequiredChains(bestRoute)}
|
|
55
62
|
selectableWallets={selectableWallets}
|
|
56
|
-
onBack={(
|
|
63
|
+
onBack={navigateBackFrom.bind(null, navigationRoutes.confirmWallets)}
|
|
57
64
|
swap={bestRoute!}
|
|
58
|
-
|
|
65
|
+
fromAmount={fromAmount}
|
|
66
|
+
toAmount={toAmount}
|
|
67
|
+
onConfirm={navigate.bind(null, navigationRoutes.confirmSwap)}
|
|
59
68
|
onChange={(wallet) => setSelectedWallet(wallet)}
|
|
60
69
|
confirmDisabled={confirmDisabled}
|
|
61
70
|
handleConnectChain={(wallet) => handleConnectChain(wallet)}
|
|
62
|
-
isExperimentalChain={(wallet) =>
|
|
71
|
+
isExperimentalChain={(wallet) =>
|
|
72
|
+
getKeplrCompatibleConnectedWallets(selectableWallets).length > 0
|
|
73
|
+
? isExperimentalChain(blockchains, wallet)
|
|
74
|
+
: false
|
|
75
|
+
}
|
|
63
76
|
/>
|
|
64
77
|
);
|
|
65
|
-
}
|
|
78
|
+
}
|