@lifi/widget 3.0.2 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/_esm/components/Card/CardIconButton.js +1 -0
  3. package/_esm/components/Card/CardIconButton.js.map +1 -1
  4. package/_esm/components/Card/CardLabel.d.ts +1 -1
  5. package/_esm/components/Card/CardLabel.js +8 -12
  6. package/_esm/components/Card/CardLabel.js.map +1 -1
  7. package/_esm/components/ChainSelect/ChainSelect.js +1 -1
  8. package/_esm/components/ChainSelect/ChainSelect.js.map +1 -1
  9. package/_esm/components/FeeBreakdownTooltip.d.ts +12 -0
  10. package/_esm/components/FeeBreakdownTooltip.js +13 -0
  11. package/_esm/components/FeeBreakdownTooltip.js.map +1 -0
  12. package/_esm/components/GasMessage/GasRefuelMessage.js +1 -1
  13. package/_esm/components/GasMessage/GasRefuelMessage.js.map +1 -1
  14. package/_esm/components/Header/CloseDrawerButton.js +1 -1
  15. package/_esm/components/Header/CloseDrawerButton.js.map +1 -1
  16. package/_esm/components/Header/SettingsButton.js +1 -1
  17. package/_esm/components/Header/SettingsButton.js.map +1 -1
  18. package/_esm/components/Header/TransactionHistoryButton.js +1 -1
  19. package/_esm/components/Header/TransactionHistoryButton.js.map +1 -1
  20. package/_esm/components/IconTypography.d.ts +3 -0
  21. package/_esm/components/IconTypography.js +8 -0
  22. package/_esm/components/IconTypography.js.map +1 -0
  23. package/_esm/components/PoweredBy/PoweredBy.js +1 -1
  24. package/_esm/components/PoweredBy/PoweredBy.js.map +1 -1
  25. package/_esm/components/ProgressToNextUpdate.js +1 -1
  26. package/_esm/components/ProgressToNextUpdate.js.map +1 -1
  27. package/_esm/components/RouteCard/RouteCard.js +7 -16
  28. package/_esm/components/RouteCard/RouteCard.js.map +1 -1
  29. package/_esm/components/RouteCard/RouteCard.style.d.ts +0 -3
  30. package/_esm/components/RouteCard/RouteCard.style.js +1 -7
  31. package/_esm/components/RouteCard/RouteCard.style.js.map +1 -1
  32. package/_esm/components/RouteCard/RouteCardEssentials.js +13 -14
  33. package/_esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
  34. package/_esm/components/RouteCard/RouteCardEssentialsExpanded.js +4 -20
  35. package/_esm/components/RouteCard/RouteCardEssentialsExpanded.js.map +1 -1
  36. package/_esm/components/RouteCard/types.d.ts +1 -6
  37. package/_esm/components/Routes/RoutesExpanded.js +2 -4
  38. package/_esm/components/Routes/RoutesExpanded.js.map +1 -1
  39. package/_esm/components/SendToWallet/SendToWalletExpandButton.js +1 -1
  40. package/_esm/components/SendToWallet/SendToWalletExpandButton.js.map +1 -1
  41. package/_esm/components/Step/Step.d.ts +1 -0
  42. package/_esm/components/Step/Step.js +2 -2
  43. package/_esm/components/Step/Step.js.map +1 -1
  44. package/_esm/components/Step/StepList.js +16 -7
  45. package/_esm/components/Step/StepList.js.map +1 -1
  46. package/_esm/components/Step/StepTimer.js +3 -3
  47. package/_esm/components/Step/StepTimer.js.map +1 -1
  48. package/_esm/components/StepActions/StepActions.js +5 -4
  49. package/_esm/components/StepActions/StepActions.js.map +1 -1
  50. package/_esm/components/StepActions/StepActions.style.js +4 -4
  51. package/_esm/components/StepActions/StepActions.style.js.map +1 -1
  52. package/_esm/components/Token/Token.d.ts +2 -0
  53. package/_esm/components/Token/Token.js +22 -8
  54. package/_esm/components/Token/Token.js.map +1 -1
  55. package/_esm/components/Token/Token.style.js +1 -0
  56. package/_esm/components/Token/Token.style.js.map +1 -1
  57. package/_esm/components/TokenRate.d.ts +7 -0
  58. package/_esm/components/TokenRate.js +41 -0
  59. package/_esm/components/TokenRate.js.map +1 -0
  60. package/_esm/components/TransactionDetails.d.ts +7 -0
  61. package/_esm/components/TransactionDetails.js +46 -0
  62. package/_esm/components/TransactionDetails.js.map +1 -0
  63. package/_esm/config/version.d.ts +1 -1
  64. package/_esm/config/version.js +1 -1
  65. package/_esm/hooks/timer/useInterval.d.ts +1 -0
  66. package/_esm/hooks/timer/useInterval.js +18 -0
  67. package/_esm/hooks/timer/useInterval.js.map +1 -0
  68. package/_esm/hooks/timer/useTimer.d.ts +18 -0
  69. package/_esm/hooks/timer/useTimer.js +61 -0
  70. package/_esm/hooks/timer/useTimer.js.map +1 -0
  71. package/_esm/hooks/timer/utils.d.ts +11 -0
  72. package/_esm/hooks/timer/utils.js +46 -0
  73. package/_esm/hooks/timer/utils.js.map +1 -0
  74. package/_esm/hooks/useAccount.js +4 -5
  75. package/_esm/hooks/useAccount.js.map +1 -1
  76. package/_esm/hooks/useAvailableChains.js +1 -0
  77. package/_esm/hooks/useAvailableChains.js.map +1 -1
  78. package/_esm/hooks/useGasRecommendation.js +1 -0
  79. package/_esm/hooks/useGasRecommendation.js.map +1 -1
  80. package/_esm/hooks/useProcessMessage.js +8 -0
  81. package/_esm/hooks/useProcessMessage.js.map +1 -1
  82. package/_esm/hooks/useRoutes.d.ts +4 -2
  83. package/_esm/hooks/useRoutes.js +17 -10
  84. package/_esm/hooks/useRoutes.js.map +1 -1
  85. package/_esm/hooks/useTokens.js +1 -0
  86. package/_esm/hooks/useTokens.js.map +1 -1
  87. package/_esm/hooks/useTools.js +1 -0
  88. package/_esm/hooks/useTools.js.map +1 -1
  89. package/_esm/hooks/useTransactionDetails.d.ts +1 -1
  90. package/_esm/hooks/useTransactionDetails.js +1 -1
  91. package/_esm/hooks/useTransactionDetails.js.map +1 -1
  92. package/_esm/hooks/useTransactionHistory.js.map +1 -1
  93. package/_esm/i18n/en.json +19 -21
  94. package/_esm/i18n/index.js +15 -15
  95. package/_esm/i18n/index.js.map +1 -1
  96. package/_esm/index.d.ts +2 -1
  97. package/_esm/index.js +1 -4
  98. package/_esm/index.js.map +1 -1
  99. package/_esm/pages/MainPage/ReviewButton.js +2 -4
  100. package/_esm/pages/MainPage/ReviewButton.js.map +1 -1
  101. package/_esm/pages/RoutesPage/RoutesPage.js +2 -4
  102. package/_esm/pages/RoutesPage/RoutesPage.js.map +1 -1
  103. package/_esm/pages/SelectEnabledToolsPage.js +1 -1
  104. package/_esm/pages/SelectEnabledToolsPage.js.map +1 -1
  105. package/_esm/pages/SendToWallet/SendToWalletPage.js +1 -1
  106. package/_esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
  107. package/_esm/pages/SettingsPage/ThemeSettings.js +1 -1
  108. package/_esm/pages/SettingsPage/ThemeSettings.js.map +1 -1
  109. package/_esm/pages/TransactionDetailsPage/TransactionDetailsPage.js +5 -7
  110. package/_esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
  111. package/_esm/pages/TransactionHistoryPage/TransactionHistoryItem.js +2 -2
  112. package/_esm/pages/TransactionHistoryPage/TransactionHistoryItem.js.map +1 -1
  113. package/_esm/pages/TransactionPage/ExchangeRateBottomSheet.js +2 -2
  114. package/_esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
  115. package/_esm/pages/TransactionPage/RouteTracker.d.ts +7 -0
  116. package/_esm/pages/TransactionPage/RouteTracker.js +39 -0
  117. package/_esm/pages/TransactionPage/RouteTracker.js.map +1 -0
  118. package/_esm/pages/TransactionPage/StartTransactionButton.d.ts +0 -1
  119. package/_esm/pages/TransactionPage/StartTransactionButton.js +0 -9
  120. package/_esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
  121. package/_esm/pages/TransactionPage/TransactionPage.js +10 -21
  122. package/_esm/pages/TransactionPage/TransactionPage.js.map +1 -1
  123. package/_esm/pages/TransactionPage/types.d.ts +0 -1
  124. package/_esm/providers/I18nProvider/I18nProvider.js +2 -0
  125. package/_esm/providers/I18nProvider/I18nProvider.js.map +1 -1
  126. package/_esm/providers/I18nProvider/currencyExtendedFormatter.d.ts +1 -0
  127. package/_esm/providers/I18nProvider/currencyExtendedFormatter.js +13 -0
  128. package/_esm/providers/I18nProvider/currencyExtendedFormatter.js.map +1 -0
  129. package/_esm/providers/WalletProvider/EVMBaseProvider.js +18 -12
  130. package/_esm/providers/WalletProvider/EVMBaseProvider.js.map +1 -1
  131. package/_esm/stores/routes/createRouteExecutionStore.js +2 -2
  132. package/_esm/stores/routes/createRouteExecutionStore.js.map +1 -1
  133. package/_esm/stores/routes/types.d.ts +1 -1
  134. package/_esm/stores/routes/useSetExecutableRoute.d.ts +1 -1
  135. package/_esm/themes/createTheme.js +6 -0
  136. package/_esm/themes/createTheme.js.map +1 -1
  137. package/_esm/types/widget.d.ts +1 -2
  138. package/_esm/utils/converters.js +5 -13
  139. package/_esm/utils/converters.js.map +1 -1
  140. package/_esm/utils/fees.d.ts +3 -3
  141. package/_esm/utils/fees.js +22 -14
  142. package/_esm/utils/fees.js.map +1 -1
  143. package/_esm/utils/format.d.ts +13 -4
  144. package/_esm/utils/format.js +51 -13
  145. package/_esm/utils/format.js.map +1 -1
  146. package/components/Card/CardIconButton.tsx +1 -0
  147. package/components/Card/CardLabel.tsx +13 -29
  148. package/components/ChainSelect/ChainSelect.tsx +1 -9
  149. package/components/FeeBreakdownTooltip.tsx +66 -0
  150. package/components/GasMessage/GasRefuelMessage.tsx +1 -1
  151. package/components/Header/CloseDrawerButton.tsx +1 -1
  152. package/components/Header/SettingsButton.tsx +1 -1
  153. package/components/Header/TransactionHistoryButton.tsx +1 -1
  154. package/components/IconTypography.ts +9 -0
  155. package/components/PoweredBy/PoweredBy.tsx +1 -1
  156. package/components/ProgressToNextUpdate.tsx +0 -3
  157. package/components/RouteCard/RouteCard.style.ts +1 -9
  158. package/components/RouteCard/RouteCard.tsx +15 -71
  159. package/components/RouteCard/RouteCardEssentials.tsx +52 -81
  160. package/components/RouteCard/RouteCardEssentialsExpanded.tsx +17 -107
  161. package/components/RouteCard/types.ts +1 -7
  162. package/components/Routes/RoutesExpanded.tsx +3 -4
  163. package/components/SendToWallet/SendToWalletExpandButton.tsx +1 -6
  164. package/components/Step/Step.tsx +11 -2
  165. package/components/Step/StepList.tsx +19 -10
  166. package/components/Step/StepTimer.tsx +9 -6
  167. package/components/StepActions/StepActions.style.tsx +4 -4
  168. package/components/StepActions/StepActions.tsx +11 -14
  169. package/components/Token/Token.style.tsx +1 -0
  170. package/components/Token/Token.tsx +49 -9
  171. package/components/TokenRate.tsx +79 -0
  172. package/components/TransactionDetails.tsx +182 -0
  173. package/config/version.ts +1 -1
  174. package/hooks/timer/useInterval.ts +21 -0
  175. package/hooks/timer/useTimer.ts +91 -0
  176. package/hooks/timer/utils.ts +54 -0
  177. package/hooks/useAccount.ts +8 -5
  178. package/hooks/useAvailableChains.ts +2 -1
  179. package/hooks/useGasRecommendation.ts +1 -0
  180. package/hooks/useProcessMessage.ts +8 -0
  181. package/hooks/useRoutes.ts +23 -13
  182. package/hooks/useTokens.ts +1 -0
  183. package/hooks/useTools.ts +2 -1
  184. package/hooks/useTransactionDetails.ts +3 -3
  185. package/hooks/useTransactionHistory.ts +1 -1
  186. package/i18n/en.json +19 -21
  187. package/i18n/index.ts +15 -15
  188. package/index.ts +2 -5
  189. package/package.json +18 -19
  190. package/pages/MainPage/ReviewButton.tsx +2 -4
  191. package/pages/RoutesPage/RoutesPage.tsx +3 -4
  192. package/pages/SelectEnabledToolsPage.tsx +1 -1
  193. package/pages/SendToWallet/SendToWalletPage.tsx +1 -1
  194. package/pages/SettingsPage/ThemeSettings.tsx +1 -1
  195. package/pages/TransactionDetailsPage/TransactionDetailsPage.tsx +9 -20
  196. package/pages/TransactionHistoryPage/TransactionHistoryItem.tsx +3 -5
  197. package/pages/TransactionPage/ExchangeRateBottomSheet.tsx +0 -2
  198. package/pages/TransactionPage/RouteTracker.tsx +68 -0
  199. package/pages/TransactionPage/StartTransactionButton.tsx +0 -24
  200. package/pages/TransactionPage/TransactionPage.tsx +21 -48
  201. package/pages/TransactionPage/types.ts +0 -1
  202. package/providers/I18nProvider/I18nProvider.tsx +6 -0
  203. package/providers/I18nProvider/currencyExtendedFormatter.ts +15 -0
  204. package/providers/WalletProvider/EVMBaseProvider.tsx +13 -7
  205. package/stores/routes/createRouteExecutionStore.ts +2 -2
  206. package/stores/routes/types.ts +1 -1
  207. package/themes/createTheme.ts +6 -0
  208. package/types/widget.ts +1 -2
  209. package/utils/converters.ts +5 -13
  210. package/utils/fees.ts +30 -25
  211. package/utils/format.ts +67 -20
  212. package/_esm/components/Insurance/Insurance.d.ts +0 -2
  213. package/_esm/components/Insurance/Insurance.js +0 -8
  214. package/_esm/components/Insurance/Insurance.js.map +0 -1
  215. package/_esm/components/Insurance/InsuranceCard.d.ts +0 -2
  216. package/_esm/components/Insurance/InsuranceCard.js +0 -36
  217. package/_esm/components/Insurance/InsuranceCard.js.map +0 -1
  218. package/_esm/components/Insurance/InsuranceCollapsed.d.ts +0 -2
  219. package/_esm/components/Insurance/InsuranceCollapsed.js +0 -29
  220. package/_esm/components/Insurance/InsuranceCollapsed.js.map +0 -1
  221. package/_esm/components/Insurance/types.d.ts +0 -19
  222. package/_esm/components/Insurance/types.js +0 -2
  223. package/_esm/components/Insurance/types.js.map +0 -1
  224. package/_esm/components/StepActions/StepFeeBreakdown.d.ts +0 -4
  225. package/_esm/components/StepActions/StepFeeBreakdown.js +0 -42
  226. package/_esm/components/StepActions/StepFeeBreakdown.js.map +0 -1
  227. package/_esm/icons/InsuraceLogo.d.ts +0 -2
  228. package/_esm/icons/InsuraceLogo.js +0 -8
  229. package/_esm/icons/InsuraceLogo.js.map +0 -1
  230. package/components/Insurance/Insurance.tsx +0 -22
  231. package/components/Insurance/InsuranceCard.tsx +0 -119
  232. package/components/Insurance/InsuranceCollapsed.tsx +0 -59
  233. package/components/Insurance/types.ts +0 -24
  234. package/components/StepActions/StepFeeBreakdown.tsx +0 -108
  235. package/icons/InsuraceLogo.tsx +0 -46
