@rango-dev/widget-embedded 0.1.19 → 0.1.20-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/dist/QueueManager.d.ts +3 -3
  2. package/dist/QueueManager.d.ts.map +1 -1
  3. package/dist/Widget.d.ts +8 -0
  4. package/dist/Widget.d.ts.map +1 -0
  5. package/dist/components/AppRouter.d.ts +7 -7
  6. package/dist/components/AppRouter.d.ts.map +1 -1
  7. package/dist/components/AppRoutes.d.ts +7 -7
  8. package/dist/components/AppRoutes.d.ts.map +1 -1
  9. package/dist/components/BottomLogo.d.ts +2 -2
  10. package/dist/components/BottomLogo.d.ts.map +1 -1
  11. package/dist/components/ChangeSlippageButton.d.ts +2 -2
  12. package/dist/components/ChangeSlippageButton.d.ts.map +1 -1
  13. package/dist/components/ConfirmSwapErrors.d.ts +3 -3
  14. package/dist/components/ConfirmSwapErrors.d.ts.map +1 -1
  15. package/dist/components/ConfirmSwapWarnings.d.ts +2 -2
  16. package/dist/components/ConfirmSwapWarnings.d.ts.map +1 -1
  17. package/dist/components/Footer.d.ts +111 -1
  18. package/dist/components/Footer.d.ts.map +1 -1
  19. package/dist/components/HeaderButtons.d.ts +6 -6
  20. package/dist/components/HeaderButtons.d.ts.map +1 -1
  21. package/dist/components/Layout.d.ts +6 -6
  22. package/dist/components/Layout.d.ts.map +1 -1
  23. package/dist/components/PercentageChange.d.ts +8 -8
  24. package/dist/components/PercentageChange.d.ts.map +1 -1
  25. package/dist/components/RoutesOverview.d.ts +119 -9
  26. package/dist/components/RoutesOverview.d.ts.map +1 -1
  27. package/dist/components/SwapDetailsPlaceholder.d.ts +119 -9
  28. package/dist/components/SwapDetailsPlaceholder.d.ts.map +1 -1
  29. package/dist/components/SwitchFromAndTo.d.ts +3 -3
  30. package/dist/components/SwitchFromAndTo.d.ts.map +1 -1
  31. package/dist/components/TokenInfo.d.ts +17 -17
  32. package/dist/components/TokenInfo.d.ts.map +1 -1
  33. package/dist/components/TokenPreview.d.ts +20 -20
  34. package/dist/components/TokenPreview.d.ts.map +1 -1
  35. package/dist/components/UpdateUrl.d.ts +1 -1
  36. package/dist/components/UpdateUrl.d.ts.map +1 -1
  37. package/dist/components/warnings/BalanceErrors.d.ts +6 -6
  38. package/dist/components/warnings/BalanceErrors.d.ts.map +1 -1
  39. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts +6 -6
  40. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts.map +1 -1
  41. package/dist/components/warnings/HighSlippageWarning.d.ts +6 -6
  42. package/dist/components/warnings/HighSlippageWarning.d.ts.map +1 -1
  43. package/dist/components/warnings/MinRequiredSlippage.d.ts +6 -6
  44. package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -1
  45. package/dist/constants/errors.d.ts +3 -3
  46. package/dist/constants/errors.d.ts.map +1 -1
  47. package/dist/constants/navigationRoutes.d.ts +13 -13
  48. package/dist/constants/navigationRoutes.d.ts.map +1 -1
  49. package/dist/constants/numbers.d.ts +2 -2
  50. package/dist/constants/numbers.d.ts.map +1 -1
  51. package/dist/constants/searchParams.d.ts +7 -7
  52. package/dist/constants/searchParams.d.ts.map +1 -1
  53. package/dist/constants/swapSettings.d.ts +5 -5
  54. package/dist/constants/swapSettings.d.ts.map +1 -1
  55. package/dist/globalStyles.d.ts +1 -1
  56. package/dist/globalStyles.d.ts.map +1 -1
  57. package/dist/hooks/useConfirmSwap.d.ts +10 -10
  58. package/dist/hooks/useConfirmSwap.d.ts.map +1 -1
  59. package/dist/hooks/useNavigateBack.d.ts +3 -3
  60. package/dist/hooks/useNavigateBack.d.ts.map +1 -1
  61. package/dist/hooks/usePrevious.d.ts +1 -1
  62. package/dist/hooks/usePrevious.d.ts.map +1 -1
  63. package/dist/hooks/useSelectLanguage.d.ts +4 -4
  64. package/dist/hooks/useSelectLanguage.d.ts.map +1 -1
  65. package/dist/hooks/useTheme.d.ts +30 -4
  66. package/dist/hooks/useTheme.d.ts.map +1 -1
  67. package/dist/i18n.d.ts +2 -2
  68. package/dist/i18n.d.ts.map +1 -1
  69. package/dist/index.d.ts +5 -9
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +2 -8
  72. package/dist/index.js.map +7 -0
  73. package/dist/mockData/pendingSwap.d.ts +1 -1
  74. package/dist/mockData/pendingSwap.d.ts.map +1 -1
  75. package/dist/pages/ConfirmSwapPage.d.ts +2 -2
  76. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  77. package/dist/pages/HistoryPage.d.ts +2 -2
  78. package/dist/pages/HistoryPage.d.ts.map +1 -1
  79. package/dist/pages/Home.d.ts +2 -2
  80. package/dist/pages/Home.d.ts.map +1 -1
  81. package/dist/pages/LiquiditySourcesPage.d.ts +6 -6
  82. package/dist/pages/LiquiditySourcesPage.d.ts.map +1 -1
  83. package/dist/pages/SelectChainPage.d.ts +7 -7
  84. package/dist/pages/SelectChainPage.d.ts.map +1 -1
  85. package/dist/pages/SelectTokenPage.d.ts +14 -14
  86. package/dist/pages/SelectTokenPage.d.ts.map +1 -1
  87. package/dist/pages/SettingsPage.d.ts +7 -7
  88. package/dist/pages/SettingsPage.d.ts.map +1 -1
  89. package/dist/pages/SwapDetailsPage.d.ts +2 -2
  90. package/dist/pages/SwapDetailsPage.d.ts.map +1 -1
  91. package/dist/pages/WalletsPage.d.ts +8 -8
  92. package/dist/pages/WalletsPage.d.ts.map +1 -1
  93. package/dist/services/httpService.d.ts +3 -3
  94. package/dist/services/httpService.d.ts.map +1 -1
  95. package/dist/store/bestRoute.d.ts +67 -31
  96. package/dist/store/bestRoute.d.ts.map +1 -1
  97. package/dist/store/meta.d.ts +17 -8
  98. package/dist/store/meta.d.ts.map +1 -1
  99. package/dist/store/selectors.d.ts +10 -10
  100. package/dist/store/selectors.d.ts.map +1 -1
  101. package/dist/store/settings.d.ts +55 -18
  102. package/dist/store/settings.d.ts.map +1 -1
  103. package/dist/store/ui.d.ts +22 -1
  104. package/dist/store/ui.d.ts.map +1 -1
  105. package/dist/store/wallets.d.ts +55 -33
  106. package/dist/store/wallets.d.ts.map +1 -1
  107. package/dist/types/config.d.ts +114 -114
  108. package/dist/types/config.d.ts.map +1 -1
  109. package/dist/types/index.d.ts +4 -4
  110. package/dist/types/index.d.ts.map +1 -1
  111. package/dist/types/routing.d.ts +57 -57
  112. package/dist/types/routing.d.ts.map +1 -1
  113. package/dist/types/swap.d.ts +16 -16
  114. package/dist/types/swap.d.ts.map +1 -1
  115. package/dist/types/wallets.d.ts +6 -6
  116. package/dist/types/wallets.d.ts.map +1 -1
  117. package/dist/utils/common.d.ts +3 -3
  118. package/dist/utils/common.d.ts.map +1 -1
  119. package/dist/utils/configs.d.ts +6 -6
  120. package/dist/utils/configs.d.ts.map +1 -1
  121. package/dist/utils/date.d.ts +2 -2
  122. package/dist/utils/date.d.ts.map +1 -1
  123. package/dist/utils/numbers.d.ts +13 -13
  124. package/dist/utils/numbers.d.ts.map +1 -1
  125. package/dist/utils/queue.d.ts +3 -3
  126. package/dist/utils/queue.d.ts.map +1 -1
  127. package/dist/utils/routing.d.ts +17 -17
  128. package/dist/utils/routing.d.ts.map +1 -1
  129. package/dist/utils/swap.d.ts +50 -50
  130. package/dist/utils/swap.d.ts.map +1 -1
  131. package/dist/utils/time.d.ts +3 -3
  132. package/dist/utils/time.d.ts.map +1 -1
  133. package/dist/utils/wallets.d.ts +27 -27
  134. package/dist/utils/wallets.d.ts.map +1 -1
  135. package/package.json +15 -11
  136. package/src/QueueManager.tsx +5 -1
  137. package/src/{index.tsx → Widget.tsx} +1 -14
  138. package/src/components/Layout.tsx +23 -17
  139. package/src/components/RoutesOverview.tsx +2 -2
  140. package/src/components/TokenInfo.tsx +4 -4
  141. package/src/components/TokenPreview.tsx +3 -3
  142. package/src/components/warnings/BalanceErrors.tsx +2 -2
  143. package/src/components/warnings/MinRequiredSlippage.tsx +2 -2
  144. package/src/index.ts +18 -0
  145. package/src/pages/ConfirmSwapPage.tsx +14 -12
  146. package/src/pages/SwapDetailsPage.tsx +1 -1
  147. package/src/pages/WalletsPage.tsx +6 -2
  148. package/src/utils/wallets.ts +6 -3
  149. package/dist/widget-embedded.cjs.development.js +0 -3398
  150. package/dist/widget-embedded.cjs.development.js.map +0 -1
  151. package/dist/widget-embedded.cjs.production.min.js +0 -3398
  152. package/dist/widget-embedded.cjs.production.min.js.map +0 -1
  153. package/dist/widget-embedded.esm.js +0 -3384
  154. package/dist/widget-embedded.esm.js.map +0 -1
