@rango-dev/widget-embedded 0.1.10-next.77 → 0.1.10-next.81

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 +1790 -1357
  57. package/dist/widget-embedded.cjs.development.js.map +1 -1
  58. package/dist/widget-embedded.cjs.production.min.js +1790 -1357
  59. package/dist/widget-embedded.cjs.production.min.js.map +1 -1
  60. package/dist/widget-embedded.esm.js +1794 -1361
  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 +17 -6
  85. package/src/pages/SwapDetailsPage.tsx +9 -3
  86. package/src/pages/WalletsPage.tsx +43 -23
  87. package/src/store/bestRoute.ts +147 -28
  88. package/src/store/confirmSwap.ts +327 -0
  89. package/src/store/settings.ts +40 -28
  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 -12
  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 -234
@@ -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
+ infinitApprove: 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
+ toggleInfinitApprove: () => set(state => ({
134
+ infinitApprove: !state.infinitApprove
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,133 +390,6 @@ 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;
594
- }
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
393
  function getOutputRatio(inputUsdValue, outputUsdValue) {
610
394
  if (inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) return 0;
611
395
  return outputUsdValue.div(inputUsdValue).minus(1).multipliedBy(100);
@@ -625,14 +409,90 @@ function hasLimitError(bestRoute) {
625
409
  }
626
410
  }).length > 0;
627
411
  }
628
- function getSwapButtonTitle(accounts, loading, hasLimitError, highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath) {
629
- if (loading) return 'Finding Best Route...';
630
- 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';
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);
426
+ }
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
+ };
631
491
  }
632
492
  function canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue) {
633
- return !((inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) && !!bestRoute?.result && !!inputAmount && inputAmount !== '0' && parseFloat(inputAmount || '0') !== 0);
493
+ return !((inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) && !!bestRoute?.result && !!inputAmount && inputAmount !== '0' && parseFloat(inputAmount || '0') !== 0 && !!bestRoute.result);
634
494
  }
635
- function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validateBalanceOrFee) {
495
+ function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validateBalanceOrFee, meta) {
636
496
  const simulationResult = bestRoute.result;
637
497
  if (!simulationResult) throw Error('Simulation result should not be null');
638
498
  return {
@@ -650,52 +510,58 @@ function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validat
650
510
  networkStatusExtraMessage: null,
651
511
  networkStatusExtraMessageDetail: null,
652
512
  lastNotificationTime: null,
513
+ //@ts-ignore
653
514
  settings: settings,
654
515
  simulationResult: simulationResult,
655
516
  validateBalanceOrFee,
656
- //TODO: finalize PendingSwap type and remove ts-ignore
657
- //@ts-ignore
658
- steps: bestRoute.result?.swaps?.map((s, i) => ({
659
- id: i + 1,
660
- fromBlockchain: s.from.blockchain,
661
- fromSymbol: s.from.symbol,
662
- fromSymbolAddress: s.from.address,
663
- fromDecimals: s.from.decimals,
664
- fromAmountPrecision: s.fromAmountPrecision,
665
- fromAmountMinValue: s.fromAmountMinValue,
666
- fromAmountMaxValue: s.fromAmountMaxValue,
667
- toBlockchain: s.to.blockchain,
668
- fromLogo: s.from.logo,
669
- toSymbol: s.to.symbol,
670
- toSymbolAddress: s.to.address,
671
- toDecimals: s.to.decimals,
672
- toLogo: s.to.logo,
673
- startTransactionTime: new Date().getTime(),
674
- swapperId: s.swapperId,
675
- expectedOutputAmountHumanReadable: s.toAmount,
676
- outputAmount: null,
677
- status: 'created',
678
- networkStatus: null,
679
- executedTransactionId: null,
680
- externalTransactionId: null,
681
- explorerUrl: null,
682
- trackingCode: null,
683
- cosmosTransaction: null,
684
- solanaTransaction: null,
685
- starknetTransaction: null,
686
- starknetApprovalTransaction: null,
687
- tronTransaction: null,
688
- tronApprovalTransaction: null,
689
- evmTransaction: null,
690
- evmApprovalTransaction: null,
691
- transferTransaction: null,
692
- diagnosisUrl: null,
693
- internalSteps: null,
694
- fromBlockchainLogo: '',
695
- toBlockchainLogo: '',
696
- swapperLogo: '',
697
- swapperType: ''
698
- })) || []
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);
522
+ return {
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
563
+ };
564
+ }) || []
699
565
  };
700
566
  }
701
567
  function requiredWallets(route) {
@@ -710,399 +576,1207 @@ function requiredWallets(route) {
710
576
  });
711
577
  return wallets;
712
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]
616
+ });
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
+ }
713
676
 
714
- function useConfirmSwap() {
715
- const fromToken = useBestRouteStore.use.fromToken();
716
- const toToken = useBestRouteStore.use.toToken();
717
- const inputAmount = useBestRouteStore.use.inputAmount();
718
- const bestRoute = useBestRouteStore.use.bestRoute();
719
- const setBestRoute = useBestRouteStore.use.setBestRoute();
720
- const accounts = useWalletsStore.use.accounts();
721
- const selectedWallets = useWalletsStore.use.selectedWallets();
722
- const slippage = useSettingsStore.use.slippage();
723
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
724
- const [loading, setLoading] = useState(false);
725
- const [error, setError] = useState('');
726
- const [warning, setWarning] = useState('');
727
- const [data, setData] = useState(null);
728
- const [feeStatus, setFeeStatus] = useState(null);
729
- const [bestRouteChanged, setBestRouteChanged] = useState(false);
730
- const [enoughBalance, setEnoughBalance] = useState(null);
731
- const hasEnoughBalanceOrProperSlippage = (route, selectedWallets, userSlippage, routeChanged) => {
732
- const fee = route.validationStatus;
733
- if (fee === null || fee.length === 0) return {
734
- balance: true,
735
- slippage: true,
736
- routeChanged
737
- };
738
- for (const wallet of selectedWallets) {
739
- const requiredAssets = getRequiredBalanceOfWallet(wallet, fee);
740
- if (!requiredAssets) continue;
741
- const hasEnoughBalance = requiredAssets?.map(it => it.ok).reduce((a, b) => a && b);
742
- if (!hasEnoughBalance) return {
743
- balance: false,
744
- slippage: true,
745
- routeChanged
746
- };
747
- }
748
- const slippages = route.result?.swaps?.map(s => s.recommendedSlippage);
749
- const slippageError = (slippages?.filter(s => !!s?.error)?.length || 0) > 0;
750
- const minSlippage = slippages?.map(s => parseFloat(s?.slippage.toString() || '0') || 0).filter(s => s > 0).sort((a, b) => b - a).find(() => true) || null;
751
- if (slippageError) {
752
- setError('Server cannot calculated required slippage for your swap');
753
- return {
754
- balance: true,
755
- slippage: false,
756
- routeChanged
757
- };
758
- } else if (minSlippage !== null && minSlippage > parseFloat(userSlippage)) {
759
- setError(`Your slippage should be ${minSlippage} at least`);
760
- return {
761
- balance: true,
762
- slippage: false,
763
- routeChanged
764
- };
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);
765
696
  }
766
697
  return {
767
- balance: true,
768
- slippage: true,
769
- routeChanged
698
+ bestRoute,
699
+ ...(!!bestRoute && {
700
+ outputAmount,
701
+ outputUsdValue
702
+ })
770
703
  };
771
- };
772
- const checkFeeAndBalance = async selectedWallets => {
773
- setLoading(true);
774
- setFeeStatus(null);
775
- const selectedWalletsMap = selectedWallets.reduce((selectedWalletsMap, selectedWallet) => (selectedWalletsMap[selectedWallet.chain] = selectedWallet.address, selectedWalletsMap), {});
776
- const connectedWallets = [];
777
- accounts.forEach(account => {
778
- const chainAndAccounts = connectedWallets.find(wallet => wallet.blockchain);
779
- if (!!chainAndAccounts) chainAndAccounts.addresses.push(account.address);else connectedWallets.push({
780
- blockchain: account.chain,
781
- addresses: [account.address]
782
- });
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
783
748
  });
784
- const r = await httpService.getBestRoute({
785
- amount: inputAmount.toString(),
786
- checkPrerequisites: true,
787
- from: {
788
- address: fromToken.address,
789
- blockchain: fromToken.blockchain,
790
- symbol: fromToken.symbol
791
- },
792
- to: {
793
- address: toToken.address,
794
- blockchain: toToken.blockchain,
795
- symbol: toToken.symbol
796
- },
797
- connectedWallets,
798
- selectedWallets: selectedWalletsMap,
799
- //@ts-ignore
800
- swapperGroups: disabledLiquiditySources,
801
- swappersGroupsExclude: true
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;
802
760
  }).catch(error => {
803
- setError(error.message);
804
- setLoading(false);
761
+ if (error.code === 'ERR_CANCELED') return;
762
+ bestRouteStore.setState({
763
+ error: error.message,
764
+ loading: false
765
+ });
805
766
  });
806
- setLoading(false);
807
- if (!r || !r.result || !bestRoute) return {
808
- bestRoute: null
809
- };
810
- if (!new BigNumber(r.requestAmount).isEqualTo(new BigNumber(inputAmount || '-1'))) return null;
811
- setFeeStatus(r.validationStatus);
812
- const routeChangeStatus = compareRoutes(bestRoute, r, inputAmount.toString(), fromToken.usdPrice, toToken.usdPrice);
813
- setBestRoute(r);
814
- const isChanged = routeChangeStatus.isChanged;
815
- setBestRouteChanged(isChanged);
816
- setWarning('Best route changed');
817
- setData(r);
818
- return {
819
- hasEnoughBalanceOrSlippage: hasEnoughBalanceOrProperSlippage(r, selectedWallets, slippage.toString(), isChanged),
820
- bestRoute: r
821
- };
822
767
  };
