@lifi/widget 3.25.0-beta.5 → 3.26.0

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 (274) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/esm/components/AmountInput/AmountInput.js +75 -17
  3. package/dist/esm/components/AmountInput/AmountInput.js.map +1 -1
  4. package/dist/esm/components/AmountInput/AmountInput.style.d.ts +4 -0
  5. package/dist/esm/components/AmountInput/AmountInput.style.js +11 -0
  6. package/dist/esm/components/AmountInput/AmountInput.style.js.map +1 -1
  7. package/dist/esm/components/AmountInput/AmountInputAdornment.style.d.ts +1 -0
  8. package/dist/esm/components/AmountInput/AmountInputAdornment.style.js +64 -5
  9. package/dist/esm/components/AmountInput/AmountInputAdornment.style.js.map +1 -1
  10. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +20 -7
  11. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
  12. package/dist/esm/components/AmountInput/PriceFormHelperText.js +41 -15
  13. package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
  14. package/dist/esm/components/AmountInput/PriceFormHelperText.style.d.ts +1 -0
  15. package/dist/esm/components/AmountInput/PriceFormHelperText.style.js +29 -0
  16. package/dist/esm/components/AmountInput/PriceFormHelperText.style.js.map +1 -0
  17. package/dist/esm/components/AppContainer.js +1 -0
  18. package/dist/esm/components/AppContainer.js.map +1 -1
  19. package/dist/esm/components/ChainSelect/useChainSelect.js +2 -4
  20. package/dist/esm/components/ChainSelect/useChainSelect.js.map +1 -1
  21. package/dist/esm/components/Chains/ChainList.d.ts +2 -3
  22. package/dist/esm/components/Chains/ChainList.js +4 -3
  23. package/dist/esm/components/Chains/ChainList.js.map +1 -1
  24. package/dist/esm/components/Chains/ChainList.style.js +10 -3
  25. package/dist/esm/components/Chains/ChainList.style.js.map +1 -1
  26. package/dist/esm/components/Chains/ChainListItem.d.ts +4 -1
  27. package/dist/esm/components/Chains/ChainListItem.js +14 -2
  28. package/dist/esm/components/Chains/ChainListItem.js.map +1 -1
  29. package/dist/esm/components/Chains/PinChainButton.d.ts +7 -0
  30. package/dist/esm/components/Chains/PinChainButton.js +34 -0
  31. package/dist/esm/components/Chains/PinChainButton.js.map +1 -0
  32. package/dist/esm/components/Chains/SelectChainContent.js +15 -16
  33. package/dist/esm/components/Chains/SelectChainContent.js.map +1 -1
  34. package/dist/esm/components/Chains/VirtualizedChainList.d.ts +2 -1
  35. package/dist/esm/components/Chains/VirtualizedChainList.js +45 -9
  36. package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
  37. package/dist/esm/components/Header/NavigationHeader.js +5 -1
  38. package/dist/esm/components/Header/NavigationHeader.js.map +1 -1
  39. package/dist/esm/components/Messages/MinFromAmountUSDMessage.d.ts +6 -0
  40. package/dist/esm/components/Messages/MinFromAmountUSDMessage.js +15 -0
  41. package/dist/esm/components/Messages/MinFromAmountUSDMessage.js.map +1 -0
  42. package/dist/esm/components/Messages/WarningMessages.js +3 -0
  43. package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
  44. package/dist/esm/components/Messages/useMessageQueue.js +15 -4
  45. package/dist/esm/components/Messages/useMessageQueue.js.map +1 -1
  46. package/dist/esm/components/Routes/RoutesContent.js +3 -2
  47. package/dist/esm/components/Routes/RoutesContent.js.map +1 -1
  48. package/dist/esm/components/Routes/RoutesExpanded.style.js +3 -2
  49. package/dist/esm/components/Routes/RoutesExpanded.style.js.map +1 -1
  50. package/dist/esm/components/SendToWallet/SendToWalletButton.js +1 -1
  51. package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
  52. package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js +3 -3
  53. package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js.map +1 -1
  54. package/dist/esm/components/Step/StepProcess.js +3 -8
  55. package/dist/esm/components/Step/StepProcess.js.map +1 -1
  56. package/dist/esm/components/TokenList/TokenDetailsSheet.js +0 -2
  57. package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -1
  58. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js +27 -4
  59. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -1
  60. package/dist/esm/components/TokenList/TokenList.js +10 -1
  61. package/dist/esm/components/TokenList/TokenList.js.map +1 -1
  62. package/dist/esm/components/TokenList/TokenListItem.js +3 -1
  63. package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
  64. package/dist/esm/components/TokenList/useTokenSelect.js +2 -4
  65. package/dist/esm/components/TokenList/useTokenSelect.js.map +1 -1
  66. package/dist/esm/config/version.d.ts +1 -1
  67. package/dist/esm/config/version.js +1 -1
  68. package/dist/esm/config/version.js.map +1 -1
  69. package/dist/esm/hooks/useFromAmountThreshold.d.ts +4 -0
  70. package/dist/esm/hooks/useFromAmountThreshold.js +23 -0
  71. package/dist/esm/hooks/useFromAmountThreshold.js.map +1 -0
  72. package/dist/esm/hooks/useGasSufficiency.js +3 -3
  73. package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
  74. package/dist/esm/hooks/useLongPress.d.ts +7 -0
  75. package/dist/esm/hooks/useLongPress.js +41 -0
  76. package/dist/esm/hooks/useLongPress.js.map +1 -0
  77. package/dist/esm/hooks/useNavigateBack.d.ts +1 -1
  78. package/dist/esm/hooks/useNavigateBack.js +8 -2
  79. package/dist/esm/hooks/useNavigateBack.js.map +1 -1
  80. package/dist/esm/hooks/useRouteExecution.js +1 -2
  81. package/dist/esm/hooks/useRouteExecution.js.map +1 -1
  82. package/dist/esm/hooks/useRoutes.js +19 -4
  83. package/dist/esm/hooks/useRoutes.js.map +1 -1
  84. package/dist/esm/hooks/useSettingMonitor.js +1 -2
  85. package/dist/esm/hooks/useSettingMonitor.js.map +1 -1
  86. package/dist/esm/hooks/useTokenAddressBalance.js +4 -1
  87. package/dist/esm/hooks/useTokenAddressBalance.js.map +1 -1
  88. package/dist/esm/hooks/useTokenBalances.d.ts +1 -2
  89. package/dist/esm/hooks/useTokenBalances.js +2 -3
  90. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  91. package/dist/esm/hooks/useTokenSearch.d.ts +2 -2
  92. package/dist/esm/hooks/useTokenSearch.js +5 -2
  93. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  94. package/dist/esm/hooks/useTokens.d.ts +1 -2
  95. package/dist/esm/hooks/useTokens.js +3 -12
  96. package/dist/esm/hooks/useTokens.js.map +1 -1
  97. package/dist/esm/hooks/useTools.js +2 -2
  98. package/dist/esm/hooks/useTools.js.map +1 -1
  99. package/dist/esm/i18n/bn.json +5 -2
  100. package/dist/esm/i18n/de.json +5 -2
  101. package/dist/esm/i18n/en.json +5 -2
  102. package/dist/esm/i18n/es.json +5 -2
  103. package/dist/esm/i18n/fr.json +5 -2
  104. package/dist/esm/i18n/hi.json +5 -2
  105. package/dist/esm/i18n/id.json +5 -2
  106. package/dist/esm/i18n/it.json +5 -2
  107. package/dist/esm/i18n/ja.json +5 -2
  108. package/dist/esm/i18n/ko.json +5 -2
  109. package/dist/esm/i18n/pl.json +4 -1
  110. package/dist/esm/i18n/pt.json +5 -2
  111. package/dist/esm/i18n/th.json +5 -2
  112. package/dist/esm/i18n/tr.json +5 -2
  113. package/dist/esm/i18n/uk.json +5 -2
  114. package/dist/esm/i18n/vi.json +5 -2
  115. package/dist/esm/i18n/zh.json +5 -2
  116. package/dist/esm/pages/SelectEnabledToolsPage.js +4 -2
  117. package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
  118. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.js +14 -7
  119. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.js.map +1 -1
  120. package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js +1 -2
  121. package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js.map +1 -1
  122. package/dist/esm/pages/TransactionPage/TransactionPage.js +5 -3
  123. package/dist/esm/pages/TransactionPage/TransactionPage.js.map +1 -1
  124. package/dist/esm/stores/bookmarks/BookmarkStore.d.ts +1 -2
  125. package/dist/esm/stores/bookmarks/BookmarkStore.js +3 -3
  126. package/dist/esm/stores/bookmarks/BookmarkStore.js.map +1 -1
  127. package/dist/esm/stores/bookmarks/useBookmarkActions.js +1 -2
  128. package/dist/esm/stores/bookmarks/useBookmarkActions.js.map +1 -1
  129. package/dist/esm/stores/bookmarks/useBookmarks.js +1 -2
  130. package/dist/esm/stores/bookmarks/useBookmarks.js.map +1 -1
  131. package/dist/esm/stores/chains/ChainOrderStore.d.ts +1 -1
  132. package/dist/esm/stores/chains/ChainOrderStore.js +20 -7
  133. package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
  134. package/dist/esm/stores/chains/createChainOrderStore.js +19 -1
  135. package/dist/esm/stores/chains/createChainOrderStore.js.map +1 -1
  136. package/dist/esm/stores/chains/types.d.ts +2 -0
  137. package/dist/esm/stores/chains/useChainOrder.js +1 -2
  138. package/dist/esm/stores/chains/useChainOrder.js.map +1 -1
  139. package/dist/esm/stores/form/useFieldActions.js +1 -2
  140. package/dist/esm/stores/form/useFieldActions.js.map +1 -1
  141. package/dist/esm/stores/form/useFieldValues.js +1 -2
  142. package/dist/esm/stores/form/useFieldValues.js.map +1 -1
  143. package/dist/esm/stores/form/useFormStore.d.ts +1 -2
  144. package/dist/esm/stores/form/useFormStore.js +3 -3
  145. package/dist/esm/stores/form/useFormStore.js.map +1 -1
  146. package/dist/esm/stores/form/useTouchedFields.js +1 -2
  147. package/dist/esm/stores/form/useTouchedFields.js.map +1 -1
  148. package/dist/esm/stores/form/useValidation.js +5 -2
  149. package/dist/esm/stores/form/useValidation.js.map +1 -1
  150. package/dist/esm/stores/form/useValidationActions.js +1 -2
  151. package/dist/esm/stores/form/useValidationActions.js.map +1 -1
  152. package/dist/esm/stores/header/useHeaderStore.d.ts +1 -1
  153. package/dist/esm/stores/header/useHeaderStore.js +5 -5
  154. package/dist/esm/stores/header/useHeaderStore.js.map +1 -1
  155. package/dist/esm/stores/inputMode/useInputModeStore.d.ts +9 -0
  156. package/dist/esm/stores/inputMode/useInputModeStore.js +19 -0
  157. package/dist/esm/stores/inputMode/useInputModeStore.js.map +1 -0
  158. package/dist/esm/stores/routes/RouteExecutionStore.d.ts +1 -1
  159. package/dist/esm/stores/routes/RouteExecutionStore.js +3 -2
  160. package/dist/esm/stores/routes/RouteExecutionStore.js.map +1 -1
  161. package/dist/esm/stores/routes/useExecutingRoutesIds.js +1 -2
  162. package/dist/esm/stores/routes/useExecutingRoutesIds.js.map +1 -1
  163. package/dist/esm/stores/settings/useSendToWalletStore.d.ts +2 -1
  164. package/dist/esm/stores/settings/useSendToWalletStore.js +6 -3
  165. package/dist/esm/stores/settings/useSendToWalletStore.js.map +1 -1
  166. package/dist/esm/stores/settings/useSettings.js +1 -2
  167. package/dist/esm/stores/settings/useSettings.js.map +1 -1
  168. package/dist/esm/stores/settings/useSettingsActions.js +1 -2
  169. package/dist/esm/stores/settings/useSettingsActions.js.map +1 -1
  170. package/dist/esm/stores/settings/useSettingsStore.d.ts +2 -1
  171. package/dist/esm/stores/settings/useSettingsStore.js +5 -1
  172. package/dist/esm/stores/settings/useSettingsStore.js.map +1 -1
  173. package/dist/esm/stores/settings/useSplitSubvariantStore.js +2 -1
  174. package/dist/esm/stores/settings/useSplitSubvariantStore.js.map +1 -1
  175. package/dist/esm/themes/createTheme.js +5 -1
  176. package/dist/esm/themes/createTheme.js.map +1 -1
  177. package/dist/esm/types/widget.d.ts +3 -1
  178. package/dist/esm/types/widget.js +1 -0
  179. package/dist/esm/types/widget.js.map +1 -1
  180. package/dist/esm/utils/format.d.ts +4 -0
  181. package/dist/esm/utils/format.js +26 -0
  182. package/dist/esm/utils/format.js.map +1 -1
  183. package/dist/esm/utils/getPriceImpact.d.ts +2 -2
  184. package/dist/esm/utils/getPriceImpact.js.map +1 -1
  185. package/package.json +12 -12
  186. package/package.json.tmp +14 -14
  187. package/src/components/AmountInput/AmountInput.style.tsx +13 -0
  188. package/src/components/AmountInput/AmountInput.tsx +91 -18
  189. package/src/components/AmountInput/AmountInputAdornment.style.tsx +66 -5
  190. package/src/components/AmountInput/AmountInputEndAdornment.tsx +40 -10
  191. package/src/components/AmountInput/PriceFormHelperText.style.tsx +29 -0
  192. package/src/components/AmountInput/PriceFormHelperText.tsx +63 -19
  193. package/src/components/AppContainer.tsx +1 -0
  194. package/src/components/ChainSelect/useChainSelect.ts +2 -4
  195. package/src/components/Chains/ChainList.style.tsx +10 -2
  196. package/src/components/Chains/ChainList.tsx +6 -5
  197. package/src/components/Chains/ChainListItem.tsx +29 -0
  198. package/src/components/Chains/PinChainButton.tsx +51 -0
  199. package/src/components/Chains/SelectChainContent.tsx +18 -21
  200. package/src/components/Chains/VirtualizedChainList.tsx +67 -20
  201. package/src/components/Header/NavigationHeader.tsx +10 -1
  202. package/src/components/Messages/MinFromAmountUSDMessage.tsx +35 -0
  203. package/src/components/Messages/WarningMessages.tsx +8 -0
  204. package/src/components/Messages/useMessageQueue.ts +16 -4
  205. package/src/components/Routes/RoutesContent.tsx +6 -2
  206. package/src/components/Routes/RoutesExpanded.style.ts +3 -2
  207. package/src/components/SendToWallet/SendToWalletButton.tsx +1 -1
  208. package/src/components/SendToWallet/SendToWalletExpandButton.tsx +8 -3
  209. package/src/components/Step/StepProcess.tsx +3 -8
  210. package/src/components/TokenList/TokenDetailsSheet.tsx +0 -2
  211. package/src/components/TokenList/TokenDetailsSheetContent.tsx +50 -3
  212. package/src/components/TokenList/TokenList.tsx +24 -1
  213. package/src/components/TokenList/TokenListItem.tsx +6 -0
  214. package/src/components/TokenList/useTokenSelect.ts +2 -4
  215. package/src/config/version.ts +1 -1
  216. package/src/hooks/useFromAmountThreshold.ts +35 -0
  217. package/src/hooks/useGasSufficiency.ts +4 -4
  218. package/src/hooks/useLongPress.ts +51 -0
  219. package/src/hooks/useNavigateBack.ts +26 -17
  220. package/src/hooks/useRouteExecution.ts +1 -3
  221. package/src/hooks/useRoutes.ts +24 -4
  222. package/src/hooks/useSettingMonitor.ts +7 -11
  223. package/src/hooks/useTokenAddressBalance.ts +6 -1
  224. package/src/hooks/useTokenBalances.ts +3 -10
  225. package/src/hooks/useTokenSearch.ts +7 -4
  226. package/src/hooks/useTokens.ts +4 -31
  227. package/src/hooks/useTools.ts +2 -2
  228. package/src/i18n/bn.json +5 -2
  229. package/src/i18n/de.json +5 -2
  230. package/src/i18n/en.json +5 -2
  231. package/src/i18n/es.json +5 -2
  232. package/src/i18n/fr.json +5 -2
  233. package/src/i18n/hi.json +5 -2
  234. package/src/i18n/id.json +5 -2
  235. package/src/i18n/it.json +5 -2
  236. package/src/i18n/ja.json +5 -2
  237. package/src/i18n/ko.json +5 -2
  238. package/src/i18n/pl.json +4 -1
  239. package/src/i18n/pt.json +5 -2
  240. package/src/i18n/th.json +5 -2
  241. package/src/i18n/tr.json +5 -2
  242. package/src/i18n/uk.json +5 -2
  243. package/src/i18n/vi.json +5 -2
  244. package/src/i18n/zh.json +5 -2
  245. package/src/pages/SelectEnabledToolsPage.tsx +4 -5
  246. package/src/pages/SelectTokenPage/SearchTokenInput.tsx +19 -7
  247. package/src/pages/SettingsPage/BridgeAndExchangeSettings.tsx +1 -2
  248. package/src/pages/TransactionPage/TransactionPage.tsx +17 -9
  249. package/src/stores/bookmarks/BookmarkStore.tsx +3 -6
  250. package/src/stores/bookmarks/useBookmarkActions.ts +9 -13
  251. package/src/stores/bookmarks/useBookmarks.ts +1 -3
  252. package/src/stores/chains/ChainOrderStore.tsx +26 -8
  253. package/src/stores/chains/createChainOrderStore.ts +19 -1
  254. package/src/stores/chains/types.ts +2 -0
  255. package/src/stores/chains/useChainOrder.ts +1 -5
  256. package/src/stores/form/useFieldActions.ts +10 -14
  257. package/src/stores/form/useFieldValues.ts +1 -3
  258. package/src/stores/form/useFormStore.ts +3 -6
  259. package/src/stores/form/useTouchedFields.ts +1 -2
  260. package/src/stores/form/useValidation.ts +5 -5
  261. package/src/stores/form/useValidationActions.ts +5 -9
  262. package/src/stores/header/useHeaderStore.tsx +5 -14
  263. package/src/stores/inputMode/useInputModeStore.ts +29 -0
  264. package/src/stores/routes/RouteExecutionStore.tsx +3 -3
  265. package/src/stores/routes/useExecutingRoutesIds.ts +14 -17
  266. package/src/stores/settings/useSendToWalletStore.ts +11 -8
  267. package/src/stores/settings/useSettings.ts +8 -11
  268. package/src/stores/settings/useSettingsActions.ts +8 -12
  269. package/src/stores/settings/useSettingsStore.ts +8 -1
  270. package/src/stores/settings/useSplitSubvariantStore.tsx +2 -1
  271. package/src/themes/createTheme.ts +5 -1
  272. package/src/types/widget.ts +2 -0
  273. package/src/utils/format.ts +33 -0
  274. package/src/utils/getPriceImpact.ts +2 -2
