@rango-dev/widget-embedded 0.1.10-next.100

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