@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
@@ -1,96 +1,63 @@
1
- import { WalletState, ConfirmSwap, History, Tooltip, Button, RetryIcon, HistoryIcon, SettingsIcon, styled, Typography, InfoCircleIcon, AngleDownIcon, TextField, VerticalSwapIcon, BestRoute, Alert, LiquiditySourcesSelector, BlockchainSelector, TokenSelector, Settings, SecondaryPage, Wallet, ConfirmWallets, SwapHistory, AddWalletIcon, globalCss, lightTheme, darkTheme, SwapContainer } from '@rango-dev/ui';
2
- import React, { useRef, useEffect, Fragment, useState } from 'react';
3
- import { useInRouterContext, MemoryRouter } from 'react-router';
4
- import { useSearchParams, useLocation, useNavigate, useInRouterContext as useInRouterContext$1, useRoutes } from 'react-router-dom';
1
+ import { WalletState, Tooltip, Button, RetryIcon, HistoryIcon, SettingsIcon, styled, Typography, InfoCircleIcon, AngleDownIcon, TextField, VerticalSwapIcon, BestRoute, Alert, ConfirmSwap, History, LiquiditySourcesSelector, BlockchainSelector, TokenSelector, Settings, SecondaryPage, Wallet, ConfirmWallets, SwapHistory, AddWalletIcon, globalCss, lightTheme, darkTheme, SwapContainer } from '@rango-dev/ui';
2
+ import React, { useRef, useEffect, useState } from 'react';
3
+ import { useInRouterContext as useInRouterContext$1, MemoryRouter, useLocation as useLocation$1, useNavigate as useNavigate$1 } from 'react-router';
4
+ import { useSearchParams, useLocation, createSearchParams, useNavigate, useInRouterContext, useRoutes } from 'react-router-dom';
5
5
  import { create } from 'zustand';
6
- import { immer } from 'zustand/middleware/immer';
7
6
  import BigNumber, { BigNumber as BigNumber$1 } from 'bignumber.js';
7
+ import { persist, subscribeWithSelector } from 'zustand/middleware';
8
8
  import { RangoClient, TransactionType } from 'rango-sdk';
9
- import { readAccountAddress, useWallets, Provider, Events } from '@rango-dev/wallets-core';
10
- import { allProviders } from '@rango-dev/provider-all';
11
9
  import { Network, isEvmAddress, KEPLR_COMPATIBLE_WALLETS, WalletType, getCosmosExperimentalChainInfo, isCosmosBlockchain, isEvmBlockchain } from '@rango-dev/wallets-shared';
12
- import { persist } from 'zustand/middleware';
10
+ import { readAccountAddress, useWallets, Provider, Events } from '@rango-dev/wallets-core';
13
11
  import { styled as styled$1 } from '@rango-dev/ui/src/theme';
12
+ import { allProviders } from '@rango-dev/provider-all';
13
+ import { shallow } from 'zustand/shallow';
14
+
15
+ const navigationRoutes = {
16
+ home: '/',
17
+ fromChain: '/from-chain',
18
+ fromToken: '/from-token',
19
+ toChain: '/to-chain',
20
+ toToken: '/to-token',
21
+ settings: '/settings',
22
+ liquiditySources: '/settings/liquidity-sources',
23
+ history: '/history',
24
+ wallets: '/wallets',
25
+ confirmSwap: '/confirm-swap',
26
+ confirmWallets: '/confirm-wallets',
27
+ swapDetails: '/history/swap-details'
28
+ };
14
29
 
15
30
  const ZERO = /*#__PURE__*/new BigNumber(0);
16
31
 
17
- const numberToString = function (number, minDecimals, maxDecimals) {
18
- if (minDecimals === void 0) {
19
- minDecimals = null;
20
- }
21
- if (maxDecimals === void 0) {
22
- maxDecimals = null;
23
- }
24
- if (number === null) return '';
25
- if (number === '') return '';
26
- const n = new BigNumber$1(number);
27
- const roundingMode = 1;
28
- let maxI = 1000;
29
- for (let i = 0; i < 60; i++) {
30
- if (new BigNumber$1(n.toFixed(i, roundingMode)).eq(n)) {
31
- maxI = i;
32
- break;
33
- }
34
- }
35
- if (n.gte(10000)) return n.toFormat(0, roundingMode);
36
- if (n.gte(1000)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))), roundingMode);
37
- if (n.gte(100)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))), roundingMode);
38
- if (n.gte(1)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 2))), roundingMode);
39
- if (n.gte(0.01)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 4))), roundingMode);
40
- for (let i = minDecimals || 4; i < 17; i++) if (n.gte(Math.pow(10, -i))) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, i))), roundingMode);
41
- if (n.isEqualTo(0)) return '0';
42
- return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 8))), roundingMode);
43
- };
32
+ function removeDuplicateFrom(array) {
33
+ return Array.from(new Set(array));
34
+ }
35
+ function areEqual(array1, array2) {
36
+ return array1.length === array2.length && array1.every((v, i) => v === array2[i]);
37
+ }
44
38
 
45
39
  const getBestRouteToTokenUsdPrice = bestRoute => bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1].to.usdPrice;
46
- const compareRoutes = (route1, route2, inputAmount, fromTokenUsdPrice, toTokenUsdPrice) => {
47
- let outUsdValue = (new BigNumber(route2.result?.outputAmount || '0') || ZERO).multipliedBy(toTokenUsdPrice || 0);
48
- if (outUsdValue.isNaN()) outUsdValue = ZERO;
49
- let inUsdValue = new BigNumber(inputAmount || '0').multipliedBy(fromTokenUsdPrice || 0);
50
- if (inUsdValue.isNaN()) inUsdValue = ZERO;
51
- const outToInRatio = inUsdValue === null || inUsdValue.lte(ZERO) ? 0 : outUsdValue === null || outUsdValue.lte(ZERO) ? 0 : outUsdValue.div(inUsdValue).minus(1).multipliedBy(100);
52
- const disableSwapButton = parseInt(outToInRatio?.toFixed(2) || '0') <= -10 && (inUsdValue === null || inUsdValue.gte(new BigNumber(400))) || parseInt(outToInRatio?.toFixed(2) || '0') <= -5 && (inUsdValue === null || inUsdValue.gte(new BigNumber(1000)));
53
- if (disableSwapButton) {
54
- return {
55
- isChanged: true,
56
- warningMessage: 'Route updated and price impact is too high, try again later!'
57
- };
58
- }
59
- const out1 = route1.result?.outputAmount || null;
60
- const out2 = route2.result?.outputAmount || null;
61
- if (!!out1 && !!out2) {
62
- const changePercent = new BigNumber(out2).div(new BigNumber(out1)).minus(1).multipliedBy(100);
63
- if (changePercent.toNumber() <= -1) {
64
- return {
65
- isChanged: true,
66
- warningMessage: `Output amount changed to ${numberToString(out2)}
67
- (${numberToString(changePercent, null, 2)}% change).`
68
- };
69
- }
70
- }
40
+ function isNumberOfSwapsChanged(route1, route2) {
71
41
  const route1Swaps = route1.result?.swaps || [];
72
42
  const route2Swaps = route2.result?.swaps || [];
73
- if (route1Swaps.length !== route2Swaps.length) return {
74
- isChanged: true,
75
- warningMessage: 'Route has been updated.'
76
- };else {
77
- for (let i = 0; i < route1Swaps.length; i++) {
78
- if (route1Swaps[i].swapperId !== route2Swaps[i].swapperId) return {
79
- isChanged: true,
80
- warningMessage: 'Route swappers has been updated.'
81
- };else if (route1Swaps[i].to.symbol !== route2Swaps[i].to.symbol) return {
82
- isChanged: true,
83
- warningMessage: 'Route internal coins has been updated.'
84
- };
85
- }
86
- }
87
- return {
88
- isChanged: false
89
- };
43
+ return route1Swaps.length !== route2Swaps.length;
44
+ }
45
+ function isRouteSwappersUpdated(route1, route2) {
46
+ const route1Swappers = route1.result?.swaps.map(swap => swap.swapperId) || [];
47
+ const route2Swappers = route2.result?.swaps.map(swap => swap.swapperId) || [];
48
+ return !areEqual(route1Swappers, route2Swappers);
49
+ }
50
+ function isRouteInternalCoinsUpdated(route1, route2) {
51
+ const route1InternalCoins = route1.result?.swaps.map(swap => swap.to.symbol) || [];
52
+ const route2InternalCoins = route2.result?.swaps.map(swap => swap.to.symbol) || [];
53
+ return !areEqual(route1InternalCoins, route2InternalCoins);
54
+ }
55
+ const isRouteChanged = (route1, route2) => {
56
+ return isNumberOfSwapsChanged(route1, route2) || isRouteSwappersUpdated(route1, route2) || isRouteInternalCoinsUpdated(route1, route2);
90
57
  };
91
- const getRequiredBalanceOfWallet = (wallet, fee) => {
58
+ const getRequiredBalanceOfWallet = (selectedWallet, fee) => {
92
59
  if (fee === null) return null;
93
- const relatedFeeStatus = fee?.find(item => item.blockchain === wallet.chain)?.wallets.find(it => it.address?.toLowerCase() === wallet.address.toLowerCase());
60
+ const relatedFeeStatus = fee?.find(item => item.blockchain === selectedWallet.chain)?.wallets.find(wallet => wallet.address?.toLowerCase() === selectedWallet.address.toLowerCase());
94
61
  if (!relatedFeeStatus) return null;
95
62
  return relatedFeeStatus.requiredAssets;
96
63
  };
@@ -104,49 +71,13 @@ const createSelectors = _store => {
104
71
  return store;
105
72
  };
106
73
 
107
- const getUsdValue = (token, amount) => new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0);
108
- const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/immer(set => ({
109
- fromChain: null,
110
- fromToken: null,
111
- inputAmount: '',
112
- outputAmount: null,
113
- inputUsdValue: new BigNumber(0),
114
- outputUsdValue: new BigNumber(0),
115
- toChain: null,
116
- toToken: null,
117
- bestRoute: null,
118
- setBestRoute: bestRoute => set(state => {
119
- state.bestRoute = bestRoute;
120
- if (!!bestRoute) {
121
- const outputAmount = !!bestRoute.result?.outputAmount ? new BigNumber(bestRoute.result?.outputAmount) : null;
122
- state.outputAmount = outputAmount;
123
- state.outputUsdValue = new BigNumber(outputAmount || ZERO).multipliedBy(getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice || 0);
124
- }
125
- }),
126
- setFromChain: chain => set(state => {
127
- state.fromChain = chain;
128
- }),
129
- setFromToken: token => set(state => {
130
- state.fromToken = token;
131
- if (!!state.inputAmount) state.inputUsdValue = getUsdValue(state.fromToken, state.inputAmount);
132
- }),
133
- setToChain: chain => set(state => {
134
- state.toChain = chain;
135
- }),
136
- setToToken: token => set(state => {
137
- state.toToken = token;
138
- }),
139
- setInputAmount: amount => set(state => {
140
- state.inputAmount = amount;
141
- if (!!state.fromToken) state.inputUsdValue = getUsdValue(state.fromToken, state.inputAmount);
142
- })
143
- }))));
144
-
145
74
  const httpService = /*#__PURE__*/new RangoClient(process.env.REACT_API_KEY);
146
75
 
147
- function removeDuplicateFrom(array) {
148
- return Array.from(new Set(array));
149
- }
76
+ const SLIPPAGES = [0.5, 1, 3, 5, 8, 13, 20];
77
+ const DEFAULT_SLIPPAGE = 1;
78
+ const HIGH_SLIPPAGE = 5;
79
+ const MAX_SLIPPAGE = 100;
80
+ const MIN_SLIPPGAE = 0;
150
81
 
151
82
  const useMetaStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()(set => ({
152
83
  meta: {
@@ -174,103 +105,87 @@ const useMetaStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()(set =>
174
105
  }
175
106
  })));
176
107
 
177
- var SearchParams;
178
- (function (SearchParams) {
179
- SearchParams["FROM_CHAIN"] = "fromChain";
180
- SearchParams["FROM_TOKEN"] = "fromToken";
181
- SearchParams["TO_CHAIN"] = "toChain";
182
- SearchParams["TO_TOKEN"] = "toToken";
183
- SearchParams["FROM_AMOUNT"] = "fromAmount";
184
- })(SearchParams || (SearchParams = {}));
185
-
186
- function searchParamsToToken(tokens, searchParams) {
187
- return tokens.find(token => {
188
- const symbolAndAddress = searchParams?.split('--');
189
- if (symbolAndAddress?.length === 1) return token.symbol === symbolAndAddress[0] && token.address === null;
190
- return token.symbol === symbolAndAddress?.[0] && token.address === symbolAndAddress?.[1];
191
- }) || null;
192
- }
193
- function UpdateUrl() {
194
- const firstRender = useRef(true);
195
- const [searchParams, setSearchParams] = useSearchParams();
196
- const location = useLocation();
197
- const fromChain = useBestRouteStore.use.fromChain();
198
- const toChain = useBestRouteStore.use.toChain();
199
- const fromToken = useBestRouteStore.use.fromToken();
200
- const toToken = useBestRouteStore.use.toToken();
201
- const setFromChain = useBestRouteStore.use.setFromChain();
202
- const setFromToken = useBestRouteStore.use.setFromToken();
203
- const setToChain = useBestRouteStore.use.setToChain();
204
- const setToToken = useBestRouteStore.use.setToToken();
205
- const inputAmount = useBestRouteStore.use.inputAmount();
206
- const setInputAmount = useBestRouteStore.use.setInputAmount();
207
- const loadingStatus = useMetaStore.use.loadingStatus();
208
- const {
209
- blockchains,
210
- tokens
211
- } = useMetaStore.use.meta();
212
- useEffect(() => {
213
- if (!firstRender.current) {
214
- const fromChainString = fromChain?.name || '';
215
- const fromTokenString = (fromToken?.symbol || '') + (fromToken?.address ? `--${fromToken?.address}` : '');
216
- const toChainString = toChain?.name || '';
217
- const toTokenString = (toToken?.symbol || '') + (toToken?.address ? `--${toToken?.address}` : '');
218
- const fromAmount = inputAmount;
219
- setSearchParams({
220
- ...(fromChainString && {
221
- [SearchParams.FROM_CHAIN]: fromChainString
222
- }),
223
- ...(fromTokenString && {
224
- [SearchParams.FROM_TOKEN]: fromTokenString
225
- }),
226
- ...(toChainString && {
227
- [SearchParams.TO_CHAIN]: toChainString
228
- }),
229
- ...(toTokenString && {
230
- [SearchParams.TO_TOKEN]: toTokenString
231
- }),
232
- ...(fromAmount && {
233
- [SearchParams.FROM_AMOUNT]: fromAmount.toString()
234
- })
235
- }, {
236
- replace: true
237
- });
238
- }
239
- firstRender.current = false;
240
- }, [location.pathname, inputAmount]);
241
- useEffect(() => {
242
- if (loadingStatus === 'success') {
243
- const fronChainString = searchParams.get(SearchParams.FROM_CHAIN);
244
- const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
245
- const toChainString = searchParams.get(SearchParams.TO_CHAIN);
246
- const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
247
- const fromAmount = searchParams.get(SearchParams.FROM_AMOUNT);
248
- const fromChain = blockchains.find(blockchain => blockchain.name === fronChainString);
249
- const fromToken = searchParamsToToken(tokens, fromTokenString);
250
- const toChain = blockchains.find(blockchain => blockchain.name === toChainString);
251
- const toToken = searchParamsToToken(tokens, toTokenString);
252
- if (!!fromChain) {
253
- setFromChain(fromChain);
254
- if (!!fromToken) setFromToken(fromToken);
255
- }
256
- if (!!toChain) {
257
- setToChain(toChain);
258
- if (!!toToken) setToToken(toToken);
259
- }
260
- if (fromAmount) setInputAmount(fromAmount);
108
+ const useSettingsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/persist( /*#__PURE__*/subscribeWithSelector(set => ({
109
+ slippage: DEFAULT_SLIPPAGE,
110
+ customSlippage: null,
111
+ infiniteApprove: false,
112
+ disabledLiquiditySources: [],
113
+ theme: 'auto',
114
+ setSlippage: slippage => set(() => ({
115
+ slippage: slippage
116
+ })),
117
+ setCustomSlippage: customSlippage => set(() => ({
118
+ customSlippage: customSlippage
119
+ })),
120
+ toggleAllLiquiditySources: () => set(state => {
121
+ const {
122
+ swappers
123
+ } = useMetaStore.getState().meta;
124
+ const swappersGroup = removeDuplicateFrom(swappers.map(swapper => swapper.swapperGroup));
125
+ if (swappersGroup.length === state.disabledLiquiditySources.length) return {
126
+ disabledLiquiditySources: []
127
+ };else {
128
+ return {
129
+ disabledLiquiditySources: swappersGroup
130
+ };
261
131
  }
262
- }, [loadingStatus]);
263
- return null;
264
- }
132
+ }),
133
+ toggleInfiniteApprove: () => set(state => ({
134
+ infiniteApprove: !state.infiniteApprove
135
+ })),
136
+ toggleLiquiditySource: name => set(state => {
137
+ if (state.disabledLiquiditySources.includes(name)) return {
138
+ disabledLiquiditySources: state.disabledLiquiditySources.filter(liquiditySource => liquiditySource != name)
139
+ };else return {
140
+ disabledLiquiditySources: state.disabledLiquiditySources.concat(name)
141
+ };
142
+ }),
143
+ setTheme: theme => set(() => ({
144
+ theme
145
+ }))
146
+ })), {
147
+ name: 'user-settings'
148
+ })));
265
149
 
266
- function AppRouter(_ref) {
267
- let {
268
- children
269
- } = _ref;
270
- const isRouterInContext = useInRouterContext();
271
- const Router = isRouterInContext ? Fragment : MemoryRouter;
272
- return React.createElement(React.Fragment, null, React.createElement(Router, null, children), isRouterInContext && React.createElement(UpdateUrl, null));
273
- }
150
+ const secondsToString = s => {
151
+ const seconds = (s % 60).toString().padStart(2, '0');
152
+ const minutes = parseInt((s / 60).toString()).toString().padStart(2, '0');
153
+ return `${minutes}:${seconds}`;
154
+ };
155
+ const numberToString = function (number, minDecimals, maxDecimals) {
156
+ if (minDecimals === void 0) {
157
+ minDecimals = null;
158
+ }
159
+ if (maxDecimals === void 0) {
160
+ maxDecimals = null;
161
+ }
162
+ if (number === null) return '';
163
+ if (number === '') return '';
164
+ const n = new BigNumber$1(number);
165
+ const roundingMode = 1;
166
+ let maxI = 1000;
167
+ for (let i = 0; i < 60; i++) {
168
+ if (new BigNumber$1(n.toFixed(i, roundingMode)).eq(n)) {
169
+ maxI = i;
170
+ break;
171
+ }
172
+ }
173
+ if (n.gte(10000)) return n.toFormat(0, roundingMode);
174
+ if (n.gte(1000)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))), roundingMode);
175
+ if (n.gte(100)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))), roundingMode);
176
+ if (n.gte(1)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 2))), roundingMode);
177
+ if (n.gte(0.01)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 4))), roundingMode);
178
+ for (let i = minDecimals || 4; i < 17; i++) if (n.gte(Math.pow(10, -i))) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, i))), roundingMode);
179
+ if (n.isEqualTo(0)) return '0';
180
+ return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 8))), roundingMode);
181
+ };
182
+ const totalArrivalTime = data => data?.result?.swaps?.reduce((a, b) => a + b.estimatedTimeInSeconds, 0) || 0;
183
+ const decimalNumber = function (number, toFixed) {
184
+ if (number === void 0) {
185
+ number = '0';
186
+ }
187
+ return parseFloat(number).toFixed(toFixed);
188
+ };
274
189
 
275
190
  function getStateWallet(state) {
276
191
  switch (true) {
@@ -366,7 +281,7 @@ function getRequiredChains(route) {
366
281
  });
367
282
  return wallets;
368
283
  }
