@lifi/widget 4.6.0 → 4.7.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 (394) hide show
  1. package/README.md +26 -3
  2. package/dist/esm/App.d.ts +1 -2
  3. package/dist/esm/App.d.ts.map +1 -1
  4. package/dist/esm/AppDrawer.d.ts +1 -2
  5. package/dist/esm/AppDrawer.d.ts.map +1 -1
  6. package/dist/esm/components/ActionRow/ActionRow.d.ts +1 -2
  7. package/dist/esm/components/ActionRow/ActionRow.d.ts.map +1 -1
  8. package/dist/esm/components/AmountInput/AmountInput.style.d.ts +2 -2
  9. package/dist/esm/components/AmountInput/AmountInput.style.d.ts.map +1 -1
  10. package/dist/esm/components/AmountInput/AmountInputEndAdornment.d.ts +1 -2
  11. package/dist/esm/components/AmountInput/AmountInputEndAdornment.d.ts.map +1 -1
  12. package/dist/esm/components/AmountInput/PriceFormHelperText.style.d.ts +1 -2
  13. package/dist/esm/components/AmountInput/PriceFormHelperText.style.d.ts.map +1 -1
  14. package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js +6 -2
  15. package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js.map +1 -1
  16. package/dist/esm/components/Avatar/Avatar.d.ts +1 -2
  17. package/dist/esm/components/Avatar/Avatar.d.ts.map +1 -1
  18. package/dist/esm/components/Avatar/TokenAvatar.d.ts +1 -2
  19. package/dist/esm/components/Avatar/TokenAvatar.d.ts.map +1 -1
  20. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.d.ts +1 -2
  21. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.d.ts.map +1 -1
  22. package/dist/esm/components/BaseTransactionButton/types.d.ts +1 -2
  23. package/dist/esm/components/BaseTransactionButton/types.d.ts.map +1 -1
  24. package/dist/esm/components/BottomSheet/BottomSheet.js +1 -0
  25. package/dist/esm/components/BottomSheet/BottomSheet.js.map +1 -1
  26. package/dist/esm/components/BottomSheet/types.d.ts +1 -2
  27. package/dist/esm/components/BottomSheet/types.d.ts.map +1 -1
  28. package/dist/esm/components/ButtonTertiary.d.ts +1 -2
  29. package/dist/esm/components/ButtonTertiary.d.ts.map +1 -1
  30. package/dist/esm/components/Card/CardIconButton.d.ts +1 -2
  31. package/dist/esm/components/Card/CardIconButton.d.ts.map +1 -1
  32. package/dist/esm/components/Card/CardTitle.d.ts +1 -2
  33. package/dist/esm/components/Card/CardTitle.d.ts.map +1 -1
  34. package/dist/esm/components/Card/InputCard.d.ts +1 -2
  35. package/dist/esm/components/Card/InputCard.d.ts.map +1 -1
  36. package/dist/esm/components/ChainSelect/ChainSelect.d.ts +1 -2
  37. package/dist/esm/components/ChainSelect/ChainSelect.d.ts.map +1 -1
  38. package/dist/esm/components/ChainSelect/ChainSelect.style.d.ts +1 -2
  39. package/dist/esm/components/ChainSelect/ChainSelect.style.d.ts.map +1 -1
  40. package/dist/esm/components/ContractComponent/ContractComponent.d.ts +1 -2
  41. package/dist/esm/components/ContractComponent/ContractComponent.d.ts.map +1 -1
  42. package/dist/esm/components/ContractComponent/ItemPrice.d.ts +2 -3
  43. package/dist/esm/components/ContractComponent/ItemPrice.d.ts.map +1 -1
  44. package/dist/esm/components/ContractComponent/NFT/NFT.d.ts +1 -2
  45. package/dist/esm/components/ContractComponent/NFT/NFT.d.ts.map +1 -1
  46. package/dist/esm/components/ContractComponent/NFT/NFTBase.d.ts +1 -2
  47. package/dist/esm/components/ContractComponent/NFT/NFTBase.d.ts.map +1 -1
  48. package/dist/esm/components/ContractComponent/NFT/types.d.ts +3 -4
  49. package/dist/esm/components/ContractComponent/NFT/types.d.ts.map +1 -1
  50. package/dist/esm/components/ExecutionStatusCard/ExecutionStatusCard.d.ts +1 -2
  51. package/dist/esm/components/ExecutionStatusCard/ExecutionStatusCard.d.ts.map +1 -1
  52. package/dist/esm/components/ExecutionStatusCard/StatusIcon.d.ts +1 -2
  53. package/dist/esm/components/ExecutionStatusCard/StatusIcon.d.ts.map +1 -1
  54. package/dist/esm/components/FeeBreakdownTooltip.d.ts +1 -2
  55. package/dist/esm/components/FeeBreakdownTooltip.d.ts.map +1 -1
  56. package/dist/esm/components/IconCircle/IconCircle.d.ts +1 -2
  57. package/dist/esm/components/IconCircle/IconCircle.d.ts.map +1 -1
  58. package/dist/esm/components/IconCircle/statusIcons.d.ts +1 -2
  59. package/dist/esm/components/IconCircle/statusIcons.d.ts.map +1 -1
  60. package/dist/esm/components/IconTypography.d.ts +1 -2
  61. package/dist/esm/components/IconTypography.d.ts.map +1 -1
  62. package/dist/esm/components/ListItem/ListItemButton.d.ts +1 -2
  63. package/dist/esm/components/ListItem/ListItemButton.d.ts.map +1 -1
  64. package/dist/esm/components/Messages/WarningMessages.d.ts +1 -2
  65. package/dist/esm/components/Messages/WarningMessages.d.ts.map +1 -1
  66. package/dist/esm/components/PageContainer.d.ts +2 -3
  67. package/dist/esm/components/PageContainer.d.ts.map +1 -1
  68. package/dist/esm/components/PoweredBy/PoweredBy.d.ts +1 -2
  69. package/dist/esm/components/PoweredBy/PoweredBy.d.ts.map +1 -1
  70. package/dist/esm/components/ProgressToNextUpdate.d.ts +1 -2
  71. package/dist/esm/components/ProgressToNextUpdate.d.ts.map +1 -1
  72. package/dist/esm/components/RouteCard/RouteCard.d.ts +1 -2
  73. package/dist/esm/components/RouteCard/RouteCard.d.ts.map +1 -1
  74. package/dist/esm/components/RouteCard/RouteCardSkeleton.d.ts +1 -2
  75. package/dist/esm/components/RouteCard/RouteCardSkeleton.d.ts.map +1 -1
  76. package/dist/esm/components/RouteCard/RouteDetails.d.ts +1 -2
  77. package/dist/esm/components/RouteCard/RouteDetails.d.ts.map +1 -1
  78. package/dist/esm/components/RouteCard/RouteDetails.style.d.ts +5 -6
  79. package/dist/esm/components/RouteCard/RouteDetails.style.d.ts.map +1 -1
  80. package/dist/esm/components/RouteCard/RouteNotFoundCard.d.ts +1 -2
  81. package/dist/esm/components/RouteCard/RouteNotFoundCard.d.ts.map +1 -1
  82. package/dist/esm/components/RouteCard/RouteTokens.d.ts +1 -2
  83. package/dist/esm/components/RouteCard/RouteTokens.d.ts.map +1 -1
  84. package/dist/esm/components/RouteCard/types.d.ts +2 -3
  85. package/dist/esm/components/RouteCard/types.d.ts.map +1 -1
  86. package/dist/esm/components/Search/SearchInput.d.ts +1 -2
  87. package/dist/esm/components/Search/SearchInput.d.ts.map +1 -1
  88. package/dist/esm/components/SendToWallet/SendToWalletButton.d.ts +1 -2
  89. package/dist/esm/components/SendToWallet/SendToWalletButton.d.ts.map +1 -1
  90. package/dist/esm/components/Skeleton/WidgetSkeleton.d.ts +1 -2
  91. package/dist/esm/components/Skeleton/WidgetSkeleton.d.ts.map +1 -1
  92. package/dist/esm/components/StepActions/SentToWalletRow.d.ts +1 -2
  93. package/dist/esm/components/StepActions/SentToWalletRow.d.ts.map +1 -1
  94. package/dist/esm/components/StepActions/StepActionRow.style.d.ts +1 -2
  95. package/dist/esm/components/StepActions/StepActionRow.style.d.ts.map +1 -1
  96. package/dist/esm/components/StepActions/StepActionsList.d.ts +1 -2
  97. package/dist/esm/components/StepActions/StepActionsList.d.ts.map +1 -1
  98. package/dist/esm/components/StepActions/executionRows.d.ts +2 -3
  99. package/dist/esm/components/StepActions/executionRows.d.ts.map +1 -1
  100. package/dist/esm/components/Token/Token.d.ts.map +1 -1
  101. package/dist/esm/components/Token/Token.js +2 -4
  102. package/dist/esm/components/Token/Token.js.map +1 -1
  103. package/dist/esm/components/TokenList/RecentTokensHeader.js +44 -0
  104. package/dist/esm/components/TokenList/RecentTokensHeader.js.map +1 -0
  105. package/dist/esm/components/TokenList/RecentTokensToggle.js +36 -0
  106. package/dist/esm/components/TokenList/RecentTokensToggle.js.map +1 -0
  107. package/dist/esm/components/TokenList/RemoveRecentTokenButton.js +32 -0
  108. package/dist/esm/components/TokenList/RemoveRecentTokenButton.js.map +1 -0
  109. package/dist/esm/components/TokenList/TokenList.js +55 -5
  110. package/dist/esm/components/TokenList/TokenList.js.map +1 -1
  111. package/dist/esm/components/TokenList/TokenListItem.js +35 -19
  112. package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
  113. package/dist/esm/components/TokenList/TokenNotFound.d.ts +1 -2
  114. package/dist/esm/components/TokenList/TokenNotFound.d.ts.map +1 -1
  115. package/dist/esm/components/TokenList/VirtualizedTokenList.d.ts +1 -2
  116. package/dist/esm/components/TokenList/VirtualizedTokenList.d.ts.map +1 -1
  117. package/dist/esm/components/TokenList/VirtualizedTokenList.js +55 -42
  118. package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
  119. package/dist/esm/components/TokenList/types.d.ts +9 -2
  120. package/dist/esm/components/TokenList/types.d.ts.map +1 -1
  121. package/dist/esm/components/TokenList/useTokenSelect.d.ts +1 -2
  122. package/dist/esm/components/TokenList/useTokenSelect.d.ts.map +1 -1
  123. package/dist/esm/components/TokenRate/TokenRate.d.ts +1 -2
  124. package/dist/esm/components/TokenRate/TokenRate.d.ts.map +1 -1
  125. package/dist/esm/components/TransactionCard/TransactionCard.style.d.ts +2 -3
  126. package/dist/esm/components/TransactionCard/TransactionCard.style.d.ts.map +1 -1
  127. package/dist/esm/config/constants.d.ts +1 -2
  128. package/dist/esm/config/constants.d.ts.map +1 -1
  129. package/dist/esm/config/version.d.ts +2 -3
  130. package/dist/esm/config/version.d.ts.map +1 -1
  131. package/dist/esm/config/version.js +1 -1
  132. package/dist/esm/config/version.js.map +1 -1
  133. package/dist/esm/hooks/useAddressActivity.d.ts +1 -2
  134. package/dist/esm/hooks/useAddressActivity.d.ts.map +1 -1
  135. package/dist/esm/hooks/useAddressValidation.d.ts +2 -3
  136. package/dist/esm/hooks/useAddressValidation.d.ts.map +1 -1
  137. package/dist/esm/hooks/useAvailableChains.d.ts +1 -2
  138. package/dist/esm/hooks/useAvailableChains.d.ts.map +1 -1
  139. package/dist/esm/hooks/useChain.d.ts +1 -2
  140. package/dist/esm/hooks/useChain.d.ts.map +1 -1
  141. package/dist/esm/hooks/useContactSupport.d.ts +1 -2
  142. package/dist/esm/hooks/useContactSupport.d.ts.map +1 -1
  143. package/dist/esm/hooks/useDebouncedWatch.d.ts +1 -2
  144. package/dist/esm/hooks/useDebouncedWatch.d.ts.map +1 -1
  145. package/dist/esm/hooks/useDisplayedTokens.js +6 -4
  146. package/dist/esm/hooks/useDisplayedTokens.js.map +1 -1
  147. package/dist/esm/hooks/useExplorer.d.ts +1 -2
  148. package/dist/esm/hooks/useExplorer.d.ts.map +1 -1
  149. package/dist/esm/hooks/useHeader.d.ts +1 -2
  150. package/dist/esm/hooks/useHeader.d.ts.map +1 -1
  151. package/dist/esm/hooks/useListHeight.d.ts +1 -2
  152. package/dist/esm/hooks/useListHeight.d.ts.map +1 -1
  153. package/dist/esm/hooks/useNavigateBack.d.ts +1 -2
  154. package/dist/esm/hooks/useNavigateBack.d.ts.map +1 -1
  155. package/dist/esm/hooks/useRecentTokens.js +46 -0
  156. package/dist/esm/hooks/useRecentTokens.js.map +1 -0
  157. package/dist/esm/hooks/useRouteExecution.d.ts +1 -2
  158. package/dist/esm/hooks/useRouteExecution.d.ts.map +1 -1
  159. package/dist/esm/hooks/useRouteExecutionMessage.d.ts +1 -2
  160. package/dist/esm/hooks/useRouteExecutionMessage.d.ts.map +1 -1
  161. package/dist/esm/hooks/useRoutes.d.ts +1 -2
  162. package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
  163. package/dist/esm/hooks/useRoutes.js +7 -2
  164. package/dist/esm/hooks/useRoutes.js.map +1 -1
  165. package/dist/esm/hooks/useToAddressRequirements.d.ts +1 -2
  166. package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
  167. package/dist/esm/hooks/useToAddressRequirements.js +8 -2
  168. package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
  169. package/dist/esm/hooks/useToken.d.ts +1 -2
  170. package/dist/esm/hooks/useToken.d.ts.map +1 -1
  171. package/dist/esm/hooks/useTokenAddressBalance.d.ts +1 -2
  172. package/dist/esm/hooks/useTokenAddressBalance.d.ts.map +1 -1
  173. package/dist/esm/hooks/useTokenBalances.d.ts +3 -2
  174. package/dist/esm/hooks/useTokenBalances.d.ts.map +1 -1
  175. package/dist/esm/hooks/useTokenBalances.js +15 -9
  176. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  177. package/dist/esm/hooks/useTokenList.d.ts +1 -2
  178. package/dist/esm/hooks/useTokenList.d.ts.map +1 -1
  179. package/dist/esm/hooks/useTokenSearch.js +3 -2
  180. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  181. package/dist/esm/hooks/useTokens.js +26 -15
  182. package/dist/esm/hooks/useTokens.js.map +1 -1
  183. package/dist/esm/hooks/useTools.d.ts +1 -2
  184. package/dist/esm/hooks/useTools.d.ts.map +1 -1
  185. package/dist/esm/hooks/useWidgetChains.d.ts +1 -2
  186. package/dist/esm/hooks/useWidgetChains.d.ts.map +1 -1
  187. package/dist/esm/hooks/useWidgetEvents.d.ts +3 -4
  188. package/dist/esm/hooks/useWidgetEvents.d.ts.map +1 -1
  189. package/dist/esm/i18n/bn.json +4 -0
  190. package/dist/esm/i18n/de.json +4 -0
  191. package/dist/esm/i18n/en.json +4 -0
  192. package/dist/esm/i18n/es.json +4 -0
  193. package/dist/esm/i18n/fr.json +4 -0
  194. package/dist/esm/i18n/hi.json +4 -0
  195. package/dist/esm/i18n/id.json +4 -0
  196. package/dist/esm/i18n/it.json +4 -0
  197. package/dist/esm/i18n/ja.json +4 -0
  198. package/dist/esm/i18n/ko.json +4 -0
  199. package/dist/esm/i18n/pl.json +4 -0
  200. package/dist/esm/i18n/pt.json +4 -0
  201. package/dist/esm/i18n/th.json +4 -0
  202. package/dist/esm/i18n/tr.json +4 -0
  203. package/dist/esm/i18n/uk.json +4 -0
  204. package/dist/esm/i18n/vi.json +4 -0
  205. package/dist/esm/i18n/zh.json +4 -0
  206. package/dist/esm/pages/MainPage/MainWarningMessages.d.ts +1 -2
  207. package/dist/esm/pages/MainPage/MainWarningMessages.d.ts.map +1 -1
  208. package/dist/esm/pages/SelectChainPage/SelectChainPage.d.ts +1 -2
  209. package/dist/esm/pages/SelectChainPage/SelectChainPage.d.ts.map +1 -1
  210. package/dist/esm/pages/SelectChainPage/types.d.ts +1 -2
  211. package/dist/esm/pages/SelectChainPage/types.d.ts.map +1 -1
  212. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.d.ts +1 -2
  213. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.d.ts.map +1 -1
  214. package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.d.ts +1 -2
  215. package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.d.ts.map +1 -1
  216. package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.d.ts +1 -2
  217. package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.d.ts.map +1 -1
  218. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.d.ts +2 -3
  219. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.d.ts.map +1 -1
  220. package/dist/esm/pages/TransactionPage/ExecutionDoneCard.d.ts +1 -2
  221. package/dist/esm/pages/TransactionPage/ExecutionDoneCard.d.ts.map +1 -1
  222. package/dist/esm/pages/TransactionPage/RouteTracker.d.ts +1 -2
  223. package/dist/esm/pages/TransactionPage/RouteTracker.d.ts.map +1 -1
  224. package/dist/esm/pages/TransactionPage/StartTransactionButton.d.ts +1 -2
  225. package/dist/esm/pages/TransactionPage/StartTransactionButton.d.ts.map +1 -1
  226. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.d.ts +1 -2
  227. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.d.ts.map +1 -1
  228. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js +0 -1
  229. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
  230. package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js +0 -1
  231. package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js.map +1 -1
  232. package/dist/esm/pages/TransactionPage/TransactionDoneButtons.d.ts +1 -2
  233. package/dist/esm/pages/TransactionPage/TransactionDoneButtons.d.ts.map +1 -1
  234. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js +38 -12
  235. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js.map +1 -1
  236. package/dist/esm/pages/TransactionPage/TransactionReview.js +22 -21
  237. package/dist/esm/pages/TransactionPage/TransactionReview.js.map +1 -1
  238. package/dist/esm/pages/TransactionPage/types.d.ts +1 -2
  239. package/dist/esm/pages/TransactionPage/types.d.ts.map +1 -1
  240. package/dist/esm/pages/TransactionPage/utils.d.ts +2 -3
  241. package/dist/esm/pages/TransactionPage/utils.d.ts.map +1 -1
  242. package/dist/esm/pages/TransactionPage/utils.js +23 -1
  243. package/dist/esm/pages/TransactionPage/utils.js.map +1 -1
  244. package/dist/esm/providers/I18nProvider/I18nProvider.d.ts +1 -2
  245. package/dist/esm/providers/I18nProvider/I18nProvider.d.ts.map +1 -1
  246. package/dist/esm/providers/I18nProvider/types.d.ts +4 -5
  247. package/dist/esm/providers/I18nProvider/types.d.ts.map +1 -1
  248. package/dist/esm/providers/QueryClientProvider.d.ts +1 -2
  249. package/dist/esm/providers/QueryClientProvider.d.ts.map +1 -1
  250. package/dist/esm/providers/SDKClientProvider.d.ts +2 -3
  251. package/dist/esm/providers/SDKClientProvider.d.ts.map +1 -1
  252. package/dist/esm/providers/WalletProvider/WalletProvider.d.ts +1 -2
  253. package/dist/esm/providers/WalletProvider/WalletProvider.d.ts.map +1 -1
  254. package/dist/esm/providers/WidgetProvider/WidgetProvider.d.ts +2 -3
  255. package/dist/esm/providers/WidgetProvider/WidgetProvider.d.ts.map +1 -1
  256. package/dist/esm/providers/WidgetProvider/types.d.ts +2 -3
  257. package/dist/esm/providers/WidgetProvider/types.d.ts.map +1 -1
  258. package/dist/esm/stores/StoreProvider.d.ts +1 -2
  259. package/dist/esm/stores/StoreProvider.d.ts.map +1 -1
  260. package/dist/esm/stores/StoreProvider.js +10 -6
  261. package/dist/esm/stores/StoreProvider.js.map +1 -1
  262. package/dist/esm/stores/bookmarks/BookmarkStore.d.ts +1 -2
  263. package/dist/esm/stores/bookmarks/BookmarkStore.d.ts.map +1 -1
  264. package/dist/esm/stores/bookmarks/types.d.ts +5 -6
  265. package/dist/esm/stores/bookmarks/types.d.ts.map +1 -1
  266. package/dist/esm/stores/chains/ChainOrderStore.d.ts +1 -2
  267. package/dist/esm/stores/chains/ChainOrderStore.d.ts.map +1 -1
  268. package/dist/esm/stores/chains/ChainOrderStore.js +11 -5
  269. package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
  270. package/dist/esm/stores/chains/types.d.ts +1 -2
  271. package/dist/esm/stores/chains/types.d.ts.map +1 -1
  272. package/dist/esm/stores/form/types.d.ts +20 -21
  273. package/dist/esm/stores/form/types.d.ts.map +1 -1
  274. package/dist/esm/stores/form/useFieldActions.d.ts +1 -2
  275. package/dist/esm/stores/form/useFieldActions.d.ts.map +1 -1
  276. package/dist/esm/stores/form/useFieldValues.d.ts +1 -2
  277. package/dist/esm/stores/form/useFieldValues.d.ts.map +1 -1
  278. package/dist/esm/stores/header/types.d.ts +1 -2
  279. package/dist/esm/stores/header/types.d.ts.map +1 -1
  280. package/dist/esm/stores/header/useHeaderStore.d.ts +2 -3
  281. package/dist/esm/stores/header/useHeaderStore.d.ts.map +1 -1
  282. package/dist/esm/stores/inputMode/useInputModeStore.d.ts +1 -2
  283. package/dist/esm/stores/inputMode/useInputModeStore.d.ts.map +1 -1
  284. package/dist/esm/stores/recentTokens/RecentTokensStore.js +23 -0
  285. package/dist/esm/stores/recentTokens/RecentTokensStore.js.map +1 -0
  286. package/dist/esm/stores/recentTokens/createRecentTokensStore.js +54 -0
  287. package/dist/esm/stores/recentTokens/createRecentTokensStore.js.map +1 -0
  288. package/dist/esm/stores/recentTokens/utils.js +15 -0
  289. package/dist/esm/stores/recentTokens/utils.js.map +1 -0
  290. package/dist/esm/stores/routes/RouteExecutionStore.d.ts +2 -3
  291. package/dist/esm/stores/routes/RouteExecutionStore.d.ts.map +1 -1
  292. package/dist/esm/stores/routes/types.d.ts +3 -4
  293. package/dist/esm/stores/routes/types.d.ts.map +1 -1
  294. package/dist/esm/stores/routes/utils.d.ts +4 -5
  295. package/dist/esm/stores/routes/utils.d.ts.map +1 -1
  296. package/dist/esm/stores/settings/SettingsStore.d.ts +2 -3
  297. package/dist/esm/stores/settings/SettingsStore.d.ts.map +1 -1
  298. package/dist/esm/stores/settings/types.d.ts +2 -3
  299. package/dist/esm/stores/settings/types.d.ts.map +1 -1
  300. package/dist/esm/stores/types.d.ts +2 -3
  301. package/dist/esm/stores/types.d.ts.map +1 -1
  302. package/dist/esm/themes/azureLight.d.ts +1 -2
  303. package/dist/esm/themes/azureLight.d.ts.map +1 -1
  304. package/dist/esm/themes/jumper.d.ts +1 -2
  305. package/dist/esm/themes/jumper.d.ts.map +1 -1
  306. package/dist/esm/themes/palettes.d.ts +3 -4
  307. package/dist/esm/themes/palettes.d.ts.map +1 -1
  308. package/dist/esm/themes/types.d.ts +1 -0
  309. package/dist/esm/themes/watermelonLight.d.ts +1 -2
  310. package/dist/esm/themes/watermelonLight.d.ts.map +1 -1
  311. package/dist/esm/themes/windows95.d.ts +1 -2
  312. package/dist/esm/themes/windows95.d.ts.map +1 -1
  313. package/dist/esm/types/events.d.ts +13 -14
  314. package/dist/esm/types/events.d.ts.map +1 -1
  315. package/dist/esm/types/token.d.ts +4 -2
  316. package/dist/esm/types/token.d.ts.map +1 -1
  317. package/dist/esm/types/widget.d.ts +55 -51
  318. package/dist/esm/types/widget.d.ts.map +1 -1
  319. package/dist/esm/types/widget.js.map +1 -1
  320. package/dist/esm/utils/address.js +19 -0
  321. package/dist/esm/utils/address.js.map +1 -0
  322. package/dist/esm/utils/compactNumberFormatter.d.ts +1 -2
  323. package/dist/esm/utils/compactNumberFormatter.d.ts.map +1 -1
  324. package/dist/esm/utils/converters.d.ts +1 -2
  325. package/dist/esm/utils/converters.d.ts.map +1 -1
  326. package/dist/esm/utils/currencyExtendedFormatter.d.ts +1 -2
  327. package/dist/esm/utils/currencyExtendedFormatter.d.ts.map +1 -1
  328. package/dist/esm/utils/customReceiver.js +6 -1
  329. package/dist/esm/utils/customReceiver.js.map +1 -1
  330. package/dist/esm/utils/elements.d.ts +2 -3
  331. package/dist/esm/utils/elements.d.ts.map +1 -1
  332. package/dist/esm/utils/enum.d.ts +1 -2
  333. package/dist/esm/utils/enum.d.ts.map +1 -1
  334. package/dist/esm/utils/fees.d.ts +2 -3
  335. package/dist/esm/utils/fees.d.ts.map +1 -1
  336. package/dist/esm/utils/format.d.ts +8 -9
  337. package/dist/esm/utils/format.d.ts.map +1 -1
  338. package/dist/esm/utils/getPriceImpact.d.ts +1 -2
  339. package/dist/esm/utils/getPriceImpact.d.ts.map +1 -1
  340. package/dist/esm/utils/input.d.ts +1 -2
  341. package/dist/esm/utils/input.d.ts.map +1 -1
  342. package/dist/esm/utils/navigationRoutes.d.ts +2 -3
  343. package/dist/esm/utils/navigationRoutes.d.ts.map +1 -1
  344. package/dist/esm/utils/percentFormatter.d.ts +1 -2
  345. package/dist/esm/utils/percentFormatter.d.ts.map +1 -1
  346. package/dist/esm/utils/recentTokens.js +97 -0
  347. package/dist/esm/utils/recentTokens.js.map +1 -0
  348. package/dist/esm/utils/token.js +30 -4
  349. package/dist/esm/utils/token.js.map +1 -1
  350. package/dist/esm/utils/tokenList.js +18 -6
  351. package/dist/esm/utils/tokenList.js.map +1 -1
  352. package/dist/esm/utils/tokenListBands.js +85 -0
  353. package/dist/esm/utils/tokenListBands.js.map +1 -0
  354. package/dist/esm/utils/wallet.d.ts +1 -2
  355. package/dist/esm/utils/wallet.d.ts.map +1 -1
  356. package/package.json +9 -9
  357. package/src/components/AmountInputCard/ReceiveAmountCard.tsx +16 -3
  358. package/src/components/BottomSheet/BottomSheet.tsx +3 -0
  359. package/src/components/Token/Token.tsx +2 -1
  360. package/src/components/TokenList/RecentTokensHeader.tsx +52 -0
  361. package/src/components/TokenList/RecentTokensToggle.tsx +45 -0
  362. package/src/components/TokenList/RemoveRecentTokenButton.tsx +38 -0
  363. package/src/components/TokenList/TokenList.tsx +92 -3
  364. package/src/components/TokenList/TokenListItem.tsx +15 -0
  365. package/src/components/TokenList/VirtualizedTokenList.tsx +84 -125
  366. package/src/components/TokenList/types.ts +9 -0
  367. package/src/config/version.ts +1 -1
  368. package/src/hooks/useDisplayedTokens.ts +17 -3
  369. package/src/hooks/useRecentTokens.ts +88 -0
  370. package/src/hooks/useRoutes.ts +8 -5
  371. package/src/hooks/useToAddressRequirements.ts +11 -5
  372. package/src/hooks/useTokenBalances.ts +34 -31
  373. package/src/hooks/useTokenSearch.ts +5 -14
  374. package/src/hooks/useTokens.ts +69 -27
  375. package/src/pages/TransactionPage/TokenValueBottomSheet.tsx +1 -1
  376. package/src/pages/TransactionPage/TokenVerificationBottomSheet.tsx +1 -1
  377. package/src/pages/TransactionPage/TransactionFailedButtons.tsx +62 -26
  378. package/src/pages/TransactionPage/TransactionReview.tsx +36 -37
  379. package/src/pages/TransactionPage/utils.ts +78 -0
  380. package/src/stores/StoreProvider.tsx +10 -7
  381. package/src/stores/chains/ChainOrderStore.test.tsx +298 -0
  382. package/src/stores/chains/ChainOrderStore.tsx +25 -6
  383. package/src/stores/recentTokens/RecentTokensStore.tsx +39 -0
  384. package/src/stores/recentTokens/createRecentTokensStore.ts +107 -0
  385. package/src/stores/recentTokens/types.ts +37 -0
  386. package/src/stores/recentTokens/utils.ts +18 -0
  387. package/src/types/token.ts +2 -0
  388. package/src/types/widget.ts +5 -0
  389. package/src/utils/address.ts +21 -0
  390. package/src/utils/customReceiver.ts +24 -0
  391. package/src/utils/recentTokens.ts +187 -0
  392. package/src/utils/token.ts +69 -10
  393. package/src/utils/tokenList.ts +41 -23
  394. package/src/utils/tokenListBands.ts +181 -0
