@rango-dev/widget-embedded 0.1.10-next.99 → 0.1.10

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 (99) 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 +6 -1
  4. package/dist/components/AppRouter.d.ts.map +1 -1
  5. package/dist/components/AppRoutes.d.ts.map +1 -1
  6. package/dist/components/HeaderButtons.d.ts +4 -1
  7. package/dist/components/HeaderButtons.d.ts.map +1 -1
  8. package/dist/components/Layout.d.ts.map +1 -1
  9. package/dist/components/SwapDetailsPlaceholder.d.ts +9 -0
  10. package/dist/components/SwapDetailsPlaceholder.d.ts.map +1 -0
  11. package/dist/components/TokenPreview.d.ts +1 -1
  12. package/dist/components/TokenPreview.d.ts.map +1 -1
  13. package/dist/components/UpdateUrl.d.ts.map +1 -1
  14. package/dist/components/warnings/BalanceWarnings.d.ts.map +1 -1
  15. package/dist/components/warnings/MinRequiredSlippage.d.ts +1 -1
  16. package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -1
  17. package/dist/constants/navigationRoutes.d.ts +0 -1
  18. package/dist/constants/navigationRoutes.d.ts.map +1 -1
  19. package/dist/globalStyles.d.ts.map +1 -1
  20. package/dist/hooks/useConfirmSwap.d.ts.map +1 -1
  21. package/dist/lib.d.ts.map +1 -1
  22. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  23. package/dist/pages/HistoryPage.d.ts.map +1 -1
  24. package/dist/pages/Home.d.ts.map +1 -1
  25. package/dist/pages/LiquiditySourcesPage.d.ts.map +1 -1
  26. package/dist/pages/SelectTokenPage.d.ts.map +1 -1
  27. package/dist/pages/SettingsPage.d.ts.map +1 -1
  28. package/dist/pages/SwapDetailsPage.d.ts.map +1 -1
  29. package/dist/pages/WalletsPage.d.ts +1 -0
  30. package/dist/pages/WalletsPage.d.ts.map +1 -1
  31. package/dist/store/bestRoute.d.ts +2 -0
  32. package/dist/store/bestRoute.d.ts.map +1 -1
  33. package/dist/store/ui.d.ts.map +1 -1
  34. package/dist/store/wallets.d.ts +14 -0
  35. package/dist/store/wallets.d.ts.map +1 -1
  36. package/dist/types/routing.d.ts +1 -1
  37. package/dist/types/swap.d.ts +6 -0
  38. package/dist/types/swap.d.ts.map +1 -1
  39. package/dist/utils/common.d.ts +1 -0
  40. package/dist/utils/common.d.ts.map +1 -1
  41. package/dist/utils/date.d.ts +3 -0
  42. package/dist/utils/date.d.ts.map +1 -0
  43. package/dist/utils/routing.d.ts +1 -0
  44. package/dist/utils/routing.d.ts.map +1 -1
  45. package/dist/utils/swap.d.ts +16 -5
  46. package/dist/utils/swap.d.ts.map +1 -1
  47. package/dist/utils/time.d.ts +4 -0
  48. package/dist/utils/time.d.ts.map +1 -0
  49. package/dist/utils/wallets.d.ts +1 -1
  50. package/dist/utils/wallets.d.ts.map +1 -1
  51. package/dist/widget-embedded.cjs.development.js +1048 -705
  52. package/dist/widget-embedded.cjs.development.js.map +1 -1
  53. package/dist/widget-embedded.cjs.production.min.js +1048 -705
  54. package/dist/widget-embedded.cjs.production.min.js.map +1 -1
  55. package/dist/widget-embedded.esm.js +1057 -714
  56. package/dist/widget-embedded.esm.js.map +1 -1
  57. package/package.json +12 -11
  58. package/readme.md +1 -2
  59. package/src/App.tsx +30 -5
  60. package/src/QueueManager.tsx +5 -2
  61. package/src/components/AppRouter.tsx +24 -13
  62. package/src/components/AppRoutes.tsx +15 -12
  63. package/src/components/HeaderButtons.tsx +9 -2
  64. package/src/components/Layout.tsx +37 -5
  65. package/src/components/SwapDetailsPlaceholder.tsx +32 -0
  66. package/src/components/TokenPreview.tsx +7 -4
  67. package/src/components/UpdateUrl.tsx +1 -3
  68. package/src/components/warnings/BalanceWarnings.tsx +1 -0
  69. package/src/components/warnings/MinRequiredSlippage.tsx +9 -4
  70. package/src/constants/navigationRoutes.ts +0 -1
  71. package/src/globalStyles.ts +2 -1
  72. package/src/hooks/useConfirmSwap.ts +2 -1
  73. package/src/hooks/useNavigateBack.ts +3 -3
  74. package/src/lib.tsx +25 -3
  75. package/src/pages/ConfirmSwapPage.tsx +128 -20
  76. package/src/pages/HistoryPage.tsx +4 -4
  77. package/src/pages/Home.tsx +19 -8
  78. package/src/pages/LiquiditySourcesPage.tsx +2 -0
  79. package/src/pages/SelectTokenPage.tsx +3 -1
  80. package/src/pages/SettingsPage.tsx +3 -0
  81. package/src/pages/SwapDetailsPage.tsx +142 -6
  82. package/src/pages/WalletsPage.tsx +47 -11
  83. package/src/store/bestRoute.ts +110 -12
  84. package/src/store/ui.ts +4 -0
  85. package/src/store/wallets.ts +4 -1
  86. package/src/types/routing.ts +1 -1
  87. package/src/types/swap.ts +7 -0
  88. package/src/utils/common.ts +14 -0
  89. package/src/utils/date.ts +62 -0
  90. package/src/utils/routing.ts +23 -13
  91. package/src/utils/swap.ts +101 -10
  92. package/src/utils/time.ts +52 -0
  93. package/src/utils/wallets.ts +13 -4
  94. package/dist/components/Header.d.ts +0 -10
  95. package/dist/components/Header.d.ts.map +0 -1
  96. package/dist/pages/ConfirmWalletsPage.d.ts +0 -3
  97. package/dist/pages/ConfirmWalletsPage.d.ts.map +0 -1
  98. package/src/components/Header.tsx +0 -37
  99. package/src/pages/ConfirmWalletsPage.tsx +0 -127
@@ -1,22 +1,23 @@
1
- import { WalletState, Tooltip, Button, RetryIcon, HistoryIcon, SettingsIcon, styled, css, Typography, InfoCircleIcon, AngleDownIcon, Spacer, TextField, VerticalSwapIcon, BestRoute, Alert, ConfirmSwap, History, LiquiditySourcesSelector, BlockchainSelector, TokenSelector, Settings, SecondaryPage, Wallet, ChevronRightIcon, GasIcon, ConfirmWallets, SwapHistory, AddWalletIcon, globalCss, createTheme, SwapContainer } from '@rango-dev/ui';
1
+ import { WalletState, InfoCircleIcon, AngleDownIcon, Typography, Spacer, Button, TextField, styled, Tooltip, RetryIcon, HistoryIcon, SettingsIcon, Header as Header$1, VerticalSwapIcon, BestRoute, Alert, ChevronRightIcon, GasIcon, ConfirmSwap, History, LiquiditySourcesSelector, BlockchainSelector, TokenSelector, Settings, SecondaryPage, Spinner, LoadingFailedAlert, Wallet, SwapHistory, AddWalletIcon, globalCss, createTheme, SwapContainer } from '@rango-dev/ui';
2
2
  import React, { useRef, useEffect, useState, useLayoutEffect } from 'react';
3
3
  import { useInRouterContext as useInRouterContext$1, MemoryRouter, useLocation as useLocation$1, useNavigate as useNavigate$1 } from 'react-router';
4
+ import { PendingSwapNetworkStatus, useQueueManager, getCurrentStep, getCurrentBlockchainOfOrNull, getRelatedWalletOrNull, cancelSwap, swapQueueDef, checkWaitingForNetworkChange } from '@rango-dev/queue-manager-rango-preset';
5
+ import { isCosmosBlockchain, isEvmBlockchain } from 'rango-types';
4
6
  import { useSearchParams, useLocation, createSearchParams, useNavigate, useInRouterContext, useRoutes } from 'react-router-dom';
5
7
  import { create } from 'zustand';
6
8
  import BigNumber, { BigNumber as BigNumber$1 } from 'bignumber.js';
7
- import { Network, isEvmAddress, detectInstallLink, KEPLR_COMPATIBLE_WALLETS, WalletType, getCosmosExperimentalChainInfo, detectMobileScreens, convertEvmBlockchainMetaToEvmChainInfo } from '@rango-dev/wallets-shared';
8
- import { isCosmosBlockchain } from 'rango-types';
9
+ import { Network, isEvmAddress, KEPLR_COMPATIBLE_WALLETS, detectInstallLink, WalletType, getCosmosExperimentalChainInfo, detectMobileScreens, convertEvmBlockchainMetaToEvmChainInfo } from '@rango-dev/wallets-shared';
9
10
  import { readAccountAddress, useWallets, Provider as Provider$1, Events } from '@rango-dev/wallets-core';
10
11
  import { persist, subscribeWithSelector } from 'zustand/middleware';
11
- import { RangoClient, isEvmBlockchain } from 'rango-sdk';
12
+ import { RangoClient, isEvmBlockchain as isEvmBlockchain$1 } from 'rango-sdk';
12
13
  import { shallow } from 'zustand/shallow';
13
14
  import { useTranslation, initReactI18next } from 'react-i18next';
14
15
  import { styled as styled$1 } from '@rango-dev/ui/src/theme';
15
16
  import { allProviders } from '@rango-dev/provider-all';
16
- import { useManager, Provider } from '@rango-dev/queue-manager-react';
17
17
  import i18n, { t } from 'i18next';
18
+ import { useManager, Provider } from '@rango-dev/queue-manager-react';
19
+ import dayjs from 'dayjs';
18
20
  import copy from 'copy-to-clipboard';
19
- import { cancelSwap, swapQueueDef } from '@rango-dev/queue-manager-rango-preset';
20
21
  import Backend from 'i18next-http-backend';
21
22
  import LanguageDetector from 'i18next-browser-languagedetector';
22
23
 
@@ -31,7 +32,6 @@ const navigationRoutes = {
31
32
  swaps: '/swaps',
32
33
  wallets: '/wallets',
33
34
  confirmSwap: '/confirm-swap',
34
- confirmWallets: '/confirm-wallets',
35
35
  swapDetails: '/swaps/:requestId'
36
36
  };
37
37
 
@@ -61,6 +61,22 @@ function shadeColor(color, percent) {
61
61
  var BB = B.toString(16).length == 1 ? '0' + B.toString(16) : B.toString(16);
62
62
  return '#' + RR + GG + BB;
63
63
  }
64
+ function debounce(fn, time) {
65
+ let timeoutId;
66
+ return wrapper;
67
+ function wrapper() {
68
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
69
+ args[_key] = arguments[_key];
70
+ }
71
+ if (timeoutId) {
72
+ clearTimeout(timeoutId);
73
+ }
74
+ timeoutId = setTimeout(() => {
75
+ timeoutId = null;
76
+ fn(...args);
77
+ }, time);
78
+ }
79
+ }
64
80
 
65
81
  const secondsToString = s => {
66
82
  const seconds = (s % 60).toString().padStart(2, '0');
@@ -327,7 +343,7 @@ function getSortedTokens(chain, tokens, balances, otherChainTokens) {
327
343
  return sortTokens(getTokensWithBalance(filteredTokens, balances));
328
344
  }
329
345
  function tokensAreEqual(tokenA, tokenB) {
330
- return tokenA?.blockchain === tokenB?.blockchain && tokenA?.name === tokenB?.name && tokenA?.address === tokenB?.address;
346
+ return tokenA?.blockchain === tokenB?.blockchain && tokenA?.symbol === tokenB?.symbol && tokenA?.address === tokenB?.address;
331
347
  }
332
348
  function getDefaultToken(sortedTokens, otherToken) {
333
349
  let selectedToken;
@@ -337,7 +353,7 @@ function getDefaultToken(sortedTokens, otherToken) {
337
353
  return selectedToken;
338
354
  }
339
355
  function sortWalletsBasedOnState(wallets) {
340
- return wallets.sort((a, b) => Number(b.state === WalletState.CONNECTED) - Number(a.state === WalletState.CONNECTED) || Number(b.state === WalletState.DISCONNECTED) - Number(a.state === WalletState.DISCONNECTED));
356
+ return wallets.sort((a, b) => Number(b.state === WalletState.CONNECTED) - Number(a.state === WalletState.CONNECTED) || Number(b.state === WalletState.DISCONNECTED || b.state === WalletState.CONNECTING) - Number(a.state === WalletState.DISCONNECTED || a.state === WalletState.CONNECTING));
341
357
  }
342
358
 
343
359
  function getOutputRatio(inputUsdValue, outputUsdValue) {
@@ -453,6 +469,7 @@ function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validat
453
469
  finishTime: null,
454
470
  requestId: bestRoute.requestId || '',
455
471
  inputAmount: inputAmount,
472
+ //@ts-ignore
456
473
  wallets,
457
474
  status: 'running',
458
475
  isPaused: false,
@@ -467,6 +484,7 @@ function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validat
467
484
  settings: settings,
468
485
  simulationResult: simulationResult,
469
486
  validateBalanceOrFee,
487
+ //@ts-ignore
470
488
  steps: bestRoute.result?.swaps?.map((swap, index) => {
471
489
  const swapper = meta.swappers.find(swapper => swapper.id === swap.swapperId);
472
490
  const swapperType = swapper?.types[0];
@@ -552,11 +570,10 @@ function hasHighFee(totalFeeInUsd) {
552
570
  }
553
571
  function getMinRequiredSlippage(route) {
554
572
  const slippages = route.result?.swaps.map(slippage => slippage.recommendedSlippage);
555
- return slippages?.map(s => parseFloat(s?.slippage || '0'))?.filter(s => s > 0)?.sort((a, b) => b - a)?.find(() => true) || null;
573
+ return slippages?.map(s => s?.slippage || '0')?.filter(s => parseFloat(s) > 0)?.sort((a, b) => parseFloat(b) - parseFloat(a))?.find(() => true) || null;
556
574
  }
557
575
  function hasProperSlippage(userSlippage, minRequiredSlippage) {
558
576
  if (!minRequiredSlippage) return true;
559
- //@ts-ignore
560
577
  return parseFloat(userSlippage) >= parseFloat(minRequiredSlippage);
561
578
  }
562
579
  function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, selectedWallets, disabledLiquiditySources, slippage, checkPrerequisites) {
@@ -569,6 +586,7 @@ function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, se
569
586
  addresses: [wallet.address]
570
587
  });
571
588
  });
589
+ const filteredBlockchains = selectedWallets.map(wallet => wallet.chain);
572
590
  const requestBody = {
573
591
  amount: inputAmount.toString(),
574
592
  checkPrerequisites,
@@ -586,8 +604,10 @@ function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, se
586
604
  selectedWallets: selectedWalletsMap,
587
605
  swapperGroups: disabledLiquiditySources,
588
606
  swappersGroupsExclude: true,
589
- //@ts-ignore
590
- slippage: slippage.toString()
607
+ slippage: slippage.toString(),
608
+ ...(checkPrerequisites && {
609
+ blockchains: filteredBlockchains
610
+ })
591
611
  };
592
612
  return requestBody;
593
613
  }