369
- function getSelectableWallets(accounts, selectedWallets, getWalletInfo, requiredChains) {
284
+ function getSelectableWallets(accounts, selectedWallets, getWalletInfo) {
370
285
  const connectedWallets = accounts.map(account => ({
371
286
  address: account.address,
372
287
  walletType: account.walletType,
@@ -375,12 +290,8 @@ function getSelectableWallets(accounts, selectedWallets, getWalletInfo, required
375
290
  name: getWalletInfo(account.walletType).name,
376
291
  selected: !!selectedWallets.find(wallet => wallet.chain === account.chain && wallet.walletType === account.walletType)
377
292
  }));
378
- return requiredChains ? connectedWallets.filter((wallet, index, array) => requiredChains.includes(wallet.chain) && array.findIndex(w => w.address === wallet.address) === index) : removeDuplicateWallets(connectedWallets, 'walletType');
293
+ return connectedWallets;
379
294
  }
380
- const removeDuplicateWallets = (arr, key) => {
381
- const map = new Map(arr.map(item => [item[key], item]));
382
- return Array.from(map.values());
383
- };
384
295
  function getBalanceFromWallet(balances, chain, symbol, address) {
385
296
  if (balances.length === 0) return null;
386
297
  const selectedChainBalances = balances.filter(balance => balance.chain === chain);
@@ -479,540 +390,1393 @@ const getKeplrCompatibleConnectedWallets = selectableWallets => {
479
390
  return KEPLR_COMPATIBLE_WALLETS.filter(compatibleWallet => connectedWalletTypes.has(compatibleWallet));
480
391
  };
481
392
 
482
- const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()(set => ({
483
- accounts: [],
484
- balances: [],
485
- selectedWallets: [],
486
- connectWallet: accounts => {
487
- const tokens = useMetaStore.getState().meta.tokens;
488
- set(state => ({
489
- accounts: state.accounts.concat(accounts),
490
- balances: state.balances.concat(accounts.map(account => ({
491
- balances: [],
492
- address: account.address,
493
- chain: account.chain,
494
- loading: true,
495
- walletType: account.walletType,
496
- error: false,
497
- explorerUrl: null
498
- })))
499
- }));
500
- accounts.forEach(async account => {
501
- try {
502
- const response = await httpService.getWalletsDetails([{
503
- address: account.address,
504
- blockchain: account.chain
505
- }]);
506
- const retrivedBalance = response.wallets[0];
507
- if (retrivedBalance) {
508
- set(state => ({
509
- balances: state.balances.map(balance => {
510
- return isAccountAndBalanceMatched(account, balance) ? makeBalanceFor(account, retrivedBalance, tokens) : balance;
511
- })
512
- }));
513
- } else throw new Error('Wallet not found');
514
- } catch (error) {
515
- set(state => ({
516
- balances: state.balances.map(balance => {
517
- return isAccountAndBalanceMatched(account, balance) ? resetBalanceState(balance) : balance;
518
- })
519
- }));
520
- }
521
- });
522
- },
523
- disconnectWallet: walletType => {
524
- set(state => ({
525
- accounts: state.accounts.filter(account => account.walletType !== walletType),
526
- balances: state.balances.filter(balance => balance.walletType !== walletType),
527
- selectedWallets: state.selectedWallets.filter(wallet => wallet.walletType != walletType)
528
- }));
529
- },
530
- initSelectedWallets: () => set(state => {
531
- const requiredChains = getRequiredChains(useBestRouteStore.getState().bestRoute);
532
- const connectedWallets = state.accounts;
533
- const selectedWallets = [];
534
- requiredChains.forEach(chain => {
535
- const anyWalletSelected = !!state.selectedWallets.find(wallet => wallet.chain === chain);
536
- if (!anyWalletSelected) {
537
- const firstWalletWithMatchedChain = connectedWallets.find(wallet => wallet.chain === chain);
538
- if (!!firstWalletWithMatchedChain) selectedWallets.push({
539
- address: firstWalletWithMatchedChain.address,
540
- chain: firstWalletWithMatchedChain.chain,
541
- walletType: firstWalletWithMatchedChain.walletType
542
- });
543
- }
544
- });
545
- return {
546
- selectedWallets: state.selectedWallets.concat(selectedWallets)
547
- };
548
- }),
549
- setSelectedWallet: wallet => set(state => ({
550
- selectedWallets: state.selectedWallets.filter(selectedWallet => selectedWallet.chain !== wallet.chain).concat({
551
- chain: wallet.chain,
552
- address: wallet.address,
553
- walletType: wallet.walletType
554
- })
555
- }))
556
- })));
557
-
558
- const navigationRoutes = {
559
- home: '/',
560
- fromChain: '/from-chain',
561
- fromToken: '/from-token',
562
- toChain: '/to-chain',
563
- toToken: '/to-token',
564
- settings: '/settings',
565
- liquiditySources: '/liquidity-sources',
566
- history: '/history',
567
- wallets: '/wallets',
568
- confirmSwap: '/confirm-swap',
569
- confirmWallets: '/confirm-wallets',
570
- swapDetails: '/swap-details'
571
- };
572
-
573
- const useSettingsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/persist( /*#__PURE__*/immer(set => ({
574
- slippage: 1,
575
- customSlippage: null,
576
- infinitApprove: false,
577
- disabledLiquiditySources: [],
578
- theme: 'auto',
579
- setSlippage: slippage => set(state => {
580
- state.slippage = slippage;
581
- }),
582
- setCustomSlippage: customSlippage => {
583
- return set(state => {
584
- state.customSlippage = customSlippage;
585
- });
586
- },
587
- toggleAllLiquiditySources: () => set(state => {
588
- const {
589
- swappers
590
- } = useMetaStore.getState().meta;
591
- if (swappers.length - state.disabledLiquiditySources.length === 0) state.disabledLiquiditySources = [];else {
592
- const allSwappers = swappers.map(swapper => swapper.swapperGroup);
593
- state.disabledLiquiditySources = allSwappers;
393
+ function getOutputRatio(inputUsdValue, outputUsdValue) {
394
+ if (inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) return 0;
395
+ return outputUsdValue.div(inputUsdValue).minus(1).multipliedBy(100);
396
+ }
397
+ function outputRatioHasWarning(inputUsdValue, outputRatio) {
398
+ return parseInt(outputRatio.toFixed(2) || '0') <= -10 && inputUsdValue.gte(new BigNumber(400)) || parseInt(outputRatio.toFixed(2) || '0') <= -5 && inputUsdValue.gte(new BigNumber(1000));
399
+ }
400
+ function hasLimitError(bestRoute) {
401
+ return (bestRoute?.result?.swaps || []).filter(swap => {
402
+ const minimum = !!swap.fromAmountMinValue ? new BigNumber(swap.fromAmountMinValue) : null;
403
+ const maximum = !!swap.fromAmountMaxValue ? new BigNumber(swap.fromAmountMaxValue) : null;
404
+ const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
405
+ if (isExclusive) {
406
+ return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);
407
+ } else {
408
+ return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);
594
409
  }
595
- }),
596
- toggleInfinitApprove: () => set(state => {
597
- state.infinitApprove = !state.infinitApprove;
598
- }),
599
- toggleLiquiditySource: name => set(state => {
600
- state.disabledLiquiditySources = state.disabledLiquiditySources.includes(name) ? state.disabledLiquiditySources.filter(liquiditySource => liquiditySource != name) : state.disabledLiquiditySources.concat(name);
601
- }),
602
- setTheme: theme => set(state => {
603
- state.theme = theme;
604
- })
605
- })), {
606
- name: 'user-settings'
607
- })));
608
-
609
- // import { WalletType } from '@rango-dev/wallets-shared';
610
- function useConfirmSwap() {
611
- const fromToken = useBestRouteStore.use.fromToken();
612
- const toToken = useBestRouteStore.use.toToken();
613
- const inputAmount = useBestRouteStore.use.inputAmount();
614
- const bestRoute = useBestRouteStore.use.bestRoute();
615
- const setBestRoute = useBestRouteStore.use.setBestRoute();
616
- const accounts = useWalletsStore.use.accounts();
617
- const selectedWallets = useWalletsStore.use.selectedWallets();
618
- const slippage = useSettingsStore.use.slippage();
619
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
620
- const [loading, setLoading] = useState(false);
621
- const [error, setError] = useState('');
622
- const [warning, setWarning] = useState('');
623
- const [data, setData] = useState(null);
624
- const [feeStatus, setFeeStatus] = useState(null);
625
- const [bestRouteChanged, setBestRouteChanged] = useState(false);
626
- const [enoughBalance, setEnoughBalance] = useState(null);
627
- const hasEnoughBalanceOrProperSlippage = (route, selectedWallets, userSlippage, routeChanged) => {
628
- const fee = route.validationStatus;
629
- if (fee === null || fee.length === 0) return {
630
- balance: true,
631
- slippage: true,
632
- routeChanged
633
- };
634
- for (const wallet of selectedWallets) {
635
- const requiredAssets = getRequiredBalanceOfWallet(wallet, fee);
636
- if (!requiredAssets) continue;
637
- const hasEnoughBalance = requiredAssets?.map(it => it.ok).reduce((a, b) => a && b);
638
- if (!hasEnoughBalance) return {
639
- balance: false,
640
- slippage: true,
641
- routeChanged
642
- };
410
+ }).length > 0;
411
+ }
412
+ function LimitErrorMessage(bestRoute) {
413
+ if (!bestRoute) return {
414
+ swap: null,
415
+ fromAmountRangeError: '',
416
+ recommendation: ''
417
+ };
418
+ const swap = (bestRoute?.result?.swaps || []).filter(swap => {
419
+ const minimum = !!swap.fromAmountMinValue ? new BigNumber(swap.fromAmountMinValue) : null;
420
+ const maximum = !!swap.fromAmountMaxValue ? new BigNumber(swap.fromAmountMaxValue) : null;
421
+ const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
422
+ if (isExclusive) {
423
+ return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);
424
+ } else {
425
+ return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);
643
426
  }
644
- const slippages = route.result?.swaps?.map(s => s.recommendedSlippage);
645
- const slippageError = (slippages?.filter(s => !!s?.error)?.length || 0) > 0;
646
- const minSlippage = slippages?.map(s => parseFloat(s?.slippage.toString() || '0') || 0).filter(s => s > 0).sort((a, b) => b - a).find(() => true) || null;
647
- if (slippageError) {
648
- setError('Server cannot calculated required slippage for your swap');
649
- return {
650
- balance: true,
651
- slippage: false,
652
- routeChanged
653
- };
654
- } else if (minSlippage !== null && minSlippage > parseFloat(userSlippage)) {
655
- setError(`Your slippage should be ${minSlippage} at least`);
427
+ })[0];
428
+ if (!swap) return {
429
+ swap: null,
430
+ fromAmountRangeError: '',
431
+ recommendation: ''
432
+ };
433
+ const minimum = !!swap.fromAmountMinValue ? new BigNumber(swap.fromAmountMinValue) : null;
434
+ const maximum = !!swap.fromAmountMaxValue ? new BigNumber(swap.fromAmountMaxValue) : null;
435
+ const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
436
+ let fromAmountRangeError = '';
437
+ let recommendation = '';
438
+ if (!isExclusive && !!minimum && minimum.gt(swap.fromAmount)) {
439
+ fromAmountRangeError = `Required: >= ${numberToString(minimum)} ${swap.from.symbol}`;
440
+ recommendation = 'Increase your swap amount';
441
+ } else if (isExclusive && !!minimum && minimum.gte(swap.fromAmount)) {
442
+ fromAmountRangeError = `Required: > ${numberToString(minimum)} ${swap.from.symbol}`;
443
+ recommendation = 'Increase your swap amount';
444
+ }
445
+ if (!isExclusive && !!maximum && maximum.lt(swap.fromAmount)) {
446
+ fromAmountRangeError = `Required: <= ${numberToString(maximum)} ${swap.from.symbol}`;
447
+ recommendation = 'Decrease your swap amount';
448
+ } else if (isExclusive && !!maximum && maximum.lte(swap.fromAmount)) {
449
+ fromAmountRangeError = `Required: < ${numberToString(maximum)} ${swap.from.symbol}`;
450
+ recommendation = 'Decrease your swap amount';
451
+ }
452
+ return {
453
+ swap,
454
+ fromAmountRangeError,
455
+ recommendation
456
+ };
457
+ }
458
+ function getSwapButtonState(loadingMetaStatus, accounts, loading, bestRoute, hasLimitError, highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath) {
459
+ if (loadingMetaStatus !== 'success') return {
460
+ title: 'Connect Wallet',
461
+ disabled: true
462
+ };
463
+ if (accounts.length == 0) return {
464
+ title: 'Connect Wallet',
465
+ disabled: false
466
+ };
467
+ if (loading) return {
468
+ title: 'Finding Best Route...',
469
+ disabled: true
470
+ };else if (!bestRoute) return {
471
+ title: 'Swap',
472
+ disabled: true
473
+ };else if (hasLimitError) return {
474
+ title: 'Limit Error',
475
+ disabled: true
476
+ };else if (highValueLoss) return {
477
+ title: 'Price impact is too high!',
478
+ disabled: true
479
+ };else if (priceImpactCanNotBeComputed) return {
480
+ title: 'USD price is unknown, price impact might be high!',
481
+ disabled: false,
482
+ hasWarning: true
483
+ };else if (needsToWarnEthOnPath) return {
484
+ title: 'The route goes through Ethereum. Continue?',
485
+ disabled: false,
486
+ hasWarning: true
487
+ };else return {
488
+ title: 'Swap',
489
+ disabled: false
490
+ };
491
+ }
492
+ function canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue) {
493
+ return !((inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) && !!bestRoute?.result && !!inputAmount && inputAmount !== '0' && parseFloat(inputAmount || '0') !== 0 && !!bestRoute.result);
494
+ }
495
+ function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validateBalanceOrFee, meta) {
496
+ const simulationResult = bestRoute.result;
497
+ if (!simulationResult) throw Error('Simulation result should not be null');
498
+ return {
499
+ creationTime: new Date().getTime().toString(),
500
+ finishTime: null,
501
+ requestId: bestRoute.requestId || '',
502
+ inputAmount: inputAmount,
503
+ wallets,
504
+ status: 'running',
505
+ isPaused: false,
506
+ extraMessage: null,
507
+ extraMessageSeverity: null,
508
+ extraMessageDetail: null,
509
+ extraMessageErrorCode: null,
510
+ networkStatusExtraMessage: null,
511
+ networkStatusExtraMessageDetail: null,
512
+ lastNotificationTime: null,
513
+ //@ts-ignore
514
+ settings: settings,
515
+ simulationResult: simulationResult,
516
+ validateBalanceOrFee,
517
+ steps: bestRoute.result?.swaps?.map((swap, index) => {
518
+ const swapper = meta.swappers.find(swapper => swapper.id === swap.swapperId);
519
+ const swapperType = swapper?.types[0];
520
+ const fromBlockchain = meta.blockchains.find(blockchain => blockchain.name === swap.from.blockchain);
521
+ const toBlockchain = meta.blockchains.find(blockchain => blockchain.name === swap.to.blockchain);
656
522
  return {
657
- balance: true,
658
- slippage: false,
659
- routeChanged
523
+ id: index + 1,
524
+ fromBlockchain: swap.from.blockchain,
525
+ fromSymbol: swap.from.symbol,
526
+ fromSymbolAddress: swap.from.address,
527
+ fromDecimals: swap.from.decimals,
528
+ fromAmountPrecision: swap.fromAmountPrecision,
529
+ fromAmountMinValue: swap.fromAmountMinValue,
530
+ fromAmountMaxValue: swap.fromAmountMaxValue,
531
+ toBlockchain: swap.to.blockchain,
532
+ fromLogo: swap.from.logo,
533
+ toSymbol: swap.to.symbol,
534
+ toSymbolAddress: swap.to.address,
535
+ toDecimals: swap.to.decimals,
536
+ toLogo: swap.to.logo,
537
+ startTransactionTime: new Date().getTime(),
538
+ swapperId: swap.swapperId,
539
+ feeInUsd: numberToString(getUsdFeeOfStep(swap, meta.tokens), null, 2),
540
+ expectedOutputAmountHumanReadable: swap.toAmount,
541
+ outputAmount: '',
542
+ status: 'created',
543
+ networkStatus: null,
544
+ executedTransactionId: null,
545
+ externalTransactionId: null,
546
+ explorerUrl: null,
547
+ trackingCode: null,
548
+ cosmosTransaction: null,
549
+ solanaTransaction: null,
550
+ starknetTransaction: null,
551
+ starknetApprovalTransaction: null,
552
+ tronTransaction: null,
553
+ tronApprovalTransaction: null,
554
+ evmTransaction: null,
555
+ evmApprovalTransaction: null,
556
+ transferTransaction: null,
557
+ diagnosisUrl: null,
558
+ internalSteps: null,
559
+ fromBlockchainLogo: fromBlockchain.logo,
560
+ toBlockchainLogo: toBlockchain.logo,
561
+ swapperLogo: swapper?.logo,
562
+ swapperType: swapperType
660
563
  };
661
- }
662
- return {
663
- balance: true,
664
- slippage: true,
665
- routeChanged
666
- };
564
+ }) || []
667
565
  };
