@lifi/widget 4.6.0 → 4.7.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 (424) 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 +2 -3
  148. package/dist/esm/hooks/useExplorer.d.ts.map +1 -1
  149. package/dist/esm/hooks/useExplorer.js +7 -3
  150. package/dist/esm/hooks/useExplorer.js.map +1 -1
  151. package/dist/esm/hooks/useHeader.d.ts +1 -2
  152. package/dist/esm/hooks/useHeader.d.ts.map +1 -1
  153. package/dist/esm/hooks/useListHeight.d.ts +1 -2
  154. package/dist/esm/hooks/useListHeight.d.ts.map +1 -1
  155. package/dist/esm/hooks/useNavigateBack.d.ts +1 -2
  156. package/dist/esm/hooks/useNavigateBack.d.ts.map +1 -1
  157. package/dist/esm/hooks/useRecentTokens.js +46 -0
  158. package/dist/esm/hooks/useRecentTokens.js.map +1 -0
  159. package/dist/esm/hooks/useRouteExecution.d.ts +1 -2
  160. package/dist/esm/hooks/useRouteExecution.d.ts.map +1 -1
  161. package/dist/esm/hooks/useRouteExecutionMessage.d.ts +1 -2
  162. package/dist/esm/hooks/useRouteExecutionMessage.d.ts.map +1 -1
  163. package/dist/esm/hooks/useRoutes.d.ts +1 -2
  164. package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
  165. package/dist/esm/hooks/useRoutes.js +7 -2
  166. package/dist/esm/hooks/useRoutes.js.map +1 -1
  167. package/dist/esm/hooks/useToAddressRequirements.d.ts +1 -2
  168. package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
  169. package/dist/esm/hooks/useToAddressRequirements.js +8 -2
  170. package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
  171. package/dist/esm/hooks/useToken.d.ts +1 -2
  172. package/dist/esm/hooks/useToken.d.ts.map +1 -1
  173. package/dist/esm/hooks/useTokenAddressBalance.d.ts +1 -2
  174. package/dist/esm/hooks/useTokenAddressBalance.d.ts.map +1 -1
  175. package/dist/esm/hooks/useTokenBalances.d.ts +3 -2
  176. package/dist/esm/hooks/useTokenBalances.d.ts.map +1 -1
  177. package/dist/esm/hooks/useTokenBalances.js +15 -9
  178. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  179. package/dist/esm/hooks/useTokenList.d.ts +1 -2
  180. package/dist/esm/hooks/useTokenList.d.ts.map +1 -1
  181. package/dist/esm/hooks/useTokenSearch.js +3 -2
  182. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  183. package/dist/esm/hooks/useTokens.js +26 -15
  184. package/dist/esm/hooks/useTokens.js.map +1 -1
  185. package/dist/esm/hooks/useTools.d.ts +1 -2
  186. package/dist/esm/hooks/useTools.d.ts.map +1 -1
  187. package/dist/esm/hooks/useWidgetChains.d.ts +1 -2
  188. package/dist/esm/hooks/useWidgetChains.d.ts.map +1 -1
  189. package/dist/esm/hooks/useWidgetEvents.d.ts +3 -4
  190. package/dist/esm/hooks/useWidgetEvents.d.ts.map +1 -1
  191. package/dist/esm/i18n/bn.json +4 -0
  192. package/dist/esm/i18n/de.json +4 -0
  193. package/dist/esm/i18n/en.json +4 -0
  194. package/dist/esm/i18n/es.json +4 -0
  195. package/dist/esm/i18n/fr.json +4 -0
  196. package/dist/esm/i18n/hi.json +4 -0
  197. package/dist/esm/i18n/id.json +4 -0
  198. package/dist/esm/i18n/it.json +4 -0
  199. package/dist/esm/i18n/ja.json +4 -0
  200. package/dist/esm/i18n/ko.json +4 -0
  201. package/dist/esm/i18n/pl.json +4 -0
  202. package/dist/esm/i18n/pt.json +4 -0
  203. package/dist/esm/i18n/th.json +4 -0
  204. package/dist/esm/i18n/tr.json +4 -0
  205. package/dist/esm/i18n/uk.json +4 -0
  206. package/dist/esm/i18n/vi.json +4 -0
  207. package/dist/esm/i18n/zh.json +4 -0
  208. package/dist/esm/pages/MainPage/MainWarningMessages.d.ts +1 -2
  209. package/dist/esm/pages/MainPage/MainWarningMessages.d.ts.map +1 -1
  210. package/dist/esm/pages/SelectChainPage/SelectChainPage.d.ts +1 -2
  211. package/dist/esm/pages/SelectChainPage/SelectChainPage.d.ts.map +1 -1
  212. package/dist/esm/pages/SelectChainPage/types.d.ts +1 -2
  213. package/dist/esm/pages/SelectChainPage/types.d.ts.map +1 -1
  214. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.d.ts +1 -2
  215. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.d.ts.map +1 -1
  216. package/dist/esm/pages/SendToWallet/BookmarksPage.js +2 -1
  217. package/dist/esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
  218. package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js +2 -1
  219. package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
  220. package/dist/esm/pages/SendToWallet/RecentWalletsPage.js +2 -1
  221. package/dist/esm/pages/SendToWallet/RecentWalletsPage.js.map +1 -1
  222. package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js +2 -1
  223. package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js.map +1 -1
  224. package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.d.ts +1 -2
  225. package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.d.ts.map +1 -1
  226. package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js +2 -1
  227. package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
  228. package/dist/esm/pages/TransactionDetailsPage/TransferIdCard.js +2 -1
  229. package/dist/esm/pages/TransactionDetailsPage/TransferIdCard.js.map +1 -1
  230. package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.d.ts +1 -2
  231. package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.d.ts.map +1 -1
  232. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.d.ts +2 -3
  233. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.d.ts.map +1 -1
  234. package/dist/esm/pages/TransactionPage/ExecutionDoneCard.d.ts +1 -2
  235. package/dist/esm/pages/TransactionPage/ExecutionDoneCard.d.ts.map +1 -1
  236. package/dist/esm/pages/TransactionPage/RouteTracker.d.ts +1 -2
  237. package/dist/esm/pages/TransactionPage/RouteTracker.d.ts.map +1 -1
  238. package/dist/esm/pages/TransactionPage/StartTransactionButton.d.ts +1 -2
  239. package/dist/esm/pages/TransactionPage/StartTransactionButton.d.ts.map +1 -1
  240. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.d.ts +1 -2
  241. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.d.ts.map +1 -1
  242. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js +0 -1
  243. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
  244. package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js +0 -1
  245. package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js.map +1 -1
  246. package/dist/esm/pages/TransactionPage/TransactionDoneButtons.d.ts +1 -2
  247. package/dist/esm/pages/TransactionPage/TransactionDoneButtons.d.ts.map +1 -1
  248. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js +38 -12
  249. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js.map +1 -1
  250. package/dist/esm/pages/TransactionPage/TransactionReview.js +22 -21
  251. package/dist/esm/pages/TransactionPage/TransactionReview.js.map +1 -1
  252. package/dist/esm/pages/TransactionPage/types.d.ts +1 -2
  253. package/dist/esm/pages/TransactionPage/types.d.ts.map +1 -1
  254. package/dist/esm/pages/TransactionPage/utils.d.ts +2 -3
  255. package/dist/esm/pages/TransactionPage/utils.d.ts.map +1 -1
  256. package/dist/esm/pages/TransactionPage/utils.js +23 -1
  257. package/dist/esm/pages/TransactionPage/utils.js.map +1 -1
  258. package/dist/esm/providers/I18nProvider/I18nProvider.d.ts +1 -2
  259. package/dist/esm/providers/I18nProvider/I18nProvider.d.ts.map +1 -1
  260. package/dist/esm/providers/I18nProvider/types.d.ts +4 -5
  261. package/dist/esm/providers/I18nProvider/types.d.ts.map +1 -1
  262. package/dist/esm/providers/QueryClientProvider.d.ts +1 -2
  263. package/dist/esm/providers/QueryClientProvider.d.ts.map +1 -1
  264. package/dist/esm/providers/SDKClientProvider.d.ts +2 -3
  265. package/dist/esm/providers/SDKClientProvider.d.ts.map +1 -1
  266. package/dist/esm/providers/WalletProvider/WalletProvider.d.ts +1 -2
  267. package/dist/esm/providers/WalletProvider/WalletProvider.d.ts.map +1 -1
  268. package/dist/esm/providers/WidgetProvider/WidgetProvider.d.ts +2 -3
  269. package/dist/esm/providers/WidgetProvider/WidgetProvider.d.ts.map +1 -1
  270. package/dist/esm/providers/WidgetProvider/types.d.ts +2 -3
  271. package/dist/esm/providers/WidgetProvider/types.d.ts.map +1 -1
  272. package/dist/esm/shared.d.ts +2 -1
  273. package/dist/esm/shared.js +2 -1
  274. package/dist/esm/stores/StoreProvider.d.ts +1 -2
  275. package/dist/esm/stores/StoreProvider.d.ts.map +1 -1
  276. package/dist/esm/stores/StoreProvider.js +10 -6
  277. package/dist/esm/stores/StoreProvider.js.map +1 -1
  278. package/dist/esm/stores/bookmarks/BookmarkStore.d.ts +1 -2
  279. package/dist/esm/stores/bookmarks/BookmarkStore.d.ts.map +1 -1
  280. package/dist/esm/stores/bookmarks/types.d.ts +5 -6
  281. package/dist/esm/stores/bookmarks/types.d.ts.map +1 -1
  282. package/dist/esm/stores/chains/ChainOrderStore.d.ts +1 -2
  283. package/dist/esm/stores/chains/ChainOrderStore.d.ts.map +1 -1
  284. package/dist/esm/stores/chains/ChainOrderStore.js +11 -5
  285. package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
  286. package/dist/esm/stores/chains/types.d.ts +1 -2
  287. package/dist/esm/stores/chains/types.d.ts.map +1 -1
  288. package/dist/esm/stores/form/types.d.ts +20 -21
  289. package/dist/esm/stores/form/types.d.ts.map +1 -1
  290. package/dist/esm/stores/form/useFieldActions.d.ts +1 -2
  291. package/dist/esm/stores/form/useFieldActions.d.ts.map +1 -1
  292. package/dist/esm/stores/form/useFieldValues.d.ts +1 -2
  293. package/dist/esm/stores/form/useFieldValues.d.ts.map +1 -1
  294. package/dist/esm/stores/header/types.d.ts +1 -2
  295. package/dist/esm/stores/header/types.d.ts.map +1 -1
  296. package/dist/esm/stores/header/useHeaderStore.d.ts +2 -3
  297. package/dist/esm/stores/header/useHeaderStore.d.ts.map +1 -1
  298. package/dist/esm/stores/inputMode/useInputModeStore.d.ts +1 -2
  299. package/dist/esm/stores/inputMode/useInputModeStore.d.ts.map +1 -1
  300. package/dist/esm/stores/recentTokens/RecentTokensStore.js +23 -0
  301. package/dist/esm/stores/recentTokens/RecentTokensStore.js.map +1 -0
  302. package/dist/esm/stores/recentTokens/createRecentTokensStore.js +54 -0
  303. package/dist/esm/stores/recentTokens/createRecentTokensStore.js.map +1 -0
  304. package/dist/esm/stores/recentTokens/utils.js +15 -0
  305. package/dist/esm/stores/recentTokens/utils.js.map +1 -0
  306. package/dist/esm/stores/routes/RouteExecutionStore.d.ts +2 -3
  307. package/dist/esm/stores/routes/RouteExecutionStore.d.ts.map +1 -1
  308. package/dist/esm/stores/routes/types.d.ts +3 -4
  309. package/dist/esm/stores/routes/types.d.ts.map +1 -1
  310. package/dist/esm/stores/routes/utils.d.ts +4 -5
  311. package/dist/esm/stores/routes/utils.d.ts.map +1 -1
  312. package/dist/esm/stores/settings/SettingsStore.d.ts +2 -3
  313. package/dist/esm/stores/settings/SettingsStore.d.ts.map +1 -1
  314. package/dist/esm/stores/settings/types.d.ts +2 -3
  315. package/dist/esm/stores/settings/types.d.ts.map +1 -1
  316. package/dist/esm/stores/types.d.ts +2 -3
  317. package/dist/esm/stores/types.d.ts.map +1 -1
  318. package/dist/esm/themes/azureLight.d.ts +1 -2
  319. package/dist/esm/themes/azureLight.d.ts.map +1 -1
  320. package/dist/esm/themes/jumper.d.ts +1 -2
  321. package/dist/esm/themes/jumper.d.ts.map +1 -1
  322. package/dist/esm/themes/palettes.d.ts +3 -4
  323. package/dist/esm/themes/palettes.d.ts.map +1 -1
  324. package/dist/esm/themes/types.d.ts +1 -0
  325. package/dist/esm/themes/watermelonLight.d.ts +1 -2
  326. package/dist/esm/themes/watermelonLight.d.ts.map +1 -1
  327. package/dist/esm/themes/windows95.d.ts +1 -2
  328. package/dist/esm/themes/windows95.d.ts.map +1 -1
  329. package/dist/esm/types/events.d.ts +13 -14
  330. package/dist/esm/types/events.d.ts.map +1 -1
  331. package/dist/esm/types/token.d.ts +4 -2
  332. package/dist/esm/types/token.d.ts.map +1 -1
  333. package/dist/esm/types/widget.d.ts +55 -51
  334. package/dist/esm/types/widget.d.ts.map +1 -1
  335. package/dist/esm/types/widget.js.map +1 -1
  336. package/dist/esm/utils/address.js +19 -0
  337. package/dist/esm/utils/address.js.map +1 -0
  338. package/dist/esm/utils/compactNumberFormatter.d.ts +1 -2
  339. package/dist/esm/utils/compactNumberFormatter.d.ts.map +1 -1
  340. package/dist/esm/utils/converters.d.ts +1 -2
  341. package/dist/esm/utils/converters.d.ts.map +1 -1
  342. package/dist/esm/utils/currencyExtendedFormatter.d.ts +1 -2
  343. package/dist/esm/utils/currencyExtendedFormatter.d.ts.map +1 -1
  344. package/dist/esm/utils/customReceiver.js +6 -1
  345. package/dist/esm/utils/customReceiver.js.map +1 -1
  346. package/dist/esm/utils/elements.d.ts +2 -3
  347. package/dist/esm/utils/elements.d.ts.map +1 -1
  348. package/dist/esm/utils/enum.d.ts +1 -2
  349. package/dist/esm/utils/enum.d.ts.map +1 -1
  350. package/dist/esm/utils/fees.d.ts +2 -3
  351. package/dist/esm/utils/fees.d.ts.map +1 -1
  352. package/dist/esm/utils/format.d.ts +8 -9
  353. package/dist/esm/utils/format.d.ts.map +1 -1
  354. package/dist/esm/utils/getPriceImpact.d.ts +1 -2
  355. package/dist/esm/utils/getPriceImpact.d.ts.map +1 -1
  356. package/dist/esm/utils/input.d.ts +1 -2
  357. package/dist/esm/utils/input.d.ts.map +1 -1
  358. package/dist/esm/utils/navigationRoutes.d.ts +2 -3
  359. package/dist/esm/utils/navigationRoutes.d.ts.map +1 -1
  360. package/dist/esm/utils/percentFormatter.d.ts +1 -2
  361. package/dist/esm/utils/percentFormatter.d.ts.map +1 -1
  362. package/dist/esm/utils/recentTokens.js +97 -0
  363. package/dist/esm/utils/recentTokens.js.map +1 -0
  364. package/dist/esm/utils/token.js +30 -4
  365. package/dist/esm/utils/token.js.map +1 -1
  366. package/dist/esm/utils/tokenList.js +18 -6
  367. package/dist/esm/utils/tokenList.js.map +1 -1
  368. package/dist/esm/utils/tokenListBands.js +85 -0
  369. package/dist/esm/utils/tokenListBands.js.map +1 -0
  370. package/dist/esm/utils/url.d.ts +5 -0
  371. package/dist/esm/utils/url.d.ts.map +1 -0
  372. package/dist/esm/utils/url.js +17 -0
  373. package/dist/esm/utils/url.js.map +1 -0
  374. package/dist/esm/utils/wallet.d.ts +1 -2
  375. package/dist/esm/utils/wallet.d.ts.map +1 -1
  376. package/package.json +9 -9
  377. package/src/components/AmountInputCard/ReceiveAmountCard.tsx +16 -3
  378. package/src/components/BottomSheet/BottomSheet.tsx +3 -0
  379. package/src/components/Token/Token.tsx +2 -1
  380. package/src/components/TokenList/RecentTokensHeader.tsx +52 -0
  381. package/src/components/TokenList/RecentTokensToggle.tsx +45 -0
  382. package/src/components/TokenList/RemoveRecentTokenButton.tsx +38 -0
  383. package/src/components/TokenList/TokenList.tsx +92 -3
  384. package/src/components/TokenList/TokenListItem.tsx +15 -0
  385. package/src/components/TokenList/VirtualizedTokenList.tsx +84 -125
  386. package/src/components/TokenList/types.ts +9 -0
  387. package/src/config/version.ts +1 -1
  388. package/src/hooks/useDisplayedTokens.ts +17 -3
  389. package/src/hooks/useExplorer.test.tsx +106 -0
  390. package/src/hooks/useExplorer.ts +11 -5
  391. package/src/hooks/useRecentTokens.ts +88 -0
  392. package/src/hooks/useRoutes.ts +8 -5
  393. package/src/hooks/useToAddressRequirements.ts +11 -5
  394. package/src/hooks/useTokenBalances.ts +34 -31
  395. package/src/hooks/useTokenSearch.ts +5 -14
  396. package/src/hooks/useTokens.ts +69 -27
  397. package/src/pages/SendToWallet/BookmarksPage.tsx +3 -3
  398. package/src/pages/SendToWallet/ConnectedWalletsPage.tsx +3 -3
  399. package/src/pages/SendToWallet/RecentWalletsPage.tsx +3 -3
  400. package/src/pages/SendToWallet/SendToConfiguredWalletPage.tsx +3 -3
  401. package/src/pages/TransactionDetailsPage/TransactionDetailsPage.tsx +5 -5
  402. package/src/pages/TransactionDetailsPage/TransferIdCard.tsx +2 -1
  403. package/src/pages/TransactionPage/TokenValueBottomSheet.tsx +1 -1
  404. package/src/pages/TransactionPage/TokenVerificationBottomSheet.tsx +1 -1
  405. package/src/pages/TransactionPage/TransactionFailedButtons.tsx +62 -26
  406. package/src/pages/TransactionPage/TransactionReview.tsx +36 -37
  407. package/src/pages/TransactionPage/utils.ts +78 -0
  408. package/src/shared.ts +1 -0
  409. package/src/stores/StoreProvider.tsx +10 -7
  410. package/src/stores/chains/ChainOrderStore.test.tsx +298 -0
  411. package/src/stores/chains/ChainOrderStore.tsx +25 -6
  412. package/src/stores/recentTokens/RecentTokensStore.tsx +39 -0
  413. package/src/stores/recentTokens/createRecentTokensStore.ts +107 -0
  414. package/src/stores/recentTokens/types.ts +37 -0
  415. package/src/stores/recentTokens/utils.ts +18 -0
  416. package/src/types/token.ts +2 -0
  417. package/src/types/widget.ts +5 -0
  418. package/src/utils/address.ts +21 -0
  419. package/src/utils/customReceiver.ts +24 -0
  420. package/src/utils/recentTokens.ts +187 -0
  421. package/src/utils/token.ts +69 -10
  422. package/src/utils/tokenList.ts +41 -23
  423. package/src/utils/tokenListBands.ts +181 -0
  424. package/src/utils/url.ts +17 -0