@@ -1,100 +1,18 @@
1
- import { AccessTimeFilled, Layers, MonetizationOn } from '@mui/icons-material';
1
+ import { Layers } from '@mui/icons-material';
2
2
  import { Box, Typography } from '@mui/material';
3
- import type { TFunction } from 'i18next';
4
3
  import { useTranslation } from 'react-i18next';
5
- import { formatUnits } from 'viem';
6
- import {
7
- getFeeCostsBreakdown,
8
- getGasCostsBreakdown,
9
- } from '../../utils/fees.js';
10
- import { IconTypography } from './RouteCard.style.js';
11
- import type { FeesBreakdown, RouteCardEssentialsProps } from './types.js';
4
+ import { IconTypography } from '../IconTypography.js';
5
+ import type { RouteCardEssentialsProps } from './types.js';
12
6
 
13
7
  export const RouteCardEssentialsExpanded: React.FC<
14
8
  RouteCardEssentialsProps
15
9
  > = ({ route }) => {
16
- const { t, i18n } = useTranslation();
17
- const executionTimeMinutes = Math.ceil(
18
- route.steps
19
- .map((step) => step.estimate.executionDuration)
20
- .reduce((duration, x) => duration + x, 0) / 60,
21
- );
22
- const gasCostUSD = parseFloat(route.gasCostUSD ?? '') || 0.01;
23
- const gasCosts = getGasCostsBreakdown(route);
24
- const feeCosts = getFeeCostsBreakdown(route, false);
25
- const fees =
26
- gasCostUSD + feeCosts.reduce((sum, feeCost) => sum + feeCost.amountUSD, 0);
10
+ const { t } = useTranslation();
27
11
  return (
28
12
  <Box flex={1} mt={2}>
29
- <Box>
30
- <Box display="flex" alignItems="center">
31
- <IconTypography ml={1} mr={3}>
32
- <MonetizationOn />
33
- </IconTypography>
34
- <Typography
35
- fontSize={16}
36
- color="text.primary"
37
- fontWeight="600"
38
- lineHeight={1.125}
39
- >
40
- {t(`format.currency`, {
41
- value: fees,
42
- })}
43
- </Typography>
44
- </Box>
45
- <Box mt={0.5} ml={7}>
46
- <Typography
47
- fontSize={12}
48
- color="text.secondary"
49
- fontWeight="500"
50
- lineHeight={1.125}
51
- >
52
- {t('main.fees.networkEstimated')}
53
- </Typography>
54
- {getFeeBreakdownTypography(gasCosts, t)}
55
- {feeCosts.length ? (
56
- <Box mt={0.5}>
57
- <Typography
58
- fontSize={12}
59
- color="text.secondary"
60
- fontWeight="500"
61
- lineHeight={1.125}
62
- >
63
- {t('main.fees.providerEstimated')}
64
- </Typography>
65
- {getFeeBreakdownTypography(feeCosts, t)}
66
- </Box>
67
- ) : null}
68
- </Box>
69
- </Box>
70
- <Box mt={2}>
71
- <Box display="flex" alignItems="center">
72
- <IconTypography ml={1} mr={3}>
73
- <Layers />
74
- </IconTypography>
75
- <Typography
76
- fontSize={16}
77
- color="text.primary"
78
- fontWeight="600"
79
- lineHeight={1.125}
80
- >
81
- {route.steps.length}
82
- </Typography>
83
- </Box>
84
- <Box mt={0.5} ml={7}>
85
- <Typography
86
- fontSize={12}
87
- color="text.secondary"
88
- fontWeight="500"
89
- lineHeight={1.125}
90
- >
91
- {t(`tooltip.numberOfSteps`)}
92
- </Typography>
93
- </Box>
94
- </Box>
95
- <Box display="flex" alignItems="center" mt={2}>
13
+ <Box display="flex" alignItems="center">
96
14
  <IconTypography ml={1} mr={3}>
97
- <AccessTimeFilled />
15
+ <Layers />
98
16
  </IconTypography>
99
17
  <Typography
100
18
  fontSize={16}
@@ -102,27 +20,19 @@ export const RouteCardEssentialsExpanded: React.FC<
102
20
  fontWeight="600"
103
21
  lineHeight={1.125}
104
22
  >
105
- {new Intl.NumberFormat(i18n.language, {
106
- style: 'unit',
107
- unit: 'minute',
108
- unitDisplay: 'long',
109
- }).format(executionTimeMinutes)}
23
+ {route.steps.length}
24
+ </Typography>
25
+ </Box>
26
+ <Box mt={0.5} ml={7}>
27
+ <Typography
28
+ fontSize={12}
29
+ color="text.secondary"
30
+ fontWeight="500"
31
+ lineHeight={1.125}
32
+ >
33
+ {t(`tooltip.numberOfSteps`)}
110
34
  </Typography>
111
35
  </Box>
112
36
  </Box>
113
37
  );
114
38
  };
