@lifi/widget 4.4.0 → 4.6.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 (329) hide show
  1. package/dist/esm/App.js.map +1 -1
  2. package/dist/esm/AppDrawer.js +2 -1
  3. package/dist/esm/AppDrawer.js.map +1 -1
  4. package/dist/esm/AppLayout.js.map +1 -1
  5. package/dist/esm/AppProvider.js.map +1 -1
  6. package/dist/esm/components/ActionRow/ActionRow.js.map +1 -1
  7. package/dist/esm/components/AmountInput/AmountInput.js +13 -7
  8. package/dist/esm/components/AmountInput/AmountInput.js.map +1 -1
  9. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +2 -13
  10. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
  11. package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
  12. package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -1
  13. package/dist/esm/components/AmountInputCard/BalanceDisplay.js.map +1 -1
  14. package/dist/esm/components/AmountInputCard/FiatValueToggle.js.map +1 -1
  15. package/dist/esm/components/AmountInputCard/PercentageChips.js +2 -13
  16. package/dist/esm/components/AmountInputCard/PercentageChips.js.map +1 -1
  17. package/dist/esm/components/AmountInputCard/PercentageChips.style.js +1 -1
  18. package/dist/esm/components/AmountInputCard/PercentageChips.style.js.map +1 -1
  19. package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js.map +1 -1
  20. package/dist/esm/components/AmountInputCard/SendAmountCard.js +13 -6
  21. package/dist/esm/components/AmountInputCard/SendAmountCard.js.map +1 -1
  22. package/dist/esm/components/AppContainer.js.map +1 -1
  23. package/dist/esm/components/Avatar/AccountAvatar.js.map +1 -1
  24. package/dist/esm/components/Avatar/Avatar.js.map +1 -1
  25. package/dist/esm/components/Avatar/ChainBadgeContent.js.map +1 -1
  26. package/dist/esm/components/Avatar/TokenAvatar.js.map +1 -1
  27. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
  28. package/dist/esm/components/Card/CardButton.js.map +1 -1
  29. package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
  30. package/dist/esm/components/Chains/AllChainsAvatar.js +7 -1
  31. package/dist/esm/components/Chains/AllChainsAvatar.js.map +1 -1
  32. package/dist/esm/components/Chains/ChainList.js.map +1 -1
  33. package/dist/esm/components/Chains/ChainListItem.js.map +1 -1
  34. package/dist/esm/components/Chains/ChainsExpanded.js.map +1 -1
  35. package/dist/esm/components/Chains/PinChainButton.js.map +1 -1
  36. package/dist/esm/components/Chains/SelectChainExpansionContent.js.map +1 -1
  37. package/dist/esm/components/Chains/SelectChainPageContent.js.map +1 -1
  38. package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
  39. package/dist/esm/components/ContextMenu.js.map +1 -1
  40. package/dist/esm/components/ContractComponent/NFT/NFTBase.js.map +1 -1
  41. package/dist/esm/components/Dialog/Dialog.js +2 -1
  42. package/dist/esm/components/Dialog/Dialog.js.map +1 -1
  43. package/dist/esm/components/ExecutionStatusCard/ExecutionChecklist.js.map +1 -1
  44. package/dist/esm/components/ExecutionStatusCard/ExecutionStatusCard.js.map +1 -1
  45. package/dist/esm/components/ExecutionStatusCard/StaggeredRevealTypography.js.map +1 -1
  46. package/dist/esm/components/ExecutionStatusCard/StatusIcon.js.map +1 -1
  47. package/dist/esm/components/Expansion/Expansion.js +4 -3
  48. package/dist/esm/components/Expansion/Expansion.js.map +1 -1
  49. package/dist/esm/components/Expansion/ExpansionTransition.js.map +1 -1
  50. package/dist/esm/components/FeeBreakdownTooltip.js.map +1 -1
  51. package/dist/esm/components/Header/ActivitiesButton.js.map +1 -1
  52. package/dist/esm/components/Header/BackButton.js.map +1 -1
  53. package/dist/esm/components/Header/CloseDrawerButton.js.map +1 -1
  54. package/dist/esm/components/Header/DisconnectIconButton.js.map +1 -1
  55. package/dist/esm/components/Header/HeaderTabs.js.map +1 -1
  56. package/dist/esm/components/Header/NavigationHeader.js.map +1 -1
  57. package/dist/esm/components/Header/SettingsButton.js +2 -1
  58. package/dist/esm/components/Header/SettingsButton.js.map +1 -1
  59. package/dist/esm/components/Header/WalletHeader.js.map +1 -1
  60. package/dist/esm/components/Header/WalletMenu.js.map +1 -1
  61. package/dist/esm/components/IconCircle/IconCircle.js +2 -1
  62. package/dist/esm/components/IconCircle/IconCircle.js.map +1 -1
  63. package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.js.map +1 -1
  64. package/dist/esm/components/LimitPriceCard/LimitPriceCard.js.map +1 -1
  65. package/dist/esm/components/LimitPriceCard/LimitPricePresets.js.map +1 -1
  66. package/dist/esm/components/Messages/AccountDeployedMessage.js.map +1 -1
  67. package/dist/esm/components/Messages/AccountNotDeployedMessage.js.map +1 -1
  68. package/dist/esm/components/Messages/AlertMessage.js.map +1 -1
  69. package/dist/esm/components/Messages/FundsSufficiencyMessage.js.map +1 -1
  70. package/dist/esm/components/Messages/GasRefuelMessage.js.map +1 -1
  71. package/dist/esm/components/Messages/GasSufficiencyMessage.js.map +1 -1
  72. package/dist/esm/components/Messages/MinFromAmountUSDMessage.js.map +1 -1
  73. package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.js.map +1 -1
  74. package/dist/esm/components/Messages/UnsupportedToAddressMessage.js +27 -0
  75. package/dist/esm/components/Messages/UnsupportedToAddressMessage.js.map +1 -0
  76. package/dist/esm/components/Messages/WarningMessages.d.ts.map +1 -1
  77. package/dist/esm/components/Messages/WarningMessages.js +2 -0
  78. package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
  79. package/dist/esm/components/Messages/useMessageQueue.js +6 -1
  80. package/dist/esm/components/Messages/useMessageQueue.js.map +1 -1
  81. package/dist/esm/components/NotFound.js.map +1 -1
  82. package/dist/esm/components/PoweredBy/PoweredBy.js.map +1 -1
  83. package/dist/esm/components/ProgressToNextUpdate.js.map +1 -1
  84. package/dist/esm/components/ReverseTokensButton/ReverseTokensButton.js.map +1 -1
  85. package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
  86. package/dist/esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
  87. package/dist/esm/components/RouteCard/RouteCardSkeleton.js.map +1 -1
  88. package/dist/esm/components/RouteCard/RouteDetails.js +2 -1
  89. package/dist/esm/components/RouteCard/RouteDetails.js.map +1 -1
  90. package/dist/esm/components/RouteCard/RouteNotFoundCard.js.map +1 -1
  91. package/dist/esm/components/RouteCard/RouteProviderCard.js.map +1 -1
  92. package/dist/esm/components/RouteCard/RouteToken.js.map +1 -1
  93. package/dist/esm/components/RouteCard/RouteTokens.js.map +1 -1
  94. package/dist/esm/components/Routes/LimitOrderRoutes.js +2 -2
  95. package/dist/esm/components/Routes/LimitOrderRoutes.js.map +1 -1
  96. package/dist/esm/components/Routes/Routes.js.map +1 -1
  97. package/dist/esm/components/Routes/RoutesContent.js +2 -2
  98. package/dist/esm/components/Routes/RoutesContent.js.map +1 -1
  99. package/dist/esm/components/Routes/RoutesExpanded.js.map +1 -1
  100. package/dist/esm/components/Search/SearchInput.js.map +1 -1
  101. package/dist/esm/components/SelectChainAndToken.js.map +1 -1
  102. package/dist/esm/components/SelectTokenButton/SelectTokenButton.js.map +1 -1
  103. package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
  104. package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js +2 -2
  105. package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js.map +1 -1
  106. package/dist/esm/components/SettingsPanel/SettingsPanel.js.map +1 -1
  107. package/dist/esm/components/Skeleton/WidgetSkeleton.js +2 -1
  108. package/dist/esm/components/Skeleton/WidgetSkeleton.js.map +1 -1
  109. package/dist/esm/components/Step/StepActions.js +18 -16
  110. package/dist/esm/components/Step/StepActions.js.map +1 -1
  111. package/dist/esm/components/StepActions/SentToWalletRow.js.map +1 -1
  112. package/dist/esm/components/StepActions/StepActionRow.js +2 -1
  113. package/dist/esm/components/StepActions/StepActionRow.js.map +1 -1
  114. package/dist/esm/components/StepActions/StepActionsList.js.map +1 -1
  115. package/dist/esm/components/SwapButton/SwapButton.js.map +1 -1
  116. package/dist/esm/components/Switch.js +1 -1
  117. package/dist/esm/components/Switch.js.map +1 -1
  118. package/dist/esm/components/Tabs/Tabs.style.js +4 -2
  119. package/dist/esm/components/Tabs/Tabs.style.js.map +1 -1
  120. package/dist/esm/components/TextFitter/TextFitter.js.map +1 -1
  121. package/dist/esm/components/Timer/StepStatusTimer.js.map +1 -1
  122. package/dist/esm/components/Token/Token.js.map +1 -1
  123. package/dist/esm/components/TokenList/PinTokenButton.js.map +1 -1
  124. package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -1
  125. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -1
  126. package/dist/esm/components/TokenList/TokenList.js.map +1 -1
  127. package/dist/esm/components/TokenList/TokenListItem.js +46 -8
  128. package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
  129. package/dist/esm/components/TokenList/VirtualizedTokenList.js +22 -9
  130. package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
  131. package/dist/esm/components/TokenPillButton/TokenPillButton.js.map +1 -1
  132. package/dist/esm/components/TokenRate/TokenRate.js +2 -1
  133. package/dist/esm/components/TokenRate/TokenRate.js.map +1 -1
  134. package/dist/esm/components/Tools/ToolItem.js.map +1 -1
  135. package/dist/esm/components/Tools/Tools.js.map +1 -1
  136. package/dist/esm/components/TransactionCard/ActiveTransactionCard.js +22 -21
  137. package/dist/esm/components/TransactionCard/ActiveTransactionCard.js.map +1 -1
  138. package/dist/esm/components/TransactionCard/TransactionCard.js.map +1 -1
  139. package/dist/esm/components/TransactionCard/TransactionCardSkeleton.js.map +1 -1
  140. package/dist/esm/config/version.d.ts +1 -1
  141. package/dist/esm/config/version.js +1 -1
  142. package/dist/esm/config/version.js.map +1 -1
  143. package/dist/esm/hooks/timer/time.js +2 -2
  144. package/dist/esm/hooks/timer/time.js.map +1 -1
  145. package/dist/esm/hooks/useAccountsBalancesData.js +1 -14
  146. package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
  147. package/dist/esm/hooks/useAvailableChains.d.ts.map +1 -1
  148. package/dist/esm/hooks/useAvailableChains.js +2 -1
  149. package/dist/esm/hooks/useAvailableChains.js.map +1 -1
  150. package/dist/esm/hooks/useExplorer.d.ts.map +1 -1
  151. package/dist/esm/hooks/useExplorer.js +4 -0
  152. package/dist/esm/hooks/useExplorer.js.map +1 -1
  153. package/dist/esm/hooks/useFlaggedTokenGuard.js +28 -0
  154. package/dist/esm/hooks/useFlaggedTokenGuard.js.map +1 -0
  155. package/dist/esm/hooks/useGasSufficiency.js +3 -1
  156. package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
  157. package/dist/esm/hooks/useMaxSendAmount.js +15 -0
  158. package/dist/esm/hooks/useMaxSendAmount.js.map +1 -0
  159. package/dist/esm/hooks/usePacedRouteExecution.js +3 -2
  160. package/dist/esm/hooks/usePacedRouteExecution.js.map +1 -1
  161. package/dist/esm/hooks/useRouteExecutionMessage.js +3 -2
  162. package/dist/esm/hooks/useRouteExecutionMessage.js.map +1 -1
  163. package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
  164. package/dist/esm/hooks/useRoutes.js +3 -1
  165. package/dist/esm/hooks/useRoutes.js.map +1 -1
  166. package/dist/esm/hooks/useToAddressAutoPopulate.js.map +1 -1
  167. package/dist/esm/hooks/useToAddressRequirements.d.ts +2 -0
  168. package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
  169. package/dist/esm/hooks/useToAddressRequirements.js +7 -1
  170. package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
  171. package/dist/esm/hooks/useTokenBalances.d.ts.map +1 -1
  172. package/dist/esm/hooks/useTokenBalances.js +7 -2
  173. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  174. package/dist/esm/hooks/useTokenBalancesQueries.js +32 -29
  175. package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -1
  176. package/dist/esm/hooks/useTokenSearch.js +3 -5
  177. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  178. package/dist/esm/hooks/useTokens.js +14 -10
  179. package/dist/esm/hooks/useTokens.js.map +1 -1
  180. package/dist/esm/hooks/useWideVariant.js +2 -1
  181. package/dist/esm/hooks/useWideVariant.js.map +1 -1
  182. package/dist/esm/i18n/bn.json +3 -1
  183. package/dist/esm/i18n/de.json +3 -1
  184. package/dist/esm/i18n/en.json +12 -3
  185. package/dist/esm/i18n/es.json +3 -1
  186. package/dist/esm/i18n/fr.json +3 -1
  187. package/dist/esm/i18n/hi.json +3 -1
  188. package/dist/esm/i18n/id.json +3 -1
  189. package/dist/esm/i18n/it.json +3 -1
  190. package/dist/esm/i18n/ja.json +3 -1
  191. package/dist/esm/i18n/ko.json +3 -1
  192. package/dist/esm/i18n/pl.json +3 -1
  193. package/dist/esm/i18n/pt.json +3 -1
  194. package/dist/esm/i18n/th.json +3 -1
  195. package/dist/esm/i18n/tr.json +3 -1
  196. package/dist/esm/i18n/uk.json +3 -1
  197. package/dist/esm/i18n/vi.json +3 -1
  198. package/dist/esm/i18n/zh.json +3 -1
  199. package/dist/esm/pages/ActivitiesPage/ActivitiesPage.js.map +1 -1
  200. package/dist/esm/pages/ActivitiesPage/ActivitiesPageMenuButton.js.map +1 -1
  201. package/dist/esm/pages/LanguagesPage.js.map +1 -1
  202. package/dist/esm/pages/MainPage/LimitPageContent.js.map +1 -1
  203. package/dist/esm/pages/MainPage/MainPage.js +2 -1
  204. package/dist/esm/pages/MainPage/MainPage.js.map +1 -1
  205. package/dist/esm/pages/MainPage/MainPageActions.js.map +1 -1
  206. package/dist/esm/pages/MainPage/ReviewButton.js +2 -2
  207. package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
  208. package/dist/esm/pages/RoutePriorityPage.js.map +1 -1
  209. package/dist/esm/pages/RoutesPage/RoutesPage.js +2 -2
  210. package/dist/esm/pages/RoutesPage/RoutesPage.js.map +1 -1
  211. package/dist/esm/pages/SelectChainPage/SelectChainPage.js +13 -12
  212. package/dist/esm/pages/SelectChainPage/SelectChainPage.js.map +1 -1
  213. package/dist/esm/pages/SelectEnabledToolsPage.js +8 -5
  214. package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
  215. package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js +2 -1
  216. package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js.map +1 -1
  217. package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js.map +1 -1
  218. package/dist/esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
  219. package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.js.map +1 -1
  220. package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
  221. package/dist/esm/pages/SendToWallet/RecentWalletsPage.js.map +1 -1
  222. package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js.map +1 -1
  223. package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
  224. package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js.map +1 -1
  225. package/dist/esm/pages/SettingsPage/GasPriceSettings.js.map +1 -1
  226. package/dist/esm/pages/SettingsPage/LanguageSetting.js.map +1 -1
  227. package/dist/esm/pages/SettingsPage/ResetSettingsButton.js.map +1 -1
  228. package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js.map +1 -1
  229. package/dist/esm/pages/SettingsPage/SettingsCard/BadgedValue.js.map +1 -1
  230. package/dist/esm/pages/SettingsPage/SettingsCard/SettingCardExpandable.js.map +1 -1
  231. package/dist/esm/pages/SettingsPage/SettingsPage.js.map +1 -1
  232. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippagePage.js.map +1 -1
  233. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js.map +1 -1
  234. package/dist/esm/pages/SettingsPage/SmallBalanceFilterSettings.js +2 -1
  235. package/dist/esm/pages/SettingsPage/SmallBalanceFilterSettings.js.map +1 -1
  236. package/dist/esm/pages/SettingsPage/ThemeSettings.js.map +1 -1
  237. package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.js +2 -1
  238. package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.js.map +1 -1
  239. package/dist/esm/pages/TransactionDetailsPage/ReceiptsCard.js.map +1 -1
  240. package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js +2 -1
  241. package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
  242. package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsSkeleton.js.map +1 -1
  243. package/dist/esm/pages/TransactionDetailsPage/TransferIdCard.js.map +1 -1
  244. package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.js.map +1 -1
  245. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
  246. package/dist/esm/pages/TransactionPage/ExecutionDoneCard.js.map +1 -1
  247. package/dist/esm/pages/TransactionPage/StartTransactionButton.js +4 -3
  248. package/dist/esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
  249. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
  250. package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js +64 -0
  251. package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js.map +1 -0
  252. package/dist/esm/pages/TransactionPage/TransactionDoneButtons.js.map +1 -1
  253. package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js +19 -16
  254. package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js.map +1 -1
  255. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js +3 -1
  256. package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js.map +1 -1
  257. package/dist/esm/pages/TransactionPage/TransactionPage.js.map +1 -1
  258. package/dist/esm/pages/TransactionPage/TransactionReview.js +24 -2
  259. package/dist/esm/pages/TransactionPage/TransactionReview.js.map +1 -1
  260. package/dist/esm/providers/I18nProvider/I18nProvider.js +37 -36
  261. package/dist/esm/providers/I18nProvider/I18nProvider.js.map +1 -1
  262. package/dist/esm/providers/I18nProvider/types.d.ts.map +1 -1
  263. package/dist/esm/providers/ThemeProvider/ThemeProvider.js +2 -1
  264. package/dist/esm/providers/ThemeProvider/ThemeProvider.js.map +1 -1
  265. package/dist/esm/providers/WalletProvider/WalletProvider.js +10 -9
  266. package/dist/esm/providers/WalletProvider/WalletProvider.js.map +1 -1
  267. package/dist/esm/providers/WalletProvider/useExternalWalletProvider.js +7 -3
  268. package/dist/esm/providers/WalletProvider/useExternalWalletProvider.js.map +1 -1
  269. package/dist/esm/stores/StoreProvider.js.map +1 -1
  270. package/dist/esm/stores/form/FormStore.js.map +1 -1
  271. package/dist/esm/stores/form/FormUpdater.js.map +1 -1
  272. package/dist/esm/stores/navigationTabs/useNavigationTabsStore.js.map +1 -1
  273. package/dist/esm/stores/routes/useRouteExecutionIndicator.js +4 -3
  274. package/dist/esm/stores/routes/useRouteExecutionIndicator.js.map +1 -1
  275. package/dist/esm/types/token.d.ts +4 -1
  276. package/dist/esm/types/token.d.ts.map +1 -1
  277. package/dist/esm/utils/compactNumberFormatter.js +1 -3
  278. package/dist/esm/utils/compactNumberFormatter.js.map +1 -1
  279. package/dist/esm/utils/customReceiver.js +7 -0
  280. package/dist/esm/utils/customReceiver.js.map +1 -0
  281. package/dist/esm/utils/gas.js +24 -0
  282. package/dist/esm/utils/gas.js.map +1 -0
  283. package/dist/esm/utils/getErrorMessage.js +0 -1
  284. package/dist/esm/utils/getErrorMessage.js.map +1 -1
  285. package/dist/esm/utils/limitOrder.js +1 -1
  286. package/dist/esm/utils/limitOrder.js.map +1 -1
  287. package/dist/esm/utils/token.js +21 -4
  288. package/dist/esm/utils/token.js.map +1 -1
  289. package/dist/esm/utils/tokenList.js +37 -23
  290. package/dist/esm/utils/tokenList.js.map +1 -1
  291. package/package.json +15 -15
  292. package/src/components/AmountInput/AmountInputEndAdornment.tsx +2 -21
  293. package/src/components/AmountInputCard/PercentageChips.tsx +2 -18
  294. package/src/components/Chains/AllChainsAvatar.tsx +7 -1
  295. package/src/components/Messages/UnsupportedToAddressMessage.tsx +24 -0
  296. package/src/components/Messages/WarningMessages.tsx +3 -0
  297. package/src/components/Messages/useMessageQueue.ts +9 -0
  298. package/src/components/Routes/LimitOrderRoutes.tsx +5 -2
  299. package/src/components/Routes/RoutesContent.tsx +5 -2
  300. package/src/components/SendToWallet/SendToWalletExpandButton.tsx +2 -1
  301. package/src/components/TokenList/TokenListItem.tsx +68 -9
  302. package/src/components/TokenList/VirtualizedTokenList.tsx +33 -9
  303. package/src/components/TokenList/types.ts +4 -0
  304. package/src/config/version.ts +1 -1
  305. package/src/hooks/useAccountsBalancesData.ts +4 -31
  306. package/src/hooks/useAvailableChains.ts +1 -0
  307. package/src/hooks/useExplorer.ts +2 -0
  308. package/src/hooks/useFlaggedTokenGuard.ts +33 -0
  309. package/src/hooks/useGasSufficiency.ts +9 -1
  310. package/src/hooks/useMaxSendAmount.ts +21 -0
  311. package/src/hooks/useRoutes.ts +7 -0
  312. package/src/hooks/useToAddressRequirements.ts +17 -1
  313. package/src/hooks/useTokenBalances.ts +18 -2
  314. package/src/hooks/useTokenBalancesQueries.ts +12 -4
  315. package/src/hooks/useTokenSearch.ts +1 -5
  316. package/src/hooks/useTokens.ts +28 -13
  317. package/src/pages/MainPage/ReviewButton.tsx +6 -2
  318. package/src/pages/RoutesPage/RoutesPage.tsx +5 -2
  319. package/src/pages/TransactionPage/TokenVerificationBottomSheet.tsx +93 -0
  320. package/src/pages/TransactionPage/TransactionReview.tsx +28 -1
  321. package/src/providers/WalletProvider/useExternalWalletProvider.ts +9 -1
  322. package/src/types/token.ts +6 -3
  323. package/src/utils/customReceiver.ts +7 -0
  324. package/src/utils/gas.ts +41 -0
  325. package/src/utils/token.ts +53 -9
  326. package/src/utils/tokenList.ts +27 -7
  327. package/dist/esm/hooks/useFilteredByTokenBalances.js +0 -74
  328. package/dist/esm/hooks/useFilteredByTokenBalances.js.map +0 -1
  329. package/src/hooks/useFilteredByTokenBalances.ts +0 -145
