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