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

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 +1039 -709
  52. package/dist/widget-embedded.cjs.development.js.map +1 -1
  53. package/dist/widget-embedded.cjs.production.min.js +1039 -709
  54. package/dist/widget-embedded.cjs.production.min.js.map +1 -1
  55. package/dist/widget-embedded.esm.js +1048 -718
  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 +27 -8
  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 +5 -2
  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
@@ -8,12 +8,13 @@ var ui = require('@rango-dev/ui');
8
8
  var React = require('react');
9
9
  var React__default = _interopDefault(React);
10
10
  var reactRouter = require('react-router');
11
+ var queueManagerRangoPreset = require('@rango-dev/queue-manager-rango-preset');
12
+ var rangoTypes = require('rango-types');
11
13
  var reactRouterDom = require('react-router-dom');
12
14
  var zustand = require('zustand');
13
15
  var BigNumber = require('bignumber.js');
14
16
  var BigNumber__default = _interopDefault(BigNumber);
15
17
  var walletsShared = require('@rango-dev/wallets-shared');
16
- var rangoTypes = require('rango-types');
17
18
  var walletsCore = require('@rango-dev/wallets-core');
18
19
  var middleware = require('zustand/middleware');
19
20
  var rangoSdk = require('rango-sdk');
@@ -21,11 +22,11 @@ var shallow = require('zustand/shallow');
21
22
  var reactI18next = require('react-i18next');
22
23
  var theme = require('@rango-dev/ui/src/theme');
23
24
  var providerAll = require('@rango-dev/provider-all');
24
- var queueManagerReact = require('@rango-dev/queue-manager-react');
25
25
  var i18n = require('i18next');
26
26
  var i18n__default = _interopDefault(i18n);
27
+ var queueManagerReact = require('@rango-dev/queue-manager-react');
28
+ var dayjs = _interopDefault(require('dayjs'));
27
29
  var copy = _interopDefault(require('copy-to-clipboard'));
28
- var queueManagerRangoPreset = require('@rango-dev/queue-manager-rango-preset');
29
30
  var Backend = _interopDefault(require('i18next-http-backend'));
30
31
  var LanguageDetector = _interopDefault(require('i18next-browser-languagedetector'));
31
32
 
@@ -40,7 +41,6 @@ const navigationRoutes = {
40
41
  swaps: '/swaps',
41
42
  wallets: '/wallets',
42
43
  confirmSwap: '/confirm-swap',
43
- confirmWallets: '/confirm-wallets',
44
44
  swapDetails: '/swaps/:requestId'
45
45
  };
46
46
 
@@ -70,6 +70,22 @@ function shadeColor(color, percent) {
70
70
  var BB = B.toString(16).length == 1 ? '0' + B.toString(16) : B.toString(16);
71
71
  return '#' + RR + GG + BB;
72
72
  }
73
+ function debounce(fn, time) {
74
+ let timeoutId;
75
+ return wrapper;
76
+ function wrapper() {
77
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
78
+ args[_key] = arguments[_key];
79
+ }
80
+ if (timeoutId) {
81
+ clearTimeout(timeoutId);
82
+ }
83
+ timeoutId = setTimeout(() => {
84
+ timeoutId = null;
85
+ fn(...args);
86
+ }, time);
87
+ }
88
+ }
73
89
 
74
90
  const secondsToString = s => {
75
91
  const seconds = (s % 60).toString().padStart(2, '0');
@@ -336,7 +352,7 @@ function getSortedTokens(chain, tokens, balances, otherChainTokens) {
336
352
  return sortTokens(getTokensWithBalance(filteredTokens, balances));
337
353
  }
338
354
  function tokensAreEqual(tokenA, tokenB) {
339
- return tokenA?.blockchain === tokenB?.blockchain && tokenA?.name === tokenB?.name && tokenA?.address === tokenB?.address;
355
+ return tokenA?.blockchain === tokenB?.blockchain && tokenA?.symbol === tokenB?.symbol && tokenA?.address === tokenB?.address;
340
356
  }
341
357
  function getDefaultToken(sortedTokens, otherToken) {
342
358
  let selectedToken;
@@ -462,6 +478,7 @@ function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validat
462
478
  finishTime: null,
463
479
  requestId: bestRoute.requestId || '',
464
480
  inputAmount: inputAmount,
481
+ //@ts-ignore
465
482
  wallets,
466
483
  status: 'running',
467
484
  isPaused: false,
@@ -476,6 +493,7 @@ function calculatePendingSwap(inputAmount, bestRoute, wallets, settings, validat
476
493
  settings: settings,
477
494
  simulationResult: simulationResult,
478
495
  validateBalanceOrFee,
496
+ //@ts-ignore
479
497
  steps: bestRoute.result?.swaps?.map((swap, index) => {
480
498
  const swapper = meta.swappers.find(swapper => swapper.id === swap.swapperId);
481
499
  const swapperType = swapper?.types[0];
@@ -561,11 +579,10 @@ function hasHighFee(totalFeeInUsd) {
561
579
  }
562
580
  function getMinRequiredSlippage(route) {
563
581
  const slippages = route.result?.swaps.map(slippage => slippage.recommendedSlippage);
564
- return slippages?.map(s => parseFloat(s?.slippage || '0'))?.filter(s => s > 0)?.sort((a, b) => b - a)?.find(() => true) || null;
582
+ return slippages?.map(s => s?.slippage || '0')?.filter(s => parseFloat(s) > 0)?.sort((a, b) => parseFloat(b) - parseFloat(a))?.find(() => true) || null;
565
583
  }
566
584
  function hasProperSlippage(userSlippage, minRequiredSlippage) {
567
585
  if (!minRequiredSlippage) return true;
568
- //@ts-ignore
569
586
  return parseFloat(userSlippage) >= parseFloat(minRequiredSlippage);
570
587
  }
571
588
  function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, selectedWallets, disabledLiquiditySources, slippage, checkPrerequisites) {
@@ -578,6 +595,7 @@ function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, se
578
595
  addresses: [wallet.address]
579
596
  });
580
597
  });
598
+ const filteredBlockchains = selectedWallets.map(wallet => wallet.chain);
581
599
  const requestBody = {
582
600
  amount: inputAmount.toString(),
583
601
  checkPrerequisites,
@@ -595,8 +613,10 @@ function createBestRouteRequestBody(fromToken, toToken, inputAmount, wallets, se
595
613
  selectedWallets: selectedWalletsMap,
596
614
  swapperGroups: disabledLiquiditySources,
597
615
  swappersGroupsExclude: true,
598
- //@ts-ignore
599
- slippage: slippage.toString()
616
+ slippage: slippage.toString(),
617
+ ...(checkPrerequisites && {
618
+ blockchains: filteredBlockchains
619
+ })
600
620
  };
601
621
  return requestBody;
602
622
  }
@@ -642,6 +662,61 @@ function calcOutputUsdValue(outputAmount, tokenPrice) {
642
662
  const amount = !!outputAmount ? new BigNumber__default(outputAmount) : ZERO;
643
663
  return amount.multipliedBy(tokenPrice || 0);
644
664
  }
665
+ function isNetworkStatusInWarningState(pendingSwapStep) {
666
+ return !!pendingSwapStep && pendingSwapStep.networkStatus !== null && pendingSwapStep.networkStatus !== queueManagerRangoPreset.PendingSwapNetworkStatus.NetworkChanged;
667
+ }
668
+ function getSwapMessages(pendingSwap, currentStep) {
669
+ const textForRemove = 'bellow button or';
670
+ let message = pendingSwap.extraMessage;
671
+ let detailedMessage = pendingSwap.extraMessageDetail;
672
+ if (pendingSwap.networkStatusExtraMessageDetail?.includes(textForRemove)) {
673
+ pendingSwap.networkStatusExtraMessageDetail = pendingSwap.networkStatusExtraMessageDetail.replace(textForRemove, '');
674
+ }
675
+ const networkWarningState = isNetworkStatusInWarningState(currentStep);
676
+ if (networkWarningState) {
677
+ message = pendingSwap.networkStatusExtraMessage || '';
678
+ detailedMessage = pendingSwap.networkStatusExtraMessageDetail || '';
679
+ switch (currentStep?.networkStatus) {
680
+ case queueManagerRangoPreset.PendingSwapNetworkStatus.WaitingForConnectingWallet:
681
+ message = message || 'Waiting for connecting wallet';
682
+ break;
683
+ case queueManagerRangoPreset.PendingSwapNetworkStatus.WaitingForQueue:
684
+ message = message || 'Waiting for other running tasks to be finished';
685
+ break;
686
+ case queueManagerRangoPreset.PendingSwapNetworkStatus.WaitingForNetworkChange:
687
+ message = message || 'Waiting for changing wallet network';
688
+ break;
689
+ }
690
+ }
691
+ detailedMessage = detailedMessage || '';
692
+ message = message || '';
693
+ const isRpc = message?.indexOf('code') !== -1 && message?.indexOf('reason') !== -1;
694
+ return {
695
+ shortMessage: message,
696
+ detailedMessage: {
697
+ content: detailedMessage,
698
+ long: isRpc
699
+ }
700
+ };
701
+ }
702
+ function getLastConvertedTokenInFailedSwap(pendingSwap) {
703
+ let resultToken = null;
704
+ if (pendingSwap.status === 'failed') {
705
+ const lastSuccessStep = pendingSwap.steps.slice().reverse().filter(step => step.status === 'success')[0];
706
+ if (lastSuccessStep) {
707
+ resultToken = {
708
+ blockchain: lastSuccessStep.toBlockchain,
709
+ symbol: lastSuccessStep.toSymbol,
710
+ outputAmount: lastSuccessStep.outputAmount,
711
+ address: lastSuccessStep.toSymbolAddress
712
+ };
713
+ }
714
+ }
715
+ return resultToken;
716
+ }
717
+ function shouldRetrySwap(pendingSwap) {
718
+ return pendingSwap.status === 'failed' && !!pendingSwap.finishTime && new Date().getTime() - parseInt(pendingSwap.finishTime) < 4 * 3600 * 1000;
719
+ }
645
720
 
646
721
  function searchParamsToToken(tokens, searchParams, chain) {
647
722
  if (!chain) return null;
@@ -679,22 +754,13 @@ function getRequiredBalanceOfWallet(selectedWallet, fee) {
679
754
  return relatedFeeStatus.requiredAssets;
680
755
  }
681
756
  function isRouteParametersChanged(prevParams, currentParams) {
682
- 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;
683
- }
684
- function getBestRouteWithCalculatedFees(bestRoute, tokens) {
685
- if (!bestRoute || !bestRoute.result) return null;
686
- const swapsWithFee = (bestRoute?.result?.swaps || []).map(swap => ({
687
- ...swap,
688
- feeInUsd: numberToString(getUsdFeeOfStep(swap, tokens), 0, 2)
689
- }));
690
- return {
691
- ...bestRoute,
692
- result: {
693
- ...bestRoute.result,
694
- swaps: swapsWithFee
695
- }
696
- };
757
+ 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);
697
758
  }
759
+ //todo: refactor bestRoute store and add loadingStatus
760
+ const getBestRouteStatus = (loading, error) => {
761
+ if (loading) return 'loading';
762
+ if (error) return 'failed';else return 'success';
763
+ };
698
764
 
699
765
  const createSelectors = _store => {
700
766
  let store = _store;
@@ -845,7 +911,7 @@ const useWalletsStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.creat
845
911
  }
846
912
  });
847
913
  return {
848
- selectedWallets: state.selectedWallets.concat(selectedWallets)
914
+ selectedWallets: selectedWallets
849
915
  };
850
916
  }),