@@ -633,6 +653,61 @@ function calcOutputUsdValue(outputAmount, tokenPrice) {
633
653
  const amount = !!outputAmount ? new BigNumber(outputAmount) : ZERO;
634
654
  return amount.multipliedBy(tokenPrice || 0);
635
655
  }
656
+ function isNetworkStatusInWarningState(pendingSwapStep) {
657
+ return !!pendingSwapStep && pendingSwapStep.networkStatus !== null && pendingSwapStep.networkStatus !== PendingSwapNetworkStatus.NetworkChanged;
658
+ }
659
+ function getSwapMessages(pendingSwap, currentStep) {
660
+ const textForRemove = 'bellow button or';
661
+ let message = pendingSwap.extraMessage;
662
+ let detailedMessage = pendingSwap.extraMessageDetail;
663
+ if (pendingSwap.networkStatusExtraMessageDetail?.includes(textForRemove)) {
664
+ pendingSwap.networkStatusExtraMessageDetail = pendingSwap.networkStatusExtraMessageDetail.replace(textForRemove, '');
665
+ }
666
+ const networkWarningState = isNetworkStatusInWarningState(currentStep);
667
+ if (networkWarningState) {
668
+ message = pendingSwap.networkStatusExtraMessage || '';
669
+ detailedMessage = pendingSwap.networkStatusExtraMessageDetail || '';
670
+ switch (currentStep?.networkStatus) {
671
+ case PendingSwapNetworkStatus.WaitingForConnectingWallet:
672
+ message = message || 'Waiting for connecting wallet';
673
+ break;
674
+ case PendingSwapNetworkStatus.WaitingForQueue:
675
+ message = message || 'Waiting for other running tasks to be finished';
676
+ break;
677
+ case PendingSwapNetworkStatus.WaitingForNetworkChange:
678
+ message = message || 'Waiting for changing wallet network';
679
+ break;
680
+ }
681
+ }
682
+ detailedMessage = detailedMessage || '';
683
+ message = message || '';
684
+ const isRpc = message?.indexOf('code') !== -1 && message?.indexOf('reason') !== -1;
685
+ return {
686
+ shortMessage: message,
687
+ detailedMessage: {
688
+ content: detailedMessage,
689
+ long: isRpc
690
+ }
691
+ };
692
+ }
693
+ function getLastConvertedTokenInFailedSwap(pendingSwap) {
694
+ let resultToken = null;
695
+ if (pendingSwap.status === 'failed') {
696
+ const lastSuccessStep = pendingSwap.steps.slice().reverse().filter(step => step.status === 'success')[0];
697
+ if (lastSuccessStep) {
698
+ resultToken = {
699
+ blockchain: lastSuccessStep.toBlockchain,
700
+ symbol: lastSuccessStep.toSymbol,
701
+ outputAmount: lastSuccessStep.outputAmount,
702
+ address: lastSuccessStep.toSymbolAddress
703
+ };
704
+ }
705
+ }
706
+ return resultToken;
707
+ }
708
+ function shouldRetrySwap(pendingSwap) {
709
+ return pendingSwap.status === 'failed' && !!pendingSwap.finishTime && new Date().getTime() - parseInt(pendingSwap.finishTime) < 4 * 3600 * 1000;
710
+ }
636
711
 
637
712
  function searchParamsToToken(tokens, searchParams, chain) {
638
713
  if (!chain) return null;
@@ -670,22 +745,13 @@ function getRequiredBalanceOfWallet(selectedWallet, fee) {
670
745
  return relatedFeeStatus.requiredAssets;
671
746
  }
672
747
  function isRouteParametersChanged(prevParams, currentParams) {
673
- return prevParams.fromChain?.name !== currentParams.fromChain?.name || prevParams.toChain?.name !== currentParams.toChain?.name || prevParams.fromToken?.symbol !== currentParams.fromToken?.symbol || prevParams.toToken?.symbol !== currentParams.toToken?.symbol || prevParams.fromToken?.blockchain !== currentParams.fromToken?.blockchain || prevParams.toToken?.blockchain !== currentParams.toToken?.blockchain || prevParams.fromToken?.address !== currentParams.fromToken?.address || prevParams.toToken?.address !== currentParams.toToken?.address || prevParams.inputAmount !== currentParams.inputAmount || prevParams.slippage !== currentParams.slippage || prevParams.customSlippage !== currentParams.customSlippage || prevParams.disabledLiquiditySources?.length !== currentParams.disabledLiquiditySources?.length;
674
- }
675
- function getBestRouteWithCalculatedFees(bestRoute, tokens) {
676
- if (!bestRoute || !bestRoute.result) return null;
677
- const swapsWithFee = (bestRoute?.result?.swaps || []).map(swap => ({
678
- ...swap,
679
- feeInUsd: numberToString(getUsdFeeOfStep(swap, tokens), 0, 2)
680
- }));
681
- return {
682
- ...bestRoute,
683
- result: {
684
- ...bestRoute.result,
685
- swaps: swapsWithFee
686
- }
687
- };
748
+ return !!currentParams.fromToken && !!currentParams.toToken && (prevParams.fromChain?.name !== currentParams.fromChain?.name || prevParams.toChain?.name !== currentParams.toChain?.name || prevParams.fromToken?.symbol !== currentParams.fromToken?.symbol || prevParams.toToken?.symbol !== currentParams.toToken?.symbol || prevParams.fromToken?.blockchain !== currentParams.fromToken?.blockchain || prevParams.toToken?.blockchain !== currentParams.toToken?.blockchain || prevParams.fromToken?.address !== currentParams.fromToken?.address || prevParams.toToken?.address !== currentParams.toToken?.address || prevParams.inputAmount !== currentParams.inputAmount || prevParams.slippage !== currentParams.slippage || prevParams.customSlippage !== currentParams.customSlippage || prevParams.disabledLiquiditySources?.length !== currentParams.disabledLiquiditySources?.length);
688
749
  }
750
+ //todo: refactor bestRoute store and add loadingStatus
751
+ const getBestRouteStatus = (loading, error) => {
752
+ if (loading) return 'loading';
753
+ if (error) return 'failed';else return 'success';
754
+ };
689
755
 
690
756
  const createSelectors = _store => {
691
757
  let store = _store;
@@ -836,7 +902,7 @@ const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#
836
902
  }
837
903
  });
838
904
  return {
839
- selectedWallets: state.selectedWallets.concat(selectedWallets)
905
+ selectedWallets: selectedWallets
840
906
  };
841
907
  }),