668
- const checkFeeAndBalance = async selectedWallets => {
669
- setLoading(true);
670
- setFeeStatus(null);
671
- const selectedWalletsMap = selectedWallets.reduce((selectedWalletsMap, selectedWallet) => (selectedWalletsMap[selectedWallet.chain] = selectedWallet.address, selectedWalletsMap), {});
672
- const connectedWallets = [];
673
- accounts.forEach(account => {
674
- const chainAndAccounts = connectedWallets.find(wallet => wallet.blockchain);
675
- if (!!chainAndAccounts) chainAndAccounts.addresses.push(account.address);else connectedWallets.push({
676
- blockchain: account.chain,
677
- addresses: [account.address]
678
- });
679
- });
680
- const r = await httpService.getBestRoute({
681
- amount: inputAmount.toString(),
682
- checkPrerequisites: true,
683
- from: {
684
- address: fromToken.address,
685
- blockchain: fromToken.blockchain,
686
- symbol: fromToken.symbol
687
- },
688
- to: {
689
- address: toToken.address,
690
- blockchain: toToken.blockchain,
691
- symbol: toToken.symbol
692
- },
693
- connectedWallets,
694
- selectedWallets: selectedWalletsMap,
695
- //@ts-ignore
696
- swapperGroups: disabledLiquiditySources,
697
- swappersGroupsExclude: true
698
- }).catch(error => {
699
- setError(error.message);
700
- setLoading(false);
566
+ }
567
+ function requiredWallets(route) {
568
+ const wallets = [];
569
+ route?.result?.swaps.forEach(swap => {
570
+ const currentStepFromBlockchain = swap.from.blockchain;
571
+ const currentStepToBlockchain = swap.to.blockchain;
572
+ let lastAddedWallet = wallets[wallets.length - 1];
573
+ if (currentStepFromBlockchain != lastAddedWallet) wallets.push(currentStepFromBlockchain);
574
+ lastAddedWallet = wallets[wallets.length - 1];
575
+ if (currentStepToBlockchain != lastAddedWallet) wallets.push(currentStepToBlockchain);
576
+ });
577
+ return wallets;
578
+ }
579
+ const getUsdPrice$1 = (blockchain, symbol, address, allTokens) => {
580
+ const token = allTokens?.find(t => t.blockchain === blockchain && t.symbol?.toUpperCase() === symbol?.toUpperCase() && t.address === address);
581
+ return token?.usdPrice || null;
582
+ };
583
+ function getUsdFeeOfStep(step, allTokens) {
584
+ let totalFeeInUsd = ZERO;
585
+ for (let i = 0; i < step.fee.length; i++) {
586
+ const fee = step.fee[i];
587
+ if (fee.expenseType === 'DECREASE_FROM_OUTPUT') continue;
588
+ const unitPrice = getUsdPrice$1(fee.asset.blockchain, fee.asset.symbol, fee.asset.address, allTokens);
589
+ totalFeeInUsd = totalFeeInUsd.plus(new BigNumber(fee.amount).multipliedBy(unitPrice || 0));
590
+ }
591
+ return totalFeeInUsd;
592
+ }
593
+ function getTotalFeeInUsd(bestRoute, allTokens) {
594
+ return bestRoute?.result?.swaps.reduce((totalFee, step) => totalFee.plus(getUsdFeeOfStep(step, allTokens)), ZERO) || null;
595
+ }
596
+ function hasHighFee(totalFeeInUsd) {
597
+ if (!totalFeeInUsd) return false;
598
+ return !totalFeeInUsd.lt(new BigNumber(30));
599
+ }
600
+ function getMinRequiredSlippage(route) {
601
+ const slippages = route.result?.swaps.map(slippage => slippage.recommendedSlippage);
602
+ return slippages?.map(s => s?.slippage || 0)?.filter(s => s > 0)?.sort((a, b) => b - a)?.find(() => true) || null;
603
+ }
604
+ function hasProperSlippage(userSlippage, minRequiredSlippage) {
605
+ if (!minRequiredSlippage) return true;
606
+ return parseFloat(userSlippage) > minRequiredSlippage;
607
+ }
608
+ function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, selectedWallets, disabledLiquiditySources, slippage, checkPrerequisites) {
609
+ const selectedWalletsMap = selectedWallets.reduce((selectedWalletsMap, selectedWallet) => (selectedWalletsMap[selectedWallet.chain] = selectedWallet.address, selectedWalletsMap), {});
610
+ const connectedWallets = [];
611
+ wallets.forEach(wallet => {
612
+ const chainAndAccounts = connectedWallets.find(connectedWallet => connectedWallet.blockchain === wallet.chain);
613
+ if (!!chainAndAccounts) chainAndAccounts.addresses.push(wallet.address);else connectedWallets.push({
614
+ blockchain: wallet.chain,
615
+ addresses: [wallet.address]
701
616
  });
702
- setLoading(false);
703
- if (!r || !r.result || !bestRoute) return {
704
- bestRoute: null
705
- };
706
- if (!new BigNumber(r.requestAmount).isEqualTo(new BigNumber(inputAmount || '-1'))) return null;
707
- setFeeStatus(r.validationStatus);
708
- const routeChangeStatus = compareRoutes(bestRoute, r, inputAmount.toString(), fromToken.usdPrice, toToken.usdPrice);
709
- setBestRoute(r);
710
- const isChanged = routeChangeStatus.isChanged;
711
- // const changeWarningMessage = routeChangeStatus.warningMessage;
712
- setBestRouteChanged(isChanged);
713
- setWarning('Best route changed');
714
- setData(r);
617
+ });
618
+ const requestBody = {
619
+ amount: inputAmount.toString(),
620
+ checkPrerequisites,
621
+ from: {
622
+ address: fromToken.address,
623
+ blockchain: fromToken.blockchain,
624
+ symbol: fromToken.symbol
625
+ },
626
+ to: {
627
+ address: toToken.address,
628
+ blockchain: toToken.blockchain,
629
+ symbol: toToken.symbol
630
+ },
631
+ connectedWallets,
632
+ selectedWallets: selectedWalletsMap,
633
+ swapperGroups: disabledLiquiditySources,
634
+ swappersGroupsExclude: true,
635
+ //@ts-ignore
636
+ slippage: slippage.toString()
637
+ };
638
+ return requestBody;
639
+ }
640
+ function getWalletsForNewSwap(selectedWallets) {
641
+ const wallets = selectedWallets.reduce((selectedWalletsMap, selectedWallet) => (selectedWalletsMap[selectedWallet.chain] = {
642
+ address: selectedWallet.address,
643
+ walletType: selectedWallet.walletType
644
+ }, selectedWalletsMap), {});
645
+ return wallets;
646
+ }
647
+ function getRouteOutputAmount(route) {
648
+ return route.result?.outputAmount || null;
649
+ }
650
+ function getPercentageChange(oldValue, newValue) {
651
+ return new BigNumber(newValue).div(new BigNumber(oldValue)).minus(1).multipliedBy(100);
652
+ }
653
+ function isOutputAmountChangedALot(oldRoute, newRoute) {
654
+ const oldOutputAmount = getRouteOutputAmount(oldRoute);
655
+ const newOutputAmount = getRouteOutputAmount(newRoute);
656
+ if (!oldOutputAmount || !newOutputAmount) return false;
657
+ const percentageChange = getPercentageChange(oldOutputAmount, newOutputAmount);
658
+ return percentageChange.toNumber() <= -1;
659
+ }
660
+ function getBalanceWarnings(route, selectedWallets) {
661
+ const fee = route.validationStatus;
662
+ const requiredWallets = getRequiredChains(route);
663
+ const walletsSortedByRequiredWallets = selectedWallets.sort((selectedWallet1, selectedWallet2) => requiredWallets.indexOf(selectedWallet1.chain) - requiredWallets.indexOf(selectedWallet2.chain));
664
+ return walletsSortedByRequiredWallets.flatMap(wallet => getRequiredBalanceOfWallet(wallet, fee) || []).filter(asset => !asset.ok).map(asset => {
665
+ const symbol = asset.asset.symbol;
666
+ const currentAmount = numberToString(new BigNumber(asset.currentAmount.amount).shiftedBy(-asset.currentAmount.decimals), 8);
667
+ const requiredAmount = numberToString(new BigNumber(asset.requiredAmount.amount).shiftedBy(-asset.requiredAmount.decimals), 8);
668
+ let reason = '';
669
+ if (asset.reason === 'FEE') reason = ' for network fee';
670
+ if (asset.reason === 'INPUT_ASSET') reason = ' for swap';
671
+ if (asset.reason === 'FEE_AND_INPUT_ASSET') reason = ' for input and network fee';
672
+ const warningMessage = `Needs ≈ ${requiredAmount} ${symbol}${reason}, but you have ${currentAmount} ${symbol} in your ${asset.asset.blockchain} wallet.`;
673
+ return warningMessage;
674
+ });
675
+ }
676
+
677
+ const getUsdValue = (token, amount) => new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0);
678
+ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/subscribeWithSelector(set => ({
679
+ fromChain: null,
680
+ fromToken: null,
681
+ inputAmount: '',
682
+ outputAmount: null,
683
+ inputUsdValue: new BigNumber(0),
684
+ outputUsdValue: new BigNumber(0),
685
+ toChain: null,
686
+ toToken: null,
687
+ bestRoute: null,
688
+ loading: false,
689
+ error: '',
690
+ setBestRoute: bestRoute => set(state => {
691
+ let outputAmount = null;
692
+ let outputUsdValue = ZERO;
693
+ if (!!bestRoute) {
694
+ outputAmount = !!bestRoute.result?.outputAmount ? new BigNumber(bestRoute.result?.outputAmount) : null;
695
+ outputUsdValue = new BigNumber(outputAmount || ZERO).multipliedBy(getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice || 0);
696
+ }
715
697
  return {
716
- hasEnoughBalanceOrSlippage: hasEnoughBalanceOrProperSlippage(r, selectedWallets, slippage.toString(), isChanged),
717
- bestRoute: r
698
+ bestRoute,
699
+ ...(!!bestRoute && {
700
+ outputAmount,
701
+ outputUsdValue
702
+ })
718
703
  };
719
- };
720
- const swap = () => {
721
- if (!bestRoute) return;
722
- if (inputAmount.toString() === '') return;
723
- // const wallets = selectedWallets.reduce(
724
- // (
725
- // selectedWalletsMap: { [p: string]: { address: string; walletType: WalletType } },
726
- // selectedWallet,
727
- // ) => (
728
- // (selectedWalletsMap[selectedWallet.chain] = {
729
- // address: selectedWallet.address,
730
- // walletType: selectedWallet.walletType,
731
- // }),
732
- // selectedWalletsMap
733
- // ),
734
- // {},
735
- // );
736
- const proceedAnyway = enoughBalance !== null;
737
- // const settings: SwapSavedSettings = {
738
- // slippage: slippage.toString(),
739
- // disabledSwappersGroups: ['Osmosis'],
740
- // disabledSwappersIds: [],
741
- // };
742
- // if (proceedAnyway) {
743
- // const newSwap: PendingSwap = calculatePendingSwap(
744
- // inputAmount!.toString(),
745
- // bestRoute,
746
- // wallets,
747
- // settings,
748
- // false,
749
- // );
750
- // }
751
- !proceedAnyway && checkFeeAndBalance(selectedWallets).then(data => {
752
- if (!data) {
753
- setError('confirm swap error');
754
- return;
755
- }
756
- if (!data.bestRoute) {
757
- setError('confirm swap error');
758
- return;
759
- } else {
760
- // @ts-ignore
761
- const {
762
- hasEnoughBalanceOrSlippage
763
- } = data;
764
- if (!hasEnoughBalanceOrSlippage) {
765
- return;
766
- }
767
- setEnoughBalance(hasEnoughBalanceOrSlippage.balance && hasEnoughBalanceOrSlippage.slippage);
768
- if (hasEnoughBalanceOrSlippage.balance && hasEnoughBalanceOrSlippage.slippage && !hasEnoughBalanceOrSlippage.routeChanged) ; else if (!hasEnoughBalanceOrSlippage.balance) {
769
- setError('not enough balance');
770
- }
771
- }
704
+ }),
705
+ setFromChain: chain => set(() => ({
706
+ fromChain: chain
707
+ })),
708
+ setFromToken: token => set(state => ({
709
+ fromToken: token,
710
+ ...(!!state.inputAmount && {
711
+ inputUsdValue: getUsdValue(token, state.inputAmount)
712
+ })
713
+ })),
714
+ setToChain: chain => set(() => ({
715
+ toChain: chain
716
+ })),
717
+ setToToken: token => set(() => ({
718
+ toToken: token
719
+ })),
720
+ setInputAmount: amount => set(state => ({
721
+ inputAmount: amount,
722
+ ...(!!state.fromToken && {
723
+ inputUsdValue: getUsdValue(state.fromToken, amount)
724
+ })
725
+ }))
726
+ }))));
727
+ const bestRoute = (bestRouteStore, settingsStore) => {
728
+ let abortController = null;
729
+ const fetchBestRoute = () => {
730
+ const {
731
+ fromToken,
732
+ toToken,
733
+ inputAmount
734
+ } = bestRouteStore.getState();
735
+ const {
736
+ slippage,
737
+ customSlippage,
738
+ disabledLiquiditySources
739
+ } = settingsStore.getState();
740
+ if (!fromToken || !toToken || !inputAmount) return;
741
+ abortController?.abort();
742
+ abortController = new AbortController();
743
+ const userSlippage = customSlippage | slippage;
744
+ const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, [], [], disabledLiquiditySources, userSlippage, false);
745
+ bestRouteStore.setState({
746
+ loading: true,
747
+ bestRoute: null
748
+ });
749
+ httpService.getBestRoute(requestBody, {
750
+ signal: abortController.signal
751
+ }).then(res => {
752
+ const {
753
+ setBestRoute
754
+ } = bestRouteStore.getState();
755
+ setBestRoute(res);
756
+ bestRouteStore.setState({
757
+ loading: false
758
+ });
759
+ abortController = null;
772
760
  }).catch(error => {
773
- console.log('unexpected error', error);
761
+ if (error.code === 'ERR_CANCELED') return;
762
+ bestRouteStore.setState({
763
+ error: error.message,
764
+ loading: false
765
+ });
774
766
  });
775
767
  };
768
+ useBestRouteStore.subscribe(state => ({
769
+ fromChain: state.fromChain,
770
+ fromToken: state.fromToken,
771
+ toChain: state.toChain,
772
+ toToken: state.toToken,
773
+ inputAmount: state.inputAmount
774
+ }), fetchBestRoute.bind(null), {
775
+ equalityFn: (prevState, state) => {
776
+ if (prevState.fromChain?.name !== state.fromChain?.name || prevState.toChain?.name !== state.toChain?.name || prevState.fromToken?.symbol !== state.fromToken?.symbol || prevState.toToken?.symbol !== state.toToken?.symbol || prevState.fromToken?.blockchain !== state.fromToken?.blockchain || prevState.toToken?.blockchain !== state.toToken?.blockchain || prevState.fromToken?.address !== state.fromToken?.address || prevState.toToken?.address !== state.toToken?.address || prevState.inputAmount !== state.inputAmount) return false;else return true;
777
+ }
778
+ });
779
+ useSettingsStore.subscribe(state => ({
780
+ slippage: state.slippage,
781
+ customSlippage: state.customSlippage,
782
+ disabledLiquiditySources: state.disabledLiquiditySources
783
+ }), fetchBestRoute.bind(null), {
784
+ equalityFn: (prevState, state) => {
785
+ if (prevState.slippage !== state.slippage || prevState.customSlippage !== state.customSlippage || prevState.disabledLiquiditySources.length !== state.disabledLiquiditySources.length) return false;else return true;
786
+ }
787
+ });
776
788
  return {
777
- loading,
778
- error,
779
- data,
780
- warning,
781
- feeStatus,
782
- bestRouteChanged,
783
- enoughBalance,
784
- swap
789
+ fetchBestRoute
785
790
  };
786
- }
791
+ };
792
+ const {
793
+ fetchBestRoute
794
+ } = /*#__PURE__*/bestRoute(useBestRouteStore, useSettingsStore);
787
795
 
788
- function ConfirmSwapPage() {
789
- const navigate = useNavigate();
790
- const bestRoute = useBestRouteStore.use.bestRoute();
791
- const {
792
- error,
793
- loading,
794
- warning,
795
- swap
796
- } = useConfirmSwap();
797
- return React.createElement(ConfirmSwap, {
798
- onConfirm: swap.bind(null),
799
- onBack: navigate.bind(null, -1),
800
- bestRoute: bestRoute,
801
- loading: loading,
802
- error: error,
803
- warning: warning
804
- });
805
- }
796
+ var SearchParams;
797
+ (function (SearchParams) {
798
+ SearchParams["FROM_CHAIN"] = "fromChain";
799
+ SearchParams["FROM_TOKEN"] = "fromToken";
800
+ SearchParams["TO_CHAIN"] = "toChain";
801
+ SearchParams["TO_TOKEN"] = "toToken";
802
+ SearchParams["FROM_AMOUNT"] = "fromAmount";
803
+ })(SearchParams || (SearchParams = {}));
806
804
 
