@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.
Files changed (105) hide show
  1. package/dist/components/AppRouter.d.ts.map +1 -1
  2. package/dist/components/AppRoutes.d.ts.map +1 -1
  3. package/dist/components/ChangeSlippageButton.d.ts +2 -0
  4. package/dist/components/ChangeSlippageButton.d.ts.map +1 -0
  5. package/dist/components/ConfirmSwapErrors.d.ts +3 -0
  6. package/dist/components/ConfirmSwapErrors.d.ts.map +1 -0
  7. package/dist/components/ConfirmSwapWarnings.d.ts +3 -0
  8. package/dist/components/ConfirmSwapWarnings.d.ts.map +1 -0
  9. package/dist/components/Layout.d.ts.map +1 -1
  10. package/dist/components/UpdateUrl.d.ts.map +1 -1
  11. package/dist/components/warnings/BalanceWarnings.d.ts +6 -0
  12. package/dist/components/warnings/BalanceWarnings.d.ts.map +1 -0
  13. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts +6 -0
  14. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts.map +1 -0
  15. package/dist/components/warnings/HighSlippageWarning.d.ts +6 -0
  16. package/dist/components/warnings/HighSlippageWarning.d.ts.map +1 -0
  17. package/dist/components/warnings/MinRequiredSlippage.d.ts +6 -0
  18. package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -0
  19. package/dist/constants/swapSettings.d.ts +6 -0
  20. package/dist/constants/swapSettings.d.ts.map +1 -0
  21. package/dist/hooks/useNavigateBack.d.ts +4 -0
  22. package/dist/hooks/useNavigateBack.d.ts.map +1 -0
  23. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  24. package/dist/pages/ConfirmWalletsPage.d.ts +0 -5
  25. package/dist/pages/ConfirmWalletsPage.d.ts.map +1 -1
  26. package/dist/pages/HistoryPage.d.ts.map +1 -1
  27. package/dist/pages/Home.d.ts.map +1 -1
  28. package/dist/pages/LiquiditySourcesPage.d.ts.map +1 -1
  29. package/dist/pages/SelectChainPage.d.ts.map +1 -1
  30. package/dist/pages/SelectTokenPage.d.ts.map +1 -1
  31. package/dist/pages/SettingsPage.d.ts.map +1 -1
  32. package/dist/pages/SwapDetailsPage.d.ts.map +1 -1
  33. package/dist/pages/WalletsPage.d.ts.map +1 -1
  34. package/dist/store/bestRoute.d.ts +1 -0
  35. package/dist/store/bestRoute.d.ts.map +1 -1
  36. package/dist/store/confirmSwap.d.ts +35 -0
  37. package/dist/store/confirmSwap.d.ts.map +1 -0
  38. package/dist/store/settings.d.ts.map +1 -1
  39. package/dist/store/ui.d.ts +2 -0
  40. package/dist/store/ui.d.ts.map +1 -0
  41. package/dist/store/wallets.d.ts.map +1 -1
  42. package/dist/types/index.d.ts +2 -0
  43. package/dist/types/index.d.ts.map +1 -0
  44. package/dist/types/swap.d.ts +11 -0
  45. package/dist/types/swap.d.ts.map +1 -0
  46. package/dist/utils/common.d.ts +1 -0
  47. package/dist/utils/common.d.ts.map +1 -1
  48. package/dist/utils/numbers.d.ts +5 -0
  49. package/dist/utils/numbers.d.ts.map +1 -1
  50. package/dist/utils/routing.d.ts +5 -7
  51. package/dist/utils/routing.d.ts.map +1 -1
  52. package/dist/utils/swap.d.ts +31 -3
  53. package/dist/utils/swap.d.ts.map +1 -1
  54. package/dist/utils/wallets.d.ts +2 -3
  55. package/dist/utils/wallets.d.ts.map +1 -1
  56. package/dist/widget-embedded.cjs.development.js +1814 -1327
  57. package/dist/widget-embedded.cjs.development.js.map +1 -1
  58. package/dist/widget-embedded.cjs.production.min.js +1814 -1327
  59. package/dist/widget-embedded.cjs.production.min.js.map +1 -1
  60. package/dist/widget-embedded.esm.js +1818 -1331
  61. package/dist/widget-embedded.esm.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/components/AppRouter.tsx +38 -3
  64. package/src/components/AppRoutes.tsx +8 -2
  65. package/src/components/ChangeSlippageButton.tsx +23 -0
  66. package/src/components/ConfirmSwapErrors.tsx +38 -0
  67. package/src/components/ConfirmSwapWarnings.tsx +38 -0
  68. package/src/components/Layout.tsx +22 -6
  69. package/src/components/UpdateUrl.tsx +100 -18
  70. package/src/components/warnings/BalanceWarnings.tsx +16 -0
  71. package/src/components/warnings/ConfirmSwapExtraMessages.tsx +14 -0
  72. package/src/components/warnings/HighSlippageWarning.tsx +21 -0
  73. package/src/components/warnings/MinRequiredSlippage.tsx +18 -0
  74. package/src/constants/navigationRoutes.ts +2 -2
  75. package/src/constants/swapSettings.ts +9 -0
  76. package/src/hooks/useNavigateBack.ts +37 -0
  77. package/src/pages/ConfirmSwapPage.tsx +30 -8
  78. package/src/pages/ConfirmWalletsPage.tsx +30 -17
  79. package/src/pages/HistoryPage.tsx +4 -4
  80. package/src/pages/Home.tsx +79 -36
  81. package/src/pages/LiquiditySourcesPage.tsx +11 -8
  82. package/src/pages/SelectChainPage.tsx +9 -28
  83. package/src/pages/SelectTokenPage.tsx +38 -27
  84. package/src/pages/SettingsPage.tsx +26 -11
  85. package/src/pages/SwapDetailsPage.tsx +9 -3
  86. package/src/pages/WalletsPage.tsx +37 -22
  87. package/src/store/bestRoute.ts +147 -28
  88. package/src/store/confirmSwap.ts +327 -0
  89. package/src/store/settings.ts +44 -32
  90. package/src/store/ui.ts +15 -0
  91. package/src/store/wallets.ts +93 -80
  92. package/src/swapBox.tsx +5 -5
  93. package/src/types/index.ts +1 -0
  94. package/src/types/swap.ts +13 -0
  95. package/src/utils/common.ts +4 -0
  96. package/src/utils/numbers.ts +17 -0
  97. package/src/utils/routing.ts +28 -77
  98. package/src/utils/swap.ts +445 -67
  99. package/src/utils/wallets.ts +4 -19
  100. package/dist/hooks/useBestRoute.d.ts +0 -8
  101. package/dist/hooks/useBestRoute.d.ts.map +0 -1
  102. package/dist/hooks/useConfirmSwap.d.ts +0 -2
  103. package/dist/hooks/useConfirmSwap.d.ts.map +0 -1
  104. package/src/hooks/useBestRoute.ts +0 -70
  105. package/src/hooks/useConfirmSwap.ts +0 -268
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rango-dev/widget-embedded",
3
- "version": "0.1.10-next.80",
3
+ "version": "0.1.10-next.82",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -1,10 +1,45 @@
1
- import React, { Fragment, PropsWithChildren } from 'react';
2
- import { MemoryRouter, useInRouterContext } from 'react-router';
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 ? Fragment : MemoryRouter;
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
- { path: navigationRoutes.fromChain, element: <SelectChainPage type="from" /> },
18
+ {
19
+ path: navigationRoutes.fromChain,
20
+ element: <SelectChainPage type="from" />,
21
+ },
19
22
  { path: navigationRoutes.toChain, element: <SelectChainPage type="to" /> },