115
-
116
- const getFeeBreakdownTypography = (fees: FeesBreakdown[], t: TFunction) =>
117
- fees.map((fee, index) => (
118
- <Typography
119
- fontSize={12}
120
- fontWeight="500"
121
- color="text.secondary"
122
- key={`${fee.token.address}${index}`}
123
- >
124
- {t(`format.currency`, { value: fee.amountUSD })} (
125
- {parseFloat(formatUnits(fee.amount, fee.token.decimals))?.toFixed(9)}{' '}
126
- {fee.token.symbol})
127
- </Typography>
128
- ));
@@ -1,4 +1,4 @@
1
- import type { Route, Token } from '@lifi/sdk';
1
+ import type { Route } from '@lifi/sdk';
2
2
 
3
3
  export interface RouteCardProps {
4
4
  route: Route;
@@ -14,9 +14,3 @@ export interface RouteCardEssentialsProps {
14
14
  export interface RouteCardSkeletonProps {
15
15
  variant?: 'default' | 'cardless';
16
16
  }
17
-
18
- export interface FeesBreakdown {
19
- amount: bigint;
20
- amountUSD: number;
21
- token: Token;
22
- }
@@ -11,7 +11,6 @@ import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.j
11
11
  import { useWidgetEvents } from '../../hooks/useWidgetEvents.js';
12
12
  import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
13
13
  import { useFieldValues } from '../../stores/form/useFieldValues.js';
14
- import { useSetExecutableRoute } from '../../stores/routes/useSetExecutableRoute.js';
15
14
  import { WidgetEvent } from '../../types/events.js';
16
15
  import { navigationRoutes } from '../../utils/navigationRoutes.js';
17
16
  import { PageContainer } from '../PageContainer.js';
@@ -59,7 +58,6 @@ export const RoutesExpanded = () => {
59
58
  export const RoutesExpandedElement = () => {
60
59
  const { t } = useTranslation();
61
60
  const navigate = useNavigate();
62
- const setExecutableRoute = useSetExecutableRoute();
63
61
  const { subvariant } = useWidgetConfig();
64
62
  const routesRef = useRef<Route[]>();
65
63
  const emitter = useWidgetEvents();
@@ -71,15 +69,16 @@ export const RoutesExpandedElement = () => {
71
69
  isFetched,
72
70
  dataUpdatedAt,
73
71
  refetchTime,
74
- refetch,
75
72
  fromChain,
73
+ refetch,
74
+ setReviewableRoute,
76
75
  } = useRoutes();
77
76
  const { account } = useAccount({ chainType: fromChain?.chainType });
78
77
  const [toAddress] = useFieldValues('toAddress');
79
78
  const { requiredToAddress } = useToAddressRequirements();
80
79
 
81
80
  const handleRouteClick = (route: Route) => {
82
- setExecutableRoute(route);
81
+ setReviewableRoute(route);
83
82
  navigate(navigationRoutes.transactionExecution, {
84
83
  state: { routeId: route.id },
85
84
  });
@@ -41,12 +41,7 @@ export const SendToWalletExpandButton: React.FC = () => {
41
41
  };
42
42
 
43
43
  return (
44
- <Tooltip
45
- title={t('main.sendToWallet')}
46
- placement="bottom-end"
47
- enterDelay={400}
48
- arrow
49
- >
44
+ <Tooltip title={t('main.sendToWallet')} placement="bottom-end">
50
45
  <Button
51
46
  variant={isActive ? 'contained' : 'text'}
52
47
  onClick={handleClick}
@@ -17,8 +17,9 @@ export const Step: React.FC<{
17
17
  step: LiFiStepExtended;
18
18
  fromToken?: TokenAmount;
19
19
  toToken?: TokenAmount;
20
+ impactToken?: TokenAmount;
20
21
  toAddress?: string;
21
- }> = ({ step, fromToken, toToken, toAddress }) => {
22
+ }> = ({ step, fromToken, toToken, impactToken, toAddress }) => {
22
23
  const { t } = useTranslation();
23
24
  const { getChainById } = useAvailableChains();
24
25
  const { subvariant } = useWidgetConfig();
@@ -89,7 +90,15 @@ export const Step: React.FC<{
89
90
  toAddressLink={toAddressLink}
90
91
  />
91
92
  ) : null}
92
- {toToken ? <Token token={toToken} px={2} py={1} /> : null}
93
+ {toToken ? (
94
+ <Token
95
+ token={toToken}
96
+ impactToken={impactToken}
97
+ enableImpactTokenTooltip
98
+ px={2}
99
+ py={1}
100
+ />
101
+ ) : null}
93
102
  </Box>
94
103
  </Card>
95
104
  );
@@ -12,19 +12,27 @@ export const getStepList = (
12
12
  const lastIndex = steps.length - 1;
13
13
  const fromToken: TokenAmount | undefined =
14
14
  index === 0
15
- ? { ...step.action.fromToken, amount: BigInt(step.action.fromAmount) }
16
- : undefined;
17
- const toToken: TokenAmount | undefined =
18
- index === lastIndex
19
15
  ? {
20
- ...(step.execution?.toToken ?? step.action?.toToken),
21
- amount: step.execution?.toAmount
22
- ? BigInt(step.execution.toAmount)
23
- : subvariant === 'custom'
24
- ? BigInt(route.toAmount)
25
- : BigInt(step.estimate.toAmount),
16
+ ...step.action.fromToken,
17
+ amount: BigInt(step.action.fromAmount),
26
18
  }
27
19
  : undefined;
20
+ let toToken: TokenAmount | undefined;
21
+ let impactToken: TokenAmount | undefined;
22
+ if (index === lastIndex) {
23
+ toToken = {
24
+ ...(step.execution?.toToken ?? step.action.toToken),
25
+ amount: step.execution?.toAmount
26
+ ? BigInt(step.execution.toAmount)
27
+ : subvariant === 'custom'
28
+ ? BigInt(route.toAmount)
29
+ : BigInt(step.estimate.toAmount),
30
+ };
31
+ impactToken = {
32
+ ...steps[0].action.fromToken,
33
+ amount: BigInt(steps[0].action.fromAmount),
34
+ };
35
+ }
28
36
  const toAddress =
29
37
  index === lastIndex && route.fromAddress !== route.toAddress
30
38
  ? route.toAddress
@@ -35,6 +43,7 @@ export const getStepList = (
35
43
  step={step}
36
44
  fromToken={fromToken}
37
45
  toToken={toToken}
46
+ impactToken={impactToken}
38
47
  toAddress={toAddress}
39
48
  />
40
49
  {steps.length > 1 && index !== steps.length - 1 ? (
@@ -1,7 +1,7 @@
1
1
  import type { LiFiStepExtended } from '@lifi/sdk';
2
2
  import { useEffect, useState } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
- import { useTimer } from 'react-timer-hook';
4
+ import { useTimer } from '../../hooks/timer/useTimer.js';
5
5
 
6
6
  const getExpiryTimestamp = (step: LiFiStepExtended) =>
7
7
  new Date(
@@ -52,11 +52,14 @@ export const StepTimer: React.FC<{
52
52
  ]);
53
53
 
54
54
  if (!isExecutionStarted) {
55
- return new Intl.NumberFormat(i18n.language, {
56
- style: 'unit',
57
- unit: 'minute',
58
- unitDisplay: 'narrow',
59
- }).format(Math.ceil(step.estimate.executionDuration / 60));
55
+ return Math.ceil(step.estimate.executionDuration / 60).toLocaleString(
56
+ i18n.language,
57
+ {
58
+ style: 'unit',
59
+ unit: 'minute',
60
+ unitDisplay: 'narrow',
61
+ },
62
+ );
60
63
  }
61
64
 
62
65
  const isTimerExpired = isExpired || (!minutes && !seconds);
@@ -20,8 +20,8 @@ export const StepConnector = styled(MuiStepConnector, {
20
20
  borderLeftWidth: 2,
21
21
  borderColor:
22
22
  theme.palette.mode === 'light'
23
- ? theme.palette.grey[300]
24
- : theme.palette.grey[800],
23
+ ? alpha(theme.palette.common.black, 0.12)
24
+ : alpha(theme.palette.common.white, 0.16),
25
25
  },
26
26
  }));
27
27
 
@@ -60,8 +60,8 @@ export const StepContent = styled(Box, {
60
60
  ? 'none'
61
61
  : `2px solid ${
62
62
  theme.palette.mode === 'light'
63
- ? theme.palette.grey[300]
64
- : theme.palette.grey[800]
63
+ ? alpha(theme.palette.common.black, 0.12)
64
+ : alpha(theme.palette.common.white, 0.16)
65
65
  }`,
66
66
  margin: theme.spacing(0, 0, 0, 2.375),
67
67
  paddingLeft: last ? theme.spacing(4.625) : theme.spacing(4.375),
@@ -26,7 +26,6 @@ import {
26
26
  StepLabel,
27
27
  StepLabelTypography,
28
28
  } from './StepActions.style.js';
29
- import { StepFeeBreakdown } from './StepFeeBreakdown.js';
30
29
  import { StepFees } from './StepFees.js';
31
30
  import type {
32
31
  IncludedStepsProps,
@@ -74,22 +73,21 @@ export const StepActions: React.FC<StepActionsProps> = ({
74
73
  </Badge>
75
74
  <Box flex={1}>
76
75
  <Typography fontSize={18} fontWeight={600} lineHeight={1.3334} ml={2}>
77
- {t(`main.stepDetails`, {
78
- tool: toolDetails.name,
79
- })}
76
+ {toolDetails.name?.includes('LI.FI')
77
+ ? toolDetails.name
78
+ : t(`main.stepDetails`, {
79
+ tool: toolDetails.name,
80
+ })}
80
81
  </Typography>
81
- <Collapse
82
- timeout={225}
83
- in={dense && !cardExpanded}
84
- mountOnEnter
85
- unmountOnExit
86
- >
87
- <StepFees ml={2} step={step} />
88
- </Collapse>
82
+ <StepFees ml={2} step={step} />
89
83
  </Box>
90
84
  {dense ? (
91
85
  <CardIconButton onClick={handleExpand} size="small">
92
- {cardExpanded ? <ExpandLess /> : <ExpandMore />}
86
+ {cardExpanded ? (
87
+ <ExpandLess fontSize="inherit" />
88
+ ) : (
89
+ <ExpandMore fontSize="inherit" />
90
+ )}
93
91
  </CardIconButton>
94
92
  ) : null}
95
93
  </Box>
@@ -100,7 +98,6 @@ export const StepActions: React.FC<StepActionsProps> = ({
100
98
  subvariant={subvariant}
101
99
  subvariantOptions={subvariantOptions}
102
100
  />
103
- <StepFeeBreakdown step={step} />
104
101
  </Collapse>
105
102
  ) : (
106
103
  <IncludedSteps
@@ -16,6 +16,7 @@ export const TextSecondary = styled(Typography, {
16
16
  color: dot
17
17
  ? alpha(theme.palette.text.secondary, 0.56)
18
18
  : theme.palette.text.secondary,
19
+ whiteSpace: 'nowrap',
19
20
  }));
20
21
 
21
22
  export const TokenDivider = styled(Box)(({ theme }) => ({
@@ -1,12 +1,16 @@
1
1
  /* eslint-disable react/no-array-index-key */
2
2
  import type { LiFiStep, TokenAmount } from '@lifi/sdk';
3
3
  import type { BoxProps } from '@mui/material';
4
- import { Box, Grow, Skeleton } from '@mui/material';
4
+ import { Box, Grow, Skeleton, Tooltip } from '@mui/material';
5
5
  import type { FC, PropsWithChildren, ReactElement } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { useChain } from '../../hooks/useChain.js';
8
8
  import { useToken } from '../../hooks/useToken.js';
9
- import { formatTokenAmount, formatTokenPrice } from '../../utils/format.js';
9
+ import {
10
+ convertToSubscriptFormat,
11
+ formatTokenAmount,
12
+ formatTokenPrice,
13
+ } from '../../utils/format.js';
10
14
  import { AvatarBadgedSkeleton } from '../Avatar/Avatar.js';
11
15
  import { TokenAvatar } from '../Avatar/TokenAvatar.js';
12
16
  import { SmallAvatar } from '../SmallAvatar.js';
@@ -15,6 +19,8 @@ import { TextSecondary, TextSecondaryContainer } from './Token.style.js';
15
19
 
16
20
  interface TokenProps {
17
21
  token: TokenAmount;
22
+ impactToken?: TokenAmount;
23
+ enableImpactTokenTooltip?: boolean;
18
24
  step?: LiFiStep;
19
25
  stepVisible?: boolean;
20
26
  disableDescription?: boolean;
@@ -49,6 +55,8 @@ export const TokenFallback: FC<TokenProps & BoxProps> = ({
49
55
 
50
56
  export const TokenBase: FC<TokenProps & BoxProps> = ({
51
57
  token,
58
+ impactToken,
59
+ enableImpactTokenTooltip,
52
60
  step,
53
61
  stepVisible,
54
62
  disableDescription,
@@ -69,11 +77,29 @@ export const TokenBase: FC<TokenProps & BoxProps> = ({
69
77
  );
70
78
  }
71
79
 
72
- const formattedTokenAmount = formatTokenAmount(token.amount, token.decimals);
73
- const formattedTokenPrice = formatTokenPrice(
74
- formattedTokenAmount,
75
- token.priceUSD,
76
- );
80
+ const tokenAmount = formatTokenAmount(token.amount, token.decimals);
81
+ const tokenPrice = formatTokenPrice(tokenAmount, token.priceUSD);
82
+
83
+ let priceImpact;
84
+ if (impactToken) {
85
+ const impactTokenAmount = formatTokenAmount(
86
+ impactToken.amount,
87
+ impactToken.decimals,
88
+ );
89
+ const impactTokenPrice =
90
+ formatTokenPrice(impactTokenAmount, impactToken.priceUSD) || 0.01;
91
+
92
+ const impact = (tokenPrice / impactTokenPrice - 1) * 100;
93
+
94
+ priceImpact = convertToSubscriptFormat(impact, {
95
+ notation: 'standard',
96
+ roundingPriority: 'morePrecision',
97
+ maximumSignificantDigits: 2,
98
+ maximumFractionDigits: 2,
99
+ useGrouping: false,
100
+ roundingMode: 'trunc',
101
+ });
102
+ }
77
103
 
78
104
  const tokenOnChain = !disableDescription ? (
79
105
  <TextSecondary>
@@ -101,16 +127,30 @@ export const TokenBase: FC<TokenProps & BoxProps> = ({
101
127
  }}
102
128
  >
103
129
  {t('format.number', {
104
- value: formattedTokenAmount,
130
+ value: tokenAmount,
105
131
  })}
106
132
  </TextFitter>
107
133
  </Box>
108
134
  <TextSecondaryContainer component="span">
109
135
  <TextSecondary>
110
136
  {t(`format.currency`, {
111
- value: formattedTokenPrice,
137
+ value: tokenPrice,
112
138
  })}
113
139
  </TextSecondary>
140
+ {impactToken ? (
141
+ <TextSecondary px={0.5} dot>
142
+ &#x2022;
143
+ </TextSecondary>
144
+ ) : null}
145
+ {impactToken ? (
146
+ enableImpactTokenTooltip ? (
147
+ <Tooltip title={t('tooltip.priceImpact')} sx={{ cursor: 'help' }}>
148
+ <TextSecondary>{priceImpact}%</TextSecondary>
149
+ </Tooltip>
150
+ ) : (
151
+ <TextSecondary>{priceImpact}%</TextSecondary>
152
+ )
153
+ ) : null}
114
154
  {!disableDescription ? (
115
155
  <TextSecondary px={0.5} dot>
116
156
  &#x2022;
@@ -0,0 +1,79 @@
1
+ import type { RouteExtended } from '@lifi/sdk';
2
+ import type { TypographyProps } from '@mui/material';
3
+ import { Typography } from '@mui/material';
4
+ import type { MouseEventHandler } from 'react';
5
+ import { formatUnits } from 'viem';
6
+ import { create } from 'zustand';
7
+ import {
8
+ convertToSubscriptFormat,
9
+ precisionFormatter,
10
+ } from '../utils/format.js';
11
+
12
+ interface TokenRateProps extends TypographyProps {
13
+ route: RouteExtended;
14
+ }
15
+
16
+ interface TokenRateState {
17
+ isForward: boolean;
18
+ toggleIsForward(): void;
19
+ }
20
+
21
+ const useTokenRateStore = create<TokenRateState>((set) => ({
22
+ isForward: true,
23
+ toggleIsForward: () => set((state) => ({ isForward: !state.isForward })),
24
+ }));
25
+
26
+ export const TokenRate: React.FC<TokenRateProps> = ({ route, ...props }) => {
27
+ const { isForward, toggleIsForward } = useTokenRateStore();
28
+
29
+ const toggleRate: MouseEventHandler<HTMLSpanElement> = (e) => {
30
+ e.stopPropagation();
31
+ toggleIsForward();
32
+ };
33
+
34
+ const lastStep = route.steps.at(-1);
35
+
36
+ const fromToken = {
37
+ ...route.fromToken,
38
+ amount: BigInt(route.fromAmount),
39
+ };
40
+ const toToken = {
41
+ ...(lastStep?.execution?.toToken ??
42
+ lastStep?.action.toToken ??
43
+ route.toToken),
44
+ amount: lastStep?.execution?.toAmount
45
+ ? BigInt(lastStep.execution.toAmount)
46
+ : BigInt(route.toAmount),
47
+ };
48
+
49
+ const fromToRate =
50
+ parseFloat(formatUnits(toToken.amount!, toToken.decimals)) /
51
+ parseFloat(formatUnits(fromToken.amount!, fromToken.decimals));
52
+ const toFromRate =
53
+ parseFloat(formatUnits(fromToken.amount!, fromToken.decimals)) /
54
+ parseFloat(formatUnits(toToken.amount!, toToken.decimals));
55
+
56
+ const rateText = isForward
57
+ ? `1 ${fromToken.symbol} ≈ ${convertToSubscriptFormat(fromToRate)} ${toToken.symbol}`
58
+ : `1 ${toToken.symbol} ≈ ${convertToSubscriptFormat(toFromRate)} ${fromToken.symbol}`;
59
+
60
+ const rateTitle = isForward
61
+ ? `1 ${fromToken.symbol} ≈ ${precisionFormatter.format(fromToRate)} ${toToken.symbol}`
62
+ : `1 ${toToken.symbol} ≈ ${precisionFormatter.format(toFromRate)} ${fromToken.symbol}`;
63
+
64
+ return (
65
+ <Typography
66
+ fontSize={14}
67
+ lineHeight={1.429}
68
+ color="text.secondary"
69
+ fontWeight="500"
70
+ onClick={toggleRate}
71
+ role="button"
72
+ sx={{ cursor: 'pointer' }}
73
+ title={rateTitle}
74
+ {...props}
75
+ >
76
+ {rateText}
77
+ </Typography>
78
+ );
79
+ };