@@ -1,3384 +0,0 @@
1
- import { WalletState, InfoCircleIcon, Typography, Button, Image, Spacer, styled, ChevronRightIcon, GasIcon, Alert, ConfirmSwap, LoadingFailedAlert, History, AngleDownIcon, TextField, Tooltip, RetryIcon, HistoryIcon, SettingsIcon, Header as Header$1, VerticalSwapIcon, BestRoute, LiquiditySourcesSelector, BlockchainSelector, TokenSelector, Settings, SecondaryPage, Spinner, Wallet, useCopyToClipboard, SwapHistory, AddWalletIcon, globalCss, generateRangeColors, createTheme, SwapContainer } from '@rango-dev/ui';
2
- import React, { useRef, useEffect, Fragment, useState, useLayoutEffect, useMemo } from 'react';
3
- import { useInRouterContext, MemoryRouter } from 'react-router';
4
- import { PendingSwapNetworkStatus, useQueueManager, calculatePendingSwap, getCurrentStep, getCurrentBlockchainOfOrNull, getRelatedWalletOrNull, cancelSwap, makeQueueDefinition, checkWaitingForNetworkChange } from '@rango-dev/queue-manager-rango-preset';
5
- import { isCosmosBlockchain, isEvmBlockchain } from 'rango-types';
6
- import { useSearchParams, useLocation, createSearchParams, useInRouterContext as useInRouterContext$1, useNavigate, useRoutes } from 'react-router-dom';
7
- import { create } from 'zustand';
8
- import BigNumber, { BigNumber as BigNumber$1 } from 'bignumber.js';
9
- import { persist, subscribeWithSelector } from 'zustand/middleware';
10
- import { RangoClient, isEvmBlockchain as isEvmBlockchain$1 } from 'rango-sdk';
11
- import { Network, isEvmAddress, KEPLR_COMPATIBLE_WALLETS, detectInstallLink, WalletType, getCosmosExperimentalChainInfo, detectMobileScreens, convertEvmBlockchainMetaToEvmChainInfo } from '@rango-dev/wallets-shared';
12
- export { WalletType } from '@rango-dev/wallets-shared';
13
- import { readAccountAddress, useWallets, Provider as Provider$1, Events } from '@rango-dev/wallets-core';
14
- import { shallow } from 'zustand/shallow';
15
- import { allProviders } from '@rango-dev/provider-all';
16
- import { useTranslation, initReactI18next } from 'react-i18next';
17
- import i18n, { t } from 'i18next';
18
- import { useManager, Provider } from '@rango-dev/queue-manager-react';
19
- import dayjs from 'dayjs';
20
- import { styled as styled$1 } from '@rango-dev/ui/';
21
- import Backend from 'i18next-http-backend';
22
- import LanguageDetector from 'i18next-browser-languagedetector';
23
-
24
- const ZERO = /*#__PURE__*/new BigNumber(0);
25
-
26
- function removeDuplicateFrom(array) {
27
- return Array.from(new Set(array));
28
- }
29
- function areEqual(array1, array2) {
30
- return array1.length === array2.length && array1.every((v, i) => v === array2[i]);
31
- }
32
- function debounce(fn, time) {
33
- let timeoutId;
34
- return wrapper;
35
- function wrapper() {
36
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
37
- args[_key] = arguments[_key];
38
- }
39
- if (timeoutId) {
40
- clearTimeout(timeoutId);
41
- }
42
- timeoutId = setTimeout(() => {
43
- timeoutId = null;
44
- fn(...args);
45
- }, time);
46
- }
47
- }
48
-
49
- const secondsToString = s => {
50
- const seconds = (s % 60).toString().padStart(2, '0');
51
- const minutes = parseInt((s / 60).toString()).toString().padStart(2, '0');
52
- return `${minutes}:${seconds}`;
53
- };
54
- const numberToString = function (number, minDecimals, maxDecimals) {
55
- if (minDecimals === void 0) {
56
- minDecimals = null;
57
- }
58
- if (maxDecimals === void 0) {
59
- maxDecimals = null;
60
- }
61
- if (number === null || number === undefined) return '';
62
- if (number === '') return '';
63
- const n = new BigNumber$1(number);
64
- const roundingMode = 1;
65
- let maxI = 1000;
66
- for (let i = 0; i < 60; i++) {
67
- if (new BigNumber$1(n.toFixed(i, roundingMode)).eq(n)) {
68
- maxI = i;
69
- break;
70
- }
71
- }
72
- if (n.gte(10000)) return n.toFormat(0, roundingMode);
73
- if (n.gte(1000)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))), roundingMode);
74
- if (n.gte(100)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))), roundingMode);
75
- if (n.gte(1)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 2))), roundingMode);
76
- if (n.gte(0.01)) return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 4))), roundingMode);
77
- 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);
78
- if (n.isEqualTo(0)) return '0';
79
- return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 8))), roundingMode);
80
- };
81
- const totalArrivalTime = data => data?.result?.swaps?.reduce((a, b) => a + b.estimatedTimeInSeconds, 0) || 0;
82
- const isPositiveNumber = text => !!text && parseFloat(text) > 0;
83
-
84
- function searchParamsToToken(tokens, searchParams, chain) {
85
- if (!chain) return null;
86
- return tokens.find(token => {
87
- const symbolAndAddress = searchParams?.split('--');
88
- if (symbolAndAddress?.length === 1) return token.symbol === symbolAndAddress[0] && token.address === null && token.blockchain === chain.name;
89
- return token.symbol === symbolAndAddress?.[0] && token.address === symbolAndAddress?.[1] && token.blockchain === chain.name;
90
- }) || null;
91
- }
92
- function getBestRouteToTokenUsdPrice(bestRoute) {
93
- return bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1].to.usdPrice;
94
- }
95
- function isNumberOfSwapsChanged(route1, route2) {
96
- const route1Swaps = route1.result?.swaps || [];
97
- const route2Swaps = route2.result?.swaps || [];
98
- return route1Swaps.length !== route2Swaps.length;
99
- }
100
- function isRouteSwappersUpdated(route1, route2) {
101
- const route1Swappers = route1.result?.swaps.map(swap => swap.swapperId) || [];
102
- const route2Swappers = route2.result?.swaps.map(swap => swap.swapperId) || [];
103
- return !areEqual(route1Swappers, route2Swappers);
104
- }
105
- function isRouteInternalCoinsUpdated(route1, route2) {
106
- const route1InternalCoins = route1.result?.swaps.map(swap => swap.to.symbol) || [];
107
- const route2InternalCoins = route2.result?.swaps.map(swap => swap.to.symbol) || [];
108
- return !areEqual(route1InternalCoins, route2InternalCoins);
109
- }
110
- function isRouteChanged(route1, route2) {
111
- return isNumberOfSwapsChanged(route1, route2) || isRouteSwappersUpdated(route1, route2) || isRouteInternalCoinsUpdated(route1, route2);
112
- }
113
- function getRequiredBalanceOfWallet(selectedWallet, fee) {
114
- if (fee === null) return null;
115
- const relatedFeeStatus = fee?.find(item => item.blockchain === selectedWallet.chain)?.wallets.find(wallet => wallet.address?.toLowerCase() === selectedWallet.address.toLowerCase());
116
- if (!relatedFeeStatus) return null;
117
- return relatedFeeStatus.requiredAssets;
118
- }
119
- function isRouteParametersChanged(params) {
120
- if (params.store === 'bestRoute') {
121
- const {
122
- prevState,
123
- currentState
124
- } = params;
125
- return !!currentState.fromToken && !!currentState.toToken && (prevState.fromChain?.name !== currentState.fromChain?.name || prevState.toChain?.name !== currentState.toChain?.name || prevState.fromToken?.symbol !== currentState.fromToken?.symbol || prevState.toToken?.symbol !== currentState.toToken?.symbol || prevState.fromToken?.blockchain !== prevState.fromToken?.blockchain || prevState.toToken?.blockchain !== currentState.toToken?.blockchain || prevState.fromToken?.address !== currentState.fromToken?.address || prevState.toToken?.address !== currentState.toToken?.address || prevState.inputAmount !== currentState.inputAmount);
126
- } else if (params.store === 'settings') {
127
- const {
128
- prevState,
129
- currentState
130
- } = params;
131
- return prevState.slippage !== currentState.slippage || prevState.customSlippage !== currentState.customSlippage || prevState.disabledLiquiditySources?.length !== currentState.disabledLiquiditySources?.length || prevState.infiniteApprove || currentState.infiniteApprove;
132
- }
133
- return false;
134
- }
135
- function getFormatedBestRoute(bestRoute) {
136
- if (!bestRoute) return null;
137
- const formatedSwaps = (bestRoute.result?.swaps || []).map(swap => ({
138
- ...swap,
139
- fromAmount: numberToString(swap.fromAmount, 6, 6),
140
- toAmount: numberToString(swap.toAmount, 6, 6)
141
- }));
142
- return {
143
- ...bestRoute,
144
- ...(bestRoute.result && {
145
- result: {
146
- ...bestRoute.result,
147
- swaps: formatedSwaps
148
- }
149
- })
150
- };
151
- }
152
- function getFormatedPendingSwap(pendingSwap) {
153
- const formatedSteps = pendingSwap.steps.map(step => ({
154
- ...step,
155
- feeInUsd: numberToString(step.feeInUsd, 4, 4),
156
- outputAmount: numberToString(step.outputAmount, 6, 6),
157
- expectedOutputAmountHumanReadable: numberToString(step.expectedOutputAmountHumanReadable, 6, 6)
158
- }));
159
- return {
160
- ...pendingSwap,
161
- inputAmount: numberToString(pendingSwap.inputAmount, 6, 6),
162
- steps: formatedSteps
163
- };
164
- }
165
- //todo: refactor bestRoute store and add loadingStatus
166
- const getBestRouteStatus = (loading, error) => {
167
- if (loading) return 'loading';
168
- if (error) return 'failed';else return 'success';
169
- };
170
-
171
- const createSelectors = _store => {
172
- let store = _store;
173
- store.use = {};
174
- for (let k of Object.keys(store.getState())) {
175
- store.use[k] = () => store(s => s[k]);
176
- }
177
- return store;
178
- };
179
-
180
- const RANGO_PUBLIC_API_KEY = 'c6381a79-2817-4602-83bf-6a641a409e32';
181
- let configs = {
182
- API_KEY: RANGO_PUBLIC_API_KEY
183
- };
184
- function getConfig(name) {
185
- return configs[name];
186
- }
187
- function initConfig(nextConfigs) {
188
- let clonedConfigs;
189
- if (typeof structuredClone === 'function') {
190
- clonedConfigs = structuredClone(nextConfigs);
191
- } else {
192
- clonedConfigs = JSON.parse(JSON.stringify(nextConfigs));
193
- }
194
- configs = clonedConfigs;
195
- return configs;
196
- }
197
-
198
- let rango = undefined;
199
- const httpService = () => {
200
- if (rango) return rango;
201
- rango = new RangoClient(getConfig('API_KEY'));
202
- return rango;
203
- };
204
-
205
- const SLIPPAGES = [0.5, 1, 3, 5, 8, 13, 20];
206
- const DEFAULT_SLIPPAGE = 1;
207
- const HIGH_SLIPPAGE = 5;
208
- const MAX_SLIPPAGE = 100;
209
- const MIN_SLIPPGAE = 0;
210
-
211
- const useMetaStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()(set => ({
212
- meta: {
213
- blockchains: [],
214
- popularTokens: [],
215
- swappers: [],
216
- tokens: []
217
- },
218
- loadingStatus: 'loading',
219
- fetchMeta: async () => {
220
- try {
221
- const response = await httpService().getAllMetadata();
222
- const chainThatHasTokenInMetaResponse = removeDuplicateFrom(response.tokens.map(t => t.blockchain));
223
- const enabledChains = response.blockchains.filter(chain => chain.enabled && chainThatHasTokenInMetaResponse.includes(chain.name));
224
- response.blockchains = enabledChains.sort((a, b) => a.sort - b.sort);
225
- set({
226
- meta: response,
227
- loadingStatus: 'success'
228
- });
229
- } catch (error) {
230
- set({
231
- loadingStatus: 'failed'
232
- });
233
- }
234
- }
235
- })));
236
-
237
- const useSettingsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/persist( /*#__PURE__*/subscribeWithSelector(set => ({
238
- slippage: DEFAULT_SLIPPAGE,
239
- customSlippage: null,
240
- infiniteApprove: false,
241
- affiliateRef: null,
242
- disabledLiquiditySources: [],
243
- theme: 'auto',
244
- setSlippage: slippage => set(() => ({
245
- slippage: slippage
246
- })),
247
- setCustomSlippage: customSlippage => set(() => ({
248
- customSlippage: customSlippage
249
- })),
250
- setAffiliateRef: affiliateRef => set(() => ({
251
- affiliateRef
252
- })),
253
- toggleAllLiquiditySources: () => set(state => {
254
- const {
255
- swappers
256
- } = useMetaStore.getState().meta;
257
- const swappersGroup = removeDuplicateFrom(swappers.map(swapper => swapper.swapperGroup));
258
- if (swappersGroup.length === state.disabledLiquiditySources.length) return {
259
- disabledLiquiditySources: []
260
- };else {
261
- return {
262
- disabledLiquiditySources: swappersGroup
263
- };
264
- }
265
- }),
266
- toggleInfiniteApprove: () => set(state => ({
267
- infiniteApprove: !state.infiniteApprove
268
- })),
269
- toggleLiquiditySource: name => set(state => {
270
- if (state.disabledLiquiditySources.includes(name)) return {
271
- disabledLiquiditySources: state.disabledLiquiditySources.filter(liquiditySource => liquiditySource != name)
272
- };else return {
273
- disabledLiquiditySources: state.disabledLiquiditySources.concat(name)
274
- };
275
- }),
276
- setTheme: theme => set(() => ({
277
- theme
278
- }))
279
- })), {
280
- name: 'user-settings'
281
- })));
282
-
283
- function getStateWallet(state) {
284
- switch (true) {
285
- case state.connected:
286
- return WalletState.CONNECTED;
287
- case state.connecting:
288
- return WalletState.CONNECTING;
289
- case !state.installed:
290
- return WalletState.NOT_INSTALLED;
291
- default:
292
- return WalletState.DISCONNECTED;
293
- }
294
- }
295
- const excludedWallets = [WalletType.UNKNOWN, WalletType.LEAP];
296
- function getlistWallet(getState, getWalletInfo, list) {
297
- return list.filter(wallet => !excludedWallets.includes(wallet)).map(type => {
298
- const {
299
- name,
300
- img: image,
301
- installLink,
302
- showOnMobile
303
- } = getWalletInfo(type);
304
- const state = getStateWallet(getState(type));
305
- return {
306
- name,
307
- image,
308
- installLink: detectInstallLink(installLink),
309
- state,
310
- type,
311
- showOnMobile: typeof showOnMobile === 'undefined' ? false : true
312
- };
313
- });
314
- }
315
- function walletAndSupportedChainsNames(supportedChains) {
316
- if (!supportedChains) return null;
317
- let walletAndSupportedChainsNames = [];
318
- walletAndSupportedChainsNames = supportedChains.map(blockchainMeta => blockchainMeta.name);
319
- return walletAndSupportedChainsNames;
320
- }
321
- function prepareAccountsForWalletStore(wallet, accounts, evmBasedChains, supportedChainNames) {
322
- const result = [];
323
- function addAccount(network, address) {
324
- const newAccount = {
325
- address,
326
- chain: network,
327
- walletType: wallet
328
- };
329
- result.push(newAccount);
330
- }
331
- const supportedChains = supportedChainNames || [];
332
- accounts.forEach(account => {
333
- const {
334
- address,
335
- network
336
- } = readAccountAddress(account);
337
- const hasLimitation = supportedChains.length > 0;
338
- const isSupported = supportedChains.includes(network);
339
- const isUnknown = network === Network.Unknown;
340
- const notSupportedNetworkByWallet = hasLimitation && !isSupported && !isUnknown;
341
- // Here we check given `network` is not supported by wallet
342
- // And also the network is known.
343
- if (notSupportedNetworkByWallet) return;
344
- // In some cases we can handle unknown network by checking its address
345
- // pattern and act on it.
346
- // Example: showing our evm compatible netwrok when the uknown network is evem.
347
- // Otherwise, we stop executing this function.
348
- const isUknownAndEvmBased = network === Network.Unknown && isEvmAddress(address);
349
- if (isUnknown && !isUknownAndEvmBased) return;
350
- const isEvmBasedChain = evmBasedChains.includes(network);
351
- // If it's an evm network, we will add the address to all the evm chains.
352
- if (isEvmBasedChain || isUknownAndEvmBased) {
353
- // all evm chains are not supported in wallets, so we are adding
354
- // only to those that are supported by wallet.
355
- const evmChainsSupportedByWallet = supportedChains.filter(chain => evmBasedChains.includes(chain));
356
- evmChainsSupportedByWallet.forEach(network => {
357
- // EVM addresses are not case sensetive.
358
- // Some wallets like Binance-chain return some letters in uppercase which produces bugs in our wallet state.
359
- addAccount(network, address.toLowerCase());
360
- });
361
- } else {
362
- addAccount(network, address);
363
- }
364
- });
365
- return result;
366
- }
367
- function getRequiredChains(route) {
368
- const wallets = [];
369
- route?.result?.swaps.forEach(swap => {
370
- const currentStepFromBlockchain = swap.from.blockchain;
371
- const currentStepToBlockchain = swap.to.blockchain;
372
- let lastAddedWallet = wallets[wallets.length - 1];
373
- if (currentStepFromBlockchain != lastAddedWallet) wallets.push(currentStepFromBlockchain);
374
- lastAddedWallet = wallets[wallets.length - 1];
375
- if (currentStepToBlockchain != lastAddedWallet) wallets.push(currentStepToBlockchain);
376
- });
377
- return wallets;
378
- }
379
- function getSelectableWallets(connectedWallets, selectedWallets, getWalletInfo) {
380
- const selectableWallets = connectedWallets.map(connectedWallet => ({
381
- address: connectedWallet.address,
382
- walletType: connectedWallet.walletType,
383
- chain: connectedWallet.chain,
384
- image: getWalletInfo(connectedWallet.walletType).img,
385
- name: getWalletInfo(connectedWallet.walletType).name,
386
- selected: !!selectedWallets.find(selectedWallet => selectedWallet.chain === connectedWallet.chain && selectedWallet.walletType === connectedWallet.walletType)
387
- }));
388
- return selectableWallets;
389
- }
390
- function getBalanceFromWallet(connectedWallets, chain, symbol, address) {
391
- if (connectedWallets.length === 0) return null;
392
- const selectedChainWallets = connectedWallets.filter(wallet => wallet.chain === chain);
393
- if (selectedChainWallets.length === 0) return null;
394
- return selectedChainWallets.map(wallet => wallet.balances?.find(balance => address !== null && balance.address === address || address === null && balance.address === address && balance.symbol === symbol) || null).filter(balance => balance !== null).sort((a, b) => parseFloat(b?.amount || '0') - parseFloat(a?.amount || '1')).find(() => true) || null;
395
- }
396
- function isAccountAndWalletMatched(account, connectedWallet) {
397
- return account.address === connectedWallet.address && account.chain === connectedWallet.chain;
398
- }
399
- function makeBalanceFor(wallet, retrivedBalance, tokens) {
400
- const {
401
- address,
402
- blockChain: chain,
403
- explorerUrl,
404
- balances = []
405
- } = retrivedBalance;
406
- return {
407
- address,
408
- chain,
409
- loading: false,
410
- error: false,
411
- explorerUrl,
412
- walletType: wallet.walletType,
413
- balances: balances?.map(tokenBalance => ({
414
- chain,
415
- symbol: tokenBalance.asset.symbol,
416
- ticker: tokenBalance.asset.symbol,
417
- address: tokenBalance.asset.address || null,
418
- rawAmount: tokenBalance.amount.amount,
419
- decimal: tokenBalance.amount.decimals,
420
- amount: new BigNumber(tokenBalance.amount.amount).shiftedBy(-tokenBalance.amount.decimals).toFixed(),
421
- logo: '',
422
- usdPrice: getUsdPrice(chain, tokenBalance.asset.symbol, tokenBalance.asset.address, tokens) || null
423
- })) || []
424
- };
425
- }
426
- function resetConnectedWalletState(connectedWallet) {
427
- return {
428
- ...connectedWallet,
429
- loading: false,
430
- error: true
431
- };
432
- }
433
- const calculateWalletUsdValue = connectedWallet => {
434
- const uniqueAccountAddresses = new Set();
435
- const uniqueBalane = connectedWallet?.reduce((acc, current) => {
436
- return acc.findIndex(i => i.address === current.address && i.chain === current.chain) === -1 ? [...acc, current] : acc;
437
- }, []);
438
- const modifiedWalletBlockchains = uniqueBalane?.map(chain => {
439
- const modifiedWalletBlockchain = {
440
- name: chain.chain,
441
- accounts: []
442
- };
443
- if (!uniqueAccountAddresses.has(chain.address)) {
444
- uniqueAccountAddresses.add(chain.address);
445
- }
446
- uniqueAccountAddresses.forEach(accountAddress => {
447
- if (chain.address === accountAddress) modifiedWalletBlockchain.accounts.push(chain);
448
- });
449
- return modifiedWalletBlockchain;
450
- });
451
- const total = numberToString(modifiedWalletBlockchains?.flatMap(b => b.accounts)?.flatMap(a => a?.balances)?.map(b => new BigNumber(b?.amount || ZERO).multipliedBy(b?.usdPrice || 0))?.reduce((a, b) => a.plus(b), ZERO) || ZERO).toString();
452
- return numberWithThousandSeperator(total);
453
- };
454
- function numberWithThousandSeperator(number) {
455
- var parts = number.toString().split('.');
456
- parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
457
- return parts.join('.');
458
- }
459
- const sortTokens = tokens => {
460
- let walletConnected = !!tokens.some(token => token.balance);
461
- if (!walletConnected) {
462
- return tokens.filter(token => !token.address).concat(tokens.filter(token => token.address && !token.isSecondaryCoin), tokens.filter(token => token.isSecondaryCoin));
463
- }
464
- return tokens.filter(token => !!token.balance).sort((tokenA, tokenB) => parseFloat(tokenB.balance?.usdValue || '0') - parseFloat(tokenA.balance?.usdValue || '0')).concat(tokens.filter(token => !token.balance && !token.isSecondaryCoin), tokens.filter(token => !token.balance && token.isSecondaryCoin));
465
- };
466
- const getUsdPrice = (blockchain, symbol, address, allTokens) => {
467
- const token = allTokens?.find(t => t.blockchain === blockchain && t.symbol?.toUpperCase() === symbol?.toUpperCase() && t.address === address);
468
- return token?.usdPrice || null;
469
- };
470
- const isExperimentalChain = (blockchains, wallet) => {
471
- const cosmosExperimentalChainInfo = getCosmosExperimentalChainInfo(Object.entries(blockchains).map(_ref => {
472
- let [, blockchainMeta] = _ref;
473
- return blockchainMeta;
474
- }).filter(isCosmosBlockchain));
475
- return cosmosExperimentalChainInfo && !!cosmosExperimentalChainInfo[wallet];
476
- };
477
- const getKeplrCompatibleConnectedWallets = selectableWallets => {
478
- const connectedWalletTypes = new Set(selectableWallets.map(a => a.walletType.toString()));
479
- return KEPLR_COMPATIBLE_WALLETS.filter(compatibleWallet => connectedWalletTypes.has(compatibleWallet));
480
- };
481
- function getTokensWithBalance(tokens, connectedWallets) {
482
- return tokens.map(_ref2 => {
483
- let {
484
- balance,
485
- ...otherProps
486
- } = _ref2;
487
- const tokenAmount = numberToString(new BigNumber(getBalanceFromWallet(connectedWallets, otherProps.blockchain, otherProps.symbol, otherProps.address)?.amount || ZERO));
488
- let tokenUsdValue = '';
489
- if (otherProps.usdPrice) tokenUsdValue = numberToString(new BigNumber(getBalanceFromWallet(connectedWallets, otherProps.blockchain, otherProps.symbol, otherProps.address)?.amount || ZERO).multipliedBy(otherProps.usdPrice));
490
- return {
491
- ...otherProps,
492
- ...(tokenAmount !== '0' && {
493
- balance: {
494
- amount: tokenAmount,
495
- usdValue: tokenUsdValue
496
- }
497
- })
498
- };
499
- });
500
- }
501
- function getSortedTokens(chain, tokens, connectedWallets, otherChainTokens) {
502
- const fromChainEqueulsToToChain = chain?.name === otherChainTokens[0]?.name;
503
- if (fromChainEqueulsToToChain) return otherChainTokens;
504
- const filteredTokens = tokens.filter(token => token.blockchain === chain?.name);
505
- return sortTokens(getTokensWithBalance(filteredTokens, connectedWallets));
506
- }
507
- function tokensAreEqual(tokenA, tokenB) {
508
- return tokenA?.blockchain === tokenB?.blockchain && tokenA?.symbol === tokenB?.symbol && tokenA?.address === tokenB?.address;
509
- }
510
- function getDefaultToken(sortedTokens, otherToken) {
511
- let selectedToken;
512
- const firstToken = sortedTokens[0];
513
- const secondToken = sortedTokens[1];
514
- if (sortedTokens.length === 1) selectedToken = firstToken;else if (tokensAreEqual(firstToken, otherToken)) selectedToken = secondToken;else selectedToken = firstToken;
515
- return selectedToken;
516
- }
517
- function sortWalletsBasedOnState(wallets) {
518
- return wallets.sort((a, b) => Number(b.state === WalletState.CONNECTED) - Number(a.state === WalletState.CONNECTED) || Number(b.state === WalletState.DISCONNECTED || b.state === WalletState.CONNECTING) - Number(a.state === WalletState.DISCONNECTED || a.state === WalletState.CONNECTING));
519
- }
520
-
521
- function getOutputRatio(inputUsdValue, outputUsdValue) {
522
- if (inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) return 0;
523
- return outputUsdValue.div(inputUsdValue).minus(1).multipliedBy(100);
524
- }
525
- function outputRatioHasWarning(inputUsdValue, outputRatio) {
526
- return parseInt(outputRatio.toFixed(2) || '0') <= -10 && inputUsdValue.gte(new BigNumber(400)) || parseInt(outputRatio.toFixed(2) || '0') <= -5 && inputUsdValue.gte(new BigNumber(1000));
527
- }
528
- function hasLimitError(bestRoute) {
529
- return (bestRoute?.result?.swaps || []).filter(swap => {
530
- const minimum = !!swap.fromAmountMinValue ? new BigNumber(swap.fromAmountMinValue) : null;
531
- const maximum = !!swap.fromAmountMaxValue ? new BigNumber(swap.fromAmountMaxValue) : null;
532
- const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
533
- if (isExclusive) {
534
- return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);
535
- } else {
536
- return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);
537
- }
538
- }).length > 0;
539
- }
540
- function LimitErrorMessage(bestRoute) {
541
- if (!bestRoute) return {
542
- swap: null,
543
- fromAmountRangeError: '',
544
- recommendation: ''
545
- };
546
- const swap = (bestRoute?.result?.swaps || []).filter(swap => {
547
- const minimum = !!swap.fromAmountMinValue ? new BigNumber(swap.fromAmountMinValue) : null;
548
- const maximum = !!swap.fromAmountMaxValue ? new BigNumber(swap.fromAmountMaxValue) : null;
549
- const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
550
- if (isExclusive) {
551
- return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);
552
- } else {
553
- return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);
554
- }
555
- })[0];
556
- if (!swap) return {
557
- swap: null,
558
- fromAmountRangeError: '',
559
- recommendation: ''
560
- };
561
- const minimum = !!swap.fromAmountMinValue ? new BigNumber(swap.fromAmountMinValue) : null;
562
- const maximum = !!swap.fromAmountMaxValue ? new BigNumber(swap.fromAmountMaxValue) : null;
563
- const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
564
- let fromAmountRangeError = '';
565
- let recommendation = '';
566
- if (!isExclusive && !!minimum && minimum.gt(swap.fromAmount)) {
567
- fromAmountRangeError = `Required: >= ${numberToString(minimum)} ${swap.from.symbol}`;
568
- recommendation = 'Increase your swap amount';
569
- } else if (isExclusive && !!minimum && minimum.gte(swap.fromAmount)) {
570
- fromAmountRangeError = `Required: > ${numberToString(minimum)} ${swap.from.symbol}`;
571
- recommendation = 'Increase your swap amount';
572
- }
573
- if (!isExclusive && !!maximum && maximum.lt(swap.fromAmount)) {
574
- fromAmountRangeError = `Required: <= ${numberToString(maximum)} ${swap.from.symbol}`;
575
- recommendation = 'Decrease your swap amount';
576
- } else if (isExclusive && !!maximum && maximum.lte(swap.fromAmount)) {
577
- fromAmountRangeError = `Required: < ${numberToString(maximum)} ${swap.from.symbol}`;
578
- recommendation = 'Decrease your swap amount';
579
- }
580
- return {
581
- swap,
582
- fromAmountRangeError,
583
- recommendation
584
- };
585
- }
586
- function getSwapButtonState(loadingMetaStatus, connectedWallets, loading, bestRoute, hasLimitError, highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath, inputAmount) {
587
- if (loadingMetaStatus !== 'success') return {
588
- title: 'Connect Wallet',
589
- disabled: true
590
- };
591
- if (connectedWallets.length == 0) return {
592
- title: 'Connect Wallet',
593
- disabled: false
594
- };
595
- if (loading) return {
596
- title: 'Finding Best Route...',
597
- disabled: true
598
- };else if (!inputAmount || inputAmount === '0') return {
599
- title: 'Enter an amount',
600
- disabled: true
601
- };else if (!bestRoute || !bestRoute.result) return {
602
- title: 'Swap',
603
- disabled: true
604
- };else if (hasLimitError) return {
605
- title: 'Limit Error',
606
- disabled: true
607
- };else if (highValueLoss) return {
608
- title: 'Price impact is too high!',
609
- disabled: true
610
- };else if (priceImpactCanNotBeComputed) return {
611
- title: 'USD price is unknown, price impact might be high!',
612
- disabled: false,
613
- hasWarning: true
614
- };else if (needsToWarnEthOnPath) return {
615
- title: 'The route goes through Ethereum. Continue?',
616
- disabled: false,
617
- hasWarning: true
618
- };else return {
619
- title: 'Swap',
620
- disabled: false
621
- };
622
- }
623
- function canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue) {
624
- return !((inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) && !!bestRoute?.result && !!inputAmount && inputAmount !== '0' && parseFloat(inputAmount || '0') !== 0 && !!bestRoute.result);
625
- }
626
- function requiredWallets(route) {
627
- const wallets = [];
628
- route?.result?.swaps.forEach(swap => {
629
- const currentStepFromBlockchain = swap.from.blockchain;
630
- const currentStepToBlockchain = swap.to.blockchain;
631
- let lastAddedWallet = wallets[wallets.length - 1];
632
- if (currentStepFromBlockchain != lastAddedWallet) wallets.push(currentStepFromBlockchain);
633
- lastAddedWallet = wallets[wallets.length - 1];
634
- if (currentStepToBlockchain != lastAddedWallet) wallets.push(currentStepToBlockchain);
635
- });
636
- return wallets;
637
- }
638
- const getUsdPrice$1 = (blockchain, symbol, address, allTokens) => {
639
- const token = allTokens?.find(t => t.blockchain === blockchain && t.symbol?.toUpperCase() === symbol?.toUpperCase() && t.address === address);
640
- return token?.usdPrice || null;
641
- };
642
- function getUsdFeeOfStep(step, allTokens) {
643
- let totalFeeInUsd = ZERO;
644
- for (let i = 0; i < step.fee.length; i++) {
645
- const fee = step.fee[i];
646
- if (fee.expenseType === 'DECREASE_FROM_OUTPUT') continue;
647
- const unitPrice = getUsdPrice$1(fee.asset.blockchain, fee.asset.symbol, fee.asset.address, allTokens);
648
- totalFeeInUsd = totalFeeInUsd.plus(new BigNumber(fee.amount).multipliedBy(unitPrice || 0));
649
- }
650
- return totalFeeInUsd;
651
- }
652
- function getTotalFeeInUsd(bestRoute, allTokens) {
653
- return bestRoute?.result?.swaps.reduce((totalFee, step) => totalFee.plus(getUsdFeeOfStep(step, allTokens)), ZERO) || null;
654
- }
655
- function hasHighFee(totalFeeInUsd) {
656
- if (!totalFeeInUsd) return false;
657
- return !totalFeeInUsd.lt(new BigNumber(30));
658
- }
659
- function getMinRequiredSlippage(route) {
660
- const slippages = route.result?.swaps.map(slippage => slippage.recommendedSlippage);
661
- return slippages?.map(s => s?.slippage || '0')?.filter(s => parseFloat(s) > 0)?.sort((a, b) => parseFloat(b) - parseFloat(a))?.find(() => true) || null;
662
- }
663
- function hasProperSlippage(userSlippage, minRequiredSlippage) {
664
- if (!minRequiredSlippage) return true;
665
- return parseFloat(userSlippage) >= parseFloat(minRequiredSlippage);
666
- }
667
- function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, selectedWallets, disabledLiquiditySources, slippage, affiliateRef, initialRoute) {
668
- const selectedWalletsMap = selectedWallets.reduce((selectedWalletsMap, selectedWallet) => (selectedWalletsMap[selectedWallet.chain] = selectedWallet.address, selectedWalletsMap), {});
669
- const connectedWallets = [];
670
- wallets.forEach(wallet => {
671
- const chainAndAccounts = connectedWallets.find(connectedWallet => connectedWallet.blockchain === wallet.chain);
672
- if (!!chainAndAccounts) chainAndAccounts.addresses.push(wallet.address);else connectedWallets.push({
673
- blockchain: wallet.chain,
674
- addresses: [wallet.address]
675
- });
676
- });
677
- const checkPrerequisites = !!initialRoute;
678
- const filteredBlockchains = removeDuplicateFrom((initialRoute?.result?.swaps || []).reduce((blockchains, swap) => (blockchains.push(swap.from.blockchain, swap.to.blockchain), blockchains), []));
679
- const requestBody = {
680
- amount: inputAmount.toString(),
681
- affiliateRef,
682
- checkPrerequisites,
683
- from: {
684
- address: fromToken.address,
685
- blockchain: fromToken.blockchain,
686
- symbol: fromToken.symbol
687
- },
688
- to: {
689
- address: toToken.address,
690
- blockchain: toToken.blockchain,
691
- symbol: toToken.symbol
692
- },
693
- connectedWallets,
694
- selectedWallets: selectedWalletsMap,
695
- swapperGroups: disabledLiquiditySources,
696
- swappersGroupsExclude: true,
697
- slippage: slippage.toString(),
698
- ...(checkPrerequisites && {
699
- blockchains: filteredBlockchains
700
- })
701
- };
702
- return requestBody;
703
- }
704
- function getWalletsForNewSwap(selectedWallets) {
705
- const wallets = selectedWallets.reduce((selectedWalletsMap, selectedWallet) => (selectedWalletsMap[selectedWallet.chain] = {
706
- address: selectedWallet.address,
707
- walletType: selectedWallet.walletType
708
- }, selectedWalletsMap), {});
709
- return wallets;
710
- }
711
- function getRouteOutputAmount(route) {
712
- return route?.result?.outputAmount || null;
713
- }
714
- function getPercentageChange(oldValue, newValue) {
715
- if (!oldValue || !newValue) return null;
716
- return new BigNumber(newValue).div(new BigNumber(oldValue)).minus(1).multipliedBy(100);
717
- }
718
- function isOutputAmountChangedALot(oldRoute, newRoute) {
719
- const oldOutputAmount = getRouteOutputAmount(oldRoute);
720
- const newOutputAmount = getRouteOutputAmount(newRoute);
721
- if (!oldOutputAmount || !newOutputAmount) return false;
722
- const percentageChange = getPercentageChange(oldOutputAmount, newOutputAmount);
723
- if (!percentageChange) return true;
724
- return percentageChange.toNumber() <= -1;
725
- }
726
- function getBalanceWarnings(route, selectedWallets) {
727
- const fee = route.validationStatus;
728
- const requiredWallets = getRequiredChains(route);
729
- const walletsSortedByRequiredWallets = selectedWallets.sort((selectedWallet1, selectedWallet2) => requiredWallets.indexOf(selectedWallet1.chain) - requiredWallets.indexOf(selectedWallet2.chain));
730
- return walletsSortedByRequiredWallets.flatMap(wallet => getRequiredBalanceOfWallet(wallet, fee) || []).filter(asset => !asset.ok).map(asset => {
731
- const symbol = asset.asset.symbol;
732
- const currentAmount = numberToString(new BigNumber(asset.currentAmount.amount).shiftedBy(-asset.currentAmount.decimals), 8);
733
- const requiredAmount = numberToString(new BigNumber(asset.requiredAmount.amount).shiftedBy(-asset.requiredAmount.decimals), 8);
734
- let reason = '';
735
- if (asset.reason === 'FEE') reason = ' for network fee';
736
- if (asset.reason === 'INPUT_ASSET') reason = ' for swap';
737
- if (asset.reason === 'FEE_AND_INPUT_ASSET') reason = ' for input and network fee';
738
- const warningMessage = `Needs ≈ ${requiredAmount} ${symbol}${reason}, but you have ${currentAmount} ${symbol} in your ${asset.asset.blockchain} wallet.`;
739
- return warningMessage;
740
- });
741
- }
742
- function calcOutputUsdValue(outputAmount, tokenPrice) {
743
- const amount = !!outputAmount ? new BigNumber(outputAmount) : ZERO;
744
- return amount.multipliedBy(tokenPrice || 0);
745
- }
746
- function isNetworkStatusInWarningState(pendingSwapStep) {
747
- return !!pendingSwapStep && pendingSwapStep.networkStatus !== null && pendingSwapStep.networkStatus !== PendingSwapNetworkStatus.NetworkChanged;
748
- }
749
- function getSwapMessages(pendingSwap, currentStep) {
750
- const textForRemove = 'bellow button or';
751
- let message = pendingSwap.extraMessage;
752
- let detailedMessage = pendingSwap.extraMessageDetail;
753
- if (pendingSwap.networkStatusExtraMessageDetail?.includes(textForRemove)) {
754
- pendingSwap.networkStatusExtraMessageDetail = pendingSwap.networkStatusExtraMessageDetail.replace(textForRemove, '');
755
- }
756
- const networkWarningState = isNetworkStatusInWarningState(currentStep);
757
- if (networkWarningState) {
758
- message = pendingSwap.networkStatusExtraMessage || '';
759
- detailedMessage = pendingSwap.networkStatusExtraMessageDetail || '';
760
- switch (currentStep?.networkStatus) {
761
- case PendingSwapNetworkStatus.WaitingForConnectingWallet:
762
- message = message || 'Waiting for connecting wallet';
763
- break;
764
- case PendingSwapNetworkStatus.WaitingForQueue:
765
- message = message || 'Waiting for other running tasks to be finished';
766
- break;
767
- case PendingSwapNetworkStatus.WaitingForNetworkChange:
768
- message = message || 'Waiting for changing wallet network';
769
- break;
770
- }
771
- }
772
- detailedMessage = detailedMessage || '';
773
- message = message || '';
774
- const isRpc = message?.indexOf('code') !== -1 && message?.indexOf('reason') !== -1;
775
- return {
776
- shortMessage: message,
777
- detailedMessage: {
778
- content: detailedMessage,
779
- long: isRpc
780
- }
781
- };
782
- }
783
- function getLastConvertedTokenInFailedSwap(pendingSwap) {
784
- let resultToken = null;
785
- if (pendingSwap.status === 'failed') {
786
- const lastSuccessStep = pendingSwap.steps.slice().reverse().filter(step => step.status === 'success')[0];
787
- if (lastSuccessStep) {
788
- resultToken = {
789
- blockchain: lastSuccessStep.toBlockchain,
790
- symbol: lastSuccessStep.toSymbol,
791
- outputAmount: lastSuccessStep.outputAmount,
792
- address: lastSuccessStep.toSymbolAddress
793
- };
794
- }
795
- }
796
- return resultToken;
797
- }
798
- function shouldRetrySwap(pendingSwap) {
799
- return pendingSwap.status === 'failed' && !!pendingSwap.finishTime && new Date().getTime() - parseInt(pendingSwap.finishTime) < 4 * 3600 * 1000;
800
- }
801
-
802
- const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/subscribeWithSelector((set, get) => ({
803
- connectedWallets: [],
804
- selectedWallets: [],
805
- connectWallet: accounts => {
806
- const getOneOfWalletsDetails = get().getOneOfWalletsDetails;
807
- set(state => ({
808
- connectedWallets: state.connectedWallets.filter(wallet => wallet.walletType !== accounts[0].walletType).concat(accounts.map(account => ({
809
- balances: [],
810
- address: account.address,
811
- chain: account.chain,
812
- loading: true,
813
- walletType: account.walletType,
814
- error: false,
815
- explorerUrl: null
816
- })))
817
- }));
818
- accounts.forEach(async account => getOneOfWalletsDetails(account));
819
- },
820
- disconnectWallet: walletType => {
821
- set(state => ({
822
- connectedWallets: state.connectedWallets.filter(balance => balance.walletType !== walletType),
823
- selectedWallets: state.selectedWallets.filter(wallet => wallet.walletType != walletType)
824
- }));
825
- },
826
- initSelectedWallets: () => set(state => {
827
- const requiredChains = getRequiredChains(useBestRouteStore.getState().bestRoute);
828
- const connectedWallets = state.connectedWallets;
829
- const selectedWallets = [];
830
- requiredChains.forEach(chain => {
831
- const anyWalletSelected = !!state.selectedWallets.find(wallet => wallet.chain === chain);
832
- if (!anyWalletSelected) {
833
- const firstWalletWithMatchedChain = connectedWallets.find(wallet => wallet.chain === chain);
834
- if (!!firstWalletWithMatchedChain) selectedWallets.push({
835
- address: firstWalletWithMatchedChain.address,
836
- chain: firstWalletWithMatchedChain.chain,
837
- walletType: firstWalletWithMatchedChain.walletType
838
- });
839
- }
840
- });
841
- return {
842
- selectedWallets: state.selectedWallets.concat(selectedWallets)
843
- };
844
- }),
845
- setSelectedWallet: wallet => set(state => ({
846
- selectedWallets: state.selectedWallets.filter(selectedWallet => selectedWallet.chain !== wallet.chain).concat({
847
- chain: wallet.chain,
848
- address: wallet.address,
849
- walletType: wallet.walletType
850
- })
851
- })),
852
- clearConnectedWallet: () => set(() => ({
853
- connectedWallets: [],
854
- selectedWallets: []
855
- })),
856
- getOneOfWalletsDetails: async account => {
857
- const tokens = useMetaStore.getState().meta.tokens;
858
- set(state => ({
859
- connectedWallets: state.connectedWallets.map(balance => {
860
- return balance.address === account.address && balance.chain === account.chain ? {
861
- ...balance,
862
- loading: true
863
- } : balance;
864
- })
865
- }));
866
- try {
867
- const response = await httpService().getWalletsDetails([{
868
- address: account.address,
869
- blockchain: account.chain
870
- }]);
871
- const retrivedBalance = response.wallets[0];
872
- if (retrivedBalance) {
873
- set(state => ({
874
- connectedWallets: state.connectedWallets.map(connectedWallet => {
875
- return isAccountAndWalletMatched(account, connectedWallet) ? makeBalanceFor(account, retrivedBalance, tokens) : connectedWallet;
876
- })
877
- }));
878
- } else throw new Error('Wallet not found');
879
- } catch (error) {
880
- set(state => ({
881
- connectedWallets: state.connectedWallets.map(balance => {
882
- return isAccountAndWalletMatched(account, balance) ? resetConnectedWalletState(balance) : balance;
883
- })
884
- }));
885
- }
886
- }
887
- }))));
888
- useWalletsStore.subscribe(state => state.connectedWallets, connectedWallets => {
889
- useBestRouteStore.setState(_ref => {
890
- let {
891
- sourceTokens,
892
- destinationTokens
893
- } = _ref;
894
- const sourceTokensWithBalance = getTokensWithBalance(sourceTokens, connectedWallets);
895
- const destinationTokensWithBalance = getTokensWithBalance(destinationTokens, connectedWallets);
896
- return {
897
- sourceTokens: sortTokens(sourceTokensWithBalance),
898
- destinationTokens: sortTokens(destinationTokensWithBalance)
899
- };
900
- });
901
- }, {
902
- equalityFn: shallow
903
- });
904
- const fetchingBalanceSelector = state => !!state.connectedWallets.find(wallet => wallet.loading);
905
-
906
- const getUsdValue = (token, amount) => new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0);
907
- const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/subscribeWithSelector(set => ({
908
- fromChain: null,
909
- fromToken: null,
910
- inputAmount: '',
911
- outputAmount: null,
912
- inputUsdValue: new BigNumber(0),
913
- outputUsdValue: new BigNumber(0),
914
- toChain: null,
915
- toToken: null,
916
- bestRoute: null,
917
- loading: false,
918
- error: '',
919
- sourceTokens: [],
920
- destinationTokens: [],
921
- setBestRoute: bestRoute => set(state => {
922
- let outputAmount = null;
923
- let outputUsdValue = ZERO;
924
- if (!isPositiveNumber(state.inputAmount)) return {};
925
- if (!!bestRoute) {
926
- outputAmount = !!bestRoute.result?.outputAmount ? new BigNumber(bestRoute.result?.outputAmount) : null;
927
- outputUsdValue = calcOutputUsdValue(bestRoute.result?.outputAmount, getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice);
928
- }
929
- return {
930
- bestRoute,
931
- ...(!!bestRoute && {
932
- outputAmount,
933
- outputUsdValue
934
- })
935
- };
936
- }),
937
- resetRoute: () => set(() => ({
938
- loading: true,
939
- error: '',
940
- bestRoute: null,
941
- outputAmount: null,
942
- outputUsdValue: new BigNumber(0)
943
- })),
944
- setFromChain: (chain, setDefaultToken) => {
945
- set(state => {
946
- if (state.fromChain?.name === chain?.name) return {};
947
- const tokens = useMetaStore.getState().meta.tokens;
948
- const connectedWallets = useWalletsStore.getState().connectedWallets;
949
- const sortedTokens = getSortedTokens(chain, tokens, connectedWallets, state.destinationTokens);
950
- const fromToken = getDefaultToken(sortedTokens, state.toToken);
951
- return {
952
- fromChain: chain,
953
- sourceTokens: sortedTokens,
954
- ...(setDefaultToken && {
955
- fromToken
956
- }),
957
- ...(!!state.inputAmount && {
958
- inputUsdValue: getUsdValue(fromToken, state.inputAmount)
959
- })
960
- };
961
- });
962
- },
963
- setFromToken: token => set(state => ({
964
- fromToken: token,
965
- ...(!!state.inputAmount && {
966
- inputUsdValue: getUsdValue(token, state.inputAmount)
967
- })
968
- })),
969
- setToChain: (chain, setDefaultToken) => {
970
- set(state => {
971
- if (state.toChain?.name === chain?.name) return {};
972
- const tokens = useMetaStore.getState().meta.tokens;
973
- const connectedWallets = useWalletsStore.getState().connectedWallets;
974
- const sortedTokens = getSortedTokens(chain, tokens, connectedWallets, state.destinationTokens);
975
- return {
976
- toChain: chain,
977
- destinationTokens: sortedTokens,
978
- ...(setDefaultToken && {
979
- toToken: getDefaultToken(sortedTokens, state.fromToken)
980
- })
981
- };
982
- });
983
- },
984
- setToToken: token => set(() => ({
985
- toToken: token
986
- })),
987
- setInputAmount: amount => {
988
- set(state => ({
989
- inputAmount: amount,
990
- ...(!amount && {
991
- outputAmount: new BigNumber(0),
992
- outputUsdValue: new BigNumber(0),
993
- bestRoute: null,
994
- error: ''
995
- }),
996
- ...(!!state.fromToken && {
997
- inputUsdValue: getUsdValue(state.fromToken, amount)
998
- })
999
- }));
1000
- },
1001
- retry: pendingSwap => {
1002
- const {
1003
- tokens,
1004
- blockchains
1005
- } = useMetaStore.getState().meta;
1006
- const connectedWallets = useWalletsStore.getState().connectedWallets;
1007
- const failedIndex = pendingSwap.status === 'failed' ? pendingSwap.steps.findIndex(s => s.status === 'failed') : null;
1008
- if (failedIndex === null || failedIndex < 0) return;
1009
- const firstStep = pendingSwap.steps[0];
1010
- const lastStep = pendingSwap.steps[pendingSwap.steps.length - 1];
1011
- const fromChain = blockchains.find(blockchain => blockchain.name === firstStep.fromBlockchain) || null;
1012
- const toChain = blockchains.find(blockchain => blockchain.name === lastStep.toBlockchain) || null;
1013
- const fromToken = tokens.find(token => tokensAreEqual(token, {
1014
- blockchain: firstStep.fromBlockchain,
1015
- symbol: firstStep.fromSymbol,
1016
- address: firstStep.fromSymbolAddress
1017
- }));
1018
- const toToken = tokens.find(token => tokensAreEqual(token, {
1019
- blockchain: lastStep.toBlockchain,
1020
- symbol: lastStep.toSymbol,
1021
- address: lastStep.toSymbolAddress
1022
- }));
1023
- const sortedSourceTokens = getSortedTokens(fromChain, tokens, connectedWallets, []);
1024
- const sortedDestinationTokens = getSortedTokens(toChain, tokens, connectedWallets, []);
1025
- const inputAmount = pendingSwap.inputAmount;
1026
- set({
1027
- fromChain,
1028
- fromToken,
1029
- inputAmount,
1030
- outputAmount: null,
1031
- inputUsdValue: getUsdValue(fromToken || null, inputAmount),
1032
- outputUsdValue: new BigNumber(0),
1033
- toChain,
1034
- toToken,
1035
- bestRoute: null,
1036
- loading: false,
1037
- error: '',
1038
- sourceTokens: sortedSourceTokens,
1039
- destinationTokens: sortedDestinationTokens
1040
- });
1041
- },
1042
- switchFromAndTo: () => set(state => ({
1043
- fromChain: state.toChain,
1044
- fromToken: state.toToken,
1045
- toChain: state.fromChain,
1046
- toToken: state.fromToken,
1047
- sourceTokens: state.destinationTokens,
1048
- destinationTokens: state.sourceTokens,
1049
- inputAmount: state.outputAmount?.toString() || '',
1050
- inputUsdValue: getUsdValue(state.toToken, state.outputAmount?.toString() || '')
1051
- }))
1052
- }))));
1053
- const bestRoute = (bestRouteStore, settingsStore) => {
1054
- let abortController = null;
1055
- const fetchBestRoute = () => {
1056
- const {
1057
- fromToken,
1058
- toToken,
1059
- inputAmount,
1060
- resetRoute
1061
- } = bestRouteStore.getState();
1062
- const {
1063
- slippage,
1064
- customSlippage,
1065
- disabledLiquiditySources,
1066
- affiliateRef
1067
- } = settingsStore.getState();
1068
- if (!fromToken || !toToken || !isPositiveNumber(inputAmount)) return;
1069
- abortController?.abort();
1070
- abortController = new AbortController();
1071
- const userSlippage = !!customSlippage ? customSlippage : slippage;
1072
- const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, [], [], disabledLiquiditySources, userSlippage, affiliateRef);
1073
- if (!bestRouteStore.getState().loading) {
1074
- resetRoute();
1075
- }
1076
- httpService().getBestRoute(requestBody, {
1077
- signal: abortController.signal
1078
- }).then(res => {
1079
- const {
1080
- setBestRoute
1081
- } = bestRouteStore.getState();
1082
- setBestRoute(res);
1083
- bestRouteStore.setState({
1084
- loading: false
1085
- });
1086
- abortController = null;
1087
- }).catch(error => {
1088
- if (error.code === 'ERR_CANCELED') return;
1089
- bestRouteStore.setState({
1090
- error: error.message,
1091
- loading: false
1092
- });
1093
- });
1094
- };
1095
- const debouncedFetchBestRoute = debounce(fetchBestRoute, 600);
1096
- const bestRouteParamsListener = () => {
1097
- const {
1098
- fromToken,
1099
- toToken,
1100
- inputAmount,
1101
- inputUsdValue,
1102
- resetRoute
1103
- } = useBestRouteStore.getState();
1104
- if (!isPositiveNumber(inputAmount) || inputUsdValue.eq(0)) return bestRouteStore.setState({
1105
- loading: false
1106
- });
1107
- if (tokensAreEqual(fromToken, toToken)) return bestRouteStore.setState({
1108
- loading: false,
1109
- bestRoute: null,
1110
- outputAmount: new BigNumber(inputAmount),
1111
- outputUsdValue: inputUsdValue
1112
- });
1113
- if (!bestRouteStore.getState().loading) resetRoute();
1114
- debouncedFetchBestRoute();
1115
- };
1116
- useBestRouteStore.subscribe(state => ({
1117
- fromChain: state.fromChain,
1118
- fromToken: state.fromToken,
1119
- toChain: state.toChain,
1120
- toToken: state.toToken,
1121
- inputAmount: state.inputAmount
1122
- }), bestRouteParamsListener, {
1123
- equalityFn: (prevState, currentState) => {
1124
- if (isRouteParametersChanged({
1125
- store: 'bestRoute',
1126
- prevState,
1127
- currentState
1128
- })) return false;else return true;
1129
- }
1130
- });
1131
- useSettingsStore.subscribe(state => ({
1132
- slippage: state.slippage,
1133
- customSlippage: state.customSlippage,
1134
- disabledLiquiditySources: state.disabledLiquiditySources,
1135
- infiniteApprove: state.infiniteApprove
1136
- }), bestRouteParamsListener, {
1137
- equalityFn: (prevState, currentState) => {
1138
- if (isRouteParametersChanged({
1139
- store: 'settings',
1140
- prevState,
1141
- currentState
1142
- })) return false;else return true;
1143
- }
1144
- });
1145
- return {
1146
- fetchBestRoute
1147
- };
1148
- };
1149
- const {
1150
- fetchBestRoute
1151
- } = /*#__PURE__*/bestRoute(useBestRouteStore, useSettingsStore);
1152
-
1153
- var SearchParams;
1154
- (function (SearchParams) {
1155
- SearchParams["FROM_CHAIN"] = "fromChain";
1156
- SearchParams["FROM_TOKEN"] = "fromToken";
1157
- SearchParams["TO_CHAIN"] = "toChain";
1158
- SearchParams["TO_TOKEN"] = "toToken";
1159
- SearchParams["FROM_AMOUNT"] = "fromAmount";
1160
- })(SearchParams || (SearchParams = {}));
1161
-
1162
- const navigationRoutes = {
1163
- home: '/',
1164
- fromChain: 'from-chain',
1165
- fromToken: 'from-token',
1166
- toChain: 'to-chain',
1167
- toToken: 'to-token',
1168
- settings: 'settings',
1169
- liquiditySources: '/settings/liquidity-sources',
1170
- swaps: 'swaps',
1171
- wallets: 'wallets',
1172
- confirmSwap: 'confirm-swap',
1173
- swapDetails: 'swaps/:requestId'
1174
- };
1175
-
1176
- const useUiStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()(set => ({
1177
- connectWalletsButtonDisabled: false,
1178
- selectedSwapRequestId: null,
1179
- currentPage: '',
1180
- toggleConnectWalletsButton: () => set(state => ({
1181
- connectWalletsButtonDisabled: !state.connectWalletsButtonDisabled
1182
- })),
1183
- setSelectedSwap: requestId => set({
1184
- selectedSwapRequestId: requestId
1185
- }),
1186
- setCurrentPage: path => set({
1187
- currentPage: path
1188
- })
1189
- })));
1190
-
1191
- function UpdateUrl() {
1192
- const firstRender = useRef(true);
1193
- const [searchParams, setSearchParams] = useSearchParams();
1194
- const location = useLocation();
1195
- const firstRenderSearchParams = useRef(location.search);
1196
- const searchParamsRef = useRef({});
1197
- const fromChain = useBestRouteStore.use.fromChain();
1198
- const toChain = useBestRouteStore.use.toChain();
1199
- const fromToken = useBestRouteStore.use.fromToken();
1200
- const toToken = useBestRouteStore.use.toToken();
1201
- const setFromChain = useBestRouteStore.use.setFromChain();
1202
- const setFromToken = useBestRouteStore.use.setFromToken();
1203
- const setToChain = useBestRouteStore.use.setToChain();
1204
- const setToToken = useBestRouteStore.use.setToToken();
1205
- const inputAmount = useBestRouteStore.use.inputAmount();
1206
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1207
- const loadingStatus = useMetaStore.use.loadingStatus();
1208
- const {
1209
- blockchains,
1210
- tokens
1211
- } = useMetaStore.use.meta();
1212
- const setSelectedSwap = useUiStore.use.setSelectedSwap();
1213
- useEffect(() => {
1214
- const params = {};
1215
- createSearchParams(firstRenderSearchParams.current).forEach((value, key) => {
1216
- params[key] = value;
1217
- });
1218
- searchParamsRef.current = params;
1219
- const requestId = location.pathname.split(navigationRoutes.swaps + '/')[1] || null;
1220
- if (requestId) setSelectedSwap(requestId);
1221
- }, []);
1222
- useEffect(() => {
1223
- if (!firstRender.current) {
1224
- let fromChainString = '',
1225
- fromTokenString = '',
1226
- toChainString = '',
1227
- toTokenString = '',
1228
- fromAmount = '';
1229
- if (loadingStatus !== 'success') {
1230
- fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
1231
- fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
1232
- toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
1233
- toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];
1234
- fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT] || inputAmount;
1235
- } else {
1236
- if (location.state === 'redirect') return;
1237
- fromChainString = fromChain?.name || '';
1238
- fromTokenString = (fromToken?.symbol || '') + (fromToken?.address ? `--${fromToken?.address}` : '');
1239
- toChainString = toChain?.name || '';
1240
- toTokenString = (toToken?.symbol || '') + (toToken?.address ? `--${toToken?.address}` : '');
1241
- fromAmount = inputAmount;
1242
- }
1243
- setSearchParams({
1244
- ...(fromChainString && {
1245
- [SearchParams.FROM_CHAIN]: fromChainString
1246
- }),
1247
- ...(fromTokenString && {
1248
- [SearchParams.FROM_TOKEN]: fromTokenString
1249
- }),
1250
- ...(toChainString && {
1251
- [SearchParams.TO_CHAIN]: toChainString
1252
- }),
1253
- ...(toTokenString && {
1254
- [SearchParams.TO_TOKEN]: toTokenString
1255
- }),
1256
- ...(fromAmount && {
1257
- [SearchParams.FROM_AMOUNT]: fromAmount.toString()
1258
- })
1259
- }, {
1260
- replace: true
1261
- });
1262
- }
1263
- firstRender.current = false;
1264
- }, [location.pathname, inputAmount, fromChain, fromToken, toChain, toToken]);
1265
- useEffect(() => {
1266
- if (loadingStatus === 'success') {
1267
- const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
1268
- const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
1269
- const toChainString = searchParams.get(SearchParams.TO_CHAIN);
1270
- const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
1271
- const fromAmount = searchParams.get(SearchParams.FROM_AMOUNT);
1272
- const fromChain = blockchains.find(blockchain => blockchain.name === fromChainString);
1273
- const fromToken = searchParamsToToken(tokens, fromTokenString, fromChain || null);
1274
- const toChain = blockchains.find(blockchain => blockchain.name === toChainString);
1275
- const toToken = searchParamsToToken(tokens, toTokenString, toChain || null);
1276
- if (!!fromChain) {
1277
- setFromChain(fromChain);
1278
- if (!!fromToken) setFromToken(fromToken);
1279
- }
1280
- if (!!toChain) {
1281
- setToChain(toChain);
1282
- if (!!toToken) setToToken(toToken);
1283
- }
1284
- if (fromAmount) setInputAmount(fromAmount);
1285
- }
1286
- }, [loadingStatus]);
1287
- return null;
1288
- }
1289
-
1290
- function AppRouter(_ref) {
1291
- let {
1292
- children,
1293
- ...props
1294
- } = _ref;
1295
- const isRouterInContext = useInRouterContext();
1296
- const Router = isRouterInContext ? Fragment : MemoryRouter;
1297
- const {
1298
- blockchains
1299
- } = useMetaStore.use.meta();
1300
- const evmChains = blockchains.filter(isEvmBlockchain);
1301
- useQueueManager({
1302
- lastConnectedWallet: props.lastConnectedWallet,
1303
- clearDisconnectedWallet: props.clearDisconnectedWallet,
1304
- disconnectedWallet: props.disconnectedWallet,
1305
- evmChains,
1306
- notifier: () => {}
1307
- });
1308
- return React.createElement(React.Fragment, null, React.createElement(Router, null, children), isRouterInContext && React.createElement(UpdateUrl, null));
1309
- }
1310
-
1311
- function useNavigateBack() {
1312
- const isRouterInContext = useInRouterContext$1();
1313
- const navigate = useNavigate();
1314
- const navigateBackFrom = currentRoute => {
1315
- if (currentRoute === navigationRoutes.swapDetails) return navigate('/' + navigationRoutes.swaps, {
1316
- replace: true
1317
- });
1318
- if (!isRouterInContext || window.history.state && window.history.state.idx > 0) navigate(-1);else {
1319
- if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.swaps, navigationRoutes.confirmSwap].includes(currentRoute)) navigate(navigationRoutes.home, {
1320
- replace: true
1321
- });else if (currentRoute === navigationRoutes.liquiditySources) navigate('/' + navigationRoutes.settings, {
1322
- replace: true
1323
- });
1324
- }
1325
- };
1326
- return {
1327
- navigateBackFrom
1328
- };
1329
- }
1330
-
1331
- const Box = /*#__PURE__*/styled('div', {
1332
- display: 'flex',
1333
- flexDirection: 'column',
1334
- width: '100%',
1335
- overflow: 'hidden'
1336
- });
1337
- const Container = /*#__PURE__*/styled('div', {
1338
- boxSizing: 'border-box',
1339
- borderRadius: '$5',
1340
- padding: '$8 $16 $16 $16',
1341
- variants: {
1342
- type: {
1343
- filled: {
1344
- backgroundColor: '$neutral100'
1345
- },
1346
- outlined: {
1347
- border: '1px solid $neutral100'
1348
- }
1349
- }
1350
- },
1351
- defaultVariants: {
1352
- type: 'filled'
1353
- },
1354
- '.head': {
1355
- display: 'flex',
1356
- justifyContent: 'space-between',
1357
- alignItems: 'center',
1358
- minHeight: '32px',
1359
- '.usd-value': {
1360
- paddingLeft: '$8'
1361
- }
1362
- },
1363
- '.form': {
1364
- display: 'flex',
1365
- width: '100%',
1366
- padding: '$2 0',
1367
- '.selectors': {
1368
- width: '35%',
1369
- '._text': {
1370
- whiteSpace: 'nowrap',
1371
- overflow: 'hidden',
1372
- textOverflow: 'ellipsis'
1373
- }
1374
- },
1375
- '.amount': {
1376
- width: '30%'
1377
- }
1378
- }
1379
- });
1380
- const ImagePlaceholder = /*#__PURE__*/styled('span', {
1381
- width: '24px',
1382
- height: '24px',
1383
- backgroundColor: '$neutral100',
1384
- borderRadius: '99999px'
1385
- });
1386
- const OutputContainer = /*#__PURE__*/styled('div', {
1387
- windth: '100%',
1388
- height: '$48',
1389
- borderRadius: '$5',
1390
- backgroundColor: '$surface',
1391
- border: '1px solid transparent',
1392
- position: 'relative',
1393
- display: 'flex',
1394
- alignItems: 'center',
1395
- paddingLeft: '$8',
1396
- paddingRight: '$8'
1397
- });
1398
- function TokenPreview(props) {
1399
- const {
1400
- chain,
1401
- token,
1402
- loadingStatus,
1403
- percentageChange
1404
- } = props;
1405
- const {
1406
- t
1407
- } = useTranslation();
1408
- const ItemSuffix = React.createElement("div", {
1409
- style: {
1410
- display: 'flex',
1411
- justifyContent: 'center',
1412
- alignItems: 'center'
1413
- }
1414
- }, loadingStatus === 'failed' && React.createElement(InfoCircleIcon, {
1415
- color: "error",
1416
- size: 24
1417
- }));
1418
- return React.createElement(Box, null, React.createElement(Container, {
1419
- type: 'outlined'
1420
- }, React.createElement("div", {
1421
- className: "head"
1422
- }, React.createElement(Typography, {
1423
- variant: "body2",
1424
- color: "neutral800"
1425
- }, props.label), React.createElement("div", null, percentageChange, props.usdValue && React.createElement(Typography, {
1426
- variant: "caption",
1427
- color: "neutral600",
1428
- className: "usd-value"
1429
- }, `$${numberToString(props.usdValue)}`))), React.createElement("div", {
1430
- className: "form"
1431
- }, React.createElement(Button, {
1432
- className: "selectors",
1433
- variant: "outlined",
1434
- loading: loadingStatus === 'loading',
1435
- prefix: loadingStatus === 'success' && chain ? React.createElement(Image, {
1436
- src: chain.logo,
1437
- size: 24
1438
- }) : React.createElement(ImagePlaceholder, null),
1439
- suffix: ItemSuffix,
1440
- align: "start",
1441
- size: "large"
1442
- }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React.createElement(Spacer, {
1443
- size: 12
1444
- }), React.createElement(Button, {
1445
- className: "selectors",
1446
- variant: "outlined",
1447
- loading: loadingStatus === 'loading',
1448
- prefix: loadingStatus === 'success' && token ? React.createElement(Image, {
1449
- src: token.image,
1450
- size: 24
1451
- }) : React.createElement(ImagePlaceholder, null),
1452
- suffix: ItemSuffix,
1453
- size: "large",
1454
- align: "start"
1455
- }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React.createElement(Spacer, {
1456
- size: 12
1457
- }), React.createElement("div", {
1458
- className: "amount"
1459
- }, React.createElement(OutputContainer, null, React.createElement(Typography, {
1460
- variant: "h4"
1461
- }, props.amount))))));
1462
- }
1463
-
1464
- const Container$1 = /*#__PURE__*/styled('div', {
1465
- display: 'flex',
1466
- alignItems: 'center',
1467
- justifyContent: 'space-between',
1468
- padding: '$8',
1469
- borderRadius: '$5',
1470
- backgroundColor: '$neutral100',
1471
- color: '$neutral800',
1472
- fontSize: '$12',
1473
- '.routes': {
1474
- display: 'flex',
1475
- alignItems: 'center'
1476
- },
1477
- '.fee': {
1478
- display: 'flex',
1479
- alignItems: 'center'
1480
- }
1481
- });
1482
- function RoutesOverview(props) {
1483
- if (!props.routes) return null;
1484
- const swaps = props.routes.result?.swaps;
1485
- return React.createElement(Container$1, null, React.createElement("div", {
1486
- className: "routes"
1487
- }, swaps?.map((swap, idx) => {
1488
- const isLast = idx + 1 == swaps.length;
1489
- return React.createElement(React.Fragment, {
1490
- key: idx
1491
- }, React.createElement("div", {
1492
- className: "route"
1493
- }, swap.from.symbol), React.createElement(ChevronRightIcon, {
1494
- size: 12
1495
- }), isLast ? React.createElement("div", {
1496
- className: "route"
1497
- }, swap.to.symbol) : null);
1498
- })), props.totalFee ? React.createElement("div", {
1499
- className: "fee"
1500
- }, React.createElement(GasIcon, {
1501
- size: 12
1502
- }), React.createElement(Spacer, {
1503
- size: 4
1504
- }), "$", props.totalFee) : null);
1505
- }
1506
-
1507
- var ConfirmSwapErrorTypes;
1508
- (function (ConfirmSwapErrorTypes) {
1509
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
1510
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
1511
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
1512
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
1513
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
1514
- })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
1515
- var ConfirmSwapWarningTypes;
1516
- (function (ConfirmSwapWarningTypes) {
1517
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
1518
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
1519
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
1520
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
1521
- })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
1522
-
1523
- function useConfirmSwap() {
1524
- const fromToken = useBestRouteStore.use.fromToken();
1525
- const toToken = useBestRouteStore.use.toToken();
1526
- const inputAmount = useBestRouteStore.use.inputAmount();
1527
- const initialRoute = useBestRouteStore.use.bestRoute();
1528
- const setBestRoute = useBestRouteStore.use.setBestRoute();
1529
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1530
- const affiliateRef = useSettingsStore.use.affiliateRef();
1531
- const connectedWallets = useWalletsStore.use.connectedWallets();
1532
- const selectedWallets = useWalletsStore.use.selectedWallets();
1533
- const meta = useMetaStore.use.meta();
1534
- const customSlippage = useSettingsStore.use.customSlippage();
1535
- const slippage = useSettingsStore.use.slippage();
1536
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
1537
- const userSlippage = customSlippage || slippage;
1538
- const proceedAnywayRef = useRef(false);
1539
- const confiremedRouteRef = useRef(null);
1540
- let abortControllerRef = useRef(null);
1541
- const [loading, setLoading] = useState(false);
1542
- const [errors, setErrors] = useState([]);
1543
- const [warnings, setWarnings] = useState([]);
1544
- useEffect(() => {
1545
- return () => abortControllerRef.current?.abort();
1546
- }, []);
1547
- if (!fromToken || !toToken || !inputAmount || !initialRoute) return {
1548
- loading: false,
1549
- warnings: [],
1550
- errors: [],
1551
- confirmSwap: null
1552
- };
1553
- const confirmSwap = async () => {
1554
- if (proceedAnywayRef.current) {
1555
- const swapSettings = {
1556
- slippage: userSlippage.toString(),
1557
- disabledSwappersGroups: disabledLiquiditySources
1558
- };
1559
- if (errors.length > 0) setErrors([]);
1560
- if (warnings.length > 0) setWarnings([]);
1561
- proceedAnywayRef.current = false;
1562
- if (confiremedRouteRef.current) {
1563
- const newSwap = calculatePendingSwap(inputAmount.toString(), confiremedRouteRef.current, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
1564
- return newSwap;
1565
- }
1566
- return;
1567
- }
1568
- abortControllerRef.current = new AbortController();
1569
- setLoading(true);
1570
- const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, connectedWallets, selectedWallets, disabledLiquiditySources, userSlippage, affiliateRef, initialRoute);
1571
- try {
1572
- const confiremedRoute = await httpService().getBestRoute(requestBody, {
1573
- signal: abortControllerRef.current?.signal
1574
- });
1575
- abortControllerRef.current = null;
1576
- setLoading(false);
1577
- if (!confiremedRoute.result || !new BigNumber(confiremedRoute.requestAmount).isEqualTo(new BigNumber(inputAmount || '-1'))) {
1578
- setErrors(prevState => prevState.concat({
1579
- type: ConfirmSwapErrorTypes.NO_ROUTE
1580
- }));
1581
- return;
1582
- }
1583
- const confirmSwapState = {
1584
- errors: [],
1585
- warnings: []
1586
- };
1587
- const routeChanged = isRouteChanged(initialRoute, confiremedRoute);
1588
- if (routeChanged) {
1589
- setBestRoute(confiremedRoute);
1590
- const newRouteOutputUsdValue = new BigNumber(confiremedRoute.result?.outputAmount || '0').multipliedBy(toToken.usdPrice || 0);
1591
- const outputRatio = getOutputRatio(inputUsdValue, newRouteOutputUsdValue);
1592
- const highValueLoss = outputRatioHasWarning(inputUsdValue, outputRatio);
1593
- if (highValueLoss) confirmSwapState.errors.push({
1594
- type: ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS
1595
- });else if (isOutputAmountChangedALot(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1596
- type: ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED,
1597
- newOutputAmount: numberToString(getRouteOutputAmount(confiremedRoute)),
1598
- percentageChange: numberToString(getPercentageChange(getRouteOutputAmount(initialRoute), getRouteOutputAmount(confiremedRoute)), null, 2)
1599
- });else if (isRouteInternalCoinsUpdated(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1600
- type: ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED
1601
- });else if (isNumberOfSwapsChanged(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1602
- type: ConfirmSwapWarningTypes.ROUTE_UPDATED
1603
- });else if (isRouteSwappersUpdated(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1604
- type: ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED
1605
- });
1606
- }
1607
- const balanceWarnings = getBalanceWarnings(confiremedRoute, selectedWallets);
1608
- const enoughBalance = balanceWarnings.length === 0;
1609
- if (!enoughBalance) confirmSwapState.errors.push({
1610
- type: ConfirmSwapErrorTypes.INSUFFICIENT_BALANCE,
1611
- messages: balanceWarnings
1612
- });
1613
- const minRequiredSlippage = getMinRequiredSlippage(initialRoute);
1614
- if (!hasProperSlippage(userSlippage.toString(), minRequiredSlippage)) confirmSwapState.errors.push({
1615
- type: ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE,
1616
- minRequiredSlippage
1617
- });
1618
- const noErrors = confirmSwapState.errors.length === 0;
1619
- const noWarnings = confirmSwapState.warnings.length === 0;
1620
- if ((noErrors || !noErrors && proceedAnywayRef.current) && (noWarnings || !noWarnings && proceedAnywayRef.current)) {
1621
- const swapSettings = {
1622
- slippage: userSlippage.toString(),
1623
- disabledSwappersGroups: disabledLiquiditySources
1624
- };
1625
- const newSwap = calculatePendingSwap(inputAmount.toString(), confiremedRoute, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
1626
- return newSwap;
1627
- } else if (!proceedAnywayRef.current) {
1628
- proceedAnywayRef.current = true;
1629
- setErrors(confirmSwapState.errors);
1630
- setWarnings(confirmSwapState.warnings);
1631
- confiremedRouteRef.current = confiremedRoute;
1632
- }
1633
- return;
1634
- } catch (error) {
1635
- if (error?.code === 'ERR_CANCELED') {
1636
- return;
1637
- }
1638
- const status = error?.response?.status;
1639
- setLoading(false);
1640
- setErrors([{
1641
- type: ConfirmSwapErrorTypes.REQUEST_FAILED,
1642
- status
1643
- }]);
1644
- return;
1645
- }
1646
- };
1647
- return {
1648
- loading,
1649
- warnings,
1650
- errors,
1651
- confirmSwap
1652
- };
1653
- }
1654
-
1655
- function ChangeSlippageButton() {
1656
- const navigate = useNavigate();
1657
- return React.createElement(Button, {
1658
- type: "primary",
1659
- variant: "outlined",
1660
- size: "small",
1661
- onClick: () => navigate('/' + navigationRoutes.settings)
1662
- }, "Change Slippage");
1663
- }
1664
-
1665
- const StyledMessage = /*#__PURE__*/styled(Typography, {
1666
- color: '$error500 !important'
1667
- });
1668
- function MinRequiredSlippage(_ref) {
1669
- let {
1670
- minRequiredSlippage
1671
- } = _ref;
1672
- return React.createElement(StyledMessage, {
1673
- variant: "body2"
1674
- }, "We recommend you to increase slippage to at least \u00A0", minRequiredSlippage, "\u00A0 for this route.", React.createElement(Spacer, {
1675
- size: 8,
1676
- direction: "vertical"
1677
- }), React.createElement(ChangeSlippageButton, null));
1678
- }
1679
-
1680
- const List = /*#__PURE__*/styled('ul', {
1681
- padding: 0,
1682
- margin: 0,
1683
- variants: {
1684
- showListStyle: {
1685
- true: {
1686
- paddingLeft: '$24'
1687
- }
1688
- }
1689
- }
1690
- });
1691
- const ListItem = /*#__PURE__*/styled('li', {
1692
- variants: {
1693
- showListStyle: {
1694
- true: {
1695
- listStyleType: 'disc',
1696
- listStylePosition: 'outside'
1697
- }
1698
- }
1699
- }
1700
- });
1701
- const Message = /*#__PURE__*/styled(Typography, {
1702
- display: 'block'
1703
- });
1704
- function BalanceErrors(_ref) {
1705
- let {
1706
- messages
1707
- } = _ref;
1708
- const showListStyle = messages.length > 1;
1709
- return React.createElement(React.Fragment, null, React.createElement(Typography, {
1710
- className: "title",
1711
- variant: "title",
1712
- color: 'error'
1713
- }, "Insufficent Balance:"), React.createElement(Spacer, {
1714
- size: 8,
1715
- direction: "vertical"
1716
- }), React.createElement(List, {
1717
- showListStyle: showListStyle
1718
- }, messages.map((warning, index) => React.createElement(ListItem, {
1719
- showListStyle: showListStyle,
1720
- key: index
1721
- }, React.createElement(Message, {
1722
- variant: "body2"
1723
- }, warning)))));
1724
- }
1725
-
1726
- function ConfirmSwapErrors(errors) {
1727
- return errors.flatMap(error => {
1728
- switch (error.type) {
1729
- case ConfirmSwapErrorTypes.NO_ROUTE:
1730
- return 'No routes found. Please try again later.';
1731
- case ConfirmSwapErrorTypes.REQUEST_FAILED:
1732
- return `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`;
1733
- case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
1734
- return 'Route updated and price impact is too high, try again later!';
1735
- case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
1736
- return React.createElement(MinRequiredSlippage, {
1737
- minRequiredSlippage: error.minRequiredSlippage
1738
- });
1739
- case ConfirmSwapErrorTypes.INSUFFICIENT_BALANCE:
1740
- return React.createElement(BalanceErrors, {
1741
- messages: error.messages
1742
- });
1743
- default:
1744
- return [];
1745
- }
1746
- });
1747
- }
1748
-
1749
- function ConfirmSwapWarnings(warnings) {
1750
- return warnings.flatMap(warning => {
1751
- switch (warning.type) {
1752
- case ConfirmSwapWarningTypes.ROUTE_UPDATED:
1753
- return "Route has been updated.";
1754
- case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
1755
- return `Output amount changed to ${warning.newOutputAmount} (${warning.percentageChange}% change).`;
1756
- case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
1757
- return "Route swappers has been updated.";
1758
- case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
1759
- return "Route internal coins has been updated.";
1760
- default:
1761
- return [];
1762
- }
1763
- });
1764
- }
1765
-
1766
- function HighSlippageWarning(props) {
1767
- const {
1768
- selectedSlippage
1769
- } = props;
1770
- return React.createElement(Alert, {
1771
- type: "warning",
1772
- footer: React.createElement(ChangeSlippageButton, null)
1773
- }, "Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.");
1774
- }
1775
-
1776
- function ConfirmSwapExtraMessages(props) {
1777
- const {
1778
- selectedSlippage
1779
- } = props;
1780
- const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
1781
- return React.createElement(React.Fragment, null, highSlippage && React.createElement(HighSlippageWarning, {
1782
- selectedSlippage: selectedSlippage
1783
- }));
1784
- }
1785
-
1786
- function PercentageChange(props) {
1787
- const {
1788
- inputUsdValue,
1789
- outputUsdValue
1790
- } = props;
1791
- if (!inputUsdValue || !outputUsdValue || !outputUsdValue.gt(0)) return null;
1792
- const percentageChange = getPercentageChange(inputUsdValue.toNumber(), outputUsdValue.toNumber());
1793
- const showPercentageChange = percentageChange?.lt(0);
1794
- return React.createElement(React.Fragment, null, showPercentageChange && React.createElement(Typography, {
1795
- variant: "caption",
1796
- color: "$error500"
1797
- }, `(${numberToString(percentageChange, 0, 2)}%)`));
1798
- }
1799
-
1800
- function ConfirmSwapPage() {
1801
- const navigate = useNavigate();
1802
- const {
1803
- navigateBackFrom
1804
- } = useNavigateBack();
1805
- const bestRoute = useBestRouteStore.use.bestRoute();
1806
- const fetchingBestRoute = useBestRouteStore.use.loading();
1807
- const fetchingBestRouteError = useBestRouteStore.use.error();
1808
- const setSelectedSwap = useUiStore.use.setSelectedSwap();
1809
- const {
1810
- blockchains,
1811
- tokens
1812
- } = useMetaStore.use.meta();
1813
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
1814
- const connectedWallets = useWalletsStore.use.connectedWallets();
1815
- const selectedWallets = useWalletsStore.use.selectedWallets();
1816
- const initSelectedWallets = useWalletsStore.use.initSelectedWallets();
1817
- const setSelectedWallet = useWalletsStore.use.setSelectedWallet();
1818
- const slippage = useSettingsStore.use.slippage();
1819
- const customSlippage = useSettingsStore.use.customSlippage();
1820
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1821
- const outputUsdValue = useBestRouteStore.use.outputUsdValue();
1822
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1823
- const [dbErrorMessage, setDbErrorMessage] = useState('');
1824
- const bestRouteloadingStatus = getBestRouteStatus(fetchingBestRoute, !!fetchingBestRouteError);
1825
- const {
1826
- manager
1827
- } = useManager();
1828
- const {
1829
- loading: fetchingConfirmedRoute,
1830
- errors,
1831
- warnings,
1832
- confirmSwap
1833
- } = useConfirmSwap();
1834
- const selectedSlippage = customSlippage || slippage;
1835
- const showHighSlippageWarning = !errors.find(error => error.type === ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE);
1836
- const {
1837
- getWalletInfo,
1838
- connect
1839
- } = useWallets();
1840
- const confirmDisabled = fetchingBestRoute || !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
1841
- const firstStep = bestRoute?.result?.swaps[0];
1842
- const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
1843
- const fromAmount = numberToString(firstStep?.fromAmount, 4, 6);
1844
- const toAmount = numberToString(lastStep?.toAmount, 4, 6);
1845
- useEffect(() => {
1846
- initSelectedWallets();
1847
- }, []);
1848
- const selectableWallets = getSelectableWallets(connectedWallets, selectedWallets, getWalletInfo);
1849
- const handleConnectChain = wallet => {
1850
- const network = wallet;
1851
- getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
1852
- };
1853
- const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
1854
- return React.createElement(ConfirmSwap, {
1855
- requiredWallets: getRequiredChains(bestRoute),
1856
- selectableWallets: selectableWallets,
1857
- onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
1858
- onConfirm: async () => {
1859
- confirmSwap?.().then(async swap => {
1860
- if (swap) {
1861
- try {
1862
- await manager?.create('swap', {
1863
- swapDetails: swap
1864
- }, {
1865
- id: swap.requestId
1866
- });
1867
- setSelectedSwap(swap.requestId);
1868
- navigate('/' + navigationRoutes.swaps + `/${swap.requestId}`, {
1869
- replace: true
1870
- });
1871
- setTimeout(() => {
1872
- setInputAmount('');
1873
- }, 0);
1874
- } catch (e) {
1875
- setDbErrorMessage('Error: ' + e?.message);
1876
- }
1877
- }
1878
- });
1879
- },
1880
- onChange: wallet => setSelectedWallet(wallet),
1881
- confirmDisabled: loadingMetaStatus !== 'success' || confirmDisabled,
1882
- handleConnectChain: wallet => handleConnectChain(wallet),
1883
- isExperimentalChain: wallet => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains, wallet) : false,
1884
- previewInputs: React.createElement(React.Fragment, null, React.createElement(TokenPreview, {
1885
- chain: {
1886
- displayName: firstStep?.from.blockchain || '',
1887
- logo: firstStep?.from.blockchainLogo || ''
1888
- },
1889
- token: {
1890
- symbol: firstStep?.from.symbol || '',
1891
- image: firstStep?.from.logo || ''
1892
- },
1893
- usdValue: inputUsdValue,
1894
- amount: fromAmount,
1895
- label: t('From'),
1896
- loadingStatus: loadingMetaStatus !== 'success' ? loadingMetaStatus : bestRouteloadingStatus
1897
- }), React.createElement(Spacer, {
1898
- size: 12,
1899
- direction: "vertical"
1900
- }), React.createElement(TokenPreview, {
1901
- chain: {
1902
- displayName: lastStep?.to.blockchain || '',
1903
- logo: lastStep?.to.blockchainLogo || ''
1904
- },
1905
- token: {
1906
- symbol: lastStep?.to.symbol || '',
1907
- image: lastStep?.to.logo || ''
1908
- },
1909
- usdValue: outputUsdValue,
1910
- amount: toAmount,
1911
- label: t('To'),
1912
- loadingStatus: loadingMetaStatus !== 'success' ? loadingMetaStatus : bestRouteloadingStatus,
1913
- percentageChange: React.createElement(PercentageChange, {
1914
- inputUsdValue: inputUsdValue,
1915
- outputUsdValue: outputUsdValue
1916
- })
1917
- })),
1918
- previewRoutes: React.createElement(RoutesOverview, {
1919
- routes: bestRoute,
1920
- totalFee: numberToString(totalFeeInUsd, 0, 2)
1921
- }),
1922
- loading: fetchingConfirmedRoute,
1923
- errors: dbErrorMessage ? [dbErrorMessage, ...ConfirmSwapErrors(errors)] : ConfirmSwapErrors(errors),
1924
- warnings: ConfirmSwapWarnings(warnings),
1925
- extraMessages: React.createElement(React.Fragment, null, loadingMetaStatus === 'failed' && React.createElement(LoadingFailedAlert, null), loadingMetaStatus === 'failed' && showHighSlippageWarning && React.createElement(Spacer, {
1926
- direction: "vertical"
1927
- }), showHighSlippageWarning && React.createElement(ConfirmSwapExtraMessages, {
1928
- selectedSlippage: selectedSlippage
1929
- })),
1930
- confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!'
1931
- });
1932
- }
1933
-
1934
- const getPendingSwaps = manager => {
1935
- const result = [];
1936
- manager?.getAll().forEach((q, id) => {
1937
- const storage = q.list.getStorage();
1938
- if (storage?.swapDetails) {
1939
- result.push({
1940
- id,
1941
- swap: storage?.swapDetails
1942
- });
1943
- }
1944
- });
1945
- return result.sort((a, b) => Number(b.swap.creationTime) - Number(a.swap.creationTime));
1946
- };
1947
-
1948
- const groupSwapsByDate = swaps => {
1949
- const output = new Map([['today', {
1950
- title: 'Today',
1951
- swaps: []
1952
- }], ['week', {
1953
- title: 'This week',
1954
- swaps: []
1955
- }], ['month', {
1956
- title: 'This month',
1957
- swaps: []
1958
- }], ['year', {
1959
- title: 'This year',
1960
- swaps: []
1961
- }], ['history', {
1962
- title: 'History',
1963
- swaps: []
1964
- }]]);
1965
- const now = dayjs();
1966
- swaps.forEach(swap => {
1967
- const swapDate = dayjs(Number(swap.creationTime));
1968
- if (now.isSame(swapDate, 'day')) output.get('today')?.swaps.push(swap);else if (now.isSame(swapDate, 'week')) output.get('week')?.swaps.push(swap);else if (now.isSame(swapDate, 'month')) output.get('month')?.swaps.push(swap);else if (now.isSame(swapDate, 'year')) output.get('year')?.swaps.push(swap);else output.get('history')?.swaps.push(swap);
1969
- });
1970
- return Array.from(output.values());
1971
- };
1972
-
1973
- function HistoryPage() {
1974
- const setSelectedSwap = useUiStore.use.setSelectedSwap();
1975
- const navigate = useNavigate();
1976
- const {
1977
- navigateBackFrom
1978
- } = useNavigateBack();
1979
- const {
1980
- manager,
1981
- state
1982
- } = useManager();
1983
- const pendingSwaps = getPendingSwaps(manager).map(_ref => {
1984
- let {
1985
- swap
1986
- } = _ref;
1987
- return swap;
1988
- });
1989
- const loading = !state.loadedFromPersistor;
1990
- return React.createElement(History, {
1991
- list: pendingSwaps,
1992
- groupBy: groupSwapsByDate,
1993
- loading: loading,
1994
- onSwapClick: requestId => {
1995
- setSelectedSwap(requestId);
1996
- navigate(`${requestId}`, {
1997
- replace: true
1998
- });
1999
- },
2000
- onBack: navigateBackFrom.bind(null, navigationRoutes.swaps)
2001
- });
2002
- }
2003
-
2004
- const Box$1 = /*#__PURE__*/styled('div', {
2005
- display: 'flex',
2006
- flexDirection: 'column',
2007
- width: '100%',
2008
- overflow: 'hidden'
2009
- });
2010
- const Container$2 = /*#__PURE__*/styled('div', {
2011
- boxSizing: 'border-box',
2012
- borderRadius: '$5',
2013
- padding: '$8 $16 $16 $16',
2014
- variants: {
2015
- type: {
2016
- filled: {
2017
- backgroundColor: '$neutral100'
2018
- },
2019
- outlined: {
2020
- border: '1px solid $neutral100',
2021
- backgroundColor: '$surface'
2022
- }
2023
- }
2024
- },
2025
- defaultVariants: {
2026
- type: 'filled'
2027
- },
2028
- '.head': {
2029
- display: 'flex',
2030
- justifyContent: 'space-between',
2031
- alignItems: 'center',
2032
- minHeight: '32px'
2033
- },
2034
- '.form': {
2035
- display: 'flex',
2036
- width: '100%',
2037
- padding: '$2 0',
2038
- '.selectors': {
2039
- width: '35%',
2040
- '._text': {
2041
- whiteSpace: 'nowrap',
2042
- overflow: 'hidden',
2043
- textOverflow: 'ellipsis'
2044
- }
2045
- },
2046
- '.amount': {
2047
- width: '30%'
2048
- }
2049
- },
2050
- '.output-usd': {
2051
- display: 'flex',
2052
- div: {
2053
- display: 'flex',
2054
- paddingLeft: '$8'
2055
- }
2056
- }
2057
- });
2058
- const Options = /*#__PURE__*/styled('div', {
2059
- display: 'flex',
2060
- justifyContent: 'flex-end',
2061
- '.balance': {
2062
- display: 'flex',
2063
- alignItems: 'center'
2064
- }
2065
- });
2066
- const ImagePlaceholder$1 = /*#__PURE__*/styled('span', {
2067
- width: '24px',
2068
- height: '24px',
2069
- backgroundColor: '$neutral100',
2070
- borderRadius: '99999px'
2071
- });
2072
- const OutputContainer$1 = /*#__PURE__*/styled('div', {
2073
- windth: '100%',
2074
- height: '$48',
2075
- borderRadius: '$5',
2076
- backgroundColor: '$surface',
2077
- border: '1px solid transparent',
2078
- position: 'relative',
2079
- display: 'flex',
2080
- alignItems: 'center',
2081
- paddingLeft: '$8',
2082
- paddingRight: '$8'
2083
- });
2084
- function TokenInfo(props) {
2085
- const {
2086
- type,
2087
- chain,
2088
- token
2089
- } = props;
2090
- const loadingStatus = useMetaStore.use.loadingStatus();
2091
- const fromChain = useBestRouteStore.use.fromChain();
2092
- const toChain = useBestRouteStore.use.toChain();
2093
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
2094
- const fromToken = useBestRouteStore.use.fromToken();
2095
- const setInputAmount = useBestRouteStore.use.setInputAmount();
2096
- const bestRoute = useBestRouteStore.use.bestRoute();
2097
- const inputAmount = useBestRouteStore.use.inputAmount();
2098
- const connectedWallets = useWalletsStore.use.connectedWallets();
2099
- const fetchingBestRoute = useBestRouteStore.use.loading();
2100
- const navigate = useNavigate();
2101
- const {
2102
- t
2103
- } = useTranslation();
2104
- const tokenBalance = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(connectedWallets, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', 8) : '0';
2105
- const tokenBalanceReal = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(connectedWallets, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', getBalanceFromWallet(connectedWallets, fromChain?.name, fromToken?.symbol, fromToken?.address)?.decimal) : '0';
2106
- const ItemSuffix = React.createElement("div", {
2107
- style: {
2108
- display: 'flex',
2109
- justifyContent: 'center',
2110
- alignItems: 'center'
2111
- }
2112
- }, loadingStatus === 'failed' && React.createElement(InfoCircleIcon, {
2113
- color: "error",
2114
- size: 24
2115
- }), React.createElement(AngleDownIcon, null));
2116
- return React.createElement(Box$1, null, React.createElement(Container$2, {
2117
- type: props.type === 'From' ? 'filled' : 'outlined'
2118
- }, React.createElement("div", {
2119
- className: "head"
2120
- }, React.createElement(Typography, {
2121
- variant: "body2",
2122
- color: "neutral800"
2123
- }, t(type)), props.type === 'From' ? React.createElement(Options, null, React.createElement("div", {
2124
- className: "balance",
2125
- onClick: () => {
2126
- if (tokenBalance !== '0') setInputAmount(tokenBalanceReal.split(',').join(''));
2127
- }
2128
- }, React.createElement(Typography, {
2129
- variant: "body3",
2130
- color: "neutral600"
2131
- }, `${t('Balance')}: ${tokenBalance} ${fromToken?.symbol || ''}`), React.createElement(Spacer, {
2132
- size: 4
2133
- }), React.createElement(Button, {
2134
- type: "primary",
2135
- variant: "ghost",
2136
- size: "compact"
2137
- }, t('Max')))) : React.createElement("div", {
2138
- className: "output-usd"
2139
- }, React.createElement(PercentageChange, {
2140
- inputUsdValue: inputUsdValue,
2141
- outputUsdValue: props.outputUsdValue
2142
- }), React.createElement("div", null, React.createElement(Typography, {
2143
- variant: "caption",
2144
- color: "neutral600"
2145
- }, `$${numberToString(props.outputUsdValue)}`)))), React.createElement("div", {
2146
- className: "form"
2147
- }, React.createElement(Button, {
2148
- className: "selectors",
2149
- onClick: () => {
2150
- navigate(`${props.type.toLowerCase()}-chain`);
2151
- },
2152
- variant: "outlined",
2153
- disabled: loadingStatus === 'failed',
2154
- loading: loadingStatus === 'loading',
2155
- prefix: loadingStatus === 'success' && chain ? React.createElement(Image, {
2156
- src: chain.logo,
2157
- size: 24
2158
- }) : React.createElement(ImagePlaceholder$1, null),
2159
- suffix: ItemSuffix,
2160
- align: "start",
2161
- size: "large"
2162
- }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React.createElement(Spacer, {
2163
- size: 12
2164
- }), React.createElement(Button, {
2165
- className: "selectors",
2166
- onClick: () => {
2167
- navigate(`${props.type.toLowerCase()}-token`);
2168
- },
2169
- variant: "outlined",
2170
- disabled: loadingStatus === 'failed' || type === 'From' && !fromChain || type === 'To' && !toChain,
2171
- loading: loadingStatus === 'loading',
2172
- prefix: loadingStatus === 'success' && token ? React.createElement(Image, {
2173
- src: token.image,
2174
- size: 24
2175
- }) : React.createElement(ImagePlaceholder$1, null),
2176
- suffix: ItemSuffix,
2177
- size: "large",
2178
- align: "start"
2179
- }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React.createElement(Spacer, {
2180
- size: 12
2181
- }), React.createElement("div", {
2182
- className: "amount"
2183
- }, props.type === 'From' ? React.createElement(TextField, {
2184
- type: "number",
2185
- size: "large",
2186
- autoFocus: true,
2187
- placeholder: "0",
2188
- style: {
2189
- position: 'relative',
2190
- backgroundColor: '$background !important'
2191
- },
2192
- suffix: React.createElement("span", {
2193
- style: {
2194
- position: 'absolute',
2195
- right: '4px',
2196
- bottom: '2px'
2197
- }
2198
- }, React.createElement(Typography, {
2199
- variant: "caption",
2200
- color: "neutral800"
2201
- }, `$${numberToString(inputUsdValue)}`)),
2202
- value: props.inputAmount || '',
2203
- min: 0,
2204
- onChange: props.type === 'From' ? event => {
2205
- props.onAmountChange(event.target.value);
2206
- } : undefined
2207
- }) : React.createElement(OutputContainer$1, null, React.createElement(Typography, {
2208
- variant: "h4"
2209
- }, fetchingBestRoute && '?', !!bestRoute?.result && `≈ ${numberToString(props.outputAmount)}`, (!inputAmount || inputAmount === '0') && '0'))))));
2210
- }
2211
-
2212
- const Container$3 = /*#__PURE__*/styled$1('div', {
2213
- display: 'flex',
2214
- width: '100%',
2215
- justifyContent: 'end',
2216
- alignItems: 'center',
2217
- paddingTop: '$16'
2218
- });
2219
- const Logo = /*#__PURE__*/styled$1('svg', {
2220
- fill: '$foreground',
2221
- width: '$24',
2222
- margin: '0 $8 0 $16'
2223
- });
2224
- const StyledAnchor = /*#__PURE__*/styled$1('a', {
2225
- display: 'flex',
2226
- justifyContent: 'center',
2227
- alignItems: 'center',
2228
- textDecoration: 'none'
2229
- });
2230
- function BottomLogo() {
2231
- const {
2232
- t
2233
- } = useTranslation();
2234
- return React.createElement(Container$3, null, React.createElement(Typography, {
2235
- variant: "caption",
2236
- color: "$neutral600"
2237
- }, t('Powered By')), React.createElement(StyledAnchor, {
2238
- href: "https://rango.exchange",
2239
- target: "_blank"
2240
- }, React.createElement(Logo, {
2241
- xmlns: "http://www.w3.org/2000/svg",
2242
- viewBox: "0 0 33.68 29"
2243
- }, React.createElement("defs", null), React.createElement("g", {
2244
- id: "Layer_2",
2245
- "data-name": "Layer 2"
2246
- }, React.createElement("g", {
2247
- id: "Layer_1-2",
2248
- "data-name": "Layer 1"
2249
- }, React.createElement("path", {
2250
- 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"
2251
- }), React.createElement("path", {
2252
- 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"
2253
- })))), React.createElement(Typography, {
2254
- variant: "body2"
2255
- }, "RANGO")));
2256
- }
2257
-
2258
- function SwithFromAndTo(_ref) {
2259
- let {
2260
- count
2261
- } = _ref;
2262
- const firstRender = useRef(true);
2263
- const [searchParams, setSearchParams] = useSearchParams();
2264
- const outputAmount = useBestRouteStore.use.outputAmount();
2265
- useEffect(() => {
2266
- if (!firstRender.current) {
2267
- const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
2268
- const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
2269
- const toChainString = searchParams.get(SearchParams.TO_CHAIN);
2270
- const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
2271
- setSearchParams({
2272
- ...(toChainString && {
2273
- [SearchParams.FROM_CHAIN]: toChainString
2274
- }),
2275
- ...(toTokenString && {
2276
- [SearchParams.FROM_TOKEN]: toTokenString
2277
- }),
2278
- ...(fromChainString && {
2279
- [SearchParams.TO_CHAIN]: fromChainString
2280
- }),
2281
- ...(fromTokenString && {
2282
- [SearchParams.TO_TOKEN]: fromTokenString
2283
- }),
2284
- ...(outputAmount && {
2285
- [SearchParams.FROM_AMOUNT]: outputAmount.toString()
2286
- })
2287
- });
2288
- } else {
2289
- firstRender.current = false;
2290
- }
2291
- }, [count]);
2292
- return null;
2293
- }
2294
-
2295
- const Footer = /*#__PURE__*/styled('div', {
2296
- display: 'flex',
2297
- flexDirection: 'column',
2298
- width: '100%',
2299
- paddingTop: '$16'
2300
- });
2301
-
2302
- const errorMessages = {
2303
- genericServerError: 'Error connecting server, please reload the app and try again'
2304
- };
2305
-
2306
- const ButtonsContainer = /*#__PURE__*/styled('div', {
2307
- display: 'flex'
2308
- });
2309
- function HeaderButtons(props) {
2310
- const {
2311
- onClickRefresh
2312
- } = props;
2313
- const navigate = useNavigate();
2314
- return React.createElement(ButtonsContainer, null, React.createElement(Tooltip, {
2315
- content: "Refresh"
2316
- }, React.createElement(Button, {
2317
- variant: "ghost",
2318
- onClick: onClickRefresh,
2319
- disabled: !onClickRefresh
2320
- }, React.createElement(RetryIcon, {
2321
- size: 24,
2322
- disabled: !onClickRefresh
2323
- }))), React.createElement(Tooltip, {
2324
- content: "Transactions History"
2325
- }, React.createElement(Button, {
2326
- variant: "ghost",
2327
- onClick: () => navigate(navigationRoutes.swaps)
2328
- }, React.createElement(HistoryIcon, {
2329
- size: 24
2330
- }))), React.createElement(Tooltip, {
2331
- content: "Settings"
2332
- }, React.createElement(Button, {
2333
- variant: "ghost",
2334
- onClick: () => navigate(navigationRoutes.settings)
2335
- }, React.createElement(SettingsIcon, {
2336
- size: 24
2337
- }))));
2338
- }
2339
-
2340
- const Container$4 = /*#__PURE__*/styled('div', {
2341
- display: 'flex',
2342
- flexDirection: 'column'
2343
- });
2344
- const FromContainer = /*#__PURE__*/styled('div', {
2345
- position: 'relative',
2346
- paddingBottom: '$12'
2347
- });
2348
- const SwitchButtonContainer = /*#__PURE__*/styled('div', {
2349
- position: 'absolute',
2350
- bottom: '-12px',
2351
- left: '50%',
2352
- transform: 'translate(-50%, 10%)'
2353
- });
2354
- const BestRouteContainer = /*#__PURE__*/styled('div', {
2355
- width: '100%',
2356
- paddingTop: '$16'
2357
- });
2358
- const Alerts = /*#__PURE__*/styled('div', {
2359
- width: '100%',
2360
- paddingTop: '$16'
2361
- });
2362
- function Home() {
2363
- const isRouterInContext = useInRouterContext$1();
2364
- const navigate = useNavigate();
2365
- const [count, setCount] = useState(0);
2366
- const fromChain = useBestRouteStore.use.fromChain();
2367
- const fromToken = useBestRouteStore.use.fromToken();
2368
- const toChain = useBestRouteStore.use.toChain();
2369
- const toToken = useBestRouteStore.use.toToken();
2370
- const setInputAmount = useBestRouteStore.use.setInputAmount();
2371
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
2372
- const inputAmount = useBestRouteStore.use.inputAmount();
2373
- const outputAmount = useBestRouteStore.use.outputAmount();
2374
- const outputUsdValue = useBestRouteStore.use.outputUsdValue();
2375
- const bestRoute = useBestRouteStore.use.bestRoute();
2376
- const tokens = useMetaStore.use.meta().tokens;
2377
- const fetchingBestRoute = useBestRouteStore.use.loading();
2378
- const bestRouteError = useBestRouteStore.use.error();
2379
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
2380
- const connectedWallets = useWalletsStore.use.connectedWallets();
2381
- const setCurrentPage = useUiStore.use.setCurrentPage();
2382
- const switchFromAndTo = useBestRouteStore.use.switchFromAndTo();
2383
- const errorMessage = loadingMetaStatus === 'failed' ? errorMessages.genericServerError : bestRouteError;
2384
- const needsToWarnEthOnPath = false;
2385
- const showBestRoute = inputAmount && (!!bestRoute || fetchingBestRoute || bestRouteError);
2386
- const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);
2387
- const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);
2388
- const {
2389
- fromAmountRangeError,
2390
- recommendation,
2391
- swap
2392
- } = LimitErrorMessage(bestRoute);
2393
- const priceImpactCanNotBeComputed = !canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue);
2394
- const swapButtonState = getSwapButtonState(loadingMetaStatus, connectedWallets, fetchingBestRoute, bestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath, inputAmount);
2395
- const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
2396
- const highFee = hasHighFee(totalFeeInUsd);
2397
- useEffect(() => {
2398
- setCurrentPage(navigationRoutes.home);
2399
- return setCurrentPage.bind(null, '');
2400
- }, []);
2401
- return React.createElement(Container$4, null, React.createElement(Header$1, {
2402
- title: "SWAP",
2403
- suffix: React.createElement(HeaderButtons, {
2404
- onClickRefresh: !!bestRoute || bestRouteError ? fetchBestRoute : undefined
2405
- })
2406
- }), React.createElement(FromContainer, null, React.createElement(TokenInfo, {
2407
- type: "From",
2408
- chain: fromChain,
2409
- token: fromToken,
2410
- onAmountChange: setInputAmount,
2411
- inputAmount: inputAmount
2412
- }), React.createElement(SwitchButtonContainer, null, React.createElement(Button, {
2413
- variant: "ghost",
2414
- onClick: () => {
2415
- switchFromAndTo();
2416
- setCount(prev => prev + 1);
2417
- }
2418
- }, React.createElement(VerticalSwapIcon, {
2419
- size: 32
2420
- }), isRouterInContext && React.createElement(SwithFromAndTo, {
2421
- count: count
2422
- })))), React.createElement(TokenInfo, {
2423
- type: "To",
2424
- chain: toChain,
2425
- token: toToken,
2426
- outputAmount: outputAmount ? new BigNumber(outputAmount) : new BigNumber(0),
2427
- outputUsdValue: outputUsdValue
2428
- }), showBestRoute && React.createElement(BestRouteContainer, null, React.createElement(BestRoute, {
2429
- error: bestRouteError,
2430
- loading: fetchingBestRoute,
2431
- data: getFormatedBestRoute(bestRoute),
2432
- totalFee: numberToString(totalFeeInUsd, 0, 2),
2433
- feeWarning: highFee,
2434
- totalTime: secondsToString(totalArrivalTime(bestRoute))
2435
- })), (errorMessage || hasLimitError(bestRoute)) && React.createElement(Alerts, null, errorMessage && React.createElement(Alert, {
2436
- type: "error"
2437
- }, errorMessage), hasLimitError(bestRoute) && React.createElement(Alert, {
2438
- type: "error",
2439
- title: `${swap?.swapperId} Limit`
2440
- }, React.createElement(React.Fragment, null, React.createElement(Typography, {
2441
- variant: "body2"
2442
- }, `${fromAmountRangeError}, Yours: ${numberToString(swap?.fromAmount || null)} ${swap?.from.symbol}`), React.createElement(Typography, {
2443
- variant: "body2"
2444
- }, recommendation)))), React.createElement(Footer, null, React.createElement(Button, {
2445
- type: "primary",
2446
- align: "grow",
2447
- size: "large",
2448
- disabled: swapButtonState.disabled,
2449
- onClick: () => {
2450
- if (swapButtonState.title === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
2451
- navigate(navigationRoutes.confirmSwap, {
2452
- replace: true
2453
- });
2454
- }
2455
- }
2456
- }, swapButtonState.title), React.createElement(BottomLogo, null)));
2457
- }
2458
-
2459
- function LiquiditySourcePage(_ref) {
2460
- let {
2461
- supportedSwappers
2462
- } = _ref;
2463
- const swappers = useMetaStore.use.meta().swappers;
2464
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
2465
- const toggleLiquiditySource = useSettingsStore.use.toggleLiquiditySource();
2466
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2467
- const toggleAllLiquiditySources = useSettingsStore.use.toggleAllLiquiditySources();
2468
- const {
2469
- navigateBackFrom
2470
- } = useNavigateBack();
2471
- const uniqueSwappersGroups = [];
2472
- removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2473
- return swappers.find(s => s.swapperGroup === swapperGroup);
2474
- }).find(s => {
2475
- if (s) {
2476
- for (const type of s.types) {
2477
- uniqueSwappersGroups.push({
2478
- title: s.swapperGroup,
2479
- logo: s.logo,
2480
- type,
2481
- selected: !disabledLiquiditySources.includes(s.swapperGroup)
2482
- });
2483
- }
2484
- }
2485
- });
2486
- return React.createElement(LiquiditySourcesSelector, {
2487
- toggleAll: toggleAllLiquiditySources,
2488
- list: supportedSwappers ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s === item.title).length > 0) : uniqueSwappersGroups,
2489
- onChange: liquiditySource => toggleLiquiditySource(liquiditySource.title),
2490
- onBack: navigateBackFrom.bind(null, navigationRoutes.liquiditySources),
2491
- loadingStatus: loadingMetaStatus
2492
- });
2493
- }
2494
-
2495
- function SelectChainPage(props) {
2496
- const {
2497
- type,
2498
- supportedChains
2499
- } = props;
2500
- const blockchains = supportedChains ? useMetaStore.use.meta().blockchains.filter(chain => supportedChains.includes(chain.name)) : useMetaStore.use.meta().blockchains;
2501
- const loadingStatus = useMetaStore.use.loadingStatus();
2502
- const fromChain = useBestRouteStore.use.fromChain();
2503
- const toChain = useBestRouteStore.use.toChain();
2504
- const setFromChain = useBestRouteStore.use.setFromChain();
2505
- const setToChain = useBestRouteStore.use.setToChain();
2506
- const {
2507
- navigateBackFrom
2508
- } = useNavigateBack();
2509
- return React.createElement(BlockchainSelector, {
2510
- type: type === 'from' ? 'Source' : 'Destination',
2511
- list: blockchains,
2512
- selected: type === 'from' ? fromChain : toChain,
2513
- loadingStatus: loadingStatus,
2514
- onChange: chain => {
2515
- if (type === 'from') setFromChain(chain, true);else setToChain(chain, true);
2516
- navigateBackFrom(navigationRoutes.fromChain);
2517
- },
2518
- onBack: navigateBackFrom.bind(null, navigationRoutes.fromChain)
2519
- });
2520
- }
2521
-
2522
- function SelectTokenPage(props) {
2523
- const {
2524
- navigateBackFrom
2525
- } = useNavigateBack();
2526
- const {
2527
- type,
2528
- supportedTokens
2529
- } = props;
2530
- const sourceTokens = useBestRouteStore.use.sourceTokens();
2531
- const destinationTokens = useBestRouteStore.use.destinationTokens();
2532
- const supportedSourceTokens = supportedTokens ? sourceTokens.filter(token => supportedTokens.some(supportedToken => tokensAreEqual(supportedToken, token))) : sourceTokens;
2533
- const supportedDestinationTokens = supportedTokens ? destinationTokens.filter(token => supportedTokens.some(supportedToken => tokensAreEqual(supportedToken, token))) : destinationTokens;
2534
- const fromToken = useBestRouteStore.use.fromToken();
2535
- const toToken = useBestRouteStore.use.toToken();
2536
- const setFromToken = useBestRouteStore.use.setFromToken();
2537
- const setToToken = useBestRouteStore.use.setToToken();
2538
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
2539
- return React.createElement(TokenSelector, {
2540
- type: type === 'from' ? 'Source' : 'Destination',
2541
- list: type == 'from' ? supportedSourceTokens : supportedDestinationTokens,
2542
- selected: type === 'from' ? fromToken : toToken,
2543
- onChange: token => {
2544
- if (type === 'from') setFromToken(token);else setToToken(token);
2545
- navigateBackFrom(navigationRoutes.fromToken);
2546
- },
2547
- onBack: navigateBackFrom.bind(null, navigationRoutes.fromToken),
2548
- loadingStatus: loadingMetaStatus
2549
- });
2550
- }
2551
-
2552
- function SettingsPage(_ref) {
2553
- let {
2554
- supportedSwappers,
2555
- singleTheme
2556
- } = _ref;
2557
- const slippage = useSettingsStore.use.slippage();
2558
- const setSlippage = useSettingsStore.use.setSlippage();
2559
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2560
- const customSlippage = useSettingsStore.use.customSlippage();
2561
- const setCustomSlippage = useSettingsStore.use.setCustomSlippage();
2562
- const theme = useSettingsStore.use.theme();
2563
- const setTheme = useSettingsStore.use.setTheme();
2564
- const swappers = useMetaStore.use.meta().swappers;
2565
- const navigate = useNavigate();
2566
- const {
2567
- navigateBackFrom
2568
- } = useNavigateBack();
2569
- const infiniteApprove = useSettingsStore.use.infiniteApprove();
2570
- const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();
2571
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
2572
- const uniqueSwappersGroups = [];
2573
- removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2574
- return swappers.find(s => s.swapperGroup === swapperGroup);
2575
- }).find(s => {
2576
- if (s) {
2577
- for (const type of s.types) {
2578
- uniqueSwappersGroups.push({
2579
- title: s.swapperGroup,
2580
- logo: s.logo,
2581
- type,
2582
- selected: !disabledLiquiditySources.includes(s.swapperGroup)
2583
- });
2584
- }
2585
- }
2586
- });
2587
- supportedSwappers && uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s === item.title).length > 0);
2588
- const supportedUniqueSwappersGroups = supportedSwappers ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s === item.title).length > 0) : uniqueSwappersGroups;
2589
- return React.createElement(Settings, {
2590
- slippages: SLIPPAGES,
2591
- selectedSlippage: slippage,
2592
- onSlippageChange: slippage => setSlippage(slippage),
2593
- onLiquiditySourcesClick: () => navigate(navigationRoutes.liquiditySources),
2594
- onBack: navigateBackFrom.bind(null, navigationRoutes.settings),
2595
- liquiditySources: supportedUniqueSwappersGroups,
2596
- selectedLiquiditySources: supportedUniqueSwappersGroups.filter(s => s.selected),
2597
- singleTheme: singleTheme,
2598
- customSlippage: customSlippage,
2599
- onCustomSlippageChange: setCustomSlippage,
2600
- minSlippage: MIN_SLIPPGAE,
2601
- maxSlippage: MAX_SLIPPAGE,
2602
- selectedTheme: theme,
2603
- onThemeChange: setTheme,
2604
- infiniteApprove: infiniteApprove,
2605
- toggleInfiniteApprove: toggleInfiniteApprove,
2606
- loadingStatus: loadingMetaStatus
2607
- });
2608
- }
2609
-
2610
- const ListContainer = /*#__PURE__*/styled('div', {
2611
- display: 'grid',
2612
- gap: '.5rem',
2613
- gridTemplateColumns: ' repeat(2, minmax(0, 1fr))',
2614
- alignContent: 'baseline',
2615
- padding: '0.5rem',
2616
- overflowY: 'auto'
2617
- });
2618
- const LoaderContainer = /*#__PURE__*/styled('div', {
2619
- display: 'flex',
2620
- justifyContent: 'center',
2621
- width: '100%',
2622
- position: 'absolute',
2623
- top: '50%'
2624
- });
2625
- const AlertContainer = /*#__PURE__*/styled('div', {
2626
- paddingBottom: '$16'
2627
- });
2628
- function WalletsPage(_ref) {
2629
- let {
2630
- supportedWallets,
2631
- multiWallets
2632
- } = _ref;
2633
- const {
2634
- navigateBackFrom
2635
- } = useNavigateBack();
2636
- const {
2637
- state,
2638
- disconnect,
2639
- getWalletInfo,
2640
- connect
2641
- } = useWallets();
2642
- const wallets = getlistWallet(state, getWalletInfo, supportedWallets || Object.values(WalletType));
2643
- const walletsRef = useRef();
2644
- let sortedWallets = detectMobileScreens() ? wallets.filter(wallet => wallet.showOnMobile) : wallets;
2645
- sortedWallets = sortWalletsBasedOnState(sortedWallets);
2646
- const [walletErrorMessage, setWalletErrorMessage] = useState('');
2647
- const toggleConnectWalletsButton = useUiStore.use.toggleConnectWalletsButton();
2648
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
2649
- const {
2650
- t
2651
- } = useTranslation();
2652
- const onSelectWallet = async type => {
2653
- const wallet = state(type);
2654
- try {
2655
- if (walletErrorMessage) setWalletErrorMessage('');
2656
- if (wallet.connected) {
2657
- await disconnect(type);
2658
- } else {
2659
- if (!multiWallets && !!wallets.find(w => w.state === WalletState.CONNECTED)) {
2660
- return;
2661
- }
2662
- await connect(type);
2663
- }
2664
- } catch (e) {
2665
- setWalletErrorMessage('Error: ' + e?.message);
2666
- }
2667
- };
2668
- const disconnectConnectingWallets = () => {
2669
- const connectingWallets = walletsRef.current?.filter(wallet => wallet.state === WalletState.CONNECTING) || [];
2670
- for (const wallet of connectingWallets) {
2671
- disconnect(wallet.type);
2672
- }
2673
- };
2674
- useEffect(() => {
2675
- toggleConnectWalletsButton();
2676
- return () => {
2677
- disconnectConnectingWallets();
2678
- toggleConnectWalletsButton();
2679
- };
2680
- }, []);
2681
- useEffect(() => {
2682
- walletsRef.current = wallets;
2683
- }, [wallets]);
2684
- return React.createElement(SecondaryPage, {
2685
- title: t('Select Wallet') || '',
2686
- textField: false,
2687
- onBack: navigateBackFrom.bind(null, navigationRoutes.wallets)
2688
- }, React.createElement(React.Fragment, null, walletErrorMessage && React.createElement(AlertContainer, null, React.createElement(Alert, {
2689
- type: "error",
2690
- title: walletErrorMessage
2691
- })), loadingMetaStatus === 'loading' && React.createElement(LoaderContainer, {
2692
- className: "loader"
2693
- }, React.createElement(Spinner, {
2694
- size: 24
2695
- })), loadingMetaStatus === 'failed' && React.createElement(LoadingFailedAlert, null), React.createElement(ListContainer, null, loadingMetaStatus === 'success' && sortedWallets.map((wallet, index) => React.createElement(Wallet, Object.assign({}, wallet, {
2696
- key: `${index}-${wallet.type}`,
2697
- onClick: onSelectWallet
2698
- }))))));
2699
- }
2700
-
2701
- function timeSince(timeMillis) {
2702
- const seconds = Math.floor((new Date().getTime() - timeMillis) / 1000);
2703
- let intervalType;
2704
- let interval = Math.floor(seconds / 31536000);
2705
- if (interval >= 1) {
2706
- intervalType = 'year';
2707
- } else {
2708
- interval = Math.floor(seconds / 2592000);
2709
- if (interval >= 1) {
2710
- intervalType = 'month';
2711
- } else {
2712
- interval = Math.floor(seconds / 86400);
2713
- if (interval >= 1) {
2714
- intervalType = 'day';
2715
- } else {
2716
- interval = Math.floor(seconds / 3600);
2717
- if (interval >= 1) {
2718
- intervalType = 'hour';
2719
- } else {
2720
- interval = Math.floor(seconds / 60);
2721
- if (interval >= 1) {
2722
- intervalType = 'minute';
2723
- } else {
2724
- interval = seconds;
2725
- intervalType = 'second';
2726
- }
2727
- }
2728
- }
2729
- }
2730
- }
2731
- if (interval > 1 || interval === 0) {
2732
- intervalType += 's';
2733
- }
2734
- return interval + ' ' + intervalType;
2735
- }
2736
- function getSwapDate(pendingSwap) {
2737
- return pendingSwap.finishTime ? `${timeSince(parseInt(pendingSwap.finishTime))} ago` : `${timeSince(parseInt(pendingSwap.creationTime))} ago`;
2738
- }
2739
-
2740
- const PlaceholderContainer = /*#__PURE__*/styled('div', {
2741
- height: '450px'
2742
- });
2743
- const LoaderContainer$1 = /*#__PURE__*/styled('div', {
2744
- display: 'flex',
2745
- justifyContent: 'center',
2746
- width: '100%',
2747
- paddingTop: '33%',
2748
- flex: 1
2749
- });
2750
- function SwapDetailsPlaceholder(props) {
2751
- const {
2752
- requestId,
2753
- loading,
2754
- onBack
2755
- } = props;
2756
- return React.createElement(SecondaryPage, {
2757
- title: "Swap Details",
2758
- textField: false,
2759
- onBack: onBack
2760
- }, React.createElement(PlaceholderContainer, null, loading ? React.createElement(LoaderContainer$1, null, React.createElement(Spinner, {
2761
- size: 24
2762
- })) : React.createElement(Alert, {
2763
- type: "secondary",
2764
- title: `Swap with request ID = ${requestId} not found.`
2765
- })));
2766
- }
2767
-
2768
- function SwapDetailsPage() {
2769
- const selectedSwapRequestId = useUiStore.use.selectedSwapRequestId();
2770
- const {
2771
- canSwitchNetworkTo,
2772
- connect
2773
- } = useWallets();
2774
- const retry = useBestRouteStore.use.retry();
2775
- const navigate = useNavigate();
2776
- const {
2777
- navigateBackFrom
2778
- } = useNavigateBack();
2779
- const [isCopied, handleCopy] = useCopyToClipboard(2000);
2780
- const {
2781
- manager,
2782
- state
2783
- } = useManager();
2784
- const pendingSwaps = getPendingSwaps(manager);
2785
- const selectedSwap = pendingSwaps.find(_ref => {
2786
- let {
2787
- swap
2788
- } = _ref;
2789
- return swap.requestId === selectedSwapRequestId;
2790
- });
2791
- const onCancel = () => {
2792
- const swap = manager?.get(selectedSwap?.id);
2793
- if (swap) cancelSwap(swap);
2794
- };
2795
- const swap = selectedSwap?.swap;
2796
- const loading = !state.loadedFromPersistor;
2797
- if (!swap) return React.createElement(SwapDetailsPlaceholder, {
2798
- requestId: selectedSwapRequestId || '',
2799
- loading: loading,
2800
- onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails)
2801
- });
2802
- const currentStep = getCurrentStep(swap);
2803
- const currentStepBlockchain = currentStep ? getCurrentBlockchainOfOrNull(swap, currentStep) : null;
2804
- const currentStepWallet = currentStep ? getRelatedWalletOrNull(swap, currentStep) : null;
2805
- const currentStepNetworkStatus = currentStep?.networkStatus;
2806
- const swapMessages = getSwapMessages(swap, currentStep);
2807
- const networkWarningState = isNetworkStatusInWarningState(currentStep);
2808
- const swapDate = getSwapDate(swap);
2809
- const shouldRetry = shouldRetrySwap(swap);
2810
- const switchNetwork = !!currentStepBlockchain && !!currentStepWallet?.walletType && currentStepNetworkStatus === PendingSwapNetworkStatus.WaitingForNetworkChange && canSwitchNetworkTo(currentStepWallet?.walletType, currentStepBlockchain) ? connect.bind(null, currentStepWallet.walletType, currentStepBlockchain) : undefined;
2811
- const lastConvertedTokenInFailedSwap = getLastConvertedTokenInFailedSwap(swap);
2812
- return React.createElement(SwapHistory, Object.assign({
2813
- onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),
2814
- /* TODO: It was temporarily removed to find a better solution*/
2815
- /*
2816
- previewInputs={
2817
- <>
2818
- <TokenPreview
2819
- chain={{
2820
- displayName: firstStep?.fromBlockchain || '',
2821
- logo: firstStep?.fromBlockchainLogo || '',
2822
- }}
2823
- token={{
2824
- symbol: firstStep?.fromSymbol || '',
2825
- image: firstStep?.fromLogo || '',
2826
- }}
2827
- amount={fromAmount}
2828
- label={t('From')}
2829
- loadingStatus={'success'}
2830
- />
2831
- <Spacer size={12} direction="vertical" />
2832
- <TokenPreview
2833
- chain={{
2834
- displayName: lastStep?.toBlockchain || '',
2835
- logo: lastStep?.toBlockchainLogo || '',
2836
- }}
2837
- token={{
2838
- symbol: lastStep?.toSymbol || '',
2839
- image: lastStep?.toLogo || '',
2840
- }}
2841
- amount={toAmount}
2842
- label={t('To')}
2843
- loadingStatus={'success'}
2844
- />
2845
- </>
2846
- }
2847
- */
2848
- pendingSwap: getFormatedPendingSwap(swap),
2849
- onCopy: handleCopy,
2850
- isCopied: isCopied,
2851
- onCancel: onCancel,
2852
- shortMessage: swapMessages.shortMessage,
2853
- detailedMessage: swapMessages.detailedMessage,
2854
- currentStepBlockchain: currentStepBlockchain || '',
2855
- switchNetwork: switchNetwork,
2856
- type: networkWarningState ? 'warning' : swap.extraMessageSeverity || undefined,
2857
- date: swapDate
2858
- }, shouldRetry && {
2859
- onRetry: () => {
2860
- retry(swap);
2861
- setTimeout(() => {
2862
- navigate(navigationRoutes.home);
2863
- }, 0);
2864
- }
2865
- }, lastConvertedTokenInFailedSwap && {
2866
- lastConvertedTokenInFailedSwap: {
2867
- blockchain: lastConvertedTokenInFailedSwap.blockchain,
2868
- outputAmount: lastConvertedTokenInFailedSwap.outputAmount || '',
2869
- symbol: lastConvertedTokenInFailedSwap.symbol
2870
- }
2871
- }));
2872
- }
2873
-
2874
- const getAbsolutePath = path => path.replace('/', '');
2875
- function AppRoutes(props) {
2876
- const {
2877
- config
2878
- } = props;
2879
- return useRoutes([{
2880
- path: navigationRoutes.home,
2881
- element: React.createElement(Home, null)
2882
- }, {
2883
- path: navigationRoutes.fromChain,
2884
- element: React.createElement(SelectChainPage, {
2885
- type: "from",
2886
- supportedChains: config?.from?.blockchains
2887
- })
2888
- }, {
2889
- path: navigationRoutes.toChain,
2890
- element: React.createElement(SelectChainPage, {
2891
- type: "to",
2892
- supportedChains: config?.to?.blockchains
2893
- })
2894
- }, {
2895
- path: navigationRoutes.fromToken,
2896
- element: React.createElement(SelectTokenPage, {
2897
- type: "from",
2898
- supportedTokens: config?.from?.tokens
2899
- })
2900
- }, {
2901
- path: navigationRoutes.toToken,
2902
- element: React.createElement(SelectTokenPage, {
2903
- type: "to",
2904
- supportedTokens: config?.to?.tokens
2905
- })
2906
- }, {
2907
- path: navigationRoutes.settings,
2908
- element: React.createElement(SettingsPage, {
2909
- singleTheme: config?.theme?.singleTheme,
2910
- supportedSwappers: config?.liquiditySources
2911
- })
2912
- }, {
2913
- path: navigationRoutes.liquiditySources,
2914
- element: React.createElement(LiquiditySourcePage, {
2915
- supportedSwappers: config?.liquiditySources
2916
- })
2917
- }, {
2918
- path: navigationRoutes.swaps,
2919
- element: React.createElement(HistoryPage, null)
2920
- }, {
2921
- path: navigationRoutes.swapDetails,
2922
- element: React.createElement(SwapDetailsPage, null)
2923
- }, {
2924
- path: navigationRoutes.wallets,
2925
- element: React.createElement(WalletsPage, {
2926
- supportedWallets: config?.wallets,
2927
- multiWallets: typeof config?.multiWallets === 'undefined' ? true : config.multiWallets
2928
- })
2929
- }, {
2930
- path: getAbsolutePath(navigationRoutes.confirmSwap),
2931
- element: React.createElement(ConfirmSwapPage, null)
2932
- }]);
2933
- }
2934
-
2935
- const Header = /*#__PURE__*/styled('div', {
2936
- display: 'flex',
2937
- width: '100%',
2938
- justifyContent: 'end',
2939
- '.balance': {
2940
- display: 'flex'
2941
- }
2942
- });
2943
- const WalletImageContainer = /*#__PURE__*/styled('div', {
2944
- marginLeft: -15,
2945
- marginRight: '$6',
2946
- '& img': {
2947
- borderRadius: '50%'
2948
- }
2949
- });
2950
- function Layout(_ref) {
2951
- let {
2952
- config
2953
- } = _ref;
2954
- const navigate = useNavigate();
2955
- const {
2956
- connectedWallets,
2957
- selectedWallets
2958
- } = useWalletsStore();
2959
- const {
2960
- getWalletInfo
2961
- } = useWallets();
2962
- const connectedWalletsImages = removeDuplicateFrom(getSelectableWallets(connectedWallets, selectedWallets, getWalletInfo).map(w => w.image));
2963
- const {
2964
- blockchains,
2965
- tokens
2966
- } = useMetaStore.use.meta();
2967
- const setFromChain = useBestRouteStore.use.setFromChain();
2968
- const setFromToken = useBestRouteStore.use.setFromToken();
2969
- const setToChain = useBestRouteStore.use.setToChain();
2970
- const setToToken = useBestRouteStore.use.setToToken();
2971
- const setInputAmount = useBestRouteStore.use.setInputAmount();
2972
- const setAffiliateRef = useSettingsStore.use.setAffiliateRef();
2973
- const totalBalance = calculateWalletUsdValue(connectedWallets);
2974
- const connectWalletsButtonDisabled = useUiStore.use.connectWalletsButtonDisabled();
2975
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
2976
- const fetchingBalance = useWalletsStore(fetchingBalanceSelector);
2977
- const {
2978
- t
2979
- } = useTranslation();
2980
- useEffect(() => {
2981
- if (loadingMetaStatus === 'success') {
2982
- const chain = blockchains.find(chain => chain.name === config?.to?.blockchain);
2983
- const token = tokens.find(t => tokensAreEqual(t, config?.to?.token || null));
2984
- setToChain(chain || null);
2985
- setToToken(token || null);
2986
- }
2987
- }, [config?.to?.token, config?.to?.blockchain, loadingMetaStatus]);
2988
- useEffect(() => {
2989
- setInputAmount(config?.amount?.toString() || '');
2990
- }, [config?.amount]);
2991
- useEffect(() => {
2992
- if (loadingMetaStatus === 'success') {
2993
- const chain = blockchains.find(chain => chain.name === config?.from?.blockchain);
2994
- const token = tokens.find(t => tokensAreEqual(t, config?.from?.token || null));
2995
- setFromChain(chain || null);
2996
- setFromToken(token || null);
2997
- }
2998
- }, [config?.from?.token, config?.from?.blockchain, loadingMetaStatus]);
2999
- useEffect(() => {
3000
- setAffiliateRef(config?.affiliateRef || null);
3001
- }, [config?.affiliateRef]);
3002
- return React.createElement(React.Fragment, null, React.createElement(Header, null, React.createElement(Button, {
3003
- size: "small",
3004
- suffix: React.createElement(AddWalletIcon, {
3005
- size: 20
3006
- }),
3007
- variant: "ghost",
3008
- flexContent: true,
3009
- loading: loadingMetaStatus === 'loading',
3010
- disabled: loadingMetaStatus === 'failed',
3011
- onClick: () => {
3012
- if (!connectWalletsButtonDisabled) navigate(navigationRoutes.wallets);
3013
- }
3014
- }, connectedWalletsImages?.length ? connectedWalletsImages.map((walletImage, index) => React.createElement(WalletImageContainer, {
3015
- key: index
3016
- }, React.createElement(Image, {
3017
- src: walletImage,
3018
- size: 24
3019
- }))) : React.createElement(React.Fragment, null), React.createElement("div", {
3020
- className: "balance"
3021
- }, React.createElement(Typography, {
3022
- variant: "body2"
3023
- }, !connectedWallets?.length ? t('Connect Wallet') : `$${totalBalance || 0}`), fetchingBalance && React.createElement(Spinner, null)))), React.createElement(AppRoutes, {
3024
- config: config
3025
- }));
3026
- }
3027
-
3028
- const globalFont = fontFamily => globalCss({
3029
- '@import': ["url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap')", "url('https://fonts.cdnfonts.com/css/times-new-roman')"],
3030
- body: {
3031
- fontFamily
3032
- }
3033
- })();
3034
-
3035
- function usePrevious(value) {
3036
- // The ref object is a generic container whose current property is mutable ...
3037
- // ... and can hold any value, similar to an instance property on a class
3038
- const ref = useRef();
3039
- // Store current value in ref
3040
- useEffect(() => {
3041
- ref.current = value;
3042
- }, [value]); // Only re-run if value changes
3043
- // Return previous value (happens before update in useEffect above)
3044
- return ref.current;
3045
- }
3046
-
3047
- function useTheme(_ref) {
3048
- let {
3049
- colors: themeColors,
3050
- fontFamily = 'Roboto',
3051
- borderRadius = 8,
3052
- mode = 'auto'
3053
- } = _ref;
3054
- const theme = useSettingsStore.use.theme();
3055
- const fetchMeta = useMetaStore.use.fetchMeta();
3056
- const setTheme = useSettingsStore.use.setTheme();
3057
- const light = themeColors?.light;
3058
- const dark = themeColors?.dark;
3059
- const neutral = light?.neutral || '#fafafa';
3060
- const background = light?.background || '#fff';
3061
- const foreground = light?.foreground || '#000';
3062
- const darkColors = {
3063
- ...generateRangeColors('primary', 'dark', dark?.primary),
3064
- ...generateRangeColors('error', 'dark', dark?.error),
3065
- ...generateRangeColors('warning', 'dark', dark?.warning),
3066
- ...generateRangeColors('success', 'dark', dark?.success),
3067
- ...generateRangeColors('neutral', 'dark', dark?.neutral),
3068
- surface: dark?.surface,
3069
- background: dark?.background,
3070
- foreground: dark?.foreground
3071
- };
3072
- const lightColors = {
3073
- surface: light?.surface || '#fff',
3074
- ...generateRangeColors('primary', 'light', light?.primary || '#5FA425'),
3075
- ...generateRangeColors('error', 'light', light?.error || '#FF0000'),
3076
- ...generateRangeColors('warning', 'light', light?.warning || '#F5A623'),
3077
- ...generateRangeColors('success', 'light', light?.success || '#0070F3'),
3078
- ...generateRangeColors('neutral', 'light', neutral),
3079
- background,
3080
- foreground
3081
- };
3082
- const customLightTheme = createTheme({
3083
- colors: lightColors,
3084
- radii: {
3085
- 5: `${borderRadius}px`
3086
- },
3087
- shadows: {
3088
- s: `0px 3px 5px 3px ${light?.neutral || '#f0f2f5'} ,0px 6px 10px 3px ${light?.neutral || '#f0f2f5'}, 0px 1px 18px 3px ${light?.neutral || '#f0f2f5'}`
3089
- }
3090
- });
3091
- const customDarkTheme = createTheme({
3092
- colors: {
3093
- ...lightColors,
3094
- ...generateRangeColors('neutral', 'dark', '#111111'),
3095
- foreground: background,
3096
- background: foreground,
3097
- surface: '#000',
3098
- ...JSON.parse(JSON.stringify(darkColors))
3099
- },
3100
- radii: {
3101
- 5: `${borderRadius}px`
3102
- },
3103
- shadows: {
3104
- s: `0px 3px 5px 3px ${dark?.neutral || '#222'}, 0px 6px 10px 3px ${dark?.neutral || '#222'}, 0px 1px 18px 3px ${dark?.neutral || '#222'}`
3105
- }
3106
- });
3107
- const [OSTheme, setOSTheme] = useState('light');
3108
- useEffect(() => {
3109
- (async () => {
3110
- await fetchMeta();
3111
- })();
3112
- const switchTheme = event => {
3113
- if (event.matches) setOSTheme('dark');else setOSTheme('light');
3114
- };
3115
- if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
3116
- setOSTheme('dark');
3117
- }
3118
- window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', switchTheme);
3119
- return () => {
3120
- window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', switchTheme);
3121
- };
3122
- }, []);
3123
- useEffect(() => {
3124
- if (mode !== 'auto') setTheme(mode);
3125
- }, [mode]);
3126
- const prevFont = usePrevious(fontFamily);
3127
- useLayoutEffect(() => {
3128
- const {
3129
- classList
3130
- } = document.body;
3131
- if (prevFont) classList.remove(`font_${prevFont.replace(/ /g, '')}`);
3132
- classList.add(`font_${fontFamily.replace(/ /g, '')}`);
3133
- }, [fontFamily]);
3134
- const getActiveTheme = () => {
3135
- if (theme === 'auto') return OSTheme === 'dark' ? customDarkTheme : customLightTheme;else return theme === 'dark' ? customDarkTheme : customLightTheme;
3136
- };
3137
- return {
3138
- activeTheme: getActiveTheme()
3139
- };
3140
- }
3141
-
3142
- function useSelectLanguage() {
3143
- const {
3144
- i18n
3145
- } = useTranslation();
3146
- // @ts-ignore
3147
- const currentLanguage = i18n?.language || 'en';
3148
- const changeLanguage = value => {
3149
- if (currentLanguage !== value) {
3150
- // @ts-ignore
3151
- i18n.changeLanguage(value);
3152
- }
3153
- };
3154
- return {
3155
- changeLanguage,
3156
- currentLanguage
3157
- };
3158
- }
3159
-
3160
- var swap = "SWAP";
3161
- var From = "You sell";
3162
- var To = "You receive";
3163
- var Balance = "Balance";
3164
- var Max = "Max";
3165
- var Chain = "Chain";
3166
- var Token = "Token";
3167
- var Source = "Source";
3168
- var Destination = "Destination";
3169
- var en = {
3170
- swap: swap,
3171
- "Connect Wallet": "Connect Wallet",
3172
- "Powered By": "Powered By",
3173
- From: From,
3174
- To: To,
3175
- Balance: Balance,
3176
- Max: Max,
3177
- Chain: Chain,
3178
- Token: Token,
3179
- Source: Source,
3180
- Destination: Destination,
3181
- "Select Wallet": "Connect Your Wallet"
3182
- };
3183
-
3184
- var swap$1 = "TAKAS";
3185
- var From$1 = "İtibaren";
3186
- var To$1 = "İle";
3187
- var Max$1 = "maks.";
3188
- var Chain$1 = "Zincir";
3189
- var Token$1 = "Jeton";
3190
- var tr = {
3191
- swap: swap$1,
3192
- "Select Wallet": "Cüzdan Seç",
3193
- "Powered By": "Tarafından desteklenmektedir",
3194
- "Connect Wallet": "Cüzdanı Bağla",
3195
- From: From$1,
3196
- To: To$1,
3197
- Max: Max$1,
3198
- Chain: Chain$1,
3199
- Token: Token$1
3200
- };
3201
-
3202
- const languages = ['en', 'tr'];
3203
- i18n.use(Backend)
3204
- // detect user language
3205
- .use(LanguageDetector)
3206
- // pass the i18n instance to react-i18next.
3207
- .use(initReactI18next).init({
3208
- resources: {
3209
- en: {
3210
- translation: en
3211
- },
3212
- tr: {
3213
- translation: tr
3214
- }
3215
- },
3216
- fallbackLng: 'en',
3217
- debug: true,
3218
- whitelist: languages
3219
- });
3220
-
3221
- function QueueManager(props) {
3222
- const {
3223
- providers,
3224
- getSigners,
3225
- state,
3226
- connect,
3227
- canSwitchNetworkTo,
3228
- getWalletInfo
3229
- } = useWallets();
3230
- const swapQueueDef = useMemo(() => {
3231
- return makeQueueDefinition({
3232
- API_KEY: getConfig('API_KEY')
3233
- });
3234
- }, []);
3235
- const getOneOfWalletsDetails = useWalletsStore.use.getOneOfWalletsDetails();
3236
- const {
3237
- blockchains
3238
- } = useMetaStore.use.meta();
3239
- const connectedWallets = useWalletsStore.use.connectedWallets();
3240
- const wallets = {
3241
- blockchains: connectedWallets.map(wallet => ({
3242
- accounts: [wallet],
3243
- name: wallet.chain
3244
- }))
3245
- };
3246
- const switchNetwork = (wallet, network) => {
3247
- if (!canSwitchNetworkTo(wallet, network)) {
3248
- return undefined;
3249
- }
3250
- return connect(wallet, network);
3251
- };
3252
- // TODO: this code copy & pasted from rango, should be refactored.
3253
- const allBlockchains = blockchains.filter(blockchain => blockchain.enabled).reduce((blockchainsObj, blockchain) => (blockchainsObj[blockchain.name] = blockchain, blockchainsObj), {});
3254
- const evmBasedChains = blockchains.filter(isEvmBlockchain$1);
3255
- const getSupportedChainNames = type => {
3256
- const {
3257
- supportedChains
3258
- } = getWalletInfo(type);
3259
- return walletAndSupportedChainsNames(supportedChains);
3260
- };
3261
- const allProviders = providers();
3262
- const notifier = data => {
3263
- const lastStep = data.swap?.steps[data.swap.steps.length - 1];
3264
- const outputAmount = data.step?.outputAmount || '';
3265
- const step = data.step || lastStep;
3266
- if (data.eventType === 'task_completed' || data.eventType === 'step_completed_with_output' && lastStep?.id !== data.step?.id || !!outputAmount) {
3267
- const fromAccount = connectedWallets.find(account => account.chain === step?.fromBlockchain);
3268
- const toAccount = step?.fromBlockchain !== step?.toBlockchain && connectedWallets.find(wallet => wallet.chain === step?.toBlockchain);
3269
- fromAccount && getOneOfWalletsDetails(fromAccount);
3270
- toAccount && getOneOfWalletsDetails(toAccount);
3271
- }
3272
- };
3273
- const context = {
3274
- meta: {
3275
- blockchains: allBlockchains,
3276
- evmBasedChains: evmBasedChains,
3277
- evmNetworkChainInfo: convertEvmBlockchainMetaToEvmChainInfo(evmBasedChains),
3278
- getSupportedChainNames
3279
- },
3280
- getSigners,
3281
- //todo: remove Network type
3282
- //@ts-ignore
3283
- wallets,
3284
- providers: allProviders,
3285
- switchNetwork,
3286
- connect,
3287
- state,
3288
- notifier
3289
- };
3290
- return React.createElement(Provider, {
3291
- queuesDefs: [swapQueueDef],
3292
- context: context,
3293
- onPersistedDataLoaded: manager => {
3294
- checkWaitingForNetworkChange(manager);
3295
- },
3296
- isPaused: false
3297
- }, props.children);
3298
- }
3299
-
3300
- const Widget = _ref => {
3301
- let {
3302
- config
3303
- } = _ref;
3304
- globalFont(config?.theme?.fontFamily || 'Roboto');
3305
- const {
3306
- activeTheme
3307
- } = useTheme({
3308
- ...config?.theme
3309
- });
3310
- const {
3311
- blockchains
3312
- } = useMetaStore.use.meta();
3313
- const disconnectWallet = useWalletsStore.use.disconnectWallet();
3314
- const connectWallet = useWalletsStore.use.connectWallet();
3315
- const {
3316
- changeLanguage
3317
- } = useSelectLanguage();
3318
- const clearConnectedWallet = useWalletsStore.use.clearConnectedWallet();
3319
- const [lastConnectedWalletWithNetwork, setLastConnectedWalletWithNetwork] = useState('');
3320
- const [disconnectedWallet, setDisconnectedWallet] = useState();
3321
- const currentPage = useUiStore.use.currentPage();
3322
- const evmBasedChainNames = blockchains.filter(isEvmBlockchain$1).map(chain => chain.name);
3323
- useMemo(() => {
3324
- if (config?.apiKey) {
3325
- initConfig({
3326
- API_KEY: config?.apiKey
3327
- });
3328
- }
3329
- }, [config]);
3330
- const onUpdateState = (type, event, value, state, supportedChains) => {
3331
- if (event === Events.ACCOUNTS) {
3332
- if (value) {
3333
- const supportedChainNames = walletAndSupportedChainsNames(supportedChains);
3334
- const data = prepareAccountsForWalletStore(type, value, evmBasedChainNames, supportedChainNames);
3335
- connectWallet(data);
3336
- } else {
3337
- disconnectWallet(type);
3338
- }
3339
- }
3340
- if (event === Events.ACCOUNTS && state.connected) {
3341
- const key = `${type}-${state.network}-${value}`;
3342
- if (state.connected) {
3343
- setLastConnectedWalletWithNetwork(key);
3344
- }
3345
- }
3346
- if (event === Events.NETWORK && state.network) {
3347
- const key = `${type}-${state.network}`;
3348
- setLastConnectedWalletWithNetwork(key);
3349
- }
3350
- };
3351
- let providers = allProviders();
3352
- useEffect(() => {
3353
- const wallets = config?.wallets;
3354
- clearConnectedWallet();
3355
- providers = !wallets ? allProviders() : allProviders().filter(provider => {
3356
- const type = provider.config.type;
3357
- return wallets.find(w => w === type);
3358
- });
3359
- }, [config?.wallets]);
3360
- useEffect(() => {
3361
- changeLanguage(config?.language || 'en');
3362
- }, [config?.language]);
3363
- return React.createElement(Provider$1, {
3364
- allBlockChains: blockchains,
3365
- providers: providers,
3366
- onUpdateState: onUpdateState
3367
- }, React.createElement("div", {
3368
- id: "swap-container",
3369
- className: activeTheme
3370
- }, React.createElement(QueueManager, null, React.createElement(SwapContainer, {
3371
- fixedHeight: currentPage !== navigationRoutes.home
3372
- }, React.createElement(AppRouter, {
3373
- lastConnectedWallet: lastConnectedWalletWithNetwork,
3374
- disconnectedWallet: disconnectedWallet,
3375
- clearDisconnectedWallet: () => {
3376
- setDisconnectedWallet(undefined);
3377
- }
3378
- }, React.createElement(Layout, {
3379
- config: config
3380
- }))))));
3381
- };
3382
-
3383
- export { Widget };
3384
- //# sourceMappingURL=widget-embedded.esm.js.map