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