20
- { path: navigationRoutes.fromToken + '/*', element: <SelectTokenPage type="from" /> },
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 { calculateWalletUsdValue, getSelectableWallets } from '../utils/wallets';
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 filterSelelectedWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
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={() => navigate(navigationRoutes.wallets)}>
40
- {accounts?.length ? (
41
- filterSelelectedWallets.map((selectedWallet, index) => (
42
- <WalletImage key={index} src={selectedWallet.image} />
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 { useLocation, useSearchParams } from 'react-router-dom';
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(tokens: Token[], searchParams: string | null): Token | null {
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 token.symbol === symbolAndAddress?.[0] && token.address === symbolAndAddress?.[1];
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
- if (!firstRender.current) {
39
- const fromChainString = fromChain?.name || '';
40
- const fromTokenString =
41
- (fromToken?.symbol || '') + (fromToken?.address ? `--${fromToken?.address}` : '');
42
- const toChainString = toChain?.name || '';
43
- const toTokenString =
44
- (toToken?.symbol || '') + (toToken?.address ? `--${toToken?.address}` : '');
45
- const fromAmount = inputAmount;
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 && { [SearchParams.FROM_CHAIN]: fromChainString }),
50
- ...(fromTokenString && { [SearchParams.FROM_TOKEN]: fromTokenString }),
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 && { [SearchParams.FROM_AMOUNT]: fromAmount.toString() }),
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((blockchain) => blockchain.name === fronChainString);
146
+ const fromChain = blockchains.find(
147
+ (blockchain) => blockchain.name === fronChainString
148
+ );
69
149
  const fromToken = searchParamsToToken(tokens, fromTokenString);
70
- const toChain = blockchains.find((blockchain) => blockchain.name === toChainString);
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=&gt; 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 =&gt; 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,9 @@
1
+ export const SLIPPAGES = [0.5, 1, 3, 5, 8, 13, 20];
2
+
3
+ export const DEFAULT_SLIPPAGE = 1;
4
+
5
+ export const HIGH_SLIPPAGE = 5;
6
+
7
+ export const MAX_SLIPPAGE = 100;
8
+
9
+ export const MIN_SLIPPGAE = 0;
@@ -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 { useConfirmSwap } from '../hooks/useConfirmSwap';
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 navigate = useNavigate();
13
+ const { navigateBackFrom } = useNavigateBack();
9
14
 
10
15
  const bestRoute = useBestRouteStore.use.bestRoute();
11
16
 
12
- const { error, loading, warning, swap } = useConfirmSwap();
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={swap.bind(null)}
17
- onBack={navigate.bind(null, -1)}
29
+ onConfirm={confirmSwap.bind(null)}
30
+ onBack={navigateBackFrom.bind(null, navigationRoutes.confirmSwap)}
18
31
  bestRoute={bestRoute}
19
32
  loading={loading}
20
- error={error}
21
- warning={warning}
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 { getKeplrCompatibleConnectedWallets, getRequiredChains, getSelectableWallets, isExperimentalChain, SelectedWallet } from '../utils/wallets';
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={() => navigate(-1)}
63
+ onBack={navigateBackFrom.bind(null, navigationRoutes.confirmWallets)}
57
64
  swap={bestRoute!}
58
- onConfirm={() => navigate(navigationRoutes.confirmSwap)}
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) => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains , wallet) : false}
71
+ isExperimentalChain={(wallet) =>
72
+ getKeplrCompatibleConnectedWallets(selectableWallets).length > 0
73
+ ? isExperimentalChain(blockchains, wallet)
74
+ : false
75
+ }
63
76
  />
64
77
  );
65
- }
78
+ }