@@ -37,7 +37,16 @@ export const NavigationHeader: React.FC = () => {
37
37
  <>
38
38
  <HeaderAppBar elevation={0}>
39
39
  {backButtonRoutes.includes(path) ? (
40
- <BackButton onClick={navigateBack} />
40
+ <BackButton
41
+ onClick={() =>
42
+ navigateBack(
43
+ // From transaction details page, navigate to home page
44
+ path === navigationRoutes.transactionDetails
45
+ ? navigationRoutes.home
46
+ : undefined
47
+ )
48
+ }
49
+ />
41
50
  ) : null}
42
51
  {splitSubvariant ? (
43
52
  <Box
@@ -0,0 +1,35 @@
1
+ import WarningRounded from '@mui/icons-material/WarningRounded'
2
+ import { type BoxProps, Typography } from '@mui/material'
3
+ import { useTranslation } from 'react-i18next'
4
+ import { AlertMessage } from './AlertMessage.js'
5
+
6
+ type MinFromAmountUSDMessageProps = BoxProps & {
7
+ minFromAmountUSD: number
8
+ }
9
+
10
+ export const MinFromAmountUSDMessage: React.FC<
11
+ MinFromAmountUSDMessageProps
12
+ > = ({ minFromAmountUSD, ...props }) => {
13
+ const { t } = useTranslation()
14
+ return (
15
+ <AlertMessage
16
+ severity="warning"
17
+ icon={<WarningRounded />}
18
+ title={
19
+ <Typography
20
+ variant="body2"
21
+ sx={{
22
+ color: 'text.primary',
23
+ }}
24
+ >
25
+ {t('warning.message.minFromAmountUSD', {
26
+ amount: minFromAmountUSD,
27
+ minimumFractionDigits: 0,
28
+ })}
29
+ </Typography>
30
+ }
31
+ multiline
32
+ {...props}
33
+ />
34
+ )
35
+ }
@@ -5,6 +5,7 @@ import { AccountDeployedMessage } from './AccountDeployedMessage.js'
5
5
  import { AccountNotDeployedMessage } from './AccountNotDeployedMessage.js'
6
6
  import { FundsSufficiencyMessage } from './FundsSufficiencyMessage.js'
7
7
  import { GasSufficiencyMessage } from './GasSufficiencyMessage.js'
8
+ import { MinFromAmountUSDMessage } from './MinFromAmountUSDMessage.js'
8
9
  import { MissingRouteRequiredAccountMessage } from './MissingRouteRequiredAccountMessage.js'
9
10
  import { ToAddressRequiredMessage } from './ToAddressRequiredMessage.js'
10
11
  import { useMessageQueue } from './useMessageQueue.js'
@@ -40,6 +41,13 @@ export const WarningMessages: React.FC<WarningMessagesProps> = ({
40
41
  {...props}
41
42
  />
42
43
  )
44
+ case 'MIN_FROM_AMOUNT_USD':
45
+ return (
46
+ <MinFromAmountUSDMessage
47
+ minFromAmountUSD={messages[0].props?.minFromAmountUSD}
48
+ {...props}
49
+ />
50
+ )
43
51
  case 'ACCOUNT_NOT_DEPLOYED':
44
52
  return <AccountNotDeployedMessage {...props} />
45
53
  case 'ACCOUNT_DEPLOYED':
@@ -1,5 +1,6 @@
1
1
  import type { Route } from '@lifi/sdk'
2
2
  import { useMemo } from 'react'
3
+ import { useFromAmountThreshold } from '../../hooks/useFromAmountThreshold.js'
3
4
  import { useFromTokenSufficiency } from '../../hooks/useFromTokenSufficiency.js'
4
5
  import { useGasSufficiency } from '../../hooks/useGasSufficiency.js'
5
6
  import { useRouteRequiredAccountConnection } from '../../hooks/useRouteRequiredAccountConnection.js'
@@ -25,6 +26,7 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => {
25
26
  useGasSufficiency(route)
26
27
  const { missingChain, missingAccountAddress } =
27
28
  useRouteRequiredAccountConnection(route)
29
+ const { belowMinFromAmountUSD, minFromAmountUSD } = useFromAmountThreshold()
28
30
 
29
31
  const messageQueue = useMemo(() => {
30
32
  const queue: QueuedMessage[] = []
@@ -44,10 +46,18 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => {
44
46
  })
45
47
  }
46
48
 
49
+ if (belowMinFromAmountUSD) {
50
+ queue.push({
51
+ id: 'MIN_FROM_AMOUNT_USD',
52
+ priority: 3,
53
+ props: { minFromAmountUSD },
54
+ })
55
+ }
56
+
47
57
  if (insufficientGas?.length) {
48
58
  queue.push({
49
59
  id: 'INSUFFICIENT_GAS',
50
- priority: 3,
60
+ priority: 4,
51
61
  props: { insufficientGas },
52
62
  })
53
63
  }
@@ -55,21 +65,21 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => {
55
65
  if (accountNotDeployedAtDestination && !allowInteraction) {
56
66
  queue.push({
57
67
  id: 'ACCOUNT_NOT_DEPLOYED',
58
- priority: 4,
68
+ priority: 5,
59
69
  })
60
70
  }
61
71
 
62
72
  if (requiredToAddress && !toAddress) {
63
73
  queue.push({
64
74
  id: 'TO_ADDRESS_REQUIRED',
65
- priority: 5,
75
+ priority: 6,
66
76
  })
67
77
  }
68
78
 
69
79
  if (accountDeployedAtDestination && !allowInteraction) {
70
80
  queue.push({
71
81
  id: 'ACCOUNT_DEPLOYED',
72
- priority: 6,
82
+ priority: 7,
73
83
  })
74
84
  }
75
85
 
@@ -84,6 +94,8 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => {
84
94
  toAddress,
85
95
  missingChain,
86
96
  missingAccountAddress,
97
+ belowMinFromAmountUSD,
98
+ minFromAmountUSD,
87
99
  ])
88
100
 
89
101
  return {
@@ -29,6 +29,8 @@ interface RoutesContentProps {
29
29
  refetch: () => void
30
30
  }
31
31
 
32
+ const headerHeight = '64px'
33
+
32
34
  export const RoutesContent = ({
33
35
  routes,
34
36
  isFetching,
@@ -77,7 +79,7 @@ export const RoutesContent = ({
77
79
 
78
80
  return (
79
81
  <Container enableColorScheme minimumHeight={isLoading}>
80
- <Header>
82
+ <Header sx={{ height: headerHeight }}>
81
83
  <Typography
82
84
  noWrap
83
85
  sx={{
@@ -96,7 +98,9 @@ export const RoutesContent = ({
96
98
  sx={{ marginRight: -1 }}
97
99
  />
98
100
  </Header>
99
- <PageContainer>
101
+ <PageContainer
102
+ sx={{ height: `calc(100% - ${headerHeight})`, overflow: 'auto' }}
103
+ >
100
104
  <Stack
101
105
  direction="column"
102
106
  spacing={2}
@@ -12,11 +12,13 @@ export const Container = styled(ScopedCssBaseline, {
12
12
  shouldForwardProp: (prop) => !['minimumHeight'].includes(prop as string),
13
13
  })<ContainerProps>(({ theme, minimumHeight }) => ({
14
14
  backgroundColor: theme.vars.palette.background.default,
15
- overflow: 'auto',
15
+ overflow: 'hidden',
16
16
  width: routesExpansionWidth,
17
17
  display: 'flex',
18
18
  flexDirection: 'column',
19
19
  whiteSpace: 'normal',
20
+ borderRadius: theme.container?.borderRadius ?? 0,
21
+ boxShadow: theme.container?.boxShadow ?? 'none',
20
22
  ...(theme.container?.display !== 'flex'
21
23
  ? {
22
24
  maxHeight:
@@ -26,7 +28,6 @@ export const Container = styled(ScopedCssBaseline, {
26
28
  ...(minimumHeight ? { '&': { height: 'auto' } } : {}),
27
29
  }
28
30
  : { height: minimumHeight ? 'auto' : '100%' }),
29
- ...theme.container,
30
31
  ...theme.routesContainer,
31
32
  }))
32
33
 
@@ -36,7 +36,7 @@ export const SendToWalletButton: React.FC<CardProps> = (props) => {
36
36
  subvariant,
37
37
  subvariantOptions,
38
38
  } = useWidgetConfig()
39
- const { showSendToWallet } = useSendToWalletStore()
39
+ const { showSendToWallet } = useSendToWalletStore((state) => state)
40
40
  const [toAddressFieldValue, toChainId, toTokenAddress] = useFieldValues(
41
41
  'toAddress',
42
42
  'toChain',
@@ -7,7 +7,10 @@ import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.j
7
7
  import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js'
8
8
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
9
9
  import { useFieldValues } from '../../stores/form/useFieldValues.js'
10
- import { useSendToWalletStore } from '../../stores/settings/useSendToWalletStore.js'
10
+ import {
11
+ sendToWalletStore,
12
+ useSendToWalletStore,
13
+ } from '../../stores/settings/useSendToWalletStore.js'
11
14
  import { WidgetEvent } from '../../types/events.js'
12
15
  import { DisabledUI, HiddenUI } from '../../types/widget.js'
13
16
 
@@ -17,7 +20,9 @@ export const SendToWalletExpandButton: React.FC = () => {
17
20
  const { setFieldValue } = useFieldActions()
18
21
  const { setSelectedBookmark } = useBookmarkActions()
19
22
  const emitter = useWidgetEvents()
20
- const { showSendToWallet, setSendToWallet } = useSendToWalletStore()
23
+ const { showSendToWallet, setSendToWallet } = useSendToWalletStore(
24
+ (state) => state
25
+ )
21
26
  const [toAddressFieldValue] = useFieldValues('toAddress')
22
27
  const { requiredToAddress } = useToAddressRequirements()
23
28
 
@@ -33,7 +38,7 @@ export const SendToWalletExpandButton: React.FC = () => {
33
38
  setSendToWallet(!showSendToWallet)
34
39
  emitter.emit(
35
40
  WidgetEvent.SendToWalletToggled,
36
- useSendToWalletStore.getState().showSendToWallet
41
+ sendToWalletStore.getState().showSendToWallet
37
42
  )
38
43
  }
39
44
 
@@ -13,17 +13,12 @@ export const StepProcess: React.FC<{
13
13
  const { title, message } = useProcessMessage(step, process)
14
14
  const { getTransactionLink } = useExplorer()
15
15
 
16
- const transactionLink = process.txHash
16
+ const transactionLink = process.txLink
17
17
  ? getTransactionLink({
18
- txHash: process.txHash,
18
+ txLink: process.txLink,
19
19
  chain: process.chainId,
20
20
  })
21
- : process.txLink
22
- ? getTransactionLink({
23
- txLink: process.txLink,
24
- chain: process.chainId,
25
- })
26
- : undefined
21
+ : undefined
27
22
 
28
23
  return (
29
24
  <Box
@@ -29,8 +29,6 @@ export const TokenDetailsSheet = forwardRef<
29
29
  },
30
30
  close: () => {
31
31
  bottomSheetRef.current?.close()
32
- setTokenAddress(undefined)
33
- setWithoutContractAddress(false)
34
32
  },
35
33
  }),
36
34
  []
@@ -7,7 +7,6 @@ import { useTranslation } from 'react-i18next'
7
7
  import { useAvailableChains } from '../../hooks/useAvailableChains.js'
8
8
  import { useExplorer } from '../../hooks/useExplorer.js'
9
9
  import { useTokenSearch } from '../../hooks/useTokenSearch.js'
10
- import { formatTokenPrice } from '../../utils/format.js'
11
10
  import { shortenAddress } from '../../utils/wallet.js'
12
11
  import { TokenAvatar } from '../Avatar/TokenAvatar.js'
13
12
  import { CardIconButton } from '../Card/CardIconButton.js'
@@ -117,9 +116,9 @@ export const TokenDetailsSheetContent = forwardRef<
117
116
  color: 'text.primary',
118
117
  }}
119
118
  >
120
- {token
119
+ {token?.priceUSD
121
120
  ? t('format.currency', {
122
- value: formatTokenPrice('1', token.priceUSD, token.decimals),
121
+ value: token.priceUSD,
123
122
  })
124
123
  : noDataLabel}
125
124
  </Typography>
@@ -169,6 +168,54 @@ export const TokenDetailsSheetContent = forwardRef<
169
168
  </Box>
170
169
  </MetricWithSkeleton>
171
170
  )}
171
+ <MetricWithSkeleton
172
+ isLoading={isLoading}
173
+ label={t('tokenMetric.marketCap')}
174
+ width={200}
175
+ height={24}
176
+ >
177
+ <Typography
178
+ sx={{
179
+ fontWeight: 700,
180
+ fontSize: '18px',
181
+ lineHeight: '24px',
182
+ color: 'text.primary',
183
+ }}
184
+ >
185
+ {token?.marketCapUSD
186
+ ? t('format.currency', {
187
+ value: token.marketCapUSD,
188
+ notation: 'compact',
189
+ compactDisplay: 'short',
190
+ maximumFractionDigits: 2,
191
+ })
192
+ : noDataLabel}
193
+ </Typography>
194
+ </MetricWithSkeleton>
195
+ <MetricWithSkeleton
196
+ isLoading={isLoading}
197
+ label={t('tokenMetric.volume24h')}
198
+ width={200}
199
+ height={24}
200
+ >
201
+ <Typography
202
+ sx={{
203
+ fontWeight: 700,
204
+ fontSize: '18px',
205
+ lineHeight: '24px',
206
+ color: 'text.primary',
207
+ }}
208
+ >
209
+ {token?.volumeUSD24H
210
+ ? t('format.currency', {
211
+ value: token.volumeUSD24H,
212
+ notation: 'compact',
213
+ compactDisplay: 'short',
214
+ maximumFractionDigits: 2,
215
+ })
216
+ : noDataLabel}
217
+ </Typography>
218
+ </MetricWithSkeleton>
172
219
  </TokenDetailsSheetContainer>
173
220
  )
174
221
  })
@@ -1,3 +1,4 @@
1
+ import type { BaseToken } from '@lifi/sdk'
1
2
  import { useAccount } from '@lifi/wallet-management'
2
3
  import { Box } from '@mui/material'
3
4
  import { type FC, useEffect } from 'react'
@@ -6,10 +7,12 @@ import { useDebouncedWatch } from '../../hooks/useDebouncedWatch.js'
6
7
  import { useTokenBalances } from '../../hooks/useTokenBalances.js'
7
8
  import { useTokenSearch } from '../../hooks/useTokenSearch.js'
8
9
  import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
10
+ import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
9
11
  import { FormKeyHelper } from '../../stores/form/types.js'
10
12
  import { useFieldValues } from '../../stores/form/useFieldValues.js'
11
13
  import { WidgetEvent } from '../../types/events.js'
12
14
  import type { TokenAmount } from '../../types/token.js'
15
+ import { getConfigItemSets, isFormItemAllowed } from '../../utils/item.js'
13
16
  import { TokenNotFound } from './TokenNotFound.js'
14
17
  import type { TokenListProps } from './types.js'
15
18
  import { useTokenSelect } from './useTokenSelect.js'
@@ -32,6 +35,8 @@ export const TokenList: FC<TokenListProps> = ({
32
35
  'tokenSearchFilter'
33
36
  )
34
37
 
38
+ const { tokens: configTokens } = useWidgetConfig()
39
+
35
40
  const { chain: selectedChain, isLoading: isSelectedChainLoading } =
36
41
  useChain(selectedChainId)
37
42
  const { account } = useAccount({
@@ -45,12 +50,30 @@ export const TokenList: FC<TokenListProps> = ({
45
50
  isBalanceLoading,
46
51
  featuredTokens,
47
52
  popularTokens,
48
- } = useTokenBalances(selectedChainId, formType)
53
+ } = useTokenBalances(selectedChainId)
49
54
 
50
55
  let filteredTokens = (tokensWithBalance ?? chainTokens ?? []) as TokenAmount[]
51
56
  const normalizedSearchFilter = tokenSearchFilter?.replaceAll('$', '')
52
57
  const searchFilter = normalizedSearchFilter?.toUpperCase() ?? ''
53
58
 
59
+ const filteredConfigTokens = getConfigItemSets(
60
+ configTokens,
61
+ (tokens: BaseToken[]) =>
62
+ new Set(
63
+ tokens
64
+ .filter((t) => t.chainId === selectedChainId)
65
+ .map((t) => t.address)
66
+ ),
67
+ formType
68
+ )
69
+
70
+ // Get the appropriate allow/deny lists based on formType
71
+ filteredTokens = filteredTokens.filter(
72
+ (token) =>
73
+ token.chainId === selectedChainId &&
74
+ isFormItemAllowed(token, filteredConfigTokens, formType, (t) => t.address)
75
+ )
76
+
54
77
  filteredTokens = tokenSearchFilter
55
78
  ? filteredTokens
56
79
  .filter(
@@ -12,6 +12,7 @@ import {
12
12
  import type { MouseEventHandler } from 'react'
13
13
  import { memo, useRef, useState } from 'react'
14
14
  import { useTranslation } from 'react-i18next'
15
+ import { useLongPress } from '../../hooks/useLongPress.js'
15
16
  import { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'
16
17
  import { shortenAddress } from '../../utils/wallet.js'
17
18
  import { ListItemButton } from '../ListItem/ListItemButton.js'
@@ -147,11 +148,16 @@ export const TokenListItemButton: React.FC<TokenListItemButtonProps> = ({
147
148
  token.decimals
148
149
  )
149
150
 
151
+ const longPressEvents = useLongPress(() =>
152
+ onShowTokenDetails(token.address, withoutContractAddress)
153
+ )
154
+
150
155
  return (
151
156
  <ListItemButton
152
157
  onClick={onClick}
153
158
  onMouseEnter={onMouseEnter}
154
159
  onMouseLeave={onMouseLeave}
160
+ {...longPressEvents}
155
161
  dense
156
162
  selected={selected}
157
163
  sx={{
@@ -6,7 +6,6 @@ import { useChainOrderStoreContext } from '../../stores/chains/ChainOrderStore.j
6
6
  import type { FormType } from '../../stores/form/types.js'
7
7
  import { FormKeyHelper } from '../../stores/form/types.js'
8
8
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
9
- import { useFieldController } from '../../stores/form/useFieldController.js'
10
9
  import { WidgetEvent } from '../../types/events.js'
11
10
  import type { DisabledUI } from '../../types/widget.js'
12
11
 
@@ -23,11 +22,10 @@ export const useTokenSelect = (formType: FormType, onClick?: () => void) => {
23
22
  const chainOrderStore = useChainOrderStoreContext()
24
23
 
25
24
  const tokenKey = FormKeyHelper.getTokenKey(formType)
26
- const { onChange } = useFieldController({ name: tokenKey })
27
25
 
28
26
  return useCallback(
29
27
  (tokenAddress: string, chainId?: number) => {
30
- onChange(tokenAddress)
28
+ setFieldValue(tokenKey, tokenAddress, { isDirty: true, isTouched: true })
31
29
  const selectedChainId =
32
30
  chainId ?? getFieldValues(FormKeyHelper.getChainKey(formType))[0]
33
31
  // Set chain again to trigger URL builder update
@@ -105,10 +103,10 @@ export const useTokenSelect = (formType: FormType, onClick?: () => void) => {
105
103
  emitter,
106
104
  formType,
107
105
  getFieldValues,
108
- onChange,
109
106
  onClick,
110
107
  setFieldValue,
111
108
  subvariant,
109
+ tokenKey,
112
110
  ]
113
111
  )
114
112
  }
@@ -1,2 +1,2 @@
1
1
  export const name = '@lifi/widget'
2
- export const version = '3.25.0-beta.5'
2
+ export const version = '3.26.0'
@@ -0,0 +1,35 @@
1
+ import { useMemo } from 'react'
2
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider'
3
+ import { FormKeyHelper } from '../stores/form/types'
4
+ import { useFieldValues } from '../stores/form/useFieldValues'
5
+ import { formatTokenPrice } from '../utils/format'
6
+ import { useToken } from './useToken'
7
+
8
+ export const useFromAmountThreshold = () => {
9
+ const { minFromAmountUSD } = useWidgetConfig()
10
+
11
+ const [chainId, tokenAddress, fromAmount] = useFieldValues(
12
+ FormKeyHelper.getChainKey('from'),
13
+ FormKeyHelper.getTokenKey('from'),
14
+ FormKeyHelper.getAmountKey('from')
15
+ )
16
+ const { token } = useToken(chainId, tokenAddress)
17
+
18
+ const belowMinFromAmountUSD = useMemo(() => {
19
+ const fromAmountUSD = formatTokenPrice(
20
+ fromAmount,
21
+ token?.priceUSD,
22
+ token?.decimals
23
+ )
24
+
25
+ if (!minFromAmountUSD || !fromAmountUSD) {
26
+ return false
27
+ }
28
+ return fromAmountUSD < minFromAmountUSD
29
+ }, [minFromAmountUSD, fromAmount, token?.priceUSD, token?.decimals])
30
+
31
+ return {
32
+ belowMinFromAmountUSD,
33
+ minFromAmountUSD,
34
+ }
35
+ }
@@ -57,7 +57,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
57
57
  EVMAccount.chainType
58
58
  )
59
59
 
60
- const { data: insufficientGas, isLoading } = useQuery({
60
+ const { data: insufficientGas, isLoading } = useQuery<GasSufficiency[]>({
61
61
  queryKey: [
62
62
  getQueryKey('gas-sufficiency-check', keyPrefix),
63
63
  relevantAccountsQueryKey,
@@ -66,7 +66,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
66
66
  ] as const,
67
67
  queryFn: async () => {
68
68
  if (!route) {
69
- return
69
+ return []
70
70
  }
71
71
 
72
72
  // Filter out steps that are relayer steps or have primaryType 'Permit' or 'Order'
@@ -80,7 +80,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
80
80
 
81
81
  // If all steps are filtered out, we don't need to check for gas sufficiency
82
82
  if (!filteredSteps.length) {
83
- return
83
+ return []
84
84
  }
85
85
 
86
86
  // We assume that LI.Fuel protocol always refuels the destination chain
@@ -163,7 +163,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
163
163
  .flatMap((result) => result.value)
164
164
 
165
165
  if (!tokenBalances?.length) {
166
- return
166
+ return []
167
167
  }
168
168
 
169
169
  Object.keys(gasCosts).forEach((chainId) => {
@@ -0,0 +1,51 @@
1
+ import { useCallback, useRef } from 'react'
2
+
3
+ export const useLongPress = (callback = () => {}, ms = 500) => {
4
+ const timerRef = useRef<NodeJS.Timeout | null>(null)
5
+ const isPressedRef = useRef(false)
6
+ const startPosRef = useRef<{ x: number; y: number } | null>(null)
7
+
8
+ const start = useCallback(
9
+ (e: React.PointerEvent) => {
10
+ isPressedRef.current = true
11
+ startPosRef.current = { x: e.clientX, y: e.clientY }
12
+ timerRef.current = setTimeout(() => {
13
+ if (isPressedRef.current) {
14
+ callback()
15
+ }
16
+ }, ms)
17
+ },
18
+ [callback, ms]
19
+ )
20
+
21
+ const clear = useCallback(() => {
22
+ isPressedRef.current = false
23
+ startPosRef.current = null
24
+ if (timerRef.current) {
25
+ clearTimeout(timerRef.current)
26
+ }
27
+ }, [])
28
+
29
+ // Based on https://github.com/minwork/react/tree/main/packages/use-long-press
30
+ const move = useCallback(
31
+ (e: React.PointerEvent) => {
32
+ if (isPressedRef.current && startPosRef.current) {
33
+ const dx = Math.abs(e.clientX - startPosRef.current.x)
34
+ const dy = Math.abs(e.clientY - startPosRef.current.y)
35
+ const limit = 25
36
+ if (dx > limit || dy > limit) {
37
+ clear() // cancel on movement
38
+ }
39
+ }
40
+ },
41
+ [clear]
42
+ )
43
+
44
+ return {
45
+ onPointerDown: start,
46
+ onPointerUp: clear,
47
+ onPointerLeave: clear,
48
+ onPointerCancel: clear,
49
+ onPointerMove: move,
50
+ }
51
+ }
@@ -4,23 +4,32 @@ import { useNavigate } from 'react-router-dom'
4
4
  export const useNavigateBack = () => {
5
5
  const navigate = useNavigate()
6
6
 
7
- const navigateBack = useCallback(() => {
8
- // TODO: find a better router with nested memory routers support
9
- // https://github.com/remix-run/react-router/pull/9112
10
- // https://github.com/remix-run/react-router/discussions/9601
11
- //
12
- // if (window.history.length > 2) {
13
- navigate(-1)
14
- // } else {
15
- // navigate(
16
- // window.location.pathname.substring(
17
- // 0,
18
- // window.location.pathname.lastIndexOf('/'),
19
- // ) || '/',
20
- // { replace: true },
21
- // );
22
- // }
23
- }, [navigate])
7
+ const navigateBack = useCallback(
8
+ (toPathname?: string) => {
9
+ // TODO: find a better router with nested memory routers support
10
+ // https://github.com/remix-run/react-router/pull/9112
11
+ // https://github.com/remix-run/react-router/discussions/9601
12
+ //
13
+ // if (window.history.length > 2) {
14
+ // navigate(-1)
15
+ // } else {
16
+ // navigate(
17
+ // window.location.pathname.substring(
18
+ // 0,
19
+ // window.location.pathname.lastIndexOf('/'),
20
+ // ) || '/',
21
+ // { replace: true },
22
+ // );
23
+ // }
24
+
25
+ if (toPathname) {
26
+ navigate(toPathname)
27
+ } else {
28
+ navigate(-1)
29
+ }
30
+ },
31
+ [navigate]
32
+ )
24
33
 
25
34
  return { navigateBack, navigate }
26
35
  }
@@ -3,7 +3,6 @@ import { executeRoute, resumeRoute, updateRouteExecution } from '@lifi/sdk'
3
3
  import { useAccount } from '@lifi/wallet-management'
4
4
  import { useMutation, useQueryClient } from '@tanstack/react-query'
5
5
  import { useCallback, useEffect, useRef } from 'react'
6
- import { shallow } from 'zustand/shallow'
7
6
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
8
7
  import {
9
8
  useRouteExecutionStore,
@@ -43,8 +42,7 @@ export const useRouteExecution = ({
43
42
  (state) => state.routes[routeId]
44
43
  )
45
44
  const [updateRoute, restartRoute, deleteRoute] = useRouteExecutionStore(
46
- (state) => [state.updateRoute, state.restartRoute, state.deleteRoute],
47
- shallow
45
+ (state) => [state.updateRoute, state.restartRoute, state.deleteRoute]
48
46
  )
49
47
 
50
48
  const updateRouteHook = (updatedRoute: Route) => {