@rango-dev/widget-embedded 0.1.13-next.0 → 0.1.13-next.5

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 (55) hide show
  1. package/dist/App.d.ts.map +1 -1
  2. package/dist/QueueManager.d.ts.map +1 -1
  3. package/dist/components/AppRouter.d.ts.map +1 -1
  4. package/dist/components/Layout.d.ts.map +1 -1
  5. package/dist/components/TokenInfo.d.ts.map +1 -1
  6. package/dist/components/TokenPreview.d.ts.map +1 -1
  7. package/dist/components/UpdateUrl.d.ts.map +1 -1
  8. package/dist/components/warnings/BalanceErrors.d.ts.map +1 -1
  9. package/dist/globalStyles.d.ts +0 -1
  10. package/dist/globalStyles.d.ts.map +1 -1
  11. package/dist/hooks/useNavigateBack.d.ts.map +1 -1
  12. package/dist/lib.d.ts +1 -1
  13. package/dist/lib.d.ts.map +1 -1
  14. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  15. package/dist/pages/SwapDetailsPage.d.ts.map +1 -1
  16. package/dist/store/bestRoute.d.ts +1 -0
  17. package/dist/store/bestRoute.d.ts.map +1 -1
  18. package/dist/store/wallets.d.ts +1 -0
  19. package/dist/store/wallets.d.ts.map +1 -1
  20. package/dist/utils/numbers.d.ts +1 -2
  21. package/dist/utils/numbers.d.ts.map +1 -1
  22. package/dist/widget-embedded.cjs.development.js +1087 -1149
  23. package/dist/widget-embedded.cjs.development.js.map +1 -1
  24. package/dist/widget-embedded.cjs.production.min.js +1087 -1149
  25. package/dist/widget-embedded.cjs.production.min.js.map +1 -1
  26. package/dist/widget-embedded.esm.js +1090 -1152
  27. package/dist/widget-embedded.esm.js.map +1 -1
  28. package/package.json +3 -3
  29. package/src/App.tsx +1 -2
  30. package/src/QueueManager.tsx +28 -3
  31. package/src/components/AppRouter.tsx +4 -29
  32. package/src/components/AppRoutes.tsx +9 -9
  33. package/src/components/BottomLogo.tsx +1 -1
  34. package/src/components/ChangeSlippageButton.tsx +1 -1
  35. package/src/components/Layout.tsx +3 -1
  36. package/src/components/RoutesOverview.tsx +2 -2
  37. package/src/components/TokenInfo.tsx +3 -2
  38. package/src/components/TokenPreview.tsx +1 -0
  39. package/src/components/UpdateUrl.tsx +19 -50
  40. package/src/components/warnings/BalanceErrors.tsx +4 -2
  41. package/src/constants/navigationRoutes.ts +9 -9
  42. package/src/globalStyles.ts +0 -19
  43. package/src/hooks/useNavigateBack.ts +3 -4
  44. package/src/index.tsx +1 -1
  45. package/src/lib.tsx +16 -8
  46. package/src/pages/ConfirmSwapPage.tsx +33 -13
  47. package/src/pages/HistoryPage.tsx +1 -1
  48. package/src/pages/Home.tsx +1 -1
  49. package/src/pages/SwapDetailsPage.tsx +1 -2
  50. package/src/store/bestRoute.ts +18 -16
  51. package/src/store/wallets.ts +38 -28
  52. package/src/utils/numbers.ts +2 -5
  53. package/dist/hooks/useCopyToClipboard.d.ts +0 -2
  54. package/dist/hooks/useCopyToClipboard.d.ts.map +0 -1
  55. package/src/hooks/useCopyToClipboard.ts +0 -23
@@ -19,31 +19,16 @@ var rangoSdk = require('rango-sdk');
19
19
  var walletsShared = require('@rango-dev/wallets-shared');
20
20
  var walletsCore = require('@rango-dev/wallets-core');
21
21
  var shallow = require('zustand/shallow');
22
- var reactI18next = require('react-i18next');
23
- var theme = require('@rango-dev/ui/src/theme');
24
22
  var providerAll = require('@rango-dev/provider-all');
23
+ var reactI18next = require('react-i18next');
25
24
  var i18n = require('i18next');
26
25
  var i18n__default = _interopDefault(i18n);
27
26
  var queueManagerReact = require('@rango-dev/queue-manager-react');
28
27
  var dayjs = _interopDefault(require('dayjs'));
29
- var copy = _interopDefault(require('copy-to-clipboard'));
28
+ var theme = require('@rango-dev/ui/src/theme');
30
29
  var Backend = _interopDefault(require('i18next-http-backend'));
31
30
  var LanguageDetector = _interopDefault(require('i18next-browser-languagedetector'));
32
31
 
33
- const navigationRoutes = {
34
- home: '/',
35
- fromChain: '/from-chain',
36
- fromToken: '/from-token',
37
- toChain: '/to-chain',
38
- toToken: '/to-token',
39
- settings: '/settings',
40
- liquiditySources: '/settings/liquidity-sources',
41
- swaps: '/swaps',
42
- wallets: '/wallets',
43
- confirmSwap: '/confirm-swap',
44
- swapDetails: '/swaps/:requestId'
45
- };
46
-
47
32
  const ZERO = /*#__PURE__*/new BigNumber__default(0);
48
33
 
49
34
  function removeDuplicateFrom(array) {
@@ -99,7 +84,7 @@ const numberToString = function (number, minDecimals, maxDecimals) {
99
84
  if (maxDecimals === void 0) {
100
85
  maxDecimals = null;
101
86
  }
102
- if (number === null) return '';
87
+ if (number === null || number === undefined) return '';
103
88
  if (number === '') return '';
104
89
  const n = new BigNumber.BigNumber(number);
105
90
  const roundingMode = 1;
@@ -120,12 +105,6 @@ const numberToString = function (number, minDecimals, maxDecimals) {
120
105
  return n.toFormat(Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 8))), roundingMode);
121
106
  };
122
107
  const totalArrivalTime = data => data?.result?.swaps?.reduce((a, b) => a + b.estimatedTimeInSeconds, 0) || 0;
123
- const decimalNumber = function (number, toFixed) {
124
- if (number === void 0) {
125
- number = '0';
126
- }
127
- return parseFloat(number).toFixed(toFixed);
128
- };
129
108
  const isPositiveNumber = text => !!text && parseFloat(text) > 0;
130
109
 