823
- const swap = () => {
824
- if (!bestRoute) return;
825
- if (inputAmount.toString() === '') return;
826
- const wallets = selectedWallets.reduce((selectedWalletsMap, selectedWallet) => (selectedWalletsMap[selectedWallet.chain] = {
827
- address: selectedWallet.address,
828
- walletType: selectedWallet.walletType
829
- }, selectedWalletsMap), {});
830
- const proceedAnyway = enoughBalance !== null;
831
- const settings = {
832
- slippage: slippage.toString(),
833
- disabledSwappersGroups: ['Osmosis'],
834
- disabledSwappersIds: []
835
- };
836
- if (proceedAnyway) {
837
- const newSwap = calculatePendingSwap(inputAmount.toString(), bestRoute, wallets, settings, false);
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;
838
777
  }
839
- !proceedAnyway && checkFeeAndBalance(selectedWallets).then(data => {
840
- if (!data) {
841
- setError('confirm swap error');
842
- return;
843
- }
844
- if (!data.bestRoute) {
845
- setError('confirm swap error');
846
- return;
847
- } else {
848
- const {
849
- hasEnoughBalanceOrSlippage,
850
- bestRoute: newBestRoute
851
- } = data;
852
- if (!hasEnoughBalanceOrSlippage) {
853
- return;
854
- }
855
- setEnoughBalance(hasEnoughBalanceOrSlippage.balance && hasEnoughBalanceOrSlippage.slippage);
856
- if (hasEnoughBalanceOrSlippage.balance && hasEnoughBalanceOrSlippage.slippage && !hasEnoughBalanceOrSlippage.routeChanged) {
857
- const newSwap = calculatePendingSwap(inputAmount.toString(), newBestRoute, wallets, settings, true);
858
- } else if (!hasEnoughBalanceOrSlippage.balance) {
859
- setError('not enough balance');
860
- }
861
- }
862
- }).catch(error => {
863
- console.log('unexpected error', error);
864
- });
865
- };
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
+ });
866
788
  return {
867
- loading,
868
- error,
869
- data,
870
- warning,
871
- feeStatus,
872
- bestRouteChanged,
873
- enoughBalance,
874
- swap
789
+ fetchBestRoute
875
790
  };
876
- }
791
+ };
792
+ const {
793
+ fetchBestRoute
794
+ } = /*#__PURE__*/bestRoute(useBestRouteStore, useSettingsStore);
877
795
 
878
- function ConfirmSwapPage() {
879
- const navigate = useNavigate();
880
- const bestRoute = useBestRouteStore.use.bestRoute();
881
- const {
882
- error,
883
- loading,
884
- warning,
885
- swap
886
- } = useConfirmSwap();
887
- return React.createElement(ConfirmSwap, {
888
- onConfirm: swap.bind(null),
889
- onBack: navigate.bind(null, -1),
890
- bestRoute: bestRoute,
891
- loading: loading,
892
- error: error,
893
- warning: warning
894
- });
895
- }
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 = {}));
896
804
 
897
- const pendingSwap = [{
898
- creationTime: '1673164511955',
899
- finishTime: '1673164550137',
900
- requestId: '51e211d9-d61c-45d2-a4d4-1f9f7f90ee85',
901
- inputAmount: '1',
902
- wallets: {
903
- OSMOSIS: {
904
- walletType: 'keplr',
905
- address: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl'
906
- }
907
- },
908
- status: 'running',
909
- isPaused: false,
910
- extraMessage: null,
911
- extraMessageSeverity: 'info',
912
- extraMessageDetail: '',
913
- extraMessageErrorCode: null,
914
- networkStatusExtraMessage: null,
915
- networkStatusExtraMessageDetail: null,
916
- lastNotificationTime: null,
917
- settings: {
918
- slippage: '1.0',
919
- disabledSwappersIds: [],
920
- disabledSwappersGroups: []
921
- },
922
- simulationResult: {
923
- outputAmount: '1.540670',
924
- swaps: [{
925
- swapperId: 'Osmosis',
926
- swapperType: 'DEX',
927
- swapperLogo: '',
928
- // @ts-ignore
929
- result: null,
930
- from: {
931
- symbol: 'JUNO',
932
- logo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
933
- address: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
934
- blockchain: 'OSMOSIS',
935
- blockchainLogo: '',
936
- decimals: 6,
937
- usdPrice: 1.1091996179668873
938
- },
939
- to: {
940
- symbol: 'OSMO',
941
- logo: 'https://api.rango.exchange/i/mJQPS2',
942
- address: null,
943
- blockchain: 'OSMOSIS',
944
- decimals: 6,
945
- blockchainLogo: '',
946
- usdPrice: 0.7192435454440882
947
- },
948
- fromAmount: '1.000000',
949
- fromAmountPrecision: null,
950
- fromAmountMinValue: null,
951
- fromAmountMaxValue: null,
952
- toAmount: '1.540670',
953
- fee: [{
954
- name: '',
955
- asset: {
956
- blockchain: 'OSMOSIS',
957
- symbol: 'OSMO',
958
- address: null
959
- },
960
- expenseType: 'FROM_SOURCE_WALLET',
961
- amount: '0'
962
- }],
963
- estimatedTimeInSeconds: 45,
964
- swapChainType: 'INTRA_CHAIN',
965
- routes: [{
966
- nodes: [{
967
- nodes: [{
968
- marketName: 'pool#498',
969
- marketId: null,
970
- percent: 1
971
- }],
972
- from: 'JUNO',
973
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
974
- fromAddress: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
975
- fromBlockchain: 'OSMOSIS',
976
- to: 'ATOM',
977
- toLogo: 'https://api.rango.exchange/tokens/COSMOS/ATOM.png',
978
- toAddress: 'ibc/27394fb092d2eccd56123c74f36e4c1f926001ceada9ca97ea622b25f41e5eb2',
979
- toBlockchain: 'OSMOSIS'
980
- }, {
981
- nodes: [{
982
- marketName: 'pool#8',
983
- marketId: null,
984
- percent: 1
985
- }],
986
- from: 'ATOM',
987
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/ATOM.png',
988
- fromAddress: 'ibc/27394fb092d2eccd56123c74f36e4c1f926001ceada9ca97ea622b25f41e5eb2',
989
- fromBlockchain: 'OSMOSIS',
990
- to: 'IRIS',
991
- toLogo: 'https://api.rango.exchange/tokens/COSMOS/IRIS.png',
992
- toAddress: 'ibc/7c4d60aa95e5a7558b0a364860979ca34b7ff8aaf255b87af9e879374470cec0',
993
- 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
+ })
994
907
  }, {
995
- nodes: [{
996
- marketName: 'pool#7',
997
- marketId: null,
998
- percent: 1
999
- }],
1000
- from: 'IRIS',
1001
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/IRIS.png',
1002
- fromAddress: 'ibc/7c4d60aa95e5a7558b0a364860979ca34b7ff8aaf255b87af9e879374470cec0',
1003
- fromBlockchain: 'OSMOSIS',
1004
- to: 'OSMO',
1005
- toLogo: 'https://api.rango.exchange/tokens/COSMOS/OSMO.png',
1006
- toAddress: null,
1007
- toBlockchain: 'OSMOSIS'
1008
- }]
1009
- }],
1010
- recommendedSlippage: null,
1011
- timeStat: {
1012
- min: 6,
1013
- avg: 40,
1014
- max: 241
1015
- },
1016
- includesDestinationTx: false
1017
- }]
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
+ });
1018
1029
  },