851
917
  setSelectedWallet: wallet => set(state => ({
@@ -877,6 +943,7 @@ useWalletsStore.subscribe(state => state.balances, balances => {
877
943
  }, {
878
944
  equalityFn: shallow.shallow
879
945
  });
946
+ const fetchingBalanceSelector = state => !!state.balances.find(wallet => wallet.loading);
880
947
 
881
948
  const getUsdValue = (token, amount) => new BigNumber__default(amount || ZERO).multipliedBy(token?.usdPrice || 0);
882
949
  const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.create()( /*#__PURE__*/middleware.subscribeWithSelector(set => ({
@@ -896,6 +963,7 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.cre
896
963
  setBestRoute: bestRoute => set(state => {
897
964
  let outputAmount = null;
898
965
  let outputUsdValue = ZERO;
966
+ if (!state.inputAmount || state.inputAmount === '0') return {};
899
967
  if (!!bestRoute) {
900
968
  outputAmount = !!bestRoute.result?.outputAmount ? new BigNumber__default(bestRoute.result?.outputAmount) : null;
901
969
  outputUsdValue = calcOutputUsdValue(bestRoute.result?.outputAmount, getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice);
@@ -952,6 +1020,7 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.cre
952
1020
  toToken: token
953
1021
  })),
954
1022
  setInputAmount: amount => {
1023
+ console.log(amount, typeof amount);
955
1024
  set(state => ({
956
1025
  inputAmount: amount,
957
1026
  ...(!amount && {
@@ -963,6 +1032,47 @@ const useBestRouteStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.cre
963
1032
  inputUsdValue: getUsdValue(state.fromToken, amount)
964
1033
  })
965
1034
  }));
1035
+ },
1036
+ retry: pendingSwap => {
1037
+ const {
1038
+ tokens,
1039
+ blockchains
1040
+ } = useMetaStore.getState().meta;
1041
+ const balances = useWalletsStore.getState().balances;
1042
+ const failedIndex = pendingSwap.status === 'failed' ? pendingSwap.steps.findIndex(s => s.status === 'failed') : null;
1043
+ if (failedIndex === null || failedIndex < 0) return;
1044
+ const firstStep = pendingSwap.steps[0];
1045
+ const lastStep = pendingSwap.steps[pendingSwap.steps.length - 1];
1046
+ const fromChain = blockchains.find(blockchain => blockchain.name === firstStep.fromBlockchain) || null;
1047
+ const toChain = blockchains.find(blockchain => blockchain.name === lastStep.toBlockchain) || null;
1048
+ const fromToken = tokens.find(token => tokensAreEqual(token, {
1049
+ blockchain: firstStep.fromBlockchain,
1050
+ symbol: firstStep.fromSymbol,
1051
+ address: firstStep.fromSymbolAddress
1052
+ }));
1053
+ const toToken = tokens.find(token => tokensAreEqual(token, {
1054
+ blockchain: lastStep.toBlockchain,
1055
+ symbol: lastStep.toSymbol,
1056
+ address: lastStep.toSymbolAddress
1057
+ }));
1058
+ const sortedSourceTokens = getSortedTokens(fromChain, tokens, balances, []);
1059
+ const sortedDestinationTokens = getSortedTokens(toChain, tokens, balances, []);
1060
+ const inputAmount = pendingSwap.inputAmount;
1061
+ set({
1062
+ fromChain,
1063
+ fromToken,
1064
+ inputAmount,
1065
+ outputAmount: null,
1066
+ inputUsdValue: getUsdValue(fromToken || null, inputAmount),
1067
+ outputUsdValue: new BigNumber__default(0),
1068
+ toChain,
1069
+ toToken,
1070
+ bestRoute: null,
1071
+ loading: false,
1072
+ error: '',
1073
+ sourceTokens: sortedSourceTokens,
1074
+ destinationTokens: sortedDestinationTokens
1075
+ });
966
1076
  }
967
1077
  }))));
968
1078
  const bestRoute = (bestRouteStore, settingsStore) => {
@@ -978,12 +1088,12 @@ const bestRoute = (bestRouteStore, settingsStore) => {
978
1088
  customSlippage,
979
1089
  disabledLiquiditySources
980
1090
  } = settingsStore.getState();
981
- if (!fromToken || !toToken || !inputAmount) return;
1091
+ if (!fromToken || !toToken || !inputAmount || inputAmount === '0') return;
982
1092
  abortController?.abort();
983
1093
  abortController = new AbortController();
984
1094
  const userSlippage = !!customSlippage ? customSlippage : slippage;
985
1095
  const requestBody = createBestRouteRequestBody(fromToken, toToken, inputAmount, [], [], disabledLiquiditySources, userSlippage, false);
986
- bestRouteStore.setState({
1096
+ if (!bestRouteStore.getState().loading) bestRouteStore.setState({
987
1097
  loading: true,
988
1098
  bestRoute: null,
989
1099
  outputAmount: null,
@@ -1008,13 +1118,36 @@ const bestRoute = (bestRouteStore, settingsStore) => {
1008
1118
  });
1009
1119
  });
1010
1120
  };
1121
+ const debouncedFetchBestRoute = debounce(fetchBestRoute, 600);
1122
+ const bestRouteParamsListener = () => {
1123
+ const {
1124
+ fromToken,
1125
+ toToken,
1126
+ inputAmount,
1127
+ inputUsdValue
1128
+ } = useBestRouteStore.getState();
1129
+ if (!inputAmount || inputAmount === '0') return;
1130
+ if (tokensAreEqual(fromToken, toToken)) return bestRouteStore.setState({
1131
+ loading: false,
1132
+ bestRoute: null,
1133
+ outputAmount: new BigNumber__default(inputAmount),
1134
+ outputUsdValue: inputUsdValue
1135
+ });
1136
+ if (!bestRouteStore.getState().loading) bestRouteStore.setState({
1137
+ loading: true,
1138
+ bestRoute: null,
1139
+ outputAmount: null,
1140
+ outputUsdValue: new BigNumber__default(0)
1141
+ });
1142
+ debouncedFetchBestRoute();
1143
+ };
1011
1144
  useBestRouteStore.subscribe(state => ({
1012
1145
  fromChain: state.fromChain,
1013
1146
  fromToken: state.fromToken,
1014
1147
  toChain: state.toChain,
1015
1148
  toToken: state.toToken,
1016
1149
  inputAmount: state.inputAmount
1017
- }), fetchBestRoute.bind(null), {
1150
+ }), bestRouteParamsListener, {
1018
1151
  equalityFn: (prevState, state) => {
1019
1152
  if (isRouteParametersChanged(prevState, state)) return false;else return true;
1020
1153
  }
@@ -1023,7 +1156,7 @@ const bestRoute = (bestRouteStore, settingsStore) => {
1023
1156
  slippage: state.slippage,
1024
1157
  customSlippage: state.customSlippage,
1025
1158
  disabledLiquiditySources: state.disabledLiquiditySources
1026
- }), fetchBestRoute.bind(null), {
1159
+ }), bestRouteParamsListener, {
1027
1160
  equalityFn: (prevState, state) => {
1028
1161
  if (isRouteParametersChanged(prevState, state)) return false;else return true;
1029
1162
  }
@@ -1048,11 +1181,15 @@ var SearchParams;
1048
1181
  const useUiStore = /*#__PURE__*/createSelectors( /*#__PURE__*/zustand.create()(set => ({
1049
1182
  connectWalletsButtonDisabled: false,
1050
1183
  selectedSwapRequestId: null,
1184
+ currentPage: '',
1051
1185
  toggleConnectWalletsButton: () => set(state => ({
1052
1186
  connectWalletsButtonDisabled: !state.connectWalletsButtonDisabled
1053
1187
  })),
1054
1188
  setSelectedSwap: requestId => set({
1055
1189
  selectedSwapRequestId: requestId
1190
+ }),
1191
+ setCurrentPage: path => set({
1192
+ currentPage: path
1056
1193
  })
1057
1194
  })));
1058
1195
 
@@ -1093,7 +1230,7 @@ function UpdateUrl() {
1093
1230
  toChainString = '',
1094
1231
  toTokenString = '',
1095
1232
  fromAmount = '';
1096
- if (loadingStatus !== 'success' && ![navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname)) {
1233
+ if (loadingStatus !== 'success' && location.pathname != navigationRoutes.confirmSwap) {
1097
1234
  fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];
1098
1235
  fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];
1099
1236
  toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];
@@ -1186,67 +1323,6 @@ function UpdateUrl() {
1186
1323
  return null;
1187
1324
  }
1188
1325
 
1189
- const ButtonsContainer = /*#__PURE__*/ui.styled('div', {
1190
- display: 'flex'
1191
- });
1192
- function HeaderButtons(props) {
1193
- const {
1194
- onClickRefresh
1195
- } = props;
1196
- const navigate = reactRouterDom.useNavigate();
1197
- return React__default.createElement(ButtonsContainer, null, React__default.createElement(ui.Tooltip, {
1198
- content: "Refresh"
1199
- }, React__default.createElement(ui.Button, {
1200
- variant: "ghost",
1201
- onClick: onClickRefresh
1202
- }, React__default.createElement(ui.RetryIcon, {
1203
- size: 24
1204
- }))), React__default.createElement(ui.Tooltip, {
1205
- content: "Transactions History"
1206
- }, React__default.createElement(ui.Button, {
1207
- variant: "ghost",
1208
- onClick: () => navigate(navigationRoutes.swaps)
1209
- }, React__default.createElement(ui.HistoryIcon, {
1210
- size: 24
1211
- }))), React__default.createElement(ui.Tooltip, {
1212
- content: "Settings"
1213
- }, React__default.createElement(ui.Button, {
1214
- variant: "ghost",
1215
- onClick: () => navigate(navigationRoutes.settings)
1216
- }, React__default.createElement(ui.SettingsIcon, {
1217
- size: 24
1218
- }))));
1219
- }
1220
-
1221
- const HeaderContainer = /*#__PURE__*/ui.styled('div', {
1222
- display: 'flex',
1223
- justifyContent: 'space-between',
1224
- alignItems: 'center',
1225
- width: '100%',
1226
- padding: '$16 0'
1227
- });
1228
- function Header(props) {
1229
- const {
1230
- onClickRefresh,
1231
- title,
1232
- titleSize,
1233
- titleWeight
1234
- } = props;
1235
- const {
1236
- t
1237
- } = reactI18next.useTranslation();
1238
- const titleStyle = ui.css({
1239
- fontSize: `${titleSize}px !important`,
1240
- fontWeight: `${titleWeight} !important`
1241
- });
1242
- return React__default.createElement(HeaderContainer, null, React__default.createElement(ui.Typography, {
1243
- variant: "h4",
1244
- className: titleStyle()
1245
- }, title ? t(title.toLocaleLowerCase()) : ''), React__default.createElement(HeaderButtons, {
1246
- onClickRefresh: onClickRefresh
1247
- }));
1248
- }
1249
-
1250
1326
  const Box = /*#__PURE__*/ui.styled('div', {
1251
1327
  display: 'flex',
1252
1328
  flexDirection: 'column',
@@ -1534,6 +1610,39 @@ const errorMessages = {
1534
1610
  genericServerError: 'Error connecting server, please reload the app and try again'
1535
1611
  };
1536
1612
 
1613
+ const ButtonsContainer = /*#__PURE__*/ui.styled('div', {
1614
+ display: 'flex'
1615
+ });
1616
+ function HeaderButtons(props) {
1617
+ const {
1618
+ onClickRefresh
1619
+ } = props;
1620
+ const navigate = reactRouterDom.useNavigate();
1621
+ return React__default.createElement(ButtonsContainer, null, React__default.createElement(ui.Tooltip, {
1622
+ content: "Refresh"
1623
+ }, React__default.createElement(ui.Button, {
1624
+ variant: "ghost",
1625
+ onClick: onClickRefresh,
1626
+ disabled: !onClickRefresh
1627
+ }, React__default.createElement(ui.RetryIcon, {
1628
+ size: 24
1629
+ }))), React__default.createElement(ui.Tooltip, {
1630
+ content: "Transactions History"
1631
+ }, React__default.createElement(ui.Button, {
1632
+ variant: "ghost",
1633
+ onClick: () => navigate(navigationRoutes.swaps)
1634
+ }, React__default.createElement(ui.HistoryIcon, {
1635
+ size: 24
1636
+ }))), React__default.createElement(ui.Tooltip, {
1637
+ content: "Settings"
1638
+ }, React__default.createElement(ui.Button, {
1639
+ variant: "ghost",
1640
+ onClick: () => navigate(navigationRoutes.settings)
1641
+ }, React__default.createElement(ui.SettingsIcon, {
1642
+ size: 24
1643
+ }))));
1644
+ }
1645
+
1537
1646
  const Container$2 = /*#__PURE__*/ui.styled('div', {
1538
1647
  display: 'flex',
1539
1648
  flexDirection: 'column'
@@ -1558,9 +1667,7 @@ const Alerts = /*#__PURE__*/ui.styled('div', {
1558
1667
  });
1559
1668
  function Home(props) {
1560
1669
  const {
1561
- title = 'SWAP',
1562
- titleSize = 18,
1563
- titleWeight = 600
1670
+ title = 'SWAP'
1564
1671
  } = props;
1565
1672
  const isRouterInContext = reactRouterDom.useInRouterContext();
1566
1673
  const navigate = reactRouterDom.useNavigate();
@@ -1584,6 +1691,7 @@ function Home(props) {
1584
1691
  const bestRouteError = useBestRouteStore.use.error();
1585
1692
  const loadingMetaStatus = useMetaStore.use.loadingStatus();
1586
1693
  const accounts = useWalletsStore.use.accounts();
1694
+ const setCurrentPage = useUiStore.use.setCurrentPage();
1587
1695
  const swithFromAndTo = () => {
1588
1696
  setFromChain(toChain);
1589
1697
  setFromToken(toToken);
@@ -1607,11 +1715,15 @@ function Home(props) {
1607
1715
  const swapButtonState = getSwapButtonState(loadingMetaStatus, accounts, fetchingBestRoute, bestRoute, hasLimitError(bestRoute), highValueLoss, priceImpactCanNotBeComputed, needsToWarnEthOnPath, inputIsZero);
1608
1716
  const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
1609
1717
  const highFee = hasHighFee(totalFeeInUsd);
1610
- return React__default.createElement(Container$2, null, React__default.createElement(Header, {
1718
+ React.useEffect(() => {
1719
+ setCurrentPage(navigationRoutes.home);
1720
+ return setCurrentPage.bind(null, '');
1721
+ }, []);
1722
+ return React__default.createElement(Container$2, null, React__default.createElement(ui.Header, {
1611
1723
  title: title,
1612
- titleSize: titleSize,
1613
- titleWeight: titleWeight,
1614
- onClickRefresh: fetchBestRoute
1724
+ suffix: React__default.createElement(HeaderButtons, {
1725
+ onClickRefresh: !!bestRoute ? fetchBestRoute : undefined
1726
+ })
1615
1727
  }), React__default.createElement(FromContainer, null, React__default.createElement(TokenInfo, {
1616
1728
  type: "From",
1617
1729
  chain: fromChain,
@@ -1622,7 +1734,7 @@ function Home(props) {
1622
1734
  variant: "ghost",
1623
1735
  onClick: swithFromAndTo
1624
1736
  }, React__default.createElement(ui.VerticalSwapIcon, {
1625
- size: 24
1737
+ size: 32
1626
1738
  }), isRouterInContext && React__default.createElement(SwithFromAndTo, {
1627
1739
  count: count
1628
1740
  })))), React__default.createElement(TokenInfo, {
@@ -1656,7 +1768,7 @@ function Home(props) {
1656
1768
  disabled: swapButtonState.disabled,
1657
1769
  onClick: () => {
1658
1770
  if (swapButtonState.title === 'Connect Wallet') navigate(navigationRoutes.wallets);else {
1659
- navigate(navigationRoutes.confirmWallets, {
1771
+ navigate(navigationRoutes.confirmSwap, {
1660
1772
  replace: true
1661
1773
  });
1662
1774
  }
@@ -1673,12 +1785,12 @@ const Route = _ref => {
1673
1785
  const navigate = reactRouter.useNavigate();
1674
1786
  const ref = React.useRef(true);
1675
1787
  React.useEffect(() => {
1676
- if ([navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname) && ref.current) navigate(navigationRoutes.home + location.search, {
1788
+ if (location.pathname === navigationRoutes.confirmSwap && ref.current) navigate(navigationRoutes.home + location.search, {
1677
1789
  state: 'redirect'
1678
1790
  });
1679
1791
  ref.current = false;
1680
1792
  }, []);
1681
- if ([navigationRoutes.confirmWallets, navigationRoutes.confirmSwap].includes(location.pathname) && ref.current) return React__default.createElement(Home, Object.assign({}, props));
1793
+ if (location.pathname === navigationRoutes.confirmSwap && ref.current) return React__default.createElement(Home, Object.assign({}, props));
1682
1794
  return React__default.createElement(React__default.Fragment, null, " ", children);
1683
1795
  };
1684
1796
  function AppRouter(_ref2) {
@@ -1688,52 +1800,34 @@ function AppRouter(_ref2) {
1688
1800
  } = _ref2;
1689
1801
  const isRouterInContext = reactRouter.useInRouterContext();
1690
1802
  const Router = isRouterInContext ? Route : reactRouter.MemoryRouter;
1691
- return React__default.createElement(React__default.Fragment, null, React__default.createElement(Router, Object.assign({}, props), children), isRouterInContext && React__default.createElement(UpdateUrl, null));
1692
- }
1693
-
1694
- function ChangeSlippageButton() {
1695
- const navigate = reactRouterDom.useNavigate();
1696
- return React__default.createElement(ui.Button, {
1697
- type: "primary",
1698
- variant: "outlined",
1699
- size: "small",
1700
- onClick: () => navigate(navigationRoutes.settings)
1701
- }, "Change Slippage");
1702
- }
1703
-
1704
- function HighSlippageWarning(props) {
1705
- const {
1706
- selectedSlippage
1707
- } = props;
1708
- return React__default.createElement(ui.Alert, {
1709
- type: "warning",
1710
- footer: React__default.createElement(ChangeSlippageButton, null)
1711
- }, "Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.");
1712
- }
1713
-
1714
- function ConfirmSwapExtraMessages(props) {
1715
1803
  const {
1716
- selectedSlippage
1717
- } = props;
1718
- const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
1719
- return React__default.createElement(React__default.Fragment, null, highSlippage && React__default.createElement(HighSlippageWarning, {
1720
- selectedSlippage: selectedSlippage
1721
- }));
1804
+ blockchains
1805
+ } = useMetaStore.use.meta();
1806
+ const evmChains = blockchains.filter(rangoTypes.isEvmBlockchain);
1807
+ queueManagerRangoPreset.useQueueManager({
1808
+ lastConnectedWallet: props.lastConnectedWallet,
1809
+ clearDisconnectedWallet: props.clearDisconnectedWallet,
1810
+ disconnectedWallet: props.disconnectedWallet,
1811
+ evmChains,
1812
+ notifier: () => {}
1813
+ });
1814
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement(Router, Object.assign({}, props), children), isRouterInContext && React__default.createElement(UpdateUrl, null));
1722
1815
  }
1723
1816
 
1724
1817
  function useNavigateBack() {
1725
1818
  const isRouterInContext = reactRouterDom.useInRouterContext();
1726
1819
  const navigate = reactRouterDom.useNavigate();
1727
1820
  const navigateBackFrom = currentRoute => {
1821
+ if (currentRoute === navigationRoutes.swapDetails) return navigate(navigationRoutes.swaps, {
1822
+ replace: true
1823
+ });
1728
1824
  if (!isRouterInContext || window.history.state && window.history.state.idx > 0) navigate(-1);else {
1729
- if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.swaps, navigationRoutes.confirmWallets].includes(currentRoute)) navigate(navigationRoutes.home, {
1825
+ if ([navigationRoutes.fromChain, navigationRoutes.fromToken, navigationRoutes.toChain, navigationRoutes.toToken, navigationRoutes.settings, navigationRoutes.wallets, navigationRoutes.swaps, navigationRoutes.confirmSwap].includes(currentRoute)) navigate(navigationRoutes.home, {
1730
1826
  replace: true
1731
1827
  });else if (currentRoute === navigationRoutes.liquiditySources) navigate(navigationRoutes.settings, {
1732
1828
  replace: true
1733
1829
  });else if (currentRoute === navigationRoutes.swapDetails) navigate(navigationRoutes.swaps, {
1734
1830
  replace: true
1735
- });else if (currentRoute === navigationRoutes.confirmSwap) navigate(navigationRoutes.confirmWallets, {
1736
- replace: true
1737
1831
  });
1738
1832
  }
1739
1833
  };
@@ -1742,122 +1836,192 @@ function useNavigateBack() {
1742
1836
  };
1743
1837
  }
1744
1838
 
1745
- var ConfirmSwapErrorTypes;
1746
- (function (ConfirmSwapErrorTypes) {
1747
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
1748
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
1749
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
1750
- ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
1751
- })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
1752
- var ConfirmSwapWarningTypes;
1753
- (function (ConfirmSwapWarningTypes) {
1754
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
1755
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
1756
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
1757
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
1758
- ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
1759
- })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
1760
-
1761
- function MinRequiredSlippage(_ref) {
1762
- let {
1763
- minRequiredSlippage
1764
- } = _ref;
1765
- return React__default.createElement(ui.Typography, {
1766
- variant: "body2"
1767
- }, "We recommend you to increase slippage to at least \u00A0", minRequiredSlippage, "\u00A0 for this route.", React__default.createElement(ChangeSlippageButton, null));
1768
- }
1769
-
1770
- function ConfirmSwapErrors(errors) {
1771
- return errors.flatMap(error => {
1772
- switch (error.type) {
1773
- case ConfirmSwapErrorTypes.NO_ROUTE:
1774
- return React__default.createElement(ui.Typography, {
1775
- variant: "body2"
1776
- }, "No routes found. Please try again later.");
1777
- case ConfirmSwapErrorTypes.REQUEST_FAILED:
1778
- return React__default.createElement(ui.Typography, {
1779
- variant: "body2"
1780
- }, `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`);
1781
- case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
1782
- return React__default.createElement(ui.Typography, {
1783
- variant: "body2"
1784
- }, "Route updated and price impact is too high, try again later!");
1785
- case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
1786
- return React__default.createElement(MinRequiredSlippage, {
1787
- minRequiredSlippage: error.minRequiredSlippage
1788
- });
1789
- default:
1790
- return [];
1791
- }
1792
- });
1793
- }
1794
-
1795
- const List = /*#__PURE__*/ui.styled('ul', {
1796
- variants: {
1797
- showListStyle: {
1798
- true: {
1799
- paddingLeft: '$24'
1800
- }
1801
- }
1802
- }
1839
+ const Box$1 = /*#__PURE__*/ui.styled('div', {
1840
+ display: 'flex',
1841
+ flexDirection: 'column',
1842
+ width: '100%'
1803
1843
  });
1804
- const ListItem = /*#__PURE__*/ui.styled('li', {
1844
+ const Container$3 = /*#__PURE__*/ui.styled('div', {
1845
+ boxSizing: 'border-box',
1846
+ borderRadius: '$5',
1847
+ padding: '$8 $16 $16 $16',
1805
1848
  variants: {
1806
- showListStyle: {
1807
- true: {
1808
- listStyleType: 'disc',
1809
- listStylePosition: 'outside'
1849
+ type: {
1850
+ filled: {
1851
+ backgroundColor: '$neutrals300'
1852
+ },
1853
+ outlined: {
1854
+ border: '1px solid $neutrals300'
1810
1855
  }
1811
1856
  }
1812
- }
1813
- });
1814
- const Message = /*#__PURE__*/ui.styled(ui.Typography, {
1815
- display: 'block'
1816
- });
1817
- function BalanceWarnings(_ref) {
1818
- let {
1819
- messages
1820
- } = _ref;
1821
- const showListStyle = messages.length > 1;
1822
- return React__default.createElement(List, {
1823
- showListStyle: showListStyle
1824
- }, messages.map(warning => React__default.createElement(ListItem, {
1825
- showListStyle: showListStyle
1826
- }, React__default.createElement(Message, {
1827
- variant: "body2"
1828
- }, warning))));
1857
+ },
1858
+ defaultVariants: {
1859
+ type: 'filled'
1860
+ },
1861
+ '.head': {
1862
+ display: 'flex',
1863
+ justifyContent: 'space-between',
1864
+ alignItems: 'center',
1865
+ minHeight: '32px'
1866
+ },
1867
+ '.form': {
1868
+ display: 'flex',
1869
+ width: '100%',
1870
+ padding: '$2 0',
1871
+ '.selectors': {
1872
+ width: '35%',
1873
+ '._text': {
1874
+ whiteSpace: 'nowrap',
1875
+ overflow: 'hidden',
1876
+ textOverflow: 'ellipsis'
1877
+ }
1878
+ },
1879
+ '.amount': {
1880
+ width: '30%'
1881
+ }
1882
+ }
1883
+ });
1884
+ const StyledImage$1 = /*#__PURE__*/ui.styled('img', {
1885
+ width: '$24',
1886
+ maxHeight: '$24'
1887
+ });
1888
+ const ImagePlaceholder$1 = /*#__PURE__*/ui.styled('span', {
1889
+ width: '24px',
1890
+ height: '24px',
1891
+ backgroundColor: '$neutrals300',
1892
+ borderRadius: '99999px'
1893
+ });
1894
+ const OutputContainer$1 = /*#__PURE__*/ui.styled('div', {
1895
+ windth: '100%',
1896
+ height: '$48',
1897
+ borderRadius: '$5',
1898
+ backgroundColor: '$background',
1899
+ border: '1px solid transparent',
1900
+ position: 'relative',
1901
+ display: 'flex',
1902
+ alignItems: 'center',
1903
+ paddingLeft: '$8',
1904
+ paddingRight: '$8'
1905
+ });
1906
+ function TokenPreview(props) {
1907
+ const {
1908
+ chain,
1909
+ token,
1910
+ loadingStatus
1911
+ } = props;
1912
+ const {
1913
+ t
1914
+ } = reactI18next.useTranslation();
1915
+ const ItemSuffix = React__default.createElement("div", {
1916
+ style: {
1917
+ display: 'flex',
1918
+ justifyContent: 'center',
1919
+ alignItems: 'center'
1920
+ }
1921
+ }, loadingStatus === 'failed' && React__default.createElement(ui.InfoCircleIcon, {
1922
+ color: "error",
1923
+ size: 24
1924
+ }));
1925
+ return React__default.createElement(Box$1, null, React__default.createElement(Container$3, {
1926
+ type: 'outlined'
1927
+ }, React__default.createElement("div", {
1928
+ className: "head"
1929
+ }, React__default.createElement(ui.Typography, {
1930
+ variant: "body2",
1931
+ color: "neutrals800"
1932
+ }, props.label), props.usdValue && React__default.createElement(ui.Typography, {
1933
+ variant: "caption",
1934
+ color: "neutrals600"
1935
+ }, `$${numberToString(props.usdValue)}`)), React__default.createElement("div", {
1936
+ className: "form"
1937
+ }, React__default.createElement(ui.Button, {
1938
+ className: "selectors",
1939
+ variant: "outlined",
1940
+ loading: loadingStatus === 'loading',
1941
+ prefix: loadingStatus === 'success' && chain ? React__default.createElement(StyledImage$1, {
1942
+ src: chain.logo
1943
+ }) : React__default.createElement(ImagePlaceholder$1, null),
1944
+ suffix: ItemSuffix,
1945
+ align: "start",
1946
+ size: "large"
1947
+ }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React__default.createElement(ui.Spacer, {
1948
+ size: 12
1949
+ }), React__default.createElement(ui.Button, {
1950
+ className: "selectors",
1951
+ variant: "outlined",
1952
+ loading: loadingStatus === 'loading',
1953
+ prefix: loadingStatus === 'success' && token ? React__default.createElement(StyledImage$1, {
1954
+ src: token.image
1955
+ }) : React__default.createElement(ImagePlaceholder$1, null),
1956
+ suffix: ItemSuffix,
1957
+ size: "large",
1958
+ align: "start"
1959
+ }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React__default.createElement(ui.Spacer, {
1960
+ size: 12
1961
+ }), React__default.createElement("div", {
1962
+ className: "amount"
1963
+ }, React__default.createElement(OutputContainer$1, null, React__default.createElement(ui.Typography, {
1964
+ variant: "h4"
1965
+ }, props.amount))))));
1829
1966
  }
1830
1967
 
1831
- function ConfirmSwapWarnings(warnings) {
1832
- return warnings.flatMap(warning => {
1833
- switch (warning.type) {
1834
- case ConfirmSwapWarningTypes.ROUTE_UPDATED:
1835
- return React__default.createElement(ui.Typography, {
1836
- variant: "body2"
1837
- }, "Route has been updated.");
1838
- case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
1839
- return React__default.createElement(ui.Typography, {
1840
- variant: "body2"
1841
- }, `Output amount changed to ${warning.newOutputAmount}
1842
- (${warning.percentageChange}% change).`);
1843
- case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
1844
- return React__default.createElement(ui.Typography, {
1845
- variant: "body2"
1846
- }, "Route swappers has been updated.");
1847
- case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
1848
- return React__default.createElement(ui.Typography, {
1849
- variant: "body2"
1850
- }, "Route internal coins has been updated.");
1851
- case ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE:
1852
- return React__default.createElement(BalanceWarnings, {
1853
- messages: warning.messages
1854
- });
1855
- default:
1856
- return [];
1857
- }
1858
- });
1968
+ const Container$4 = /*#__PURE__*/ui.styled('div', {
1969
+ display: 'flex',
1970
+ alignItems: 'center',
1971
+ justifyContent: 'space-between',
1972
+ padding: '$8',
1973
+ borderRadius: '$5',
1974
+ backgroundColor: '$neutrals300',
1975
+ color: '$neutrals800',
1976
+ fontSize: '$12',
1977
+ '.routes': {
1978
+ display: 'flex',
1979
+ alignItems: 'center'
1980
+ },
1981
+ '.fee': {
1982
+ display: 'flex',
1983
+ alignItems: 'center'
1984
+ }
1985
+ });
1986
+ function RoutesOverview(props) {
1987
+ if (!props.routes) return null;
1988
+ const swaps = props.routes.result?.swaps;
1989
+ return React__default.createElement(Container$4, null, React__default.createElement("div", {
1990
+ className: "routes"
1991
+ }, swaps?.map((swap, idx) => {
1992
+ const isLast = idx + 1 == swaps.length;
1993
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
1994
+ className: "route"
1995
+ }, swap.from.symbol), React__default.createElement(ui.ChevronRightIcon, {
1996
+ size: 12
1997
+ }), isLast ? React__default.createElement("div", {
1998
+ className: "route"
1999
+ }, swap.to.symbol) : null);
2000
+ })), props.totalFee ? React__default.createElement("div", {
2001
+ className: "fee"
2002
+ }, React__default.createElement(ui.GasIcon, {
2003
+ size: 12
2004
+ }), React__default.createElement(ui.Spacer, {
2005
+ size: 4
2006
+ }), "$", props.totalFee) : null);
1859
2007
  }
1860
2008
 
2009
+ var ConfirmSwapErrorTypes;
2010
+ (function (ConfirmSwapErrorTypes) {
2011
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["NO_ROUTE"] = 0] = "NO_ROUTE";
2012
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS"] = 1] = "ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS";
2013
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["REQUEST_FAILED"] = 2] = "REQUEST_FAILED";
2014
+ ConfirmSwapErrorTypes[ConfirmSwapErrorTypes["INSUFFICIENT_SLIPPAGE"] = 3] = "INSUFFICIENT_SLIPPAGE";
2015
+ })(ConfirmSwapErrorTypes || (ConfirmSwapErrorTypes = {}));
2016
+ var ConfirmSwapWarningTypes;
2017
+ (function (ConfirmSwapWarningTypes) {
2018
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_UPDATED"] = 0] = "ROUTE_UPDATED";
2019
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_SWAPPERS_UPDATED"] = 1] = "ROUTE_SWAPPERS_UPDATED";
2020
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_COINS_UPDATED"] = 2] = "ROUTE_COINS_UPDATED";
2021
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["ROUTE_AND_OUTPUT_AMOUNT_UPDATED"] = 3] = "ROUTE_AND_OUTPUT_AMOUNT_UPDATED";
2022
+ ConfirmSwapWarningTypes[ConfirmSwapWarningTypes["INSUFFICIENT_BALANCE"] = 4] = "INSUFFICIENT_BALANCE";
2023
+ })(ConfirmSwapWarningTypes || (ConfirmSwapWarningTypes = {}));
2024
+
1861
2025
  function useConfirmSwap() {
1862
2026
  const fromToken = useBestRouteStore.use.fromToken();
1863
2027
  const toToken = useBestRouteStore.use.toToken();
@@ -1898,6 +2062,7 @@ function useConfirmSwap() {
1898
2062
  proceedAnywayRef.current = false;
1899
2063
  if (confiremedRouteRef.current) {
1900
2064
  const newSwap = calculatePendingSwap(inputAmount.toString(), confiremedRouteRef.current, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
2065
+ //@ts-ignore
1901
2066
  return newSwap;
1902
2067
  }
1903
2068
  return;
@@ -1960,6 +2125,7 @@ function useConfirmSwap() {
1960
2125
  disabledSwappersGroups: disabledLiquiditySources
1961
2126
  };
1962
2127
  const newSwap = calculatePendingSwap(inputAmount.toString(), confiremedRoute, getWalletsForNewSwap(selectedWallets), swapSettings, false, meta);
2128
+ //@ts-ignore
1963
2129
  return newSwap;
1964
2130
  } else if (!proceedAnywayRef.current) {
1965
2131
  proceedAnywayRef.current = true;
@@ -1989,62 +2155,262 @@ function useConfirmSwap() {
1989
2155
  };
1990
2156
  }
1991
2157
 
1992
- function ConfirmSwapPage() {
1993
- const setSelectedSwap = useUiStore.use.setSelectedSwap();
1994
- const {
1995
- navigateBackFrom
1996
- } = useNavigateBack();
1997
- const {
1998
- manager
1999
- } = queueManagerReact.useManager();
2158
+ function ChangeSlippageButton() {
2000
2159
  const navigate = reactRouterDom.useNavigate();
2001
- const bestRoute = useBestRouteStore.use.bestRoute();
2002
- const fetchingBestRoute = useBestRouteStore.use.loading();
2003
- const {
2004
- tokens
2005
- } = useMetaStore.use.meta();
2006
- const slippage = useSettingsStore.use.slippage();
2007
- const customSlippage = useSettingsStore.use.customSlippage();
2008
- const selectedSlippage = customSlippage || slippage;
2009
- const {
2010
- loading,
2011
- errors,
2012
- warnings,
2013
- confirmSwap
2014
- } = useConfirmSwap();
2015
- const showHighSlippageWarning = !errors.find(error => error.type === ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE);
2016
- return React__default.createElement(ui.ConfirmSwap, {
2017
- onConfirm: () => {
2018
- confirmSwap?.().then(swap => {
2019
- if (swap) {
2020
- manager?.create('swap', {
2021
- swapDetails: swap
2022
- }, {
2023
- id: swap.requestId
2024
- });
2025
- setSelectedSwap(swap.requestId);
2026
- navigate(navigationRoutes.swaps + `/${swap.requestId}`, {
2027
- replace: true
2028
- });
2029
- }
2030
- });
2031
- },
2032
- onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
2033
- bestRoute: getBestRouteWithCalculatedFees(bestRoute, tokens),
2034
- loading: loading,
2035
- errors: ConfirmSwapErrors(errors),
2036
- warnings: ConfirmSwapWarnings(warnings),
2037
- extraMessages: showHighSlippageWarning && React__default.createElement(ConfirmSwapExtraMessages, {
2038
- selectedSlippage: selectedSlippage
2039
- }),
2040
- confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!',
2041
- confirmButtonDisabled: fetchingBestRoute
2042
- });
2160
+ return React__default.createElement(ui.Button, {
2161
+ type: "primary",
2162
+ variant: "outlined",
2163
+ size: "small",
2164
+ onClick: () => navigate(navigationRoutes.settings)
2165
+ }, "Change Slippage");
2043
2166
  }
2044
2167
 
2045
- const getPendingSwaps = manager => {
2046
- const result = [];
2047
- manager?.getAll().forEach((q, id) => {
2168
+ const StyledMessage = /*#__PURE__*/ui.styled(ui.Typography, {
2169
+ color: '$error500 !important'
2170
+ });
2171
+ function MinRequiredSlippage(_ref) {
2172
+ let {
2173
+ minRequiredSlippage
2174
+ } = _ref;
2175
+ return React__default.createElement(StyledMessage, {
2176
+ variant: "body2"
2177
+ }, "We recommend you to increase slippage to at least \u00A0", minRequiredSlippage, "\u00A0 for this route.", React__default.createElement(ui.Spacer, {
2178
+ size: 8,
2179
+ direction: "vertical"
2180
+ }), React__default.createElement(ChangeSlippageButton, null));
2181
+ }
2182
+
2183
+ function ConfirmSwapErrors(errors) {
2184
+ return errors.flatMap(error => {
2185
+ switch (error.type) {
2186
+ case ConfirmSwapErrorTypes.NO_ROUTE:
2187
+ return React__default.createElement(ui.Typography, {
2188
+ variant: "body2"
2189
+ }, "No routes found. Please try again later.");
2190
+ case ConfirmSwapErrorTypes.REQUEST_FAILED:
2191
+ return React__default.createElement(ui.Typography, {
2192
+ variant: "body2"
2193
+ }, `Failed to confirm swap ${error.status ? `'status': ${error.status})` : ''}, please try again.`);
2194
+ case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:
2195
+ return React__default.createElement(ui.Typography, {
2196
+ variant: "body2"
2197
+ }, "Route updated and price impact is too high, try again later!");
2198
+ case ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE:
2199
+ return React__default.createElement(MinRequiredSlippage, {
2200
+ minRequiredSlippage: error.minRequiredSlippage
2201
+ });
2202
+ default:
2203
+ return [];
2204
+ }
2205
+ });
2206
+ }
2207
+
2208
+ const List = /*#__PURE__*/ui.styled('ul', {
2209
+ variants: {
2210
+ showListStyle: {
2211
+ true: {
2212
+ paddingLeft: '$24'
2213
+ }
2214
+ }
2215
+ }
2216
+ });
2217
+ const ListItem = /*#__PURE__*/ui.styled('li', {
2218
+ variants: {
2219
+ showListStyle: {
2220
+ true: {
2221
+ listStyleType: 'disc',
2222
+ listStylePosition: 'outside'
2223
+ }
2224
+ }
2225
+ }
2226
+ });
2227
+ const Message = /*#__PURE__*/ui.styled(ui.Typography, {
2228
+ display: 'block',
2229
+ color: '$warning500 !important'
2230
+ });
2231
+ function BalanceWarnings(_ref) {
2232
+ let {
2233
+ messages
2234
+ } = _ref;
2235
+ const showListStyle = messages.length > 1;
2236
+ return React__default.createElement(List, {
2237
+ showListStyle: showListStyle
2238
+ }, messages.map(warning => React__default.createElement(ListItem, {
2239
+ showListStyle: showListStyle
2240
+ }, React__default.createElement(Message, {
2241
+ variant: "body2"
2242
+ }, warning))));
2243
+ }
2244
+
2245
+ function ConfirmSwapWarnings(warnings) {
2246
+ return warnings.flatMap(warning => {
2247
+ switch (warning.type) {
2248
+ case ConfirmSwapWarningTypes.ROUTE_UPDATED:
2249
+ return React__default.createElement(ui.Typography, {
2250
+ variant: "body2"
2251
+ }, "Route has been updated.");
2252
+ case ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:
2253
+ return React__default.createElement(ui.Typography, {
2254
+ variant: "body2"
2255
+ }, `Output amount changed to ${warning.newOutputAmount}
2256
+ (${warning.percentageChange}% change).`);
2257
+ case ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED:
2258
+ return React__default.createElement(ui.Typography, {
2259
+ variant: "body2"
2260
+ }, "Route swappers has been updated.");
2261
+ case ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED:
2262
+ return React__default.createElement(ui.Typography, {
2263
+ variant: "body2"
2264
+ }, "Route internal coins has been updated.");
2265
+ case ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE:
2266
+ return React__default.createElement(BalanceWarnings, {
2267
+ messages: warning.messages
2268
+ });
2269
+ default:
2270
+ return [];
2271
+ }
2272
+ });
2273
+ }
2274
+
2275
+ function HighSlippageWarning(props) {
2276
+ const {
2277
+ selectedSlippage
2278
+ } = props;
2279
+ return React__default.createElement(ui.Alert, {
2280
+ type: "warning",
2281
+ footer: React__default.createElement(ChangeSlippageButton, null)
2282
+ }, "Caution, your slippage is high (=", selectedSlippage, "). Your trade may be front run.");
2283
+ }
2284
+
2285
+ function ConfirmSwapExtraMessages(props) {
2286
+ const {
2287
+ selectedSlippage
2288
+ } = props;
2289
+ const highSlippage = selectedSlippage >= HIGH_SLIPPAGE;
2290
+ return React__default.createElement(React__default.Fragment, null, highSlippage && React__default.createElement(HighSlippageWarning, {
2291
+ selectedSlippage: selectedSlippage
2292
+ }));
2293
+ }
2294
+
2295
+ function ConfirmSwapPage() {
2296
+ const navigate = reactRouterDom.useNavigate();
2297
+ const {
2298
+ navigateBackFrom
2299
+ } = useNavigateBack();
2300
+ const bestRoute = useBestRouteStore.use.bestRoute();
2301
+ const fetchingBestRoute = useBestRouteStore.use.loading();
2302
+ const fetchingBestRouteError = useBestRouteStore.use.error();
2303
+ const setSelectedSwap = useUiStore.use.setSelectedSwap();
2304
+ const {
2305
+ blockchains,
2306
+ tokens
2307
+ } = useMetaStore.use.meta();
2308
+ const accounts = useWalletsStore.use.accounts();
2309
+ const selectedWallets = useWalletsStore.use.selectedWallets();
2310
+ const initSelectedWallets = useWalletsStore.use.initSelectedWallets();
2311
+ const setSelectedWallet = useWalletsStore.use.setSelectedWallet();
2312
+ const slippage = useSettingsStore.use.slippage();
2313
+ const customSlippage = useSettingsStore.use.customSlippage();
2314
+ const bestRouteloadingStatus = getBestRouteStatus(fetchingBestRoute, !!fetchingBestRouteError);
2315
+ const {
2316
+ manager
2317
+ } = queueManagerReact.useManager();
2318
+ const {
2319
+ loading,
2320
+ errors,
2321
+ warnings,
2322
+ confirmSwap
2323
+ } = useConfirmSwap();
2324
+ const selectedSlippage = customSlippage || slippage;
2325
+ const showHighSlippageWarning = !errors.find(error => error.type === ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE);
2326
+ const {
2327
+ getWalletInfo,
2328
+ connect
2329
+ } = walletsCore.useWallets();
2330
+ const confirmDisabled = fetchingBestRoute || !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
2331
+ const firstStep = bestRoute?.result?.swaps[0];
2332
+ const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
2333
+ const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
2334
+ const toAmount = decimalNumber(lastStep?.toAmount, 3);
2335
+ React.useEffect(() => {
2336
+ initSelectedWallets();
2337
+ }, []);
2338
+ const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
2339
+ const handleConnectChain = wallet => {
2340
+ const network = wallet;
2341
+ getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
2342
+ };
2343
+ const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
2344
+ return React__default.createElement(ui.ConfirmSwap, {
2345
+ requiredWallets: getRequiredChains(bestRoute),
2346
+ selectableWallets: selectableWallets,
2347
+ onBack: navigateBackFrom.bind(null, navigationRoutes.confirmSwap),
2348
+ onConfirm: () => {
2349
+ confirmSwap?.().then(swap => {
2350
+ if (swap) {
2351
+ manager?.create('swap', {
2352
+ swapDetails: swap
2353
+ }, {
2354
+ id: swap.requestId
2355
+ });
2356
+ setSelectedSwap(swap.requestId);
2357
+ navigate(navigationRoutes.swaps + `/${swap.requestId}`, {
2358
+ replace: true
2359
+ });
2360
+ }
2361
+ });
2362
+ },
2363
+ onChange: wallet => setSelectedWallet(wallet),
2364
+ confirmDisabled: confirmDisabled,
2365
+ handleConnectChain: wallet => handleConnectChain(wallet),
2366
+ isExperimentalChain: wallet => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains, wallet) : false,
2367
+ previewInputs: React__default.createElement(React__default.Fragment, null, React__default.createElement(TokenPreview, {
2368
+ chain: {
2369
+ displayName: firstStep?.from.blockchain || '',
2370
+ logo: firstStep?.from.blockchainLogo || ''
2371
+ },
2372
+ token: {
2373
+ symbol: firstStep?.from.symbol || '',
2374
+ image: firstStep?.from.logo || ''
2375
+ },
2376
+ usdValue: calcOutputUsdValue(fromAmount, firstStep?.from.usdPrice),
2377
+ amount: fromAmount,
2378
+ label: i18n.t('From'),
2379
+ loadingStatus: bestRouteloadingStatus
2380
+ }), React__default.createElement(ui.Spacer, {
2381
+ size: 12,
2382
+ direction: "vertical"
2383
+ }), React__default.createElement(TokenPreview, {
2384
+ chain: {
2385
+ displayName: lastStep?.to.blockchain || '',
2386
+ logo: lastStep?.to.blockchainLogo || ''
2387
+ },
2388
+ token: {
2389
+ symbol: lastStep?.to.symbol || '',
2390
+ image: lastStep?.to.logo || ''
2391
+ },
2392
+ usdValue: calcOutputUsdValue(toAmount, lastStep?.to.usdPrice),
2393
+ amount: toAmount,
2394
+ label: i18n.t('To'),
2395
+ loadingStatus: bestRouteloadingStatus
2396
+ })),
2397
+ previewRoutes: React__default.createElement(RoutesOverview, {
2398
+ routes: bestRoute,
2399
+ totalFee: numberToString(totalFeeInUsd, 0, 2)
2400
+ }),
2401
+ loading: loading,
2402
+ errors: ConfirmSwapErrors(errors),
2403
+ warnings: ConfirmSwapWarnings(warnings),
2404
+ extraMessages: showHighSlippageWarning && React__default.createElement(ConfirmSwapExtraMessages, {
2405
+ selectedSlippage: selectedSlippage
2406
+ }),
2407
+ confirmButtonTitle: warnings.length > 0 || errors.length > 0 ? 'Proceed anyway!' : 'Confirm swap!'
2408
+ });
2409
+ }
2410
+
2411
+ const getPendingSwaps = manager => {
2412
+ const result = [];
2413
+ manager?.getAll().forEach((q, id) => {
2048
2414
  const storage = q.list.getStorage();
2049
2415
  if (storage?.swapDetails) {
2050
2416
  result.push({
@@ -2056,6 +2422,31 @@ const getPendingSwaps = manager => {
2056
2422
  return result.sort((a, b) => Number(b.swap.creationTime) - Number(a.swap.creationTime));
2057
2423
  };
2058
2424
 
2425
+ const groupSwapsByDate = swaps => {
2426
+ const output = new Map([['today', {
2427
+ title: 'Today',
2428
+ swaps: []
2429
+ }], ['week', {
2430
+ title: 'This week',
2431
+ swaps: []
2432
+ }], ['month', {
2433
+ title: 'This month',
2434
+ swaps: []
2435
+ }], ['year', {
2436
+ title: 'This year',
2437
+ swaps: []
2438
+ }], ['history', {
2439
+ title: 'History',
2440
+ swaps: []
2441
+ }]]);
2442
+ const now = dayjs();
2443
+ swaps.forEach(swap => {
2444
+ const swapDate = dayjs(Number(swap.creationTime));
2445
+ 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);
2446
+ });
2447
+ return Array.from(output.values());
2448
+ };
2449
+
2059
2450
  function HistoryPage() {
2060
2451
  const setSelectedSwap = useUiStore.use.setSelectedSwap();
2061
2452
  const navigate = reactRouterDom.useNavigate();
@@ -2071,16 +2462,14 @@ function HistoryPage() {
2071
2462
  } = _ref;
2072
2463
  return swap;
2073
2464
  });
2074
- return React__default.createElement(ui.History
2075
- //todo: move PendingSwap type to rango-types
2076
- //@ts-ignore
2077
- , {
2078
- //todo: move PendingSwap type to rango-types
2079
- //@ts-ignore
2465
+ return React__default.createElement(ui.History, {
2080
2466
  list: pendingSwaps,
2467
+ groupBy: groupSwapsByDate,
2081
2468
  onSwapClick: requestId => {
2082
2469
  setSelectedSwap(requestId);
2083
- navigate(navigationRoutes.swaps + `/${requestId}`);
2470
+ navigate(navigationRoutes.swaps + `/${requestId}`, {
2471
+ replace: true
2472
+ });
2084
2473
  },
2085
2474
  onBack: navigateBackFrom.bind(null, navigationRoutes.swaps)
2086
2475
  });
@@ -2091,6 +2480,7 @@ function LiquiditySourcePage(_ref) {
2091
2480
  supportedSwappers
2092
2481
  } = _ref;
2093
2482
  const swappers = useMetaStore.use.meta().swappers;
2483
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2094
2484
  const toggleLiquiditySource = useSettingsStore.use.toggleLiquiditySource();
2095
2485
  const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2096
2486
  const toggleAllLiquiditySources = useSettingsStore.use.toggleAllLiquiditySources();
@@ -2116,7 +2506,8 @@ function LiquiditySourcePage(_ref) {
2116
2506
  toggleAll: toggleAllLiquiditySources,
2117
2507
  list: supportedSwappers !== 'all' ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0) : uniqueSwappersGroups,
2118
2508
  onChange: liquiditySource => toggleLiquiditySource(liquiditySource.title),
2119
- onBack: navigateBackFrom.bind(null, navigationRoutes.liquiditySources)
2509
+ onBack: navigateBackFrom.bind(null, navigationRoutes.liquiditySources),
2510
+ loadingStatus: loadingMetaStatus
2120
2511
  });
2121
2512
  }
2122
2513
 
@@ -2159,403 +2550,168 @@ function SelectTokenPage(props) {
2159
2550
  const destinationTokens = useBestRouteStore.use.destinationTokens();
2160
2551
  const supportedSourceTokens = supportedTokens === 'all' ? sourceTokens : sourceTokens.filter(token => supportedTokens.some(supportedToken => tokensAreEqual(supportedToken, token)));
2161
2552
  const supportedDestinationTokens = supportedTokens === 'all' ? destinationTokens : destinationTokens.filter(token => supportedTokens.some(supportedToken => tokensAreEqual(supportedToken, token)));
2162
- console.log(supportedSourceTokens);
2163
2553
  const fromToken = useBestRouteStore.use.fromToken();
2164
2554
  const toToken = useBestRouteStore.use.toToken();
2165
2555
  const setFromToken = useBestRouteStore.use.setFromToken();
2166
2556
  const setToToken = useBestRouteStore.use.setToToken();
2557
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2167
2558
  return React__default.createElement(ui.TokenSelector, {
2168
2559
  type: type === 'from' ? 'Source' : 'Destination',
2169
2560
  list: type == 'from' ? supportedSourceTokens : supportedDestinationTokens,
2170
2561
  selected: type === 'from' ? fromToken : toToken,
2171
2562
  onChange: token => {
2172
- if (type === 'from') setFromToken(token);else setToToken(token);
2173
- navigateBackFrom(navigationRoutes.fromToken);
2174
- },
2175
- onBack: navigateBackFrom.bind(null, navigationRoutes.fromToken)
2176
- });
2177
- }
2178
-
2179
- function SettingsPage(_ref) {
2180
- let {
2181
- supportedSwappers
2182
- } = _ref;
2183
- const slippage = useSettingsStore.use.slippage();
2184
- const setSlippage = useSettingsStore.use.setSlippage();
2185
- const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2186
- const customSlippage = useSettingsStore.use.customSlippage();
2187
- const setCustomSlippage = useSettingsStore.use.setCustomSlippage();
2188
- const theme = useSettingsStore.use.theme();
2189
- const setTheme = useSettingsStore.use.setTheme();
2190
- const swappers = useMetaStore.use.meta().swappers;
2191
- const navigate = reactRouterDom.useNavigate();
2192
- const {
2193
- navigateBackFrom
2194
- } = useNavigateBack();
2195
- const infiniteApprove = useSettingsStore.use.infiniteApprove();
2196
- const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();
2197
- const uniqueSwappersGroups = [];
2198
- removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2199
- return swappers.find(s => s.swapperGroup === swapperGroup);
2200
- }).find(s => {
2201
- if (s) {
2202
- for (const type of s.types) {
2203
- uniqueSwappersGroups.push({
2204
- title: s.swapperGroup,
2205
- logo: s.logo,
2206
- type,
2207
- selected: !disabledLiquiditySources.includes(s.swapperGroup)
2208
- });
2209
- }
2210
- }
2211
- });
2212
- supportedSwappers !== 'all' && uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0);
2213
- const supportedUniqueSwappersGroups = supportedSwappers !== 'all' ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0) : uniqueSwappersGroups;
2214
- return React__default.createElement(ui.Settings, {
2215
- slippages: SLIPPAGES,
2216
- selectedSlippage: slippage,
2217
- onSlippageChange: slippage => setSlippage(slippage),
2218
- onLiquiditySourcesClick: () => navigate(navigationRoutes.liquiditySources),
2219
- onBack: navigateBackFrom.bind(null, navigationRoutes.settings),
2220
- liquiditySources: supportedUniqueSwappersGroups,
2221
- selectedLiquiditySources: supportedUniqueSwappersGroups.filter(s => s.selected),
2222
- customSlippage: customSlippage || NaN,
2223
- onCustomSlippageChange: setCustomSlippage,
2224
- minSlippage: MIN_SLIPPGAE,
2225
- maxSlippage: MAX_SLIPPAGE,
2226
- selectedTheme: theme,
2227
- onThemeChange: setTheme,
2228
- infiniteApprove: infiniteApprove,
2229
- toggleInfiniteApprove: toggleInfiniteApprove
2230
- });
2231
- }
2232
-
2233
- const ListContainer = /*#__PURE__*/ui.styled('div', {
2234
- display: 'grid',
2235
- gap: '.5rem',
2236
- gridTemplateColumns: ' repeat(2, minmax(0, 1fr))',
2237
- height: '450px',
2238
- alignContent: 'baseline',
2239
- padding: '0.5rem'
2240
- });
2241
- const AlertContainer = /*#__PURE__*/ui.styled('div', {
2242
- paddingBottom: '$16'
2243
- });
2244
- function WalletsPage(_ref) {
2245
- let {
2246
- supportedWallets,
2247
- multiWallets
2248
- } = _ref;
2249
- const {
2250
- navigateBackFrom
2251
- } = useNavigateBack();
2252
- const {
2253
- state,
2254
- disconnect,
2255
- getWalletInfo,
2256
- connect
2257
- } = walletsCore.useWallets();
2258
- const wallets = getlistWallet(state, getWalletInfo, supportedWallets === 'all' ? Object.values(walletsShared.WalletType) : supportedWallets);
2259
- const walletsRef = React.useRef();
2260
- let sortedWallets = walletsShared.detectMobileScreens() ? wallets.filter(wallet => wallet.showOnMobile) : wallets;
2261
- sortedWallets = sortWalletsBasedOnState(sortedWallets);
2262
- const [walletErrorMessage, setWalletErrorMessage] = React.useState('');
2263
- const toggleConnectWalletsButton = useUiStore.use.toggleConnectWalletsButton();
2264
- const {
2265
- t
2266
- } = reactI18next.useTranslation();
2267
- const onSelectWallet = async type => {
2268
- const wallet = state(type);
2269
- try {
2270
- if (walletErrorMessage) setWalletErrorMessage('');
2271
- if (wallet.connected) {
2272
- await disconnect(type);
2273
- } else {
2274
- if (!multiWallets && !!wallets.find(w => w.state === ui.WalletState.CONNECTED)) {
2275
- return;
2276
- }
2277
- await connect(type);
2278
- }
2279
- } catch (e) {
2280
- setWalletErrorMessage('Error: ' + e?.message);
2281
- }
2282
- };
2283
- const disconnectConnectingWallets = () => {
2284
- const connectingWallets = walletsRef.current?.filter(wallet => wallet.state === ui.WalletState.CONNECTING) || [];
2285
- for (const wallet of connectingWallets) {
2286
- disconnect(wallet.type);
2287
- }
2288
- };
2289
- React.useEffect(() => {
2290
- toggleConnectWalletsButton();
2291
- return () => {
2292
- disconnectConnectingWallets();
2293
- toggleConnectWalletsButton();
2294
- };
2295
- }, []);
2296
- React.useEffect(() => {
2297
- walletsRef.current = wallets;
2298
- }, [wallets]);
2299
- return React__default.createElement(ui.SecondaryPage, {
2300
- title: t('Select Wallet') || '',
2301
- textField: false,
2302
- onBack: navigateBackFrom.bind(null, navigationRoutes.wallets)
2303
- }, React__default.createElement(React__default.Fragment, null, walletErrorMessage && React__default.createElement(AlertContainer, null, React__default.createElement(ui.Alert, {
2304
- type: "error"
2305
- }, walletErrorMessage)), React__default.createElement(ListContainer, null, sortedWallets.map((wallet, index) => React__default.createElement(ui.Wallet, Object.assign({}, wallet, {
2306
- key: `${index}-${wallet.type}`,
2307
- onClick: onSelectWallet
2308
- }))))));
2309
- }
2310
-
2311
- const Box$1 = /*#__PURE__*/ui.styled('div', {
2312
- display: 'flex',
2313
- flexDirection: 'column',
2314
- width: '100%'
2315
- });
2316
- const Container$3 = /*#__PURE__*/ui.styled('div', {
2317
- boxSizing: 'border-box',
2318
- borderRadius: '$5',
2319
- padding: '$8 $16 $16 $16',
2320
- variants: {
2321
- type: {
2322
- filled: {
2323
- backgroundColor: '$neutrals300'
2324
- },
2325
- outlined: {
2326
- border: '1px solid $neutrals300'
2327
- }
2328
- }
2329
- },
2330
- defaultVariants: {
2331
- type: 'filled'
2332
- },
2333
- '.head': {
2334
- display: 'flex',
2335
- justifyContent: 'space-between',
2336
- alignItems: 'center',
2337
- minHeight: '32px'
2338
- },
2339
- '.form': {
2340
- display: 'flex',
2341
- width: '100%',
2342
- padding: '$2 0',
2343
- '.selectors': {
2344
- width: '35%',
2345
- '._text': {
2346
- whiteSpace: 'nowrap',
2347
- overflow: 'hidden',
2348
- textOverflow: 'ellipsis'
2349
- }
2350
- },
2351
- '.amount': {
2352
- width: '30%'
2353
- }
2354
- }
2355
- });
2356
- const StyledImage$1 = /*#__PURE__*/ui.styled('img', {
2357
- width: '$24',
2358
- maxHeight: '$24'
2359
- });
2360
- const ImagePlaceholder$1 = /*#__PURE__*/ui.styled('span', {
2361
- width: '24px',
2362
- height: '24px',
2363
- backgroundColor: '$neutrals300',
2364
- borderRadius: '99999px'
2365
- });
2366
- const OutputContainer$1 = /*#__PURE__*/ui.styled('div', {
2367
- windth: '100%',
2368
- height: '$48',
2369
- borderRadius: '$5',
2370
- backgroundColor: '$background',
2371
- border: '1px solid transparent',
2372
- position: 'relative',
2373
- display: 'flex',
2374
- alignItems: 'center',
2375
- paddingLeft: '$8',
2376
- paddingRight: '$8'
2377
- });
2378
- function TokenPreview(props) {
2379
- const {
2380
- chain,
2381
- token,
2382
- loadingStatus
2383
- } = props;
2384
- const {
2385
- t
2386
- } = reactI18next.useTranslation();
2387
- const ItemSuffix = React__default.createElement("div", {
2388
- style: {
2389
- display: 'flex',
2390
- justifyContent: 'center',
2391
- alignItems: 'center'
2392
- }
2393
- }, loadingStatus === 'failed' && React__default.createElement(ui.InfoCircleIcon, {
2394
- color: "error",
2395
- size: 24
2396
- }));
2397
- return React__default.createElement(Box$1, null, React__default.createElement(Container$3, {
2398
- type: 'outlined'
2399
- }, React__default.createElement("div", {
2400
- className: "head"
2401
- }, React__default.createElement(ui.Typography, {
2402
- variant: "body2",
2403
- color: "neutrals800"
2404
- }, props.label), React__default.createElement(ui.Typography, {
2405
- variant: "caption",
2406
- color: "neutrals600"
2407
- }, `$${numberToString(props.usdValue)}`)), React__default.createElement("div", {
2408
- className: "form"
2409
- }, React__default.createElement(ui.Button, {
2410
- className: "selectors",
2411
- variant: "outlined",
2412
- loading: loadingStatus === 'loading',
2413
- prefix: loadingStatus === 'success' && chain ? React__default.createElement(StyledImage$1, {
2414
- src: chain.logo
2415
- }) : React__default.createElement(ImagePlaceholder$1, null),
2416
- suffix: ItemSuffix,
2417
- align: "start",
2418
- size: "large"
2419
- }, loadingStatus === 'success' && chain ? chain.displayName : t('Chain')), React__default.createElement(ui.Spacer, {
2420
- size: 12
2421
- }), React__default.createElement(ui.Button, {
2422
- className: "selectors",
2423
- variant: "outlined",
2424
- loading: loadingStatus === 'loading',
2425
- prefix: loadingStatus === 'success' && token ? React__default.createElement(StyledImage$1, {
2426
- src: token.image
2427
- }) : React__default.createElement(ImagePlaceholder$1, null),
2428
- suffix: ItemSuffix,
2429
- size: "large",
2430
- align: "start"
2431
- }, loadingStatus === 'success' && token ? token.symbol : t('Token')), React__default.createElement(ui.Spacer, {
2432
- size: 12
2433
- }), React__default.createElement("div", {
2434
- className: "amount"
2435
- }, React__default.createElement(OutputContainer$1, null, React__default.createElement(ui.Typography, {
2436
- variant: "h4"
2437
- }, props.amount))))));
2438
- }
2439
-
2440
- const Container$4 = /*#__PURE__*/ui.styled('div', {
2441
- display: 'flex',
2442
- alignItems: 'center',
2443
- justifyContent: 'space-between',
2444
- padding: '$8',
2445
- borderRadius: '$5',
2446
- backgroundColor: '$neutrals300',
2447
- color: '$neutrals800',
2448
- fontSize: '$12',
2449
- '.routes': {
2450
- display: 'flex',
2451
- alignItems: 'center'
2452
- },
2453
- '.fee': {
2454
- display: 'flex',
2455
- alignItems: 'center'
2456
- }
2457
- });
2458
- function RoutesOverview(props) {
2459
- if (!props.routes) return null;
2460
- const swaps = props.routes.result?.swaps;
2461
- return React__default.createElement(Container$4, null, React__default.createElement("div", {
2462
- className: "routes"
2463
- }, swaps?.map((swap, idx) => {
2464
- const isLast = idx + 1 == swaps.length;
2465
- return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
2466
- className: "route"
2467
- }, swap.from.symbol), React__default.createElement(ui.ChevronRightIcon, {
2468
- size: 12
2469
- }), isLast ? React__default.createElement("div", {
2470
- className: "route"
2471
- }, swap.to.symbol) : null);
2472
- })), props.totalFee ? React__default.createElement("div", {
2473
- className: "fee"
2474
- }, React__default.createElement(ui.GasIcon, {
2475
- size: 12
2476
- }), React__default.createElement(ui.Spacer, {
2477
- size: 4
2478
- }), "$", props.totalFee) : null);
2563
+ if (type === 'from') setFromToken(token);else setToToken(token);
2564
+ navigateBackFrom(navigationRoutes.fromToken);
2565
+ },
2566
+ onBack: navigateBackFrom.bind(null, navigationRoutes.fromToken),
2567
+ loadingStatus: loadingMetaStatus
2568
+ });
2479
2569
  }
2480
2570
 
2481
- function ConfirmWalletsPage() {
2571
+ function SettingsPage(_ref) {
2572
+ let {
2573
+ supportedSwappers
2574
+ } = _ref;
2575
+ const slippage = useSettingsStore.use.slippage();
2576
+ const setSlippage = useSettingsStore.use.setSlippage();
2577
+ const disabledLiquiditySources = useSettingsStore.use.disabledLiquiditySources();
2578
+ const customSlippage = useSettingsStore.use.customSlippage();
2579
+ const setCustomSlippage = useSettingsStore.use.setCustomSlippage();
2580
+ const theme = useSettingsStore.use.theme();
2581
+ const setTheme = useSettingsStore.use.setTheme();
2582
+ const swappers = useMetaStore.use.meta().swappers;
2482
2583
  const navigate = reactRouterDom.useNavigate();
2483
2584
  const {
2484
2585
  navigateBackFrom
2485
2586
  } = useNavigateBack();
2486
- const bestRoute = useBestRouteStore.use.bestRoute();
2587
+ const infiniteApprove = useSettingsStore.use.infiniteApprove();
2588
+ const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();
2589
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2590
+ const uniqueSwappersGroups = [];
2591
+ removeDuplicateFrom(swappers.map(s => s.swapperGroup)).map(swapperGroup => {
2592
+ return swappers.find(s => s.swapperGroup === swapperGroup);
2593
+ }).find(s => {
2594
+ if (s) {
2595
+ for (const type of s.types) {
2596
+ uniqueSwappersGroups.push({
2597
+ title: s.swapperGroup,
2598
+ logo: s.logo,
2599
+ type,
2600
+ selected: !disabledLiquiditySources.includes(s.swapperGroup)
2601
+ });
2602
+ }
2603
+ }
2604
+ });
2605
+ supportedSwappers !== 'all' && uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0);
2606
+ const supportedUniqueSwappersGroups = supportedSwappers !== 'all' ? uniqueSwappersGroups.filter(item => supportedSwappers.filter(s => s.title === item.title && s.type === item.type).length > 0) : uniqueSwappersGroups;
2607
+ return React__default.createElement(ui.Settings, {
2608
+ slippages: SLIPPAGES,
2609
+ selectedSlippage: slippage,
2610
+ onSlippageChange: slippage => setSlippage(slippage),
2611
+ onLiquiditySourcesClick: () => navigate(navigationRoutes.liquiditySources),
2612
+ onBack: navigateBackFrom.bind(null, navigationRoutes.settings),
2613
+ liquiditySources: supportedUniqueSwappersGroups,
2614
+ selectedLiquiditySources: supportedUniqueSwappersGroups.filter(s => s.selected),
2615
+ customSlippage: customSlippage || NaN,
2616
+ onCustomSlippageChange: setCustomSlippage,
2617
+ minSlippage: MIN_SLIPPGAE,
2618
+ maxSlippage: MAX_SLIPPAGE,
2619
+ selectedTheme: theme,
2620
+ onThemeChange: setTheme,
2621
+ infiniteApprove: infiniteApprove,
2622
+ toggleInfiniteApprove: toggleInfiniteApprove,
2623
+ loadingStatus: loadingMetaStatus
2624
+ });
2625
+ }
2626
+
2627
+ const ListContainer = /*#__PURE__*/ui.styled('div', {
2628
+ display: 'grid',
2629
+ gap: '.5rem',
2630
+ gridTemplateColumns: ' repeat(2, minmax(0, 1fr))',
2631
+ alignContent: 'baseline',
2632
+ padding: '0.5rem',
2633
+ overflowY: 'auto'
2634
+ });
2635
+ const LoaderContainer = /*#__PURE__*/ui.styled('div', {
2636
+ display: 'flex',
2637
+ justifyContent: 'center',
2638
+ width: '100%',
2639
+ position: 'absolute',
2640
+ top: '50%'
2641
+ });
2642
+ const AlertContainer = /*#__PURE__*/ui.styled('div', {
2643
+ paddingBottom: '$16'
2644
+ });
2645
+ function WalletsPage(_ref) {
2646
+ let {
2647
+ supportedWallets,
2648
+ multiWallets
2649
+ } = _ref;
2487
2650
  const {
2488
- blockchains,
2489
- tokens
2490
- } = useMetaStore.use.meta();
2491
- const accounts = useWalletsStore.use.accounts();
2492
- const selectedWallets = useWalletsStore.use.selectedWallets();
2493
- const initSelectedWallets = useWalletsStore.use.initSelectedWallets();
2494
- const setSelectedWallet = useWalletsStore.use.setSelectedWallet();
2651
+ navigateBackFrom
2652
+ } = useNavigateBack();
2495
2653
  const {
2654
+ state,
2655
+ disconnect,
2496
2656
  getWalletInfo,
2497
2657
  connect
2498
2658
  } = walletsCore.useWallets();
2499
- const confirmDisabled = !requiredWallets(bestRoute).every(chain => selectedWallets.map(wallet => wallet.chain).includes(chain));
2500
- const firstStep = bestRoute?.result?.swaps[0];
2501
- const lastStep = bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1];
2502
- const fromAmount = decimalNumber(firstStep?.fromAmount, 3);
2503
- const toAmount = decimalNumber(lastStep?.toAmount, 3);
2659
+ const wallets = getlistWallet(state, getWalletInfo, supportedWallets === 'all' ? Object.values(walletsShared.WalletType) : supportedWallets);
2660
+ const walletsRef = React.useRef();
2661
+ let sortedWallets = walletsShared.detectMobileScreens() ? wallets.filter(wallet => wallet.showOnMobile) : wallets;
2662
+ sortedWallets = sortWalletsBasedOnState(sortedWallets);
2663
+ const [walletErrorMessage, setWalletErrorMessage] = React.useState('');
2664
+ const toggleConnectWalletsButton = useUiStore.use.toggleConnectWalletsButton();
2665
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
2666
+ const {
2667
+ t
2668
+ } = reactI18next.useTranslation();
2669
+ const onSelectWallet = async type => {
2670
+ const wallet = state(type);
2671
+ try {
2672
+ if (walletErrorMessage) setWalletErrorMessage('');
2673
+ if (wallet.connected) {
2674
+ await disconnect(type);
2675
+ } else {
2676
+ if (!multiWallets && !!wallets.find(w => w.state === ui.WalletState.CONNECTED)) {
2677
+ return;
2678
+ }
2679
+ await connect(type);
2680
+ }
2681
+ } catch (e) {
2682
+ setWalletErrorMessage('Error: ' + e?.message);
2683
+ }
2684
+ };
2685
+ const disconnectConnectingWallets = () => {
2686
+ const connectingWallets = walletsRef.current?.filter(wallet => wallet.state === ui.WalletState.CONNECTING) || [];
2687
+ for (const wallet of connectingWallets) {
2688
+ disconnect(wallet.type);
2689
+ }
2690
+ };
2504
2691
  React.useEffect(() => {
2505
- initSelectedWallets();
2692
+ toggleConnectWalletsButton();
2693
+ return () => {
2694
+ disconnectConnectingWallets();
2695
+ toggleConnectWalletsButton();
2696
+ };
2506
2697
  }, []);
2507
- const selectableWallets = getSelectableWallets(accounts, selectedWallets, getWalletInfo);
2508
- const handleConnectChain = wallet => {
2509
- const network = wallet;
2510
- getKeplrCompatibleConnectedWallets(selectableWallets).forEach(compatibleWallet => connect?.(compatibleWallet, network));
2511
- };
2512
- const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);
2513
- return React__default.createElement(ui.ConfirmWallets, {
2514
- requiredWallets: getRequiredChains(bestRoute),
2515
- selectableWallets: selectableWallets,
2516
- onBack: navigateBackFrom.bind(null, navigationRoutes.confirmWallets),
2517
- onConfirm: () => navigate(navigationRoutes.confirmSwap, {
2518
- replace: true
2519
- }),
2520
- onChange: wallet => setSelectedWallet(wallet),
2521
- confirmDisabled: confirmDisabled,
2522
- handleConnectChain: wallet => handleConnectChain(wallet),
2523
- isExperimentalChain: wallet => getKeplrCompatibleConnectedWallets(selectableWallets).length > 0 ? isExperimentalChain(blockchains, wallet) : false,
2524
- previewInputs: React__default.createElement(React__default.Fragment, null, React__default.createElement(TokenPreview, {
2525
- chain: {
2526
- displayName: firstStep?.from.blockchain || '',
2527
- logo: firstStep?.from.blockchainLogo || ''
2528
- },
2529
- token: {
2530
- symbol: firstStep?.from.symbol || '',
2531
- image: firstStep?.from.logo || ''
2532
- },
2533
- usdValue: calcOutputUsdValue(fromAmount, firstStep?.from.usdPrice),
2534
- amount: fromAmount,
2535
- label: i18n.t('From'),
2536
- loadingStatus: 'success'
2537
- }), React__default.createElement(ui.Spacer, {
2538
- size: 12,
2539
- direction: "vertical"
2540
- }), React__default.createElement(TokenPreview, {
2541
- chain: {
2542
- displayName: lastStep?.to.blockchain || '',
2543
- logo: lastStep?.to.blockchainLogo || ''
2544
- },
2545
- token: {
2546
- symbol: lastStep?.to.symbol || '',
2547
- image: lastStep?.to.logo || ''
2548
- },
2549
- usdValue: calcOutputUsdValue(toAmount, lastStep?.to.usdPrice),
2550
- amount: toAmount,
2551
- label: i18n.t('To'),
2552
- loadingStatus: 'success'
2553
- })),
2554
- previewRoutes: React__default.createElement(RoutesOverview, {
2555
- routes: bestRoute,
2556
- totalFee: numberToString(totalFeeInUsd, 0, 2)
2557
- })
2558
- });
2698
+ React.useEffect(() => {
2699
+ walletsRef.current = wallets;
2700
+ }, [wallets]);
2701
+ return React__default.createElement(ui.SecondaryPage, {
2702
+ title: t('Select Wallet') || '',
2703
+ textField: false,
2704
+ onBack: navigateBackFrom.bind(null, navigationRoutes.wallets)
2705
+ }, React__default.createElement(React__default.Fragment, null, walletErrorMessage && React__default.createElement(AlertContainer, null, React__default.createElement(ui.Alert, {
2706
+ type: "error"
2707
+ }, walletErrorMessage)), loadingMetaStatus === 'loading' && React__default.createElement(LoaderContainer, {
2708
+ className: "loader"
2709
+ }, React__default.createElement(ui.Spinner, {
2710
+ size: 24
2711
+ })), loadingMetaStatus === 'failed' && React__default.createElement(ui.LoadingFailedAlert, null), React__default.createElement(ListContainer, null, loadingMetaStatus === 'success' && sortedWallets.map((wallet, index) => React__default.createElement(ui.Wallet, Object.assign({}, wallet, {
2712
+ key: `${index}-${wallet.type}`,
2713
+ onClick: onSelectWallet
2714
+ }))))));
2559
2715
  }
2560
2716
 
2561
2717
  function useCopyToClipboard(resetInterval) {
@@ -2576,15 +2732,87 @@ function useCopyToClipboard(resetInterval) {
2576
2732
  return [isCopied, handleCopy];
2577
2733
  }
2578
2734
 
2735
+ function timeSince(timeMillis) {
2736
+ const seconds = Math.floor((new Date().getTime() - timeMillis) / 1000);
2737
+ let intervalType;
2738
+ let interval = Math.floor(seconds / 31536000);
2739
+ if (interval >= 1) {
2740
+ intervalType = 'year';
2741
+ } else {
2742
+ interval = Math.floor(seconds / 2592000);
2743
+ if (interval >= 1) {
2744
+ intervalType = 'month';
2745
+ } else {
2746
+ interval = Math.floor(seconds / 86400);
2747
+ if (interval >= 1) {
2748
+ intervalType = 'day';
2749
+ } else {
2750
+ interval = Math.floor(seconds / 3600);
2751
+ if (interval >= 1) {
2752
+ intervalType = 'hour';
2753
+ } else {
2754
+ interval = Math.floor(seconds / 60);
2755
+ if (interval >= 1) {
2756
+ intervalType = 'minute';
2757
+ } else {
2758
+ interval = seconds;
2759
+ intervalType = 'second';
2760
+ }
2761
+ }
2762
+ }
2763
+ }
2764
+ }
2765
+ if (interval > 1 || interval === 0) {
2766
+ intervalType += 's';
2767
+ }
2768
+ return interval + ' ' + intervalType;
2769
+ }
2770
+ function getSwapDate(pendingSwap) {
2771
+ 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()}`;
2772
+ }
2773
+
2774
+ const PlaceholderContainer = /*#__PURE__*/ui.styled('div', {
2775
+ height: '450px'
2776
+ });
2777
+ function SwapDetailsPlaceholder(props) {
2778
+ const {
2779
+ requestId,
2780
+ loading,
2781
+ onBack
2782
+ } = props;
2783
+ return React__default.createElement(ui.SecondaryPage, {
2784
+ title: "Swap Details",
2785
+ textField: false,
2786
+ onBack: onBack
2787
+ }, React__default.createElement(PlaceholderContainer, null, loading ? React__default.createElement(LoaderContainer, null, React__default.createElement(ui.Spinner, {
2788
+ size: 24
2789
+ })) : React__default.createElement(ui.Alert, {
2790
+ type: "secondary",
2791
+ title: `Swap with request ID = ${requestId} not found.`
2792
+ })));
2793
+ }
2794
+
2579
2795
  function SwapDetailsPage() {
2580
2796
  const selectedSwapRequestId = useUiStore.use.selectedSwapRequestId();
2797
+ const {
2798
+ canSwitchNetworkTo,
2799
+ connect
2800
+ } = walletsCore.useWallets();
2801
+ const retry = useBestRouteStore.use.retry();
2802
+ const navigate = reactRouterDom.useNavigate();
2581
2803
  const {
2582
2804
  navigateBackFrom
2583
2805
  } = useNavigateBack();
2806
+ const [isCopied, handleCopy] = useCopyToClipboard(2000);
2584
2807
  const {
2585
2808
  manager
2586
2809
  } = queueManagerReact.useManager();
2587
- const [isCopied, handleCopy] = useCopyToClipboard(2000);
2810
+ const [loading, setLoading] = React.useState(true);
2811
+ React.useEffect(() => {
2812
+ setTimeout(() => {
2813
+ setLoading(false);
2814
+ }, 5000);
2815
+ }, []);
2588
2816
  const pendingSwaps = getPendingSwaps(manager);
2589
2817
  const selectedSwap = pendingSwaps.find(_ref => {
2590
2818
  let {
@@ -2592,92 +2820,161 @@ function SwapDetailsPage() {
2592
2820
  } = _ref;
2593
2821
  return swap.requestId === selectedSwapRequestId;
2594
2822
  });
2595
- //TODO: implement swap cancellation (move queueManager logic to queueManager/rango-preset)
2596
2823
  const onCancel = () => {
2597
- const swap = selectedSwap ? manager?.get(selectedSwap.id) : undefined;
2824
+ const swap = manager?.get(selectedSwap?.id);
2598
2825
  if (swap) queueManagerRangoPreset.cancelSwap(swap);
2599
2826
  };
2600
- return React__default.createElement(ui.SwapHistory, {
2827
+ const swap = selectedSwap?.swap;
2828
+ if (!swap) return React__default.createElement(SwapDetailsPlaceholder, {
2829
+ requestId: selectedSwapRequestId || '',
2830
+ loading: loading,
2831
+ onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails)
2832
+ });
2833
+ const firstStep = swap.steps[0];
2834
+ const lastStep = swap.steps[swap.steps.length - 1];
2835
+ const fromAmount = numberToString(swap.inputAmount);
2836
+ const toAmount = numberToString(swap.simulationResult.outputAmount);
2837
+ const currentStep = queueManagerRangoPreset.getCurrentStep(swap);
2838
+ const currentStepBlockchain = currentStep ? queueManagerRangoPreset.getCurrentBlockchainOfOrNull(swap, currentStep) : null;
2839
+ const currentStepWallet = currentStep ? queueManagerRangoPreset.getRelatedWalletOrNull(swap, currentStep) : null;
2840
+ const currentStepNetworkStatus = currentStep?.networkStatus;
2841
+ const swapMessages = getSwapMessages(swap, currentStep);
2842
+ const networkWarningState = isNetworkStatusInWarningState(currentStep);
2843
+ const swapDate = getSwapDate(swap);
2844
+ const shouldRetry = shouldRetrySwap(swap);
2845
+ const switchNetwork = !!currentStepBlockchain && !!currentStepWallet?.walletType && currentStepNetworkStatus === queueManagerRangoPreset.PendingSwapNetworkStatus.WaitingForNetworkChange && canSwitchNetworkTo(currentStepWallet?.walletType, currentStepBlockchain) ? connect.bind(null, currentStepWallet.walletType, currentStepBlockchain) : undefined;
2846
+ const lastConvertedTokenInFailedSwap = getLastConvertedTokenInFailedSwap(swap);
2847
+ return React__default.createElement(ui.SwapHistory, Object.assign({
2601
2848
  onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),
2849
+ previewInputs: React__default.createElement(React__default.Fragment, null, React__default.createElement(TokenPreview, {
2850
+ chain: {
2851
+ displayName: firstStep?.fromBlockchain || '',
2852
+ // @ts-ignore
2853
+ logo: firstStep?.fromBlockchainLogo || ''
2854
+ },
2855
+ token: {
2856
+ symbol: firstStep?.fromSymbol || '',
2857
+ image: firstStep?.fromLogo || ''
2858
+ },
2859
+ amount: fromAmount,
2860
+ label: i18n.t('From'),
2861
+ loadingStatus: 'success'
2862
+ }), React__default.createElement(ui.Spacer, {
2863
+ size: 12,
2864
+ direction: "vertical"
2865
+ }), React__default.createElement(TokenPreview, {
2866
+ chain: {
2867
+ displayName: lastStep?.toBlockchain || '',
2868
+ // @ts-ignore
2869
+ logo: lastStep?.toBlockchainLogo || ''
2870
+ },
2871
+ token: {
2872
+ symbol: lastStep?.toSymbol || '',
2873
+ image: lastStep?.toLogo || ''
2874
+ },
2875
+ amount: toAmount,
2876
+ label: i18n.t('To'),
2877
+ loadingStatus: 'success'
2878
+ })),
2602
2879
  //todo: move PendingSwap type to rango-types
2603
2880
  //@ts-ignore
2604
- pendingSwap: selectedSwap?.swap,
2881
+ pendingSwap: swap,
2605
2882
  onCopy: handleCopy,
2606
2883
  isCopied: isCopied,
2607
- onCancel: onCancel
2608
- });
2884
+ onCancel: onCancel,
2885
+ shortMessage: swapMessages.shortMessage,
2886
+ detailedMessage: swapMessages.detailedMessage,
2887
+ currentStepBlockchain: currentStepBlockchain || '',
2888
+ switchNetwork: switchNetwork,
2889
+ type: networkWarningState ? 'warning' : swap.extraMessageSeverity || undefined,
2890
+ date: swapDate
2891
+ }, shouldRetry && {
2892
+ onRetry: () => {
2893
+ retry(swap);
2894
+ setTimeout(() => {
2895
+ navigate(navigationRoutes.home);
2896
+ }, 0);
2897
+ }
2898
+ }, lastConvertedTokenInFailedSwap && {
2899
+ lastConvertedTokenInFailedSwap: {
2900
+ blockchain: lastConvertedTokenInFailedSwap.blockchain,
2901
+ outputAmount: lastConvertedTokenInFailedSwap.outputAmount || '',
2902
+ symbol: lastConvertedTokenInFailedSwap.symbol
2903
+ }
2904
+ }));
2609
2905
  }
2610
2906
 
2907
+ const getAbsolutePath = path => path.replace('/', '');
2611
2908
  function AppRoutes(props) {
2612
2909
  const {
2613
2910
  configs
2614
2911
  } = props;
2615
2912
  return reactRouterDom.useRoutes([{
2616
- path: navigationRoutes.home,
2913
+ path: getAbsolutePath(navigationRoutes.home),
2617
2914
  element: React__default.createElement(Home, {
2618
2915
  title: configs?.title,
2619
2916
  titleSize: configs?.titleSize,
2620
2917
  titleWeight: configs?.titleWeight
2621
2918
  })
2622
2919
  }, {
2623
- path: navigationRoutes.fromChain,
2920
+ path: getAbsolutePath(navigationRoutes.fromChain),
2624
2921
  element: React__default.createElement(SelectChainPage, {
2625
2922
  type: "from",
2626
2923
  supportedChains: configs?.fromChains || 'all'
2627
2924
  })
2628
2925
  }, {
2629
- path: navigationRoutes.toChain,
2926
+ path: getAbsolutePath(navigationRoutes.toChain),
2630
2927
  element: React__default.createElement(SelectChainPage, {
2631
2928
  type: "to",
2632
2929
  supportedChains: configs?.toChains || 'all'
2633
2930
  })
2634
2931
  }, {
2635
- path: navigationRoutes.fromToken + '/*',
2932
+ path: getAbsolutePath(navigationRoutes.fromToken),
2636
2933
  element: React__default.createElement(SelectTokenPage, {
2637
2934
  type: "from",
2638
2935
  supportedTokens: configs?.fromTokens || 'all'
2639
2936
  })
2640
2937
  }, {
2641
- path: navigationRoutes.toToken,
2938
+ path: getAbsolutePath(navigationRoutes.toToken),
2642
2939
  element: React__default.createElement(SelectTokenPage, {
2643
2940
  type: "to",
2644
2941
  supportedTokens: configs?.toTokens || 'all'
2645
2942
  })
2646
2943
  }, {
2647
- path: navigationRoutes.settings,
2944
+ path: getAbsolutePath(navigationRoutes.settings),
2648
2945
  element: React__default.createElement(SettingsPage, {
2649
2946
  supportedSwappers: configs?.liquiditySources || 'all'
2650
2947
  })
2651
2948
  }, {
2652
- path: navigationRoutes.liquiditySources,
2949
+ path: getAbsolutePath(navigationRoutes.liquiditySources),
2653
2950
  element: React__default.createElement(LiquiditySourcePage, {
2654
2951
  supportedSwappers: configs?.liquiditySources || 'all'
2655
2952
  })
2656
2953
  }, {
2657
- path: navigationRoutes.swaps,
2954
+ path: getAbsolutePath(navigationRoutes.swaps),
2658
2955
  element: React__default.createElement(HistoryPage, null)
2659
2956
  }, {
2660
2957
  path: navigationRoutes.swapDetails,
2661
2958
  element: React__default.createElement(SwapDetailsPage, null)
2662
2959
  }, {
2663
- path: navigationRoutes.wallets,
2960
+ path: getAbsolutePath(navigationRoutes.wallets),
2664
2961
  element: React__default.createElement(WalletsPage, {
2665
2962
  supportedWallets: configs?.wallets || 'all',
2666
2963
  multiWallets: typeof configs?.multiWallets === 'undefined' ? true : configs.multiWallets
2667
2964
  })
2668
2965
  }, {
2669
- path: navigationRoutes.confirmSwap,
2966
+ path: getAbsolutePath(navigationRoutes.confirmSwap),
2670
2967
  element: React__default.createElement(ConfirmSwapPage, null)
2671
- }, {
2672
- path: navigationRoutes.confirmWallets,
2673
- element: React__default.createElement(ConfirmWalletsPage, null)
2674
2968
  }]);
2675
2969
  }
2676
2970
 
2677
- const Header$1 = /*#__PURE__*/ui.styled('div', {
2971
+ const Header = /*#__PURE__*/ui.styled('div', {
2678
2972
  display: 'flex',
2679
2973
  width: '100%',
2680
- justifyContent: 'end'
2974
+ justifyContent: 'end',
2975
+ '.balance': {
2976
+ display: 'flex'
2977
+ }
2681
2978
  });
2682
2979
  const WalletImage = /*#__PURE__*/ui.styled('img', {
2683
2980
  width: '$24',
@@ -2707,6 +3004,8 @@ function Layout(_ref) {
2707
3004
  const setInputAmount = useBestRouteStore.use.setInputAmount();
2708
3005
  const totalBalance = calculateWalletUsdValue(balances);
2709
3006
  const connectWalletsButtonDisabled = useUiStore.use.connectWalletsButtonDisabled();
3007
+ const loadingMetaStatus = useMetaStore.use.loadingStatus();
3008
+ const fetchingBalance = useWalletsStore(fetchingBalanceSelector);
2710
3009
  const {
2711
3010
  t
2712
3011
  } = reactI18next.useTranslation();
@@ -2721,22 +3020,32 @@ function Layout(_ref) {
2721
3020
  setFromToken(configs?.fromToken || null);
2722
3021
  setFromChain(configs?.fromChain || null);
2723
3022
  }, [configs?.fromToken, configs?.fromChain]);
2724
- return React__default.createElement(React__default.Fragment, null, React__default.createElement(Header$1, null, React__default.createElement(ui.Button, {
3023
+ React.useEffect(() => {
3024
+ setToChain(null);
3025
+ setFromChain(null);
3026
+ setFromToken(null);
3027
+ setToToken(null);
3028
+ }, [configs?.fromChains, configs?.toChains, configs?.fromTokens, configs?.toTokens]);
3029
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement(Header, null, React__default.createElement(ui.Button, {
2725
3030
  size: "small",
2726
3031
  suffix: React__default.createElement(ui.AddWalletIcon, {
2727
3032
  size: 20
2728
3033
  }),
2729
3034
  variant: "ghost",
2730
3035
  flexContent: true,
3036
+ loading: loadingMetaStatus === 'loading',
3037
+ disabled: loadingMetaStatus === 'failed',
2731
3038
  onClick: () => {
2732
3039
  if (!connectWalletsButtonDisabled) navigate(navigationRoutes.wallets);
2733
3040
  }
2734
3041
  }, connectedWalletsImages?.length ? connectedWalletsImages.map((walletImage, index) => React__default.createElement(WalletImage, {
2735
3042
  key: index,
2736
3043
  src: walletImage
2737
- })) : React__default.createElement(React__default.Fragment, null), React__default.createElement(ui.Typography, {
3044
+ })) : React__default.createElement(React__default.Fragment, null), React__default.createElement("div", {
3045
+ className: "balance"
3046
+ }, React__default.createElement(ui.Typography, {
2738
3047
  variant: "body2"
2739
- }, !accounts?.length ? t('Connect Wallet') : `$${totalBalance || 0}`))), React__default.createElement(AppRoutes, {
3048
+ }, !accounts?.length ? t('Connect Wallet') : `$${totalBalance || 0}`), fetchingBalance && React__default.createElement(ui.Spinner, null)))), React__default.createElement(AppRoutes, {
2740
3049
  configs: configs
2741
3050
  }));
2742
3051
  }
@@ -2744,10 +3053,12 @@ function Layout(_ref) {
2744
3053
  const globalStyles = /*#__PURE__*/ui.globalCss({
2745
3054
  '*': {
2746
3055
  '&::-webkit-scrollbar': {
2747
- width: '$8'
3056
+ width: '$8',
3057
+ height: '$8'
2748
3058
  },
2749
3059
  '&::-webkit-scrollbar-thumb': {
2750
- backgroundColor: '$neutrals400'
3060
+ backgroundColor: '$neutrals400',
3061
+ borderRadius: '$10'
2751
3062
  },
2752
3063
  '&::-webkit-scrollbar-thumb:hover': {
2753
3064
  backgroundColor: '$neutrals500'
@@ -3021,7 +3332,9 @@ function QueueManager(props) {
3021
3332
  //@ts-ignore
3022
3333
  queuesDefs: [queueManagerRangoPreset.swapQueueDef],
3023
3334
  context: context,
3024
- onPersistedDataLoaded: _manager => {},
3335
+ onPersistedDataLoaded: manager => {
3336
+ queueManagerRangoPreset.checkWaitingForNetworkChange(manager);
3337
+ },
3025
3338
  isPaused: false
3026
3339
  }, props.children);
3027
3340
  }
@@ -3049,8 +3362,10 @@ const SwapBox = _ref => {
3049
3362
  changeLanguage
3050
3363
  } = useSelectLanguage();
3051
3364
  const clearConnectedWallet = useWalletsStore.use.clearConnectedWallet();
3365
+ const [lastConnectedWalletWithNetwork, setLastConnectedWalletWithNetwork] = React.useState('');
3366
+ const [disconnectedWallet, setDisconnectedWallet] = React.useState();
3052
3367
  const evmBasedChainNames = blockchains.filter(rangoSdk.isEvmBlockchain).map(chain => chain.name);
3053
- const onUpdateState = (type, event, value, _, supportedChains) => {
3368
+ const onUpdateState = (type, event, value, state, supportedChains) => {
3054
3369
  if (event === walletsCore.Events.ACCOUNTS) {
3055
3370
  if (value) {
3056
3371
  const supportedChainNames = walletAndSupportedChainsNames(supportedChains);
@@ -3060,6 +3375,16 @@ const SwapBox = _ref => {
3060
3375
  disconnectWallet(type);
3061
3376
  }
3062
3377
  }
3378
+ if (event === walletsCore.Events.ACCOUNTS && state.connected) {
3379
+ const key = `${type}-${state.network}-${value}`;
3380
+ if (state.connected) {
3381
+ setLastConnectedWalletWithNetwork(key);
3382
+ }
3383
+ }
3384
+ if (event === walletsCore.Events.NETWORK && state.network) {
3385
+ const key = `${type}-${state.network}`;
3386
+ setLastConnectedWalletWithNetwork(key);
3387
+ }
3063
3388
  };
3064
3389
  let providers = providerAll.allProviders();
3065
3390
  React.useEffect(() => {
@@ -3091,7 +3416,12 @@ const SwapBox = _ref => {
3091
3416
  }, React__default.createElement(AppRouter, {
3092
3417
  title: configs.title,
3093
3418
  titleSize: configs.titleSize,
3094
- titleWeight: configs.titleWeight
3419
+ titleWeight: configs.titleWeight,
3420
+ lastConnectedWallet: lastConnectedWalletWithNetwork,
3421
+ disconnectedWallet: disconnectedWallet,
3422
+ clearDisconnectedWallet: () => {
3423
+ setDisconnectedWallet(undefined);
3424
+ }
3095
3425
  }, React__default.createElement(Layout, {
3096
3426
  configs: configs
3097
3427
  }))))));