@@ -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
 
@@ -12,6 +12,7 @@ import { useSDKClient } from '../providers/SDKClientProvider.js'
12
12
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
13
13
  import type { FormType } from '../stores/form/types.js'
14
14
  import type { TokensByChain } from '../types/token.js'
15
+ import { isAddressQuery } from '../utils/address.js'
15
16
  import { defaultChainIdsByType } from '../utils/chainType.js'
16
17
  import { isItemAllowed } from '../utils/item.js'
17
18
  import { getQueryKey } from '../utils/queries.js'
@@ -32,6 +33,8 @@ export const useTokens = (
32
33
  allTokens: Record<number, TokenExtended[]> | undefined
33
34
  isLoading: boolean
34
35
  isSearchLoading: boolean
36
+ /** The search is a contract address, so only the token at that address matches. */
37
+ isAddressSearch: boolean
35
38
  } => {
36
39
  const {
37
40
  tokens: configTokens,
@@ -39,7 +42,16 @@ export const useTokens = (
39
42
  keyPrefix,
40
43
  } = useWidgetConfig()
41
44
  const sdkClient = useSDKClient()
42
- const { getChainTypeFromAddress } = useChainTypeFromAddress()
45
+ const { getChainTypeFromTokenAddress } = useChainTypeFromAddress()
46
+ // A pasted address often carries a trailing space or newline, which the
47
+ // API rejects. Trim once so the key, the requests and the checks agree.
48
+ const trimmedSearch = search?.trim()
49
+ // Keep this memoized, and out of any per-token loop: a provider validates by
50
+ // parsing, which costs microseconds per call rather than nanoseconds.
51
+ const isAddressSearch = useMemo(
52
+ () => isAddressQuery(trimmedSearch, getChainTypeFromTokenAddress),
53
+ [trimmedSearch, getChainTypeFromTokenAddress]
54
+ )
43
55
 
44
56
  // Main tokens cache - verified tokens from API
45
57
  const { data: verifiedTokens, isLoading } = useQuery({
@@ -82,13 +94,14 @@ export const useTokens = (
82
94
 
83
95
  // Search tokens cache - unverified tokens from search
84
96
  const { data: searchTokens, isLoading: isSearchLoading } = useQuery({
85
- queryKey: [getQueryKey('tokens-search', keyPrefix), search, chainId],
97
+ queryKey: [
98
+ getQueryKey('tokens-search', keyPrefix),
99
+ trimmedSearch,
100
+ chainId,
101
+ isAddressSearch,
102
+ ] as const,
86
103
  queryFn: async ({ queryKey, signal }) => {
87
- const [, searchQuery, searchChainId] = queryKey as [
88
- string,
89
- string,
90
- number,
91
- ]
104
+ const [, searchQuery, searchChainId, addressSearch] = queryKey
92
105
  const chainTypes = [
93
106
  ChainType.EVM,
94
107
  ChainType.SVM,
@@ -111,32 +124,60 @@ export const useTokens = (
111
124
  { signal }
112
125
  )
113
126
 
114
- // If the chainId is not provided, try to get it from the search query
115
- let _chainId = searchChainId
116
- if (!_chainId) {
117
- const chainType = getChainTypeFromAddress(searchQuery)
118
- if (chainType && chainType in defaultChainIdsByType) {
119
- _chainId = defaultChainIdsByType[chainType]
120
- }
121
- }
122
-
123
- // Fallback: If the main search returned no tokens for the specific chainId,
124
- // fetch a single token using the /token endpoint
125
- if (_chainId && searchQuery) {
126
- const existingTokens = tokensResponse.tokens[_chainId] || []
127
- if (!existingTokens.length) {
128
- const token = await getToken(sdkClient, _chainId, searchQuery, {
129
- signal,
130
- })
131
- if (token) {
132
- tokensResponse.tokens[_chainId] = [token]
127
+ // Fallback: fetch a single token from the /token endpoint when the
128
+ // search did not deliver one. Look it up on the selected chain, or
129
+ // without one on the default chain of the address format.
130
+ if (searchQuery) {
131
+ const chainType = getChainTypeFromTokenAddress(searchQuery)
132
+ const lookupChainId =
133
+ searchChainId ??
134
+ (chainType ? defaultChainIdsByType[chainType] : undefined)
135
+ if (lookupChainId) {
136
+ const existingTokens = tokensResponse.tokens[lookupChainId] ?? []
137
+ // The search index also matches names, so for an address query
138
+ // impersonators that embed the address can fill the list while the
139
+ // token at that address is missing. Without a selected chain the
140
+ // token can sit on any chain of the response.
141
+ const hasTokenAtAddress = () => {
142
+ const address = searchQuery.toLowerCase()
143
+ const candidates = searchChainId
144
+ ? [existingTokens]
145
+ : Object.values(tokensResponse.tokens)
146
+ return candidates.some((tokens) =>
147
+ tokens.some((token) => token.address?.toLowerCase() === address)
148
+ )
149
+ }
150
+ const isTokenMissing = addressSearch
151
+ ? !hasTokenAtAddress()
152
+ : !existingTokens.length
153
+ if (isTokenMissing) {
154
+ try {
155
+ const token = await getToken(
156
+ sdkClient,
157
+ lookupChainId,
158
+ searchQuery,
159
+ { signal }
160
+ )
161
+ if (token) {
162
+ tokensResponse.tokens[lookupChainId] = [
163
+ ...existingTokens,
164
+ token,
165
+ ]
166
+ }
167
+ } catch (error) {
168
+ // A guessed chain may not hold the token (HTTP 400). Keep the
169
+ // search results instead of failing the whole query.
170
+ if (signal.aborted) {
171
+ throw error
172
+ }
173
+ }
133
174
  }
134
175
  }
135
176
  }
136
177
 
137
178
  return tokensResponse.tokens as TokensByChain
138
179
  },
139
- enabled: !!search,
180
+ enabled: !!trimmedSearch,
140
181
  refetchInterval,
141
182
  staleTime: refetchInterval,
142
183
  })
@@ -170,5 +211,6 @@ export const useTokens = (
170
211
  allTokens,
171
212
  isLoading,
172
213
  isSearchLoading,
214
+ isAddressSearch,
173
215
  }
174
216
  }
@@ -23,6 +23,7 @@ import { useBookmarks } from '../../stores/bookmarks/useBookmarks.js'
23
23
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
24
24
  import { defaultChainIdsByType } from '../../utils/chainType.js'
25
25
  import { navigationRoutes } from '../../utils/navigationRoutes.js'
26
+ import { openInNewTab } from '../../utils/url.js'
26
27
  import { shortenAddress } from '../../utils/wallet.js'
27
28
  import { BookmarkAddressSheet } from './BookmarkAddressSheet.js'
28
29
  import { BookmarkButtonContainer } from './SendToWalletPage.style.js'
@@ -106,12 +107,11 @@ export const BookmarksPage = (): JSX.Element => {
106
107
  icon: <OpenInNewRounded />,
107
108
  label: t('button.viewOnExplorer'),
108
109
  onClick: () =>
109
- window.open(
110
+ openInNewTab(
110
111
  getAddressLink(
111
112
  bookmark.address,
112
113
  defaultChainIdsByType[bookmark.chainType]
113
- ),
114
- '_blank'
114
+ )
115
115
  ),
116
116
  },
117
117
  {
@@ -20,6 +20,7 @@ import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.j
20
20
  import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js'
21
21
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
22
22
  import { navigationRoutes } from '../../utils/navigationRoutes.js'
23
+ import { openInNewTab } from '../../utils/url.js'
23
24
  import { shortenAddress } from '../../utils/wallet.js'
24
25
 
25
26
  export const ConnectedWalletsPage = (): JSX.Element => {
@@ -81,9 +82,8 @@ export const ConnectedWalletsPage = (): JSX.Element => {
81
82
  label: t('button.viewOnExplorer'),
82
83
  onClick: () => {
83
84
  if (account.address) {
84
- window.open(
85
- getAddressLink(account.address, account.chainId),
86
- '_blank'
85
+ openInNewTab(
86
+ getAddressLink(account.address, account.chainId)
87
87
  )
88
88
  }
89
89
  },
@@ -24,6 +24,7 @@ import { useBookmarks } from '../../stores/bookmarks/useBookmarks.js'
24
24
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
25
25
  import { defaultChainIdsByType } from '../../utils/chainType.js'
26
26
  import { navigationRoutes } from '../../utils/navigationRoutes.js'
27
+ import { openInNewTab } from '../../utils/url.js'
27
28
  import { shortenAddress } from '../../utils/wallet.js'
28
29
  import { BookmarkAddressSheet } from './BookmarkAddressSheet.js'
29
30
 
@@ -118,12 +119,11 @@ export const RecentWalletsPage = (): JSX.Element => {
118
119
  icon: <OpenInNewRounded />,
119
120
  label: t('button.viewOnExplorer'),
120
121
  onClick: () =>
121
- window.open(
122
+ openInNewTab(
122
123
  getAddressLink(
123
124
  recentWallet.address,
124
125
  defaultChainIdsByType[recentWallet.chainType]
125
- ),
126
- '_blank'
126
+ )
127
127
  ),
128
128
  },
129
129
  {
@@ -18,6 +18,7 @@ import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js
18
18
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
19
19
  import type { ToAddress } from '../../types/widget.js'
20
20
  import { defaultChainIdsByType } from '../../utils/chainType.js'
21
+ import { openInNewTab } from '../../utils/url.js'
21
22
  import { shortenAddress } from '../../utils/wallet.js'
22
23
 
23
24
  export const SendToConfiguredWalletPage = (): JSX.Element => {
@@ -92,12 +93,11 @@ export const SendToConfiguredWalletPage = (): JSX.Element => {
92
93
  icon: <OpenInNewRounded />,
93
94
  label: t('button.viewOnExplorer'),
94
95
  onClick: () =>
95
- window.open(
96
+ openInNewTab(
96
97
  getAddressLink(
97
98
  toAddress.address,
98
99
  defaultChainIdsByType[toAddress.chainType]
99
- ),
100
- '_blank'
100
+ )
101
101
  ),
102
102
  },
103
103
  ]}
@@ -15,6 +15,7 @@ import { useRouteExecutionStore } from '../../stores/routes/RouteExecutionStore.
15
15
  import { getSourceTxHash } from '../../stores/routes/utils.js'
16
16
  import { buildRouteFromTxHistory } from '../../utils/converters.js'
17
17
  import { navigationRoutes } from '../../utils/navigationRoutes.js'
18
+ import { isHttpUrl } from '../../utils/url.js'
18
19
  import { ReceiptsCard } from './ReceiptsCard.js'
19
20
  import { TransactionDetailsSkeleton } from './TransactionDetailsSkeleton.js'
20
21
  import { TransferIdCard } from './TransferIdCard.js'
@@ -70,11 +71,10 @@ export const TransactionDetailsPage: React.FC = () => {
70
71
  routeExecution?.route?.steps?.at(-1)?.execution?.externalTxLink
71
72
 
72
73
  const txLink =
73
- (url
74
- ? internalTxLink?.replace(internalExplorerUrl, url)
75
- : internalTxLink) ||
76
- externalTxLink ||
77
- getTransactionLink({ txHash: supportId })
74
+ [
75
+ url ? internalTxLink?.replace(internalExplorerUrl, url) : internalTxLink,
76
+ externalTxLink,
77
+ ].find(isHttpUrl) ?? getTransactionLink({ txHash: supportId })
78
78
 
79
79
  if (process.env.NODE_ENV === 'development') {
80
80
  supportId += `_${routeExecution?.route.id}`
@@ -7,6 +7,7 @@ import { Card } from '../../components/Card/Card.js'
7
7
  import { CardIconButton } from '../../components/Card/CardIconButton.js'
8
8
  import { CardTitle } from '../../components/Card/CardTitle.js'
9
9
  import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
10
+ import { openInNewTab } from '../../utils/url.js'
10
11
  import { ContactSupportButton } from './ContactSupportButton.js'
11
12
 
12
13
  interface TransferIdCardProps {
@@ -26,7 +27,7 @@ export const TransferIdCard = ({
26
27
  }
27
28
 
28
29
  const openTransferIdInExplorer = () => {
29
- window.open(txLink, '_blank')
30
+ openInNewTab(txLink)
30
31
  }
31
32
 
32
33
  return (
@@ -36,8 +36,8 @@ export const TokenValueBottomSheet = ({
36
36
  ref?: Ref<BottomSheetBase>
37
37
  }): JSX.Element => {
38
38
  const handleCancel = () => {
39
+ // close() reaches onClose, which is onCancel
39
40
  ;(ref as RefObject<BottomSheetBase>).current?.close()
40
- onCancel?.()
41
41
  }
42
42
 
43
43
  return (
@@ -31,8 +31,8 @@ export const TokenVerificationBottomSheet = ({
31
31
  ref?: Ref<BottomSheetBase>
32
32
  }): JSX.Element => {
33
33
  const handleCancel = () => {
34
+ // close() reaches onClose, which is onCancel
34
35
  ;(ref as RefObject<BottomSheetBase>).current?.close()
35
- onCancel?.()
36
36
  }
37
37
 
38
38
  return (
@@ -5,12 +5,20 @@ import { useTranslation } from 'react-i18next'
5
5
  import type { BottomSheetBase } from '../../components/BottomSheet/types.js'
6
6
  import { useAddressActivity } from '../../hooks/useAddressActivity.js'
7
7
  import { useNavigateBack } from '../../hooks/useNavigateBack.js'
8
+ import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
8
9
  import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
10
+ import { WidgetEvent } from '../../types/events.js'
9
11
  import { getAccumulatedFeeCostsBreakdown } from '../../utils/fees.js'
10
12
  import { ConfirmToAddressSheet } from './ConfirmToAddressSheet.js'
11
13
  import { StartTransactionButton } from './StartTransactionButton.js'
12
14
  import { TokenValueBottomSheet } from './TokenValueBottomSheet.js'
13
- import { getTokenValueLossThreshold } from './utils.js'
15
+ import type { RetryGate } from './utils.js'
16
+ import {
17
+ calculateValueLossPercentage,
18
+ getRetryGates,
19
+ getTokenValueLossThreshold,
20
+ openNextGate,
21
+ } from './utils.js'
14
22
 
15
23
  interface TransactionFailedButtonsProps {
16
24
  route: RouteExtended
@@ -22,6 +30,7 @@ export const TransactionFailedButtons: React.FC<
22
30
  TransactionFailedButtonsProps
23
31
  > = ({ route, restartRoute, deleteRoute }) => {
24
32
  const { t } = useTranslation()
33
+ const emitter = useWidgetEvents()
25
34
  const navigateBack = useNavigateBack()
26
35
  const { mode, hiddenUI } = useWidgetConfig()
27
36
 
@@ -40,34 +49,61 @@ export const TransactionFailedButtons: React.FC<
40
49
  deleteRoute()
41
50
  }
42
51
 
43
- const handleRetryClick = () => {
44
- if (
45
- toAddress &&
46
- !hasActivity &&
47
- !isLoadingAddressActivity &&
48
- isActivityAddressFetched &&
49
- !hiddenUI?.lowAddressActivityConfirmation
50
- ) {
51
- confirmToAddressSheetRef.current?.open()
52
- return
53
- }
54
-
52
+ const retryGates = (() => {
55
53
  const { gasCostUSD, feeCostUSD } = getAccumulatedFeeCostsBreakdown(route)
56
- const fromAmountUSD = Number.parseFloat(route.fromAmountUSD)
57
- const toAmountUSD = Number.parseFloat(route.toAmountUSD)
58
- const tokenValueLossThresholdExceeded = getTokenValueLossThreshold(
59
- fromAmountUSD,
60
- toAmountUSD,
61
- gasCostUSD,
62
- feeCostUSD
54
+ return getRetryGates({
55
+ toAddress,
56
+ hasActivity,
57
+ isLoadingAddressActivity,
58
+ isActivityAddressFetched,
59
+ confirmationHidden: Boolean(hiddenUI?.lowAddressActivityConfirmation),
60
+ valueLossExceeded: getTokenValueLossThreshold(
61
+ Number.parseFloat(route.fromAmountUSD),
62
+ Number.parseFloat(route.toAmountUSD),
63
+ gasCostUSD,
64
+ feeCostUSD
65
+ ),
66
+ isCustomMode: mode === 'custom',
67
+ })
68
+ })()
69
+
70
+ const openGate = (after?: RetryGate) =>
71
+ openNextGate(
72
+ retryGates,
73
+ {
74
+ address: () => confirmToAddressSheetRef.current?.open(),
75
+ value: () => tokenValueBottomSheetRef.current?.open(),
76
+ },
77
+ handleRestartRoute,
78
+ after
63
79
  )
64
- if (tokenValueLossThresholdExceeded && mode !== 'custom') {
65
- tokenValueBottomSheetRef.current?.open()
66
- } else {
67
- restartRoute()
80
+
81
+ const handleRestartRoute = () => {
82
+ if (tokenValueBottomSheetRef.current?.isOpen()) {
83
+ const { gasCostUSD, feeCostUSD } = getAccumulatedFeeCostsBreakdown(route)
84
+ const fromAmountUSD = Number.parseFloat(route.fromAmountUSD)
85
+ const toAmountUSD = Number.parseFloat(route.toAmountUSD)
86
+ emitter.emit(WidgetEvent.RouteHighValueLoss, {
87
+ fromAmountUSD,
88
+ toAmountUSD,
89
+ gasCostUSD,
90
+ feeCostUSD,
91
+ valueLoss: calculateValueLossPercentage(
92
+ fromAmountUSD,
93
+ toAmountUSD,
94
+ gasCostUSD,
95
+ feeCostUSD
96
+ ),
97
+ })
68
98
  }
99
+ tokenValueBottomSheetRef.current?.close()
100
+ restartRoute()
69
101
  }
70
102
 
103
+ const handleRetryClick = () => openGate()
104
+
105
+ const handleConfirmToAddressContinue = () => openGate('address')
106
+
71
107
  return (
72
108
  <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
73
109
  <Box sx={{ display: 'flex', gap: 1.5 }}>
@@ -89,13 +125,13 @@ export const TransactionFailedButtons: React.FC<
89
125
  <TokenValueBottomSheet
90
126
  route={route}
91
127
  ref={tokenValueBottomSheetRef}
92
- onContinue={restartRoute}
128
+ onContinue={handleRestartRoute}
93
129
  />
94
130
  ) : null}
95
131
  {!hiddenUI?.lowAddressActivityConfirmation ? (
96
132
  <ConfirmToAddressSheet
97
133
  ref={confirmToAddressSheetRef}
98
- onContinue={restartRoute}
134
+ onContinue={handleConfirmToAddressContinue}
99
135
  toAddress={toAddress!}
100
136
  toChainId={route.toChainId!}
101
137
  />