1019
- validateBalanceOrFee: true,
1020
- steps: [{
1021
- id: 1,
1022
- fromBlockchain: 'OSMOSIS',
1023
- fromSymbol: 'JUNO',
1024
- fromSymbolAddress: 'ibc/46b44899322f3cd854d2d46deef881958467cdd4b3b10086da49296bbed94bed',
1025
- fromDecimals: 6,
1026
- fromAmountPrecision: null,
1027
- fromAmountMinValue: null,
1028
- swapperLogo: '',
1029
- swapperType: '',
1030
- fromAmountMaxValue: null,
1031
- toBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1032
- fromBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1033
- toBlockchain: 'OSMOSIS',
1034
- fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
1035
- toSymbol: 'OSMO',
1036
- toSymbolAddress: null,
1037
- toDecimals: 6,
1038
- toLogo: 'https://api.rango.exchange/i/mJQPS2',
1039
- startTransactionTime: 1673164519916,
1040
- swapperId: 'Osmosis',
1041
- expectedOutputAmountHumanReadable: '1.540670',
1042
- outputAmount: '1.540658',
1043
- status: 'running',
1044
- networkStatus: null,
1045
- executedTransactionId: '0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
1046
- explorerUrl: [{
1047
- url: 'https://www.mintscan.io/osmosis/txs/0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
1048
- description: null
1049
- }],
1050
- cosmosTransaction: {
1051
- type: TransactionType.COSMOS,
1052
- fromWalletAddress: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
1053
- blockChain: 'OSMOSIS',
1054
- data: {
1055
- chainId: 'osmosis-1',
1056
- account_number: 102721,
1057
- sequence: '308',
1058
- msgs: [{
1059
- __type: 'OsmosisSwapMessage',
1060
- type: 'osmosis/gamm/swap-exact-amount-in',
1061
- value: {
1062
- sender: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
1063
- routes: [{
1064
- pool_id: '498',
1065
- token_out_denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2'
1066
- }, {
1067
- pool_id: '8',
1068
- token_out_denom: 'ibc/7C4D60AA95E5A7558B0A364860979CA34B7FF8AAF255B87AF9E879374470CEC0'
1069
- }, {
1070
- pool_id: '7',
1071
- token_out_denom: 'uosmo'
1072
- }],
1073
- token_in: {
1074
- denom: 'ibc/46B44899322F3CD854D2D46DEEF881958467CDD4B3B10086DA49296BBED94BED',
1075
- amount: '1000000'
1076
- },
1077
- token_out_min_amount: '1525264'
1078
- }
1079
- }],
1080
- protoMsgs: [{
1081
- type_url: '/osmosis.gamm.v1beta1.MsgSwapExactAmountIn',
1082
- 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]
1083
- }],
1084
- memo: '',
1085
- source: null,
1086
- fee: {
1087
- gas: '900000',
1088
- amount: [{
1089
- denom: 'uosmo',
1090
- amount: '0'
1091
- }]
1092
- },
1093
- signType: 'AMINO',
1094
- rpcUrl: ''
1095
- },
1096
- rawTransfer: null
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`);
1097
1154
  },
1098
- solanaTransaction: null,
1099
- evmTransaction: null,
1100
- evmApprovalTransaction: null,
1101
- transferTransaction: null,
1102
- diagnosisUrl: null,
1103
- internalSteps: null
1104
- }]
1105
- }, {
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 = [{
1106
1780
  creationTime: '1673164511955',
1107
1781
  finishTime: '1673164550137',
1108
1782
  requestId: '51e211d9-d61c-45d2-a4d4-1f9f7f90ee85',
@@ -1113,7 +1787,7 @@ const pendingSwap = [{
1113
1787
  address: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl'
1114
1788
  }
1115
1789
  },
1116
- status: 'failed',
1790
+ status: 'running',
1117
1791
  isPaused: false,
1118
1792
  extraMessage: null,
1119
1793
  extraMessageSeverity: 'info',
@@ -1131,10 +1805,10 @@ const pendingSwap = [{
1131
1805
  outputAmount: '1.540670',
1132
1806
  swaps: [{
1133
1807
  swapperId: 'Osmosis',
1808
+ swapperType: 'DEX',
1134
1809
  swapperLogo: '',
1135
1810
  // @ts-ignore
1136
1811
  result: null,
1137
- swapperType: 'DEX',
1138
1812
  from: {
1139
1813
  symbol: 'JUNO',
1140
1814
  logo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
@@ -1233,12 +1907,12 @@ const pendingSwap = [{
1233
1907
  fromDecimals: 6,
1234
1908
  fromAmountPrecision: null,
1235
1909
  fromAmountMinValue: null,
1910
+ swapperLogo: '',
1911
+ swapperType: '',
1236
1912
  fromAmountMaxValue: null,
1237
1913
  toBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1238
1914
  fromBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1239
1915
  toBlockchain: 'OSMOSIS',
1240
- swapperLogo: '',
1241
- swapperType: '',
1242
1916
  fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
1243
1917
  toSymbol: 'OSMO',
1244
1918
  toSymbolAddress: null,
@@ -1248,7 +1922,7 @@ const pendingSwap = [{
1248
1922
  swapperId: 'Osmosis',
1249
1923
  expectedOutputAmountHumanReadable: '1.540670',
1250
1924
  outputAmount: '1.540658',
1251
- status: 'failed',
1925
+ status: 'running',
1252
1926
  networkStatus: null,
1253
1927
  executedTransactionId: '0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
1254
1928
  explorerUrl: [{
@@ -1321,7 +1995,7 @@ const pendingSwap = [{
1321
1995
  address: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl'
1322
1996
  }
1323
1997
  },
1324
- status: 'success',
1998
+ status: 'failed',
1325
1999
  isPaused: false,
1326
2000
  extraMessage: null,
1327
2001
  extraMessageSeverity: 'info',
@@ -1338,11 +2012,11 @@ const pendingSwap = [{
1338
2012
  simulationResult: {
1339
2013
  outputAmount: '1.540670',
1340
2014
  swaps: [{
1341
- // @ts-ignore
1342
- result: [],
1343
2015
  swapperId: 'Osmosis',
1344
- swapperType: 'DEX',
1345
2016
  swapperLogo: '',
2017
+ // @ts-ignore
2018
+ result: null,
2019
+ swapperType: 'DEX',
1346
2020
  from: {
1347
2021
  symbol: 'JUNO',
1348
2022
  logo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
@@ -1441,12 +2115,12 @@ const pendingSwap = [{
1441
2115
  fromDecimals: 6,
1442
2116
  fromAmountPrecision: null,
1443
2117
  fromAmountMinValue: null,
1444
- swapperLogo: '',
1445
- swapperType: '',
1446
2118
  fromAmountMaxValue: null,
1447
2119
  toBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1448
2120
  fromBlockchainLogo: 'https://api.rango.exchange/swappers/osmosis.png',
1449
2121
  toBlockchain: 'OSMOSIS',
2122
+ swapperLogo: '',
2123
+ swapperType: '',
1450
2124
  fromLogo: 'https://api.rango.exchange/tokens/COSMOS/JUNO.png',
1451
2125
  toSymbol: 'OSMO',
1452
2126
  toSymbolAddress: null,
@@ -1456,543 +2130,287 @@ const pendingSwap = [{
1456
2130
  swapperId: 'Osmosis',
1457
2131
  expectedOutputAmountHumanReadable: '1.540670',
1458
2132
  outputAmount: '1.540658',
1459
- status: 'success',
2133
+ status: 'failed',
1460
2134
  networkStatus: null,
1461
2135
  executedTransactionId: '0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
1462
2136
  explorerUrl: [{
1463
2137
  url: 'https://www.mintscan.io/osmosis/txs/0f8f17eecc863c2d6be65ef52cfe3128ff3cd7baeddf133160bea8ccdfbf876b',
1464
2138
  description: null
1465
- }],
1466
- cosmosTransaction: {
1467
- type: TransactionType.COSMOS,
1468
- fromWalletAddress: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
1469
- blockChain: 'OSMOSIS',
1470
- data: {
1471
- chainId: 'osmosis-1',
1472
- account_number: 102721,
1473
- sequence: '308',
1474
- msgs: [{
1475
- __type: 'OsmosisSwapMessage',
1476
- type: 'osmosis/gamm/swap-exact-amount-in',
1477
- value: {
1478
- sender: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
1479
- routes: [{
1480
- pool_id: '498',
1481
- token_out_denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2'
1482
- }, {
1483
- pool_id: '8',
1484
- token_out_denom: 'ibc/7C4D60AA95E5A7558B0A364860979CA34B7FF8AAF255B87AF9E879374470CEC0'
1485
- }, {
1486
- pool_id: '7',
1487
- token_out_denom: 'uosmo'
1488
- }],
1489
- token_in: {
1490
- denom: 'ibc/46B44899322F3CD854D2D46DEEF881958467CDD4B3B10086DA49296BBED94BED',
1491
- amount: '1000000'
1492
- },
1493
- token_out_min_amount: '1525264'
1494
- }
1495
- }],
1496
- protoMsgs: [{
1497
- type_url: '/osmosis.gamm.v1beta1.MsgSwapExactAmountIn',
1498
- 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]
1499
- }],
1500
- memo: '',
1501
- source: null,
1502
- fee: {
1503
- gas: '900000',
1504
- amount: [{
1505
- denom: 'uosmo',
1506
- amount: '0'
1507
- }]
1508
- },
1509
- signType: 'AMINO',
1510
- rpcUrl: ''
1511
- },
1512
- rawTransfer: null
1513
- },
1514
- solanaTransaction: null,
1515
- evmTransaction: null,
1516
- evmApprovalTransaction: null,
1517
- transferTransaction: null,
1518
- diagnosisUrl: null,
1519
- internalSteps: null
1520
- }]
1521
- }];
1522
- function HistoryPage() {
1523
- const navigate = useNavigate();
1524
- return React.createElement(History, {
1525
- list: pendingSwap,
1526
- onSwapClick: () => navigate(navigationRoutes.swapDetails),
1527
- onBack: () => {
1528
- navigate(-1);
1529
- }
1530
- });
1531
- }
1532
-
1533
- const ButtonsContainer = /*#__PURE__*/styled('div', {
1534
- display: 'flex'
1535
- });
1536
- function HeaderButtons(props) {
1537
- const {
1538
- onClickRefresh
1539
- } = props;
1540
- const navigate = useNavigate();
1541
- return React.createElement(ButtonsContainer, null, React.createElement(Tooltip, {
1542
- content: "Retry"
1543
- }, React.createElement(Button, {
1544
- variant: "ghost",
1545
- onClick: onClickRefresh.bind(null)
1546
- }, React.createElement(RetryIcon, {
1547
- size: 28
1548
- }))), React.createElement(Tooltip, {
1549
- content: "Transactions History"
1550
- }, React.createElement(Button, {
1551
- variant: "ghost",
1552
- onClick: () => navigate(navigationRoutes.history)
1553
- }, React.createElement(HistoryIcon, {
1554
- size: 24
1555
- }))), React.createElement(Tooltip, {
1556
- content: "Settings"
1557
- }, React.createElement(Button, {
1558
- variant: "ghost",
1559
- onClick: () => navigate(navigationRoutes.settings)
1560
- }, React.createElement(SettingsIcon, {
1561
- size: 24
1562
- }))));
1563
- }
1564
-
1565
- const HeaderContainer = /*#__PURE__*/styled('div', {
1566
- display: 'flex',
1567
- justifyContent: 'space-between',
1568
- alignItems: 'center',
1569
- width: '100%',
1570
- padding: '$16 0'
1571
- });
1572
- function Header(props) {
1573
- const {
1574
- onClickRefresh
1575
- } = props;
1576
- return React.createElement(HeaderContainer, null, React.createElement(Typography, {
1577
- variant: "h4"
1578
- }, "SWAP"), React.createElement(HeaderButtons, {
1579
- onClickRefresh: onClickRefresh
1580
- }));
1581
- }
1582
-
1583
- const Box = /*#__PURE__*/styled('div', {
1584
- display: 'flex',
1585
- flexDirection: 'column',
1586
- width: '100%'
1587
- });
1588
- const Container = /*#__PURE__*/styled('div', {
1589
- boxSizing: 'border-box',
1590
- backgroundColor: '$neutrals300',
1591
- borderRadius: '$5',
1592
- padding: '$8 0',
1593
- '.form': {
1594
- display: 'flex',
1595
- width: '100%',
1596
- padding: '$8 $16'
1597
- }
1598
- });
1599
- const StyledImage = /*#__PURE__*/styled('img', {
1600
- width: '$24',
1601
- maxHeight: '$24'
1602
- });
1603
- const Options = /*#__PURE__*/styled('div', {
1604
- display: 'flex',
1605
- justifyContent: 'flex-end',
1606
- padding: '0 $8'
1607
- });
1608
- const ImagePlaceholder = /*#__PURE__*/styled('span', {
1609
- width: '24px',
1610
- height: '24px',
1611
- backgroundColor: '$neutrals300',
1612
- borderRadius: '99999px'
1613
- });
1614
- const OutputContainer = /*#__PURE__*/styled('div', {
1615
- height: '$48',
1616
- borderRadius: '$5',
1617
- flexGrow: 1,
1618
- width: '70%',
1619
- backgroundColor: '$background',
1620
- border: '1px solid transparent',
1621
- position: 'relative',
1622
- display: 'flex',
1623
- alignItems: 'center',
1624
- paddingLeft: '$8',
1625
- paddingRight: '$8'
1626
- });
1627
- function TokenInfo(props) {
1628
- const {
1629
- type,
1630
- chain,
1631
- token
1632
- } = props;
1633
- const loadingStatus = useMetaStore.use.loadingStatus();
1634
- const fromChain = useBestRouteStore.use.fromChain();
1635
- const toChain = useBestRouteStore.use.toChain();
1636
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1637
- const fromToken = useBestRouteStore.use.fromToken();
1638
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1639
- const bestRoute = useBestRouteStore.use.bestRoute();
1640
- const inputAmount = useBestRouteStore.use.inputAmount();
1641
- const balances = useWalletsStore.use.balances();
1642
- const navigate = useNavigate();
1643
- const tokenBalance = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', 8) : '0';
1644
- 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';
1645
- const ItemSuffix = React.createElement("div", {
1646
- style: {
1647
- display: 'flex',
1648
- justifyContent: 'center',
1649
- alignItems: 'center'
1650
- }
1651
- }, loadingStatus === 'failed' && React.createElement(InfoCircleIcon, {
1652
- color: "error",
1653
- size: 24
1654
- }), React.createElement(AngleDownIcon, null));
1655
- return React.createElement(Box, null, React.createElement("div", null, React.createElement(Typography, {
1656
- variant: "body2"
1657
- }, type)), React.createElement(Container, null, props.type === 'From' && React.createElement(Options, null, React.createElement("div", {
1658
- className: "balance",
1659
- onClick: () => {
1660
- if (tokenBalance !== '0') setInputAmount(tokenBalanceReal.split(',').join(''));
1661
- }
1662
- }, React.createElement(Button, {
1663
- variant: "ghost",
1664
- size: "small"
1665
- }, React.createElement(Typography, {
1666
- variant: "body2"
1667
- }, `Max: ${tokenBalance} ${fromToken?.symbol || ''}`)))), React.createElement("div", {
1668
- className: "form"
1669
- }, React.createElement(Button, {
1670
- onClick: () => {
1671
- navigate(`/${props.type.toLowerCase()}-chain`);
1672
- },
1673
- variant: "outlined",
1674
- disabled: loadingStatus === 'failed',
1675
- loading: loadingStatus === 'loading',
1676
- prefix: loadingStatus === 'success' && chain ? React.createElement(StyledImage, {
1677
- src: chain.logo
1678
- }) : React.createElement(ImagePlaceholder, null),
1679
- suffix: ItemSuffix,
1680
- align: "start",
1681
- size: "large",
1682
- style: {
1683
- marginRight: '.5rem'
1684
- }
1685
- }, loadingStatus === 'success' && chain ? chain.displayName : 'Chain'), React.createElement(Button, {
1686
- onClick: () => {
1687
- navigate(`/${props.type.toLowerCase()}-token`);
1688
- },
1689
- variant: "outlined",
1690
- disabled: loadingStatus === 'failed' || type === 'From' && !fromChain || type === 'To' && !toChain,
1691
- loading: loadingStatus === 'loading',
1692
- prefix: loadingStatus === 'success' && token ? React.createElement(StyledImage, {
1693
- src: token.image
1694
- }) : React.createElement(ImagePlaceholder, null),
1695
- suffix: ItemSuffix,
1696
- size: "large",
1697
- align: "start",
1698
- style: {
1699
- marginRight: '.5rem'
1700
- }
1701
- }, loadingStatus === 'success' && token ? token.symbol : 'Token'), props.type === 'From' ? React.createElement(TextField, {
1702
- type: "number",
1703
- size: "large",
1704
- autoFocus: true,
1705
- placeholder: "0",
1706
- style: {
1707
- width: '70%',
1708
- position: 'relative',
1709
- backgroundColor: '$background !important'
2139
+ }],
2140
+ cosmosTransaction: {
2141
+ type: TransactionType.COSMOS,
2142
+ fromWalletAddress: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
2143
+ blockChain: 'OSMOSIS',
2144
+ data: {
2145
+ chainId: 'osmosis-1',
2146
+ account_number: 102721,
2147
+ sequence: '308',
2148
+ msgs: [{
2149
+ __type: 'OsmosisSwapMessage',
2150
+ type: 'osmosis/gamm/swap-exact-amount-in',
2151
+ value: {
2152
+ sender: 'osmo1unf2rcytjxfpz8x8ar63h4qeftadptg5t0nqcl',
2153
+ routes: [{
2154
+ pool_id: '498',
2155
+ token_out_denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2'
2156
+ }, {
2157
+ pool_id: '8',
2158
+ token_out_denom: 'ibc/7C4D60AA95E5A7558B0A364860979CA34B7FF8AAF255B87AF9E879374470CEC0'
2159
+ }, {
2160
+ pool_id: '7',
2161
+ token_out_denom: 'uosmo'
2162
+ }],
2163
+ token_in: {
2164
+ denom: 'ibc/46B44899322F3CD854D2D46DEEF881958467CDD4B3B10086DA49296BBED94BED',
2165
+ amount: '1000000'
2166
+ },
2167
+ token_out_min_amount: '1525264'
2168
+ }
2169
+ }],
2170
+ protoMsgs: [{
2171
+ type_url: '/osmosis.gamm.v1beta1.MsgSwapExactAmountIn',
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]
2173
+ }],
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
1710
2187
  },
1711
- suffix: React.createElement("span", {
1712
- style: {
1713
- position: 'absolute',
1714
- right: '4px',
1715
- bottom: '2px'
1716
- }
1717
- }, React.createElement(Typography, {
1718
- variant: "caption"
1719
- }, `$${numberToString(inputUsdValue)}`)),
1720
- value: props.inputAmount || '',
1721
- onChange: props.type === 'From' ? event => {
1722
- props.onAmountChange(event.target.value);
1723
- } : undefined
1724
- }) : React.createElement(OutputContainer, null, React.createElement(Typography, {
1725
- variant: "body1"
1726
- }, bestRoute ? `≈ ${numberToString(props.outputAmount)}` : inputAmount ? '?' : '0'), React.createElement("span", {
1727
- style: {
1728
- position: 'absolute',
1729
- right: '4px',
1730
- bottom: '2px'
1731
- }
1732
- }, React.createElement(Typography, {
1733
- variant: "caption"
1734
- }, `$${numberToString(props.outputUsdValue)}`))))));
1735
- }
1736
-
1737
- const Container$1 = /*#__PURE__*/styled$1('div', {
1738
- display: 'flex',
1739
- width: '100%',
1740
- justifyContent: 'end',
1741
- alignItems: 'center',
1742
- paddingTop: '$16'
1743
- });
1744
- const Logo = /*#__PURE__*/styled$1('svg', {
1745
- fill: '$foreground',
1746
- width: '$24',
1747
- margin: '0 $8 0 $16'
1748
- });
1749
- const StyledAnchor = /*#__PURE__*/styled$1('a', {
1750
- display: 'flex',
1751
- justifyContent: 'center',
1752
- alignItems: 'center',
1753
- textDecoration: 'none'
1754
- });
1755
- function BottomLogo() {
1756
- return React.createElement(Container$1, null, React.createElement(Typography, {
1757
- variant: "caption"
1758
- }, "Powered By"), React.createElement(StyledAnchor, {
1759
- href: "https://rango.exchange",
1760
- target: "_blank"
1761
- }, React.createElement(Logo, {
1762
- xmlns: "http://www.w3.org/2000/svg",
1763
- viewBox: "0 0 33.68 29"
1764
- }, React.createElement("defs", null), React.createElement("g", {
1765
- id: "Layer_2",
1766
- "data-name": "Layer 2"
1767
- }, React.createElement("g", {
1768
- id: "Layer_1-2",
1769
- "data-name": "Layer 1"
1770
- }, React.createElement("path", {
1771
- 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"
1772
- }), React.createElement("path", {
1773
- 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"
1774
- })))), React.createElement(Typography, {
1775
- variant: "body2"
1776
- }, "RANGO")));
1777
- }
1778
-
1779
- function SwithFromAndTo(_ref) {
1780
- let {
1781
- count
1782
- } = _ref;
1783
- const firstRender = useRef(true);
1784
- const [searchParams, setSearchParams] = useSearchParams();
1785
- const outputAmount = useBestRouteStore.use.outputAmount();
1786
- useEffect(() => {
1787
- if (!firstRender.current) {
1788
- const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
1789
- const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
1790
- const toChainString = searchParams.get(SearchParams.TO_CHAIN);
1791
- const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
1792
- setSearchParams({
1793
- ...(toChainString && {
1794
- [SearchParams.FROM_CHAIN]: toChainString
1795
- }),
1796
- ...(toTokenString && {
1797
- [SearchParams.FROM_TOKEN]: toTokenString
1798
- }),
1799
- ...(fromChainString && {
1800
- [SearchParams.TO_CHAIN]: fromChainString
1801
- }),
1802
- ...(fromTokenString && {
1803
- [SearchParams.TO_TOKEN]: fromTokenString
1804
- }),
1805
- ...(outputAmount && {
1806
- [SearchParams.FROM_AMOUNT]: outputAmount.toString()
1807
- })
1808
- });
1809
- } else {
1810
- 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'
1811
2204
  }
1812
- }, [count]);
1813
- return null;
1814
- }
1815
-
1816
- const Footer = /*#__PURE__*/styled('div', {
1817
- display: 'flex',
1818
- flexDirection: 'column',
1819
- width: '100%',
1820
- paddingTop: '$16'
1821
- });
1822
-
1823
- function useBestRoute() {
1824
- const fromToken = useBestRouteStore.use.fromToken();
1825
- const toToken = useBestRouteStore.use.toToken();
1826
- const inputAmount = useBestRouteStore.use.inputAmount();
1827
- const slippage = useSettingsStore.use.slippage();
1828
- const customSlippage = useSettingsStore.use.customSlippage();
1829
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
1830
- const [count, setCount] = useState(0);
1831
- const [loading, setLoading] = useState(false);
1832
- const [error, setError] = useState('');
1833
- const [data, setData] = useState(null);
1834
- const abortControllerRef = useRef(null);
1835
- const retry = () => {
1836
- setCount(prev => prev + 1);
1837
- };
1838
- useEffect(() => {
1839
- if (abortControllerRef.current) abortControllerRef.current.abort();
1840
- const abortController = new AbortController();
1841
- abortControllerRef.current = abortController;
1842
- if (!!fromToken && !!toToken && !!inputAmount) {
1843
- if (!!data) setData(null);
1844
- const requestBody = {
1845
- amount: inputAmount?.toString(),
1846
- connectedWallets: [],
1847
- selectedWallets: {},
1848
- checkPrerequisites: false,
1849
- swapperGroups: disabledLiquiditySources,
1850
- swappersGroupsExclude: true,
1851
- from: {
1852
- address: fromToken.address,
1853
- blockchain: fromToken.blockchain,
1854
- 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
+ }]
1855
2390
  },
1856
- to: {
1857
- address: toToken.address,
1858
- blockchain: toToken.blockchain,
1859
- symbol: toToken.symbol
1860
- }
1861
- };
1862
- setLoading(true);
1863
- httpService.getBestRoute(requestBody, {
1864
- signal: abortControllerRef.current.signal
1865
- }).then(res => {
1866
- setData(res);
1867
- setLoading(false);
1868
- abortControllerRef.current = null;
1869
- }).catch(error => {
1870
- if (error.code === 'ERR_CANCELED') return;
1871
- setError(error.message);
1872
- setLoading(false);
1873
- });
1874
- }
1875
- }, [fromToken, toToken, inputAmount, count, slippage, customSlippage, disabledLiquiditySources.length]);
1876
- return {
1877
- loading,
1878
- error,
1879
- data,
1880
- retry
1881
- };
1882
- }
1883
-
1884
- const errorMessages = {
1885
- genericServerError: 'Error connecting server, please reload the app and try again'
1886
- };
1887
-
1888
- const Container$2 = /*#__PURE__*/styled('div', {
1889
- display: 'flex',
1890
- flexDirection: 'column',
1891
- justifyContent: 'center',
1892
- alignItems: 'center'
1893
- });
1894
- const SwitchButtonContainer = /*#__PURE__*/styled('div', {
1895
- display: 'flex',
1896
- justifyContent: 'center',
1897
- alignItems: 'center',
1898
- position: 'relative',
1899
- top: '11px'
1900
- });
1901
- const BestRouteContainer = /*#__PURE__*/styled('div', {
1902
- width: '100%',
1903
- paddingTop: '$16'
1904
- });
1905
- const Alerts = /*#__PURE__*/styled('div', {
1906
- paddingTop: '$16'
1907
- });
1908
- function Home() {
1909
- const waningMessage = '';
1910
- 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() {
1911
2405
  const navigate = useNavigate();
1912
- const [count, setCount] = useState(0);
1913
- const fromChain = useBestRouteStore.use.fromChain();
1914
- const fromToken = useBestRouteStore.use.fromToken();
1915
- const toChain = useBestRouteStore.use.toChain();
1916
- const toToken = useBestRouteStore.use.toToken();
1917
- const setFromChain = useBestRouteStore.use.setFromChain();
1918
- const setFromToken = useBestRouteStore.use.setFromToken();
1919
- const setToChain = useBestRouteStore.use.setToChain();
1920
- const setToToken = useBestRouteStore.use.setToToken();
1921
- const setBestRoute = useBestRouteStore.use.setBestRoute();
1922
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1923
- const inputAmount = useBestRouteStore.use.inputAmount();
1924
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1925
- const outputAmount = useBestRouteStore.use.outputAmount();
1926
- const outputUsdValue = useBestRouteStore.use.outputUsdValue();
1927
- const bestRoute = useBestRouteStore.use.bestRoute();
1928
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
1929
- const accounts = useWalletsStore.use.accounts();
1930
- const swithFromAndTo = () => {
1931
- setFromChain(toChain);
1932
- setFromToken(toToken);
1933
- setToChain(fromChain);
1934
- setToToken(fromToken);
1935
- setInputAmount(outputAmount?.toString() || '');
1936
- setCount(prev => prev + 1);
1937
- };
1938
2406
  const {
1939
- data,
1940
- loading: fetchingBestRoute,
1941
- error: bestRouteError,
1942
- retry
1943
- } = useBestRoute();
1944
- const noConnectedWallet = accounts.length > 0;
1945
- const noRoutesFound = !bestRoute?.result;
1946
- const errorMessage = loadingMetaStatus === 'failed' ? errorMessages.genericServerError : bestRouteError;
1947
- const needsToWarnEthOnPath = false;
1948
- const showBestRoute = inputAmount && (!!data || fetchingBestRoute || bestRouteError);
1949
- const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);
1950
- const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);
1951
- const priceImpactCanNotBeComputed = !canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue);
1952
- const buttonTitle = getSwapButtonTitle(accounts, fetchingBestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath);
1953
- const buttonDisabled = loadingMetaStatus != 'success' || fetchingBestRoute || highValueLoss || noConnectedWallet && noRoutesFound || hasLimitError(bestRoute);
1954
- useEffect(() => {
1955
- setBestRoute(data);
1956
- }, [data]);
1957
- return React.createElement(Container$2, null, React.createElement(Header, {
1958
- onClickRefresh: retry
1959
- }), React.createElement(TokenInfo, {
1960
- type: "From",
1961
- chain: fromChain,
1962
- token: fromToken,
1963
- onAmountChange: setInputAmount,
1964
- inputAmount: inputAmount
1965
- }), React.createElement(SwitchButtonContainer, null, React.createElement(Button, {
1966
- variant: "ghost",
1967
- onClick: swithFromAndTo
1968
- }, React.createElement(VerticalSwapIcon, {
1969
- size: 36
1970
- }), isRouterInContext && React.createElement(SwithFromAndTo, {
1971
- count: count
1972
- }))), React.createElement(TokenInfo, {
1973
- type: "To",
1974
- chain: toChain,
1975
- token: toToken,
1976
- outputAmount: outputAmount,
1977
- outputUsdValue: outputUsdValue
1978
- }), showBestRoute && React.createElement(BestRouteContainer, null, React.createElement(BestRoute, {
1979
- error: bestRouteError,
1980
- loading: fetchingBestRoute,
1981
- data: data
1982
- })), (errorMessage || waningMessage) && React.createElement(Alerts, null, errorMessage && React.createElement(Alert, {
1983
- description: errorMessage,
1984
- type: "error"
1985
- }), waningMessage ), React.createElement(Footer, null, React.createElement(Button, {
1986
- type: "primary",
1987
- align: "grow",
1988
- size: "large",
1989
- disabled: buttonDisabled,
1990
- onClick: () => {
1991
- if (buttonTitle === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
1992
- navigate(navigationRoutes.confirmWallets);
1993
- }
1994
- }
1995
- }, 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
+ });
1996
2414
  }
1997
2415
 
1998
2416
  function LiquiditySourcePage() {
@@ -2002,7 +2420,9 @@ function LiquiditySourcePage() {
2002
2420
  const toggleLiquiditySource = useSettingsStore.use.toggleLiquiditySource();
2003
2421
  const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2004
2422
  const toggleAllLiquiditySources = useSettingsStore.use.toggleAllLiquiditySources();
2005
- const navigate = useNavigate();
2423
+ const {
2424
+ navigateBackFrom
2425
+ } = useNavigateBack();
2006
2426
  const uniqueSwappersGroups = [];
2007
2427
  removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2008
2428
  return swappers.find(s => s.swapperGroup === swapperGroup);
@@ -2022,9 +2442,7 @@ function LiquiditySourcePage() {
2022
2442
  toggleAll: toggleAllLiquiditySources,
2023
2443
  list: uniqueSwappersGroups,
2024
2444
  onChange: liquiditySource => toggleLiquiditySource(liquiditySource.title),
2025
- onBack: () => {
2026
- navigate(-1);
2027
- }
2445
+ onBack: navigateBackFrom.bind(null, navigationRoutes.liquiditySources)
2028
2446
  });
2029
2447
  }
2030
2448
 
@@ -2032,7 +2450,6 @@ function SelectChainPage(props) {
2032
2450
  const {
2033
2451
  type
2034
2452
  } = props;
2035
- const accounts = useWalletsStore.use.accounts();
2036
2453
  const {
2037
2454
  blockchains
2038
2455
  } = useMetaStore.use.meta();
@@ -2043,30 +2460,21 @@ function SelectChainPage(props) {
2043
2460
  const setToChain = useBestRouteStore.use.setToChain();
2044
2461
  const setFromToken = useBestRouteStore.use.setFromToken();
2045
2462
  const setToToken = useBestRouteStore.use.setToToken();
2046
- const navigate = useNavigate();
2047
- const [list, setList] = useState(blockchains);
2048
- useEffect(() => {
2049
- let chainSortedByConnectedWallets = [];
2050
- if (accounts.length !== 0) {
2051
- const connectedChains = removeDuplicateFrom(accounts.map(account => account.chain));
2052
- chainSortedByConnectedWallets = blockchains.sort((blockchainA, blockchainB) => connectedChains.lastIndexOf(blockchainA.name) - connectedChains.lastIndexOf(blockchainB.name));
2053
- } else {
2054
- chainSortedByConnectedWallets = blockchains;
2055
- }
2056
- setList(chainSortedByConnectedWallets);
2057
- }, [blockchains.length, accounts.length]);
2463
+ const {
2464
+ navigateBackFrom
2465
+ } = useNavigateBack();
2058
2466
  return React.createElement(BlockchainSelector, {
2059
2467
  type: type === 'from' ? 'Source' : 'Destination',
2060
- list: list,
2468
+ list: blockchains,
2061
2469
  selected: type === 'from' ? fromChain : toChain,
2062
2470
  loadingStatus: loadingStatus,
2063
2471
  onChange: chain => {
2064
2472
  if (type === 'from') setFromChain(chain);else setToChain(chain);
2065
2473
  if (type === 'from' && fromChain?.name != chain.name) setFromToken(null);
2066
2474
  if (type === 'to' && toChain?.name != chain.name) setToToken(null);
2067
- navigate(-1);
2475
+ navigateBackFrom(navigationRoutes.fromChain);
2068
2476
  },
2069
- onBack: navigate.bind(null, -1)
2477
+ onBack: navigateBackFrom.bind(null, navigationRoutes.fromChain)
2070
2478
  });
2071
2479
  }
2072
2480
 
@@ -2074,7 +2482,9 @@ function SelectTokenPage(props) {
2074
2482
  const {
2075
2483
  type
2076
2484
  } = props;
2077
- const navigate = useNavigate();
2485
+ const {
2486
+ navigateBackFrom
2487
+ } = useNavigateBack();
2078
2488
  const {
2079
2489
  tokens
2080
2490
  } = useMetaStore.use.meta();
@@ -2108,9 +2518,9 @@ function SelectTokenPage(props) {
2108
2518
  selected: type === 'from' ? fromToken : toToken,
2109
2519
  onChange: token => {
2110
2520
  if (type === 'from') setFromToken(token);else setToToken(token);
2111
- navigate(-1);
2521
+ navigateBackFrom(navigationRoutes.fromToken);
2112
2522
  },
2113
- onBack: navigate.bind(null, -1)
2523
+ onBack: navigateBackFrom.bind(null, navigationRoutes.fromToken)
2114
2524
  });
2115
2525
  }
2116
2526
 
@@ -2126,6 +2536,9 @@ function SettingsPage() {
2126
2536
  swappers
2127
2537
  } = useMetaStore.use.meta();
2128
2538
  const navigate = useNavigate();
2539
+ const {
2540
+ navigateBackFrom
2541
+ } = useNavigateBack();
2129
2542
  const uniqueSwappersGroups = [];
2130
2543
  removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2131
2544
  return swappers.find(s => s.swapperGroup === swapperGroup);
@@ -2142,17 +2555,17 @@ function SettingsPage() {
2142
2555
  }
2143
2556
  });
2144
2557
  return React.createElement(Settings, {
2145
- slippages: [1, 2, 3, 4],
2558
+ slippages: SLIPPAGES,
2146
2559
  selectedSlippage: slippage,
2147
2560
  onSlippageChange: slippage => setSlippage(slippage),
2148
2561
  liquiditySources: uniqueSwappersGroups,
2149
2562
  selectedLiquiditySources: uniqueSwappersGroups.filter(s => s.selected),
2150
- onLiquiditySourcesClick: () => navigate(navigationRoutes.liquiditySources),
2151
- onBack: navigate.bind(null, -1),
2563
+ onLiquiditySourcesClick: navigate.bind(null, navigationRoutes.liquiditySources),
2564
+ onBack: navigateBackFrom.bind(null, navigationRoutes.settings),
2152
2565
  customSlippage: customSlippage || NaN,
2153
2566
  onCustomSlippageChange: setCustomSlippage,
2154
- minSlippage: 1,
2155
- maxSlippage: 10,
2567
+ minSlippage: MIN_SLIPPGAE,
2568
+ maxSlippage: MAX_SLIPPAGE,
2156
2569
  selectedTheme: theme,
2157
2570
  onThemeChange: setTheme
2158
2571
  });
@@ -2163,13 +2576,16 @@ const ListContainer = /*#__PURE__*/styled('div', {
2163
2576
  gap: '.5rem',
2164
2577
  gridTemplateColumns: ' repeat(2, minmax(0, 1fr))',
2165
2578
  height: '450px',
2166
- alignContent: 'baseline'
2579
+ alignContent: 'baseline',
2580
+ padding: '0 0.5rem'
2167
2581
  });
2168
2582
  const AlertContainer = /*#__PURE__*/styled('div', {
2169
2583
  paddingBottom: '$16'
2170
2584
  });
2171
2585
  function WalletsPage() {
2172
- const navigate = useNavigate();
2586
+ const {
2587
+ navigateBackFrom
2588
+ } = useNavigateBack();
2173
2589
  const {
2174
2590
  state,
2175
2591
  disconnect,
@@ -2178,6 +2594,7 @@ function WalletsPage() {
2178
2594
  } = useWallets();
2179
2595
  const wallets = getlistWallet(state, getWalletInfo, Object.values(WalletType));
2180
2596
  const [walletErrorMessage, setWalletErrorMessage] = useState('');
2597
+ const toggleConnectWalletsButton = useUiStore.use.toggleConnectWalletsButton();
2181
2598
  const onSelectWallet = async type => {
2182
2599
  const wallet = state(type);
2183
2600
  try {
@@ -2191,24 +2608,29 @@ function WalletsPage() {
2191
2608
  setWalletErrorMessage('Error: ' + e.message);
2192
2609
  }
2193
2610
  };
2611
+ useEffect(() => {
2612
+ toggleConnectWalletsButton();
2613
+ return () => toggleConnectWalletsButton();
2614
+ }, []);
2194
2615
  return React.createElement(SecondaryPage, {
2195
2616
  title: "Select Wallet",
2196
2617
  textField: false,
2197
- onBack: () => {
2198
- navigate(-1);
2199
- },
2200
- Content: React.createElement(React.Fragment, null, walletErrorMessage && React.createElement(AlertContainer, null, React.createElement(Alert, {
2201
- type: "error",
2202
- description: walletErrorMessage
2203
- })), React.createElement(ListContainer, null, wallets.map((info, index) => React.createElement(Wallet, Object.assign({}, info, {
2204
- key: index,
2205
- onClick: onSelectWallet
2206
- })))))
2207
- });
2618
+ onBack: navigateBackFrom.bind(null, navigationRoutes.wallets)
2619
+ }, React.createElement(React.Fragment, null, walletErrorMessage && React.createElement(AlertContainer, null, React.createElement(Alert, {
2620
+ type: "error"
2621
+ }, React.createElement(Typography, {
2622
+ variant: "body2"
2623
+ }, walletErrorMessage))), React.createElement(ListContainer, null, wallets.map((info, index) => React.createElement(Wallet, Object.assign({}, info, {
2624
+ key: index,
2625
+ onClick: onSelectWallet
2626
+ }))))));
2208
2627
  }
2209
2628
 
2210
2629
  function ConfirmWalletsPage() {
2211
2630
  const navigate = useNavigate();
2631
+ const {
2632
+ navigateBackFrom
2633
+ } = useNavigateBack();
2212
2634
  const bestRoute = useBestRouteStore.use.bestRoute();
2213
2635
  const {
2214
2636
  blockchains
@@ -2222,10 +2644,14 @@ function ConfirmWalletsPage() {
2222
2644
  connect
2223
2645
  } = useWallets();
2224
2646
  const confirmDisabled = !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
2647
+ const firstStep = bestRoute?.result?.swaps[0];
2648
+ const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
2649
+ const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
2650
+ const toAmount = decimalNumber(lastStep?.toAmount, 3);
2225
2651
  useEffect(() => {
2226
2652
  initSelectedWallets();
2227
2653
  }, []);
2228
- const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo, getRequiredChains(bestRoute));
2654
+ const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
2229
2655
  const handleConnectChain = wallet => {
2230
2656
  const network = wallet;
2231
2657
  getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
@@ -2233,9 +2659,11 @@ function ConfirmWalletsPage() {
2233
2659
  return React.createElement(ConfirmWallets, {
2234
2660
  requiredWallets: getRequiredChains(bestRoute),
2235
2661
  selectableWallets: selectableWallets,
2236
- onBack: () => navigate(-1),
2662
+ onBack: navigateBackFrom.bind(null, navigationRoutes.confirmWallets),
2237
2663
  swap: bestRoute,
2238
- onConfirm: () => navigate(navigationRoutes.confirmSwap),
2664
+ fromAmount: fromAmount,
2665
+ toAmount: toAmount,
2666
+ onConfirm: navigate.bind(null, navigationRoutes.confirmSwap),
2239
2667
  onChange: wallet => setSelectedWallet(wallet),
2240
2668
  confirmDisabled: confirmDisabled,
2241
2669
  handleConnectChain: wallet => handleConnectChain(wallet),
@@ -2706,9 +3134,11 @@ const pendingSwap$1 = {
2706
3134
  };
2707
3135
 
2708
3136
  function SwapDetailsPage() {
2709
- const navigate = useNavigate();
3137
+ const {
3138
+ navigateBackFrom
3139
+ } = useNavigateBack();
2710
3140
  return React.createElement(SwapHistory, {
2711
- onBack: navigate.bind(null, -1),
3141
+ onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),
2712
3142
  pendingSwap: pendingSwap$1
2713
3143
  });
2714
3144
  }
@@ -2781,8 +3211,9 @@ function Layout() {
2781
3211
  const {
2782
3212
  getWalletInfo
2783
3213
  } = useWallets();
2784
- const filterSelelectedWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
3214
+ const connectedWalletsImages = removeDuplicateFrom(getSelectableWallets(accounts, selectedWallets, getWalletInfo).map(w => w.image));
2785
3215
  const totalBalance = calculateWalletUsdValue(balances);
3216
+ const connectWalletsButtonDisabled = useUiStore.use.connectWalletsButtonDisabled();
2786
3217
  return React.createElement(React.Fragment, null, React.createElement(Header$1, null, React.createElement(Button, {
2787
3218
  size: "small",
2788
3219
  suffix: React.createElement(AddWalletIcon, {
@@ -2790,10 +3221,12 @@ function Layout() {
2790
3221
  }),
2791
3222
  variant: "ghost",
2792
3223
  flexContent: true,
2793
- onClick: () => navigate(navigationRoutes.wallets)
2794
- }, accounts?.length ? filterSelelectedWallets.map((selectedWallet, index) => React.createElement(WalletImage, {
3224
+ onClick: () => {
3225
+ if (!connectWalletsButtonDisabled) navigate(navigationRoutes.wallets);
3226
+ }
3227
+ }, connectedWalletsImages?.length ? connectedWalletsImages.map((walletImage, index) => React.createElement(WalletImage, {
2795
3228
  key: index,
2796
- src: selectedWallet.image
3229
+ src: walletImage
2797
3230
  })) : React.createElement(React.Fragment, null), React.createElement(Typography, {
2798
3231
  variant: "body2"
2799
3232
  }, !accounts?.length ? 'Connect Wallet' : `$${totalBalance || 0}`))), React.createElement(AppRoutes, null));