842
908
  setSelectedWallet: wallet => set(state => ({
@@ -868,6 +934,7 @@ useWalletsStore.subscribe(state => state.balances, balances => {
868
934
  }, {
869
935
  equalityFn: shallow
870
936
  });
937
+ const fetchingBalanceSelector = state => !!state.balances.find(wallet => wallet.loading);
871
938
 
872
939
  const getUsdValue = (token, amount) => new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0);
873
940
  const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /*#__PURE__*/subscribeWithSelector(set => ({
@@ -887,6 +954,7 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /
887
954
  setBestRoute: bestRoute => set(state => {
888
955
  let outputAmount = null;
889
956
  let outputUsdValue = ZERO;
957
+ if (!state.inputAmount || state.inputAmount === '0') return {};
890
958
  if (!!bestRoute) {
891
959
  outputAmount = !!bestRoute.result?.outputAmount ? new BigNumber(bestRoute.result?.outputAmount) : null;
892
960
  outputUsdValue = calcOutputUsdValue(bestRoute.result?.outputAmount, getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice);
@@ -943,6 +1011,7 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /
943
1011
  toToken: token
944
1012
  })),
945
1013
  setInputAmount: amount => {
1014
+ console.log(amount, typeof amount);
946
1015
  set(state => ({
947
1016
  inputAmount: amount,
948
1017
  ...(!amount && {
@@ -954,6 +1023,47 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()( /
954
1023
  inputUsdValue: getUsdValue(state.fromToken, amount)
955
1024
  })
956
1025
  }));
1026
+ },
1027
+ retry: pendingSwap => {
1028
+ const {
1029
+ tokens,
1030
+ blockchains
1031
+ } = useMetaStore.getState().meta;
1032
+ const balances = useWalletsStore.getState().balances;
1033
+ const failedIndex = pendingSwap.status === 'failed' ? pendingSwap.steps.findIndex(s => s.status === 'failed') : null;
1034
+ if (failedIndex === null || failedIndex < 0) return;
1035
+ const firstStep = pendingSwap.steps[0];
1036
+ const lastStep = pendingSwap.steps[pendingSwap.steps.length - 1];
1037
+ const fromChain = blockchains.find(blockchain => blockchain.name === firstStep.fromBlockchain) || null;
1038
+ const toChain = blockchains.find(blockchain => blockchain.name === lastStep.toBlockchain) || null;
1039
+ const fromToken = tokens.find(token => tokensAreEqual(token, {
1040
+ blockchain: firstStep.fromBlockchain,
1041
+ symbol: firstStep.fromSymbol,
1042
+ address: firstStep.fromSymbolAddress
1043
+ }));
1044
+ const toToken = tokens.find(token => tokensAreEqual(token, {
1045
+ blockchain: lastStep.toBlockchain,
1046
+ symbol: lastStep.toSymbol,
1047
+ address: lastStep.toSymbolAddress
1048
+ }));
1049
+ const sortedSourceTokens = getSortedTokens(fromChain, tokens, balances, []);
1050
+ const sortedDestinationTokens = getSortedTokens(toChain, tokens, balances, []);
1051
+ const inputAmount = pendingSwap.inputAmount;
1052
+ set({
1053
+ fromChain,
1054
+ fromToken,
1055
+ inputAmount,
1056
+ outputAmount: null,
1057
+ inputUsdValue: getUsdValue(fromToken || null, inputAmount),
1058
+ outputUsdValue: new BigNumber(0),
1059
+ toChain,
1060
+ toToken,
1061
+ bestRoute: null,
1062
+ loading: false,
1063
+ error: '',
1064
+ sourceTokens: sortedSourceTokens,
1065
+ destinationTokens: sortedDestinationTokens
1066
+ });
957
1067
  }
958
1068
  }))));
959
1069
  const bestRoute = (bestRouteStore, settingsStore) => {
@@ -969,12 +1079,12 @@ const bestRoute = (bestRouteStore, settingsStore) => {
969
1079
  customSlippage,
970
1080
  disabledLiquiditySources
971
1081
  } = settingsStore.getState();
972
- if (!fromToken || !toToken || !inputAmount) return;
1082
+ if (!fromToken || !toToken || !inputAmount || inputAmount === '0') return;
973
1083
  abortController?.abort();
974
1084
  abortController = new AbortController();
975
1085
  const userSlippage = !!customSlippage ? customSlippage : slippage;
976
1086
  const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, [], [], disabledLiquiditySources, userSlippage, false);
977
- bestRouteStore.setState({
1087
+ if (!bestRouteStore.getState().loading) bestRouteStore.setState({
978
1088
  loading: true,
979
1089
  bestRoute: null,
980
1090
  outputAmount: null,
@@ -999,13 +1109,36 @@ const bestRoute = (bestRouteStore, settingsStore) => {
999
1109
  });
1000
1110
  });
1001
1111
  };
1112
+ const debouncedFetchBestRoute = debounce(fetchBestRoute, 600);
1113
+ const bestRouteParamsListener = () => {
1114
+ const {
1115
+ fromToken,
1116
+ toToken,
1117
+ inputAmount,
1118
+ inputUsdValue
1119
+ } = useBestRouteStore.getState();
1120
+ if (!inputAmount || inputAmount === '0') return;
1121
+ if (tokensAreEqual(fromToken, toToken)) return bestRouteStore.setState({
1122
+ loading: false,
1123
+ bestRoute: null,
1124
+ outputAmount: new BigNumber(inputAmount),
1125
+ outputUsdValue: inputUsdValue
1126
+ });
1127
+ if (!bestRouteStore.getState().loading) bestRouteStore.setState({
1128
+ loading: true,
1129
+ bestRoute: null,
1130
+ outputAmount: null,
1131
+ outputUsdValue: new BigNumber(0)
1132
+ });
1133
+ debouncedFetchBestRoute();
1134
+ };
1002
1135
  useBestRouteStore.subscribe(state => ({
1003
1136
  fromChain: state.fromChain,
1004
1137
  fromToken: state.fromToken,
1005
1138
  toChain: state.toChain,
1006
1139
  toToken: state.toToken,
1007
1140
  inputAmount: state.inputAmount
1008
- }), fetchBestRoute.bind(null), {
1141
+ }), bestRouteParamsListener, {
1009
1142
  equalityFn: (prevState, state) => {
1010
1143
  if (isRouteParametersChanged(prevState, state)) return false;else return true;
1011
1144
  }
@@ -1014,7 +1147,7 @@ const bestRoute = (bestRouteStore, settingsStore) => {
1014
1147
  slippage: state.slippage,
1015
1148
  customSlippage: state.customSlippage,
1016
1149
  disabledLiquiditySources: state.disabledLiquiditySources
1017
- }), fetchBestRoute.bind(null), {
1150
+ }), bestRouteParamsListener, {
1018
1151
  equalityFn: (prevState, state) => {
1019
1152
  if (isRouteParametersChanged(prevState, state)) return false;else return true;
1020
1153
  }
@@ -1039,11 +1172,15 @@ var SearchParams;
1039
1172
  const useUiStore = /*#__PURE__*/createSelectors( /*#__PURE__*/create()(set => ({
1040
1173
  connectWalletsButtonDisabled: false,
1041
1174
  selectedSwapRequestId: null,
1175
+ currentPage: '',
1042
1176
  toggleConnectWalletsButton: () => set(state => ({
1043
1177
  connectWalletsButtonDisabled: !state.connectWalletsButtonDisabled
1044
1178
  })),
1045
1179
  setSelectedSwap: requestId => set({
1046
1180
  selectedSwapRequestId: requestId
1181
+ }),
1182
+ setCurrentPage: path => set({
1183
+ currentPage: path
1047
1184
  })
1048
1185
  })));
1049
1186
 
@@ -1084,7 +1221,7 @@ function UpdateUrl() {
1084
1221
  toChainString = '',
1085
1222
  toTokenString = '',
1086
1223
  fromAmount = '';
1087
- if (loadingStatus !== 'success' && ![navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname)) {
1224
+ if (loadingStatus !== 'success' && location.pathname != navigationRoutes.confirmSwap) {
1088
1225
  fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
1089
1226
  fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
1090
1227
  toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
@@ -1177,67 +1314,6 @@ function UpdateUrl() {
1177
1314
  return null;
1178
1315
  }
1179
1316
 
1180
- const ButtonsContainer = /*#__PURE__*/styled('div', {
1181
- display: 'flex'
1182
- });
1183
- function HeaderButtons(props) {
1184
- const {
1185
- onClickRefresh
1186
- } = props;
1187
- const navigate = useNavigate();
1188
- return React.createElement(ButtonsContainer, null, React.createElement(Tooltip, {
1189
- content: "Refresh"
1190
- }, React.createElement(Button, {
1191
- variant: "ghost",
1192
- onClick: onClickRefresh
1193
- }, React.createElement(RetryIcon, {
1194
- size: 24
1195
- }))), React.createElement(Tooltip, {
1196
- content: "Transactions History"
1197
- }, React.createElement(Button, {
1198
- variant: "ghost",
1199
- onClick: () => navigate(navigationRoutes.swaps)
1200
- }, React.createElement(HistoryIcon, {
1201
- size: 24
1202
- }))), React.createElement(Tooltip, {
1203
- content: "Settings"
1204
- }, React.createElement(Button, {
1205
- variant: "ghost",
1206
- onClick: () => navigate(navigationRoutes.settings)
1207
- }, React.createElement(SettingsIcon, {
1208
- size: 24
1209
- }))));
1210
- }
1211
-
1212
- const HeaderContainer = /*#__PURE__*/styled('div', {
1213
- display: 'flex',
1214
- justifyContent: 'space-between',
1215
- alignItems: 'center',
1216
- width: '100%',
1217
- padding: '$16 0'
1218
- });
1219
- function Header(props) {
1220
- const {
1221
- onClickRefresh,
1222
- title,
1223
- titleSize,
1224
- titleWeight
1225
- } = props;
1226
- const {
1227
- t
1228
- } = useTranslation();
1229
- const titleStyle = css({
1230
- fontSize: `${titleSize}px !important`,
1231
- fontWeight: `${titleWeight} !important`
1232
- });
1233
- return React.createElement(HeaderContainer, null, React.createElement(Typography, {
1234
- variant: "h4",
1235
- className: titleStyle()
1236
- }, title ? t(title.toLocaleLowerCase()) : ''), React.createElement(HeaderButtons, {
1237
- onClickRefresh: onClickRefresh
1238
- }));
1239
- }
1240
-
1241
1317
  const Box = /*#__PURE__*/styled('div', {
1242
1318
  display: 'flex',
1243
1319
  flexDirection: 'column',
@@ -1525,6 +1601,39 @@ const errorMessages = {
1525
1601
  genericServerError: 'Error connecting server, please reload the app and try again'
1526
1602
  };
1527
1603
 
1604
+ const ButtonsContainer = /*#__PURE__*/styled('div', {
1605
+ display: 'flex'
1606
+ });
1607
+ function HeaderButtons(props) {
1608
+ const {
1609
+ onClickRefresh
1610
+ } = props;
1611
+ const navigate = useNavigate();
1612
+ return React.createElement(ButtonsContainer, null, React.createElement(Tooltip, {
1613
+ content: "Refresh"
1614
+ }, React.createElement(Button, {
1615
+ variant: "ghost",
1616
+ onClick: onClickRefresh,
1617
+ disabled: !onClickRefresh
1618
+ }, React.createElement(RetryIcon, {
1619
+ size: 24
1620
+ }))), React.createElement(Tooltip, {
1621
+ content: "Transactions History"
1622
+ }, React.createElement(Button, {
1623
+ variant: "ghost",
1624
+ onClick: () => navigate(navigationRoutes.swaps)
1625
+ }, React.createElement(HistoryIcon, {
1626
+ size: 24
1627
+ }))), React.createElement(Tooltip, {
1628
+ content: "Settings"
1629
+ }, React.createElement(Button, {
1630
+ variant: "ghost",
1631
+ onClick: () => navigate(navigationRoutes.settings)
1632
+ }, React.createElement(SettingsIcon, {
1633
+ size: 24
1634
+ }))));
1635
+ }
1636
+
1528
1637
  const Container$2 = /*#__PURE__*/styled('div', {
1529
1638
  display: 'flex',
1530
1639
  flexDirection: 'column'
@@ -1549,9 +1658,7 @@ const Alerts = /*#__PURE__*/styled('div', {
1549
1658
  });
1550
1659
  function Home(props) {
1551
1660
  const {
1552
- title = 'SWAP',
1553
- titleSize = 18,
1554
- titleWeight = 600
1661
+ title = 'SWAP'
1555
1662
  } = props;
1556
1663
  const isRouterInContext = useInRouterContext();
1557
1664
  const navigate = useNavigate();
@@ -1575,6 +1682,7 @@ function Home(props) {
1575
1682
  const bestRouteError = useBestRouteStore.use.error();
1576
1683
  const loadingMetaStatus = useMetaStore.use.loadingStatus();
1577
1684
  const accounts = useWalletsStore.use.accounts();
1685
+ const setCurrentPage = useUiStore.use.setCurrentPage();
1578
1686
  const swithFromAndTo = () => {
1579
1687
  setFromChain(toChain);
1580
1688
  setFromToken(toToken);
@@ -1598,11 +1706,15 @@ function Home(props) {
1598
1706
  const swapButtonState = getSwapButtonState(loadingMetaStatus, accounts, fetchingBestRoute, bestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath, inputIsZero);
1599
1707
  const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
1600
1708
  const highFee = hasHighFee(totalFeeInUsd);
1601
- return React.createElement(Container$2, null, React.createElement(Header, {
1709
+ useEffect(() => {
1710
+ setCurrentPage(navigationRoutes.home);
1711
+ return setCurrentPage.bind(null, '');
1712
+ }, []);
1713
+ return React.createElement(Container$2, null, React.createElement(Header$1, {
1602
1714
  title: title,
1603
- titleSize: titleSize,
1604
- titleWeight: titleWeight,
1605
- onClickRefresh: fetchBestRoute
1715
+ suffix: React.createElement(HeaderButtons, {
1716
+ onClickRefresh: !!bestRoute ? fetchBestRoute : undefined
1717
+ })
1606
1718
  }), React.createElement(FromContainer, null, React.createElement(TokenInfo, {
1607
1719
  type: "From",
1608
1720
  chain: fromChain,
@@ -1613,7 +1725,7 @@ function Home(props) {
1613
1725
  variant: "ghost",
1614
1726
  onClick: swithFromAndTo
1615
1727
  }, React.createElement(VerticalSwapIcon, {
1616
- size: 24
1728
+ size: 32
1617
1729
  }), isRouterInContext && React.createElement(SwithFromAndTo, {
1618
1730
  count: count
1619
1731
  })))), React.createElement(TokenInfo, {
@@ -1647,7 +1759,7 @@ function Home(props) {
1647
1759
  disabled: swapButtonState.disabled,
1648
1760
  onClick: () => {
1649
1761
  if (swapButtonState.title === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
1650
- navigate(navigationRoutes.confirmWallets, {
1762
+ navigate(navigationRoutes.confirmSwap, {
1651
1763
  replace: true
1652
1764
  });
1653
1765
  }
@@ -1664,12 +1776,12 @@ const Route = _ref => {
1664
1776
  const navigate = useNavigate$1();
1665
1777
  const ref = useRef(true);
1666
1778
  useEffect(() => {
1667
- if ([navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname) && ref.current) navigate(navigationRoutes.home + location.search, {
1779
+ if (location.pathname === navigationRoutes.confirmSwap && ref.current) navigate(navigationRoutes.home + location.search, {
1668
1780
  state: 'redirect'
1669
1781
  });
1670
1782
  ref.current = false;
1671
1783
  }, []);
1672
- if ([navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname) && ref.current) return React.createElement(Home, Object.assign({}, props));
1784
+ if (location.pathname === navigationRoutes.confirmSwap && ref.current) return React.createElement(Home, Object.assign({}, props));
1673
1785
  return React.createElement(React.Fragment, null, " ", children);
1674
1786
  };
1675
1787
  function AppRouter(_ref2) {
@@ -1679,52 +1791,34 @@ function AppRouter(_ref2) {
1679
1791
  } = _ref2;
1680
1792
  const isRouterInContext = useInRouterContext$1();
1681
1793
  const Router = isRouterInContext ? Route : MemoryRouter;
1682
- return React.createElement(React.Fragment, null, React.createElement(Router, Object.assign({}, props), children), isRouterInContext && React.createElement(UpdateUrl, null));
1683
- }
1684
-
1685
- function ChangeSlippageButton() {
1686
- const navigate = useNavigate();
1687
- return React.createElement(Button, {
1688
- type: "primary",
1689
- variant: "outlined",
1690
- size: "small",
1691
- onClick: () => navigate(navigationRoutes.settings)
1692
- }, "Change Slippage");
1693
- }
1694
-
1695
- function HighSlippageWarning(props) {
1696
- const {
1697
- selectedSlippage
1698
- } = props;
1699
- return React.createElement(Alert, {
1700
- type: "warning",
1701
- footer: React.createElement(ChangeSlippageButton, null)
1702
- }, "Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.");
1703
- }
1704
-
1705
- function ConfirmSwapExtraMessages(props) {
1706
1794
  const {
1707
- selectedSlippage
1708
- } = props;
1709
- const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
1710
- return React.createElement(React.Fragment, null, highSlippage && React.createElement(HighSlippageWarning, {
1711
- selectedSlippage: selectedSlippage
1712
- }));
1795
+ blockchains
1796
+ } = useMetaStore.use.meta();
1797
+ const evmChains = blockchains.filter(isEvmBlockchain);
1798
+ useQueueManager({
1799
+ lastConnectedWallet: props.lastConnectedWallet,
1800
+ clearDisconnectedWallet: props.clearDisconnectedWallet,
1801
+ disconnectedWallet: props.disconnectedWallet,
1802
+ evmChains,
1803
+ notifier: () => {}
1804
+ });
1805
+ return React.createElement(React.Fragment, null, React.createElement(Router, Object.assign({}, props), children), isRouterInContext && React.createElement(UpdateUrl, null));
1713
1806
  }
1714
1807
 
1715
1808
  function useNavigateBack() {
1716
1809
  const isRouterInContext = useInRouterContext();
1717
1810
  const navigate = useNavigate();
1718
1811
  const navigateBackFrom = currentRoute => {
1812
+ if (currentRoute === navigationRoutes.swapDetails) return navigate(navigationRoutes.swaps, {
1813
+ replace: true
1814
+ });
1719
1815
  if (!isRouterInContext || window.history.state && window.history.state.idx > 0) navigate(-1);else {
1720
- if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.swaps, navigationRoutes.confirmWallets].includes(currentRoute)) navigate(navigationRoutes.home, {
1816
+ if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.swaps, navigationRoutes.confirmSwap].includes(currentRoute)) navigate(navigationRoutes.home, {
1721
1817
  replace: true
1722
1818
  });else if (currentRoute === navigationRoutes.liquiditySources) navigate(navigationRoutes.settings, {
1723
1819
  replace: true
1724
1820
  });else if (currentRoute === navigationRoutes.swapDetails) navigate(navigationRoutes.swaps, {
1725
1821
  replace: true
1726
- });else if (currentRoute === navigationRoutes.confirmSwap) navigate(navigationRoutes.confirmWallets, {
1727
- replace: true
1728
1822
  });
1729
1823
  }
1730
1824
  };
@@ -1733,122 +1827,192 @@ function useNavigateBack() {
1733
1827
  };
1734
1828
  }
1735
1829
 
1736
- var ConfirmSwapErrorTypes;
1737
- (function (ConfirmSwapErrorTypes) {
1738
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
1739
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
1740
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
1741
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
1742
- })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
1743
- var ConfirmSwapWarningTypes;
1744
- (function (ConfirmSwapWarningTypes) {
1745
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
1746
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
1747
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
1748
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
1749
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
1750
- })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
1751
-
1752
- function MinRequiredSlippage(_ref) {
1753
- let {
1754
- minRequiredSlippage
1755
- } = _ref;
1756
- return React.createElement(Typography, {
1757
- variant: "body2"
1758
- }, "We recommend you to increase slippage to at least \u00A0", minRequiredSlippage, "\u00A0 for this route.", React.createElement(ChangeSlippageButton, null));
1759
- }
1760
-
1761
- function ConfirmSwapErrors(errors) {
1762
- return errors.flatMap(error => {
1763
- switch (error.type) {
1764
- case ConfirmSwapErrorTypes.NO_ROUTE:
1765
- return React.createElement(Typography, {
1766
- variant: "body2"
1767
- }, "No routes found. Please try again later.");
1768
- case ConfirmSwapErrorTypes.REQUEST_FAILED:
1769
- return React.createElement(Typography, {
1770
- variant: "body2"
1771
- }, `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`);
1772
- case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
1773
- return React.createElement(Typography, {
1774
- variant: "body2"
1775
- }, "Route updated and price impact is too high, try again later!");
1776
- case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
1777
- return React.createElement(MinRequiredSlippage, {
1778
- minRequiredSlippage: error.minRequiredSlippage
1779
- });
1780
- default:
1781
- return [];
1782
- }
1783
- });
1784
- }
1785
-
1786
- const List = /*#__PURE__*/styled('ul', {
1787
- variants: {
1788
- showListStyle: {
1789
- true: {
1790
- paddingLeft: '$24'
1791
- }
1792
- }
1793
- }
1830
+ const Box$1 = /*#__PURE__*/styled('div', {
1831
+ display: 'flex',
1832
+ flexDirection: 'column',
1833
+ width: '100%'
1794
1834
  });
1795
- const ListItem = /*#__PURE__*/styled('li', {
1835
+ const Container$3 = /*#__PURE__*/styled('div', {
1836
+ boxSizing: 'border-box',
1837
+ borderRadius: '$5',
1838
+ padding: '$8 $16 $16 $16',
1796
1839
  variants: {
1797
- showListStyle: {
1798
- true: {
1799
- listStyleType: 'disc',
1800
- listStylePosition: 'outside'
1840
+ type: {
1841
+ filled: {
1842
+ backgroundColor: '$neutrals300'
1843
+ },
1844
+ outlined: {
1845
+ border: '1px solid $neutrals300'
1801
1846
  }
1802
1847
  }
1803
- }
1804
- });
1805
- const Message = /*#__PURE__*/styled(Typography, {
1806
- display: 'block'
1807
- });
1808
- function BalanceWarnings(_ref) {
1809
- let {
1810
- messages
1811
- } = _ref;
1812
- const showListStyle = messages.length > 1;
1813
- return React.createElement(List, {
1814
- showListStyle: showListStyle
1815
- }, messages.map(warning => React.createElement(ListItem, {
1816
- showListStyle: showListStyle
1817
- }, React.createElement(Message, {
1818
- variant: "body2"
1819
- }, warning))));
1848
+ },
1849
+ defaultVariants: {
1850
+ type: 'filled'
1851
+ },
1852
+ '.head': {
1853
+ display: 'flex',
1854
+ justifyContent: 'space-between',
1855
+ alignItems: 'center',
1856
+ minHeight: '32px'
1857
+ },
1858
+ '.form': {
1859
+ display: 'flex',
1860
+ width: '100%',
1861
+ padding: '$2 0',
1862
+ '.selectors': {
1863
+ width: '35%',
1864
+ '._text': {
1865
+ whiteSpace: 'nowrap',
1866
+ overflow: 'hidden',
1867
+ textOverflow: 'ellipsis'
1868
+ }
1869
+ },
1870
+ '.amount': {
1871
+ width: '30%'
1872
+ }
1873
+ }
1874
+ });
1875
+ const StyledImage$1 = /*#__PURE__*/styled('img', {
1876
+ width: '$24',
1877
+ maxHeight: '$24'
1878
+ });
1879
+ const ImagePlaceholder$1 = /*#__PURE__*/styled('span', {
1880
+ width: '24px',
1881
+ height: '24px',
1882
+ backgroundColor: '$neutrals300',
1883
+ borderRadius: '99999px'
1884
+ });
1885
+ const OutputContainer$1 = /*#__PURE__*/styled('div', {
1886
+ windth: '100%',
1887
+ height: '$48',
1888
+ borderRadius: '$5',
1889
+ backgroundColor: '$background',
1890
+ border: '1px solid transparent',
1891
+ position: 'relative',
1892
+ display: 'flex',
1893
+ alignItems: 'center',
1894
+ paddingLeft: '$8',
1895
+ paddingRight: '$8'
1896
+ });
1897
+ function TokenPreview(props) {
1898
+ const {
1899
+ chain,
1900
+ token,
1901
+ loadingStatus
1902
+ } = props;
1903
+ const {
1904
+ t
1905
+ } = useTranslation();
1906
+ const ItemSuffix = React.createElement("div", {
1907
+ style: {
1908
+ display: 'flex',
1909
+ justifyContent: 'center',
1910
+ alignItems: 'center'
1911
+ }
1912
+ }, loadingStatus === 'failed' && React.createElement(InfoCircleIcon, {
1913
+ color: "error",
1914
+ size: 24
1915
+ }));
1916
+ return React.createElement(Box$1, null, React.createElement(Container$3, {
1917
+ type: 'outlined'
1918
+ }, React.createElement("div", {
1919
+ className: "head"
1920
+ }, React.createElement(Typography, {
1921
+ variant: "body2",
1922
+ color: "neutrals800"
1923
+ }, props.label), props.usdValue && React.createElement(Typography, {
1924
+ variant: "caption",
1925
+ color: "neutrals600"
1926
+ }, `$${numberToString(props.usdValue)}`)), React.createElement("div", {
1927
+ className: "form"
1928
+ }, React.createElement(Button, {
1929
+ className: "selectors",
1930
+ variant: "outlined",
1931
+ loading: loadingStatus === 'loading',
1932
+ prefix: loadingStatus === 'success' && chain ? React.createElement(StyledImage$1, {
1933
+ src: chain.logo
1934
+ }) : React.createElement(ImagePlaceholder$1, null),
1935
+ suffix: ItemSuffix,
1936
+ align: "start",
1937
+ size: "large"
1938
+ }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React.createElement(Spacer, {
1939
+ size: 12
1940
+ }), React.createElement(Button, {
1941
+ className: "selectors",
1942
+ variant: "outlined",
1943
+ loading: loadingStatus === 'loading',
1944
+ prefix: loadingStatus === 'success' && token ? React.createElement(StyledImage$1, {
1945
+ src: token.image
1946
+ }) : React.createElement(ImagePlaceholder$1, null),
1947
+ suffix: ItemSuffix,
1948
+ size: "large",
1949
+ align: "start"
1950
+ }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React.createElement(Spacer, {
1951
+ size: 12
1952
+ }), React.createElement("div", {
1953
+ className: "amount"
1954
+ }, React.createElement(OutputContainer$1, null, React.createElement(Typography, {
1955
+ variant: "h4"
1956
+ }, props.amount))))));
1820
1957
  }
1821
1958
 
1822
- function ConfirmSwapWarnings(warnings) {
1823
- return warnings.flatMap(warning => {
1824
- switch (warning.type) {
1825
- case ConfirmSwapWarningTypes.ROUTE_UPDATED:
1826
- return React.createElement(Typography, {
1827
- variant: "body2"
1828
- }, "Route has been updated.");
1829
- case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
1830
- return React.createElement(Typography, {
1831
- variant: "body2"
1832
- }, `Output amount changed to ${warning.newOutputAmount}
1833
- (${warning.percentageChange}% change).`);
1834
- case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
1835
- return React.createElement(Typography, {
1836
- variant: "body2"
1837
- }, "Route swappers has been updated.");
1838
- case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
1839
- return React.createElement(Typography, {
1840
- variant: "body2"
1841
- }, "Route internal coins has been updated.");
1842
- case ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE:
1843
- return React.createElement(BalanceWarnings, {
1844
- messages: warning.messages
1845
- });
1846
- default:
1847
- return [];
1848
- }
1849
- });
1959
+ const Container$4 = /*#__PURE__*/styled('div', {
1960
+ display: 'flex',
1961
+ alignItems: 'center',
1962
+ justifyContent: 'space-between',
1963
+ padding: '$8',
1964
+ borderRadius: '$5',
1965
+ backgroundColor: '$neutrals300',
1966
+ color: '$neutrals800',
1967
+ fontSize: '$12',
1968
+ '.routes': {
1969
+ display: 'flex',
1970
+ alignItems: 'center'
1971
+ },
1972
+ '.fee': {
1973
+ display: 'flex',
1974
+ alignItems: 'center'
1975
+ }
1976
+ });
1977
+ function RoutesOverview(props) {
1978
+ if (!props.routes) return null;
1979
+ const swaps = props.routes.result?.swaps;
1980
+ return React.createElement(Container$4, null, React.createElement("div", {
1981
+ className: "routes"
1982
+ }, swaps?.map((swap, idx) => {
1983
+ const isLast = idx + 1 == swaps.length;
1984
+ return React.createElement(React.Fragment, null, React.createElement("div", {
1985
+ className: "route"
1986
+ }, swap.from.symbol), React.createElement(ChevronRightIcon, {
1987
+ size: 12
1988
+ }), isLast ? React.createElement("div", {
1989
+ className: "route"
1990
+ }, swap.to.symbol) : null);
1991
+ })), props.totalFee ? React.createElement("div", {
1992
+ className: "fee"
1993
+ }, React.createElement(GasIcon, {
1994
+ size: 12
1995
+ }), React.createElement(Spacer, {
1996
+ size: 4
1997
+ }), "$", props.totalFee) : null);
1850
1998
  }
1851
1999
 
2000
+ var ConfirmSwapErrorTypes;
2001
+ (function (ConfirmSwapErrorTypes) {
2002
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
2003
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
2004
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
2005
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
2006
+ })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
2007
+ var ConfirmSwapWarningTypes;
2008
+ (function (ConfirmSwapWarningTypes) {
2009
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
2010
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
2011
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
2012
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
2013
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
2014
+ })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
2015
+
1852
2016
  function useConfirmSwap() {
1853
2017
  const fromToken = useBestRouteStore.use.fromToken();
1854
2018
  const toToken = useBestRouteStore.use.toToken();
@@ -1889,6 +2053,7 @@ function useConfirmSwap() {
1889
2053
  proceedAnywayRef.current = false;
1890
2054
  if (confiremedRouteRef.current) {
1891
2055
  const newSwap = calculatePendingSwap(inputAmount.toString(), confiremedRouteRef.current, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
2056
+ //@ts-ignore
1892
2057
  return newSwap;
1893
2058
  }
1894
2059
  return;
@@ -1951,6 +2116,7 @@ function useConfirmSwap() {
1951
2116
  disabledSwappersGroups: disabledLiquiditySources
1952
2117
  };
1953
2118
  const newSwap = calculatePendingSwap(inputAmount.toString(), confiremedRoute, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
2119
+ //@ts-ignore
1954
2120
  return newSwap;
1955
2121
  } else if (!proceedAnywayRef.current) {
1956
2122
  proceedAnywayRef.current = true;
@@ -1980,66 +2146,266 @@ function useConfirmSwap() {
1980
2146
  };
1981
2147
  }
1982
2148
 
1983
- function ConfirmSwapPage() {
1984
- const setSelectedSwap = useUiStore.use.setSelectedSwap();
1985
- const {
1986
- navigateBackFrom
1987
- } = useNavigateBack();
1988
- const {
1989
- manager
1990
- } = useManager();
2149
+ function ChangeSlippageButton() {
1991
2150
  const navigate = useNavigate();
1992
- const bestRoute = useBestRouteStore.use.bestRoute();
1993
- const fetchingBestRoute = useBestRouteStore.use.loading();
1994
- const {
1995
- tokens
1996
- } = useMetaStore.use.meta();
1997
- const slippage = useSettingsStore.use.slippage();
1998
- const customSlippage = useSettingsStore.use.customSlippage();
1999
- const selectedSlippage = customSlippage || slippage;
2000
- const {
2001
- loading,
2002
- errors,
2003
- warnings,
2004
- confirmSwap
2005
- } = useConfirmSwap();
2006
- const showHighSlippageWarning = !errors.find(error => error.type === ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE);
2007
- return React.createElement(ConfirmSwap, {
2008
- onConfirm: () => {
2009
- confirmSwap?.().then(swap => {
2010
- if (swap) {
2011
- manager?.create('swap', {
2012
- swapDetails: swap
2013
- }, {
2014
- id: swap.requestId
2015
- });
2016
- setSelectedSwap(swap.requestId);
2017
- navigate(navigationRoutes.swaps + `/${swap.requestId}`, {
2018
- replace: true
2019
- });
2020
- }
2021
- });
2022
- },
2023
- onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
2024
- bestRoute: getBestRouteWithCalculatedFees(bestRoute, tokens),
2025
- loading: loading,
2026
- errors: ConfirmSwapErrors(errors),
2027
- warnings: ConfirmSwapWarnings(warnings),
2028
- extraMessages: showHighSlippageWarning && React.createElement(ConfirmSwapExtraMessages, {
2029
- selectedSlippage: selectedSlippage
2030
- }),
2031
- confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!',
2032
- confirmButtonDisabled: fetchingBestRoute
2033
- });
2151
+ return React.createElement(Button, {
2152
+ type: "primary",
2153
+ variant: "outlined",
2154
+ size: "small",
2155
+ onClick: () => navigate(navigationRoutes.settings)
2156
+ }, "Change Slippage");
2034
2157
  }
2035
2158
 
2036
- const getPendingSwaps = manager => {
2037
- const result = [];
2038
- manager?.getAll().forEach((q, id) => {
2039
- const storage = q.list.getStorage();
2040
- if (storage?.swapDetails) {
2041
- result.push({
2042
- id,
2159
+ const StyledMessage = /*#__PURE__*/styled(Typography, {
2160
+ color: '$error500 !important'
2161
+ });
2162
+ function MinRequiredSlippage(_ref) {
2163
+ let {
2164
+ minRequiredSlippage
2165
+ } = _ref;
2166
+ return React.createElement(StyledMessage, {
2167
+ variant: "body2"
2168
+ }, "We recommend you to increase slippage to at least \u00A0", minRequiredSlippage, "\u00A0 for this route.", React.createElement(Spacer, {
2169
+ size: 8,
2170
+ direction: "vertical"
2171
+ }), React.createElement(ChangeSlippageButton, null));
2172
+ }
2173
+
2174
+ function ConfirmSwapErrors(errors) {
2175
+ return errors.flatMap(error => {
2176
+ switch (error.type) {
2177
+ case ConfirmSwapErrorTypes.NO_ROUTE:
2178
+ return React.createElement(Typography, {
2179
+ variant: "body2"
2180
+ }, "No routes found. Please try again later.");
2181
+ case ConfirmSwapErrorTypes.REQUEST_FAILED:
2182
+ return React.createElement(Typography, {
2183
+ variant: "body2"
2184
+ }, `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`);
2185
+ case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
2186
+ return React.createElement(Typography, {
2187
+ variant: "body2"
2188
+ }, "Route updated and price impact is too high, try again later!");
2189
+ case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
2190
+ return React.createElement(MinRequiredSlippage, {
2191
+ minRequiredSlippage: error.minRequiredSlippage
2192
+ });
2193
+ default:
2194
+ return [];
2195
+ }
2196
+ });
2197
+ }
2198
+
2199
+ const List = /*#__PURE__*/styled('ul', {
2200
+ variants: {
2201
+ showListStyle: {
2202
+ true: {
2203
+ paddingLeft: '$24'
2204
+ }
2205
+ }
2206
+ }
2207
+ });
2208
+ const ListItem = /*#__PURE__*/styled('li', {
2209
+ variants: {
2210
+ showListStyle: {
2211
+ true: {
2212
+ listStyleType: 'disc',
2213
+ listStylePosition: 'outside'
2214
+ }
2215
+ }
2216
+ }
2217
+ });
2218
+ const Message = /*#__PURE__*/styled(Typography, {
2219
+ display: 'block',
2220
+ color: '$warning500 !important'
2221
+ });
2222
+ function BalanceWarnings(_ref) {
2223
+ let {
2224
+ messages
2225
+ } = _ref;
2226
+ const showListStyle = messages.length > 1;
2227
+ return React.createElement(List, {
2228
+ showListStyle: showListStyle
2229
+ }, messages.map(warning => React.createElement(ListItem, {
2230
+ showListStyle: showListStyle
2231
+ }, React.createElement(Message, {
2232
+ variant: "body2"
2233
+ }, warning))));
2234
+ }
2235
+
2236
+ function ConfirmSwapWarnings(warnings) {
2237
+ return warnings.flatMap(warning => {
2238
+ switch (warning.type) {
2239
+ case ConfirmSwapWarningTypes.ROUTE_UPDATED:
2240
+ return React.createElement(Typography, {
2241
+ variant: "body2"
2242
+ }, "Route has been updated.");
2243
+ case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
2244
+ return React.createElement(Typography, {
2245
+ variant: "body2"
2246
+ }, `Output amount changed to ${warning.newOutputAmount}
2247
+ (${warning.percentageChange}% change).`);
2248
+ case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
2249
+ return React.createElement(Typography, {
2250
+ variant: "body2"
2251
+ }, "Route swappers has been updated.");
2252
+ case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
2253
+ return React.createElement(Typography, {
2254
+ variant: "body2"
2255
+ }, "Route internal coins has been updated.");
2256
+ case ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE:
2257
+ return React.createElement(BalanceWarnings, {
2258
+ messages: warning.messages
2259
+ });
2260
+ default:
2261
+ return [];
2262
+ }
2263
+ });
2264
+ }
2265
+
2266
+ function HighSlippageWarning(props) {
2267
+ const {
2268
+ selectedSlippage
2269
+ } = props;
2270
+ return React.createElement(Alert, {
2271
+ type: "warning",
2272
+ footer: React.createElement(ChangeSlippageButton, null)
2273
+ }, "Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.");
2274
+ }
2275
+
2276
+ function ConfirmSwapExtraMessages(props) {
2277
+ const {
2278
+ selectedSlippage
2279
+ } = props;
2280
+ const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
2281
+ return React.createElement(React.Fragment, null, highSlippage && React.createElement(HighSlippageWarning, {
2282
+ selectedSlippage: selectedSlippage
2283
+ }));
2284
+ }
2285
+
2286
+ function ConfirmSwapPage() {
2287
+ const navigate = useNavigate();
2288
+ const {
2289
+ navigateBackFrom
2290
+ } = useNavigateBack();
2291
+ const bestRoute = useBestRouteStore.use.bestRoute();
2292
+ const fetchingBestRoute = useBestRouteStore.use.loading();
2293
+ const fetchingBestRouteError = useBestRouteStore.use.error();
2294
+ const setSelectedSwap = useUiStore.use.setSelectedSwap();
2295
+ const {
2296
+ blockchains,
2297
+ tokens
2298
+ } = useMetaStore.use.meta();
2299
+ const accounts = useWalletsStore.use.accounts();
2300
+ const selectedWallets = useWalletsStore.use.selectedWallets();
2301
+ const initSelectedWallets = useWalletsStore.use.initSelectedWallets();
2302
+ const setSelectedWallet = useWalletsStore.use.setSelectedWallet();
2303
+ const slippage = useSettingsStore.use.slippage();
2304
+ const customSlippage = useSettingsStore.use.customSlippage();
2305
+ const bestRouteloadingStatus = getBestRouteStatus(fetchingBestRoute, !!fetchingBestRouteError);
2306
+ const {
2307
+ manager
2308
+ } = useManager();
2309
+ const {
2310
+ loading,
2311
+ errors,
2312
+ warnings,
2313
+ confirmSwap
2314
+ } = useConfirmSwap();
2315
+ const selectedSlippage = customSlippage || slippage;
2316
+ const showHighSlippageWarning = !errors.find(error => error.type === ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE);
2317
+ const {
2318
+ getWalletInfo,
2319
+ connect
2320
+ } = useWallets();
2321
+ const confirmDisabled = fetchingBestRoute || !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
2322
+ const firstStep = bestRoute?.result?.swaps[0];
2323
+ const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
2324
+ const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
2325
+ const toAmount = decimalNumber(lastStep?.toAmount, 3);
2326
+ useEffect(() => {
2327
+ initSelectedWallets();
2328
+ }, []);
2329
+ const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
2330
+ const handleConnectChain = wallet => {
2331
+ const network = wallet;
2332
+ getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
2333
+ };
2334
+ const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
2335
+ return React.createElement(ConfirmSwap, {
2336
+ requiredWallets: getRequiredChains(bestRoute),
2337
+ selectableWallets: selectableWallets,
2338
+ onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
2339
+ onConfirm: () => {
2340
+ confirmSwap?.().then(swap => {
2341
+ if (swap) {
2342
+ manager?.create('swap', {
2343
+ swapDetails: swap
2344
+ }, {
2345
+ id: swap.requestId
2346
+ });
2347
+ setSelectedSwap(swap.requestId);
2348
+ navigate(navigationRoutes.swaps + `/${swap.requestId}`, {
2349
+ replace: true
2350
+ });
2351
+ }
2352
+ });
2353
+ },
2354
+ onChange: wallet => setSelectedWallet(wallet),
2355
+ confirmDisabled: confirmDisabled,
2356
+ handleConnectChain: wallet => handleConnectChain(wallet),
2357
+ isExperimentalChain: wallet => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains, wallet) : false,
2358
+ previewInputs: React.createElement(React.Fragment, null, React.createElement(TokenPreview, {
2359
+ chain: {
2360
+ displayName: firstStep?.from.blockchain || '',
2361
+ logo: firstStep?.from.blockchainLogo || ''
2362
+ },
2363
+ token: {
2364
+ symbol: firstStep?.from.symbol || '',
2365
+ image: firstStep?.from.logo || ''
2366
+ },
2367
+ usdValue: calcOutputUsdValue(fromAmount, firstStep?.from.usdPrice),
2368
+ amount: fromAmount,
2369
+ label: t('From'),
2370
+ loadingStatus: bestRouteloadingStatus
2371
+ }), React.createElement(Spacer, {
2372
+ size: 12,
2373
+ direction: "vertical"
2374
+ }), React.createElement(TokenPreview, {
2375
+ chain: {
2376
+ displayName: lastStep?.to.blockchain || '',
2377
+ logo: lastStep?.to.blockchainLogo || ''
2378
+ },
2379
+ token: {
2380
+ symbol: lastStep?.to.symbol || '',
2381
+ image: lastStep?.to.logo || ''
2382
+ },
2383
+ usdValue: calcOutputUsdValue(toAmount, lastStep?.to.usdPrice),
2384
+ amount: toAmount,
2385
+ label: t('To'),
2386
+ loadingStatus: bestRouteloadingStatus
2387
+ })),
2388
+ previewRoutes: React.createElement(RoutesOverview, {
2389
+ routes: bestRoute,
2390
+ totalFee: numberToString(totalFeeInUsd, 0, 2)
2391
+ }),
2392
+ loading: loading,
2393
+ errors: ConfirmSwapErrors(errors),
2394
+ warnings: ConfirmSwapWarnings(warnings),
2395
+ extraMessages: showHighSlippageWarning && React.createElement(ConfirmSwapExtraMessages, {
2396
+ selectedSlippage: selectedSlippage
2397
+ }),
2398
+ confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!'
2399
+ });
2400
+ }
2401
+
2402
+ const getPendingSwaps = manager => {
2403
+ const result = [];
2404
+ manager?.getAll().forEach((q, id) => {
2405
+ const storage = q.list.getStorage();
2406
+ if (storage?.swapDetails) {
2407
+ result.push({
2408
+ id,
2043
2409
  swap: storage?.swapDetails
2044
2410
  });
2045
2411
  }
@@ -2047,6 +2413,31 @@ const getPendingSwaps = manager => {
2047
2413
  return result.sort((a, b) => Number(b.swap.creationTime) - Number(a.swap.creationTime));
2048
2414
  };
2049
2415
 
2416
+ const groupSwapsByDate = swaps => {
2417
+ const output = new Map([['today', {
2418
+ title: 'Today',
2419
+ swaps: []
2420
+ }], ['week', {
2421
+ title: 'This week',
2422
+ swaps: []
2423
+ }], ['month', {
2424
+ title: 'This month',
2425
+ swaps: []
2426
+ }], ['year', {
2427
+ title: 'This year',
2428
+ swaps: []
2429
+ }], ['history', {
2430
+ title: 'History',
2431
+ swaps: []
2432
+ }]]);
2433
+ const now = dayjs();
2434
+ swaps.forEach(swap => {
2435
+ const swapDate = dayjs(Number(swap.creationTime));
2436
+ 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);
2437
+ });
2438
+ return Array.from(output.values());
2439
+ };
2440
+
2050
2441
  function HistoryPage() {
2051
2442
  const setSelectedSwap = useUiStore.use.setSelectedSwap();
2052
2443
  const navigate = useNavigate();
@@ -2062,16 +2453,14 @@ function HistoryPage() {
2062
2453
  } = _ref;
2063
2454
  return swap;
2064
2455
  });
2065
- return React.createElement(History
2066
- //todo: move PendingSwap type to rango-types
2067
- //@ts-ignore
2068
- , {
2069
- //todo: move PendingSwap type to rango-types
2070
- //@ts-ignore
2456
+ return React.createElement(History, {
2071
2457
  list: pendingSwaps,
2458
+ groupBy: groupSwapsByDate,
2072
2459
  onSwapClick: requestId => {
2073
2460
  setSelectedSwap(requestId);
2074
- navigate(navigationRoutes.swaps + `/${requestId}`);
2461
+ navigate(navigationRoutes.swaps + `/${requestId}`, {
2462
+ replace: true
2463
+ });
2075
2464
  },
2076
2465
  onBack: navigateBackFrom.bind(null, navigationRoutes.swaps)
2077
2466
  });
@@ -2082,6 +2471,7 @@ function LiquiditySourcePage(_ref) {
2082
2471
  supportedSwappers
2083
2472
  } = _ref;
2084
2473
  const swappers = useMetaStore.use.meta().swappers;
2474
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2085
2475
  const toggleLiquiditySource = useSettingsStore.use.toggleLiquiditySource();
2086
2476
  const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2087
2477
  const toggleAllLiquiditySources = useSettingsStore.use.toggleAllLiquiditySources();
@@ -2107,7 +2497,8 @@ function LiquiditySourcePage(_ref) {
2107
2497
  toggleAll: toggleAllLiquiditySources,
2108
2498
  list: supportedSwappers !== 'all' ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0) : uniqueSwappersGroups,
2109
2499
  onChange: liquiditySource => toggleLiquiditySource(liquiditySource.title),
2110
- onBack: navigateBackFrom.bind(null, navigationRoutes.liquiditySources)
2500
+ onBack: navigateBackFrom.bind(null, navigationRoutes.liquiditySources),
2501
+ loadingStatus: loadingMetaStatus
2111
2502
  });
2112
2503
  }
2113
2504
 
@@ -2150,390 +2541,168 @@ function SelectTokenPage(props) {
2150
2541
  const destinationTokens = useBestRouteStore.use.destinationTokens();
2151
2542
  const supportedSourceTokens = supportedTokens === 'all' ? sourceTokens : sourceTokens.filter(token => supportedTokens.some(supportedToken => tokensAreEqual(supportedToken, token)));
2152
2543
  const supportedDestinationTokens = supportedTokens === 'all' ? destinationTokens : destinationTokens.filter(token => supportedTokens.some(supportedToken => tokensAreEqual(supportedToken, token)));
2153
- console.log(supportedSourceTokens);
2154
2544
  const fromToken = useBestRouteStore.use.fromToken();
2155
- const toToken = useBestRouteStore.use.toToken();
2156
- const setFromToken = useBestRouteStore.use.setFromToken();
2157
- const setToToken = useBestRouteStore.use.setToToken();
2158
- return React.createElement(TokenSelector, {
2159
- type: type === 'from' ? 'Source' : 'Destination',
2160
- list: type == 'from' ? supportedSourceTokens : supportedDestinationTokens,
2161
- selected: type === 'from' ? fromToken : toToken,
2162
- onChange: token => {
2163
- if (type === 'from') setFromToken(token);else setToToken(token);
2164
- navigateBackFrom(navigationRoutes.fromToken);
2165
- },
2166
- onBack: navigateBackFrom.bind(null, navigationRoutes.fromToken)
2167
- });
2168
- }
2169
-
2170
- function SettingsPage(_ref) {
2171
- let {
2172
- supportedSwappers
2173
- } = _ref;
2174
- const slippage = useSettingsStore.use.slippage();
2175
- const setSlippage = useSettingsStore.use.setSlippage();
2176
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2177
- const customSlippage = useSettingsStore.use.customSlippage();
2178
- const setCustomSlippage = useSettingsStore.use.setCustomSlippage();
2179
- const theme = useSettingsStore.use.theme();
2180
- const setTheme = useSettingsStore.use.setTheme();
2181
- const swappers = useMetaStore.use.meta().swappers;
2182
- const navigate = useNavigate();
2183
- const {
2184
- navigateBackFrom
2185
- } = useNavigateBack();
2186
- const infiniteApprove = useSettingsStore.use.infiniteApprove();
2187
- const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();
2188
- const uniqueSwappersGroups = [];
2189
- removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2190
- return swappers.find(s => s.swapperGroup === swapperGroup);
2191
- }).find(s => {
2192
- if (s) {
2193
- for (const type of s.types) {
2194
- uniqueSwappersGroups.push({
2195
- title: s.swapperGroup,
2196
- logo: s.logo,
2197
- type,
2198
- selected: !disabledLiquiditySources.includes(s.swapperGroup)
2199
- });
2200
- }
2201
- }
2202
- });
2203
- supportedSwappers !== 'all' && uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0);
2204
- const supportedUniqueSwappersGroups = supportedSwappers !== 'all' ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0) : uniqueSwappersGroups;
2205
- return React.createElement(Settings, {
2206
- slippages: SLIPPAGES,
2207
- selectedSlippage: slippage,
2208
- onSlippageChange: slippage => setSlippage(slippage),
2209
- onLiquiditySourcesClick: () => navigate(navigationRoutes.liquiditySources),
2210
- onBack: navigateBackFrom.bind(null, navigationRoutes.settings),
2211
- liquiditySources: supportedUniqueSwappersGroups,
2212
- selectedLiquiditySources: supportedUniqueSwappersGroups.filter(s => s.selected),
2213
- customSlippage: customSlippage || NaN,
2214
- onCustomSlippageChange: setCustomSlippage,
2215
- minSlippage: MIN_SLIPPGAE,
2216
- maxSlippage: MAX_SLIPPAGE,
2217
- selectedTheme: theme,
2218
- onThemeChange: setTheme,
2219
- infiniteApprove: infiniteApprove,
2220
- toggleInfiniteApprove: toggleInfiniteApprove
2221
- });
2222
- }
2223
-
2224
- const ListContainer = /*#__PURE__*/styled('div', {
2225
- display: 'grid',
2226
- gap: '.5rem',
2227
- gridTemplateColumns: ' repeat(2, minmax(0, 1fr))',
2228
- height: '450px',
2229
- alignContent: 'baseline',
2230
- padding: '0.5rem'
2231
- });
2232
- const AlertContainer = /*#__PURE__*/styled('div', {
2233
- paddingBottom: '$16'
2234
- });
2235
- function WalletsPage(_ref) {
2236
- let {
2237
- supportedWallets,
2238
- multiWallets
2239
- } = _ref;
2240
- const {
2241
- navigateBackFrom
2242
- } = useNavigateBack();
2243
- const {
2244
- state,
2245
- disconnect,
2246
- getWalletInfo,
2247
- connect
2248
- } = useWallets();
2249
- const wallets = getlistWallet(state, getWalletInfo, supportedWallets === 'all' ? Object.values(WalletType) : supportedWallets);
2250
- let sortedWallets = detectMobileScreens() ? wallets.filter(wallet => wallet.showOnMobile) : wallets;
2251
- sortedWallets = sortWalletsBasedOnState(sortedWallets);
2252
- const [walletErrorMessage, setWalletErrorMessage] = useState('');
2253
- const toggleConnectWalletsButton = useUiStore.use.toggleConnectWalletsButton();
2254
- const {
2255
- t
2256
- } = useTranslation();
2257
- const onSelectWallet = async type => {
2258
- const wallet = state(type);
2259
- try {
2260
- if (walletErrorMessage) setWalletErrorMessage('');
2261
- if (wallet.connected) {
2262
- await disconnect(type);
2263
- } else {
2264
- if (!multiWallets && !!wallets.find(w => w.state === WalletState.CONNECTED)) {
2265
- return;
2266
- }
2267
- await connect(type);
2268
- }
2269
- } catch (e) {
2270
- setWalletErrorMessage('Error: ' + e?.message);
2271
- }
2272
- };
2273
- useEffect(() => {
2274
- toggleConnectWalletsButton();
2275
- return () => toggleConnectWalletsButton();
2276
- }, []);
2277
- return React.createElement(SecondaryPage, {
2278
- title: t('Select Wallet') || '',
2279
- textField: false,
2280
- onBack: navigateBackFrom.bind(null, navigationRoutes.wallets)
2281
- }, React.createElement(React.Fragment, null, walletErrorMessage && React.createElement(AlertContainer, null, React.createElement(Alert, {
2282
- type: "error"
2283
- }, walletErrorMessage)), React.createElement(ListContainer, null, sortedWallets.map((wallet, index) => React.createElement(Wallet, Object.assign({}, wallet, {
2284
- key: `${index}-${wallet.type}`,
2285
- onClick: onSelectWallet
2286
- }))))));
2287
- }
2288
-
2289
- const Box$1 = /*#__PURE__*/styled('div', {
2290
- display: 'flex',
2291
- flexDirection: 'column',
2292
- width: '100%'
2293
- });
2294
- const Container$3 = /*#__PURE__*/styled('div', {
2295
- boxSizing: 'border-box',
2296
- borderRadius: '$5',
2297
- padding: '$8 $16 $16 $16',
2298
- variants: {
2299
- type: {
2300
- filled: {
2301
- backgroundColor: '$neutrals300'
2302
- },
2303
- outlined: {
2304
- border: '1px solid $neutrals300'
2305
- }
2306
- }
2307
- },
2308
- defaultVariants: {
2309
- type: 'filled'
2310
- },
2311
- '.head': {
2312
- display: 'flex',
2313
- justifyContent: 'space-between',
2314
- alignItems: 'center',
2315
- minHeight: '32px'
2316
- },
2317
- '.form': {
2318
- display: 'flex',
2319
- width: '100%',
2320
- padding: '$2 0',
2321
- '.selectors': {
2322
- width: '35%',
2323
- '._text': {
2324
- whiteSpace: 'nowrap',
2325
- overflow: 'hidden',
2326
- textOverflow: 'ellipsis'
2327
- }
2328
- },
2329
- '.amount': {
2330
- width: '30%'
2331
- }
2332
- }
2333
- });
2334
- const StyledImage$1 = /*#__PURE__*/styled('img', {
2335
- width: '$24',
2336
- maxHeight: '$24'
2337
- });
2338
- const ImagePlaceholder$1 = /*#__PURE__*/styled('span', {
2339
- width: '24px',
2340
- height: '24px',
2341
- backgroundColor: '$neutrals300',
2342
- borderRadius: '99999px'
2343
- });
2344
- const OutputContainer$1 = /*#__PURE__*/styled('div', {
2345
- windth: '100%',
2346
- height: '$48',
2347
- borderRadius: '$5',
2348
- backgroundColor: '$background',
2349
- border: '1px solid transparent',
2350
- position: 'relative',
2351
- display: 'flex',
2352
- alignItems: 'center',
2353
- paddingLeft: '$8',
2354
- paddingRight: '$8'
2355
- });
2356
- function TokenPreview(props) {
2357
- const {
2358
- chain,
2359
- token,
2360
- loadingStatus
2361
- } = props;
2362
- const {
2363
- t
2364
- } = useTranslation();
2365
- const ItemSuffix = React.createElement("div", {
2366
- style: {
2367
- display: 'flex',
2368
- justifyContent: 'center',
2369
- alignItems: 'center'
2370
- }
2371
- }, loadingStatus === 'failed' && React.createElement(InfoCircleIcon, {
2372
- color: "error",
2373
- size: 24
2374
- }));
2375
- return React.createElement(Box$1, null, React.createElement(Container$3, {
2376
- type: 'outlined'
2377
- }, React.createElement("div", {
2378
- className: "head"
2379
- }, React.createElement(Typography, {
2380
- variant: "body2",
2381
- color: "neutrals800"
2382
- }, props.label), React.createElement(Typography, {
2383
- variant: "caption",
2384
- color: "neutrals600"
2385
- }, `$${numberToString(props.usdValue)}`)), React.createElement("div", {
2386
- className: "form"
2387
- }, React.createElement(Button, {
2388
- className: "selectors",
2389
- variant: "outlined",
2390
- loading: loadingStatus === 'loading',
2391
- prefix: loadingStatus === 'success' && chain ? React.createElement(StyledImage$1, {
2392
- src: chain.logo
2393
- }) : React.createElement(ImagePlaceholder$1, null),
2394
- suffix: ItemSuffix,
2395
- align: "start",
2396
- size: "large"
2397
- }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React.createElement(Spacer, {
2398
- size: 12
2399
- }), React.createElement(Button, {
2400
- className: "selectors",
2401
- variant: "outlined",
2402
- loading: loadingStatus === 'loading',
2403
- prefix: loadingStatus === 'success' && token ? React.createElement(StyledImage$1, {
2404
- src: token.image
2405
- }) : React.createElement(ImagePlaceholder$1, null),
2406
- suffix: ItemSuffix,
2407
- size: "large",
2408
- align: "start"
2409
- }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React.createElement(Spacer, {
2410
- size: 12
2411
- }), React.createElement("div", {
2412
- className: "amount"
2413
- }, React.createElement(OutputContainer$1, null, React.createElement(Typography, {
2414
- variant: "h4"
2415
- }, props.amount))))));
2416
- }
2417
-
2418
- const Container$4 = /*#__PURE__*/styled('div', {
2419
- display: 'flex',
2420
- alignItems: 'center',
2421
- justifyContent: 'space-between',
2422
- padding: '$8',
2423
- borderRadius: '$5',
2424
- backgroundColor: '$neutrals300',
2425
- color: '$neutrals800',
2426
- fontSize: '$12',
2427
- '.routes': {
2428
- display: 'flex',
2429
- alignItems: 'center'
2430
- },
2431
- '.fee': {
2432
- display: 'flex',
2433
- alignItems: 'center'
2434
- }
2435
- });
2436
- function RoutesOverview(props) {
2437
- if (!props.routes) return null;
2438
- const swaps = props.routes.result?.swaps;
2439
- return React.createElement(Container$4, null, React.createElement("div", {
2440
- className: "routes"
2441
- }, swaps?.map((swap, idx) => {
2442
- const isLast = idx + 1 == swaps.length;
2443
- return React.createElement(React.Fragment, null, React.createElement("div", {
2444
- className: "route"
2445
- }, swap.from.symbol), React.createElement(ChevronRightIcon, {
2446
- size: 12
2447
- }), isLast ? React.createElement("div", {
2448
- className: "route"
2449
- }, swap.to.symbol) : null);
2450
- })), props.totalFee ? React.createElement("div", {
2451
- className: "fee"
2452
- }, React.createElement(GasIcon, {
2453
- size: 12
2454
- }), React.createElement(Spacer, {
2455
- size: 4
2456
- }), "$", props.totalFee) : null);
2545
+ const toToken = useBestRouteStore.use.toToken();
2546
+ const setFromToken = useBestRouteStore.use.setFromToken();
2547
+ const setToToken = useBestRouteStore.use.setToToken();
2548
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2549
+ return React.createElement(TokenSelector, {
2550
+ type: type === 'from' ? 'Source' : 'Destination',
2551
+ list: type == 'from' ? supportedSourceTokens : supportedDestinationTokens,
2552
+ selected: type === 'from' ? fromToken : toToken,
2553
+ onChange: token => {
2554
+ if (type === 'from') setFromToken(token);else setToToken(token);
2555
+ navigateBackFrom(navigationRoutes.fromToken);
2556
+ },
2557
+ onBack: navigateBackFrom.bind(null, navigationRoutes.fromToken),
2558
+ loadingStatus: loadingMetaStatus
2559
+ });
2457
2560
  }
2458
2561
 
2459
- function ConfirmWalletsPage() {
2562
+ function SettingsPage(_ref) {
2563
+ let {
2564
+ supportedSwappers
2565
+ } = _ref;
2566
+ const slippage = useSettingsStore.use.slippage();
2567
+ const setSlippage = useSettingsStore.use.setSlippage();
2568
+ const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2569
+ const customSlippage = useSettingsStore.use.customSlippage();
2570
+ const setCustomSlippage = useSettingsStore.use.setCustomSlippage();
2571
+ const theme = useSettingsStore.use.theme();
2572
+ const setTheme = useSettingsStore.use.setTheme();
2573
+ const swappers = useMetaStore.use.meta().swappers;
2460
2574
  const navigate = useNavigate();
2461
2575
  const {
2462
2576
  navigateBackFrom
2463
2577
  } = useNavigateBack();
2464
- const bestRoute = useBestRouteStore.use.bestRoute();
2578
+ const infiniteApprove = useSettingsStore.use.infiniteApprove();
2579
+ const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();
2580
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2581
+ const uniqueSwappersGroups = [];
2582
+ removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2583
+ return swappers.find(s => s.swapperGroup === swapperGroup);
2584
+ }).find(s => {
2585
+ if (s) {
2586
+ for (const type of s.types) {
2587
+ uniqueSwappersGroups.push({
2588
+ title: s.swapperGroup,
2589
+ logo: s.logo,
2590
+ type,
2591
+ selected: !disabledLiquiditySources.includes(s.swapperGroup)
2592
+ });
2593
+ }
2594
+ }
2595
+ });
2596
+ supportedSwappers !== 'all' && uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0);
2597
+ const supportedUniqueSwappersGroups = supportedSwappers !== 'all' ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0) : uniqueSwappersGroups;
2598
+ return React.createElement(Settings, {
2599
+ slippages: SLIPPAGES,
2600
+ selectedSlippage: slippage,
2601
+ onSlippageChange: slippage => setSlippage(slippage),
2602
+ onLiquiditySourcesClick: () => navigate(navigationRoutes.liquiditySources),
2603
+ onBack: navigateBackFrom.bind(null, navigationRoutes.settings),
2604
+ liquiditySources: supportedUniqueSwappersGroups,
2605
+ selectedLiquiditySources: supportedUniqueSwappersGroups.filter(s => s.selected),
2606
+ customSlippage: customSlippage || NaN,
2607
+ onCustomSlippageChange: setCustomSlippage,
2608
+ minSlippage: MIN_SLIPPGAE,
2609
+ maxSlippage: MAX_SLIPPAGE,
2610
+ selectedTheme: theme,
2611
+ onThemeChange: setTheme,
2612
+ infiniteApprove: infiniteApprove,
2613
+ toggleInfiniteApprove: toggleInfiniteApprove,
2614
+ loadingStatus: loadingMetaStatus
2615
+ });
2616
+ }
2617
+
2618
+ const ListContainer = /*#__PURE__*/styled('div', {
2619
+ display: 'grid',
2620
+ gap: '.5rem',
2621
+ gridTemplateColumns: ' repeat(2, minmax(0, 1fr))',
2622
+ alignContent: 'baseline',
2623
+ padding: '0.5rem',
2624
+ overflowY: 'auto'
2625
+ });
2626
+ const LoaderContainer = /*#__PURE__*/styled('div', {
2627
+ display: 'flex',
2628
+ justifyContent: 'center',
2629
+ width: '100%',
2630
+ position: 'absolute',
2631
+ top: '50%'
2632
+ });
2633
+ const AlertContainer = /*#__PURE__*/styled('div', {
2634
+ paddingBottom: '$16'
2635
+ });
2636
+ function WalletsPage(_ref) {
2637
+ let {
2638
+ supportedWallets,
2639
+ multiWallets
2640
+ } = _ref;
2465
2641
  const {
2466
- blockchains,
2467
- tokens
2468
- } = useMetaStore.use.meta();
2469
- const accounts = useWalletsStore.use.accounts();
2470
- const selectedWallets = useWalletsStore.use.selectedWallets();
2471
- const initSelectedWallets = useWalletsStore.use.initSelectedWallets();
2472
- const setSelectedWallet = useWalletsStore.use.setSelectedWallet();
2642
+ navigateBackFrom
2643
+ } = useNavigateBack();
2473
2644
  const {
2645
+ state,
2646
+ disconnect,
2474
2647
  getWalletInfo,
2475
2648
  connect
2476
2649
  } = useWallets();
2477
- const confirmDisabled = !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
2478
- const firstStep = bestRoute?.result?.swaps[0];
2479
- const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
2480
- const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
2481
- const toAmount = decimalNumber(lastStep?.toAmount, 3);
2650
+ const wallets = getlistWallet(state, getWalletInfo, supportedWallets === 'all' ? Object.values(WalletType) : supportedWallets);
2651
+ const walletsRef = useRef();
2652
+ let sortedWallets = detectMobileScreens() ? wallets.filter(wallet => wallet.showOnMobile) : wallets;
2653
+ sortedWallets = sortWalletsBasedOnState(sortedWallets);
2654
+ const [walletErrorMessage, setWalletErrorMessage] = useState('');
2655
+ const toggleConnectWalletsButton = useUiStore.use.toggleConnectWalletsButton();
2656
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2657
+ const {
2658
+ t
2659
+ } = useTranslation();
2660
+ const onSelectWallet = async type => {
2661
+ const wallet = state(type);
2662
+ try {
2663
+ if (walletErrorMessage) setWalletErrorMessage('');
2664
+ if (wallet.connected) {
2665
+ await disconnect(type);
2666
+ } else {
2667
+ if (!multiWallets && !!wallets.find(w => w.state === WalletState.CONNECTED)) {
2668
+ return;
2669
+ }
2670
+ await connect(type);
2671
+ }
2672
+ } catch (e) {
2673
+ setWalletErrorMessage('Error: ' + e?.message);
2674
+ }
2675
+ };
2676
+ const disconnectConnectingWallets = () => {
2677
+ const connectingWallets = walletsRef.current?.filter(wallet => wallet.state === WalletState.CONNECTING) || [];
2678
+ for (const wallet of connectingWallets) {
2679
+ disconnect(wallet.type);
2680
+ }
2681
+ };
2482
2682
  useEffect(() => {
2483
- initSelectedWallets();
2683
+ toggleConnectWalletsButton();
2684
+ return () => {
2685
+ disconnectConnectingWallets();
2686
+ toggleConnectWalletsButton();
2687
+ };
2484
2688
  }, []);
2485
- const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
2486
- const handleConnectChain = wallet => {
2487
- const network = wallet;
2488
- getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
2489
- };
2490
- const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
2491
- return React.createElement(ConfirmWallets, {
2492
- requiredWallets: getRequiredChains(bestRoute),
2493
- selectableWallets: selectableWallets,
2494
- onBack: navigateBackFrom.bind(null, navigationRoutes.confirmWallets),
2495
- onConfirm: () => navigate(navigationRoutes.confirmSwap, {
2496
- replace: true
2497
- }),
2498
- onChange: wallet => setSelectedWallet(wallet),
2499
- confirmDisabled: confirmDisabled,
2500
- handleConnectChain: wallet => handleConnectChain(wallet),
2501
- isExperimentalChain: wallet => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains, wallet) : false,
2502
- previewInputs: React.createElement(React.Fragment, null, React.createElement(TokenPreview, {
2503
- chain: {
2504
- displayName: firstStep?.from.blockchain || '',
2505
- logo: firstStep?.from.blockchainLogo || ''
2506
- },
2507
- token: {
2508
- symbol: firstStep?.from.symbol || '',
2509
- image: firstStep?.from.logo || ''
2510
- },
2511
- usdValue: calcOutputUsdValue(fromAmount, firstStep?.from.usdPrice),
2512
- amount: fromAmount,
2513
- label: t('From'),
2514
- loadingStatus: 'success'
2515
- }), React.createElement(Spacer, {
2516
- size: 12,
2517
- direction: "vertical"
2518
- }), React.createElement(TokenPreview, {
2519
- chain: {
2520
- displayName: lastStep?.to.blockchain || '',
2521
- logo: lastStep?.to.blockchainLogo || ''
2522
- },
2523
- token: {
2524
- symbol: lastStep?.to.symbol || '',
2525
- image: lastStep?.to.logo || ''
2526
- },
2527
- usdValue: calcOutputUsdValue(toAmount, lastStep?.to.usdPrice),
2528
- amount: toAmount,
2529
- label: t('To'),
2530
- loadingStatus: 'success'
2531
- })),
2532
- previewRoutes: React.createElement(RoutesOverview, {
2533
- routes: bestRoute,
2534
- totalFee: numberToString(totalFeeInUsd, 0, 2)
2535
- })
2536
- });
2689
+ useEffect(() => {
2690
+ walletsRef.current = wallets;
2691
+ }, [wallets]);
2692
+ return React.createElement(SecondaryPage, {
2693
+ title: t('Select Wallet') || '',
2694
+ textField: false,
2695
+ onBack: navigateBackFrom.bind(null, navigationRoutes.wallets)
2696
+ }, React.createElement(React.Fragment, null, walletErrorMessage && React.createElement(AlertContainer, null, React.createElement(Alert, {
2697
+ type: "error"
2698
+ }, walletErrorMessage)), loadingMetaStatus === 'loading' && React.createElement(LoaderContainer, {
2699
+ className: "loader"
2700
+ }, React.createElement(Spinner, {
2701
+ size: 24
2702
+ })), loadingMetaStatus === 'failed' && React.createElement(LoadingFailedAlert, null), React.createElement(ListContainer, null, loadingMetaStatus === 'success' && sortedWallets.map((wallet, index) => React.createElement(Wallet, Object.assign({}, wallet, {
2703
+ key: `${index}-${wallet.type}`,
2704
+ onClick: onSelectWallet
2705
+ }))))));
2537
2706
  }
2538
2707
 
2539
2708
  function useCopyToClipboard(resetInterval) {
@@ -2554,15 +2723,87 @@ function useCopyToClipboard(resetInterval) {
2554
2723
  return [isCopied, handleCopy];
2555
2724
  }
2556
2725
 
2726
+ function timeSince(timeMillis) {
2727
+ const seconds = Math.floor((new Date().getTime() - timeMillis) / 1000);
2728
+ let intervalType;
2729
+ let interval = Math.floor(seconds / 31536000);
2730
+ if (interval >= 1) {
2731
+ intervalType = 'year';
2732
+ } else {
2733
+ interval = Math.floor(seconds / 2592000);
2734
+ if (interval >= 1) {
2735
+ intervalType = 'month';
2736
+ } else {
2737
+ interval = Math.floor(seconds / 86400);
2738
+ if (interval >= 1) {
2739
+ intervalType = 'day';
2740
+ } else {
2741
+ interval = Math.floor(seconds / 3600);
2742
+ if (interval >= 1) {
2743
+ intervalType = 'hour';
2744
+ } else {
2745
+ interval = Math.floor(seconds / 60);
2746
+ if (interval >= 1) {
2747
+ intervalType = 'minute';
2748
+ } else {
2749
+ interval = seconds;
2750
+ intervalType = 'second';
2751
+ }
2752
+ }
2753
+ }
2754
+ }
2755
+ }
2756
+ if (interval > 1 || interval === 0) {
2757
+ intervalType += 's';
2758
+ }
2759
+ return interval + ' ' + intervalType;
2760
+ }
2761
+ function getSwapDate(pendingSwap) {
2762
+ return pendingSwap.finishTime ? `Finished ${timeSince(parseInt(pendingSwap.finishTime))} ago @ ${new Date(parseInt(pendingSwap.finishTime)).toLocaleString()}` : `Started ${timeSince(parseInt(pendingSwap.creationTime))} ago @ ${new Date(parseInt(pendingSwap.creationTime)).toLocaleString()}`;
2763
+ }
2764
+
2765
+ const PlaceholderContainer = /*#__PURE__*/styled('div', {
2766
+ height: '450px'
2767
+ });
2768
+ function SwapDetailsPlaceholder(props) {
2769
+ const {
2770
+ requestId,
2771
+ loading,
2772
+ onBack
2773
+ } = props;
2774
+ return React.createElement(SecondaryPage, {
2775
+ title: "Swap Details",
2776
+ textField: false,
2777
+ onBack: onBack
2778
+ }, React.createElement(PlaceholderContainer, null, loading ? React.createElement(LoaderContainer, null, React.createElement(Spinner, {
2779
+ size: 24
2780
+ })) : React.createElement(Alert, {
2781
+ type: "secondary",
2782
+ title: `Swap with request ID = ${requestId} not found.`
2783
+ })));
2784
+ }
2785
+
2557
2786
  function SwapDetailsPage() {
2558
2787
  const selectedSwapRequestId = useUiStore.use.selectedSwapRequestId();
2788
+ const {
2789
+ canSwitchNetworkTo,
2790
+ connect
2791
+ } = useWallets();
2792
+ const retry = useBestRouteStore.use.retry();
2793
+ const navigate = useNavigate();
2559
2794
  const {
2560
2795
  navigateBackFrom
2561
2796
  } = useNavigateBack();
2797
+ const [isCopied, handleCopy] = useCopyToClipboard(2000);
2562
2798
  const {
2563
2799
  manager
2564
2800
  } = useManager();
2565
- const [isCopied, handleCopy] = useCopyToClipboard(2000);
2801
+ const [loading, setLoading] = useState(true);
2802
+ useEffect(() => {
2803
+ setTimeout(() => {
2804
+ setLoading(false);
2805
+ }, 5000);
2806
+ }, []);
2566
2807
  const pendingSwaps = getPendingSwaps(manager);
2567
2808
  const selectedSwap = pendingSwaps.find(_ref => {
2568
2809
  let {
@@ -2570,92 +2811,161 @@ function SwapDetailsPage() {
2570
2811
  } = _ref;
2571
2812
  return swap.requestId === selectedSwapRequestId;
2572
2813
  });
2573
- //TODO: implement swap cancellation (move queueManager logic to queueManager/rango-preset)
2574
2814
  const onCancel = () => {
2575
- const swap = selectedSwap ? manager?.get(selectedSwap.id) : undefined;
2815
+ const swap = manager?.get(selectedSwap?.id);
2576
2816
  if (swap) cancelSwap(swap);
2577
2817
  };
2578
- return React.createElement(SwapHistory, {
2818
+ const swap = selectedSwap?.swap;
2819
+ if (!swap) return React.createElement(SwapDetailsPlaceholder, {
2820
+ requestId: selectedSwapRequestId || '',
2821
+ loading: loading,
2822
+ onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails)
2823
+ });
2824
+ const firstStep = swap.steps[0];
2825
+ const lastStep = swap.steps[swap.steps.length - 1];
2826
+ const fromAmount = numberToString(swap.inputAmount);
2827
+ const toAmount = numberToString(swap.simulationResult.outputAmount);
2828
+ const currentStep = getCurrentStep(swap);
2829
+ const currentStepBlockchain = currentStep ? getCurrentBlockchainOfOrNull(swap, currentStep) : null;
2830
+ const currentStepWallet = currentStep ? getRelatedWalletOrNull(swap, currentStep) : null;
2831
+ const currentStepNetworkStatus = currentStep?.networkStatus;
2832
+ const swapMessages = getSwapMessages(swap, currentStep);
2833
+ const networkWarningState = isNetworkStatusInWarningState(currentStep);
2834
+ const swapDate = getSwapDate(swap);
2835
+ const shouldRetry = shouldRetrySwap(swap);
2836
+ const switchNetwork = !!currentStepBlockchain && !!currentStepWallet?.walletType && currentStepNetworkStatus === PendingSwapNetworkStatus.WaitingForNetworkChange && canSwitchNetworkTo(currentStepWallet?.walletType, currentStepBlockchain) ? connect.bind(null, currentStepWallet.walletType, currentStepBlockchain) : undefined;
2837
+ const lastConvertedTokenInFailedSwap = getLastConvertedTokenInFailedSwap(swap);
2838
+ return React.createElement(SwapHistory, Object.assign({
2579
2839
  onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),
2840
+ previewInputs: React.createElement(React.Fragment, null, React.createElement(TokenPreview, {
2841
+ chain: {
2842
+ displayName: firstStep?.fromBlockchain || '',
2843
+ // @ts-ignore
2844
+ logo: firstStep?.fromBlockchainLogo || ''
2845
+ },
2846
+ token: {
2847
+ symbol: firstStep?.fromSymbol || '',
2848
+ image: firstStep?.fromLogo || ''
2849
+ },
2850
+ amount: fromAmount,
2851
+ label: t('From'),
2852
+ loadingStatus: 'success'
2853
+ }), React.createElement(Spacer, {
2854
+ size: 12,
2855
+ direction: "vertical"
2856
+ }), React.createElement(TokenPreview, {
2857
+ chain: {
2858
+ displayName: lastStep?.toBlockchain || '',
2859
+ // @ts-ignore
2860
+ logo: lastStep?.toBlockchainLogo || ''
2861
+ },
2862
+ token: {
2863
+ symbol: lastStep?.toSymbol || '',
2864
+ image: lastStep?.toLogo || ''
2865
+ },
2866
+ amount: toAmount,
2867
+ label: t('To'),
2868
+ loadingStatus: 'success'
2869
+ })),
2580
2870
  //todo: move PendingSwap type to rango-types
2581
2871
  //@ts-ignore
2582
- pendingSwap: selectedSwap?.swap,
2872
+ pendingSwap: swap,
2583
2873
  onCopy: handleCopy,
2584
2874
  isCopied: isCopied,
2585
- onCancel: onCancel
2586
- });
2875
+ onCancel: onCancel,
2876
+ shortMessage: swapMessages.shortMessage,
2877
+ detailedMessage: swapMessages.detailedMessage,
2878
+ currentStepBlockchain: currentStepBlockchain || '',
2879
+ switchNetwork: switchNetwork,
2880
+ type: networkWarningState ? 'warning' : swap.extraMessageSeverity || undefined,
2881
+ date: swapDate
2882
+ }, shouldRetry && {
2883
+ onRetry: () => {
2884
+ retry(swap);
2885
+ setTimeout(() => {
2886
+ navigate(navigationRoutes.home);
2887
+ }, 0);
2888
+ }
2889
+ }, lastConvertedTokenInFailedSwap && {
2890
+ lastConvertedTokenInFailedSwap: {
2891
+ blockchain: lastConvertedTokenInFailedSwap.blockchain,
2892
+ outputAmount: lastConvertedTokenInFailedSwap.outputAmount || '',
2893
+ symbol: lastConvertedTokenInFailedSwap.symbol
2894
+ }
2895
+ }));
2587
2896
  }
2588
2897
 
2898
+ const getAbsolutePath = path => path.replace('/', '');
2589
2899
  function AppRoutes(props) {
2590
2900
  const {
2591
2901
  configs
2592
2902
  } = props;
2593
2903
  return useRoutes([{
2594
- path: navigationRoutes.home,
2904
+ path: getAbsolutePath(navigationRoutes.home),
2595
2905
  element: React.createElement(Home, {
2596
2906
  title: configs?.title,
2597
2907
  titleSize: configs?.titleSize,
2598
2908
  titleWeight: configs?.titleWeight
2599
2909
  })
2600
2910
  }, {
2601
- path: navigationRoutes.fromChain,
2911
+ path: getAbsolutePath(navigationRoutes.fromChain),
2602
2912
  element: React.createElement(SelectChainPage, {
2603
2913
  type: "from",
2604
2914
  supportedChains: configs?.fromChains || 'all'
2605
2915
  })
2606
2916
  }, {
2607
- path: navigationRoutes.toChain,
2917
+ path: getAbsolutePath(navigationRoutes.toChain),
2608
2918
  element: React.createElement(SelectChainPage, {
2609
2919
  type: "to",
2610
2920
  supportedChains: configs?.toChains || 'all'
2611
2921
  })
2612
2922
  }, {
2613
- path: navigationRoutes.fromToken + '/*',
2923
+ path: getAbsolutePath(navigationRoutes.fromToken),
2614
2924
  element: React.createElement(SelectTokenPage, {
2615
2925
  type: "from",
2616
2926
  supportedTokens: configs?.fromTokens || 'all'
2617
2927
  })
2618
2928
  }, {
2619
- path: navigationRoutes.toToken,
2929
+ path: getAbsolutePath(navigationRoutes.toToken),
2620
2930
  element: React.createElement(SelectTokenPage, {
2621
2931
  type: "to",
2622
2932
  supportedTokens: configs?.toTokens || 'all'
2623
2933
  })
2624
2934
  }, {
2625
- path: navigationRoutes.settings,
2935
+ path: getAbsolutePath(navigationRoutes.settings),
2626
2936
  element: React.createElement(SettingsPage, {
2627
2937
  supportedSwappers: configs?.liquiditySources || 'all'
2628
2938
  })
2629
2939
  }, {
2630
- path: navigationRoutes.liquiditySources,
2940
+ path: getAbsolutePath(navigationRoutes.liquiditySources),
2631
2941
  element: React.createElement(LiquiditySourcePage, {
2632
2942
  supportedSwappers: configs?.liquiditySources || 'all'
2633
2943
  })
2634
2944
  }, {
2635
- path: navigationRoutes.swaps,
2945
+ path: getAbsolutePath(navigationRoutes.swaps),
2636
2946
  element: React.createElement(HistoryPage, null)
2637
2947
  }, {
2638
2948
  path: navigationRoutes.swapDetails,
2639
2949
  element: React.createElement(SwapDetailsPage, null)
2640
2950
  }, {
2641
- path: navigationRoutes.wallets,
2951
+ path: getAbsolutePath(navigationRoutes.wallets),
2642
2952
  element: React.createElement(WalletsPage, {
2643
2953
  supportedWallets: configs?.wallets || 'all',
2644
2954
  multiWallets: typeof configs?.multiWallets === 'undefined' ? true : configs.multiWallets
2645
2955
  })
2646
2956
  }, {
2647
- path: navigationRoutes.confirmSwap,
2957
+ path: getAbsolutePath(navigationRoutes.confirmSwap),
2648
2958
  element: React.createElement(ConfirmSwapPage, null)
2649
- }, {
2650
- path: navigationRoutes.confirmWallets,
2651
- element: React.createElement(ConfirmWalletsPage, null)
2652
2959
  }]);
2653
2960
  }
2654
2961
 
2655
- const Header$1 = /*#__PURE__*/styled('div', {
2962
+ const Header = /*#__PURE__*/styled('div', {
2656
2963
  display: 'flex',
2657
2964
  width: '100%',
2658
- justifyContent: 'end'
2965
+ justifyContent: 'end',
2966
+ '.balance': {
2967
+ display: 'flex'
2968
+ }
2659
2969
  });
2660
2970
  const WalletImage = /*#__PURE__*/styled('img', {
2661
2971
  width: '$24',
@@ -2685,6 +2995,8 @@ function Layout(_ref) {
2685
2995
  const setInputAmount = useBestRouteStore.use.setInputAmount();
2686
2996
  const totalBalance = calculateWalletUsdValue(balances);
2687
2997
  const connectWalletsButtonDisabled = useUiStore.use.connectWalletsButtonDisabled();
2998
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2999
+ const fetchingBalance = useWalletsStore(fetchingBalanceSelector);
2688
3000
  const {
2689
3001
  t
2690
3002
  } = useTranslation();
@@ -2699,22 +3011,32 @@ function Layout(_ref) {
2699
3011
  setFromToken(configs?.fromToken || null);
2700
3012
  setFromChain(configs?.fromChain || null);
2701
3013
  }, [configs?.fromToken, configs?.fromChain]);
2702
- return React.createElement(React.Fragment, null, React.createElement(Header$1, null, React.createElement(Button, {
3014
+ useEffect(() => {
3015
+ setToChain(null);
3016
+ setFromChain(null);
3017
+ setFromToken(null);
3018
+ setToToken(null);
3019
+ }, [configs?.fromChains, configs?.toChains, configs?.fromTokens, configs?.toTokens]);
3020
+ return React.createElement(React.Fragment, null, React.createElement(Header, null, React.createElement(Button, {
2703
3021
  size: "small",
2704
3022
  suffix: React.createElement(AddWalletIcon, {
2705
3023
  size: 20
2706
3024
  }),
2707
3025
  variant: "ghost",
2708
3026
  flexContent: true,
3027
+ loading: loadingMetaStatus === 'loading',
3028
+ disabled: loadingMetaStatus === 'failed',
2709
3029
  onClick: () => {
2710
3030
  if (!connectWalletsButtonDisabled) navigate(navigationRoutes.wallets);
2711
3031
  }
2712
3032
  }, connectedWalletsImages?.length ? connectedWalletsImages.map((walletImage, index) => React.createElement(WalletImage, {
2713
3033
  key: index,
2714
3034
  src: walletImage
2715
- })) : React.createElement(React.Fragment, null), React.createElement(Typography, {
3035
+ })) : React.createElement(React.Fragment, null), React.createElement("div", {
3036
+ className: "balance"
3037
+ }, React.createElement(Typography, {
2716
3038
  variant: "body2"
2717
- }, !accounts?.length ? t('Connect Wallet') : `$${totalBalance || 0}`))), React.createElement(AppRoutes, {
3039
+ }, !accounts?.length ? t('Connect Wallet') : `$${totalBalance || 0}`), fetchingBalance && React.createElement(Spinner, null)))), React.createElement(AppRoutes, {
2718
3040
  configs: configs
2719
3041
  }));
2720
3042
  }
@@ -2722,10 +3044,12 @@ function Layout(_ref) {
2722
3044
  const globalStyles = /*#__PURE__*/globalCss({
2723
3045
  '*': {
2724
3046
  '&::-webkit-scrollbar': {
2725
- width: '$8'
3047
+ width: '$8',
3048
+ height: '$8'
2726
3049
  },
2727
3050
  '&::-webkit-scrollbar-thumb': {
2728
- backgroundColor: '$neutrals400'
3051
+ backgroundColor: '$neutrals400',
3052
+ borderRadius: '$10'
2729
3053
  },
2730
3054
  '&::-webkit-scrollbar-thumb:hover': {
2731
3055
  backgroundColor: '$neutrals500'
@@ -2966,7 +3290,7 @@ function QueueManager(props) {
2966
3290
  };
2967
3291
  // TODO: this code copy & pasted from rango, should be refactored.
2968
3292
  const allBlockchains = blockchains.filter(blockchain => blockchain.enabled).reduce((blockchainsObj, blockchain) => (blockchainsObj[blockchain.name] = blockchain, blockchainsObj), {});
2969
- const evmBasedChains = blockchains.filter(isEvmBlockchain);
3293
+ const evmBasedChains = blockchains.filter(isEvmBlockchain$1);
2970
3294
  const getSupportedChainNames = type => {
2971
3295
  const {
2972
3296
  supportedChains
@@ -2999,7 +3323,9 @@ function QueueManager(props) {
2999
3323
  //@ts-ignore
3000
3324
  queuesDefs: [swapQueueDef],
3001
3325
  context: context,
3002
- onPersistedDataLoaded: _manager => {},
3326
+ onPersistedDataLoaded: manager => {
3327
+ checkWaitingForNetworkChange(manager);
3328
+ },
3003
3329
  isPaused: false
3004
3330
  }, props.children);
3005
3331
  }
@@ -3027,8 +3353,10 @@ const SwapBox = _ref => {
3027
3353
  changeLanguage
3028
3354
  } = useSelectLanguage();
3029
3355
  const clearConnectedWallet = useWalletsStore.use.clearConnectedWallet();
3030
- const evmBasedChainNames = blockchains.filter(isEvmBlockchain).map(chain => chain.name);
3031
- const onUpdateState = (type, event, value, _, supportedChains) => {
3356
+ const [lastConnectedWalletWithNetwork, setLastConnectedWalletWithNetwork] = useState('');
3357
+ const [disconnectedWallet, setDisconnectedWallet] = useState();
3358
+ const evmBasedChainNames = blockchains.filter(isEvmBlockchain$1).map(chain => chain.name);
3359
+ const onUpdateState = (type, event, value, state, supportedChains) => {
3032
3360
  if (event === Events.ACCOUNTS) {
3033
3361
  if (value) {
3034
3362
  const supportedChainNames = walletAndSupportedChainsNames(supportedChains);
@@ -3038,6 +3366,16 @@ const SwapBox = _ref => {
3038
3366
  disconnectWallet(type);
3039
3367
  }
3040
3368
  }
3369
+ if (event === Events.ACCOUNTS && state.connected) {
3370
+ const key = `${type}-${state.network}-${value}`;
3371
+ if (state.connected) {
3372
+ setLastConnectedWalletWithNetwork(key);
3373
+ }
3374
+ }
3375
+ if (event === Events.NETWORK && state.network) {
3376
+ const key = `${type}-${state.network}`;
3377
+ setLastConnectedWalletWithNetwork(key);
3378
+ }
3041
3379
  };
3042
3380
  let providers = allProviders();
3043
3381
  useEffect(() => {
@@ -3069,7 +3407,12 @@ const SwapBox = _ref => {
3069
3407
  }, React.createElement(AppRouter, {
3070
3408
  title: configs.title,
3071
3409
  titleSize: configs.titleSize,
3072
- titleWeight: configs.titleWeight
3410
+ titleWeight: configs.titleWeight,
3411
+ lastConnectedWallet: lastConnectedWalletWithNetwork,
3412
+ disconnectedWallet: disconnectedWallet,
3413
+ clearDisconnectedWallet: () => {
3414
+ setDisconnectedWallet(undefined);
3415
+ }
3073
3416
  }, React.createElement(Layout, {
3074
3417
  configs: configs
3075
3418
  }))))));