807
- const pendingSwap = [{
808
- creationTime: '1673164511955',
809
- finishTime: '1673164550137',
810
- requestId: '51e211d9-d61c-45d2-a4d4-1f9f7f90ee85',
811
- inputAmount: '1',
812
- wallets: {
813
- OSMOSIS: {
814
- walletType: 'keplr',
815
- address: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl'
816
- }
817
- },
818
- status: 'running',
819
- isPaused: false,
820
- extraMessage: null,
821
- extraMessageSeverity: 'info',
822
- extraMessageDetail: '',
823
- extraMessageErrorCode: null,
824
- networkStatusExtraMessage: null,
825
- networkStatusExtraMessageDetail: null,
826
- lastNotificationTime: null,
827
- settings: {
828
- slippage: '1.0',
829
- disabledSwappersIds: [],
830
- disabledSwappersGroups: []
831
- },
832
- simulationResult: {
833
- outputAmount: '1.540670',
834
- swaps: [{
835
- swapperId: 'Osmosis',
836
- swapperType: 'DEX',
837
- swapperLogo: '',
838
- // @ts-ignore
839
- result: null,
840
- from: {
841
- symbol: 'JUNO',
842
- logo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
843
- address: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
844
- blockchain: 'OSMOSIS',
845
- blockchainLogo: '',
846
- decimals: 6,
847
- usdPrice: 1.1091996179668873
848
- },
849
- to: {
850
- symbol: 'OSMO',
851
- logo: 'https://api.rango.exchange/i/mJQPS2',
852
- address: null,
853
- blockchain: 'OSMOSIS',
854
- decimals: 6,
855
- blockchainLogo: '',
856
- usdPrice: 0.7192435454440882
857
- },
858
- fromAmount: '1.000000',
859
- fromAmountPrecision: null,
860
- fromAmountMinValue: null,
861
- fromAmountMaxValue: null,
862
- toAmount: '1.540670',
863
- fee: [{
864
- name: '',
865
- asset: {
866
- blockchain: 'OSMOSIS',
867
- symbol: 'OSMO',
868
- address: null
869
- },
870
- expenseType: 'FROM_SOURCE_WALLET',
871
- amount: '0'
872
- }],
873
- estimatedTimeInSeconds: 45,
874
- swapChainType: 'INTRA_CHAIN',
875
- routes: [{
876
- nodes: [{
877
- nodes: [{
878
- marketName: 'pool#498',
879
- marketId: null,
880
- percent: 1
881
- }],
882
- from: 'JUNO',
883
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
884
- fromAddress: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
885
- fromBlockchain: 'OSMOSIS',
886
- to: 'ATOM',
887
- toLogo: 'https://api.rango.exchange/tokens/COSMOS/ATOM.png',
888
- toAddress: 'ibc/27394fb092d2eccd56123c74f36e4c1f926001ceada9ca97ea622b25f41e5eb2',
889
- toBlockchain: 'OSMOSIS'
890
- }, {
891
- nodes: [{
892
- marketName: 'pool#8',
893
- marketId: null,
894
- percent: 1
895
- }],
896
- from: 'ATOM',
897
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/ATOM.png',
898
- fromAddress: 'ibc/27394fb092d2eccd56123c74f36e4c1f926001ceada9ca97ea622b25f41e5eb2',
899
- fromBlockchain: 'OSMOSIS',
900
- to: 'IRIS',
901
- toLogo: 'https://api.rango.exchange/tokens/COSMOS/IRIS.png',
902
- toAddress: 'ibc/7c4d60aa95e5a7558b0a364860979ca34b7ff8aaf255b87af9e879374470cec0',
903
- toBlockchain: 'OSMOSIS'
805
+ function searchParamsToToken(tokens, searchParams) {
806
+ return tokens.find(token => {
807
+ const symbolAndAddress = searchParams?.split('--');
808
+ if (symbolAndAddress?.length === 1) return token.symbol === symbolAndAddress[0] && token.address === null;
809
+ return token.symbol === symbolAndAddress?.[0] && token.address === symbolAndAddress?.[1];
810
+ }) || null;
811
+ }
812
+ function UpdateUrl() {
813
+ const firstRender = useRef(true);
814
+ const [searchParams, setSearchParams] = useSearchParams();
815
+ const location = useLocation();
816
+ const firstRenderSearchParams = useRef(location.search);
817
+ const searchParamsRef = useRef({});
818
+ useEffect(() => {
819
+ const params = {};
820
+ createSearchParams(firstRenderSearchParams.current).forEach((value, key) => {
821
+ params[key] = value;
822
+ });
823
+ searchParamsRef.current = params;
824
+ }, []);
825
+ const fromChain = useBestRouteStore.use.fromChain();
826
+ const toChain = useBestRouteStore.use.toChain();
827
+ const fromToken = useBestRouteStore.use.fromToken();
828
+ const toToken = useBestRouteStore.use.toToken();
829
+ const setFromChain = useBestRouteStore.use.setFromChain();
830
+ const setFromToken = useBestRouteStore.use.setFromToken();
831
+ const setToChain = useBestRouteStore.use.setToChain();
832
+ const setToToken = useBestRouteStore.use.setToToken();
833
+ const inputAmount = useBestRouteStore.use.inputAmount();
834
+ const setInputAmount = useBestRouteStore.use.setInputAmount();
835
+ const loadingStatus = useMetaStore.use.loadingStatus();
836
+ const {
837
+ blockchains,
838
+ tokens
839
+ } = useMetaStore.use.meta();
840
+ useEffect(() => {
841
+ let fromChainString = '',
842
+ fromTokenString = '',
843
+ toChainString = '',
844
+ toTokenString = '',
845
+ fromAmount = '';
846
+ if (loadingStatus !== 'success' && ![navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname)) {
847
+ fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
848
+ fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
849
+ toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
850
+ toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];
851
+ fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT];
852
+ setSearchParams({
853
+ ...(fromChainString && {
854
+ [SearchParams.FROM_CHAIN]: fromChainString
855
+ }),
856
+ ...(fromTokenString && {
857
+ [SearchParams.FROM_TOKEN]: fromTokenString
858
+ }),
859
+ ...(toChainString && {
860
+ [SearchParams.TO_CHAIN]: toChainString
861
+ }),
862
+ ...(toTokenString && {
863
+ [SearchParams.TO_TOKEN]: toTokenString
864
+ }),
865
+ ...(fromAmount && {
866
+ [SearchParams.FROM_AMOUNT]: fromAmount.toString()
867
+ })
868
+ }, {
869
+ replace: true
870
+ });
871
+ }
872
+ if (!firstRender.current) {
873
+ let fromChainString = '',
874
+ fromTokenString = '',
875
+ toChainString = '',
876
+ toTokenString = '',
877
+ fromAmount = '';
878
+ if (loadingStatus !== 'success') {
879
+ fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
880
+ fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
881
+ toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
882
+ toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];
883
+ fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT];
884
+ } else {
885
+ if (location.state === 'redirect') return;
886
+ fromChainString = fromChain?.name || '';
887
+ fromTokenString = (fromToken?.symbol || '') + (fromToken?.address ? `--${fromToken?.address}` : '');
888
+ toChainString = toChain?.name || '';
889
+ toTokenString = (toToken?.symbol || '') + (toToken?.address ? `--${toToken?.address}` : '');
890
+ fromAmount = inputAmount;
891
+ setSearchParams({
892
+ ...(fromChainString && {
893
+ [SearchParams.FROM_CHAIN]: fromChainString
894
+ }),
895
+ ...(fromTokenString && {
896
+ [SearchParams.FROM_TOKEN]: fromTokenString
897
+ }),
898
+ ...(toChainString && {
899
+ [SearchParams.TO_CHAIN]: toChainString
900
+ }),
901
+ ...(toTokenString && {
902
+ [SearchParams.TO_TOKEN]: toTokenString
903
+ }),
904
+ ...(fromAmount && {
905
+ [SearchParams.FROM_AMOUNT]: fromAmount.toString()
906
+ })
904
907
  }, {
905
- nodes: [{
906
- marketName: 'pool#7',
907
- marketId: null,
908
- percent: 1
909
- }],
910
- from: 'IRIS',
911
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/IRIS.png',
912
- fromAddress: 'ibc/7c4d60aa95e5a7558b0a364860979ca34b7ff8aaf255b87af9e879374470cec0',
913
- fromBlockchain: 'OSMOSIS',
914
- to: 'OSMO',
915
- toLogo: 'https://api.rango.exchange/tokens/COSMOS/OSMO.png',
916
- toAddress: null,
917
- toBlockchain: 'OSMOSIS'
918
- }]
919
- }],
920
- recommendedSlippage: null,
921
- timeStat: {
922
- min: 6,
923
- avg: 40,
924
- max: 241
925
- },
926
- includesDestinationTx: false
927
- }]
928
- },
929
- validateBalanceOrFee: true,
930
- steps: [{
931
- id: 1,
932
- fromBlockchain: 'OSMOSIS',
933
- fromSymbol: 'JUNO',
934
- fromSymbolAddress: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
935
- fromDecimals: 6,
936
- fromAmountPrecision: null,
937
- fromAmountMinValue: null,
938
- swapperLogo: '',
939
- swapperType: '',
940
- fromAmountMaxValue: null,
941
- toBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
942
- fromBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
943
- toBlockchain: 'OSMOSIS',
944
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
945
- toSymbol: 'OSMO',
946
- toSymbolAddress: null,
947
- toDecimals: 6,
948
- toLogo: 'https://api.rango.exchange/i/mJQPS2',
949
- startTransactionTime: 1673164519916,
950
- swapperId: 'Osmosis',
951
- expectedOutputAmountHumanReadable: '1.540670',
952
- outputAmount: '1.540658',
953
- status: 'running',
954
- networkStatus: null,
955
- executedTransactionId: '0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
956
- explorerUrl: [{
957
- url: 'https://www.mintscan.io/osmosis/txs/0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
958
- description: null
959
- }],
960
- cosmosTransaction: {
961
- type: TransactionType.COSMOS,
962
- fromWalletAddress: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
963
- blockChain: 'OSMOSIS',
964
- data: {
965
- chainId: 'osmosis-1',
966
- account_number: 102721,
967
- sequence: '308',
968
- msgs: [{
969
- __type: 'OsmosisSwapMessage',
970
- type: 'osmosis/gamm/swap-exact-amount-in',
971
- value: {
972
- sender: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
973
- routes: [{
974
- pool_id: '498',
975
- token_out_denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2'
976
- }, {
977
- pool_id: '8',
978
- token_out_denom: 'ibc/7C4D60AA95E5A7558B0A364860979CA34B7FF8AAF255B87AF9E879374470CEC0'
979
- }, {
980
- pool_id: '7',
981
- token_out_denom: 'uosmo'
982
- }],
983
- token_in: {
984
- denom: 'ibc/46B44899322F3CD854D2D46DEEF881958467CDD4B3B10086DA49296BBED94BED',
985
- amount: '1000000'
986
- },
987
- token_out_min_amount: '1525264'
988
- }
989
- }],
990
- protoMsgs: [{
991
- type_url: '/osmosis.gamm.v1beta1.MsgSwapExactAmountIn',
992
- value: [10, 43, 111, 115, 109, 111, 49, 117, 110, 102, 50, 114, 99, 121, 116, 106, 120, 102, 112, 122, 56, 120, 56, 97, 114, 54, 51, 104, 52, 113, 101, 102, 116, 97, 100, 112, 116, 103, 53, 116, 48, 110, 113, 99, 108, 18, 73, 8, -14, 3, 18, 68, 105, 98, 99, 47, 50, 55, 51, 57, 52, 70, 66, 48, 57, 50, 68, 50, 69, 67, 67, 68, 53, 54, 49, 50, 51, 67, 55, 52, 70, 51, 54, 69, 52, 67, 49, 70, 57, 50, 54, 48, 48, 49, 67, 69, 65, 68, 65, 57, 67, 65, 57, 55, 69, 65, 54, 50, 50, 66, 50, 53, 70, 52, 49, 69, 53, 69, 66, 50, 18, 72, 8, 8, 18, 68, 105, 98, 99, 47, 55, 67, 52, 68, 54, 48, 65, 65, 57, 53, 69, 53, 65, 55, 53, 53, 56, 66, 48, 65, 51, 54, 52, 56, 54, 48, 57, 55, 57, 67, 65, 51, 52, 66, 55, 70, 70, 56, 65, 65, 70, 50, 53, 53, 66, 56, 55, 65, 70, 57, 69, 56, 55, 57, 51, 55, 52, 52, 55, 48, 67, 69, 67, 48, 18, 9, 8, 7, 18, 5, 117, 111, 115, 109, 111, 26, 79, 10, 68, 105, 98, 99, 47, 52, 54, 66, 52, 52, 56, 57, 57, 51, 50, 50, 70, 51, 67, 68, 56, 53, 52, 68, 50, 68, 52, 54, 68, 69, 69, 70, 56, 56, 49, 57, 53, 56, 52, 54, 55, 67, 68, 68, 52, 66, 51, 66, 49, 48, 48, 56, 54, 68, 65, 52, 57, 50, 57, 54, 66, 66, 69, 68, 57, 52, 66, 69, 68, 18, 7, 49, 48, 48, 48, 48, 48, 48, 34, 7, 49, 53, 50, 53, 50, 54, 52]
993
- }],
994
- memo: '',
995
- source: null,
996
- fee: {
997
- gas: '900000',
998
- amount: [{
999
- denom: 'uosmo',
1000
- amount: '0'
1001
- }]
1002
- },
1003
- signType: 'AMINO',
1004
- rpcUrl: ''
1005
- },
1006
- rawTransfer: null
1007
- },
1008
- solanaTransaction: null,
1009
- evmTransaction: null,
1010
- evmApprovalTransaction: null,
1011
- transferTransaction: null,
1012
- diagnosisUrl: null,
1013
- internalSteps: null
1014
- }]
1015
- }, {
908
+ replace: true
909
+ });
910
+ }
911
+ }
912
+ firstRender.current = false;
913
+ }, [location.pathname, inputAmount]);
914
+ useEffect(() => {
915
+ if (loadingStatus === 'success') {
916
+ const fronChainString = searchParams.get(SearchParams.FROM_CHAIN);
917
+ const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
918
+ const toChainString = searchParams.get(SearchParams.TO_CHAIN);
919
+ const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
920
+ const fromAmount = searchParams.get(SearchParams.FROM_AMOUNT);
921
+ const fromChain = blockchains.find(blockchain => blockchain.name === fronChainString);
922
+ const fromToken = searchParamsToToken(tokens, fromTokenString);
923
+ const toChain = blockchains.find(blockchain => blockchain.name === toChainString);
924
+ const toToken = searchParamsToToken(tokens, toTokenString);
925
+ if (!!fromChain) {
926
+ setFromChain(fromChain);
927
+ if (!!fromToken) setFromToken(fromToken);
928
+ }
929
+ if (!!toChain) {
930
+ setToChain(toChain);
931
+ if (!!toToken) setToToken(toToken);
932
+ }
933
+ if (fromAmount) setInputAmount(fromAmount);
934
+ }
935
+ }, [loadingStatus]);
936
+ return null;
937
+ }
938
+
939
+ const ButtonsContainer = /*#__PURE__*/styled('div', {
940
+ display: 'flex'
941
+ });
942
+ function HeaderButtons(props) {
943
+ const {
944
+ onClickRefresh
945
+ } = props;
946
+ const navigate = useNavigate();
947
+ return React.createElement(ButtonsContainer, null, React.createElement(Tooltip, {
948
+ content: "Retry"
949
+ }, React.createElement(Button, {
950
+ variant: "ghost",
951
+ onClick: onClickRefresh.bind(null)
952
+ }, React.createElement(RetryIcon, {
953
+ size: 28
954
+ }))), React.createElement(Tooltip, {
955
+ content: "Transactions History"
956
+ }, React.createElement(Button, {
957
+ variant: "ghost",
958
+ onClick: () => navigate(navigationRoutes.history)
959
+ }, React.createElement(HistoryIcon, {
960
+ size: 24
961
+ }))), React.createElement(Tooltip, {
962
+ content: "Settings"
963
+ }, React.createElement(Button, {
964
+ variant: "ghost",
965
+ onClick: () => navigate(navigationRoutes.settings)
966
+ }, React.createElement(SettingsIcon, {
967
+ size: 24
968
+ }))));
969
+ }
970
+
971
+ const HeaderContainer = /*#__PURE__*/styled('div', {
972
+ display: 'flex',
973
+ justifyContent: 'space-between',
974
+ alignItems: 'center',
975
+ width: '100%',
976
+ padding: '$16 0'
977
+ });
978
+ function Header(props) {
979
+ const {
980
+ onClickRefresh
981
+ } = props;
982
+ return React.createElement(HeaderContainer, null, React.createElement(Typography, {
983
+ variant: "h4"
984
+ }, "SWAP"), React.createElement(HeaderButtons, {
985
+ onClickRefresh: onClickRefresh
986
+ }));
987
+ }
988
+
989
+ const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/subscribeWithSelector(set => ({
990
+ accounts: [],
991
+ balances: [],
992
+ selectedWallets: [],
993
+ connectWallet: accounts => {
994
+ const tokens = useMetaStore.getState().meta.tokens;
995
+ set(state => ({
996
+ accounts: state.accounts.concat(accounts),
997
+ balances: state.balances.concat(accounts.map(account => ({
998
+ balances: [],
999
+ address: account.address,
1000
+ chain: account.chain,
1001
+ loading: true,
1002
+ walletType: account.walletType,
1003
+ error: false,
1004
+ explorerUrl: null
1005
+ })))
1006
+ }));
1007
+ accounts.forEach(async account => {
1008
+ try {
1009
+ const response = await httpService.getWalletsDetails([{
1010
+ address: account.address,
1011
+ blockchain: account.chain
1012
+ }]);
1013
+ const retrivedBalance = response.wallets[0];
1014
+ if (retrivedBalance) {
1015
+ set(state => ({
1016
+ balances: state.balances.map(balance => {
1017
+ return isAccountAndBalanceMatched(account, balance) ? makeBalanceFor(account, retrivedBalance, tokens) : balance;
1018
+ })
1019
+ }));
1020
+ } else throw new Error('Wallet not found');
1021
+ } catch (error) {
1022
+ set(state => ({
1023
+ balances: state.balances.map(balance => {
1024
+ return isAccountAndBalanceMatched(account, balance) ? resetBalanceState(balance) : balance;
1025
+ })
1026
+ }));
1027
+ }
1028
+ });
1029
+ },
1030
+ disconnectWallet: walletType => {
1031
+ set(state => ({
1032
+ accounts: state.accounts.filter(account => account.walletType !== walletType),
1033
+ balances: state.balances.filter(balance => balance.walletType !== walletType),
1034
+ selectedWallets: state.selectedWallets.filter(wallet => wallet.walletType != walletType)
1035
+ }));
1036
+ },
1037
+ initSelectedWallets: () => set(state => {
1038
+ const requiredChains = getRequiredChains(useBestRouteStore.getState().bestRoute);
1039
+ const connectedWallets = state.accounts;
1040
+ const selectedWallets = [];
1041
+ requiredChains.forEach(chain => {
1042
+ const anyWalletSelected = !!state.selectedWallets.find(wallet => wallet.chain === chain);
1043
+ if (!anyWalletSelected) {
1044
+ const firstWalletWithMatchedChain = connectedWallets.find(wallet => wallet.chain === chain);
1045
+ if (!!firstWalletWithMatchedChain) selectedWallets.push({
1046
+ address: firstWalletWithMatchedChain.address,
1047
+ chain: firstWalletWithMatchedChain.chain,
1048
+ walletType: firstWalletWithMatchedChain.walletType
1049
+ });
1050
+ }
1051
+ });
1052
+ return {
1053
+ selectedWallets: state.selectedWallets.concat(selectedWallets)
1054
+ };
1055
+ }),
1056
+ setSelectedWallet: wallet => set(state => ({
1057
+ selectedWallets: state.selectedWallets.filter(selectedWallet => selectedWallet.chain !== wallet.chain).concat({
1058
+ chain: wallet.chain,
1059
+ address: wallet.address,
1060
+ walletType: wallet.walletType
1061
+ })
1062
+ }))
1063
+ }))));
1064
+
1065
+ const Box = /*#__PURE__*/styled('div', {
1066
+ display: 'flex',
1067
+ flexDirection: 'column',
1068
+ width: '100%'
1069
+ });
1070
+ const Container = /*#__PURE__*/styled('div', {
1071
+ boxSizing: 'border-box',
1072
+ backgroundColor: '$neutrals300',
1073
+ borderRadius: '$5',
1074
+ padding: '$8 0',
1075
+ '.form': {
1076
+ display: 'flex',
1077
+ width: '100%',
1078
+ padding: '$8 $16'
1079
+ }
1080
+ });
1081
+ const StyledImage = /*#__PURE__*/styled('img', {
1082
+ width: '$24',
1083
+ maxHeight: '$24'
1084
+ });
1085
+ const Options = /*#__PURE__*/styled('div', {
1086
+ display: 'flex',
1087
+ justifyContent: 'flex-end',
1088
+ padding: '0 $8'
1089
+ });
1090
+ const ImagePlaceholder = /*#__PURE__*/styled('span', {
1091
+ width: '24px',
1092
+ height: '24px',
1093
+ backgroundColor: '$neutrals300',
1094
+ borderRadius: '99999px'
1095
+ });
1096
+ const OutputContainer = /*#__PURE__*/styled('div', {
1097
+ height: '$48',
1098
+ borderRadius: '$5',
1099
+ flexGrow: 1,
1100
+ width: '70%',
1101
+ backgroundColor: '$background',
1102
+ border: '1px solid transparent',
1103
+ position: 'relative',
1104
+ display: 'flex',
1105
+ alignItems: 'center',
1106
+ paddingLeft: '$8',
1107
+ paddingRight: '$8'
1108
+ });
1109
+ function TokenInfo(props) {
1110
+ const {
1111
+ type,
1112
+ chain,
1113
+ token
1114
+ } = props;
1115
+ const loadingStatus = useMetaStore.use.loadingStatus();
1116
+ const fromChain = useBestRouteStore.use.fromChain();
1117
+ const toChain = useBestRouteStore.use.toChain();
1118
+ const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1119
+ const fromToken = useBestRouteStore.use.fromToken();
1120
+ const setInputAmount = useBestRouteStore.use.setInputAmount();
1121
+ const bestRoute = useBestRouteStore.use.bestRoute();
1122
+ const inputAmount = useBestRouteStore.use.inputAmount();
1123
+ const balances = useWalletsStore.use.balances();
1124
+ const navigate = useNavigate();
1125
+ const tokenBalance = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', 8) : '0';
1126
+ const tokenBalanceReal = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.decimal) : '0';
1127
+ const ItemSuffix = React.createElement("div", {
1128
+ style: {
1129
+ display: 'flex',
1130
+ justifyContent: 'center',
1131
+ alignItems: 'center'
1132
+ }
1133
+ }, loadingStatus === 'failed' && React.createElement(InfoCircleIcon, {
1134
+ color: "error",
1135
+ size: 24
1136
+ }), React.createElement(AngleDownIcon, null));
1137
+ return React.createElement(Box, null, React.createElement("div", null, React.createElement(Typography, {
1138
+ variant: "body2"
1139
+ }, type)), React.createElement(Container, null, props.type === 'From' && React.createElement(Options, null, React.createElement("div", {
1140
+ className: "balance",
1141
+ onClick: () => {
1142
+ if (tokenBalance !== '0') setInputAmount(tokenBalanceReal.split(',').join(''));
1143
+ }
1144
+ }, React.createElement(Button, {
1145
+ variant: "ghost",
1146
+ size: "small"
1147
+ }, React.createElement(Typography, {
1148
+ variant: "body2"
1149
+ }, `Max: ${tokenBalance} ${fromToken?.symbol || ''}`)))), React.createElement("div", {
1150
+ className: "form"
1151
+ }, React.createElement(Button, {
1152
+ onClick: () => {
1153
+ navigate(`/${props.type.toLowerCase()}-chain`);
1154
+ },
1155
+ variant: "outlined",
1156
+ disabled: loadingStatus === 'failed',
1157
+ loading: loadingStatus === 'loading',
1158
+ prefix: loadingStatus === 'success' && chain ? React.createElement(StyledImage, {
1159
+ src: chain.logo
1160
+ }) : React.createElement(ImagePlaceholder, null),
1161
+ suffix: ItemSuffix,
1162
+ align: "start",
1163
+ size: "large",
1164
+ style: {
1165
+ marginRight: '.5rem'
1166
+ }
1167
+ }, loadingStatus === 'success' && chain ? chain.displayName : 'Chain'), React.createElement(Button, {
1168
+ onClick: () => {
1169
+ navigate(`/${props.type.toLowerCase()}-token`);
1170
+ },
1171
+ variant: "outlined",
1172
+ disabled: loadingStatus === 'failed' || type === 'From' && !fromChain || type === 'To' && !toChain,
1173
+ loading: loadingStatus === 'loading',
1174
+ prefix: loadingStatus === 'success' && token ? React.createElement(StyledImage, {
1175
+ src: token.image
1176
+ }) : React.createElement(ImagePlaceholder, null),
1177
+ suffix: ItemSuffix,
1178
+ size: "large",
1179
+ align: "start",
1180
+ style: {
1181
+ marginRight: '.5rem'
1182
+ }
1183
+ }, loadingStatus === 'success' && token ? token.symbol : 'Token'), props.type === 'From' ? React.createElement(TextField, {
1184
+ type: "number",
1185
+ size: "large",
1186
+ autoFocus: true,
1187
+ placeholder: "0",
1188
+ style: {
1189
+ width: '70%',
1190
+ position: 'relative',
1191
+ backgroundColor: '$background !important'
1192
+ },
1193
+ suffix: React.createElement("span", {
1194
+ style: {
1195
+ position: 'absolute',
1196
+ right: '4px',
1197
+ bottom: '2px'
1198
+ }
1199
+ }, React.createElement(Typography, {
1200
+ variant: "caption"
1201
+ }, `$${numberToString(inputUsdValue)}`)),
1202
+ value: props.inputAmount || '',
1203
+ onChange: props.type === 'From' ? event => {
1204
+ props.onAmountChange(event.target.value);
1205
+ } : undefined
1206
+ }) : React.createElement(OutputContainer, null, React.createElement(Typography, {
1207
+ variant: "body1"
1208
+ }, bestRoute ? `≈ ${numberToString(props.outputAmount)}` : inputAmount ? '?' : '0'), React.createElement("span", {
1209
+ style: {
1210
+ position: 'absolute',
1211
+ right: '4px',
1212
+ bottom: '2px'
1213
+ }
1214
+ }, React.createElement(Typography, {
1215
+ variant: "caption"
1216
+ }, `$${numberToString(props.outputUsdValue)}`))))));
1217
+ }
1218
+
1219
+ const Container$1 = /*#__PURE__*/styled$1('div', {
1220
+ display: 'flex',
1221
+ width: '100%',
1222
+ justifyContent: 'end',
1223
+ alignItems: 'center',
1224
+ paddingTop: '$16'
1225
+ });
1226
+ const Logo = /*#__PURE__*/styled$1('svg', {
1227
+ fill: '$foreground',
1228
+ width: '$24',
1229
+ margin: '0 $8 0 $16'
1230
+ });
1231
+ const StyledAnchor = /*#__PURE__*/styled$1('a', {
1232
+ display: 'flex',
1233
+ justifyContent: 'center',
1234
+ alignItems: 'center',
1235
+ textDecoration: 'none'
1236
+ });
1237
+ function BottomLogo() {
1238
+ return React.createElement(Container$1, null, React.createElement(Typography, {
1239
+ variant: "caption"
1240
+ }, "Powered By"), React.createElement(StyledAnchor, {
1241
+ href: "https://rango.exchange",
1242
+ target: "_blank"
1243
+ }, React.createElement(Logo, {
1244
+ xmlns: "http://www.w3.org/2000/svg",
1245
+ viewBox: "0 0 33.68 29"
1246
+ }, React.createElement("defs", null), React.createElement("g", {
1247
+ id: "Layer_2",
1248
+ "data-name": "Layer 2"
1249
+ }, React.createElement("g", {
1250
+ id: "Layer_1-2",
1251
+ "data-name": "Layer 1"
1252
+ }, React.createElement("path", {
1253
+ d: "M33.68,18.05A17.93,17.93,0,0,0,28.34,5.29,18.31,18.31,0,0,0,15.45,0H13.54V7.41L6.07,0H.69L9.83,9.07H0V11A17.93,17.93,0,0,0,5.34,23.71,18.32,18.32,0,0,0,18.24,29h1.9V21.59l7.38,7.31h5.39l-9-9h9.82ZM17.37,16.16H12.49a1.93,1.93,0,0,0-1.35.55,1.89,1.89,0,0,0-.56,1.34,1.85,1.85,0,0,0,.56,1.33,1.93,1.93,0,0,0,1.35.55h3.84V25.1A14.43,14.43,0,0,1,8,21a14.21,14.21,0,0,1-4.1-8.2H21.2a1.86,1.86,0,0,0,.74-.13,1.92,1.92,0,0,0,.64-.4,2,2,0,0,0,.43-.62,1.88,1.88,0,0,0,0-1.47,2,2,0,0,0-.43-.62,1.92,1.92,0,0,0-.64-.4,1.86,1.86,0,0,0-.74-.13H17.35V3.9A14.43,14.43,0,0,1,25.64,8a14.19,14.19,0,0,1,4.11,8.2Zm2.12-5.27a1.43,1.43,0,0,1,.26-.83,1.52,1.52,0,0,1,.67-.56,1.55,1.55,0,0,1,.88-.08,1.51,1.51,0,0,1,.77.4,1.54,1.54,0,0,1,.42.77,1.41,1.41,0,0,1-.09.86,1.47,1.47,0,0,1-.55.68,1.56,1.56,0,0,1-.84.25,1.52,1.52,0,0,1-1.52-1.49Z"
1254
+ }), React.createElement("path", {
1255
+ d: "M21.7,11.57a.68.68,0,0,0-.12-.38.64.64,0,0,0-.31-.25.68.68,0,0,0-.75.15.61.61,0,0,0-.19.35.62.62,0,0,0,0,.4.67.67,0,0,0,.25.3.69.69,0,0,0,.39.12.7.7,0,0,0,.49-.2A.68.68,0,0,0,21.7,11.57Z"
1256
+ })))), React.createElement(Typography, {
1257
+ variant: "body2"
1258
+ }, "RANGO")));
1259
+ }
1260
+
1261
+ function SwithFromAndTo(_ref) {
1262
+ let {
1263
+ count
1264
+ } = _ref;
1265
+ const firstRender = useRef(true);
1266
+ const [searchParams, setSearchParams] = useSearchParams();
1267
+ const outputAmount = useBestRouteStore.use.outputAmount();
1268
+ useEffect(() => {
1269
+ if (!firstRender.current) {
1270
+ const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
1271
+ const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
1272
+ const toChainString = searchParams.get(SearchParams.TO_CHAIN);
1273
+ const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
1274
+ setSearchParams({
1275
+ ...(toChainString && {
1276
+ [SearchParams.FROM_CHAIN]: toChainString
1277
+ }),
1278
+ ...(toTokenString && {
1279
+ [SearchParams.FROM_TOKEN]: toTokenString
1280
+ }),
1281
+ ...(fromChainString && {
1282
+ [SearchParams.TO_CHAIN]: fromChainString
1283
+ }),
1284
+ ...(fromTokenString && {
1285
+ [SearchParams.TO_TOKEN]: fromTokenString
1286
+ }),
1287
+ ...(outputAmount && {
1288
+ [SearchParams.FROM_AMOUNT]: outputAmount.toString()
1289
+ })
1290
+ });
1291
+ } else {
1292
+ firstRender.current = false;
1293
+ }
1294
+ }, [count]);
1295
+ return null;
1296
+ }
1297
+
1298
+ const Footer = /*#__PURE__*/styled('div', {
1299
+ display: 'flex',
1300
+ flexDirection: 'column',
1301
+ width: '100%',
1302
+ paddingTop: '$16'
1303
+ });
1304
+
1305
+ const errorMessages = {
1306
+ genericServerError: 'Error connecting server, please reload the app and try again'
1307
+ };
1308
+
1309
+ const Container$2 = /*#__PURE__*/styled('div', {
1310
+ display: 'flex',
1311
+ flexDirection: 'column',
1312
+ justifyContent: 'center',
1313
+ alignItems: 'center'
1314
+ });
1315
+ const SwitchButtonContainer = /*#__PURE__*/styled('div', {
1316
+ display: 'flex',
1317
+ justifyContent: 'center',
1318
+ alignItems: 'center',
1319
+ position: 'relative',
1320
+ top: '11px'
1321
+ });
1322
+ const BestRouteContainer = /*#__PURE__*/styled('div', {
1323
+ width: '100%',
1324
+ paddingTop: '$16'
1325
+ });
1326
+ const Alerts = /*#__PURE__*/styled('div', {
1327
+ width: '100%',
1328
+ paddingTop: '$16'
1329
+ });
1330
+ function Home() {
1331
+ const waningMessage = '';
1332
+ const isRouterInContext = useInRouterContext();
1333
+ const navigate = useNavigate();
1334
+ const [count, setCount] = useState(0);
1335
+ const fromChain = useBestRouteStore.use.fromChain();
1336
+ const fromToken = useBestRouteStore.use.fromToken();
1337
+ const toChain = useBestRouteStore.use.toChain();
1338
+ const toToken = useBestRouteStore.use.toToken();
1339
+ const setFromChain = useBestRouteStore.use.setFromChain();
1340
+ const setFromToken = useBestRouteStore.use.setFromToken();
1341
+ const setToChain = useBestRouteStore.use.setToChain();
1342
+ const setToToken = useBestRouteStore.use.setToToken();
1343
+ const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1344
+ const inputAmount = useBestRouteStore.use.inputAmount();
1345
+ const setInputAmount = useBestRouteStore.use.setInputAmount();
1346
+ const outputAmount = useBestRouteStore.use.outputAmount();
1347
+ const outputUsdValue = useBestRouteStore.use.outputUsdValue();
1348
+ const bestRoute = useBestRouteStore.use.bestRoute();
1349
+ const tokens = useMetaStore.use.meta().tokens;
1350
+ const fetchingBestRoute = useBestRouteStore.use.loading();
1351
+ const bestRouteError = useBestRouteStore.use.error();
1352
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
1353
+ const accounts = useWalletsStore.use.accounts();
1354
+ const swithFromAndTo = () => {
1355
+ setFromChain(toChain);
1356
+ setFromToken(toToken);
1357
+ setToChain(fromChain);
1358
+ setToToken(fromToken);
1359
+ setInputAmount(outputAmount?.toString() || '');
1360
+ setCount(prev => prev + 1);
1361
+ };
1362
+ const errorMessage = loadingMetaStatus === 'failed' ? errorMessages.genericServerError : bestRouteError;
1363
+ const needsToWarnEthOnPath = false;
1364
+ const showBestRoute = inputAmount && (!!bestRoute || fetchingBestRoute || bestRouteError);
1365
+ const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);
1366
+ const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);
1367
+ const {
1368
+ fromAmountRangeError,
1369
+ recommendation,
1370
+ swap
1371
+ } = LimitErrorMessage(bestRoute);
1372
+ const priceImpactCanNotBeComputed = !canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue);
1373
+ const swapButtonState = getSwapButtonState(loadingMetaStatus, accounts, fetchingBestRoute, bestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath);
1374
+ const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
1375
+ const highFee = hasHighFee(totalFeeInUsd);
1376
+ return React.createElement(Container$2, null, React.createElement(Header, {
1377
+ onClickRefresh: fetchBestRoute
1378
+ }), React.createElement(TokenInfo, {
1379
+ type: "From",
1380
+ chain: fromChain,
1381
+ token: fromToken,
1382
+ onAmountChange: setInputAmount,
1383
+ inputAmount: inputAmount
1384
+ }), React.createElement(SwitchButtonContainer, null, React.createElement(Button, {
1385
+ variant: "ghost",
1386
+ onClick: swithFromAndTo
1387
+ }, React.createElement(VerticalSwapIcon, {
1388
+ size: 36
1389
+ }), isRouterInContext && React.createElement(SwithFromAndTo, {
1390
+ count: count
1391
+ }))), React.createElement(TokenInfo, {
1392
+ type: "To",
1393
+ chain: toChain,
1394
+ token: toToken,
1395
+ outputAmount: outputAmount,
1396
+ outputUsdValue: outputUsdValue
1397
+ }), showBestRoute && React.createElement(BestRouteContainer, null, React.createElement(BestRoute, {
1398
+ error: bestRouteError,
1399
+ loading: fetchingBestRoute,
1400
+ data: bestRoute,
1401
+ totalFee: numberToString(totalFeeInUsd, 0, 2),
1402
+ feeWarning: highFee,
1403
+ totalTime: secondsToString(totalArrivalTime(bestRoute))
1404
+ })), (errorMessage || waningMessage || hasLimitError(bestRoute)) && React.createElement(Alerts, null, errorMessage && React.createElement(Alert, {
1405
+ type: "error"
1406
+ }, React.createElement(Typography, {
1407
+ variant: "body2"
1408
+ }, errorMessage)), hasLimitError(bestRoute) && React.createElement(Alert, {
1409
+ type: "error",
1410
+ title: `${swap?.swapperId} Limit`
1411
+ }, React.createElement(React.Fragment, null, React.createElement(Typography, {
1412
+ variant: "body2"
1413
+ }, fromAmountRangeError), React.createElement("br", null), React.createElement(Typography, {
1414
+ variant: "body2"
1415
+ }, "Yours: ", numberToString(swap?.fromAmount || null), swap?.from.symbol), React.createElement("br", null), React.createElement(Typography, {
1416
+ variant: "body2"
1417
+ }, recommendation))), waningMessage ), React.createElement(Footer, null, React.createElement(Button, {
1418
+ type: "primary",
1419
+ align: "grow",
1420
+ size: "large",
1421
+ disabled: swapButtonState.disabled,
1422
+ onClick: () => {
1423
+ if (swapButtonState.title === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
1424
+ navigate(navigationRoutes.confirmWallets);
1425
+ }
1426
+ }
1427
+ }, swapButtonState.title), React.createElement(BottomLogo, null)));
1428
+ }
1429
+
1430
+ const Route = props => {
1431
+ const location = useLocation$1();
1432
+ const navigate = useNavigate$1();
1433
+ const ref = useRef(true);
1434
+ useEffect(() => {
1435
+ if ([navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname) && ref.current) navigate(navigationRoutes.home + location.search, {
1436
+ state: 'redirect'
1437
+ });
1438
+ ref.current = false;
1439
+ }, []);
1440
+ if ([navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname) && ref.current) return React.createElement(Home, null);
1441
+ return React.createElement(React.Fragment, null, " ", props.children);
1442
+ };
1443
+ function AppRouter(_ref) {
1444
+ let {
1445
+ children
1446
+ } = _ref;
1447
+ const isRouterInContext = useInRouterContext$1();
1448
+ const Router = isRouterInContext ? Route : MemoryRouter;
1449
+ return React.createElement(React.Fragment, null, React.createElement(Router, null, children), isRouterInContext && React.createElement(UpdateUrl, null));
1450
+ }
1451
+
1452
+ const useUiStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()(set => ({
1453
+ connectWalletsButtonDisabled: false,
1454
+ toggleConnectWalletsButton: () => set(state => ({
1455
+ connectWalletsButtonDisabled: !state.connectWalletsButtonDisabled
1456
+ }))
1457
+ })));
1458
+
1459
+ const StyledButton = /*#__PURE__*/styled(Button, {
1460
+ marginTop: '$8'
1461
+ });
1462
+ function ChangeSlippageButton() {
1463
+ const navigate = useNavigate();
1464
+ return React.createElement(StyledButton, {
1465
+ type: "primary",
1466
+ variant: "contained",
1467
+ size: "small",
1468
+ onClick: navigate.bind(null, navigationRoutes.settings)
1469
+ }, "Change Slippage");
1470
+ }
1471
+
1472
+ function HighSlippageWarning(props) {
1473
+ const {
1474
+ selectedSlippage
1475
+ } = props;
1476
+ return React.createElement(Alert, {
1477
+ type: "warning"
1478
+ }, React.createElement(Typography, {
1479
+ variant: "body2"
1480
+ }, "slippage is high=> Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.", React.createElement(ChangeSlippageButton, null)));
1481
+ }
1482
+
1483
+ function ConfirmSwapExtraMessages(props) {
1484
+ const {
1485
+ selectedSlippage
1486
+ } = props;
1487
+ const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
1488
+ return React.createElement(React.Fragment, null, highSlippage && React.createElement(HighSlippageWarning, {
1489
+ selectedSlippage: selectedSlippage
1490
+ }));
1491
+ }
1492
+
1493
+ function useNavigateBack() {
1494
+ const isRouterInContext = useInRouterContext();
1495
+ const navigate = useNavigate();
1496
+ const navigateBackFrom = currentRoute => {
1497
+ if (!isRouterInContext || window.history.state && window.history.state.idx > 0) navigate(-1);else {
1498
+ if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.history].includes(currentRoute)) navigate(navigationRoutes.home, {
1499
+ replace: true
1500
+ });else if (currentRoute === navigationRoutes.liquiditySources) {
1501
+ navigate(navigationRoutes.settings, {
1502
+ replace: true
1503
+ });
1504
+ } else if (currentRoute === navigationRoutes.swapDetails) navigate(navigationRoutes.history, {
1505
+ replace: true
1506
+ });
1507
+ }
1508
+ };
1509
+ return {
1510
+ navigateBackFrom
1511
+ };
1512
+ }
1513
+
1514
+ const useConfirmSwapStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/subscribeWithSelector(() => ({
1515
+ loading: false,
1516
+ errors: [],
1517
+ warnings: [],
1518
+ proceedAnyway: false
1519
+ }))));
1520
+ var ConfirmSwapErrorTypes;
1521
+ (function (ConfirmSwapErrorTypes) {
1522
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
1523
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
1524
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
1525
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
1526
+ })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
1527
+ var ConfirmSwapWarningTypes;
1528
+ (function (ConfirmSwapWarningTypes) {
1529
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
1530
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
1531
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
1532
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
1533
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
1534
+ })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
1535
+ const confirmSwap = () => {
1536
+ const {
1537
+ fromToken,
1538
+ toToken,
1539
+ inputAmount,
1540
+ bestRoute: initialRoute,
1541
+ inputUsdValue,
1542
+ setBestRoute
1543
+ } = useBestRouteStore.getState();
1544
+ const {
1545
+ accounts,
1546
+ selectedWallets
1547
+ } = useWalletsStore.getState();
1548
+ const {
1549
+ proceedAnyway
1550
+ } = useConfirmSwapStore.getState();
1551
+ const {
1552
+ disabledLiquiditySources,
1553
+ slippage,
1554
+ customSlippage
1555
+ } = useSettingsStore.getState();
1556
+ const {
1557
+ meta
1558
+ } = useMetaStore.getState();
1559
+ const userSlippage = customSlippage || slippage;
1560
+ if (!fromToken || !toToken || !inputAmount || !initialRoute) return;
1561
+ if (proceedAnyway) {
1562
+ const swapSettings = {
1563
+ slippage: userSlippage.toString(),
1564
+ disabledSwappersGroups: disabledLiquiditySources
1565
+ };
1566
+ const newSwap = calculatePendingSwap(inputAmount.toString(), initialRoute, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
1567
+ console.log('new swap:', newSwap);
1568
+ return useConfirmSwapStore.setState({
1569
+ errors: [],
1570
+ warnings: [],
1571
+ proceedAnyway: false
1572
+ });
1573
+ }
1574
+ let abortController = new AbortController();
1575
+ useConfirmSwapStore.setState({
1576
+ loading: true
1577
+ });
1578
+ const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, accounts, selectedWallets, disabledLiquiditySources, userSlippage, true);
1579
+ const unsubscribeFromBestRouteStore = useBestRouteStore.subscribe(state => state.bestRoute, () => {
1580
+ abortController.abort();
1581
+ }, {
1582
+ equalityFn: shallow
1583
+ });
1584
+ const unsubscribeFromWalletsStore = useWalletsStore.subscribe(state => state.selectedWallets, () => {
1585
+ abortController?.abort();
1586
+ }, {
1587
+ equalityFn: (prevState, state) => {
1588
+ const selectedWalletsChanged = !state.every(wallet => !!prevState.find(prevWallet => wallet.address === prevWallet.address && wallet.chain === prevWallet.chain));
1589
+ if (selectedWalletsChanged) return false;else return true;
1590
+ }
1591
+ });
1592
+ httpService.getBestRoute(requestBody, {
1593
+ signal: abortController.signal
1594
+ }).then(confiremedRoute => {
1595
+ useConfirmSwapStore.setState({
1596
+ loading: false
1597
+ });
1598
+ if (!confiremedRoute.result || !new BigNumber(confiremedRoute.requestAmount).isEqualTo(new BigNumber(inputAmount || '-1'))) return useConfirmSwapStore.setState(prevState => ({
1599
+ errors: prevState.errors.concat({
1600
+ type: ConfirmSwapErrorTypes.NO_ROUTE
1601
+ })
1602
+ }));
1603
+ const confirmSwap = {
1604
+ loading: false,
1605
+ errors: [],
1606
+ warnings: [],
1607
+ proceedAnyway
1608
+ };
1609
+ const routeChanged = isRouteChanged(initialRoute, confiremedRoute);
1610
+ if (routeChanged) {
1611
+ setBestRoute(confiremedRoute);
1612
+ const newRouteOutputUsdValue = new BigNumber(confiremedRoute.result?.outputAmount || '0').multipliedBy(toToken.usdPrice || 0);
1613
+ const outputRatio = getOutputRatio(inputUsdValue, newRouteOutputUsdValue);
1614
+ const highValueLoss = outputRatioHasWarning(inputUsdValue, outputRatio);
1615
+ if (isNumberOfSwapsChanged(initialRoute, confiremedRoute)) confirmSwap.warnings.push({
1616
+ type: ConfirmSwapWarningTypes.ROUTE_UPDATED
1617
+ });else if (isRouteSwappersUpdated(initialRoute, confiremedRoute)) confirmSwap.warnings.push({
1618
+ type: ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED
1619
+ });else isRouteInternalCoinsUpdated(initialRoute, confiremedRoute);
1620
+ confirmSwap.warnings.push({
1621
+ type: ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED
1622
+ });
1623
+ if (highValueLoss) confirmSwap.errors.push({
1624
+ type: ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS
1625
+ });else if (isOutputAmountChangedALot(initialRoute, confiremedRoute)) confirmSwap.warnings.push({
1626
+ type: ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED,
1627
+ newOutputAmount: numberToString(getRouteOutputAmount(confiremedRoute)),
1628
+ percentageChange: numberToString(getPercentageChange(getRouteOutputAmount(initialRoute), getRouteOutputAmount(confiremedRoute)), null, 2)
1629
+ });
1630
+ }
1631
+ const balanceWarnings = getBalanceWarnings(confiremedRoute, selectedWallets);
1632
+ const enoughBalance = balanceWarnings.length === 0;
1633
+ if (!enoughBalance) confirmSwap.warnings.push({
1634
+ type: ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE,
1635
+ messages: balanceWarnings
1636
+ });
1637
+ const minRequiredSlippage = getMinRequiredSlippage(initialRoute);
1638
+ if (!hasProperSlippage(userSlippage.toString(), minRequiredSlippage)) confirmSwap.errors.push({
1639
+ type: ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE,
1640
+ minRequiredSlippage
1641
+ });
1642
+ const noErrors = confirmSwap.errors.length === 0;
1643
+ const noWarnings = confirmSwap.warnings.length === 0;
1644
+ if ((noErrors || !noErrors && proceedAnyway) && (noWarnings || !noWarnings && proceedAnyway)) {
1645
+ const swapSettings = {
1646
+ slippage: userSlippage.toString(),
1647
+ disabledSwappersGroups: disabledLiquiditySources
1648
+ };
1649
+ const newSwap = calculatePendingSwap(inputAmount.toString(), initialRoute, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
1650
+ console.log('new swap:', newSwap);
1651
+ } else if (!proceedAnyway) confirmSwap.proceedAnyway = true;
1652
+ abortController = null;
1653
+ useConfirmSwapStore.setState(confirmSwap);
1654
+ unsubscribeFromBestRouteStore();
1655
+ unsubscribeFromWalletsStore();
1656
+ }).catch(error => {
1657
+ abortController = null;
1658
+ if (error.code === 'ERR_CANCELED') {
1659
+ useConfirmSwapStore.setState({
1660
+ errors: [],
1661
+ warnings: [],
1662
+ loading: false,
1663
+ proceedAnyway: false
1664
+ });
1665
+ unsubscribeFromBestRouteStore();
1666
+ unsubscribeFromWalletsStore();
1667
+ }
1668
+ const status = error.response?.status;
1669
+ useConfirmSwapStore.setState(prevState => ({
1670
+ loading: false,
1671
+ errors: prevState.errors.concat({
1672
+ type: ConfirmSwapErrorTypes.REQUEST_FAILED,
1673
+ status
1674
+ })
1675
+ }));
1676
+ });
1677
+ };
1678
+
1679
+ function MinRequiredSlippage(_ref) {
1680
+ let {
1681
+ minRequiredSlippage
1682
+ } = _ref;
1683
+ return React.createElement(Typography, {
1684
+ variant: "body2"
1685
+ }, "slippage is low => We recommend you to increase slippage to at least", minRequiredSlippage, "for this route.", React.createElement(ChangeSlippageButton, null));
1686
+ }
1687
+
1688
+ function ConfirmSwapErrors(errors) {
1689
+ return errors.flatMap(error => {
1690
+ switch (error.type) {
1691
+ case ConfirmSwapErrorTypes.NO_ROUTE:
1692
+ return React.createElement(Typography, {
1693
+ variant: "body2"
1694
+ }, "No routes found. Please try again later.");
1695
+ case ConfirmSwapErrorTypes.REQUEST_FAILED:
1696
+ return React.createElement(Typography, {
1697
+ variant: "body2"
1698
+ }, `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`);
1699
+ case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
1700
+ return React.createElement(Typography, {
1701
+ variant: "body2"
1702
+ }, "Route updated and price impact is too high, try again later!");
1703
+ case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
1704
+ return React.createElement(MinRequiredSlippage, {
1705
+ minRequiredSlippage: error.minRequiredSlippage
1706
+ });
1707
+ default:
1708
+ return [];
1709
+ }
1710
+ });
1711
+ }
1712
+
1713
+ function BalanceWarnings(_ref) {
1714
+ let {
1715
+ messages
1716
+ } = _ref;
1717
+ return React.createElement("div", null, messages.map(warning => React.createElement(Typography, {
1718
+ variant: "body2"
1719
+ }, warning)));
1720
+ }
1721
+
1722
+ function ConfirmSwapWarnings(warnings) {
1723
+ return warnings.flatMap(warning => {
1724
+ switch (warning.type) {
1725
+ case ConfirmSwapWarningTypes.ROUTE_UPDATED:
1726
+ return React.createElement(Typography, {
1727
+ variant: "body2"
1728
+ }, "Route has been updated.");
1729
+ case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
1730
+ return React.createElement(Typography, {
1731
+ variant: "body2"
1732
+ }, `Output amount changed to ${warning.newOutputAmount}
1733
+ (${warning.percentageChange}% change).`);
1734
+ case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
1735
+ return React.createElement(Typography, {
1736
+ variant: "body2"
1737
+ }, "Route swappers has been updated.");
1738
+ case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
1739
+ return React.createElement(Typography, {
1740
+ variant: "body2"
1741
+ }, "Route internal coins has been updated.");
1742
+ case ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE:
1743
+ return React.createElement(BalanceWarnings, {
1744
+ messages: warning.messages
1745
+ });
1746
+ default:
1747
+ return [];
1748
+ }
1749
+ });
1750
+ }
1751
+
1752
+ function ConfirmSwapPage() {
1753
+ const {
1754
+ navigateBackFrom
1755
+ } = useNavigateBack();
1756
+ const bestRoute = useBestRouteStore.use.bestRoute();
1757
+ const loading = useConfirmSwapStore.use.loading();
1758
+ const warnings = useConfirmSwapStore.use.warnings();
1759
+ const errors = useConfirmSwapStore.use.errors();
1760
+ console.log('loading:', loading, 'warnings:', warnings, 'errors:', errors);
1761
+ const slippage = useSettingsStore.use.slippage();
1762
+ const customSlippage = useSettingsStore.use.customSlippage();
1763
+ const selectedSlippage = customSlippage || slippage;
1764
+ return React.createElement(ConfirmSwap, {
1765
+ onConfirm: confirmSwap.bind(null),
1766
+ onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
1767
+ bestRoute: bestRoute,
1768
+ loading: loading,
1769
+ errors: ConfirmSwapErrors(errors),
1770
+ warnings: ConfirmSwapWarnings(warnings),
1771
+ extraMessages: React.createElement(ConfirmSwapExtraMessages, {
1772
+ selectedSlippage: selectedSlippage
1773
+ }),
1774
+ confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!',
1775
+ confirmButtonDisabled: errors.length > 0
1776
+ });
1777
+ }
1778
+
1779
+ const pendingSwap = [{
1016
1780
  creationTime: '1673164511955',
1017
1781
  finishTime: '1673164550137',
1018
1782
  requestId: '51e211d9-d61c-45d2-a4d4-1f9f7f90ee85',
@@ -1023,7 +1787,7 @@ const pendingSwap = [{
1023
1787
  address: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl'
1024
1788
  }
1025
1789
  },
1026
- status: 'failed',
1790
+ status: 'running',
1027
1791
  isPaused: false,
1028
1792
  extraMessage: null,
1029
1793
  extraMessageSeverity: 'info',
@@ -1041,10 +1805,10 @@ const pendingSwap = [{
1041
1805
  outputAmount: '1.540670',
1042
1806
  swaps: [{
1043
1807
  swapperId: 'Osmosis',
1808
+ swapperType: 'DEX',
1044
1809
  swapperLogo: '',
1045
1810
  // @ts-ignore
1046
1811
  result: null,
1047
- swapperType: 'DEX',
1048
1812
  from: {
1049
1813
  symbol: 'JUNO',
1050
1814
  logo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
@@ -1143,12 +1907,12 @@ const pendingSwap = [{
1143
1907
  fromDecimals: 6,
1144
1908
  fromAmountPrecision: null,
1145
1909
  fromAmountMinValue: null,
1910
+ swapperLogo: '',
1911
+ swapperType: '',
1146
1912
  fromAmountMaxValue: null,
1147
1913
  toBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1148
1914
  fromBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1149
1915
  toBlockchain: 'OSMOSIS',
1150
- swapperLogo: '',
1151
- swapperType: '',
1152
1916
  fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
1153
1917
  toSymbol: 'OSMO',
1154
1918
  toSymbolAddress: null,
@@ -1158,7 +1922,7 @@ const pendingSwap = [{
1158
1922
  swapperId: 'Osmosis',
1159
1923
  expectedOutputAmountHumanReadable: '1.540670',
1160
1924
  outputAmount: '1.540658',
1161
- status: 'failed',
1925
+ status: 'running',
1162
1926
  networkStatus: null,
1163
1927
  executedTransactionId: '0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
1164
1928
  explorerUrl: [{
@@ -1231,7 +1995,7 @@ const pendingSwap = [{
1231
1995
  address: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl'
1232
1996
  }
1233
1997
  },
1234
- status: 'success',
1998
+ status: 'failed',
1235
1999
  isPaused: false,
1236
2000
  extraMessage: null,
1237
2001
  extraMessageSeverity: 'info',
@@ -1248,11 +2012,11 @@ const pendingSwap = [{
1248
2012
  simulationResult: {
1249
2013
  outputAmount: '1.540670',
1250
2014
  swaps: [{
1251
- // @ts-ignore
1252
- result: [],
1253
2015
  swapperId: 'Osmosis',
1254
- swapperType: 'DEX',
1255
2016
  swapperLogo: '',
2017
+ // @ts-ignore
2018
+ result: null,
2019
+ swapperType: 'DEX',
1256
2020
  from: {
1257
2021
  symbol: 'JUNO',
1258
2022
  logo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
@@ -1351,12 +2115,12 @@ const pendingSwap = [{
1351
2115
  fromDecimals: 6,
1352
2116
  fromAmountPrecision: null,
1353
2117
  fromAmountMinValue: null,
1354
- swapperLogo: '',
1355
- swapperType: '',
1356
2118
  fromAmountMaxValue: null,
1357
2119
  toBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1358
2120
  fromBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1359
2121
  toBlockchain: 'OSMOSIS',
2122
+ swapperLogo: '',
2123
+ swapperType: '',
1360
2124
  fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
1361
2125
  toSymbol: 'OSMO',
1362
2126
  toSymbolAddress: null,
@@ -1366,7 +2130,7 @@ const pendingSwap = [{
1366
2130
  swapperId: 'Osmosis',
1367
2131
  expectedOutputAmountHumanReadable: '1.540670',
1368
2132
  outputAmount: '1.540658',
1369
- status: 'success',
2133
+ status: 'failed',
1370
2134
  networkStatus: null,
1371
2135
  executedTransactionId: '0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
1372
2136
  explorerUrl: [{
@@ -1407,541 +2171,246 @@ const pendingSwap = [{
1407
2171
  type_url: '/osmosis.gamm.v1beta1.MsgSwapExactAmountIn',
1408
2172
  value: [10, 43, 111, 115, 109, 111, 49, 117, 110, 102, 50, 114, 99, 121, 116, 106, 120, 102, 112, 122, 56, 120, 56, 97, 114, 54, 51, 104, 52, 113, 101, 102, 116, 97, 100, 112, 116, 103, 53, 116, 48, 110, 113, 99, 108, 18, 73, 8, -14, 3, 18, 68, 105, 98, 99, 47, 50, 55, 51, 57, 52, 70, 66, 48, 57, 50, 68, 50, 69, 67, 67, 68, 53, 54, 49, 50, 51, 67, 55, 52, 70, 51, 54, 69, 52, 67, 49, 70, 57, 50, 54, 48, 48, 49, 67, 69, 65, 68, 65, 57, 67, 65, 57, 55, 69, 65, 54, 50, 50, 66, 50, 53, 70, 52, 49, 69, 53, 69, 66, 50, 18, 72, 8, 8, 18, 68, 105, 98, 99, 47, 55, 67, 52, 68, 54, 48, 65, 65, 57, 53, 69, 53, 65, 55, 53, 53, 56, 66, 48, 65, 51, 54, 52, 56, 54, 48, 57, 55, 57, 67, 65, 51, 52, 66, 55, 70, 70, 56, 65, 65, 70, 50, 53, 53, 66, 56, 55, 65, 70, 57, 69, 56, 55, 57, 51, 55, 52, 52, 55, 48, 67, 69, 67, 48, 18, 9, 8, 7, 18, 5, 117, 111, 115, 109, 111, 26, 79, 10, 68, 105, 98, 99, 47, 52, 54, 66, 52, 52, 56, 57, 57, 51, 50, 50, 70, 51, 67, 68, 56, 53, 52, 68, 50, 68, 52, 54, 68, 69, 69, 70, 56, 56, 49, 57, 53, 56, 52, 54, 55, 67, 68, 68, 52, 66, 51, 66, 49, 48, 48, 56, 54, 68, 65, 52, 57, 50, 57, 54, 66, 66, 69, 68, 57, 52, 66, 69, 68, 18, 7, 49, 48, 48, 48, 48, 48, 48, 34, 7, 49, 53, 50, 53, 50, 54, 52]
1409
2173
  }],
1410
- memo: '',
1411
- source: null,
1412
- fee: {
1413
- gas: '900000',
1414
- amount: [{
1415
- denom: 'uosmo',
1416
- amount: '0'
1417
- }]
1418
- },
1419
- signType: 'AMINO',
1420
- rpcUrl: ''
1421
- },
1422
- rawTransfer: null
1423
- },
1424
- solanaTransaction: null,
1425
- evmTransaction: null,
1426
- evmApprovalTransaction: null,
1427
- transferTransaction: null,
1428
- diagnosisUrl: null,
1429
- internalSteps: null
1430
- }]
1431
- }];
1432
- function HistoryPage() {
1433
- const navigate = useNavigate();
1434
- return React.createElement(History, {
1435
- list: pendingSwap,
1436
- onSwapClick: () => navigate(navigationRoutes.swapDetails),
1437
- onBack: () => {
1438
- navigate(-1);
1439
- }
1440
- });
1441
- }
1442
-
1443
- const ButtonsContainer = /*#__PURE__*/styled('div', {
1444
- display: 'flex'
1445
- });
1446
- function HeaderButtons(props) {
1447
- const {
1448
- onClickRefresh
1449
- } = props;
1450
- const navigate = useNavigate();
1451
- return React.createElement(ButtonsContainer, null, React.createElement(Tooltip, {
1452
- content: "Retry"
1453
- }, React.createElement(Button, {
1454
- variant: "ghost",
1455
- onClick: onClickRefresh.bind(null)
1456
- }, React.createElement(RetryIcon, {
1457
- size: 28
1458
- }))), React.createElement(Tooltip, {
1459
- content: "Transactions History"
1460
- }, React.createElement(Button, {
1461
- variant: "ghost",
1462
- onClick: () => navigate(navigationRoutes.history)
1463
- }, React.createElement(HistoryIcon, {
1464
- size: 24
1465
- }))), React.createElement(Tooltip, {
1466
- content: "Settings"
1467
- }, React.createElement(Button, {
1468
- variant: "ghost",
1469
- onClick: () => navigate(navigationRoutes.settings)
1470
- }, React.createElement(SettingsIcon, {
1471
- size: 24
1472
- }))));
1473
- }
1474
-
1475
- const HeaderContainer = /*#__PURE__*/styled('div', {
1476
- display: 'flex',
1477
- justifyContent: 'space-between',
1478
- alignItems: 'center',
1479
- width: '100%',
1480
- padding: '$16 0'
1481
- });
1482
- function Header(props) {
1483
- const {
1484
- onClickRefresh
1485
- } = props;
1486
- return React.createElement(HeaderContainer, null, React.createElement(Typography, {
1487
- variant: "h4"
1488
- }, "SWAP"), React.createElement(HeaderButtons, {
1489
- onClickRefresh: onClickRefresh
1490
- }));
1491
- }
1492
-
1493
- const Box = /*#__PURE__*/styled('div', {
1494
- display: 'flex',
1495
- flexDirection: 'column',
1496
- width: '100%'
1497
- });
1498
- const Container = /*#__PURE__*/styled('div', {
1499
- boxSizing: 'border-box',
1500
- backgroundColor: '$neutrals300',
1501
- borderRadius: '$5',
1502
- padding: '$8 0',
1503
- '.form': {
1504
- display: 'flex',
1505
- width: '100%',
1506
- padding: '$8 $16'
1507
- }
1508
- });
1509
- const StyledImage = /*#__PURE__*/styled('img', {
1510
- width: '$24',
1511
- maxHeight: '$24'
1512
- });
1513
- const Options = /*#__PURE__*/styled('div', {
1514
- display: 'flex',
1515
- justifyContent: 'flex-end',
1516
- padding: '0 $8'
1517
- });
1518
- const ImagePlaceholder = /*#__PURE__*/styled('span', {
1519
- width: '24px',
1520
- height: '24px',
1521
- backgroundColor: '$neutrals300',
1522
- borderRadius: '99999px'
1523
- });
1524
- const OutputContainer = /*#__PURE__*/styled('div', {
1525
- height: '$48',
1526
- borderRadius: '$5',
1527
- flexGrow: 1,
1528
- width: '70%',
1529
- backgroundColor: '$background',
1530
- border: '1px solid transparent',
1531
- position: 'relative',
1532
- display: 'flex',
1533
- alignItems: 'center',
1534
- paddingLeft: '$8',
1535
- paddingRight: '$8'
1536
- });
1537
- function TokenInfo(props) {
1538
- const {
1539
- type,
1540
- chain,
1541
- token
1542
- } = props;
1543
- const loadingStatus = useMetaStore.use.loadingStatus();
1544
- const fromChain = useBestRouteStore.use.fromChain();
1545
- const toChain = useBestRouteStore.use.toChain();
1546
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1547
- const fromToken = useBestRouteStore.use.fromToken();
1548
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1549
- const bestRoute = useBestRouteStore.use.bestRoute();
1550
- const inputAmount = useBestRouteStore.use.inputAmount();
1551
- const balances = useWalletsStore.use.balances();
1552
- const navigate = useNavigate();
1553
- const tokenBalance = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', 8) : '0';
1554
- const tokenBalanceReal = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.decimal) : '0';
1555
- const ItemSuffix = React.createElement("div", {
1556
- style: {
1557
- display: 'flex',
1558
- justifyContent: 'center',
1559
- alignItems: 'center'
1560
- }
1561
- }, loadingStatus === 'failed' && React.createElement(InfoCircleIcon, {
1562
- color: "error",
1563
- size: 24
1564
- }), React.createElement(AngleDownIcon, null));
1565
- return React.createElement(Box, null, React.createElement("div", null, React.createElement(Typography, {
1566
- variant: "body2"
1567
- }, type)), React.createElement(Container, null, props.type === 'From' && React.createElement(Options, null, React.createElement("div", {
1568
- className: "balance",
1569
- onClick: () => {
1570
- if (tokenBalance !== '0') setInputAmount(tokenBalanceReal.split(',').join(''));
1571
- }
1572
- }, React.createElement(Button, {
1573
- variant: "ghost",
1574
- size: "small"
1575
- }, React.createElement(Typography, {
1576
- variant: "body2"
1577
- }, `Max: ${tokenBalance} ${fromToken?.symbol || ''}`)))), React.createElement("div", {
1578
- className: "form"
1579
- }, React.createElement(Button, {
1580
- onClick: () => {
1581
- navigate(`/${props.type.toLowerCase()}-chain`);
1582
- },
1583
- variant: "outlined",
1584
- disabled: loadingStatus === 'failed',
1585
- loading: loadingStatus === 'loading',
1586
- prefix: loadingStatus === 'success' && chain ? React.createElement(StyledImage, {
1587
- src: chain.logo
1588
- }) : React.createElement(ImagePlaceholder, null),
1589
- suffix: ItemSuffix,
1590
- align: "start",
1591
- size: "large",
1592
- style: {
1593
- marginRight: '.5rem'
1594
- }
1595
- }, loadingStatus === 'success' && chain ? chain.displayName : 'Chain'), React.createElement(Button, {
1596
- onClick: () => {
1597
- navigate(`/${props.type.toLowerCase()}-token`);
1598
- },
1599
- variant: "outlined",
1600
- disabled: loadingStatus === 'failed' || type === 'From' && !fromChain || type === 'To' && !toChain,
1601
- loading: loadingStatus === 'loading',
1602
- prefix: loadingStatus === 'success' && token ? React.createElement(StyledImage, {
1603
- src: token.image
1604
- }) : React.createElement(ImagePlaceholder, null),
1605
- suffix: ItemSuffix,
1606
- size: "large",
1607
- align: "start",
1608
- style: {
1609
- marginRight: '.5rem'
1610
- }
1611
- }, loadingStatus === 'success' && token ? token.symbol : 'Token'), props.type === 'From' ? React.createElement(TextField, {
1612
- type: "number",
1613
- size: "large",
1614
- autoFocus: true,
1615
- placeholder: "0",
1616
- style: {
1617
- width: '70%',
1618
- position: 'relative',
1619
- backgroundColor: '$background !important'
2174
+ memo: '',
2175
+ source: null,
2176
+ fee: {
2177
+ gas: '900000',
2178
+ amount: [{
2179
+ denom: 'uosmo',
2180
+ amount: '0'
2181
+ }]
2182
+ },
2183
+ signType: 'AMINO',
2184
+ rpcUrl: ''
2185
+ },
2186
+ rawTransfer: null
1620
2187
  },
1621
- suffix: React.createElement("span", {
1622
- style: {
1623
- position: 'absolute',
1624
- right: '4px',
1625
- bottom: '2px'
1626
- }
1627
- }, React.createElement(Typography, {
1628
- variant: "caption"
1629
- }, `$${numberToString(inputUsdValue)}`)),
1630
- value: props.inputAmount || '',
1631
- onChange: props.type === 'From' ? event => {
1632
- props.onAmountChange(event.target.value);
1633
- } : undefined
1634
- }) : React.createElement(OutputContainer, null, React.createElement(Typography, {
1635
- variant: "body1"
1636
- }, bestRoute ? `≈ ${numberToString(props.outputAmount)}` : inputAmount ? '?' : '0'), React.createElement("span", {
1637
- style: {
1638
- position: 'absolute',
1639
- right: '4px',
1640
- bottom: '2px'
1641
- }
1642
- }, React.createElement(Typography, {
1643
- variant: "caption"
1644
- }, `$${numberToString(props.outputUsdValue)}`))))));
1645
- }
1646
-
1647
- const Container$1 = /*#__PURE__*/styled$1('div', {
1648
- display: 'flex',
1649
- width: '100%',
1650
- justifyContent: 'end',
1651
- alignItems: 'center',
1652
- paddingTop: '$16'
1653
- });
1654
- const Logo = /*#__PURE__*/styled$1('svg', {
1655
- fill: '$foreground',
1656
- width: '$24',
1657
- margin: '0 $8 0 $16'
1658
- });
1659
- const StyledAnchor = /*#__PURE__*/styled$1('a', {
1660
- display: 'flex',
1661
- justifyContent: 'center',
1662
- alignItems: 'center',
1663
- textDecoration: 'none'
1664
- });
1665
- function BottomLogo() {
1666
- return React.createElement(Container$1, null, React.createElement(Typography, {
1667
- variant: "caption"
1668
- }, "Powered By"), React.createElement(StyledAnchor, {
1669
- href: "https://rango.exchange",
1670
- target: "_blank"
1671
- }, React.createElement(Logo, {
1672
- xmlns: "http://www.w3.org/2000/svg",
1673
- viewBox: "0 0 33.68 29"
1674
- }, React.createElement("defs", null), React.createElement("g", {
1675
- id: "Layer_2",
1676
- "data-name": "Layer 2"
1677
- }, React.createElement("g", {
1678
- id: "Layer_1-2",
1679
- "data-name": "Layer 1"
1680
- }, React.createElement("path", {
1681
- d: "M33.68,18.05A17.93,17.93,0,0,0,28.34,5.29,18.31,18.31,0,0,0,15.45,0H13.54V7.41L6.07,0H.69L9.83,9.07H0V11A17.93,17.93,0,0,0,5.34,23.71,18.32,18.32,0,0,0,18.24,29h1.9V21.59l7.38,7.31h5.39l-9-9h9.82ZM17.37,16.16H12.49a1.93,1.93,0,0,0-1.35.55,1.89,1.89,0,0,0-.56,1.34,1.85,1.85,0,0,0,.56,1.33,1.93,1.93,0,0,0,1.35.55h3.84V25.1A14.43,14.43,0,0,1,8,21a14.21,14.21,0,0,1-4.1-8.2H21.2a1.86,1.86,0,0,0,.74-.13,1.92,1.92,0,0,0,.64-.4,2,2,0,0,0,.43-.62,1.88,1.88,0,0,0,0-1.47,2,2,0,0,0-.43-.62,1.92,1.92,0,0,0-.64-.4,1.86,1.86,0,0,0-.74-.13H17.35V3.9A14.43,14.43,0,0,1,25.64,8a14.19,14.19,0,0,1,4.11,8.2Zm2.12-5.27a1.43,1.43,0,0,1,.26-.83,1.52,1.52,0,0,1,.67-.56,1.55,1.55,0,0,1,.88-.08,1.51,1.51,0,0,1,.77.4,1.54,1.54,0,0,1,.42.77,1.41,1.41,0,0,1-.09.86,1.47,1.47,0,0,1-.55.68,1.56,1.56,0,0,1-.84.25,1.52,1.52,0,0,1-1.52-1.49Z"
1682
- }), React.createElement("path", {
1683
- d: "M21.7,11.57a.68.68,0,0,0-.12-.38.64.64,0,0,0-.31-.25.68.68,0,0,0-.75.15.61.61,0,0,0-.19.35.62.62,0,0,0,0,.4.67.67,0,0,0,.25.3.69.69,0,0,0,.39.12.7.7,0,0,0,.49-.2A.68.68,0,0,0,21.7,11.57Z"
1684
- })))), React.createElement(Typography, {
1685
- variant: "body2"
1686
- }, "RANGO")));
1687
- }
1688
-
1689
- function SwithFromAndTo(_ref) {
1690
- let {
1691
- count
1692
- } = _ref;
1693
- const firstRender = useRef(true);
1694
- const [searchParams, setSearchParams] = useSearchParams();
1695
- const outputAmount = useBestRouteStore.use.outputAmount();
1696
- useEffect(() => {
1697
- if (!firstRender.current) {
1698
- const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
1699
- const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
1700
- const toChainString = searchParams.get(SearchParams.TO_CHAIN);
1701
- const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
1702
- setSearchParams({
1703
- ...(toChainString && {
1704
- [SearchParams.FROM_CHAIN]: toChainString
1705
- }),
1706
- ...(toTokenString && {
1707
- [SearchParams.FROM_TOKEN]: toTokenString
1708
- }),
1709
- ...(fromChainString && {
1710
- [SearchParams.TO_CHAIN]: fromChainString
1711
- }),
1712
- ...(fromTokenString && {
1713
- [SearchParams.TO_TOKEN]: fromTokenString
1714
- }),
1715
- ...(outputAmount && {
1716
- [SearchParams.FROM_AMOUNT]: outputAmount.toString()
1717
- })
1718
- });
1719
- } else {
1720
- firstRender.current = false;
2188
+ solanaTransaction: null,
2189
+ evmTransaction: null,
2190
+ evmApprovalTransaction: null,
2191
+ transferTransaction: null,
2192
+ diagnosisUrl: null,
2193
+ internalSteps: null
2194
+ }]
2195
+ }, {
2196
+ creationTime: '1673164511955',
2197
+ finishTime: '1673164550137',
2198
+ requestId: '51e211d9-d61c-45d2-a4d4-1f9f7f90ee85',
2199
+ inputAmount: '1',
2200
+ wallets: {
2201
+ OSMOSIS: {
2202
+ walletType: 'keplr',
2203
+ address: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl'
1721
2204
  }
1722
- }, [count]);
1723
- return null;
1724
- }
1725
-
1726
- const Footer = /*#__PURE__*/styled('div', {
1727
- display: 'flex',
1728
- flexDirection: 'column',
1729
- width: '100%',
1730
- paddingTop: '$16'
1731
- });
1732
-
1733
- function useBestRoute() {
1734
- const fromToken = useBestRouteStore.use.fromToken();
1735
- const toToken = useBestRouteStore.use.toToken();
1736
- const inputAmount = useBestRouteStore.use.inputAmount();
1737
- const slippage = useSettingsStore.use.slippage();
1738
- const customSlippage = useSettingsStore.use.customSlippage();
1739
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
1740
- const [count, setCount] = useState(0);
1741
- const [loading, setLoading] = useState(false);
1742
- const [error, setError] = useState('');
1743
- const [data, setData] = useState(null);
1744
- const abortControllerRef = useRef(null);
1745
- const retry = () => {
1746
- setCount(prev => prev + 1);
1747
- };
1748
- useEffect(() => {
1749
- if (abortControllerRef.current) abortControllerRef.current.abort();
1750
- const abortController = new AbortController();
1751
- abortControllerRef.current = abortController;
1752
- if (!!fromToken && !!toToken && !!inputAmount) {
1753
- if (!!data) setData(null);
1754
- const requestBody = {
1755
- amount: inputAmount?.toString(),
1756
- connectedWallets: [],
1757
- selectedWallets: {},
1758
- checkPrerequisites: false,
1759
- swapperGroups: disabledLiquiditySources,
1760
- swappersGroupsExclude: true,
1761
- from: {
1762
- address: fromToken.address,
1763
- blockchain: fromToken.blockchain,
1764
- symbol: fromToken.symbol
2205
+ },
2206
+ status: 'success',
2207
+ isPaused: false,
2208
+ extraMessage: null,
2209
+ extraMessageSeverity: 'info',
2210
+ extraMessageDetail: '',
2211
+ extraMessageErrorCode: null,
2212
+ networkStatusExtraMessage: null,
2213
+ networkStatusExtraMessageDetail: null,
2214
+ lastNotificationTime: null,
2215
+ settings: {
2216
+ slippage: '1.0',
2217
+ disabledSwappersIds: [],
2218
+ disabledSwappersGroups: []
2219
+ },
2220
+ simulationResult: {
2221
+ outputAmount: '1.540670',
2222
+ swaps: [{
2223
+ // @ts-ignore
2224
+ result: [],
2225
+ swapperId: 'Osmosis',
2226
+ swapperType: 'DEX',
2227
+ swapperLogo: '',
2228
+ from: {
2229
+ symbol: 'JUNO',
2230
+ logo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
2231
+ address: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
2232
+ blockchain: 'OSMOSIS',
2233
+ blockchainLogo: '',
2234
+ decimals: 6,
2235
+ usdPrice: 1.1091996179668873
2236
+ },
2237
+ to: {
2238
+ symbol: 'OSMO',
2239
+ logo: 'https://api.rango.exchange/i/mJQPS2',
2240
+ address: null,
2241
+ blockchain: 'OSMOSIS',
2242
+ decimals: 6,
2243
+ blockchainLogo: '',
2244
+ usdPrice: 0.7192435454440882
2245
+ },
2246
+ fromAmount: '1.000000',
2247
+ fromAmountPrecision: null,
2248
+ fromAmountMinValue: null,
2249
+ fromAmountMaxValue: null,
2250
+ toAmount: '1.540670',
2251
+ fee: [{
2252
+ name: '',
2253
+ asset: {
2254
+ blockchain: 'OSMOSIS',
2255
+ symbol: 'OSMO',
2256
+ address: null
2257
+ },
2258
+ expenseType: 'FROM_SOURCE_WALLET',
2259
+ amount: '0'
2260
+ }],
2261
+ estimatedTimeInSeconds: 45,
2262
+ swapChainType: 'INTRA_CHAIN',
2263
+ routes: [{
2264
+ nodes: [{
2265
+ nodes: [{
2266
+ marketName: 'pool#498',
2267
+ marketId: null,
2268
+ percent: 1
2269
+ }],
2270
+ from: 'JUNO',
2271
+ fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
2272
+ fromAddress: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
2273
+ fromBlockchain: 'OSMOSIS',
2274
+ to: 'ATOM',
2275
+ toLogo: 'https://api.rango.exchange/tokens/COSMOS/ATOM.png',
2276
+ toAddress: 'ibc/27394fb092d2eccd56123c74f36e4c1f926001ceada9ca97ea622b25f41e5eb2',
2277
+ toBlockchain: 'OSMOSIS'
2278
+ }, {
2279
+ nodes: [{
2280
+ marketName: 'pool#8',
2281
+ marketId: null,
2282
+ percent: 1
2283
+ }],
2284
+ from: 'ATOM',
2285
+ fromLogo: 'https://api.rango.exchange/tokens/COSMOS/ATOM.png',
2286
+ fromAddress: 'ibc/27394fb092d2eccd56123c74f36e4c1f926001ceada9ca97ea622b25f41e5eb2',
2287
+ fromBlockchain: 'OSMOSIS',
2288
+ to: 'IRIS',
2289
+ toLogo: 'https://api.rango.exchange/tokens/COSMOS/IRIS.png',
2290
+ toAddress: 'ibc/7c4d60aa95e5a7558b0a364860979ca34b7ff8aaf255b87af9e879374470cec0',
2291
+ toBlockchain: 'OSMOSIS'
2292
+ }, {
2293
+ nodes: [{
2294
+ marketName: 'pool#7',
2295
+ marketId: null,
2296
+ percent: 1
2297
+ }],
2298
+ from: 'IRIS',
2299
+ fromLogo: 'https://api.rango.exchange/tokens/COSMOS/IRIS.png',
2300
+ fromAddress: 'ibc/7c4d60aa95e5a7558b0a364860979ca34b7ff8aaf255b87af9e879374470cec0',
2301
+ fromBlockchain: 'OSMOSIS',
2302
+ to: 'OSMO',
2303
+ toLogo: 'https://api.rango.exchange/tokens/COSMOS/OSMO.png',
2304
+ toAddress: null,
2305
+ toBlockchain: 'OSMOSIS'
2306
+ }]
2307
+ }],
2308
+ recommendedSlippage: null,
2309
+ timeStat: {
2310
+ min: 6,
2311
+ avg: 40,
2312
+ max: 241
2313
+ },
2314
+ includesDestinationTx: false
2315
+ }]
2316
+ },
2317
+ validateBalanceOrFee: true,
2318
+ steps: [{
2319
+ id: 1,
2320
+ fromBlockchain: 'OSMOSIS',
2321
+ fromSymbol: 'JUNO',
2322
+ fromSymbolAddress: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
2323
+ fromDecimals: 6,
2324
+ fromAmountPrecision: null,
2325
+ fromAmountMinValue: null,
2326
+ swapperLogo: '',
2327
+ swapperType: '',
2328
+ fromAmountMaxValue: null,
2329
+ toBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
2330
+ fromBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
2331
+ toBlockchain: 'OSMOSIS',
2332
+ fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
2333
+ toSymbol: 'OSMO',
2334
+ toSymbolAddress: null,
2335
+ toDecimals: 6,
2336
+ toLogo: 'https://api.rango.exchange/i/mJQPS2',
2337
+ startTransactionTime: 1673164519916,
2338
+ swapperId: 'Osmosis',
2339
+ expectedOutputAmountHumanReadable: '1.540670',
2340
+ outputAmount: '1.540658',
2341
+ status: 'success',
2342
+ networkStatus: null,
2343
+ executedTransactionId: '0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
2344
+ explorerUrl: [{
2345
+ url: 'https://www.mintscan.io/osmosis/txs/0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
2346
+ description: null
2347
+ }],
2348
+ cosmosTransaction: {
2349
+ type: TransactionType.COSMOS,
2350
+ fromWalletAddress: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
2351
+ blockChain: 'OSMOSIS',
2352
+ data: {
2353
+ chainId: 'osmosis-1',
2354
+ account_number: 102721,
2355
+ sequence: '308',
2356
+ msgs: [{
2357
+ __type: 'OsmosisSwapMessage',
2358
+ type: 'osmosis/gamm/swap-exact-amount-in',
2359
+ value: {
2360
+ sender: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
2361
+ routes: [{
2362
+ pool_id: '498',
2363
+ token_out_denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2'
2364
+ }, {
2365
+ pool_id: '8',
2366
+ token_out_denom: 'ibc/7C4D60AA95E5A7558B0A364860979CA34B7FF8AAF255B87AF9E879374470CEC0'
2367
+ }, {
2368
+ pool_id: '7',
2369
+ token_out_denom: 'uosmo'
2370
+ }],
2371
+ token_in: {
2372
+ denom: 'ibc/46B44899322F3CD854D2D46DEEF881958467CDD4B3B10086DA49296BBED94BED',
2373
+ amount: '1000000'
2374
+ },
2375
+ token_out_min_amount: '1525264'
2376
+ }
2377
+ }],
2378
+ protoMsgs: [{
2379
+ type_url: '/osmosis.gamm.v1beta1.MsgSwapExactAmountIn',
2380
+ value: [10, 43, 111, 115, 109, 111, 49, 117, 110, 102, 50, 114, 99, 121, 116, 106, 120, 102, 112, 122, 56, 120, 56, 97, 114, 54, 51, 104, 52, 113, 101, 102, 116, 97, 100, 112, 116, 103, 53, 116, 48, 110, 113, 99, 108, 18, 73, 8, -14, 3, 18, 68, 105, 98, 99, 47, 50, 55, 51, 57, 52, 70, 66, 48, 57, 50, 68, 50, 69, 67, 67, 68, 53, 54, 49, 50, 51, 67, 55, 52, 70, 51, 54, 69, 52, 67, 49, 70, 57, 50, 54, 48, 48, 49, 67, 69, 65, 68, 65, 57, 67, 65, 57, 55, 69, 65, 54, 50, 50, 66, 50, 53, 70, 52, 49, 69, 53, 69, 66, 50, 18, 72, 8, 8, 18, 68, 105, 98, 99, 47, 55, 67, 52, 68, 54, 48, 65, 65, 57, 53, 69, 53, 65, 55, 53, 53, 56, 66, 48, 65, 51, 54, 52, 56, 54, 48, 57, 55, 57, 67, 65, 51, 52, 66, 55, 70, 70, 56, 65, 65, 70, 50, 53, 53, 66, 56, 55, 65, 70, 57, 69, 56, 55, 57, 51, 55, 52, 52, 55, 48, 67, 69, 67, 48, 18, 9, 8, 7, 18, 5, 117, 111, 115, 109, 111, 26, 79, 10, 68, 105, 98, 99, 47, 52, 54, 66, 52, 52, 56, 57, 57, 51, 50, 50, 70, 51, 67, 68, 56, 53, 52, 68, 50, 68, 52, 54, 68, 69, 69, 70, 56, 56, 49, 57, 53, 56, 52, 54, 55, 67, 68, 68, 52, 66, 51, 66, 49, 48, 48, 56, 54, 68, 65, 52, 57, 50, 57, 54, 66, 66, 69, 68, 57, 52, 66, 69, 68, 18, 7, 49, 48, 48, 48, 48, 48, 48, 34, 7, 49, 53, 50, 53, 50, 54, 52]
2381
+ }],
2382
+ memo: '',
2383
+ source: null,
2384
+ fee: {
2385
+ gas: '900000',
2386
+ amount: [{
2387
+ denom: 'uosmo',
2388
+ amount: '0'
2389
+ }]
1765
2390
  },
1766
- to: {
1767
- address: toToken.address,
1768
- blockchain: toToken.blockchain,
1769
- symbol: toToken.symbol
1770
- }
1771
- };
1772
- setLoading(true);
1773
- httpService.getBestRoute(requestBody, {
1774
- signal: abortControllerRef.current.signal
1775
- }).then(res => {
1776
- setData(res);
1777
- setLoading(false);
1778
- abortControllerRef.current = null;
1779
- }).catch(error => {
1780
- if (error.code === 'ERR_CANCELED') return;
1781
- setError(error.message);
1782
- setLoading(false);
1783
- });
1784
- }
1785
- }, [fromToken, toToken, inputAmount, count, slippage, customSlippage, disabledLiquiditySources.length]);
1786
- return {
1787
- loading,
1788
- error,
1789
- data,
1790
- retry
1791
- };
1792
- }
1793
-
1794
- const errorMessages = {
1795
- genericServerError: 'Error connecting server, please reload the app and try again'
1796
- };
1797
-
1798
- function getOutputRatio(inputUsdValue, outputUsdValue) {
1799
- if (inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) return 0;
1800
- return outputUsdValue.div(inputUsdValue).minus(1).multipliedBy(100);
1801
- }
1802
- function outputRatioHasWarning(inputUsdValue, outputRatio) {
1803
- return parseInt(outputRatio.toFixed(2) || '0') <= -10 && inputUsdValue.gte(new BigNumber(400)) || parseInt(outputRatio.toFixed(2) || '0') <= -5 && inputUsdValue.gte(new BigNumber(1000));
1804
- }
1805
- function hasLimitError(bestRoute) {
1806
- return (bestRoute?.result?.swaps || []).filter(swap => {
1807
- const minimum = !!swap.fromAmountMinValue ? new BigNumber(swap.fromAmountMinValue) : null;
1808
- const maximum = !!swap.fromAmountMaxValue ? new BigNumber(swap.fromAmountMaxValue) : null;
1809
- const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
1810
- if (isExclusive) {
1811
- return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);
1812
- } else {
1813
- return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);
1814
- }
1815
- }).length > 0;
1816
- }
1817
- function getSwapButtonTitle(accounts, loading, hasLimitError, highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath) {
1818
- if (loading) return 'Finding Best Route...';
1819
- if (accounts.length == 0) return 'Connect Wallet';else if (hasLimitError) return 'Limit Error';else if (highValueLoss) return 'Price impact is too high!';else if (priceImpactCanNotBeComputed) return 'USD price is unknown, price impact might be high!';else if (needsToWarnEthOnPath) return 'The route goes through Ethereum. Continue?';else return 'Swap';
1820
- }
1821
- function canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue) {
1822
- return !((inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) && !!bestRoute?.result && !!inputAmount && inputAmount !== '0' && parseFloat(inputAmount || '0') !== 0);
1823
- }
1824
- function requiredWallets(route) {
1825
- const wallets = [];
1826
- route?.result?.swaps.forEach(swap => {
1827
- const currentStepFromBlockchain = swap.from.blockchain;
1828
- const currentStepToBlockchain = swap.to.blockchain;
1829
- let lastAddedWallet = wallets[wallets.length - 1];
1830
- if (currentStepFromBlockchain != lastAddedWallet) wallets.push(currentStepFromBlockchain);
1831
- lastAddedWallet = wallets[wallets.length - 1];
1832
- if (currentStepToBlockchain != lastAddedWallet) wallets.push(currentStepToBlockchain);
1833
- });
1834
- return wallets;
1835
- }
1836
-
1837
- const Container$2 = /*#__PURE__*/styled('div', {
1838
- display: 'flex',
1839
- flexDirection: 'column',
1840
- justifyContent: 'center',
1841
- alignItems: 'center'
1842
- });
1843
- const SwitchButtonContainer = /*#__PURE__*/styled('div', {
1844
- display: 'flex',
1845
- justifyContent: 'center',
1846
- alignItems: 'center',
1847
- position: 'relative',
1848
- top: '11px'
1849
- });
1850
- const BestRouteContainer = /*#__PURE__*/styled('div', {
1851
- width: '100%',
1852
- paddingTop: '$16'
1853
- });
1854
- const Alerts = /*#__PURE__*/styled('div', {
1855
- paddingTop: '$16'
1856
- });
1857
- function Home() {
1858
- const waningMessage = '';
1859
- const isRouterInContext = useInRouterContext$1();
2391
+ signType: 'AMINO',
2392
+ rpcUrl: ''
2393
+ },
2394
+ rawTransfer: null
2395
+ },
2396
+ solanaTransaction: null,
2397
+ evmTransaction: null,
2398
+ evmApprovalTransaction: null,
2399
+ transferTransaction: null,
2400
+ diagnosisUrl: null,
2401
+ internalSteps: null
2402
+ }]
2403
+ }];
2404
+ function HistoryPage() {
1860
2405
  const navigate = useNavigate();
1861
- const [count, setCount] = useState(0);
1862
- const fromChain = useBestRouteStore.use.fromChain();
1863
- const fromToken = useBestRouteStore.use.fromToken();
1864
- const toChain = useBestRouteStore.use.toChain();
1865
- const toToken = useBestRouteStore.use.toToken();
1866
- const setFromChain = useBestRouteStore.use.setFromChain();
1867
- const setFromToken = useBestRouteStore.use.setFromToken();
1868
- const setToChain = useBestRouteStore.use.setToChain();
1869
- const setToToken = useBestRouteStore.use.setToToken();
1870
- const setBestRoute = useBestRouteStore.use.setBestRoute();
1871
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1872
- const inputAmount = useBestRouteStore.use.inputAmount();
1873
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1874
- const outputAmount = useBestRouteStore.use.outputAmount();
1875
- const outputUsdValue = useBestRouteStore.use.outputUsdValue();
1876
- const bestRoute = useBestRouteStore.use.bestRoute();
1877
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
1878
- const accounts = useWalletsStore.use.accounts();
1879
- const swithFromAndTo = () => {
1880
- setFromChain(toChain);
1881
- setFromToken(toToken);
1882
- setToChain(fromChain);
1883
- setToToken(fromToken);
1884
- setInputAmount(outputAmount?.toString() || '');
1885
- setCount(prev => prev + 1);
1886
- };
1887
2406
  const {
1888
- data,
1889
- loading: fetchingBestRoute,
1890
- error: bestRouteError,
1891
- retry
1892
- } = useBestRoute();
1893
- const noConnectedWallet = accounts.length > 0;
1894
- const noRoutesFound = !bestRoute?.result;
1895
- const errorMessage = loadingMetaStatus === 'failed' ? errorMessages.genericServerError : bestRouteError;
1896
- const needsToWarnEthOnPath = false;
1897
- const showBestRoute = inputAmount && (!!data || fetchingBestRoute || bestRouteError);
1898
- const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);
1899
- const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);
1900
- const priceImpactCanNotBeComputed = !canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue);
1901
- const buttonTitle = getSwapButtonTitle(accounts, fetchingBestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath);
1902
- const buttonDisabled = loadingMetaStatus != 'success' || fetchingBestRoute || highValueLoss || noConnectedWallet && noRoutesFound || hasLimitError(bestRoute);
1903
- useEffect(() => {
1904
- setBestRoute(data);
1905
- }, [data]);
1906
- return React.createElement(Container$2, null, React.createElement(Header, {
1907
- onClickRefresh: retry
1908
- }), React.createElement(TokenInfo, {
1909
- type: "From",
1910
- chain: fromChain,
1911
- token: fromToken,
1912
- onAmountChange: setInputAmount,
1913
- inputAmount: inputAmount
1914
- }), React.createElement(SwitchButtonContainer, null, React.createElement(Button, {
1915
- variant: "ghost",
1916
- onClick: swithFromAndTo
1917
- }, React.createElement(VerticalSwapIcon, {
1918
- size: 36
1919
- }), isRouterInContext && React.createElement(SwithFromAndTo, {
1920
- count: count
1921
- }))), React.createElement(TokenInfo, {
1922
- type: "To",
1923
- chain: toChain,
1924
- token: toToken,
1925
- outputAmount: outputAmount,
1926
- outputUsdValue: outputUsdValue
1927
- }), showBestRoute && React.createElement(BestRouteContainer, null, React.createElement(BestRoute, {
1928
- error: bestRouteError,
1929
- loading: fetchingBestRoute,
1930
- data: data
1931
- })), (errorMessage || waningMessage) && React.createElement(Alerts, null, errorMessage && React.createElement(Alert, {
1932
- description: errorMessage,
1933
- type: "error"
1934
- }), waningMessage ), React.createElement(Footer, null, React.createElement(Button, {
1935
- type: "primary",
1936
- align: "grow",
1937
- size: "large",
1938
- disabled: buttonDisabled,
1939
- onClick: () => {
1940
- if (buttonTitle === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
1941
- navigate(navigationRoutes.confirmWallets);
1942
- }
1943
- }
1944
- }, buttonTitle), React.createElement(BottomLogo, null)));
2407
+ navigateBackFrom
2408
+ } = useNavigateBack();
2409
+ return React.createElement(History, {
2410
+ list: pendingSwap,
2411
+ onSwapClick: navigate.bind(null, navigationRoutes.swapDetails),
2412
+ onBack: navigateBackFrom.bind(null, navigationRoutes.history)
2413
+ });
1945
2414
  }
1946
2415
 
1947
2416
  function LiquiditySourcePage() {
@@ -1951,7 +2420,9 @@ function LiquiditySourcePage() {
1951
2420
  const toggleLiquiditySource = useSettingsStore.use.toggleLiquiditySource();
1952
2421
  const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
1953
2422
  const toggleAllLiquiditySources = useSettingsStore.use.toggleAllLiquiditySources();
1954
- const navigate = useNavigate();
2423
+ const {
2424
+ navigateBackFrom
2425
+ } = useNavigateBack();
1955
2426
  const uniqueSwappersGroups = [];
1956
2427
  removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
1957
2428
  return swappers.find(s => s.swapperGroup === swapperGroup);
@@ -1971,9 +2442,7 @@ function LiquiditySourcePage() {
1971
2442
  toggleAll: toggleAllLiquiditySources,
1972
2443
  list: uniqueSwappersGroups,
1973
2444
  onChange: liquiditySource => toggleLiquiditySource(liquiditySource.title),
1974
- onBack: () => {
1975
- navigate(-1);
1976
- }
2445
+ onBack: navigateBackFrom.bind(null, navigationRoutes.liquiditySources)
1977
2446
  });
1978
2447
  }
1979
2448
 
@@ -1981,7 +2450,6 @@ function SelectChainPage(props) {
1981
2450
  const {
1982
2451
  type
1983
2452
  } = props;
1984
- const accounts = useWalletsStore.use.accounts();
1985
2453
  const {
1986
2454
  blockchains
1987
2455
  } = useMetaStore.use.meta();
@@ -1992,30 +2460,21 @@ function SelectChainPage(props) {
1992
2460
  const setToChain = useBestRouteStore.use.setToChain();
1993
2461
  const setFromToken = useBestRouteStore.use.setFromToken();
1994
2462
  const setToToken = useBestRouteStore.use.setToToken();
1995
- const navigate = useNavigate();
1996
- const [list, setList] = useState(blockchains);
1997
- useEffect(() => {
1998
- let chainSortedByConnectedWallets = [];
1999
- if (accounts.length !== 0) {
2000
- const connectedChains = removeDuplicateFrom(accounts.map(account => account.chain));
2001
- chainSortedByConnectedWallets = blockchains.sort((blockchainA, blockchainB) => connectedChains.lastIndexOf(blockchainA.name) - connectedChains.lastIndexOf(blockchainB.name));
2002
- } else {
2003
- chainSortedByConnectedWallets = blockchains;
2004
- }
2005
- setList(chainSortedByConnectedWallets);
2006
- }, [blockchains.length, accounts.length]);
2463
+ const {
2464
+ navigateBackFrom
2465
+ } = useNavigateBack();
2007
2466
  return React.createElement(BlockchainSelector, {
2008
2467
  type: type === 'from' ? 'Source' : 'Destination',
2009
- list: list,
2468
+ list: blockchains,
2010
2469
  selected: type === 'from' ? fromChain : toChain,
2011
2470
  loadingStatus: loadingStatus,
2012
2471
  onChange: chain => {
2013
2472
  if (type === 'from') setFromChain(chain);else setToChain(chain);
2014
2473
  if (type === 'from' && fromChain?.name != chain.name) setFromToken(null);
2015
2474
  if (type === 'to' && toChain?.name != chain.name) setToToken(null);
2016
- navigate(-1);
2475
+ navigateBackFrom(navigationRoutes.fromChain);
2017
2476
  },
2018
- onBack: navigate.bind(null, -1)
2477
+ onBack: navigateBackFrom.bind(null, navigationRoutes.fromChain)
2019
2478
  });
2020
2479
  }
2021
2480
 
@@ -2023,7 +2482,9 @@ function SelectTokenPage(props) {
2023
2482
  const {
2024
2483
  type
2025
2484
  } = props;
2026
- const navigate = useNavigate();
2485
+ const {
2486
+ navigateBackFrom
2487
+ } = useNavigateBack();
2027
2488
  const {
2028
2489
  tokens
2029
2490
  } = useMetaStore.use.meta();
@@ -2057,9 +2518,9 @@ function SelectTokenPage(props) {
2057
2518
  selected: type === 'from' ? fromToken : toToken,
2058
2519
  onChange: token => {
2059
2520
  if (type === 'from') setFromToken(token);else setToToken(token);
2060
- navigate(-1);
2521
+ navigateBackFrom(navigationRoutes.fromToken);
2061
2522
  },
2062
- onBack: navigate.bind(null, -1)
2523
+ onBack: navigateBackFrom.bind(null, navigationRoutes.fromToken)
2063
2524
  });
2064
2525
  }
2065
2526
 
@@ -2075,6 +2536,11 @@ function SettingsPage() {
2075
2536
  swappers
2076
2537
  } = useMetaStore.use.meta();
2077
2538
  const navigate = useNavigate();
2539
+ const {
2540
+ navigateBackFrom
2541
+ } = useNavigateBack();
2542
+ const infiniteApprove = useSettingsStore.use.infiniteApprove();
2543
+ const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();
2078
2544
  const uniqueSwappersGroups = [];
2079
2545
  removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2080
2546
  return swappers.find(s => s.swapperGroup === swapperGroup);
@@ -2091,19 +2557,21 @@ function SettingsPage() {
2091
2557
  }
2092
2558
  });
2093
2559
  return React.createElement(Settings, {
2094
- slippages: [1, 2, 3, 4],
2560
+ slippages: SLIPPAGES,
2095
2561
  selectedSlippage: slippage,
2096
2562
  onSlippageChange: slippage => setSlippage(slippage),
2097
2563
  liquiditySources: uniqueSwappersGroups,
2098
2564
  selectedLiquiditySources: uniqueSwappersGroups.filter(s => s.selected),
2099
- onLiquiditySourcesClick: () => navigate(navigationRoutes.liquiditySources),
2100
- onBack: navigate.bind(null, -1),
2565
+ onLiquiditySourcesClick: navigate.bind(null, navigationRoutes.liquiditySources),
2566
+ onBack: navigateBackFrom.bind(null, navigationRoutes.settings),
2101
2567
  customSlippage: customSlippage || NaN,
2102
2568
  onCustomSlippageChange: setCustomSlippage,
2103
- minSlippage: 1,
2104
- maxSlippage: 10,
2569
+ minSlippage: MIN_SLIPPGAE,
2570
+ maxSlippage: MAX_SLIPPAGE,
2105
2571
  selectedTheme: theme,
2106
- onThemeChange: setTheme
2572
+ onThemeChange: setTheme,
2573
+ infiniteApprove: infiniteApprove,
2574
+ toggleInfiniteApprove: toggleInfiniteApprove
2107
2575
  });
2108
2576
  }
2109
2577
 
@@ -2119,7 +2587,9 @@ const AlertContainer = /*#__PURE__*/styled('div', {
2119
2587
  paddingBottom: '$16'
2120
2588
  });
2121
2589
  function WalletsPage() {
2122
- const navigate = useNavigate();
2590
+ const {
2591
+ navigateBackFrom
2592
+ } = useNavigateBack();
2123
2593
  const {
2124
2594
  state,
2125
2595
  disconnect,
@@ -2128,6 +2598,7 @@ function WalletsPage() {
2128
2598
  } = useWallets();
2129
2599
  const wallets = getlistWallet(state, getWalletInfo, Object.values(WalletType));
2130
2600
  const [walletErrorMessage, setWalletErrorMessage] = useState('');
2601
+ const toggleConnectWalletsButton = useUiStore.use.toggleConnectWalletsButton();
2131
2602
  const onSelectWallet = async type => {
2132
2603
  const wallet = state(type);
2133
2604
  try {
@@ -2141,24 +2612,29 @@ function WalletsPage() {
2141
2612
  setWalletErrorMessage('Error: ' + e.message);
2142
2613
  }
2143
2614
  };
2615
+ useEffect(() => {
2616
+ toggleConnectWalletsButton();
2617
+ return () => toggleConnectWalletsButton();
2618
+ }, []);
2144
2619
  return React.createElement(SecondaryPage, {
2145
2620
  title: "Select Wallet",
2146
2621
  textField: false,
2147
- onBack: () => {
2148
- navigate(-1);
2149
- },
2150
- Content: React.createElement(React.Fragment, null, walletErrorMessage && React.createElement(AlertContainer, null, React.createElement(Alert, {
2151
- type: "error",
2152
- description: walletErrorMessage
2153
- })), React.createElement(ListContainer, null, wallets.map((info, index) => React.createElement(Wallet, Object.assign({}, info, {
2154
- key: index,
2155
- onClick: onSelectWallet
2156
- })))))
2157
- });
2622
+ onBack: navigateBackFrom.bind(null, navigationRoutes.wallets)
2623
+ }, React.createElement(React.Fragment, null, walletErrorMessage && React.createElement(AlertContainer, null, React.createElement(Alert, {
2624
+ type: "error"
2625
+ }, React.createElement(Typography, {
2626
+ variant: "body2"
2627
+ }, walletErrorMessage))), React.createElement(ListContainer, null, wallets.map((info, index) => React.createElement(Wallet, Object.assign({}, info, {
2628
+ key: index,
2629
+ onClick: onSelectWallet
2630
+ }))))));
2158
2631
  }
2159
2632
 
2160
2633
  function ConfirmWalletsPage() {
2161
2634
  const navigate = useNavigate();
2635
+ const {
2636
+ navigateBackFrom
2637
+ } = useNavigateBack();
2162
2638
  const bestRoute = useBestRouteStore.use.bestRoute();
2163
2639
  const {
2164
2640
  blockchains
@@ -2172,10 +2648,14 @@ function ConfirmWalletsPage() {
2172
2648
  connect
2173
2649
  } = useWallets();
2174
2650
  const confirmDisabled = !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
2651
+ const firstStep = bestRoute?.result?.swaps[0];
2652
+ const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
2653
+ const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
2654
+ const toAmount = decimalNumber(lastStep?.toAmount, 3);
2175
2655
  useEffect(() => {
2176
2656
  initSelectedWallets();
2177
2657
  }, []);
2178
- const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo, getRequiredChains(bestRoute));
2658
+ const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
2179
2659
  const handleConnectChain = wallet => {
2180
2660
  const network = wallet;
2181
2661
  getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
@@ -2183,9 +2663,11 @@ function ConfirmWalletsPage() {
2183
2663
  return React.createElement(ConfirmWallets, {
2184
2664
  requiredWallets: getRequiredChains(bestRoute),
2185
2665
  selectableWallets: selectableWallets,
2186
- onBack: () => navigate(-1),
2666
+ onBack: navigateBackFrom.bind(null, navigationRoutes.confirmWallets),
2187
2667
  swap: bestRoute,
2188
- onConfirm: () => navigate(navigationRoutes.confirmSwap),
2668
+ fromAmount: fromAmount,
2669
+ toAmount: toAmount,
2670
+ onConfirm: navigate.bind(null, navigationRoutes.confirmSwap),
2189
2671
  onChange: wallet => setSelectedWallet(wallet),
2190
2672
  confirmDisabled: confirmDisabled,
2191
2673
  handleConnectChain: wallet => handleConnectChain(wallet),
@@ -2656,9 +3138,11 @@ const pendingSwap$1 = {
2656
3138
  };
2657
3139
 
2658
3140
  function SwapDetailsPage() {
2659
- const navigate = useNavigate();
3141
+ const {
3142
+ navigateBackFrom
3143
+ } = useNavigateBack();
2660
3144
  return React.createElement(SwapHistory, {
2661
- onBack: navigate.bind(null, -1),
3145
+ onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),
2662
3146
  pendingSwap: pendingSwap$1
2663
3147
  });
2664
3148
  }
@@ -2731,8 +3215,9 @@ function Layout() {
2731
3215
  const {
2732
3216
  getWalletInfo
2733
3217
  } = useWallets();
2734
- const filterSelelectedWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
3218
+ const connectedWalletsImages = removeDuplicateFrom(getSelectableWallets(accounts, selectedWallets, getWalletInfo).map(w => w.image));
2735
3219
  const totalBalance = calculateWalletUsdValue(balances);
3220
+ const connectWalletsButtonDisabled = useUiStore.use.connectWalletsButtonDisabled();
2736
3221
  return React.createElement(React.Fragment, null, React.createElement(Header$1, null, React.createElement(Button, {
2737
3222
  size: "small",
2738
3223
  suffix: React.createElement(AddWalletIcon, {
@@ -2740,10 +3225,12 @@ function Layout() {
2740
3225
  }),
2741
3226
  variant: "ghost",
2742
3227
  flexContent: true,
2743
- onClick: () => navigate(navigationRoutes.wallets)
2744
- }, accounts?.length ? filterSelelectedWallets.map((selectedWallet, index) => React.createElement(WalletImage, {
3228
+ onClick: () => {
3229
+ if (!connectWalletsButtonDisabled) navigate(navigationRoutes.wallets);
3230
+ }
3231
+ }, connectedWalletsImages?.length ? connectedWalletsImages.map((walletImage, index) => React.createElement(WalletImage, {
2745
3232
  key: index,
2746
- src: selectedWallet.image
3233
+ src: walletImage
2747
3234
  })) : React.createElement(React.Fragment, null), React.createElement(Typography, {
2748
3235
  variant: "body2"
2749
3236
  }, !accounts?.length ? 'Connect Wallet' : `$${totalBalance || 0}`))), React.createElement(AppRoutes, null));