131
110
  function searchParamsToToken(tokens, searchParams, chain) {
@@ -846,12 +825,12 @@ function shouldRetrySwap(pendingSwap) {
846
825
  return pendingSwap.status === 'failed' && !!pendingSwap.finishTime && new Date().getTime() - parseInt(pendingSwap.finishTime) < 4 * 3600 * 1000;
847
826
  }
848
827
 
849
- const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.create()( /*#__PURE__*/middleware.subscribeWithSelector(set => ({
828
+ const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.create()( /*#__PURE__*/middleware.subscribeWithSelector((set, get) => ({
850
829
  accounts: [],
851
830
  balances: [],
852
831
  selectedWallets: [],
853
832
  connectWallet: accounts => {
854
- const tokens = useMetaStore.getState().meta.tokens;
833
+ const getOneOfWalletsDetails = get().getOneOfWalletsDetails;
855
834
  set(state => ({
856
835
  accounts: state.accounts.concat(accounts),
857
836
  balances: state.balances.concat(accounts.map(account => ({
@@ -864,28 +843,7 @@ const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.creat
864
843
  explorerUrl: null
865
844
  })))
866
845
  }));
867
- accounts.forEach(async account => {
868
- try {
869
- const response = await httpService().getWalletsDetails([{
870
- address: account.address,
871
- blockchain: account.chain
872
- }]);
873
- const retrivedBalance = response.wallets[0];
874
- if (retrivedBalance) {
875
- set(state => ({
876
- balances: state.balances.map(balance => {
877
- return isAccountAndBalanceMatched(account, balance) ? makeBalanceFor(account, retrivedBalance, tokens) : balance;
878
- })
879
- }));
880
- } else throw new Error('Wallet not found');
881
- } catch (error) {
882
- set(state => ({
883
- balances: state.balances.map(balance => {
884
- return isAccountAndBalanceMatched(account, balance) ? resetBalanceState(balance) : balance;
885
- })
886
- }));
887
- }
888
- });
846
+ accounts.forEach(async account => getOneOfWalletsDetails(account));
889
847
  },
890
848
  disconnectWallet: walletType => {
891
849
  set(state => ({
@@ -924,7 +882,38 @@ const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.creat
924
882
  accounts: [],
925
883
  balances: [],
926
884
  selectedWallets: []
927
- }))
885
+ })),
886
+ getOneOfWalletsDetails: async account => {
887
+ const tokens = useMetaStore.getState().meta.tokens;
888
+ set(state => ({
889
+ balances: state.balances.map(balance => {
890
+ return balance.address === account.address && balance.chain === account.chain ? {
891
+ ...balance,
892
+ loading: true
893
+ } : balance;
894
+ })
895
+ }));
896
+ try {
897
+ const response = await httpService().getWalletsDetails([{
898
+ address: account.address,
899
+ blockchain: account.chain
900
+ }]);
901
+ const retrivedBalance = response.wallets[0];
902
+ if (retrivedBalance) {
903
+ set(state => ({
904
+ balances: state.balances.map(balance => {
905
+ return isAccountAndBalanceMatched(account, balance) ? makeBalanceFor(account, retrivedBalance, tokens) : balance;
906
+ })
907
+ }));
908
+ } else throw new Error('Wallet not found');
909
+ } catch (error) {
910
+ set(state => ({
911
+ balances: state.balances.map(balance => {
912
+ return isAccountAndBalanceMatched(account, balance) ? resetBalanceState(balance) : balance;
913
+ })
914
+ }));
915
+ }
916
+ }
928
917
  }))));
929
918
  useWalletsStore.subscribe(state => state.balances, balances => {
930
919
  useBestRouteStore.setState(_ref => {
@@ -975,6 +964,13 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.cre
975
964
  })
976
965
  };
977
966
  }),
967
+ resetRoute: () => set(() => ({
968
+ loading: true,
969
+ error: '',
970
+ bestRoute: null,
971
+ outputAmount: null,
972
+ outputUsdValue: new BigNumber__default(0)
973
+ })),
978
974
  setFromChain: (chain, setDefaultToken) => {
979
975
  set(state => {
980
976
  if (state.fromChain?.name === chain?.name) return {};
@@ -1024,7 +1020,8 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.cre
1024
1020
  ...(!amount && {
1025
1021
  outputAmount: new BigNumber__default(0),
1026
1022
  outputUsdValue: new BigNumber__default(0),
1027
- bestRoute: null
1023
+ bestRoute: null,
1024
+ error: ''
1028
1025
  }),
1029
1026
  ...(!!state.fromToken && {
1030
1027
  inputUsdValue: getUsdValue(state.fromToken, amount)
@@ -1089,7 +1086,8 @@ const bestRoute = (bestRouteStore, settingsStore) => {
1089
1086
  const {
1090
1087
  fromToken,
1091
1088
  toToken,
1092
- inputAmount
1089
+ inputAmount,
1090
+ resetRoute
1093
1091
  } = bestRouteStore.getState();
1094
1092
  const {
1095
1093
  slippage,
@@ -1102,12 +1100,9 @@ const bestRoute = (bestRouteStore, settingsStore) => {
1102
1100
  abortController = new AbortController();
1103
1101
  const userSlippage = !!customSlippage ? customSlippage : slippage;
1104
1102
  const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, [], [], disabledLiquiditySources, userSlippage, affiliateRef);
1105
- if (!bestRouteStore.getState().loading) bestRouteStore.setState({
1106
- loading: true,
1107
- bestRoute: null,
1108
- outputAmount: null,
1109
- outputUsdValue: new BigNumber__default(0)
1110
- });
1103
+ if (!bestRouteStore.getState().loading) {
1104
+ resetRoute();
1105
+ }
1111
1106
  httpService().getBestRoute(requestBody, {
1112
1107
  signal: abortController.signal
1113
1108
  }).then(res => {
@@ -1133,7 +1128,8 @@ const bestRoute = (bestRouteStore, settingsStore) => {
1133
1128
  fromToken,
1134
1129
  toToken,
1135
1130
  inputAmount,
1136
- inputUsdValue
1131
+ inputUsdValue,
1132
+ resetRoute
1137
1133
  } = useBestRouteStore.getState();
1138
1134
  if (!isPositiveNumber(inputAmount) || inputUsdValue.eq(0)) return bestRouteStore.setState({
1139
1135
  loading: false
@@ -1144,12 +1140,7 @@ const bestRoute = (bestRouteStore, settingsStore) => {
1144
1140
  outputAmount: new BigNumber__default(inputAmount),
1145
1141
  outputUsdValue: inputUsdValue
1146
1142
  });
1147
- if (!bestRouteStore.getState().loading) bestRouteStore.setState({
1148
- loading: true,
1149
- bestRoute: null,
1150
- outputAmount: null,
1151
- outputUsdValue: new BigNumber__default(0)
1152
- });
1143
+ if (!bestRouteStore.getState().loading) resetRoute();
1153
1144
  debouncedFetchBestRoute();
1154
1145
  };
1155
1146
  useBestRouteStore.subscribe(state => ({
@@ -1198,6 +1189,20 @@ var SearchParams;
1198
1189
  SearchParams["FROM_AMOUNT"] = "fromAmount";
1199
1190
  })(SearchParams || (SearchParams = {}));
1200
1191
 
1192
+ const navigationRoutes = {
1193
+ home: '/',
1194
+ fromChain: 'from-chain',
1195
+ fromToken: 'from-token',
1196
+ toChain: 'to-chain',
1197
+ toToken: 'to-token',
1198
+ settings: 'settings',
1199
+ liquiditySources: '/settings/liquidity-sources',
1200
+ swaps: 'swaps',
1201
+ wallets: 'wallets',
1202
+ confirmSwap: 'confirm-swap',
1203
+ swapDetails: 'swaps/:requestId'
1204
+ };
1205
+
1201
1206
  const useUiStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.create()(set => ({
1202
1207
  connectWalletsButtonDisabled: false,
1203
1208
  selectedSwapRequestId: null,
@@ -1245,37 +1250,6 @@ function UpdateUrl() {
1245
1250
  if (requestId) setSelectedSwap(requestId);
1246
1251
  }, []);
1247
1252
  React.useEffect(() => {
1248
- let fromChainString = '',
1249
- fromTokenString = '',
1250
- toChainString = '',
1251
- toTokenString = '',
1252
- fromAmount = '';
1253
- if (loadingStatus !== 'success' && location.pathname != navigationRoutes.confirmSwap) {
1254
- fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
1255
- fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
1256
- toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
1257
- toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];
1258
- fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT];
1259
- setSearchParams({
1260
- ...(fromChainString && {
1261
- [SearchParams.FROM_CHAIN]: fromChainString
1262
- }),
1263
- ...(fromTokenString && {
1264
- [SearchParams.FROM_TOKEN]: fromTokenString
1265
- }),
1266
- ...(toChainString && {
1267
- [SearchParams.TO_CHAIN]: toChainString
1268
- }),
1269
- ...(toTokenString && {
1270
- [SearchParams.TO_TOKEN]: toTokenString
1271
- }),
1272
- ...(fromAmount && {
1273
- [SearchParams.FROM_AMOUNT]: fromAmount.toString()
1274
- })
1275
- }, {
1276
- replace: true
1277
- });
1278
- }
1279
1253
  if (!firstRender.current) {
1280
1254
  let fromChainString = '',
1281
1255
  fromTokenString = '',
@@ -1287,7 +1261,7 @@ function UpdateUrl() {
1287
1261
  fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
1288
1262
  toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
1289
1263
  toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];
1290
- fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT];
1264
+ fromAmount = searchParamsRef.current[SearchParams.FROM_AMOUNT] || inputAmount;
1291
1265
  } else {
1292
1266
  if (location.state === 'redirect') return;
1293
1267
  fromChainString = fromChain?.name || '';
@@ -1295,29 +1269,29 @@ function UpdateUrl() {
1295
1269
  toChainString = toChain?.name || '';
1296
1270
  toTokenString = (toToken?.symbol || '') + (toToken?.address ? `--${toToken?.address}` : '');
1297
1271
  fromAmount = inputAmount;
1298
- setSearchParams({
1299
- ...(fromChainString && {
1300
- [SearchParams.FROM_CHAIN]: fromChainString
1301
- }),
1302
- ...(fromTokenString && {
1303
- [SearchParams.FROM_TOKEN]: fromTokenString
1304
- }),
1305
- ...(toChainString && {
1306
- [SearchParams.TO_CHAIN]: toChainString
1307
- }),
1308
- ...(toTokenString && {
1309
- [SearchParams.TO_TOKEN]: toTokenString
1310
- }),
1311
- ...(fromAmount && {
1312
- [SearchParams.FROM_AMOUNT]: fromAmount.toString()
1313
- })
1314
- }, {
1315
- replace: true
1316
- });
1317
1272
  }
1273
+ setSearchParams({
1274
+ ...(fromChainString && {
1275
+ [SearchParams.FROM_CHAIN]: fromChainString
1276
+ }),
1277
+ ...(fromTokenString && {
1278
+ [SearchParams.FROM_TOKEN]: fromTokenString
1279
+ }),
1280
+ ...(toChainString && {
1281
+ [SearchParams.TO_CHAIN]: toChainString
1282
+ }),
1283
+ ...(toTokenString && {
1284
+ [SearchParams.TO_TOKEN]: toTokenString
1285
+ }),
1286
+ ...(fromAmount && {
1287
+ [SearchParams.FROM_AMOUNT]: fromAmount.toString()
1288
+ })
1289
+ }, {
1290
+ replace: true
1291
+ });
1318
1292
  }
1319
1293
  firstRender.current = false;
1320
- }, [location.pathname, inputAmount]);
1294
+ }, [location.pathname, inputAmount, fromChain, fromToken, toChain, toToken]);
1321
1295
  React.useEffect(() => {
1322
1296
  if (loadingStatus === 'success') {
1323
1297
  const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
@@ -1343,24 +1317,52 @@ function UpdateUrl() {
1343
1317
  return null;
1344
1318
  }
1345
1319
 
1346
- function PercentageChange(props) {
1320
+ function AppRouter(_ref) {
1321
+ let {
1322
+ children,
1323
+ ...props
1324
+ } = _ref;
1325
+ const isRouterInContext = reactRouter.useInRouterContext();
1326
+ const Router = isRouterInContext ? React.Fragment : reactRouter.MemoryRouter;
1347
1327
  const {
1348
- inputUsdValue,
1349
- outputUsdValue
1350
- } = props;
1351
- if (!inputUsdValue || !outputUsdValue || !outputUsdValue.gt(0)) return null;
1352
- const percentageChange = getPercentageChange(inputUsdValue.toNumber(), outputUsdValue.toNumber());
1353
- const showPercentageChange = percentageChange?.lt(0);
1354
- return React__default.createElement(React__default.Fragment, null, showPercentageChange && React__default.createElement(ui.Typography, {
1355
- variant: "caption",
1356
- color: "$error500"
1357
- }, `(${numberToString(percentageChange, 0, 2)}%)`));
1328
+ blockchains
1329
+ } = useMetaStore.use.meta();
1330
+ const evmChains = blockchains.filter(rangoTypes.isEvmBlockchain);
1331
+ queueManagerRangoPreset.useQueueManager({
1332
+ lastConnectedWallet: props.lastConnectedWallet,
1333
+ clearDisconnectedWallet: props.clearDisconnectedWallet,
1334
+ disconnectedWallet: props.disconnectedWallet,
1335
+ evmChains,
1336
+ notifier: () => {}
1337
+ });
1338
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement(Router, null, children), isRouterInContext && React__default.createElement(UpdateUrl, null));
1339
+ }
1340
+
1341
+ function useNavigateBack() {
1342
+ const isRouterInContext = reactRouterDom.useInRouterContext();
1343
+ const navigate = reactRouterDom.useNavigate();
1344
+ const navigateBackFrom = currentRoute => {
1345
+ if (currentRoute === navigationRoutes.swapDetails) return navigate('/' + navigationRoutes.swaps, {
1346
+ replace: true
1347
+ });
1348
+ if (!isRouterInContext || window.history.state && window.history.state.idx > 0) navigate(-1);else {
1349
+ if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.swaps, navigationRoutes.confirmSwap].includes(currentRoute)) navigate(navigationRoutes.home, {
1350
+ replace: true
1351
+ });else if (currentRoute === navigationRoutes.liquiditySources) navigate('/' + navigationRoutes.settings, {
1352
+ replace: true
1353
+ });
1354
+ }
1355
+ };
1356
+ return {
1357
+ navigateBackFrom
1358
+ };
1358
1359
  }
1359
1360
 
1360
1361
  const Box = /*#__PURE__*/ui.styled('div', {
1361
1362
  display: 'flex',
1362
1363
  flexDirection: 'column',
1363
- width: '100%'
1364
+ width: '100%',
1365
+ overflow: 'hidden'
1364
1366
  });
1365
1367
  const Container = /*#__PURE__*/ui.styled('div', {
1366
1368
  boxSizing: 'border-box',
@@ -1383,7 +1385,10 @@ const Container = /*#__PURE__*/ui.styled('div', {
1383
1385
  display: 'flex',
1384
1386
  justifyContent: 'space-between',
1385
1387
  alignItems: 'center',
1386
- minHeight: '32px'
1388
+ minHeight: '32px',
1389
+ '.usd-value': {
1390
+ paddingLeft: '$8'
1391
+ }
1387
1392
  },
1388
1393
  '.form': {
1389
1394
  display: 'flex',
@@ -1400,21 +1405,6 @@ const Container = /*#__PURE__*/ui.styled('div', {
1400
1405
  '.amount': {
1401
1406
  width: '30%'
1402
1407
  }
1403
- },
1404
- '.output-usd': {
1405
- display: 'flex',
1406
- div: {
1407
- display: 'flex',
1408
- paddingLeft: '$8'
1409
- }
1410
- }
1411
- });
1412
- const Options = /*#__PURE__*/ui.styled('div', {
1413
- display: 'flex',
1414
- justifyContent: 'flex-end',
1415
- '.balance': {
1416
- display: 'flex',
1417
- alignItems: 'center'
1418
1408
  }
1419
1409
  });
1420
1410
  const ImagePlaceholder = /*#__PURE__*/ui.styled('span', {
@@ -1435,28 +1425,16 @@ const OutputContainer = /*#__PURE__*/ui.styled('div', {
1435
1425
  paddingLeft: '$8',
1436
1426
  paddingRight: '$8'
1437
1427
  });
1438
- function TokenInfo(props) {
1428
+ function TokenPreview(props) {
1439
1429
  const {
1440
- type,
1441
1430
  chain,
1442
- token
1431
+ token,
1432
+ loadingStatus,
1433
+ percentageChange
1443
1434
  } = props;
1444
- const loadingStatus = useMetaStore.use.loadingStatus();
1445
- const fromChain = useBestRouteStore.use.fromChain();
1446
- const toChain = useBestRouteStore.use.toChain();
1447
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1448
- const fromToken = useBestRouteStore.use.fromToken();
1449
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1450
- const bestRoute = useBestRouteStore.use.bestRoute();
1451
- const inputAmount = useBestRouteStore.use.inputAmount();
1452
- const balances = useWalletsStore.use.balances();
1453
- const fetchingBestRoute = useBestRouteStore.use.loading();
1454
- const navigate = reactRouterDom.useNavigate();
1455
1435
  const {
1456
1436
  t
1457
1437
  } = reactI18next.useTranslation();
1458
- const tokenBalance = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', 8) : '0';
1459
- 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';
1460
1438
  const ItemSuffix = React__default.createElement("div", {
1461
1439
  style: {
1462
1440
  display: 'flex',
@@ -1466,45 +1444,23 @@ function TokenInfo(props) {
1466
1444
  }, loadingStatus === 'failed' && React__default.createElement(ui.InfoCircleIcon, {
1467
1445
  color: "error",
1468
1446
  size: 24
1469
- }), React__default.createElement(ui.AngleDownIcon, null));
1447
+ }));
1470
1448
  return React__default.createElement(Box, null, React__default.createElement(Container, {
1471
- type: props.type === 'From' ? 'filled' : 'outlined'
1449
+ type: 'outlined'
1472
1450
  }, React__default.createElement("div", {
1473
1451
  className: "head"
1474
1452
  }, React__default.createElement(ui.Typography, {
1475
1453
  variant: "body2",
1476
1454
  color: "neutrals800"
1477
- }, t(type)), props.type === 'From' ? React__default.createElement(Options, null, React__default.createElement("div", {
1478
- className: "balance",
1479
- onClick: () => {
1480
- if (tokenBalance !== '0') setInputAmount(tokenBalanceReal.split(',').join(''));
1481
- }
1482
- }, React__default.createElement(ui.Typography, {
1483
- variant: "body3",
1484
- color: "neutrals600"
1485
- }, `${t('Balance')}: ${tokenBalance} ${fromToken?.symbol || ''}`), React__default.createElement(ui.Spacer, {
1486
- size: 4
1487
- }), React__default.createElement(ui.Button, {
1488
- type: "primary",
1489
- variant: "ghost",
1490
- size: "compact"
1491
- }, t('Max')))) : React__default.createElement("div", {
1492
- className: "output-usd"
1493
- }, React__default.createElement(PercentageChange, {
1494
- inputUsdValue: inputUsdValue,
1495
- outputUsdValue: props.outputUsdValue
1496
- }), React__default.createElement("div", null, React__default.createElement(ui.Typography, {
1455
+ }, props.label), React__default.createElement("div", null, percentageChange, props.usdValue && React__default.createElement(ui.Typography, {
1497
1456
  variant: "caption",
1498
- color: "neutrals600"
1499
- }, `$${numberToString(props.outputUsdValue)}`)))), React__default.createElement("div", {
1457
+ color: "neutrals600",
1458
+ className: "usd-value"
1459
+ }, `$${numberToString(props.usdValue)}`))), React__default.createElement("div", {
1500
1460
  className: "form"
1501
1461
  }, React__default.createElement(ui.Button, {
1502
1462
  className: "selectors",
1503
- onClick: () => {
1504
- navigate(`/${props.type.toLowerCase()}-chain`);
1505
- },
1506
1463
  variant: "outlined",
1507
- disabled: loadingStatus === 'failed',
1508
1464
  loading: loadingStatus === 'loading',
1509
1465
  prefix: loadingStatus === 'success' && chain ? React__default.createElement(ui.Image, {
1510
1466
  src: chain.logo,
@@ -1517,11 +1473,7 @@ function TokenInfo(props) {
1517
1473
  size: 12
1518
1474
  }), React__default.createElement(ui.Button, {
1519
1475
  className: "selectors",
1520
- onClick: () => {
1521
- navigate(`/${props.type.toLowerCase()}-token`);
1522
- },
1523
1476
  variant: "outlined",
1524
- disabled: loadingStatus === 'failed' || type === 'From' && !fromChain || type === 'To' && !toChain,
1525
1477
  loading: loadingStatus === 'loading',
1526
1478
  prefix: loadingStatus === 'success' && token ? React__default.createElement(ui.Image, {
1527
1479
  src: token.image,
@@ -1534,983 +1486,998 @@ function TokenInfo(props) {
1534
1486
  size: 12
1535
1487
  }), React__default.createElement("div", {
1536
1488
  className: "amount"
1537
- }, props.type === 'From' ? React__default.createElement(ui.TextField, {
1538
- type: "number",
1539
- size: "large",
1540
- autoFocus: true,
1541
- placeholder: "0",
1542
- style: {
1543
- position: 'relative',
1544
- backgroundColor: '$background !important'
1545
- },
1546
- suffix: React__default.createElement("span", {
1547
- style: {
1548
- position: 'absolute',
1549
- right: '4px',
1550
- bottom: '2px'
1551
- }
1552
- }, React__default.createElement(ui.Typography, {
1553
- variant: "caption",
1554
- color: "neutrals800"
1555
- }, `$${numberToString(inputUsdValue)}`)),
1556
- value: props.inputAmount || '',
1557
- min: 0,
1558
- onChange: props.type === 'From' ? event => {
1559
- props.onAmountChange(event.target.value);
1560
- } : undefined
1561
- }) : React__default.createElement(OutputContainer, null, React__default.createElement(ui.Typography, {
1489
+ }, React__default.createElement(OutputContainer, null, React__default.createElement(ui.Typography, {
1562
1490
  variant: "h4"
1563
- }, fetchingBestRoute && '?', !!bestRoute?.result && `≈ ${numberToString(props.outputAmount)}`, (!inputAmount || inputAmount === '0') && '0'))))));
1491
+ }, props.amount))))));
1564
1492
  }
1565
1493
 
1566
- const Container$1 = /*#__PURE__*/theme.styled('div', {
1494
+ const Container$1 = /*#__PURE__*/ui.styled('div', {
1567
1495
  display: 'flex',
1568
- width: '100%',
1569
- justifyContent: 'end',
1570
1496
  alignItems: 'center',
1571
- paddingTop: '$16'
1497
+ justifyContent: 'space-between',
1498
+ padding: '$8',
1499
+ borderRadius: '$5',
1500
+ backgroundColor: '$neutrals300',
1501
+ color: '$neutrals800',
1502
+ fontSize: '$12',
1503
+ '.routes': {
1504
+ display: 'flex',
1505
+ alignItems: 'center'
1506
+ },
1507
+ '.fee': {
1508
+ display: 'flex',
1509
+ alignItems: 'center'
1510
+ }
1572
1511
  });
1573
- const Logo = /*#__PURE__*/theme.styled('svg', {
1574
- fill: '$foreground',
1575
- width: '$24',
1576
- margin: '0 $8 0 $16'
1577
- });
1578
- const StyledAnchor = /*#__PURE__*/theme.styled('a', {
1579
- display: 'flex',
1580
- justifyContent: 'center',
1581
- alignItems: 'center',
1582
- textDecoration: 'none'
1583
- });
1584
- function BottomLogo() {
1585
- const {
1586
- t
1587
- } = reactI18next.useTranslation();
1588
- return React__default.createElement(Container$1, null, React__default.createElement(ui.Typography, {
1589
- variant: "caption"
1590
- }, t('Powered By')), React__default.createElement(StyledAnchor, {
1591
- href: "https://rango.exchange",
1592
- target: "_blank"
1593
- }, React__default.createElement(Logo, {
1594
- xmlns: "http://www.w3.org/2000/svg",
1595
- viewBox: "0 0 33.68 29"
1596
- }, React__default.createElement("defs", null), React__default.createElement("g", {
1597
- id: "Layer_2",
1598
- "data-name": "Layer 2"
1599
- }, React__default.createElement("g", {
1600
- id: "Layer_1-2",
1601
- "data-name": "Layer 1"
1602
- }, React__default.createElement("path", {
1603
- 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"
1604
- }), React__default.createElement("path", {
1605
- 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"
1606
- })))), React__default.createElement(ui.Typography, {
1607
- variant: "body2"
1608
- }, "RANGO")));
1609
- }
1610
-
1611
- function SwithFromAndTo(_ref) {
1612
- let {
1613
- count
1614
- } = _ref;
1615
- const firstRender = React.useRef(true);
1616
- const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
1617
- const outputAmount = useBestRouteStore.use.outputAmount();
1618
- React.useEffect(() => {
1619
- if (!firstRender.current) {
1620
- const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
1621
- const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
1622
- const toChainString = searchParams.get(SearchParams.TO_CHAIN);
1623
- const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
1624
- setSearchParams({
1625
- ...(toChainString && {
1626
- [SearchParams.FROM_CHAIN]: toChainString
1627
- }),
1628
- ...(toTokenString && {
1629
- [SearchParams.FROM_TOKEN]: toTokenString
1630
- }),
1631
- ...(fromChainString && {
1632
- [SearchParams.TO_CHAIN]: fromChainString
1633
- }),
1634
- ...(fromTokenString && {
1635
- [SearchParams.TO_TOKEN]: fromTokenString
1636
- }),
1637
- ...(outputAmount && {
1638
- [SearchParams.FROM_AMOUNT]: outputAmount.toString()
1639
- })
1640
- });
1641
- } else {
1642
- firstRender.current = false;
1643
- }
1644
- }, [count]);
1645
- return null;
1512
+ function RoutesOverview(props) {
1513
+ if (!props.routes) return null;
1514
+ const swaps = props.routes.result?.swaps;
1515
+ return React__default.createElement(Container$1, null, React__default.createElement("div", {
1516
+ className: "routes"
1517
+ }, swaps?.map((swap, idx) => {
1518
+ const isLast = idx + 1 == swaps.length;
1519
+ return React__default.createElement(React__default.Fragment, {
1520
+ key: idx
1521
+ }, React__default.createElement("div", {
1522
+ className: "route"
1523
+ }, swap.from.symbol), React__default.createElement(ui.ChevronRightIcon, {
1524
+ size: 12
1525
+ }), isLast ? React__default.createElement("div", {
1526
+ className: "route"
1527
+ }, swap.to.symbol) : null);
1528
+ })), props.totalFee ? React__default.createElement("div", {
1529
+ className: "fee"
1530
+ }, React__default.createElement(ui.GasIcon, {
1531
+ size: 12
1532
+ }), React__default.createElement(ui.Spacer, {
1533
+ size: 4
1534
+ }), "$", props.totalFee) : null);
1646
1535
  }
1647
1536
 
1648
- const Footer = /*#__PURE__*/ui.styled('div', {
1649
- display: 'flex',
1650
- flexDirection: 'column',
1651
- width: '100%',
1652
- paddingTop: '$16'
1653
- });
1654
-
1655
- const errorMessages = {
1656
- genericServerError: 'Error connecting server, please reload the app and try again'
1657
- };
1658
-
1659
- const ButtonsContainer = /*#__PURE__*/ui.styled('div', {
1660
- display: 'flex'
1661
- });
1662
- function HeaderButtons(props) {
1663
- const {
1664
- onClickRefresh
1665
- } = props;
1666
- const navigate = reactRouterDom.useNavigate();
1667
- return React__default.createElement(ButtonsContainer, null, React__default.createElement(ui.Tooltip, {
1668
- content: "Refresh"
1669
- }, React__default.createElement(ui.Button, {
1670
- variant: "ghost",
1671
- onClick: onClickRefresh,
1672
- disabled: !onClickRefresh
1673
- }, React__default.createElement(ui.RetryIcon, {
1674
- size: 24,
1675
- disabled: !onClickRefresh
1676
- }))), React__default.createElement(ui.Tooltip, {
1677
- content: "Transactions History"
1678
- }, React__default.createElement(ui.Button, {
1679
- variant: "ghost",
1680
- onClick: () => navigate(navigationRoutes.swaps)
1681
- }, React__default.createElement(ui.HistoryIcon, {
1682
- size: 24
1683
- }))), React__default.createElement(ui.Tooltip, {
1684
- content: "Settings"
1685
- }, React__default.createElement(ui.Button, {
1686
- variant: "ghost",
1687
- onClick: () => navigate(navigationRoutes.settings)
1688
- }, React__default.createElement(ui.SettingsIcon, {
1689
- size: 24
1690
- }))));
1691
- }
1537
+ var ConfirmSwapErrorTypes;
1538
+ (function (ConfirmSwapErrorTypes) {
1539
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
1540
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
1541
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
1542
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
1543
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
1544
+ })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
1545
+ var ConfirmSwapWarningTypes;
1546
+ (function (ConfirmSwapWarningTypes) {
1547
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
1548
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
1549
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
1550
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
1551
+ })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
1692
1552
 
1693
- const Container$2 = /*#__PURE__*/ui.styled('div', {
1694
- display: 'flex',
1695
- flexDirection: 'column'
1696
- });
1697
- const FromContainer = /*#__PURE__*/ui.styled('div', {
1698
- position: 'relative',
1699
- paddingBottom: '$12'
1700
- });
1701
- const SwitchButtonContainer = /*#__PURE__*/ui.styled('div', {
1702
- position: 'absolute',
1703
- bottom: '-12px',
1704
- left: '50%',
1705
- transform: 'translate(-50%, 10%)'
1706
- });
1707
- const BestRouteContainer = /*#__PURE__*/ui.styled('div', {
1708
- width: '100%',
1709
- paddingTop: '$16'
1710
- });
1711
- const Alerts = /*#__PURE__*/ui.styled('div', {
1712
- width: '100%',
1713
- paddingTop: '$16'
1714
- });
1715
- function Home() {
1716
- const isRouterInContext = reactRouterDom.useInRouterContext();
1717
- const navigate = reactRouterDom.useNavigate();
1718
- const [count, setCount] = React.useState(0);
1719
- const fromChain = useBestRouteStore.use.fromChain();
1553
+ function useConfirmSwap() {
1720
1554
  const fromToken = useBestRouteStore.use.fromToken();
1721
- const toChain = useBestRouteStore.use.toChain();
1722
1555
  const toToken = useBestRouteStore.use.toToken();
1723
- const setInputAmount = useBestRouteStore.use.setInputAmount();
1724
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1725
1556
  const inputAmount = useBestRouteStore.use.inputAmount();
1726
- const outputAmount = useBestRouteStore.use.outputAmount();
1727
- const outputUsdValue = useBestRouteStore.use.outputUsdValue();
1728
- const bestRoute = useBestRouteStore.use.bestRoute();
1729
- const tokens = useMetaStore.use.meta().tokens;
1730
- const fetchingBestRoute = useBestRouteStore.use.loading();
1731
- const bestRouteError = useBestRouteStore.use.error();
1732
- const loadingMetaStatus = useMetaStore.use.loadingStatus();
1557
+ const initialRoute = useBestRouteStore.use.bestRoute();
1558
+ const setBestRoute = useBestRouteStore.use.setBestRoute();
1559
+ const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1560
+ const affiliateRef = useSettingsStore.use.affiliateRef();
1733
1561
  const accounts = useWalletsStore.use.accounts();
1734
- const setCurrentPage = useUiStore.use.setCurrentPage();
1735
- const switchFromAndTo = useBestRouteStore.use.switchFromAndTo();
1736
- const errorMessage = loadingMetaStatus === 'failed' ? errorMessages.genericServerError : bestRouteError;
1737
- const needsToWarnEthOnPath = false;
1738
- const showBestRoute = inputAmount && (!!bestRoute || fetchingBestRoute || bestRouteError);
1739
- const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);
1740
- const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);
1741
- const {
1742
- fromAmountRangeError,
1743
- recommendation,
1744
- swap
1745
- } = LimitErrorMessage(bestRoute);
1746
- const priceImpactCanNotBeComputed = !canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue);
1747
- const swapButtonState = getSwapButtonState(loadingMetaStatus, accounts, fetchingBestRoute, bestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath, inputAmount);
1748
- const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
1749
- const highFee = hasHighFee(totalFeeInUsd);
1562
+ const selectedWallets = useWalletsStore.use.selectedWallets();
1563
+ const meta = useMetaStore.use.meta();
1564
+ const customSlippage = useSettingsStore.use.customSlippage();
1565
+ const slippage = useSettingsStore.use.slippage();
1566
+ const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
1567
+ const userSlippage = customSlippage || slippage;
1568
+ const proceedAnywayRef = React.useRef(false);
1569
+ const confiremedRouteRef = React.useRef(null);
1570
+ let abortControllerRef = React.useRef(null);
1571
+ const [loading, setLoading] = React.useState(false);
1572
+ const [errors, setErrors] = React.useState([]);
1573
+ const [warnings, setWarnings] = React.useState([]);
1750
1574
  React.useEffect(() => {
1751
- setCurrentPage(navigationRoutes.home);
1752
- return setCurrentPage.bind(null, '');
1575
+ return () => abortControllerRef.current?.abort();
1753
1576
  }, []);
1754
- return React__default.createElement(Container$2, null, React__default.createElement(ui.Header, {
1755
- title: "SWAP",
1756
- suffix: React__default.createElement(HeaderButtons, {
1757
- onClickRefresh: !!bestRoute ? fetchBestRoute : undefined
1758
- })
1759
- }), React__default.createElement(FromContainer, null, React__default.createElement(TokenInfo, {
1760
- type: "From",
1761
- chain: fromChain,
1762
- token: fromToken,
1763
- onAmountChange: setInputAmount,
1764
- inputAmount: inputAmount
1765
- }), React__default.createElement(SwitchButtonContainer, null, React__default.createElement(ui.Button, {
1766
- variant: "ghost",
1767
- onClick: () => {
1768
- switchFromAndTo();
1769
- setCount(prev => prev + 1);
1577
+ if (!fromToken || !toToken || !inputAmount || !initialRoute) return {
1578
+ loading: false,
1579
+ warnings: [],
1580
+ errors: [],
1581
+ confirmSwap: null
1582
+ };
1583
+ const confirmSwap = async () => {
1584
+ if (proceedAnywayRef.current) {
1585
+ const swapSettings = {
1586
+ slippage: userSlippage.toString(),
1587
+ disabledSwappersGroups: disabledLiquiditySources
1588
+ };
1589
+ if (errors.length > 0) setErrors([]);
1590
+ if (warnings.length > 0) setWarnings([]);
1591
+ proceedAnywayRef.current = false;
1592
+ if (confiremedRouteRef.current) {
1593
+ const newSwap = queueManagerRangoPreset.calculatePendingSwap(inputAmount.toString(), confiremedRouteRef.current, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
1594
+ return newSwap;
1595
+ }
1596
+ return;
1770
1597
  }
1771
- }, React__default.createElement(ui.VerticalSwapIcon, {
1772
- size: 32
1773
- }), isRouterInContext && React__default.createElement(SwithFromAndTo, {
1774
- count: count
1775
- })))), React__default.createElement(TokenInfo, {
1776
- type: "To",
1777
- chain: toChain,
1778
- token: toToken,
1779
- outputAmount: outputAmount ? new BigNumber__default(outputAmount) : new BigNumber__default(0),
1780
- outputUsdValue: outputUsdValue
1781
- }), showBestRoute && React__default.createElement(BestRouteContainer, null, React__default.createElement(ui.BestRoute, {
1782
- error: bestRouteError,
1783
- loading: fetchingBestRoute,
1784
- data: getFormatedBestRoute(bestRoute),
1785
- totalFee: numberToString(totalFeeInUsd, 0, 2),
1786
- feeWarning: highFee,
1787
- totalTime: secondsToString(totalArrivalTime(bestRoute))
1788
- })), (errorMessage || hasLimitError(bestRoute)) && React__default.createElement(Alerts, null, errorMessage && React__default.createElement(ui.Alert, {
1789
- type: "error"
1790
- }, errorMessage), hasLimitError(bestRoute) && React__default.createElement(ui.Alert, {
1791
- type: "error",
1792
- title: `${swap?.swapperId} Limit`
1793
- }, React__default.createElement(React__default.Fragment, null, React__default.createElement(ui.Typography, {
1794
- variant: "body2"
1795
- }, `${fromAmountRangeError}, Yours: ${numberToString(swap?.fromAmount || null)} ${swap?.from.symbol}`), React__default.createElement(ui.Typography, {
1796
- variant: "body2"
1797
- }, recommendation)))), React__default.createElement(Footer, null, React__default.createElement(ui.Button, {
1798
- type: "primary",
1799
- align: "grow",
1800
- size: "large",
1801
- disabled: swapButtonState.disabled,
1802
- onClick: () => {
1803
- if (swapButtonState.title === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
1804
- navigate(navigationRoutes.confirmSwap, {
1805
- replace: true
1598
+ abortControllerRef.current = new AbortController();
1599
+ setLoading(true);
1600
+ const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, accounts, selectedWallets, disabledLiquiditySources, userSlippage, affiliateRef, initialRoute);
1601
+ try {
1602
+ const confiremedRoute = await httpService().getBestRoute(requestBody, {
1603
+ signal: abortControllerRef.current?.signal
1604
+ });
1605
+ abortControllerRef.current = null;
1606
+ setLoading(false);
1607
+ if (!confiremedRoute.result || !new BigNumber__default(confiremedRoute.requestAmount).isEqualTo(new BigNumber__default(inputAmount || '-1'))) {
1608
+ setErrors(prevState => prevState.concat({
1609
+ type: ConfirmSwapErrorTypes.NO_ROUTE
1610
+ }));
1611
+ return;
1612
+ }
1613
+ const confirmSwapState = {
1614
+ errors: [],
1615
+ warnings: []
1616
+ };
1617
+ const routeChanged = isRouteChanged(initialRoute, confiremedRoute);
1618
+ if (routeChanged) {
1619
+ setBestRoute(confiremedRoute);
1620
+ const newRouteOutputUsdValue = new BigNumber__default(confiremedRoute.result?.outputAmount || '0').multipliedBy(toToken.usdPrice || 0);
1621
+ const outputRatio = getOutputRatio(inputUsdValue, newRouteOutputUsdValue);
1622
+ const highValueLoss = outputRatioHasWarning(inputUsdValue, outputRatio);
1623
+ if (highValueLoss) confirmSwapState.errors.push({
1624
+ type: ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS
1625
+ });else if (isOutputAmountChangedALot(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1626
+ type: ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED,
1627
+ newOutputAmount: numberToString(getRouteOutputAmount(confiremedRoute)),
1628
+ percentageChange: numberToString(getPercentageChange(getRouteOutputAmount(initialRoute), getRouteOutputAmount(confiremedRoute)), null, 2)
1629
+ });else if (isRouteInternalCoinsUpdated(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1630
+ type: ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED
1631
+ });else if (isNumberOfSwapsChanged(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1632
+ type: ConfirmSwapWarningTypes.ROUTE_UPDATED
1633
+ });else if (isRouteSwappersUpdated(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
1634
+ type: ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED
1806
1635
  });
1807
1636
  }
1808
- }
1809
- }, swapButtonState.title), React__default.createElement(BottomLogo, null)));
1810
- }
1811
-
1812
- const Route = _ref => {
1813
- let {
1814
- children
1815
- } = _ref;
1816
- const location = reactRouter.useLocation();
1817
- const navigate = reactRouter.useNavigate();
1818
- const ref = React.useRef(true);
1819
- React.useEffect(() => {
1820
- if (location.pathname === navigationRoutes.confirmSwap && ref.current) navigate(navigationRoutes.home + location.search, {
1821
- state: 'redirect'
1822
- });
1823
- ref.current = false;
1824
- }, []);
1825
- if (location.pathname === navigationRoutes.confirmSwap && ref.current) return React__default.createElement(Home, null);
1826
- return React__default.createElement(React__default.Fragment, null, " ", children);
1827
- };
1828
- function AppRouter(_ref2) {
1829
- let {
1830
- children,
1831
- ...props
1832
- } = _ref2;
1833
- const isRouterInContext = reactRouter.useInRouterContext();
1834
- const Router = isRouterInContext ? Route : reactRouter.MemoryRouter;
1835
- const {
1836
- blockchains
1837
- } = useMetaStore.use.meta();
1838
- const evmChains = blockchains.filter(rangoTypes.isEvmBlockchain);
1839
- queueManagerRangoPreset.useQueueManager({
1840
- lastConnectedWallet: props.lastConnectedWallet,
1841
- clearDisconnectedWallet: props.clearDisconnectedWallet,
1842
- disconnectedWallet: props.disconnectedWallet,
1843
- evmChains,
1844
- notifier: () => {}
1845
- });
1846
- return React__default.createElement(React__default.Fragment, null, React__default.createElement(Router, Object.assign({}, props), children), isRouterInContext && React__default.createElement(UpdateUrl, null));
1847
- }
1848
-
1849
- function useNavigateBack() {
1850
- const isRouterInContext = reactRouterDom.useInRouterContext();
1851
- const navigate = reactRouterDom.useNavigate();
1852
- const navigateBackFrom = currentRoute => {
1853
- if (currentRoute === navigationRoutes.swapDetails) return navigate(navigationRoutes.swaps, {
1854
- replace: true
1855
- });
1856
- if (!isRouterInContext || window.history.state && window.history.state.idx > 0) navigate(-1);else {
1857
- if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.swaps, navigationRoutes.confirmSwap].includes(currentRoute)) navigate(navigationRoutes.home, {
1858
- replace: true
1859
- });else if (currentRoute === navigationRoutes.liquiditySources) navigate(navigationRoutes.settings, {
1860
- replace: true
1861
- });else if (currentRoute === navigationRoutes.swapDetails) navigate(navigationRoutes.swaps, {
1862
- replace: true
1637
+ const balanceWarnings = getBalanceWarnings(confiremedRoute, selectedWallets);
1638
+ const enoughBalance = balanceWarnings.length === 0;
1639
+ if (!enoughBalance) confirmSwapState.errors.push({
1640
+ type: ConfirmSwapErrorTypes.INSUFFICIENT_BALANCE,
1641
+ messages: balanceWarnings
1642
+ });
1643
+ const minRequiredSlippage = getMinRequiredSlippage(initialRoute);
1644
+ if (!hasProperSlippage(userSlippage.toString(), minRequiredSlippage)) confirmSwapState.errors.push({
1645
+ type: ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE,
1646
+ minRequiredSlippage
1863
1647
  });
1648
+ const noErrors = confirmSwapState.errors.length === 0;
1649
+ const noWarnings = confirmSwapState.warnings.length === 0;
1650
+ if ((noErrors || !noErrors && proceedAnywayRef.current) && (noWarnings || !noWarnings && proceedAnywayRef.current)) {
1651
+ const swapSettings = {
1652
+ slippage: userSlippage.toString(),
1653
+ disabledSwappersGroups: disabledLiquiditySources
1654
+ };
1655
+ const newSwap = queueManagerRangoPreset.calculatePendingSwap(inputAmount.toString(), confiremedRoute, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
1656
+ return newSwap;
1657
+ } else if (!proceedAnywayRef.current) {
1658
+ proceedAnywayRef.current = true;
1659
+ setErrors(confirmSwapState.errors);
1660
+ setWarnings(confirmSwapState.warnings);
1661
+ confiremedRouteRef.current = confiremedRoute;
1662
+ }
1663
+ return;
1664
+ } catch (error) {
1665
+ if (error?.code === 'ERR_CANCELED') {
1666
+ return;
1667
+ }
1668
+ const status = error?.response?.status;
1669
+ setLoading(false);
1670
+ setErrors([{
1671
+ type: ConfirmSwapErrorTypes.REQUEST_FAILED,
1672
+ status
1673
+ }]);
1674
+ return;
1864
1675
  }
1865
1676
  };
1866
1677
  return {
1867
- navigateBackFrom
1678
+ loading,
1679
+ warnings,
1680
+ errors,
1681
+ confirmSwap
1868
1682
  };
1869
1683
  }
1870
1684
 
1871
- const Box$1 = /*#__PURE__*/ui.styled('div', {
1872
- display: 'flex',
1873
- flexDirection: 'column',
1874
- width: '100%'
1685
+ function ChangeSlippageButton() {
1686
+ const navigate = reactRouterDom.useNavigate();
1687
+ return React__default.createElement(ui.Button, {
1688
+ type: "primary",
1689
+ variant: "outlined",
1690
+ size: "small",
1691
+ onClick: () => navigate('/' + navigationRoutes.settings)
1692
+ }, "Change Slippage");
1693
+ }
1694
+
1695
+ const StyledMessage = /*#__PURE__*/ui.styled(ui.Typography, {
1696
+ color: '$error500 !important'
1875
1697
  });
1876
- const Container$3 = /*#__PURE__*/ui.styled('div', {
1877
- boxSizing: 'border-box',
1878
- borderRadius: '$5',
1879
- padding: '$8 $16 $16 $16',
1698
+ function MinRequiredSlippage(_ref) {
1699
+ let {
1700
+ minRequiredSlippage
1701
+ } = _ref;
1702
+ return React__default.createElement(StyledMessage, {
1703
+ variant: "body2"
1704
+ }, "We recommend you to increase slippage to at least \u00A0", minRequiredSlippage, "\u00A0 for this route.", React__default.createElement(ui.Spacer, {
1705
+ size: 8,
1706
+ direction: "vertical"
1707
+ }), React__default.createElement(ChangeSlippageButton, null));
1708
+ }
1709
+
1710
+ const List = /*#__PURE__*/ui.styled('ul', {
1711
+ padding: 0,
1712
+ margin: 0,
1880
1713
  variants: {
1881
- type: {
1882
- filled: {
1883
- backgroundColor: '$neutrals300'
1884
- },
1885
- outlined: {
1886
- border: '1px solid $neutrals300'
1714
+ showListStyle: {
1715
+ true: {
1716
+ paddingLeft: '$24'
1887
1717
  }
1888
1718
  }
1889
- },
1890
- defaultVariants: {
1891
- type: 'filled'
1892
- },
1893
- '.head': {
1894
- display: 'flex',
1895
- justifyContent: 'space-between',
1896
- alignItems: 'center',
1897
- minHeight: '32px',
1898
- '.usd-value': {
1899
- paddingLeft: '$8'
1900
- }
1901
- },
1902
- '.form': {
1903
- display: 'flex',
1904
- width: '100%',
1905
- padding: '$2 0',
1906
- '.selectors': {
1907
- width: '35%',
1908
- '._text': {
1909
- whiteSpace: 'nowrap',
1910
- overflow: 'hidden',
1911
- textOverflow: 'ellipsis'
1719
+ }
1720
+ });
1721
+ const ListItem = /*#__PURE__*/ui.styled('li', {
1722
+ variants: {
1723
+ showListStyle: {
1724
+ true: {
1725
+ listStyleType: 'disc',
1726
+ listStylePosition: 'outside'
1912
1727
  }
1913
- },
1914
- '.amount': {
1915
- width: '30%'
1916
1728
  }
1917
1729
  }
1918
1730
  });
1919
- const ImagePlaceholder$1 = /*#__PURE__*/ui.styled('span', {
1920
- width: '24px',
1921
- height: '24px',
1922
- backgroundColor: '$neutrals300',
1923
- borderRadius: '99999px'
1924
- });
1925
- const OutputContainer$1 = /*#__PURE__*/ui.styled('div', {
1926
- windth: '100%',
1927
- height: '$48',
1928
- borderRadius: '$5',
1929
- backgroundColor: '$background',
1930
- border: '1px solid transparent',
1931
- position: 'relative',
1932
- display: 'flex',
1933
- alignItems: 'center',
1934
- paddingLeft: '$8',
1935
- paddingRight: '$8'
1731
+ const Message = /*#__PURE__*/ui.styled(ui.Typography, {
1732
+ display: 'block'
1936
1733
  });
1937
- function TokenPreview(props) {
1938
- const {
1939
- chain,
1940
- token,
1941
- loadingStatus,
1942
- percentageChange
1943
- } = props;
1944
- const {
1945
- t
1946
- } = reactI18next.useTranslation();
1947
- const ItemSuffix = React__default.createElement("div", {
1948
- style: {
1949
- display: 'flex',
1950
- justifyContent: 'center',
1951
- alignItems: 'center'
1734
+ function BalanceErrors(_ref) {
1735
+ let {
1736
+ messages
1737
+ } = _ref;
1738
+ const showListStyle = messages.length > 1;
1739
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement(ui.Typography, {
1740
+ className: "title",
1741
+ variant: "title",
1742
+ color: 'error'
1743
+ }, "Insufficent Balance:"), React__default.createElement(ui.Spacer, {
1744
+ size: 8,
1745
+ direction: "vertical"
1746
+ }), React__default.createElement(List, {
1747
+ showListStyle: showListStyle
1748
+ }, messages.map((warning, index) => React__default.createElement(ListItem, {
1749
+ showListStyle: showListStyle,
1750
+ key: index
1751
+ }, React__default.createElement(Message, {
1752
+ variant: "body2"
1753
+ }, warning)))));
1754
+ }
1755
+
1756
+ function ConfirmSwapErrors(errors) {
1757
+ return errors.flatMap(error => {
1758
+ switch (error.type) {
1759
+ case ConfirmSwapErrorTypes.NO_ROUTE:
1760
+ return 'No routes found. Please try again later.';
1761
+ case ConfirmSwapErrorTypes.REQUEST_FAILED:
1762
+ return `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`;
1763
+ case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
1764
+ return 'Route updated and price impact is too high, try again later!';
1765
+ case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
1766
+ return React__default.createElement(MinRequiredSlippage, {
1767
+ minRequiredSlippage: error.minRequiredSlippage
1768
+ });
1769
+ case ConfirmSwapErrorTypes.INSUFFICIENT_BALANCE:
1770
+ return React__default.createElement(BalanceErrors, {
1771
+ messages: error.messages
1772
+ });
1773
+ default:
1774
+ return [];
1952
1775
  }
1953
- }, loadingStatus === 'failed' && React__default.createElement(ui.InfoCircleIcon, {
1954
- color: "error",
1955
- size: 24
1956
- }));
1957
- return React__default.createElement(Box$1, null, React__default.createElement(Container$3, {
1958
- type: 'outlined'
1959
- }, React__default.createElement("div", {
1960
- className: "head"
1961
- }, React__default.createElement(ui.Typography, {
1962
- variant: "body2",
1963
- color: "neutrals800"
1964
- }, props.label), React__default.createElement("div", null, percentageChange, props.usdValue && React__default.createElement(ui.Typography, {
1965
- variant: "caption",
1966
- color: "neutrals600",
1967
- className: "usd-value"
1968
- }, `$${numberToString(props.usdValue)}`))), React__default.createElement("div", {
1969
- className: "form"
1970
- }, React__default.createElement(ui.Button, {
1971
- className: "selectors",
1972
- variant: "outlined",
1973
- loading: loadingStatus === 'loading',
1974
- prefix: loadingStatus === 'success' && chain ? React__default.createElement(ui.Image, {
1975
- src: chain.logo,
1976
- size: 24
1977
- }) : React__default.createElement(ImagePlaceholder$1, null),
1978
- suffix: ItemSuffix,
1979
- align: "start",
1980
- size: "large"
1981
- }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React__default.createElement(ui.Spacer, {
1982
- size: 12
1983
- }), React__default.createElement(ui.Button, {
1984
- className: "selectors",
1985
- variant: "outlined",
1986
- loading: loadingStatus === 'loading',
1987
- prefix: loadingStatus === 'success' && token ? React__default.createElement(ui.Image, {
1988
- src: token.image,
1989
- size: 24
1990
- }) : React__default.createElement(ImagePlaceholder$1, null),
1991
- suffix: ItemSuffix,
1992
- size: "large",
1993
- align: "start"
1994
- }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React__default.createElement(ui.Spacer, {
1995
- size: 12
1996
- }), React__default.createElement("div", {
1997
- className: "amount"
1998
- }, React__default.createElement(OutputContainer$1, null, React__default.createElement(ui.Typography, {
1999
- variant: "h4"
2000
- }, props.amount))))));
1776
+ });
2001
1777
  }
2002
1778
 
2003
- const Container$4 = /*#__PURE__*/ui.styled('div', {
2004
- display: 'flex',
2005
- alignItems: 'center',
2006
- justifyContent: 'space-between',
2007
- padding: '$8',
2008
- borderRadius: '$5',
2009
- backgroundColor: '$neutrals300',
2010
- color: '$neutrals800',
2011
- fontSize: '$12',
2012
- '.routes': {
2013
- display: 'flex',
2014
- alignItems: 'center'
2015
- },
2016
- '.fee': {
2017
- display: 'flex',
2018
- alignItems: 'center'
2019
- }
2020
- });
2021
- function RoutesOverview(props) {
2022
- if (!props.routes) return null;
2023
- const swaps = props.routes.result?.swaps;
2024
- return React__default.createElement(Container$4, null, React__default.createElement("div", {
2025
- className: "routes"
2026
- }, swaps?.map((swap, idx) => {
2027
- const isLast = idx + 1 == swaps.length;
2028
- return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
2029
- className: "route"
2030
- }, swap.from.symbol), React__default.createElement(ui.ChevronRightIcon, {
2031
- size: 12
2032
- }), isLast ? React__default.createElement("div", {
2033
- className: "route"
2034
- }, swap.to.symbol) : null);
2035
- })), props.totalFee ? React__default.createElement("div", {
2036
- className: "fee"
2037
- }, React__default.createElement(ui.GasIcon, {
2038
- size: 12
2039
- }), React__default.createElement(ui.Spacer, {
2040
- size: 4
2041
- }), "$", props.totalFee) : null);
1779
+ function ConfirmSwapWarnings(warnings) {
1780
+ return warnings.flatMap(warning => {
1781
+ switch (warning.type) {
1782
+ case ConfirmSwapWarningTypes.ROUTE_UPDATED:
1783
+ return "Route has been updated.";
1784
+ case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
1785
+ return `Output amount changed to ${warning.newOutputAmount} (${warning.percentageChange}% change).`;
1786
+ case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
1787
+ return "Route swappers has been updated.";
1788
+ case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
1789
+ return "Route internal coins has been updated.";
1790
+ default:
1791
+ return [];
1792
+ }
1793
+ });
2042
1794
  }
2043
1795
 
2044
- var ConfirmSwapErrorTypes;
2045
- (function (ConfirmSwapErrorTypes) {
2046
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
2047
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
2048
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
2049
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
2050
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
2051
- })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
2052
- var ConfirmSwapWarningTypes;
2053
- (function (ConfirmSwapWarningTypes) {
2054
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
2055
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
2056
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
2057
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
2058
- })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
1796
+ function HighSlippageWarning(props) {
1797
+ const {
1798
+ selectedSlippage
1799
+ } = props;
1800
+ return React__default.createElement(ui.Alert, {
1801
+ type: "warning",
1802
+ footer: React__default.createElement(ChangeSlippageButton, null)
1803
+ }, "Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.");
1804
+ }
2059
1805
 
2060
- function useConfirmSwap() {
2061
- const fromToken = useBestRouteStore.use.fromToken();
2062
- const toToken = useBestRouteStore.use.toToken();
2063
- const inputAmount = useBestRouteStore.use.inputAmount();
2064
- const initialRoute = useBestRouteStore.use.bestRoute();
2065
- const setBestRoute = useBestRouteStore.use.setBestRoute();
2066
- const inputUsdValue = useBestRouteStore.use.inputUsdValue();
2067
- const affiliateRef = useSettingsStore.use.affiliateRef();
1806
+ function ConfirmSwapExtraMessages(props) {
1807
+ const {
1808
+ selectedSlippage
1809
+ } = props;
1810
+ const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
1811
+ return React__default.createElement(React__default.Fragment, null, highSlippage && React__default.createElement(HighSlippageWarning, {
1812
+ selectedSlippage: selectedSlippage
1813
+ }));
1814
+ }
1815
+
1816
+ function PercentageChange(props) {
1817
+ const {
1818
+ inputUsdValue,
1819
+ outputUsdValue
1820
+ } = props;
1821
+ if (!inputUsdValue || !outputUsdValue || !outputUsdValue.gt(0)) return null;
1822
+ const percentageChange = getPercentageChange(inputUsdValue.toNumber(), outputUsdValue.toNumber());
1823
+ const showPercentageChange = percentageChange?.lt(0);
1824
+ return React__default.createElement(React__default.Fragment, null, showPercentageChange && React__default.createElement(ui.Typography, {
1825
+ variant: "caption",
1826
+ color: "$error500"
1827
+ }, `(${numberToString(percentageChange, 0, 2)}%)`));
1828
+ }
1829
+
1830
+ function ConfirmSwapPage() {
1831
+ const navigate = reactRouterDom.useNavigate();
1832
+ const {
1833
+ navigateBackFrom
1834
+ } = useNavigateBack();
1835
+ const bestRoute = useBestRouteStore.use.bestRoute();
1836
+ const fetchingBestRoute = useBestRouteStore.use.loading();
1837
+ const fetchingBestRouteError = useBestRouteStore.use.error();
1838
+ const setSelectedSwap = useUiStore.use.setSelectedSwap();
1839
+ const {
1840
+ blockchains,
1841
+ tokens
1842
+ } = useMetaStore.use.meta();
1843
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2068
1844
  const accounts = useWalletsStore.use.accounts();
2069
1845
  const selectedWallets = useWalletsStore.use.selectedWallets();
2070
- const meta = useMetaStore.use.meta();
2071
- const customSlippage = useSettingsStore.use.customSlippage();
1846
+ const initSelectedWallets = useWalletsStore.use.initSelectedWallets();
1847
+ const setSelectedWallet = useWalletsStore.use.setSelectedWallet();
2072
1848
  const slippage = useSettingsStore.use.slippage();
2073
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2074
- const userSlippage = customSlippage || slippage;
2075
- const proceedAnywayRef = React.useRef(false);
2076
- const confiremedRouteRef = React.useRef(null);
2077
- let abortControllerRef = React.useRef(null);
2078
- const [loading, setLoading] = React.useState(false);
2079
- const [errors, setErrors] = React.useState([]);
2080
- const [warnings, setWarnings] = React.useState([]);
1849
+ const customSlippage = useSettingsStore.use.customSlippage();
1850
+ const inputUsdValue = useBestRouteStore.use.inputUsdValue();
1851
+ const outputUsdValue = useBestRouteStore.use.outputUsdValue();
1852
+ const setInputAmount = useBestRouteStore.use.setInputAmount();
1853
+ const bestRouteloadingStatus = getBestRouteStatus(fetchingBestRoute, !!fetchingBestRouteError);
1854
+ const {
1855
+ manager
1856
+ } = queueManagerReact.useManager();
1857
+ const {
1858
+ loading: fetchingConfirmedRoute,
1859
+ errors,
1860
+ warnings,
1861
+ confirmSwap
1862
+ } = useConfirmSwap();
1863
+ const selectedSlippage = customSlippage || slippage;
1864
+ const showHighSlippageWarning = !errors.find(error => error.type === ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE);
1865
+ const {
1866
+ getWalletInfo,
1867
+ connect
1868
+ } = walletsCore.useWallets();
1869
+ const confirmDisabled = fetchingBestRoute || !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
1870
+ const firstStep = bestRoute?.result?.swaps[0];
1871
+ const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
1872
+ const fromAmount = numberToString(firstStep?.fromAmount, 4, 6);
1873
+ const toAmount = numberToString(lastStep?.toAmount, 4, 6);
2081
1874
  React.useEffect(() => {
2082
- return () => abortControllerRef.current?.abort();
1875
+ initSelectedWallets();
2083
1876
  }, []);
2084
- if (!fromToken || !toToken || !inputAmount || !initialRoute) return {
2085
- loading: false,
2086
- warnings: [],
2087
- errors: [],
2088
- confirmSwap: null
1877
+ const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
1878
+ const handleConnectChain = wallet => {
1879
+ const network = wallet;
1880
+ getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
2089
1881
  };
2090
- const confirmSwap = async () => {
2091
- if (proceedAnywayRef.current) {
2092
- const swapSettings = {
2093
- slippage: userSlippage.toString(),
2094
- disabledSwappersGroups: disabledLiquiditySources
2095
- };
2096
- if (errors.length > 0) setErrors([]);
2097
- if (warnings.length > 0) setWarnings([]);
2098
- proceedAnywayRef.current = false;
2099
- if (confiremedRouteRef.current) {
2100
- const newSwap = queueManagerRangoPreset.calculatePendingSwap(inputAmount.toString(), confiremedRouteRef.current, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
2101
- return newSwap;
2102
- }
2103
- return;
2104
- }
2105
- abortControllerRef.current = new AbortController();
2106
- setLoading(true);
2107
- const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, accounts, selectedWallets, disabledLiquiditySources, userSlippage, affiliateRef, initialRoute);
2108
- try {
2109
- const confiremedRoute = await httpService().getBestRoute(requestBody, {
2110
- signal: abortControllerRef.current?.signal
2111
- });
2112
- abortControllerRef.current = null;
2113
- setLoading(false);
2114
- if (!confiremedRoute.result || !new BigNumber__default(confiremedRoute.requestAmount).isEqualTo(new BigNumber__default(inputAmount || '-1'))) {
2115
- setErrors(prevState => prevState.concat({
2116
- type: ConfirmSwapErrorTypes.NO_ROUTE
2117
- }));
2118
- return;
2119
- }
2120
- const confirmSwapState = {
2121
- errors: [],
2122
- warnings: []
2123
- };
2124
- const routeChanged = isRouteChanged(initialRoute, confiremedRoute);
2125
- if (routeChanged) {
2126
- setBestRoute(confiremedRoute);
2127
- const newRouteOutputUsdValue = new BigNumber__default(confiremedRoute.result?.outputAmount || '0').multipliedBy(toToken.usdPrice || 0);
2128
- const outputRatio = getOutputRatio(inputUsdValue, newRouteOutputUsdValue);
2129
- const highValueLoss = outputRatioHasWarning(inputUsdValue, outputRatio);
2130
- if (highValueLoss) confirmSwapState.errors.push({
2131
- type: ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS
2132
- });else if (isOutputAmountChangedALot(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
2133
- type: ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED,
2134
- newOutputAmount: numberToString(getRouteOutputAmount(confiremedRoute)),
2135
- percentageChange: numberToString(getPercentageChange(getRouteOutputAmount(initialRoute), getRouteOutputAmount(confiremedRoute)), null, 2)
2136
- });else if (isRouteInternalCoinsUpdated(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
2137
- type: ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED
2138
- });else if (isNumberOfSwapsChanged(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
2139
- type: ConfirmSwapWarningTypes.ROUTE_UPDATED
2140
- });else if (isRouteSwappersUpdated(initialRoute, confiremedRoute)) confirmSwapState.warnings.push({
2141
- type: ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED
2142
- });
2143
- }
2144
- const balanceWarnings = getBalanceWarnings(confiremedRoute, selectedWallets);
2145
- const enoughBalance = balanceWarnings.length === 0;
2146
- if (!enoughBalance) confirmSwapState.errors.push({
2147
- type: ConfirmSwapErrorTypes.INSUFFICIENT_BALANCE,
2148
- messages: balanceWarnings
1882
+ const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
1883
+ return React__default.createElement(ui.ConfirmSwap, {
1884
+ requiredWallets: getRequiredChains(bestRoute),
1885
+ selectableWallets: selectableWallets,
1886
+ onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
1887
+ onConfirm: () => {
1888
+ confirmSwap?.().then(swap => {
1889
+ if (swap) {
1890
+ manager?.create('swap', {
1891
+ swapDetails: swap
1892
+ }, {
1893
+ id: swap.requestId
1894
+ });
1895
+ setSelectedSwap(swap.requestId);
1896
+ navigate('/' + navigationRoutes.swaps + `/${swap.requestId}`, {
1897
+ replace: true
1898
+ });
1899
+ setTimeout(() => {
1900
+ setInputAmount('');
1901
+ }, 0);
1902
+ }
2149
1903
  });
2150
- const minRequiredSlippage = getMinRequiredSlippage(initialRoute);
2151
- if (!hasProperSlippage(userSlippage.toString(), minRequiredSlippage)) confirmSwapState.errors.push({
2152
- type: ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE,
2153
- minRequiredSlippage
1904
+ },
1905
+ onChange: wallet => setSelectedWallet(wallet),
1906
+ confirmDisabled: loadingMetaStatus !== 'success' || confirmDisabled,
1907
+ handleConnectChain: wallet => handleConnectChain(wallet),
1908
+ isExperimentalChain: wallet => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains, wallet) : false,
1909
+ previewInputs: React__default.createElement(React__default.Fragment, null, React__default.createElement(TokenPreview, {
1910
+ chain: {
1911
+ displayName: firstStep?.from.blockchain || '',
1912
+ logo: firstStep?.from.blockchainLogo || ''
1913
+ },
1914
+ token: {
1915
+ symbol: firstStep?.from.symbol || '',
1916
+ image: firstStep?.from.logo || ''
1917
+ },
1918
+ usdValue: inputUsdValue,
1919
+ amount: fromAmount,
1920
+ label: i18n.t('From'),
1921
+ loadingStatus: loadingMetaStatus !== 'success' ? loadingMetaStatus : bestRouteloadingStatus
1922
+ }), React__default.createElement(ui.Spacer, {
1923
+ size: 12,
1924
+ direction: "vertical"
1925
+ }), React__default.createElement(TokenPreview, {
1926
+ chain: {
1927
+ displayName: lastStep?.to.blockchain || '',
1928
+ logo: lastStep?.to.blockchainLogo || ''
1929
+ },
1930
+ token: {
1931
+ symbol: lastStep?.to.symbol || '',
1932
+ image: lastStep?.to.logo || ''
1933
+ },
1934
+ usdValue: outputUsdValue,
1935
+ amount: toAmount,
1936
+ label: i18n.t('To'),
1937
+ loadingStatus: loadingMetaStatus !== 'success' ? loadingMetaStatus : bestRouteloadingStatus,
1938
+ percentageChange: React__default.createElement(PercentageChange, {
1939
+ inputUsdValue: inputUsdValue,
1940
+ outputUsdValue: outputUsdValue
1941
+ })
1942
+ })),
1943
+ previewRoutes: React__default.createElement(RoutesOverview, {
1944
+ routes: bestRoute,
1945
+ totalFee: numberToString(totalFeeInUsd, 0, 2)
1946
+ }),
1947
+ loading: fetchingConfirmedRoute,
1948
+ errors: ConfirmSwapErrors(errors),
1949
+ warnings: ConfirmSwapWarnings(warnings),
1950
+ extraMessages: React__default.createElement(React__default.Fragment, null, loadingMetaStatus === 'failed' && React__default.createElement(ui.LoadingFailedAlert, null), loadingMetaStatus === 'failed' && showHighSlippageWarning && React__default.createElement(ui.Spacer, {
1951
+ direction: "vertical"
1952
+ }), showHighSlippageWarning && React__default.createElement(ConfirmSwapExtraMessages, {
1953
+ selectedSlippage: selectedSlippage
1954
+ })),
1955
+ confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!'
1956
+ });
1957
+ }
1958
+
1959
+ const getPendingSwaps = manager => {
1960
+ const result = [];
1961
+ manager?.getAll().forEach((q, id) => {
1962
+ const storage = q.list.getStorage();
1963
+ if (storage?.swapDetails) {
1964
+ result.push({
1965
+ id,
1966
+ swap: storage?.swapDetails
2154
1967
  });
2155
- const noErrors = confirmSwapState.errors.length === 0;
2156
- const noWarnings = confirmSwapState.warnings.length === 0;
2157
- if ((noErrors || !noErrors && proceedAnywayRef.current) && (noWarnings || !noWarnings && proceedAnywayRef.current)) {
2158
- const swapSettings = {
2159
- slippage: userSlippage.toString(),
2160
- disabledSwappersGroups: disabledLiquiditySources
2161
- };
2162
- const newSwap = queueManagerRangoPreset.calculatePendingSwap(inputAmount.toString(), confiremedRoute, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
2163
- return newSwap;
2164
- } else if (!proceedAnywayRef.current) {
2165
- proceedAnywayRef.current = true;
2166
- setErrors(confirmSwapState.errors);
2167
- setWarnings(confirmSwapState.warnings);
2168
- confiremedRouteRef.current = confiremedRoute;
2169
- }
2170
- return;
2171
- } catch (error) {
2172
- if (error?.code === 'ERR_CANCELED') {
2173
- return;
2174
- }
2175
- const status = error?.response?.status;
2176
- setLoading(false);
2177
- setErrors([{
2178
- type: ConfirmSwapErrorTypes.REQUEST_FAILED,
2179
- status
2180
- }]);
2181
- return;
2182
1968
  }
2183
- };
2184
- return {
2185
- loading,
2186
- warnings,
2187
- errors,
2188
- confirmSwap
2189
- };
2190
- }
1969
+ });
1970
+ return result.sort((a, b) => Number(b.swap.creationTime) - Number(a.swap.creationTime));
1971
+ };
2191
1972
 
2192
- function ChangeSlippageButton() {
1973
+ const groupSwapsByDate = swaps => {
1974
+ const output = new Map([['today', {
1975
+ title: 'Today',
1976
+ swaps: []
1977
+ }], ['week', {
1978
+ title: 'This week',
1979
+ swaps: []
1980
+ }], ['month', {
1981
+ title: 'This month',
1982
+ swaps: []
1983
+ }], ['year', {
1984
+ title: 'This year',
1985
+ swaps: []
1986
+ }], ['history', {
1987
+ title: 'History',
1988
+ swaps: []
1989
+ }]]);
1990
+ const now = dayjs();
1991
+ swaps.forEach(swap => {
1992
+ const swapDate = dayjs(Number(swap.creationTime));
1993
+ if (now.isSame(swapDate, 'day')) output.get('today')?.swaps.push(swap);else if (now.isSame(swapDate, 'week')) output.get('week')?.swaps.push(swap);else if (now.isSame(swapDate, 'month')) output.get('month')?.swaps.push(swap);else if (now.isSame(swapDate, 'year')) output.get('year')?.swaps.push(swap);else output.get('history')?.swaps.push(swap);
1994
+ });
1995
+ return Array.from(output.values());
1996
+ };
1997
+
1998
+ function HistoryPage() {
1999
+ const setSelectedSwap = useUiStore.use.setSelectedSwap();
2193
2000
  const navigate = reactRouterDom.useNavigate();
2194
- return React__default.createElement(ui.Button, {
2195
- type: "primary",
2196
- variant: "outlined",
2197
- size: "small",
2198
- onClick: () => navigate(navigationRoutes.settings)
2199
- }, "Change Slippage");
2001
+ const {
2002
+ navigateBackFrom
2003
+ } = useNavigateBack();
2004
+ const {
2005
+ manager,
2006
+ state
2007
+ } = queueManagerReact.useManager();
2008
+ const pendingSwaps = getPendingSwaps(manager).map(_ref => {
2009
+ let {
2010
+ swap
2011
+ } = _ref;
2012
+ return swap;
2013
+ });
2014
+ const loading = !state.loadedFromPersistor;
2015
+ return React__default.createElement(ui.History, {
2016
+ list: pendingSwaps,
2017
+ groupBy: groupSwapsByDate,
2018
+ loading: loading,
2019
+ onSwapClick: requestId => {
2020
+ setSelectedSwap(requestId);
2021
+ navigate(`${requestId}`, {
2022
+ replace: true
2023
+ });
2024
+ },
2025
+ onBack: navigateBackFrom.bind(null, navigationRoutes.swaps)
2026
+ });
2200
2027
  }
2201
2028
 
2202
- const StyledMessage = /*#__PURE__*/ui.styled(ui.Typography, {
2203
- color: '$error500 !important'
2029
+ const Box$1 = /*#__PURE__*/ui.styled('div', {
2030
+ display: 'flex',
2031
+ flexDirection: 'column',
2032
+ width: '100%',
2033
+ overflow: 'hidden'
2204
2034
  });
2205
- function MinRequiredSlippage(_ref) {
2206
- let {
2207
- minRequiredSlippage
2208
- } = _ref;
2209
- return React__default.createElement(StyledMessage, {
2210
- variant: "body2"
2211
- }, "We recommend you to increase slippage to at least \u00A0", minRequiredSlippage, "\u00A0 for this route.", React__default.createElement(ui.Spacer, {
2212
- size: 8,
2213
- direction: "vertical"
2214
- }), React__default.createElement(ChangeSlippageButton, null));
2215
- }
2216
-
2217
- const List = /*#__PURE__*/ui.styled('ul', {
2218
- variants: {
2219
- showListStyle: {
2220
- true: {
2221
- paddingLeft: '$24'
2035
+ const Container$2 = /*#__PURE__*/ui.styled('div', {
2036
+ boxSizing: 'border-box',
2037
+ borderRadius: '$5',
2038
+ padding: '$8 $16 $16 $16',
2039
+ variants: {
2040
+ type: {
2041
+ filled: {
2042
+ backgroundColor: '$neutrals300'
2043
+ },
2044
+ outlined: {
2045
+ border: '1px solid $neutrals300'
2222
2046
  }
2223
2047
  }
2224
- }
2225
- });
2226
- const ListItem = /*#__PURE__*/ui.styled('li', {
2227
- variants: {
2228
- showListStyle: {
2229
- true: {
2230
- listStyleType: 'disc',
2231
- listStylePosition: 'outside'
2048
+ },
2049
+ defaultVariants: {
2050
+ type: 'filled'
2051
+ },
2052
+ '.head': {
2053
+ display: 'flex',
2054
+ justifyContent: 'space-between',
2055
+ alignItems: 'center',
2056
+ minHeight: '32px'
2057
+ },
2058
+ '.form': {
2059
+ display: 'flex',
2060
+ width: '100%',
2061
+ padding: '$2 0',
2062
+ '.selectors': {
2063
+ width: '35%',
2064
+ '._text': {
2065
+ whiteSpace: 'nowrap',
2066
+ overflow: 'hidden',
2067
+ textOverflow: 'ellipsis'
2232
2068
  }
2069
+ },
2070
+ '.amount': {
2071
+ width: '30%'
2072
+ }
2073
+ },
2074
+ '.output-usd': {
2075
+ display: 'flex',
2076
+ div: {
2077
+ display: 'flex',
2078
+ paddingLeft: '$8'
2233
2079
  }
2234
2080
  }
2235
2081
  });
2236
- const Message = /*#__PURE__*/ui.styled(ui.Typography, {
2237
- display: 'block'
2082
+ const Options = /*#__PURE__*/ui.styled('div', {
2083
+ display: 'flex',
2084
+ justifyContent: 'flex-end',
2085
+ '.balance': {
2086
+ display: 'flex',
2087
+ alignItems: 'center'
2088
+ }
2238
2089
  });
2239
- function BalanceErrors(_ref) {
2240
- let {
2241
- messages
2242
- } = _ref;
2243
- const showListStyle = messages.length > 1;
2244
- return React__default.createElement(React__default.Fragment, null, React__default.createElement(ui.Typography, {
2245
- className: "title",
2246
- variant: "title",
2247
- color: 'error'
2248
- }, "Insufficent Balance:"), React__default.createElement(ui.Spacer, {
2249
- size: 8,
2250
- direction: "vertical"
2251
- }), React__default.createElement(List, {
2252
- showListStyle: showListStyle
2253
- }, messages.map(warning => React__default.createElement(ListItem, {
2254
- showListStyle: showListStyle
2255
- }, React__default.createElement(Message, {
2256
- variant: "body2"
2257
- }, warning)))));
2258
- }
2259
-
2260
- function ConfirmSwapErrors(errors) {
2261
- return errors.flatMap(error => {
2262
- switch (error.type) {
2263
- case ConfirmSwapErrorTypes.NO_ROUTE:
2264
- return 'No routes found. Please try again later.';
2265
- case ConfirmSwapErrorTypes.REQUEST_FAILED:
2266
- return `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`;
2267
- case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
2268
- return 'Route updated and price impact is too high, try again later!';
2269
- case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
2270
- return React__default.createElement(MinRequiredSlippage, {
2271
- minRequiredSlippage: error.minRequiredSlippage
2272
- });
2273
- case ConfirmSwapErrorTypes.INSUFFICIENT_BALANCE:
2274
- return React__default.createElement(BalanceErrors, {
2275
- messages: error.messages
2276
- });
2277
- default:
2278
- return [];
2279
- }
2280
- });
2281
- }
2282
-
2283
- function ConfirmSwapWarnings(warnings) {
2284
- return warnings.flatMap(warning => {
2285
- switch (warning.type) {
2286
- case ConfirmSwapWarningTypes.ROUTE_UPDATED:
2287
- return "Route has been updated.";
2288
- case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
2289
- return `Output amount changed to ${warning.newOutputAmount} (${warning.percentageChange}% change).`;
2290
- case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
2291
- return "Route swappers has been updated.";
2292
- case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
2293
- return "Route internal coins has been updated.";
2294
- default:
2295
- return [];
2296
- }
2297
- });
2298
- }
2299
-
2300
- function HighSlippageWarning(props) {
2301
- const {
2302
- selectedSlippage
2303
- } = props;
2304
- return React__default.createElement(ui.Alert, {
2305
- type: "warning",
2306
- footer: React__default.createElement(ChangeSlippageButton, null)
2307
- }, "Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.");
2308
- }
2309
-
2310
- function ConfirmSwapExtraMessages(props) {
2090
+ const ImagePlaceholder$1 = /*#__PURE__*/ui.styled('span', {
2091
+ width: '24px',
2092
+ height: '24px',
2093
+ backgroundColor: '$neutrals300',
2094
+ borderRadius: '99999px'
2095
+ });
2096
+ const OutputContainer$1 = /*#__PURE__*/ui.styled('div', {
2097
+ windth: '100%',
2098
+ height: '$48',
2099
+ borderRadius: '$5',
2100
+ backgroundColor: '$background',
2101
+ border: '1px solid transparent',
2102
+ position: 'relative',
2103
+ display: 'flex',
2104
+ alignItems: 'center',
2105
+ paddingLeft: '$8',
2106
+ paddingRight: '$8'
2107
+ });
2108
+ function TokenInfo(props) {
2311
2109
  const {
2312
- selectedSlippage
2110
+ type,
2111
+ chain,
2112
+ token
2313
2113
  } = props;
2314
- const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
2315
- return React__default.createElement(React__default.Fragment, null, highSlippage && React__default.createElement(HighSlippageWarning, {
2316
- selectedSlippage: selectedSlippage
2317
- }));
2318
- }
2319
-
2320
- function ConfirmSwapPage() {
2321
- const navigate = reactRouterDom.useNavigate();
2322
- const {
2323
- navigateBackFrom
2324
- } = useNavigateBack();
2325
- const bestRoute = useBestRouteStore.use.bestRoute();
2326
- const fetchingBestRoute = useBestRouteStore.use.loading();
2327
- const fetchingBestRouteError = useBestRouteStore.use.error();
2328
- const setSelectedSwap = useUiStore.use.setSelectedSwap();
2329
- const {
2330
- blockchains,
2331
- tokens
2332
- } = useMetaStore.use.meta();
2333
- const accounts = useWalletsStore.use.accounts();
2334
- const selectedWallets = useWalletsStore.use.selectedWallets();
2335
- const initSelectedWallets = useWalletsStore.use.initSelectedWallets();
2336
- const setSelectedWallet = useWalletsStore.use.setSelectedWallet();
2337
- const slippage = useSettingsStore.use.slippage();
2338
- const customSlippage = useSettingsStore.use.customSlippage();
2114
+ const loadingStatus = useMetaStore.use.loadingStatus();
2115
+ const fromChain = useBestRouteStore.use.fromChain();
2116
+ const toChain = useBestRouteStore.use.toChain();
2339
2117
  const inputUsdValue = useBestRouteStore.use.inputUsdValue();
2340
- const outputUsdValue = useBestRouteStore.use.outputUsdValue();
2118
+ const fromToken = useBestRouteStore.use.fromToken();
2341
2119
  const setInputAmount = useBestRouteStore.use.setInputAmount();
2342
- const bestRouteloadingStatus = getBestRouteStatus(fetchingBestRoute, !!fetchingBestRouteError);
2343
- const {
2344
- manager
2345
- } = queueManagerReact.useManager();
2346
- const {
2347
- loading,
2348
- errors,
2349
- warnings,
2350
- confirmSwap
2351
- } = useConfirmSwap();
2352
- const selectedSlippage = customSlippage || slippage;
2353
- const showHighSlippageWarning = !errors.find(error => error.type === ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE);
2120
+ const bestRoute = useBestRouteStore.use.bestRoute();
2121
+ const inputAmount = useBestRouteStore.use.inputAmount();
2122
+ const balances = useWalletsStore.use.balances();
2123
+ const fetchingBestRoute = useBestRouteStore.use.loading();
2124
+ const navigate = reactRouterDom.useNavigate();
2354
2125
  const {
2355
- getWalletInfo,
2356
- connect
2357
- } = walletsCore.useWallets();
2358
- const confirmDisabled = fetchingBestRoute || !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
2359
- const firstStep = bestRoute?.result?.swaps[0];
2360
- const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
2361
- const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
2362
- const toAmount = decimalNumber(lastStep?.toAmount, 3);
2363
- React.useEffect(() => {
2364
- initSelectedWallets();
2365
- }, []);
2366
- const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
2367
- const handleConnectChain = wallet => {
2368
- const network = wallet;
2369
- getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
2370
- };
2371
- const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
2372
- return React__default.createElement(ui.ConfirmSwap, {
2373
- requiredWallets: getRequiredChains(bestRoute),
2374
- selectableWallets: selectableWallets,
2375
- onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
2376
- onConfirm: () => {
2377
- confirmSwap?.().then(swap => {
2378
- if (swap) {
2379
- manager?.create('swap', {
2380
- swapDetails: swap
2381
- }, {
2382
- id: swap.requestId
2383
- });
2384
- setSelectedSwap(swap.requestId);
2385
- navigate(navigationRoutes.swaps + `/${swap.requestId}`, {
2386
- replace: true
2387
- });
2388
- setTimeout(() => {
2389
- setInputAmount('');
2390
- }, 0);
2391
- }
2392
- });
2126
+ t
2127
+ } = reactI18next.useTranslation();
2128
+ const tokenBalance = !!fromChain && !!fromToken ? numberToString(getBalanceFromWallet(balances, fromChain?.name, fromToken?.symbol, fromToken?.address)?.amount || '0', 8) : '0';
2129
+ 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';
2130
+ const ItemSuffix = React__default.createElement("div", {
2131
+ style: {
2132
+ display: 'flex',
2133
+ justifyContent: 'center',
2134
+ alignItems: 'center'
2135
+ }
2136
+ }, loadingStatus === 'failed' && React__default.createElement(ui.InfoCircleIcon, {
2137
+ color: "error",
2138
+ size: 24
2139
+ }), React__default.createElement(ui.AngleDownIcon, null));
2140
+ return React__default.createElement(Box$1, null, React__default.createElement(Container$2, {
2141
+ type: props.type === 'From' ? 'filled' : 'outlined'
2142
+ }, React__default.createElement("div", {
2143
+ className: "head"
2144
+ }, React__default.createElement(ui.Typography, {
2145
+ variant: "body2",
2146
+ color: "neutrals800"
2147
+ }, t(type)), props.type === 'From' ? React__default.createElement(Options, null, React__default.createElement("div", {
2148
+ className: "balance",
2149
+ onClick: () => {
2150
+ if (tokenBalance !== '0') setInputAmount(tokenBalanceReal.split(',').join(''));
2151
+ }
2152
+ }, React__default.createElement(ui.Typography, {
2153
+ variant: "body3",
2154
+ color: "neutrals600"
2155
+ }, `${t('Balance')}: ${tokenBalance} ${fromToken?.symbol || ''}`), React__default.createElement(ui.Spacer, {
2156
+ size: 4
2157
+ }), React__default.createElement(ui.Button, {
2158
+ type: "primary",
2159
+ variant: "ghost",
2160
+ size: "compact"
2161
+ }, t('Max')))) : React__default.createElement("div", {
2162
+ className: "output-usd"
2163
+ }, React__default.createElement(PercentageChange, {
2164
+ inputUsdValue: inputUsdValue,
2165
+ outputUsdValue: props.outputUsdValue
2166
+ }), React__default.createElement("div", null, React__default.createElement(ui.Typography, {
2167
+ variant: "caption",
2168
+ color: "neutrals600"
2169
+ }, `$${numberToString(props.outputUsdValue)}`)))), React__default.createElement("div", {
2170
+ className: "form"
2171
+ }, React__default.createElement(ui.Button, {
2172
+ className: "selectors",
2173
+ onClick: () => {
2174
+ navigate(`${props.type.toLowerCase()}-chain`);
2393
2175
  },
2394
- onChange: wallet => setSelectedWallet(wallet),
2395
- confirmDisabled: confirmDisabled,
2396
- handleConnectChain: wallet => handleConnectChain(wallet),
2397
- isExperimentalChain: wallet => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains, wallet) : false,
2398
- previewInputs: React__default.createElement(React__default.Fragment, null, React__default.createElement(TokenPreview, {
2399
- chain: {
2400
- displayName: firstStep?.from.blockchain || '',
2401
- logo: firstStep?.from.blockchainLogo || ''
2402
- },
2403
- token: {
2404
- symbol: firstStep?.from.symbol || '',
2405
- image: firstStep?.from.logo || ''
2406
- },
2407
- usdValue: inputUsdValue,
2408
- amount: fromAmount,
2409
- label: i18n.t('From'),
2410
- loadingStatus: bestRouteloadingStatus
2411
- }), React__default.createElement(ui.Spacer, {
2412
- size: 12,
2413
- direction: "vertical"
2414
- }), React__default.createElement(TokenPreview, {
2415
- chain: {
2416
- displayName: lastStep?.to.blockchain || '',
2417
- logo: lastStep?.to.blockchainLogo || ''
2418
- },
2419
- token: {
2420
- symbol: lastStep?.to.symbol || '',
2421
- image: lastStep?.to.logo || ''
2422
- },
2423
- usdValue: outputUsdValue,
2424
- amount: toAmount,
2425
- label: i18n.t('To'),
2426
- loadingStatus: bestRouteloadingStatus,
2427
- percentageChange: React__default.createElement(PercentageChange, {
2428
- inputUsdValue: inputUsdValue,
2429
- outputUsdValue: outputUsdValue
2430
- })
2431
- })),
2432
- previewRoutes: React__default.createElement(RoutesOverview, {
2433
- routes: bestRoute,
2434
- totalFee: numberToString(totalFeeInUsd, 0, 2)
2435
- }),
2436
- loading: loading,
2437
- errors: ConfirmSwapErrors(errors),
2438
- warnings: ConfirmSwapWarnings(warnings),
2439
- extraMessages: showHighSlippageWarning && React__default.createElement(ConfirmSwapExtraMessages, {
2440
- selectedSlippage: selectedSlippage
2441
- }),
2442
- confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!'
2443
- });
2176
+ variant: "outlined",
2177
+ disabled: loadingStatus === 'failed',
2178
+ loading: loadingStatus === 'loading',
2179
+ prefix: loadingStatus === 'success' && chain ? React__default.createElement(ui.Image, {
2180
+ src: chain.logo,
2181
+ size: 24
2182
+ }) : React__default.createElement(ImagePlaceholder$1, null),
2183
+ suffix: ItemSuffix,
2184
+ align: "start",
2185
+ size: "large"
2186
+ }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React__default.createElement(ui.Spacer, {
2187
+ size: 12
2188
+ }), React__default.createElement(ui.Button, {
2189
+ className: "selectors",
2190
+ onClick: () => {
2191
+ navigate(`${props.type.toLowerCase()}-token`);
2192
+ },
2193
+ variant: "outlined",
2194
+ disabled: loadingStatus === 'failed' || type === 'From' && !fromChain || type === 'To' && !toChain,
2195
+ loading: loadingStatus === 'loading',
2196
+ prefix: loadingStatus === 'success' && token ? React__default.createElement(ui.Image, {
2197
+ src: token.image,
2198
+ size: 24
2199
+ }) : React__default.createElement(ImagePlaceholder$1, null),
2200
+ suffix: ItemSuffix,
2201
+ size: "large",
2202
+ align: "start"
2203
+ }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React__default.createElement(ui.Spacer, {
2204
+ size: 12
2205
+ }), React__default.createElement("div", {
2206
+ className: "amount"
2207
+ }, props.type === 'From' ? React__default.createElement(ui.TextField, {
2208
+ type: "number",
2209
+ size: "large",
2210
+ autoFocus: true,
2211
+ placeholder: "0",
2212
+ style: {
2213
+ position: 'relative',
2214
+ backgroundColor: '$background !important'
2215
+ },
2216
+ suffix: React__default.createElement("span", {
2217
+ style: {
2218
+ position: 'absolute',
2219
+ right: '4px',
2220
+ bottom: '2px'
2221
+ }
2222
+ }, React__default.createElement(ui.Typography, {
2223
+ variant: "caption",
2224
+ color: "neutrals800"
2225
+ }, `$${numberToString(inputUsdValue)}`)),
2226
+ value: props.inputAmount || '',
2227
+ min: 0,
2228
+ onChange: props.type === 'From' ? event => {
2229
+ props.onAmountChange(event.target.value);
2230
+ } : undefined
2231
+ }) : React__default.createElement(OutputContainer$1, null, React__default.createElement(ui.Typography, {
2232
+ variant: "h4"
2233
+ }, fetchingBestRoute && '?', !!bestRoute?.result && `≈ ${numberToString(props.outputAmount)}`, (!inputAmount || inputAmount === '0') && '0'))))));
2444
2234
  }
2445
2235
 
2446
- const getPendingSwaps = manager => {
2447
- const result = [];
2448
- manager?.getAll().forEach((q, id) => {
2449
- const storage = q.list.getStorage();
2450
- if (storage?.swapDetails) {
2451
- result.push({
2452
- id,
2453
- swap: storage?.swapDetails
2236
+ const Container$3 = /*#__PURE__*/theme.styled('div', {
2237
+ display: 'flex',
2238
+ width: '100%',
2239
+ justifyContent: 'end',
2240
+ alignItems: 'center',
2241
+ paddingTop: '$16'
2242
+ });
2243
+ const Logo = /*#__PURE__*/theme.styled('svg', {
2244
+ fill: '$foreground',
2245
+ width: '$24',
2246
+ margin: '0 $8 0 $16'
2247
+ });
2248
+ const StyledAnchor = /*#__PURE__*/theme.styled('a', {
2249
+ display: 'flex',
2250
+ justifyContent: 'center',
2251
+ alignItems: 'center',
2252
+ textDecoration: 'none'
2253
+ });
2254
+ function BottomLogo() {
2255
+ const {
2256
+ t
2257
+ } = reactI18next.useTranslation();
2258
+ return React__default.createElement(Container$3, null, React__default.createElement(ui.Typography, {
2259
+ variant: "caption",
2260
+ color: '$neutrals600'
2261
+ }, t('Powered By')), React__default.createElement(StyledAnchor, {
2262
+ href: "https://rango.exchange",
2263
+ target: "_blank"
2264
+ }, React__default.createElement(Logo, {
2265
+ xmlns: "http://www.w3.org/2000/svg",
2266
+ viewBox: "0 0 33.68 29"
2267
+ }, React__default.createElement("defs", null), React__default.createElement("g", {
2268
+ id: "Layer_2",
2269
+ "data-name": "Layer 2"
2270
+ }, React__default.createElement("g", {
2271
+ id: "Layer_1-2",
2272
+ "data-name": "Layer 1"
2273
+ }, React__default.createElement("path", {
2274
+ 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"
2275
+ }), React__default.createElement("path", {
2276
+ 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"
2277
+ })))), React__default.createElement(ui.Typography, {
2278
+ variant: "body2"
2279
+ }, "RANGO")));
2280
+ }
2281
+
2282
+ function SwithFromAndTo(_ref) {
2283
+ let {
2284
+ count
2285
+ } = _ref;
2286
+ const firstRender = React.useRef(true);
2287
+ const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
2288
+ const outputAmount = useBestRouteStore.use.outputAmount();
2289
+ React.useEffect(() => {
2290
+ if (!firstRender.current) {
2291
+ const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
2292
+ const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
2293
+ const toChainString = searchParams.get(SearchParams.TO_CHAIN);
2294
+ const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
2295
+ setSearchParams({
2296
+ ...(toChainString && {
2297
+ [SearchParams.FROM_CHAIN]: toChainString
2298
+ }),
2299
+ ...(toTokenString && {
2300
+ [SearchParams.FROM_TOKEN]: toTokenString
2301
+ }),
2302
+ ...(fromChainString && {
2303
+ [SearchParams.TO_CHAIN]: fromChainString
2304
+ }),
2305
+ ...(fromTokenString && {
2306
+ [SearchParams.TO_TOKEN]: fromTokenString
2307
+ }),
2308
+ ...(outputAmount && {
2309
+ [SearchParams.FROM_AMOUNT]: outputAmount.toString()
2310
+ })
2454
2311
  });
2312
+ } else {
2313
+ firstRender.current = false;
2455
2314
  }
2456
- });
2457
- return result.sort((a, b) => Number(b.swap.creationTime) - Number(a.swap.creationTime));
2458
- };
2315
+ }, [count]);
2316
+ return null;
2317
+ }
2459
2318
 
2460
- const groupSwapsByDate = swaps => {
2461
- const output = new Map([['today', {
2462
- title: 'Today',
2463
- swaps: []
2464
- }], ['week', {
2465
- title: 'This week',
2466
- swaps: []
2467
- }], ['month', {
2468
- title: 'This month',
2469
- swaps: []
2470
- }], ['year', {
2471
- title: 'This year',
2472
- swaps: []
2473
- }], ['history', {
2474
- title: 'History',
2475
- swaps: []
2476
- }]]);
2477
- const now = dayjs();
2478
- swaps.forEach(swap => {
2479
- const swapDate = dayjs(Number(swap.creationTime));
2480
- if (now.isSame(swapDate, 'day')) output.get('today')?.swaps.push(swap);else if (now.isSame(swapDate, 'week')) output.get('week')?.swaps.push(swap);else if (now.isSame(swapDate, 'month')) output.get('month')?.swaps.push(swap);else if (now.isSame(swapDate, 'year')) output.get('year')?.swaps.push(swap);else output.get('history')?.swaps.push(swap);
2481
- });
2482
- return Array.from(output.values());
2319
+ const Footer = /*#__PURE__*/ui.styled('div', {
2320
+ display: 'flex',
2321
+ flexDirection: 'column',
2322
+ width: '100%',
2323
+ paddingTop: '$16'
2324
+ });
2325
+
2326
+ const errorMessages = {
2327
+ genericServerError: 'Error connecting server, please reload the app and try again'
2483
2328
  };
2484
2329
 
2485
- function HistoryPage() {
2486
- const setSelectedSwap = useUiStore.use.setSelectedSwap();
2487
- const navigate = reactRouterDom.useNavigate();
2330
+ const ButtonsContainer = /*#__PURE__*/ui.styled('div', {
2331
+ display: 'flex'
2332
+ });
2333
+ function HeaderButtons(props) {
2488
2334
  const {
2489
- navigateBackFrom
2490
- } = useNavigateBack();
2335
+ onClickRefresh
2336
+ } = props;
2337
+ const navigate = reactRouterDom.useNavigate();
2338
+ return React__default.createElement(ButtonsContainer, null, React__default.createElement(ui.Tooltip, {
2339
+ content: "Refresh"
2340
+ }, React__default.createElement(ui.Button, {
2341
+ variant: "ghost",
2342
+ onClick: onClickRefresh,
2343
+ disabled: !onClickRefresh
2344
+ }, React__default.createElement(ui.RetryIcon, {
2345
+ size: 24,
2346
+ disabled: !onClickRefresh
2347
+ }))), React__default.createElement(ui.Tooltip, {
2348
+ content: "Transactions History"
2349
+ }, React__default.createElement(ui.Button, {
2350
+ variant: "ghost",
2351
+ onClick: () => navigate(navigationRoutes.swaps)
2352
+ }, React__default.createElement(ui.HistoryIcon, {
2353
+ size: 24
2354
+ }))), React__default.createElement(ui.Tooltip, {
2355
+ content: "Settings"
2356
+ }, React__default.createElement(ui.Button, {
2357
+ variant: "ghost",
2358
+ onClick: () => navigate(navigationRoutes.settings)
2359
+ }, React__default.createElement(ui.SettingsIcon, {
2360
+ size: 24
2361
+ }))));
2362
+ }
2363
+
2364
+ const Container$4 = /*#__PURE__*/ui.styled('div', {
2365
+ display: 'flex',
2366
+ flexDirection: 'column'
2367
+ });
2368
+ const FromContainer = /*#__PURE__*/ui.styled('div', {
2369
+ position: 'relative',
2370
+ paddingBottom: '$12'
2371
+ });
2372
+ const SwitchButtonContainer = /*#__PURE__*/ui.styled('div', {
2373
+ position: 'absolute',
2374
+ bottom: '-12px',
2375
+ left: '50%',
2376
+ transform: 'translate(-50%, 10%)'
2377
+ });
2378
+ const BestRouteContainer = /*#__PURE__*/ui.styled('div', {
2379
+ width: '100%',
2380
+ paddingTop: '$16'
2381
+ });
2382
+ const Alerts = /*#__PURE__*/ui.styled('div', {
2383
+ width: '100%',
2384
+ paddingTop: '$16'
2385
+ });
2386
+ function Home() {
2387
+ const isRouterInContext = reactRouterDom.useInRouterContext();
2388
+ const navigate = reactRouterDom.useNavigate();
2389
+ const [count, setCount] = React.useState(0);
2390
+ const fromChain = useBestRouteStore.use.fromChain();
2391
+ const fromToken = useBestRouteStore.use.fromToken();
2392
+ const toChain = useBestRouteStore.use.toChain();
2393
+ const toToken = useBestRouteStore.use.toToken();
2394
+ const setInputAmount = useBestRouteStore.use.setInputAmount();
2395
+ const inputUsdValue = useBestRouteStore.use.inputUsdValue();
2396
+ const inputAmount = useBestRouteStore.use.inputAmount();
2397
+ const outputAmount = useBestRouteStore.use.outputAmount();
2398
+ const outputUsdValue = useBestRouteStore.use.outputUsdValue();
2399
+ const bestRoute = useBestRouteStore.use.bestRoute();
2400
+ const tokens = useMetaStore.use.meta().tokens;
2401
+ const fetchingBestRoute = useBestRouteStore.use.loading();
2402
+ const bestRouteError = useBestRouteStore.use.error();
2403
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2404
+ const accounts = useWalletsStore.use.accounts();
2405
+ const setCurrentPage = useUiStore.use.setCurrentPage();
2406
+ const switchFromAndTo = useBestRouteStore.use.switchFromAndTo();
2407
+ const errorMessage = loadingMetaStatus === 'failed' ? errorMessages.genericServerError : bestRouteError;
2408
+ const needsToWarnEthOnPath = false;
2409
+ const showBestRoute = inputAmount && (!!bestRoute || fetchingBestRoute || bestRouteError);
2410
+ const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);
2411
+ const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);
2491
2412
  const {
2492
- manager,
2493
- state
2494
- } = queueManagerReact.useManager();
2495
- const pendingSwaps = getPendingSwaps(manager).map(_ref => {
2496
- let {
2497
- swap
2498
- } = _ref;
2499
- return swap;
2500
- });
2501
- const loading = !state.loadedFromPersistor;
2502
- return React__default.createElement(ui.History, {
2503
- list: pendingSwaps,
2504
- groupBy: groupSwapsByDate,
2505
- loading: loading,
2506
- onSwapClick: requestId => {
2507
- setSelectedSwap(requestId);
2508
- navigate(navigationRoutes.swaps + `/${requestId}`, {
2509
- replace: true
2510
- });
2511
- },
2512
- onBack: navigateBackFrom.bind(null, navigationRoutes.swaps)
2513
- });
2413
+ fromAmountRangeError,
2414
+ recommendation,
2415
+ swap
2416
+ } = LimitErrorMessage(bestRoute);
2417
+ const priceImpactCanNotBeComputed = !canComputePriceImpact(bestRoute, inputAmount, inputUsdValue, outputUsdValue);
2418
+ const swapButtonState = getSwapButtonState(loadingMetaStatus, accounts, fetchingBestRoute, bestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath, inputAmount);
2419
+ const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
2420
+ const highFee = hasHighFee(totalFeeInUsd);
2421
+ React.useEffect(() => {
2422
+ setCurrentPage(navigationRoutes.home);
2423
+ return setCurrentPage.bind(null, '');
2424
+ }, []);
2425
+ return React__default.createElement(Container$4, null, React__default.createElement(ui.Header, {
2426
+ title: "SWAP",
2427
+ suffix: React__default.createElement(HeaderButtons, {
2428
+ onClickRefresh: !!bestRoute || bestRouteError ? fetchBestRoute : undefined
2429
+ })
2430
+ }), React__default.createElement(FromContainer, null, React__default.createElement(TokenInfo, {
2431
+ type: "From",
2432
+ chain: fromChain,
2433
+ token: fromToken,
2434
+ onAmountChange: setInputAmount,
2435
+ inputAmount: inputAmount
2436
+ }), React__default.createElement(SwitchButtonContainer, null, React__default.createElement(ui.Button, {
2437
+ variant: "ghost",
2438
+ onClick: () => {
2439
+ switchFromAndTo();
2440
+ setCount(prev => prev + 1);
2441
+ }
2442
+ }, React__default.createElement(ui.VerticalSwapIcon, {
2443
+ size: 32
2444
+ }), isRouterInContext && React__default.createElement(SwithFromAndTo, {
2445
+ count: count
2446
+ })))), React__default.createElement(TokenInfo, {
2447
+ type: "To",
2448
+ chain: toChain,
2449
+ token: toToken,
2450
+ outputAmount: outputAmount ? new BigNumber__default(outputAmount) : new BigNumber__default(0),
2451
+ outputUsdValue: outputUsdValue
2452
+ }), showBestRoute && React__default.createElement(BestRouteContainer, null, React__default.createElement(ui.BestRoute, {
2453
+ error: bestRouteError,
2454
+ loading: fetchingBestRoute,
2455
+ data: getFormatedBestRoute(bestRoute),
2456
+ totalFee: numberToString(totalFeeInUsd, 0, 2),
2457
+ feeWarning: highFee,
2458
+ totalTime: secondsToString(totalArrivalTime(bestRoute))
2459
+ })), (errorMessage || hasLimitError(bestRoute)) && React__default.createElement(Alerts, null, errorMessage && React__default.createElement(ui.Alert, {
2460
+ type: "error"
2461
+ }, errorMessage), hasLimitError(bestRoute) && React__default.createElement(ui.Alert, {
2462
+ type: "error",
2463
+ title: `${swap?.swapperId} Limit`
2464
+ }, React__default.createElement(React__default.Fragment, null, React__default.createElement(ui.Typography, {
2465
+ variant: "body2"
2466
+ }, `${fromAmountRangeError}, Yours: ${numberToString(swap?.fromAmount || null)} ${swap?.from.symbol}`), React__default.createElement(ui.Typography, {
2467
+ variant: "body2"
2468
+ }, recommendation)))), React__default.createElement(Footer, null, React__default.createElement(ui.Button, {
2469
+ type: "primary",
2470
+ align: "grow",
2471
+ size: "large",
2472
+ disabled: swapButtonState.disabled,
2473
+ onClick: () => {
2474
+ if (swapButtonState.title === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
2475
+ navigate(navigationRoutes.confirmSwap, {
2476
+ replace: true
2477
+ });
2478
+ }
2479
+ }
2480
+ }, swapButtonState.title), React__default.createElement(BottomLogo, null)));
2514
2481
  }
2515
2482
 
2516
2483
  function LiquiditySourcePage(_ref) {
@@ -2753,24 +2720,6 @@ function WalletsPage(_ref) {
2753
2720
  }))))));
2754
2721
  }
2755
2722
 
2756
- function useCopyToClipboard(resetInterval) {
2757
- const [isCopied, setCopied] = React__default.useState(false);
2758
- const handleCopy = React__default.useCallback(text => {
2759
- copy(text.toString());
2760
- setCopied(true);
2761
- }, []);
2762
- React__default.useEffect(() => {
2763
- let timeout;
2764
- if (isCopied && resetInterval) {
2765
- timeout = setTimeout(() => setCopied(false), resetInterval);
2766
- }
2767
- return () => {
2768
- clearTimeout(timeout);
2769
- };
2770
- }, [isCopied, resetInterval]);
2771
- return [isCopied, handleCopy];
2772
- }
2773
-
2774
2723
  function timeSince(timeMillis) {
2775
2724
  const seconds = Math.floor((new Date().getTime() - timeMillis) / 1000);
2776
2725
  let intervalType;
@@ -2849,7 +2798,7 @@ function SwapDetailsPage() {
2849
2798
  const {
2850
2799
  navigateBackFrom
2851
2800
  } = useNavigateBack();
2852
- const [isCopied, handleCopy] = useCopyToClipboard(2000);
2801
+ const [isCopied, handleCopy] = ui.useCopyToClipboard(2000);
2853
2802
  const {
2854
2803
  manager,
2855
2804
  state
@@ -2950,50 +2899,50 @@ function AppRoutes(props) {
2950
2899
  config
2951
2900
  } = props;
2952
2901
  return reactRouterDom.useRoutes([{
2953
- path: getAbsolutePath(navigationRoutes.home),
2902
+ path: navigationRoutes.home,
2954
2903
  element: React__default.createElement(Home, null)
2955
2904
  }, {
2956
- path: getAbsolutePath(navigationRoutes.fromChain),
2905
+ path: navigationRoutes.fromChain,
2957
2906
  element: React__default.createElement(SelectChainPage, {
2958
2907
  type: "from",
2959
2908
  supportedChains: config?.from?.blockchains
2960
2909
  })
2961
2910
  }, {
2962
- path: getAbsolutePath(navigationRoutes.toChain),
2911
+ path: navigationRoutes.toChain,
2963
2912
  element: React__default.createElement(SelectChainPage, {
2964
2913
  type: "to",
2965
2914
  supportedChains: config?.to?.blockchains
2966
2915
  })
2967
2916
  }, {
2968
- path: getAbsolutePath(navigationRoutes.fromToken),
2917
+ path: navigationRoutes.fromToken,
2969
2918
  element: React__default.createElement(SelectTokenPage, {
2970
2919
  type: "from",
2971
2920
  supportedTokens: config?.from?.tokens
2972
2921
  })
2973
2922
  }, {
2974
- path: getAbsolutePath(navigationRoutes.toToken),
2923
+ path: navigationRoutes.toToken,
2975
2924
  element: React__default.createElement(SelectTokenPage, {
2976
2925
  type: "to",
2977
2926
  supportedTokens: config?.to?.tokens
2978
2927
  })
2979
2928
  }, {
2980
- path: getAbsolutePath(navigationRoutes.settings),
2929
+ path: navigationRoutes.settings,
2981
2930
  element: React__default.createElement(SettingsPage, {
2982
2931
  supportedSwappers: config?.liquiditySources
2983
2932
  })
2984
2933
  }, {
2985
- path: getAbsolutePath(navigationRoutes.liquiditySources),
2934
+ path: navigationRoutes.liquiditySources,
2986
2935
  element: React__default.createElement(LiquiditySourcePage, {
2987
2936
  supportedSwappers: config?.liquiditySources
2988
2937
  })
2989
2938
  }, {
2990
- path: getAbsolutePath(navigationRoutes.swaps),
2939
+ path: navigationRoutes.swaps,
2991
2940
  element: React__default.createElement(HistoryPage, null)
2992
2941
  }, {
2993
2942
  path: navigationRoutes.swapDetails,
2994
2943
  element: React__default.createElement(SwapDetailsPage, null)
2995
2944
  }, {
2996
- path: getAbsolutePath(navigationRoutes.wallets),
2945
+ path: navigationRoutes.wallets,
2997
2946
  element: React__default.createElement(WalletsPage, {
2998
2947
  supportedWallets: config?.wallets,
2999
2948
  multiWallets: typeof config?.multiWallets === 'undefined' ? true : config.multiWallets
@@ -3015,7 +2964,9 @@ const Header = /*#__PURE__*/ui.styled('div', {
3015
2964
  const WalletImageContainer = /*#__PURE__*/ui.styled('div', {
3016
2965
  marginLeft: -15,
3017
2966
  marginRight: '$6',
3018
- borderRadius: '99999px'
2967
+ '& img': {
2968
+ borderRadius: '50%'
2969
+ }
3019
2970
  });
3020
2971
  function Layout(_ref) {
3021
2972
  let {
@@ -3092,28 +3043,6 @@ function Layout(_ref) {
3092
3043
  }));
3093
3044
  }
3094
3045
 
3095
- const globalStyles = /*#__PURE__*/ui.globalCss({
3096
- '*': {
3097
- boxSizing: 'border-box',
3098
- margin: 0,
3099
- padding: 0,
3100
- listStyleType: 'none',
3101
- '&::-webkit-scrollbar': {
3102
- width: '$8',
3103
- height: '$8'
3104
- },
3105
- '&::-webkit-scrollbar-thumb': {
3106
- backgroundColor: '$neutrals400',
3107
- borderRadius: '$10'
3108
- },
3109
- '&::-webkit-scrollbar-thumb:hover': {
3110
- backgroundColor: '$neutrals500'
3111
- },
3112
- '&::-webkit-scrollbar-track': {
3113
- backgroundColor: '$neutrals300'
3114
- }
3115
- }
3116
- });
3117
3046
  const globalFont = fontFamily => ui.globalCss({
3118
3047
  '@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')"],
3119
3048
  body: {
@@ -3344,6 +3273,8 @@ function QueueManager(props) {
3344
3273
  API_KEY: getConfig('API_KEY')
3345
3274
  });
3346
3275
  }, []);
3276
+ const getOneOfWalletsDetails = useWalletsStore.use.getOneOfWalletsDetails();
3277
+ const accounts = useWalletsStore.use.accounts();
3347
3278
  const {
3348
3279
  blockchains
3349
3280
  } = useMetaStore.use.meta();
@@ -3370,6 +3301,17 @@ function QueueManager(props) {
3370
3301
  return walletAndSupportedChainsNames(supportedChains);
3371
3302
  };
3372
3303
  const allProviders = providers();
3304
+ const notifier = data => {
3305
+ const lastStep = data.swap?.steps[data.swap.steps.length - 1];
3306
+ const outputAmount = data.step?.outputAmount || '';
3307
+ const step = data.step || lastStep;
3308
+ if (data.eventType === 'task_completed' || data.eventType === 'step_completed_with_output' && lastStep?.id !== data.step?.id || !!outputAmount) {
3309
+ const fromAccount = accounts.find(account => account.chain === step?.fromBlockchain);
3310
+ const toAccount = step?.fromBlockchain !== step?.toBlockchain && accounts.find(account => account.chain === step?.toBlockchain);
3311
+ fromAccount && getOneOfWalletsDetails(fromAccount);
3312
+ toAccount && getOneOfWalletsDetails(toAccount);
3313
+ }
3314
+ };
3373
3315
  const context = {
3374
3316
  meta: {
3375
3317
  blockchains: allBlockchains,
@@ -3385,9 +3327,7 @@ function QueueManager(props) {
3385
3327
  switchNetwork,
3386
3328
  connect,
3387
3329
  state,
3388
- notifier: message => {
3389
- console.log('[notifier]', message);
3390
- }
3330
+ notifier
3391
3331
  };
3392
3332
  return React__default.createElement(queueManagerReact.Provider
3393
3333
  //@ts-ignore
@@ -3406,7 +3346,6 @@ const Widget = _ref => {
3406
3346
  let {
3407
3347
  config
3408
3348
  } = _ref;
3409
- globalStyles();
3410
3349
  globalFont(config?.theme?.fontFamily || 'Roboto');
3411
3350
  const {
3412
3351
  activeTheme
@@ -3471,7 +3410,6 @@ const Widget = _ref => {
3471
3410
  providers: providers,
3472
3411
  onUpdateState: onUpdateState
3473
3412
  }, React__default.createElement("div", {
3474
- id: "pageContainer",
3475
3413
  className: activeTheme
3476
3414
  }, React__default.createElement(QueueManager, null, React__default.createElement(ui.SwapContainer, {
3477
3415
  fixedHeight: currentPage !== navigationRoutes.home