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