@@ -4,7 +4,11 @@ import type { FC } from 'react'
4
4
  import { useCallback, useEffect, useMemo, useRef } from 'react'
5
5
  import { useTranslation } from 'react-i18next'
6
6
  import { useAvailableChains } from '../../hooks/useAvailableChains.js'
7
- import type { TokenAmount } from '../../types/token.js'
7
+ import { getTokenKey } from '../../stores/recentTokens/utils.js'
8
+ import { isHoistableNative } from '../../utils/tokenList.js'
9
+ import { createBandResolver } from '../../utils/tokenListBands.js'
10
+ import { RecentTokensHeader } from './RecentTokensHeader.js'
11
+ import { RecentTokensToggle } from './RecentTokensToggle.js'
8
12
  import { TokenDetailsSheet } from './TokenDetailsSheet.js'
9
13
  import { List } from './TokenList.style.js'
10
14
  import { TokenListItem, TokenListItemSkeleton } from './TokenListItem.js'
@@ -26,6 +30,13 @@ export const VirtualizedTokenList: FC<VirtualizedTokenListProps> = ({
26
30
  showPinnedTokens,
27
31
  onClick,
28
32
  isAllNetworks,
33
+ recentStartIndex = 0,
34
+ recentCount = 0,
35
+ hiddenRecentCount = 0,
36
+ recentExpanded = false,
37
+ onToggleRecent,
38
+ onClearRecent,
39
+ nativeHoisted,
29
40
  }) => {
30
41
  const { t } = useTranslation()
31
42
 
@@ -52,74 +63,65 @@ export const VirtualizedTokenList: FC<VirtualizedTokenListProps> = ({
52
63
  []
53
64
  )
54
65
 
66
+ // Rows below the band keep their key as it changes size, so none remount.
55
67
  const getItemKey = useCallback(
56
68
  (index: number) => {
57
69
  const token = tokens[index]
58
- return `${token.chainId}-${token.address}-${index}`
70
+ if (token.recent) {
71
+ return `recent-${token.chainId}-${token.address}`
72
+ }
73
+ const shift = index >= recentStartIndex + recentCount ? recentCount : 0
74
+ return `${token.chainId}-${token.address}-${index - shift}`
59
75
  },
60
- [tokens]
76
+ [tokens, recentStartIndex, recentCount]
61
77
  )
62
78
 
63
- // The hoisted native token sits above every category, so the row after it
64
- // opens the first one. Only a row the hoist could have moved counts.
65
- const nativeTokenHoisted = useMemo(() => {
66
- const first = tokens[0]
67
- return (
68
- !!first?.native &&
69
- !first.pinned &&
70
- !first.featured &&
71
- !first.popular &&
72
- !first.verified
73
- )
74
- }, [tokens])
75
-
76
- const isListStartIndex = useCallback(
77
- (index: number) => index === 0 || (index === 1 && nativeTokenHoisted),
78
- [nativeTokenHoisted]
79
+ const resolvedNativeHoisted = useMemo(
80
+ () => nativeHoisted ?? isHoistableNative(tokens[0]),
81
+ [nativeHoisted, tokens]
79
82
  )
80
83
 
81
- const estimateSize = useCallback(
82
- (index: number) => {
83
- const currentToken = tokens[index]
84
- const previousToken = tokens[index - 1]
85
- let size = tokenItemHeight
86
-
87
- // Pinned tokens (always shown, even in all networks mode)
88
- if (currentToken.pinned && isListStartIndex(index)) {
89
- size += 24
90
- }
91
- if (previousToken?.pinned && !currentToken.pinned) {
92
- size += 32
93
- }
94
-
95
- if (!showCategories) {
96
- return size
97
- }
98
-
99
- if (
100
- currentToken.featured &&
101
- !currentToken.pinned &&
102
- isListStartIndex(index)
103
- ) {
104
- size += 24
105
- }
84
+ const showRecentToggle = recentCount > 0 && !!onToggleRecent
106
85
 
107
- // Category transition (excluding pinned tokens). The hoisted native row
108
- // sits above every band, so the row after it ends nothing.
109
- const isNotPinned = !currentToken.pinned && !previousToken?.pinned
110
- if (
111
- !isListStartIndex(index) &&
112
- isNotPinned &&
113
- ((previousToken?.amount && !currentToken.amount) ||
114
- (previousToken?.featured && !currentToken.featured) ||
115
- (previousToken?.popular && !currentToken.popular))
116
- ) {
117
- size += 32
86
+ // The band copy is on screen; its list row may be far below the fold.
87
+ const bandKeys = useMemo(() => {
88
+ if (!recentCount) {
89
+ return undefined
90
+ }
91
+ const keys = new Set<string>()
92
+ for (let i = recentStartIndex; i < recentStartIndex + recentCount; i++) {
93
+ const token = tokens[i]
94
+ if (token) {
95
+ keys.add(getTokenKey(token.chainId, token.address))
118
96
  }
97
+ }
98
+ return keys
99
+ }, [tokens, recentStartIndex, recentCount])
100
+
101
+ const bands = useMemo(
102
+ () =>
103
+ createBandResolver(tokens, {
104
+ showCategories: !!showCategories,
105
+ showPinnedTokens: !!showPinnedTokens,
106
+ nativeHoisted: resolvedNativeHoisted,
107
+ recentStartIndex,
108
+ recentCount,
109
+ showRecentToggle,
110
+ }),
111
+ [
112
+ tokens,
113
+ showCategories,
114
+ showPinnedTokens,
115
+ resolvedNativeHoisted,
116
+ recentStartIndex,
117
+ recentCount,
118
+ showRecentToggle,
119
+ ]
120
+ )
119
121
 
120
- return size
121
- },
122
- [tokens, showCategories, isListStartIndex]
122
+ const estimateSize = useCallback(
123
+ (index: number) => tokenItemHeight + bands.getRowExtraHeight(index),
124
+ [bands]
123
125
  )
124
126
 
125
127
  const virtualizerConfig = useMemo(
@@ -163,70 +165,16 @@ export const VirtualizedTokenList: FC<VirtualizedTokenListProps> = ({
163
165
  >
164
166
  {getVirtualItems().map((item) => {
165
167
  const currentToken = tokens[item.index]
166
- const previousToken: TokenAmount | undefined = tokens[item.index - 1]
167
168
  const chain = chainsSet?.get(currentToken.chainId)
168
-
169
- const isListStart = isListStartIndex(item.index)
170
- const isNotPinned = !currentToken.pinned
171
- const isFirstPinnedToken = currentToken.pinned && isListStart
172
- const isTransitionFromPinned = previousToken?.pinned && isNotPinned
173
-
174
- // Category transitions (excluding pinned)
175
- const isTransitionFromFeatured =
176
- previousToken?.featured && !currentToken.featured && isNotPinned
177
- const isTransitionFromMyTokens =
178
- previousToken?.amount && !currentToken.amount && isNotPinned
179
- const isTransitionFromPopular =
180
- previousToken?.popular && !currentToken.popular && isNotPinned
181
-
182
- // Determine which category label to show
183
- const startAdornmentLabel = (() => {
184
- if (showPinnedTokens && isFirstPinnedToken) {
185
- return t('main.pinnedTokens')
186
- }
187
- if (showPinnedTokens && !showCategories && isTransitionFromPinned) {
188
- return t('main.allTokens')
189
- }
190
- if (!showCategories) {
191
- return null
192
- }
193
-
194
- if (
195
- (isTransitionFromPinned && currentToken.featured) ||
196
- (currentToken.featured && isNotPinned && isListStart)
197
- ) {
198
- return t('main.featuredTokens')
199
- }
200
- if (
201
- (isTransitionFromFeatured || isTransitionFromPinned) &&
202
- currentToken.amount &&
203
- isNotPinned
204
- ) {
205
- return t('main.myTokens')
206
- }
207
- if (
208
- (isTransitionFromFeatured ||
209
- isTransitionFromMyTokens ||
210
- isTransitionFromPinned) &&
211
- currentToken.popular &&
212
- isNotPinned
213
- ) {
214
- return t('main.popularTokens')
215
- }
216
- if (
217
- isTransitionFromMyTokens ||
218
- isTransitionFromFeatured ||
219
- isTransitionFromPinned ||
220
- isTransitionFromPopular
221
- ) {
222
- return t('main.allTokens')
223
- }
224
- return null
225
- })()
169
+ const band = bands.getRowBandLabel(item.index)
226
170
 
227
171
  const isSelected =
228
172
  selectedTokenAddress === currentToken.address &&
229
- chainId === currentToken.chainId
173
+ chainId === currentToken.chainId &&
174
+ (!!currentToken.recent ||
175
+ !bandKeys?.has(
176
+ getTokenKey(currentToken.chainId, currentToken.address)
177
+ ))
230
178
 
231
179
  return (
232
180
  <TokenListItem
@@ -241,25 +189,36 @@ export const VirtualizedTokenList: FC<VirtualizedTokenListProps> = ({
241
189
  onShowTokenDetails={onShowTokenDetails}
242
190
  isBalanceLoading={isBalanceLoading}
243
191
  startAdornment={
244
- startAdornmentLabel ? (
192
+ band?.kind === 'recent' ? (
193
+ // Unconditional: the resolver always reserves this height.
194
+ <RecentTokensHeader
195
+ atListStart={band.atListStart}
196
+ onClear={onClearRecent}
197
+ />
198
+ ) : band?.kind === 'text' ? (
245
199
  <Typography
246
200
  sx={{
247
201
  fontSize: 14,
248
202
  fontWeight: 600,
249
203
  lineHeight: '16px',
250
204
  px: 1.5,
251
- pt:
252
- isFirstPinnedToken ||
253
- (currentToken.featured && isNotPinned && isListStart)
254
- ? 0
255
- : 1,
205
+ pt: band.atListStart ? 0 : 1,
256
206
  pb: 1,
257
207
  }}
258
208
  >
259
- {startAdornmentLabel}
209
+ {t(band.key)}
260
210
  </Typography>
261
211
  ) : null
262
212
  }
213
+ endAdornment={
214
+ onToggleRecent && bands.isToggleRow(item.index) ? (
215
+ <RecentTokensToggle
216
+ expanded={recentExpanded}
217
+ hiddenCount={hiddenRecentCount}
218
+ onToggle={onToggleRecent}
219
+ />
220
+ ) : null
221
+ }
263
222
  />
264
223
  )
265
224
  })}
@@ -19,6 +19,15 @@ export interface VirtualizedTokenListProps {
19
19
  onClick(tokenAddress: string, chainId?: number): void
20
20
  selectedTokenAddress?: string
21
21
  isAllNetworks: boolean
22
+ // Optional: public via shared.ts, and widget-checkout passes none of these.
23
+ recentStartIndex?: number
24
+ recentCount?: number
25
+ hiddenRecentCount?: number
26
+ recentExpanded?: boolean
27
+ onToggleRecent?: () => void
28
+ onClearRecent?: () => void
29
+ /** Defaults to this component's own `isHoistableNative(tokens[0])`. */
30
+ nativeHoisted?: boolean
22
31
  }
23
32
 
24
33
  interface TokenListItemBaseProps {
@@ -1,2 +1,2 @@
1
1
  export const name = '@lifi/widget'
2
- export const version = '4.6.0'
2
+ export const version = '4.7.0'
@@ -2,11 +2,13 @@ import type { TokenExtended } from '@lifi/sdk'
2
2
  import { useMemo } from 'react'
3
3
  import type { FormType } from '../stores/form/types.js'
4
4
  import { usePinnedTokensStore } from '../stores/pinnedTokens/PinnedTokensStore.js'
5
- import { isSearchMatch } from '../utils/tokenList.js'
5
+ import { createSearchMatcher } from '../utils/tokenList.js'
6
6
  import { useTokens } from './useTokens.js'
7
7
 
8
8
  export type IsPinnedToken = (chainId: number, tokenAddress: string) => boolean
9
9
 
10
+ export type MatchesSearch = ReturnType<typeof createSearchMatcher>
11
+
10
12
  // Balance-free core shared by useTokenList and useTokenBalances.
11
13
  export const useDisplayedTokens = (
12
14
  selectedChainId?: number,
@@ -17,6 +19,11 @@ export const useDisplayedTokens = (
17
19
  allTokens: Record<number, TokenExtended[]> | undefined
18
20
  displayedTokensList: TokenExtended[]
19
21
  isPinnedToken: IsPinnedToken | undefined
22
+ /**
23
+ * The filter this search applies, built once here so every list that shows
24
+ * the same search — with balances or without — cannot disagree with it.
25
+ */
26
+ matchesSearch: MatchesSearch
20
27
  isTokensLoading: boolean
21
28
  isSearchLoading: boolean
22
29
  } => {
@@ -24,6 +31,7 @@ export const useDisplayedTokens = (
24
31
  allTokens,
25
32
  isLoading: isTokensLoading,
26
33
  isSearchLoading,
34
+ isAddressSearch,
27
35
  } = useTokens(formType, search, isAllNetworks ? undefined : selectedChainId)
28
36
 
29
37
  const pinnedTokens = usePinnedTokensStore((state) => state.pinnedTokens)
@@ -51,19 +59,25 @@ export const useDisplayedTokens = (
51
59
  return undefined
52
60
  }, [isAllNetworks, selectedChainId, pinnedTokens])
53
61
 
62
+ const matchesSearch = useMemo<MatchesSearch>(
63
+ () => createSearchMatcher(search, isAddressSearch),
64
+ [search, isAddressSearch]
65
+ )
66
+
54
67
  const displayedTokensList = useMemo(() => {
55
68
  const tokensByChain = isAllNetworks
56
69
  ? Object.values(allTokens ?? {}).flat()
57
70
  : selectedChainId
58
71
  ? allTokens?.[selectedChainId]
59
72
  : undefined
60
- return tokensByChain?.filter((t) => isSearchMatch(t, search)) ?? []
61
- }, [allTokens, isAllNetworks, selectedChainId, search])
73
+ return tokensByChain?.filter(matchesSearch) ?? []
74
+ }, [allTokens, isAllNetworks, selectedChainId, matchesSearch])
62
75
 
63
76
  return {
64
77
  allTokens,
65
78
  displayedTokensList,
66
79
  isPinnedToken,
80
+ matchesSearch,
67
81
  isTokensLoading,
68
82
  isSearchLoading,
69
83
  }
@@ -0,0 +1,88 @@
1
+ import { useMemo } from 'react'
2
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
3
+ import type { FormType } from '../stores/form/types.js'
4
+ import { useRecentTokensStore } from '../stores/recentTokens/RecentTokensStore.js'
5
+ import type { RecentTokenId } from '../stores/recentTokens/types.js'
6
+ import type { TokenAmount } from '../types/token.js'
7
+ import type { RecentTokensResult } from '../utils/recentTokens.js'
8
+ import { resolveRecentRows, spliceRecentRows } from '../utils/recentTokens.js'
9
+ import { useChains } from './useChains.js'
10
+
11
+ export interface UseRecentTokensOptions {
12
+ selectedChainId?: number
13
+ isAllNetworks?: boolean
14
+ search?: string
15
+ expanded: boolean
16
+ formType: FormType
17
+ isTokensLoading: boolean
18
+ nativeHoisted: boolean
19
+ }
20
+
21
+ export interface UseRecentTokensResult extends RecentTokensResult {
22
+ bandEntries: RecentTokenId[]
23
+ recentStartIndex: number
24
+ }
25
+
26
+ export const useRecentTokens = (
27
+ tokens: TokenAmount[],
28
+ {
29
+ selectedChainId,
30
+ isAllNetworks,
31
+ search,
32
+ expanded,
33
+ formType,
34
+ isTokensLoading,
35
+ nativeHoisted,
36
+ }: UseRecentTokensOptions
37
+ ): UseRecentTokensResult => {
38
+ const { hiddenUI, tokens: configTokens } = useWidgetConfig()
39
+ // useChains, not useAvailableChains: only it applies chains.allow/deny.
40
+ const { chains } = useChains(formType)
41
+ const recentTokens = useRecentTokensStore((state) => state.recentTokens)
42
+
43
+ const availableChainIds = useMemo(
44
+ () => new Set(chains?.map((chain) => chain.id)),
45
+ [chains]
46
+ )
47
+
48
+ // Untrimmed, like the list layout; wait for tokens (no amber flash) and chains.
49
+ const disabled =
50
+ !!search || !!hiddenUI?.recentSearches || isTokensLoading || !chains
51
+
52
+ const resolved = useMemo(
53
+ () =>
54
+ resolveRecentRows(tokens, {
55
+ recentTokens,
56
+ availableChainIds,
57
+ configTokens,
58
+ formType,
59
+ selectedChainId,
60
+ isAllNetworks,
61
+ nativeHoisted,
62
+ disabled,
63
+ }),
64
+ [
65
+ tokens,
66
+ recentTokens,
67
+ availableChainIds,
68
+ configTokens,
69
+ formType,
70
+ selectedChainId,
71
+ isAllNetworks,
72
+ nativeHoisted,
73
+ disabled,
74
+ ]
75
+ )
76
+
77
+ // Separate, so a Show more/less click redoes the slice but not the scan.
78
+ const spliced = useMemo(
79
+ () => spliceRecentRows(tokens, resolved, expanded),
80
+ [tokens, resolved, expanded]
81
+ )
82
+
83
+ return {
84
+ ...spliced,
85
+ bandEntries: resolved.bandEntries,
86
+ recentStartIndex: resolved.recentStartIndex,
87
+ }
88
+ }
@@ -29,7 +29,7 @@ import { defaultSlippage } from '../stores/settings/createSettingsStore.js'
29
29
  import { useSettings } from '../stores/settings/useSettings.js'
30
30
  import { WidgetEvent } from '../types/events.js'
31
31
  import type { TokensByChain } from '../types/token.js'
32
- import { isCustomReceiverUnsupported } from '../utils/customReceiver.js'
32
+ import { isCustomReceiverBlocked } from '../utils/customReceiver.js'
33
33
  import { getQueryKey } from '../utils/queries.js'
34
34
  import { updateTokenInCache } from '../utils/token.js'
35
35
  import { useChain } from './useChain.js'
@@ -178,10 +178,13 @@ export const useRoutes = ({
178
178
  ? hasToAddressAndChainTypeSatisfied
179
179
  : true
180
180
 
181
- // Stellar settles to the signer, so a set receiver makes the route unfulfillable.
182
- const customReceiverBlocked =
183
- isCustomReceiverUnsupported(fromChain?.chainType, toChain?.chainType) &&
184
- Boolean(toAddress)
181
+ // Not `effectiveFromAddress`: a quote placeholder must never match a receiver.
182
+ const customReceiverBlocked = isCustomReceiverBlocked({
183
+ fromChainType: fromChain?.chainType,
184
+ toChainType: toChain?.chainType,
185
+ toAddress,
186
+ signerAddress: account.address,
187
+ })
185
188
 
186
189
  // toAddress might be an empty string, but we need to pass undefined if there is no value
187
190
  const toWalletAddress = toAddress || undefined
@@ -4,7 +4,10 @@ import { useEthereumContext } from '@lifi/widget-provider'
4
4
  import { useChain } from '../hooks/useChain.js'
5
5
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
6
6
  import { useFieldValues } from '../stores/form/useFieldValues.js'
7
- import { isCustomReceiverUnsupported } from '../utils/customReceiver.js'
7
+ import {
8
+ isCustomReceiverBlocked,
9
+ isCustomReceiverUnsupported,
10
+ } from '../utils/customReceiver.js'
8
11
  import { useIsContractAddress } from './useIsContractAddress.js'
9
12
 
10
13
  export const useToAddressRequirements = (
@@ -76,10 +79,13 @@ export const useToAddressRequirements = (
76
79
  toChain?.chainType
77
80
  )
78
81
 
79
- // Stellar routes settle to the signer, so a required receiver is never honoured.
80
- const unsupportedReceiverBlocking = Boolean(
81
- unsupportedToAddress && (toAddress || requiredUI?.toAddress)
82
- )
82
+ const unsupportedReceiverBlocking = isCustomReceiverBlocked({
83
+ fromChainType: fromChain?.chainType,
84
+ toChainType: toChain?.chainType,
85
+ toAddress,
86
+ signerAddress: fromAddress,
87
+ receiverRequired: requiredUI?.toAddress,
88
+ })
83
89
 
84
90
  const requiredToAddress = Boolean(
85
91
  (isDifferentChainType ||
@@ -6,7 +6,7 @@ import type { TokenAmount } from '../types/token.js'
6
6
  import { formatTokenPrice } from '../utils/format.js'
7
7
  import {
8
8
  hoistNativeToken,
9
- isSearchMatch,
9
+ isHoistableNative,
10
10
  processTokenList,
11
11
  } from '../utils/tokenList.js'
12
12
  import { useAccountsBalancesData } from './useAccountsBalancesData.js'
@@ -25,12 +25,15 @@ export const useTokenBalances = (
25
25
  isTokensLoading: boolean
26
26
  isSearchLoading: boolean
27
27
  isBalanceLoading: boolean
28
+ /** Always set; optional so hand-built results of this public shape stay valid. */
29
+ nativeHoisted?: boolean
28
30
  } => {
29
31
  const { hiddenUI, tokens: configTokens } = useWidgetConfig()
30
32
  const {
31
33
  allTokens,
32
34
  displayedTokensList,
33
35
  isPinnedToken,
36
+ matchesSearch,
34
37
  isTokensLoading,
35
38
  isSearchLoading,
36
39
  } = useDisplayedTokens(selectedChainId, formType, isAllNetworks, search)
@@ -77,10 +80,10 @@ export const useTokenBalances = (
77
80
  // Check if token is in displayed list and has amount
78
81
  const isInDisplayedList = displayedTokensSet.has(tokenKey) && token.amount
79
82
  // Check if it matches search (for cached appended tokens)
80
- const matchesSearch = isSearchMatch(token, search)
83
+ const matchesTheSearch = matchesSearch(token)
81
84
 
82
85
  // Filter: only include tokens that match our criteria
83
- if (!isInDisplayedList && !matchesSearch) {
86
+ if (!isInDisplayedList && !matchesTheSearch) {
84
87
  return acc
85
88
  }
86
89
 
@@ -111,45 +114,44 @@ export const useTokenBalances = (
111
114
  }, [
112
115
  allTokensWithBalances,
113
116
  displayedTokensList,
114
- search,
117
+ matchesSearch,
115
118
  selectedChainId,
116
119
  isAllNetworks,
117
120
  smallBalanceThreshold,
118
121
  hiddenUI,
119
122
  ])
120
123
 
121
- const { processedTokens, withCategories, withPinnedTokens } = useMemo(() => {
122
- const result = processTokenList(
124
+ const { processedTokens, withCategories, withPinnedTokens, nativeHoisted } =
125
+ useMemo(() => {
126
+ const result = processTokenList(
127
+ isBalanceLoading,
128
+ isAllNetworks || !!search,
129
+ configTokens,
130
+ selectedChainId,
131
+ displayedTokensList,
132
+ displayedTokensWithBalances,
133
+ isPinnedToken
134
+ )
135
+ // Search results stay ranked, and All networks has no single native.
136
+ if (isAllNetworks || search) {
137
+ return { ...result, nativeHoisted: false }
138
+ }
139
+ const hoisted = hoistNativeToken(result.processedTokens, selectedChainId)
140
+ return {
141
+ ...result,
142
+ processedTokens: hoisted,
143
+ nativeHoisted: isHoistableNative(hoisted[0], selectedChainId),
144
+ }
145
+ }, [
123
146
  isBalanceLoading,
124
- isAllNetworks || !!search,
147
+ isAllNetworks,
125
148
  configTokens,
126
149
  selectedChainId,
127
150
  displayedTokensList,
128
151
  displayedTokensWithBalances,
129
- isPinnedToken
130
- )
131
- // A search keeps its results ranked by match, and "All networks" has no
132
- // single native token to lead with.
133
- if (isAllNetworks || search) {
134
- return result
135
- }
136
- return {
137
- ...result,
138
- processedTokens: hoistNativeToken(
139
- result.processedTokens,
140
- selectedChainId
141
- ),
142
- }
143
- }, [
144
- isBalanceLoading,
145
- isAllNetworks,
146
- configTokens,
147
- selectedChainId,
148
- displayedTokensList,
149
- displayedTokensWithBalances,
150
- search,
151
- isPinnedToken,
152
- ])
152
+ search,
153
+ isPinnedToken,
154
+ ])
153
155
 
154
156
  return {
155
157
  tokens: processedTokens ?? [],
@@ -158,5 +160,6 @@ export const useTokenBalances = (
158
160
  isTokensLoading,
159
161
  isSearchLoading,
160
162
  isBalanceLoading,
163
+ nativeHoisted,
161
164
  }
162
165
  }
@@ -1,16 +1,12 @@
1
- import {
2
- type BaseToken,
3
- type ChainId,
4
- getToken,
5
- type TokenExtended,
6
- } from '@lifi/sdk'
1
+ import { type ChainId, getToken, type TokenExtended } from '@lifi/sdk'
7
2
  import { useQuery, useQueryClient } from '@tanstack/react-query'
8
3
  import { useSDKClient } from '../providers/SDKClientProvider.js'
9
4
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
10
5
  import type { FormType } from '../stores/form/types.js'
11
6
  import type { TokensByChain } from '../types/token.js'
12
- import { getConfigItemSets, isFormItemAllowed } from '../utils/item.js'
7
+ import { isFormItemAllowed } from '../utils/item.js'
13
8
  import { getQueryKey } from '../utils/queries.js'
9
+ import { getChainTokenAllowSets } from '../utils/token.js'
14
10
 
15
11
  export const useTokenSearch = (
16
12
  chainId?: number,
@@ -39,14 +35,9 @@ export const useTokenSearch = (
39
35
 
40
36
  if (token) {
41
37
  // Filter config tokens by chain before checking if token is allowed
42
- const filteredConfigTokens = getConfigItemSets(
38
+ const filteredConfigTokens = getChainTokenAllowSets(
43
39
  configTokens,
44
- (tokens: BaseToken[]) =>
45
- new Set(
46
- tokens
47
- .filter((t) => t.chainId === token.chainId)
48
- .map((t) => t.address.toLowerCase())
49
- ),
40
+ token.chainId,
50
41
  formType
51
42
  )
52
43