@@ -5,6 +5,7 @@ import { useQuery } from '@tanstack/react-query'
5
5
  import { useMemo } from 'react'
6
6
  import { useSDKClient } from '../providers/SDKClientProvider.js'
7
7
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
8
+ import { getSelfFundedGasAmount } from '../utils/gas.js'
8
9
  import { getQueryKey } from '../utils/queries.js'
9
10
  import { useAvailableChains } from './useAvailableChains.js'
10
11
  import { useIsContractAddress } from './useIsContractAddress.js'
@@ -108,7 +109,14 @@ export const useGasSufficiency = (
108
109
  amount + BigInt(Number(gasCost.amount).toFixed(0)),
109
110
  0n
110
111
  )
111
- if (gasCostAmount > 0n) {
112
+ // A previous step can deliver this step's gas token (XLM bridged to
113
+ // Stellar), so the user does not have to hold it up front
114
+ const selfFundedGasAmount = getSelfFundedGasAmount(
115
+ route,
116
+ step,
117
+ getChainById(token.chainId)?.chainType
118
+ )
119
+ if (gasCostAmount > 0n && gasCostAmount > selfFundedGasAmount) {
112
120
  groupedGasCosts[token.chainId] = {
113
121
  gasAmount: groupedGasCosts[token.chainId]
114
122
  ? groupedGasCosts[token.chainId].gasAmount + gasCostAmount
@@ -0,0 +1,21 @@
1
+ import { useGasRecommendation } from './useGasRecommendation.js'
2
+ import { useTokenAddressBalance } from './useTokenAddressBalance.js'
3
+
4
+ // Largest amount of the token the wallet can send: for the native token that is
5
+ // the balance less the gas the chain recommends keeping back.
6
+ export const useMaxSendAmount = (
7
+ chainId?: number,
8
+ tokenAddress?: string
9
+ ): bigint => {
10
+ const { token, chain } = useTokenAddressBalance(chainId, tokenAddress)
11
+ const { data } = useGasRecommendation(chainId)
12
+
13
+ if (!token?.amount) {
14
+ return 0n
15
+ }
16
+ if (chain?.nativeToken.address !== tokenAddress) {
17
+ return token.amount
18
+ }
19
+ const reserved = BigInt(data?.recommended?.amount ?? 0)
20
+ return token.amount > reserved ? token.amount - reserved : token.amount
21
+ }
@@ -29,6 +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
33
  import { getQueryKey } from '../utils/queries.js'
33
34
  import { updateTokenInCache } from '../utils/token.js'
34
35
  import { useChain } from './useChain.js'
@@ -177,6 +178,11 @@ export const useRoutes = ({
177
178
  ? hasToAddressAndChainTypeSatisfied
178
179
  : true
179
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)
185
+
180
186
  // toAddress might be an empty string, but we need to pass undefined if there is no value
181
187
  const toWalletAddress = toAddress || undefined
182
188
 
@@ -197,6 +203,7 @@ export const useRoutes = ({
197
203
  !Number.isNaN(slippage) &&
198
204
  hasAmount &&
199
205
  isToAddressSatisfied &&
206
+ !customReceiverBlocked &&
200
207
  contractCallQuoteEnabled &&
201
208
  !isBatchingSupportedLoading
202
209
 
@@ -4,12 +4,15 @@ 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
8
  import { useIsContractAddress } from './useIsContractAddress.js'
8
9
 
9
10
  export const useToAddressRequirements = (
10
11
  route?: RouteExtended
11
12
  ): {
12
13
  requiredToAddress: boolean
14
+ unsupportedToAddress: boolean
15
+ unsupportedReceiverBlocking: boolean
13
16
  requiredToChainType: ChainType | undefined
14
17
  accountNotDeployedAtDestination: boolean
15
18
  accountDeployedAtDestination: boolean
@@ -68,11 +71,22 @@ export const useToAddressRequirements = (
68
71
  fromChainId !== toChainId &&
69
72
  !fromContractCodeHasDelegationIndicator
70
73
 
74
+ const unsupportedToAddress = isCustomReceiverUnsupported(
75
+ fromChain?.chainType,
76
+ toChain?.chainType
77
+ )
78
+
79
+ // Stellar routes settle to the signer, so a required receiver is never honoured.
80
+ const unsupportedReceiverBlocking = Boolean(
81
+ unsupportedToAddress && (toAddress || requiredUI?.toAddress)
82
+ )
83
+
71
84
  const requiredToAddress = Boolean(
72
85
  (isDifferentChainType ||
73
86
  isCrossChainContractAddress ||
74
87
  requiredUI?.toAddress) &&
75
- !hiddenUI?.toAddress
88
+ !hiddenUI?.toAddress &&
89
+ !unsupportedToAddress
76
90
  )
77
91
 
78
92
  const accountNotDeployedAtDestination = Boolean(
@@ -91,6 +105,8 @@ export const useToAddressRequirements = (
91
105
 
92
106
  return {
93
107
  requiredToAddress,
108
+ unsupportedToAddress,
109
+ unsupportedReceiverBlocking,
94
110
  requiredToChainType: toChain?.chainType,
95
111
  accountNotDeployedAtDestination,
96
112
  accountDeployedAtDestination,
@@ -4,7 +4,11 @@ import type { FormType } from '../stores/form/types.js'
4
4
  import { useSettings } from '../stores/settings/useSettings.js'
5
5
  import type { TokenAmount } from '../types/token.js'
6
6
  import { formatTokenPrice } from '../utils/format.js'
7
- import { isSearchMatch, processTokenList } from '../utils/tokenList.js'
7
+ import {
8
+ hoistNativeToken,
9
+ isSearchMatch,
10
+ processTokenList,
11
+ } from '../utils/tokenList.js'
8
12
  import { useAccountsBalancesData } from './useAccountsBalancesData.js'
9
13
  import { useDisplayedTokens } from './useDisplayedTokens.js'
10
14
  import { useTokenBalancesQueries } from './useTokenBalancesQueries.js'
@@ -115,7 +119,7 @@ export const useTokenBalances = (
115
119
  ])
116
120
 
117
121
  const { processedTokens, withCategories, withPinnedTokens } = useMemo(() => {
118
- return processTokenList(
122
+ const result = processTokenList(
119
123
  isBalanceLoading,
120
124
  isAllNetworks || !!search,
121
125
  configTokens,
@@ -124,6 +128,18 @@ export const useTokenBalances = (
124
128
  displayedTokensWithBalances,
125
129
  isPinnedToken
126
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
+ }
127
143
  }, [
128
144
  isBalanceLoading,
129
145
  isAllNetworks,
@@ -1,5 +1,5 @@
1
1
  import { getTokenBalances, type TokenExtended } from '@lifi/sdk'
2
- import { useQueries } from '@tanstack/react-query'
2
+ import { keepPreviousData, useQueries } from '@tanstack/react-query'
3
3
  import { useMemo, useRef } from 'react'
4
4
  import { useSDKClient } from '../providers/SDKClientProvider.js'
5
5
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
@@ -7,6 +7,10 @@ import type { TokenAmount, TokenAmountExtended } from '../types/token.js'
7
7
  import { getQueryKey } from '../utils/queries.js'
8
8
 
9
9
  const defaultRefetchInterval = 32_000
10
+ // Max time to hold the skeleton before revealing balances in the multi-chain view.
11
+ // Sits just below the typical full-settle time so the list reveals once, sorted,
12
+ // instead of reordering as each chain streams in.
13
+ const balanceRevealTimeout = 2_000
10
14
 
11
15
  export const useTokenBalancesQueries = (
12
16
  accountsWithTokens?: Record<string, Record<number, TokenExtended[]>>,
@@ -44,7 +48,10 @@ export const useTokenBalancesQueries = (
44
48
  enabled: isBalanceLoadingEnabled,
45
49
  refetchInterval: defaultRefetchInterval,
46
50
  staleTime: defaultRefetchInterval,
47
- keepPreviousData: true,
51
+ placeholderData: keepPreviousData,
52
+ // Resolve a failed chain immediately instead of retrying past the reveal
53
+ // window (retries would pop the chain in late and re-sort the list).
54
+ retry: false,
48
55
  }
49
56
  })
50
57
  )
@@ -74,8 +81,9 @@ export const useTokenBalancesQueries = (
74
81
  ? now - firstLoadStartRef.current
75
82
  : 0
76
83
 
77
- // Return results if all complete OR if 500ms have passed since first query started
78
- const shouldReturnResults = allComplete || timeSinceStart >= 500
84
+ // Return results once all queries complete, or once the reveal timeout elapses
85
+ const shouldReturnResults =
86
+ allComplete || timeSinceStart >= balanceRevealTimeout
79
87
 
80
88
  if (shouldReturnResults) {
81
89
  const data: TokenAmount[] = results
@@ -74,13 +74,9 @@ export const useTokenSearch = (
74
74
  ) {
75
75
  return data
76
76
  }
77
- // Mark token from search as unverified
78
77
  return {
79
78
  ...data,
80
- [chainId as number]: [
81
- ...(chainTokens ?? []),
82
- { ...token, verified: false },
83
- ],
79
+ [chainId as number]: [...(chainTokens ?? []), token],
84
80
  }
85
81
  }
86
82
  )
@@ -17,8 +17,10 @@ import { isItemAllowed } from '../utils/item.js'
17
17
  import { getQueryKey } from '../utils/queries.js'
18
18
  import {
19
19
  filterAllowedTokens,
20
+ getNativeTokenAddresses,
20
21
  mergeVerifiedWithSearchTokens,
21
22
  } from '../utils/token.js'
23
+ import { useAvailableChains } from './useAvailableChains.js'
22
24
 
23
25
  const refetchInterval = 300_000
24
26
 
@@ -49,6 +51,7 @@ export const useTokens = (
49
51
  ChainType.UTXO,
50
52
  ChainType.MVM,
51
53
  ChainType.TVM,
54
+ ChainType.STL,
52
55
  ].filter((chainType) => isItemAllowed(chainType, chainsConfig?.types))
53
56
 
54
57
  const tokensResponse: TokensExtendedResponse = await getTokens(
@@ -63,11 +66,11 @@ export const useTokens = (
63
66
  { signal }
64
67
  )
65
68
 
66
- // Mark all tokens as verified
69
+ // `listed` tells a main-list token from a searched one
67
70
  const tokens: TokensByChain = Object.fromEntries(
68
71
  Object.entries(tokensResponse.tokens).map(([chainId, tokens]) => [
69
72
  chainId,
70
- tokens.map((token) => ({ ...token, verified: true })),
73
+ tokens.map((token) => ({ ...token, listed: true })),
71
74
  ])
72
75
  )
73
76
 
@@ -92,6 +95,7 @@ export const useTokens = (
92
95
  ChainType.UTXO,
93
96
  ChainType.MVM,
94
97
  ChainType.TVM,
98
+ ChainType.STL,
95
99
  ].filter((chainType) => isItemAllowed(chainType, chainsConfig?.types))
96
100
 
97
101
  const tokensResponse: TokensExtendedResponse = await getTokens(
@@ -130,26 +134,37 @@ export const useTokens = (
130
134
  }
131
135
  }
132
136
 
133
- // Mark all search tokens as unverified
134
- const tokens: TokensByChain = Object.fromEntries(
135
- Object.entries(tokensResponse.tokens).map(([chainId, tokens]) => [
136
- chainId,
137
- tokens.map((token) => ({ ...token, verified: false })),
138
- ])
139
- )
140
-
141
- return tokens
137
+ return tokensResponse.tokens as TokensByChain
142
138
  },
143
139
  enabled: !!search,
144
140
  refetchInterval,
145
141
  staleTime: refetchInterval,
146
142
  })
147
143
 
144
+ const { chains } = useAvailableChains()
145
+ const nativeTokenAddresses = useMemo(
146
+ () => getNativeTokenAddresses(chains),
147
+ [chains]
148
+ )
149
+
148
150
  // Merge tokens at read time - single place where caches are combined
149
151
  const allTokens = useMemo(() => {
150
152
  const merged = mergeVerifiedWithSearchTokens(verifiedTokens, searchTokens)
151
- return filterAllowedTokens(merged, configTokens, chainsConfig, formType)
152
- }, [verifiedTokens, searchTokens, configTokens, chainsConfig, formType])
153
+ return filterAllowedTokens(
154
+ merged,
155
+ configTokens,
156
+ chainsConfig,
157
+ formType,
158
+ nativeTokenAddresses
159
+ )
160
+ }, [
161
+ verifiedTokens,
162
+ searchTokens,
163
+ configTokens,
164
+ chainsConfig,
165
+ formType,
166
+ nativeTokenAddresses,
167
+ ])
153
168
 
154
169
  return {
155
170
  allTokens,
@@ -16,7 +16,8 @@ export const ReviewButton: React.FC = () => {
16
16
  const emitter = useWidgetEvents()
17
17
  const { mode, modeOptions } = useWidgetConfig()
18
18
  const splitState = useSplitMode()
19
- const { toAddress, requiredToAddress } = useToAddressRequirements()
19
+ const { toAddress, requiredToAddress, unsupportedReceiverBlocking } =
20
+ useToAddressRequirements()
20
21
  const { routes, setReviewableRoute } = useRoutes()
21
22
  const [selectedRouteId] = useFieldValues('selectedRouteId')
22
23
 
@@ -85,7 +86,10 @@ export const ReviewButton: React.FC = () => {
85
86
  <BaseTransactionButton
86
87
  text={getButtonText()}
87
88
  onClick={handleClick}
88
- disabled={currentRoute && requiredToAddress && !toAddress}
89
+ disabled={
90
+ currentRoute &&
91
+ (unsupportedReceiverBlocking || (requiredToAddress && !toAddress))
92
+ }
89
93
  route={currentRoute}
90
94
  sx={{ flex: 1 }}
91
95
  />
@@ -36,7 +36,8 @@ export const RoutesPage = (): JSX.Element => {
36
36
  } = useRoutes()
37
37
  const { account } = useAccount({ chainType: fromChain?.chainType })
38
38
  const [toAddress] = useFieldValues('toAddress')
39
- const { requiredToAddress } = useToAddressRequirements()
39
+ const { requiredToAddress, unsupportedReceiverBlocking } =
40
+ useToAddressRequirements()
40
41
 
41
42
  const headerAction = useMemo(
42
43
  () => (
@@ -72,7 +73,9 @@ export const RoutesPage = (): JSX.Element => {
72
73
 
73
74
  const routeNotFound = !routes?.length && !isLoading && !isFetching
74
75
 
75
- const toAddressUnsatisfied = routes?.[0] && requiredToAddress && !toAddress
76
+ const toAddressUnsatisfied =
77
+ routes?.[0] &&
78
+ (unsupportedReceiverBlocking || (requiredToAddress && !toAddress))
76
79
 
77
80
  const allowInteraction = account.isConnected && !toAddressUnsatisfied
78
81
 
@@ -0,0 +1,93 @@
1
+ import type { Token } from '@lifi/sdk'
2
+ import { Button, Checkbox, FormControlLabel } from '@mui/material'
3
+ import type { JSX, Ref, RefObject } from 'react'
4
+ import { useRef, useState } from 'react'
5
+ import { useTranslation } from 'react-i18next'
6
+ import { BottomSheet } from '../../components/BottomSheet/BottomSheet.js'
7
+ import type { BottomSheetBase } from '../../components/BottomSheet/types.js'
8
+ import { IconCircle } from '../../components/IconCircle/IconCircle.js'
9
+ import { useSetContentHeight } from '../../hooks/useSetContentHeight.js'
10
+ import {
11
+ ButtonRow,
12
+ CenterContainer,
13
+ ContentContainer,
14
+ WarningMessage,
15
+ WarningTitle,
16
+ } from './TokenValueBottomSheet.style.js'
17
+
18
+ interface TokenVerificationBottomSheetProps {
19
+ /** Source and/or destination tokens the screening provider flagged. */
20
+ tokens: Token[]
21
+ onContinue(): void
22
+ onCancel?(): void
23
+ }
24
+
25
+ export const TokenVerificationBottomSheet = ({
26
+ tokens,
27
+ onContinue,
28
+ onCancel,
29
+ ref,
30
+ }: TokenVerificationBottomSheetProps & {
31
+ ref?: Ref<BottomSheetBase>
32
+ }): JSX.Element => {
33
+ const handleCancel = () => {
34
+ ;(ref as RefObject<BottomSheetBase>).current?.close()
35
+ onCancel?.()
36
+ }
37
+
38
+ return (
39
+ <BottomSheet ref={ref} onClose={onCancel}>
40
+ <TokenVerificationBottomSheetContent
41
+ tokens={tokens}
42
+ onContinue={onContinue}
43
+ onCancel={handleCancel}
44
+ />
45
+ </BottomSheet>
46
+ )
47
+ }
48
+
49
+ const TokenVerificationBottomSheetContent: React.FC<
50
+ TokenVerificationBottomSheetProps
51
+ > = ({ tokens, onCancel, onContinue }) => {
52
+ const [accepted, setAccepted] = useState(false)
53
+ const { t } = useTranslation()
54
+ const ref = useRef<HTMLElement>(null)
55
+ useSetContentHeight(ref)
56
+
57
+ return (
58
+ <ContentContainer ref={ref}>
59
+ <CenterContainer>
60
+ <IconCircle status="error" sx={{ mb: 2.5 }} />
61
+ <WarningTitle>{t('warning.title.tokenFlagged')}</WarningTitle>
62
+ </CenterContainer>
63
+ {tokens.map((token) => (
64
+ <WarningMessage key={`${token.chainId}-${token.address}`}>
65
+ {t('warning.message.tokenFlagged', { tokenSymbol: token.symbol })}
66
+ </WarningMessage>
67
+ ))}
68
+ <FormControlLabel
69
+ control={
70
+ <Checkbox
71
+ checked={accepted}
72
+ onChange={(_, checked) => setAccepted(checked)}
73
+ />
74
+ }
75
+ label={t('warning.checkbox.tokenFlagged')}
76
+ sx={{ mt: 1 }}
77
+ />
78
+ <ButtonRow>
79
+ <Button variant="text" onClick={onCancel} fullWidth>
80
+ {t('button.cancel')}
81
+ </Button>
82
+ <Button
83
+ variant="contained"
84
+ onClick={onContinue}
85
+ disabled={!accepted}
86
+ fullWidth
87
+ >
88
+ {t('button.continue')}
89
+ </Button>
90
+ </ButtonRow>
91
+ </ContentContainer>
92
+ )
93
+ }
@@ -8,6 +8,7 @@ import { Card } from '../../components/Card/Card.js'
8
8
  import { WarningMessages } from '../../components/Messages/WarningMessages.js'
9
9
  import { RouteTokens } from '../../components/RouteCard/RouteTokens.js'
10
10
  import { useAddressActivity } from '../../hooks/useAddressActivity.js'
11
+ import { useFlaggedTokenGuard } from '../../hooks/useFlaggedTokenGuard.js'
11
12
  import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
12
13
  import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
13
14
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
@@ -18,6 +19,7 @@ import { navigationRoutes } from '../../utils/navigationRoutes.js'
18
19
  import { ConfirmToAddressSheet } from './ConfirmToAddressSheet.js'
19
20
  import { StartTransactionButton } from './StartTransactionButton.js'
20
21
  import { TokenValueBottomSheet } from './TokenValueBottomSheet.js'
22
+ import { TokenVerificationBottomSheet } from './TokenVerificationBottomSheet.js'
21
23
  import {
22
24
  calculateValueLossPercentage,
23
25
  getTokenValueLossThreshold,
@@ -44,6 +46,8 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
44
46
  const tokenValueBottomSheetRef = useRef<BottomSheetBase>(null)
45
47
  const confirmToAddressSheetRef = useRef<BottomSheetBase>(null)
46
48
 
49
+ const { flaggedTokens, flaggedTokenSheetRef } = useFlaggedTokenGuard(route)
50
+
47
51
  const {
48
52
  toAddress,
49
53
  hasActivity,
@@ -70,6 +74,7 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
70
74
  })
71
75
  }
72
76
  tokenValueBottomSheetRef.current?.close()
77
+ flaggedTokenSheetRef.current?.close()
73
78
  executeRoute()
74
79
  setFieldValue('fromAmount', '')
75
80
  if (mode === 'custom') {
@@ -81,7 +86,9 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
81
86
  })
82
87
  }
83
88
 
84
- const handleStartClick = () => {
89
+ // Runs the remaining gates. The flagged-token sheet continues into this
90
+ // rather than executing, so accepting it does not skip the others.
91
+ const handleStartAfterTokenCheck = () => {
85
92
  if (
86
93
  toAddress &&
87
94
  !hasActivity &&
@@ -109,6 +116,19 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
109
116
  }
110
117
  }
111
118
 
119
+ const handleStartClick = () => {
120
+ if (flaggedTokens.length) {
121
+ flaggedTokenSheetRef.current?.open()
122
+ return
123
+ }
124
+ handleStartAfterTokenCheck()
125
+ }
126
+
127
+ const handleFlaggedTokensContinue = () => {
128
+ flaggedTokenSheetRef.current?.close()
129
+ handleStartAfterTokenCheck()
130
+ }
131
+
112
132
  const getButtonText = (): string => {
113
133
  switch (mode) {
114
134
  case 'custom':
@@ -150,6 +170,13 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
150
170
  onContinue={handleExecuteRoute}
151
171
  />
152
172
  ) : null}
173
+ {flaggedTokens.length ? (
174
+ <TokenVerificationBottomSheet
175
+ ref={flaggedTokenSheetRef}
176
+ tokens={flaggedTokens}
177
+ onContinue={handleFlaggedTokensContinue}
178
+ />
179
+ ) : null}
153
180
  {!hiddenUI?.lowAddressActivityConfirmation ? (
154
181
  <ConfirmToAddressSheet
155
182
  ref={confirmToAddressSheetRef}
@@ -3,6 +3,7 @@ import {
3
3
  useBitcoinContext,
4
4
  useEthereumContext,
5
5
  useSolanaContext,
6
+ useStellarContext,
6
7
  useSuiContext,
7
8
  useTronContext,
8
9
  } from '@lifi/widget-provider'
@@ -21,6 +22,7 @@ const internalChainTypes = [
21
22
  ChainType.UTXO,
22
23
  ChainType.MVM,
23
24
  ChainType.TVM,
25
+ ChainType.STL,
24
26
  ]
25
27
 
26
28
  export function useExternalWalletProvider(): ExternalWalletProvider {
@@ -30,6 +32,7 @@ export function useExternalWalletProvider(): ExternalWalletProvider {
30
32
  const { isExternalContext: hasExternalBitcoinContext } = useBitcoinContext()
31
33
  const { isExternalContext: hasExternalSuiContext } = useSuiContext()
32
34
  const { isExternalContext: hasExternalTronContext } = useTronContext()
35
+ const { isExternalContext: hasExternalStellarContext } = useStellarContext()
33
36
  const data = useMemo(() => {
34
37
  const providers: ChainType[] = []
35
38
  if (hasExternalEthereumContext) {
@@ -47,12 +50,16 @@ export function useExternalWalletProvider(): ExternalWalletProvider {
47
50
  if (hasExternalTronContext) {
48
51
  providers.push(ChainType.TVM)
49
52
  }
53
+ if (hasExternalStellarContext) {
54
+ providers.push(ChainType.STL)
55
+ }
50
56
  const hasExternalProvider =
51
57
  hasExternalEthereumContext ||
52
58
  hasExternalSolanaContext ||
53
59
  hasExternalBitcoinContext ||
54
60
  hasExternalSuiContext ||
55
- hasExternalTronContext
61
+ hasExternalTronContext ||
62
+ hasExternalStellarContext
56
63
 
57
64
  const useExternalWalletProvidersOnly =
58
65
  hasExternalProvider &&
@@ -71,6 +78,7 @@ export function useExternalWalletProvider(): ExternalWalletProvider {
71
78
  hasExternalBitcoinContext,
72
79
  hasExternalSuiContext,
73
80
  hasExternalTronContext,
81
+ hasExternalStellarContext,
74
82
  walletConfig?.usePartialWalletManagement,
75
83
  walletConfig?.forceInternalWalletManagement,
76
84
  ])
@@ -4,11 +4,14 @@ import type {
4
4
  TokenExtended,
5
5
  } from '@lifi/sdk'
6
6
 
7
- interface TokenFlags {
7
+ export interface TokenFlags {
8
8
  featured?: boolean
9
9
  popular?: boolean
10
10
  pinned?: boolean
11
11
  verified?: boolean
12
+ native?: boolean
13
+ /** Came from the main token list rather than from a search. */
14
+ listed?: boolean
12
15
  }
13
16
 
14
17
  export interface TokenAmount extends SDKTokenAmount, TokenFlags {}
@@ -17,5 +20,5 @@ export interface TokenAmountExtended
17
20
  extends SDKTokenAmountExtended,
18
21
  TokenFlags {}
19
22
 
20
- export type TokenWithVerified = TokenExtended & { verified?: boolean }
21
- export type TokensByChain = Record<number, TokenWithVerified[]>
23
+ export type TokenWithFlags = TokenExtended & TokenFlags
24
+ export type TokensByChain = Record<number, TokenWithFlags[]>
@@ -0,0 +1,7 @@
1
+ import { ChainType } from '@lifi/sdk'
2
+
3
+ // Stellar routes always settle to the account that signs them.
4
+ export const isCustomReceiverUnsupported = (
5
+ fromChainType?: ChainType,
6
+ toChainType?: ChainType
7
+ ): boolean => fromChainType === ChainType.STL && toChainType === ChainType.STL
@@ -0,0 +1,41 @@
1
+ import type { LiFiStepExtended, RouteExtended } from '@lifi/sdk'
2
+ import { ChainType } from '@lifi/sdk'
3
+
4
+ /**
5
+ * Returns how much of a step's gas token the route itself delivers before that
6
+ * step runs. The previous step must output the gas token on the same chain, and
7
+ * whatever this step consumes as input is not available for gas.
8
+ * Stellar routes only — they bridge XLM to the receiver and hold back a buffer
9
+ * for the account reserve and the destination step fees.
10
+ */
11
+ export const getSelfFundedGasAmount = (
12
+ route: RouteExtended,
13
+ step: LiFiStepExtended,
14
+ gasChainType?: ChainType
15
+ ): bigint => {
16
+ // TODO: remove the chain gate when the backend reserves gas on every chain
17
+ if (gasChainType !== ChainType.STL) {
18
+ return 0n
19
+ }
20
+ const gasToken = step.estimate.gasCosts?.[0]?.token
21
+ const previousStep = route.steps[route.steps.indexOf(step) - 1]
22
+ if (!gasToken || !previousStep) {
23
+ return 0n
24
+ }
25
+ const { toToken } = previousStep.action
26
+ if (
27
+ toToken.chainId !== gasToken.chainId ||
28
+ toToken.address.toLowerCase() !== gasToken.address.toLowerCase()
29
+ ) {
30
+ return 0n
31
+ }
32
+ const deliveredAmount = BigInt(previousStep.estimate.toAmountMin)
33
+ const consumedAmount =
34
+ step.action.fromToken.address.toLowerCase() ===
35
+ gasToken.address.toLowerCase()
36
+ ? BigInt(step.action.fromAmount)
37
+ : 0n
38
+ return deliveredAmount > consumedAmount
39
+ ? deliveredAmount - consumedAmount
40
+ : 0n
41
+ }