@lifi/widget 4.0.0 → 4.2.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 (485) hide show
  1. package/dist/esm/App.d.ts +4 -2
  2. package/dist/esm/App.d.ts.map +1 -1
  3. package/dist/esm/App.js +4 -4
  4. package/dist/esm/App.js.map +1 -1
  5. package/dist/esm/AppDefault.js +14 -0
  6. package/dist/esm/AppDefault.js.map +1 -1
  7. package/dist/esm/AppDrawer.d.ts +1 -1
  8. package/dist/esm/AppDrawer.d.ts.map +1 -1
  9. package/dist/esm/AppDrawer.js +5 -6
  10. package/dist/esm/AppDrawer.js.map +1 -1
  11. package/dist/esm/AppDrawerContext.js +2 -2
  12. package/dist/esm/AppDrawerContext.js.map +1 -1
  13. package/dist/esm/components/ActionRow/ActionRow.style.js.map +1 -1
  14. package/dist/esm/components/AmountInput/AmountInput.js +2 -1
  15. package/dist/esm/components/AmountInput/AmountInput.js.map +1 -1
  16. package/dist/esm/components/AmountInput/AmountInput.style.js.map +1 -1
  17. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +4 -2
  18. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
  19. package/dist/esm/components/AmountInput/AmountInputEndAdornment.style.js +1 -1
  20. package/dist/esm/components/AmountInput/AmountInputEndAdornment.style.js.map +1 -1
  21. package/dist/esm/components/AmountInput/PriceFormHelperText.js +4 -2
  22. package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
  23. package/dist/esm/components/AmountInput/PriceFormHelperText.style.js.map +1 -1
  24. package/dist/esm/components/AmountInputCard/AmountInputCard.style.js +98 -0
  25. package/dist/esm/components/AmountInputCard/AmountInputCard.style.js.map +1 -0
  26. package/dist/esm/components/AmountInputCard/AmountInputCardPair.js +25 -0
  27. package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -0
  28. package/dist/esm/components/AmountInputCard/BalanceDisplay.js +35 -0
  29. package/dist/esm/components/AmountInputCard/BalanceDisplay.js.map +1 -0
  30. package/dist/esm/components/AmountInputCard/BalanceDisplay.style.js +11 -0
  31. package/dist/esm/components/AmountInputCard/BalanceDisplay.style.js.map +1 -0
  32. package/dist/esm/components/AmountInputCard/FiatValueToggle.js +41 -0
  33. package/dist/esm/components/AmountInputCard/FiatValueToggle.js.map +1 -0
  34. package/dist/esm/components/AmountInputCard/PercentageChips.js +80 -0
  35. package/dist/esm/components/AmountInputCard/PercentageChips.js.map +1 -0
  36. package/dist/esm/components/AmountInputCard/PercentageChips.style.js +43 -0
  37. package/dist/esm/components/AmountInputCard/PercentageChips.style.js.map +1 -0
  38. package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js +137 -0
  39. package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js.map +1 -0
  40. package/dist/esm/components/AmountInputCard/SendAmountCard.js +102 -0
  41. package/dist/esm/components/AmountInputCard/SendAmountCard.js.map +1 -0
  42. package/dist/esm/components/AppContainer.js.map +1 -1
  43. package/dist/esm/components/Avatar/AccountAvatar.js.map +1 -1
  44. package/dist/esm/components/Avatar/Avatar.js +12 -3
  45. package/dist/esm/components/Avatar/Avatar.js.map +1 -1
  46. package/dist/esm/components/Avatar/Avatar.style.js.map +1 -1
  47. package/dist/esm/components/Avatar/SmallAvatar.js.map +1 -1
  48. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js +1 -0
  49. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
  50. package/dist/esm/components/BottomSheet/BottomSheet.js +3 -3
  51. package/dist/esm/components/BottomSheet/BottomSheet.js.map +1 -1
  52. package/dist/esm/components/ButtonTertiary.js.map +1 -1
  53. package/dist/esm/components/Card/Card.js.map +1 -1
  54. package/dist/esm/components/Card/CardButton.style.js.map +1 -1
  55. package/dist/esm/components/Card/CardHeader.js.map +1 -1
  56. package/dist/esm/components/Card/CardIconButton.js.map +1 -1
  57. package/dist/esm/components/Card/CardLabel.js.map +1 -1
  58. package/dist/esm/components/Card/CardTitle.js.map +1 -1
  59. package/dist/esm/components/Card/InputCard.js.map +1 -1
  60. package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
  61. package/dist/esm/components/ChainSelect/ChainSelect.style.js.map +1 -1
  62. package/dist/esm/components/ChainSelect/useChainSelect.js.map +1 -1
  63. package/dist/esm/components/Chains/AllChainsAvatar.js.map +1 -1
  64. package/dist/esm/components/Chains/ChainList.js.map +1 -1
  65. package/dist/esm/components/Chains/ChainList.style.js.map +1 -1
  66. package/dist/esm/components/Chains/ChainsExpanded.style.js.map +1 -1
  67. package/dist/esm/components/Chains/VirtualizedChainList.js +2 -1
  68. package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
  69. package/dist/esm/components/ContextMenu.style.js.map +1 -1
  70. package/dist/esm/components/ContractComponent/NFT/NFT.style.js.map +1 -1
  71. package/dist/esm/components/Dialog/Dialog.style.js.map +1 -1
  72. package/dist/esm/components/EmptyListIndicator/EmptyListIndicator.style.js.map +1 -1
  73. package/dist/esm/components/ExecutionStatusCard/StatusIcon.js.map +1 -1
  74. package/dist/esm/components/ExecutionStatusCard/StatusIcon.style.js.map +1 -1
  75. package/dist/esm/components/ExecutionStatusCard/iconKey.js.map +1 -1
  76. package/dist/esm/components/Expansion/Expansion.style.js.map +1 -1
  77. package/dist/esm/components/Header/ActivitiesButton.style.js.map +1 -1
  78. package/dist/esm/components/Header/CloseDrawerButton.js +1 -0
  79. package/dist/esm/components/Header/CloseDrawerButton.js.map +1 -1
  80. package/dist/esm/components/Header/Header.js +7 -10
  81. package/dist/esm/components/Header/Header.js.map +1 -1
  82. package/dist/esm/components/Header/Header.style.js.map +1 -1
  83. package/dist/esm/components/Header/HeaderNavigationTabs.js +39 -0
  84. package/dist/esm/components/Header/HeaderNavigationTabs.js.map +1 -0
  85. package/dist/esm/components/Header/HeaderTabs.js +33 -0
  86. package/dist/esm/components/Header/HeaderTabs.js.map +1 -0
  87. package/dist/esm/components/Header/NavigationHeader.js +7 -5
  88. package/dist/esm/components/Header/NavigationHeader.js.map +1 -1
  89. package/dist/esm/components/Header/SettingsButton.style.js.map +1 -1
  90. package/dist/esm/components/Header/WalletMenu.style.js.map +1 -1
  91. package/dist/esm/components/IconCircle/IconCircle.style.js +1 -1
  92. package/dist/esm/components/IconCircle/IconCircle.style.js.map +1 -1
  93. package/dist/esm/components/IconTypography.js.map +1 -1
  94. package/dist/esm/components/Input.js.map +1 -1
  95. package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.js +99 -0
  96. package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.js.map +1 -0
  97. package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.style.js +52 -0
  98. package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.style.js.map +1 -0
  99. package/dist/esm/components/LimitPriceCard/LimitPriceCard.js +115 -0
  100. package/dist/esm/components/LimitPriceCard/LimitPriceCard.js.map +1 -0
  101. package/dist/esm/components/LimitPriceCard/LimitPriceCard.style.js +89 -0
  102. package/dist/esm/components/LimitPriceCard/LimitPriceCard.style.js.map +1 -0
  103. package/dist/esm/components/LimitPriceCard/LimitPricePresets.js +91 -0
  104. package/dist/esm/components/LimitPriceCard/LimitPricePresets.js.map +1 -0
  105. package/dist/esm/components/ListItem/ListItem.js.map +1 -1
  106. package/dist/esm/components/ListItem/ListItemButton.js.map +1 -1
  107. package/dist/esm/components/ListItemButton.js.map +1 -1
  108. package/dist/esm/components/ListItemText.js.map +1 -1
  109. package/dist/esm/components/Menu.js.map +1 -1
  110. package/dist/esm/components/Messages/AlertMessage.style.js.map +1 -1
  111. package/dist/esm/components/Messages/GasRefuelMessage.style.js.map +1 -1
  112. package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
  113. package/dist/esm/components/PageContainer.js.map +1 -1
  114. package/dist/esm/components/PoweredBy/PoweredBy.js.map +1 -1
  115. package/dist/esm/components/PoweredBy/PoweredBy.style.js.map +1 -1
  116. package/dist/esm/components/ReverseTokensButton/ReverseTokensButton.js +1 -0
  117. package/dist/esm/components/ReverseTokensButton/ReverseTokensButton.js.map +1 -1
  118. package/dist/esm/components/ReverseTokensButton/ReverseTokensButton.style.js.map +1 -1
  119. package/dist/esm/components/RouteCard/RouteDetails.js.map +1 -1
  120. package/dist/esm/components/RouteCard/RouteDetails.style.js +2 -2
  121. package/dist/esm/components/RouteCard/RouteDetails.style.js.map +1 -1
  122. package/dist/esm/components/RouteCard/RouteProviderCard.js +118 -0
  123. package/dist/esm/components/RouteCard/RouteProviderCard.js.map +1 -0
  124. package/dist/esm/components/RouteCard/RouteToken.style.js.map +1 -1
  125. package/dist/esm/components/RouteCard/RouteTokens.js.map +1 -1
  126. package/dist/esm/components/RouteCard/getMatchingLabels.js.map +1 -1
  127. package/dist/esm/components/Routes/LimitOrderRoutes.js +34 -0
  128. package/dist/esm/components/Routes/LimitOrderRoutes.js.map +1 -0
  129. package/dist/esm/components/Routes/Routes.js +2 -2
  130. package/dist/esm/components/Routes/Routes.js.map +1 -1
  131. package/dist/esm/components/Routes/RoutesContent.js.map +1 -1
  132. package/dist/esm/components/Routes/RoutesExpanded.style.js.map +1 -1
  133. package/dist/esm/components/Search/SearchInput.style.js.map +1 -1
  134. package/dist/esm/components/Search/SearchNotFound.style.js.map +1 -1
  135. package/dist/esm/components/SelectTokenButton/SelectTokenButton.style.js.map +1 -1
  136. package/dist/esm/components/SendToWallet/SendToWalletButton.style.js.map +1 -1
  137. package/dist/esm/components/SettingsListItemButton.js.map +1 -1
  138. package/dist/esm/components/SettingsPanel/SettingsPanel.js +51 -0
  139. package/dist/esm/components/SettingsPanel/SettingsPanel.js.map +1 -0
  140. package/dist/esm/components/SettingsPanel/SettingsPanel.style.js +33 -0
  141. package/dist/esm/components/SettingsPanel/SettingsPanel.style.js.map +1 -0
  142. package/dist/esm/components/SettingsPanel/utils.js +14 -0
  143. package/dist/esm/components/SettingsPanel/utils.js.map +1 -0
  144. package/dist/esm/components/Skeleton/WidgetSkeleton.js +50 -47
  145. package/dist/esm/components/Skeleton/WidgetSkeleton.js.map +1 -1
  146. package/dist/esm/components/Skeleton/WidgetSkeleton.style.js.map +1 -1
  147. package/dist/esm/components/Step/StepActions.js.map +1 -1
  148. package/dist/esm/components/Step/StepActions.style.js.map +1 -1
  149. package/dist/esm/components/StepActions/SentToWalletRow.style.js.map +1 -1
  150. package/dist/esm/components/StepActions/StepActionRow.style.js.map +1 -1
  151. package/dist/esm/components/SwapButton/SwapButton.js +50 -0
  152. package/dist/esm/components/SwapButton/SwapButton.js.map +1 -0
  153. package/dist/esm/components/SwapButton/SwapButton.style.js +24 -0
  154. package/dist/esm/components/SwapButton/SwapButton.style.js.map +1 -0
  155. package/dist/esm/components/Switch.js.map +1 -1
  156. package/dist/esm/components/Tabs/NavigationTabs.js +3 -0
  157. package/dist/esm/components/Tabs/NavigationTabs.js.map +1 -1
  158. package/dist/esm/components/Tabs/Tabs.style.js.map +1 -1
  159. package/dist/esm/components/Timer/StepStatusTimer.style.js.map +1 -1
  160. package/dist/esm/components/Token/Token.style.js.map +1 -1
  161. package/dist/esm/components/TokenList/PinTokenButton.js.map +1 -1
  162. package/dist/esm/components/TokenList/TokenDetailsSheet.js +4 -4
  163. package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -1
  164. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js +4 -4
  165. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -1
  166. package/dist/esm/components/TokenList/TokenDetailsSheetContent.style.js.map +1 -1
  167. package/dist/esm/components/TokenList/TokenList.style.js.map +1 -1
  168. package/dist/esm/components/TokenList/TokenListItem.js +2 -2
  169. package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
  170. package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
  171. package/dist/esm/components/TokenList/useTokenSelect.js +3 -3
  172. package/dist/esm/components/TokenList/useTokenSelect.js.map +1 -1
  173. package/dist/esm/components/TokenPillButton/TokenPillButton.js +52 -0
  174. package/dist/esm/components/TokenPillButton/TokenPillButton.js.map +1 -0
  175. package/dist/esm/components/TokenPillButton/TokenPillButton.style.js +39 -0
  176. package/dist/esm/components/TokenPillButton/TokenPillButton.style.js.map +1 -0
  177. package/dist/esm/components/TokenRate/TokenRate.style.js.map +1 -1
  178. package/dist/esm/components/TransactionCard/ActiveTransactionCard.js.map +1 -1
  179. package/dist/esm/components/TransactionCard/ActiveTransactionCard.style.js.map +1 -1
  180. package/dist/esm/components/TransactionCard/TransactionCard.style.js.map +1 -1
  181. package/dist/esm/config/version.d.ts +1 -1
  182. package/dist/esm/config/version.js +1 -1
  183. package/dist/esm/config/version.js.map +1 -1
  184. package/dist/esm/hooks/timer/validate.js.map +1 -1
  185. package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
  186. package/dist/esm/hooks/useAvailableChains.js +1 -1
  187. package/dist/esm/hooks/useChainSearch.js +2 -1
  188. package/dist/esm/hooks/useChainSearch.js.map +1 -1
  189. package/dist/esm/hooks/useChains.js +1 -1
  190. package/dist/esm/hooks/useExplorer.js.map +1 -1
  191. package/dist/esm/hooks/useFilteredByTokenBalances.js +1 -1
  192. package/dist/esm/hooks/useFilteredByTokenBalances.js.map +1 -1
  193. package/dist/esm/hooks/useFromTokenSufficiency.js.map +1 -1
  194. package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
  195. package/dist/esm/hooks/useLanguages.js +2 -2
  196. package/dist/esm/hooks/useLanguages.js.map +1 -1
  197. package/dist/esm/hooks/useLimitMarketRate.js +24 -0
  198. package/dist/esm/hooks/useLimitMarketRate.js.map +1 -0
  199. package/dist/esm/hooks/useLinkedLimitFields.js +49 -0
  200. package/dist/esm/hooks/useLinkedLimitFields.js.map +1 -0
  201. package/dist/esm/hooks/useRouteExecution.js.map +1 -1
  202. package/dist/esm/hooks/useRouteExecutionMessage.js.map +1 -1
  203. package/dist/esm/hooks/useRouteRequiredAccountConnection.js.map +1 -1
  204. package/dist/esm/hooks/useRoutes.js +23 -6
  205. package/dist/esm/hooks/useRoutes.js.map +1 -1
  206. package/dist/esm/hooks/useSwapOnly.js +2 -4
  207. package/dist/esm/hooks/useSwapOnly.js.map +1 -1
  208. package/dist/esm/hooks/useToAddressRequirements.js +2 -2
  209. package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
  210. package/dist/esm/hooks/useToken.js.map +1 -1
  211. package/dist/esm/hooks/useTokenBalance.js.map +1 -1
  212. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  213. package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -1
  214. package/dist/esm/hooks/useTokenSearch.js +1 -1
  215. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  216. package/dist/esm/hooks/useTokens.js +17 -15
  217. package/dist/esm/hooks/useTokens.js.map +1 -1
  218. package/dist/esm/hooks/useTools.js +1 -1
  219. package/dist/esm/hooks/useTransactionDetails.js.map +1 -1
  220. package/dist/esm/hooks/useTransactionHistory.js.map +1 -1
  221. package/dist/esm/hooks/useTransactionList.js.map +1 -1
  222. package/dist/esm/hooks/useWideVariant.js +5 -2
  223. package/dist/esm/hooks/useWideVariant.js.map +1 -1
  224. package/dist/esm/i18n/en.json +25 -0
  225. package/dist/esm/index.d.ts +3 -3
  226. package/dist/esm/pages/ActivitiesPage/ActivitiesPage.js.map +1 -1
  227. package/dist/esm/pages/MainPage/LimitPageContent.js +23 -0
  228. package/dist/esm/pages/MainPage/LimitPageContent.js.map +1 -0
  229. package/dist/esm/pages/MainPage/MainPage.js +19 -22
  230. package/dist/esm/pages/MainPage/MainPage.js.map +1 -1
  231. package/dist/esm/pages/MainPage/MainPageActions.js +28 -0
  232. package/dist/esm/pages/MainPage/MainPageActions.js.map +1 -0
  233. package/dist/esm/pages/MainPage/ReviewButton.js +11 -4
  234. package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
  235. package/dist/esm/pages/RoutePriorityPage.js +48 -0
  236. package/dist/esm/pages/RoutePriorityPage.js.map +1 -0
  237. package/dist/esm/pages/RoutesPage/RoutesPage.js.map +1 -1
  238. package/dist/esm/pages/RoutesPage/RoutesPage.style.js.map +1 -1
  239. package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
  240. package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js +3 -3
  241. package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js.map +1 -1
  242. package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.js +3 -3
  243. package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.js.map +1 -1
  244. package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
  245. package/dist/esm/pages/SendToWallet/SendToWalletPage.style.js.map +1 -1
  246. package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js +2 -2
  247. package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js.map +1 -1
  248. package/dist/esm/pages/SettingsPage/GasPriceSettings.js +1 -1
  249. package/dist/esm/pages/SettingsPage/ResetSettingsButton.style.js.map +1 -1
  250. package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js +12 -27
  251. package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js.map +1 -1
  252. package/dist/esm/pages/SettingsPage/SettingsCard/SettingCard.style.js.map +1 -1
  253. package/dist/esm/pages/SettingsPage/SettingsCard/SettingCardExpandable.js +3 -3
  254. package/dist/esm/pages/SettingsPage/SettingsCard/SettingCardExpandable.js.map +1 -1
  255. package/dist/esm/pages/SettingsPage/SettingsCard/SettingsAccordian.js +3 -3
  256. package/dist/esm/pages/SettingsPage/SettingsCard/SettingsAccordian.js.map +1 -1
  257. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippagePage.js +133 -0
  258. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippagePage.js.map +1 -0
  259. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js +14 -72
  260. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js.map +1 -1
  261. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.style.js +26 -14
  262. package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.style.js.map +1 -1
  263. package/dist/esm/pages/SettingsPage/ThemeSettings.js +4 -0
  264. package/dist/esm/pages/SettingsPage/ThemeSettings.js.map +1 -1
  265. package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.style.js.map +1 -1
  266. package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
  267. package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsSkeleton.js.map +1 -1
  268. package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.js +3 -3
  269. package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.js.map +1 -1
  270. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.js +16 -15
  271. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
  272. package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.style.js.map +1 -1
  273. package/dist/esm/pages/TransactionPage/RouteTracker.js.map +1 -1
  274. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js +3 -3
  275. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
  276. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.style.js.map +1 -1
  277. package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js +27 -31
  278. package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js.map +1 -1
  279. package/dist/esm/pages/TransactionPage/TransactionReview.js +4 -1
  280. package/dist/esm/pages/TransactionPage/TransactionReview.js.map +1 -1
  281. package/dist/esm/pages/TransactionPage/utils.js.map +1 -1
  282. package/dist/esm/providers/I18nProvider/I18nProvider.js +1 -1
  283. package/dist/esm/providers/I18nProvider/I18nProvider.js.map +1 -1
  284. package/dist/esm/providers/I18nProvider/enResource.d.ts +1 -1
  285. package/dist/esm/providers/I18nProvider/enResource.js +1 -1
  286. package/dist/esm/providers/I18nProvider/i18n.js.map +1 -1
  287. package/dist/esm/providers/I18nProvider/types.d.ts +2 -2
  288. package/dist/esm/providers/QueryClientProvider.js +2 -2
  289. package/dist/esm/providers/QueryClientProvider.js.map +1 -1
  290. package/dist/esm/providers/SDKClientProvider.js +3 -3
  291. package/dist/esm/providers/SDKClientProvider.js.map +1 -1
  292. package/dist/esm/providers/WidgetProvider/WidgetProvider.js +4 -5
  293. package/dist/esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
  294. package/dist/esm/stores/StoreProvider.js +3 -4
  295. package/dist/esm/stores/StoreProvider.js.map +1 -1
  296. package/dist/esm/stores/bookmarks/BookmarkStore.js +3 -3
  297. package/dist/esm/stores/bookmarks/BookmarkStore.js.map +1 -1
  298. package/dist/esm/stores/bookmarks/createBookmarkStore.js.map +1 -1
  299. package/dist/esm/stores/chains/ChainOrderStore.js +4 -4
  300. package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
  301. package/dist/esm/stores/chains/createChainOrderStore.js.map +1 -1
  302. package/dist/esm/stores/form/FormStore.js +1 -1
  303. package/dist/esm/stores/form/FormStore.js.map +1 -1
  304. package/dist/esm/stores/form/URLSearchParamsBuilder.js +14 -3
  305. package/dist/esm/stores/form/URLSearchParamsBuilder.js.map +1 -1
  306. package/dist/esm/stores/form/createFormStore.js +6 -2
  307. package/dist/esm/stores/form/createFormStore.js.map +1 -1
  308. package/dist/esm/stores/form/getDefaultValuesFromQueryString.js +3 -0
  309. package/dist/esm/stores/form/getDefaultValuesFromQueryString.js.map +1 -1
  310. package/dist/esm/stores/form/types.d.ts +9 -1
  311. package/dist/esm/stores/form/types.d.ts.map +1 -1
  312. package/dist/esm/stores/form/types.js.map +1 -1
  313. package/dist/esm/stores/form/useClearAmountFields.js +1 -0
  314. package/dist/esm/stores/form/useClearAmountFields.js.map +1 -1
  315. package/dist/esm/stores/form/useFieldActions.js.map +1 -1
  316. package/dist/esm/stores/form/useFieldValues.js.map +1 -1
  317. package/dist/esm/stores/form/useFormRef.js.map +1 -1
  318. package/dist/esm/stores/form/useFormStore.js +2 -2
  319. package/dist/esm/stores/form/useFormStore.js.map +1 -1
  320. package/dist/esm/stores/header/useHeaderStore.js +3 -3
  321. package/dist/esm/stores/header/useHeaderStore.js.map +1 -1
  322. package/dist/esm/stores/inputMode/useInputModeStore.js.map +1 -1
  323. package/dist/esm/stores/navigationTabs/useNavigationTabLabel.js +22 -0
  324. package/dist/esm/stores/navigationTabs/useNavigationTabLabel.js.map +1 -0
  325. package/dist/esm/stores/navigationTabs/useNavigationTabsStore.js +64 -0
  326. package/dist/esm/stores/navigationTabs/useNavigationTabsStore.js.map +1 -0
  327. package/dist/esm/stores/navigationTabs/utils.js +122 -0
  328. package/dist/esm/stores/navigationTabs/utils.js.map +1 -0
  329. package/dist/esm/stores/pinnedTokens/PinnedTokensStore.js +3 -3
  330. package/dist/esm/stores/pinnedTokens/PinnedTokensStore.js.map +1 -1
  331. package/dist/esm/stores/pinnedTokens/createPinnedTokensStore.js.map +1 -1
  332. package/dist/esm/stores/routes/RouteExecutionStore.js +3 -3
  333. package/dist/esm/stores/routes/RouteExecutionStore.js.map +1 -1
  334. package/dist/esm/stores/routes/createRouteExecutionStore.js.map +1 -1
  335. package/dist/esm/stores/routes/useIntermediateRoutesStore.js.map +1 -1
  336. package/dist/esm/stores/routes/useRouteExecutionIndicator.js.map +1 -1
  337. package/dist/esm/stores/routes/utils.js.map +1 -1
  338. package/dist/esm/stores/settings/SettingsStore.js +3 -3
  339. package/dist/esm/stores/settings/SettingsStore.js.map +1 -1
  340. package/dist/esm/stores/settings/createSettingsStore.js +122 -96
  341. package/dist/esm/stores/settings/createSettingsStore.js.map +1 -1
  342. package/dist/esm/stores/settings/types.d.ts +0 -2
  343. package/dist/esm/stores/settings/types.d.ts.map +1 -1
  344. package/dist/esm/stores/settings/types.js.map +1 -1
  345. package/dist/esm/stores/settings/useSettingsActions.js.map +1 -1
  346. package/dist/esm/themes/createTheme.js.map +1 -1
  347. package/dist/esm/themes/utils.js.map +1 -1
  348. package/dist/esm/types/events.d.ts +10 -1
  349. package/dist/esm/types/events.d.ts.map +1 -1
  350. package/dist/esm/types/events.js +2 -0
  351. package/dist/esm/types/events.js.map +1 -1
  352. package/dist/esm/types/widget.d.ts +28 -2
  353. package/dist/esm/types/widget.d.ts.map +1 -1
  354. package/dist/esm/types/widget.js.map +1 -1
  355. package/dist/esm/utils/compactNumberFormatter.js.map +1 -1
  356. package/dist/esm/utils/converters.js.map +1 -1
  357. package/dist/esm/utils/deepEqual.js.map +1 -1
  358. package/dist/esm/utils/fees.js.map +1 -1
  359. package/dist/esm/utils/format.d.ts +1 -1
  360. package/dist/esm/utils/format.d.ts.map +1 -1
  361. package/dist/esm/utils/format.js +2 -2
  362. package/dist/esm/utils/format.js.map +1 -1
  363. package/dist/esm/utils/getActionMessage.js.map +1 -1
  364. package/dist/esm/utils/getErrorMessage.js.map +1 -1
  365. package/dist/esm/utils/item.js.map +1 -1
  366. package/dist/esm/utils/limitOrder.js +61 -0
  367. package/dist/esm/utils/limitOrder.js.map +1 -0
  368. package/dist/esm/utils/{variant.js → mode.js} +2 -2
  369. package/dist/esm/utils/mode.js.map +1 -0
  370. package/dist/esm/utils/navigationRoutes.d.ts +2 -0
  371. package/dist/esm/utils/navigationRoutes.d.ts.map +1 -1
  372. package/dist/esm/utils/navigationRoutes.js +6 -0
  373. package/dist/esm/utils/navigationRoutes.js.map +1 -1
  374. package/dist/esm/utils/prepareActions.js +1 -1
  375. package/dist/esm/utils/prepareActions.js.map +1 -1
  376. package/dist/esm/utils/timer.js.map +1 -1
  377. package/dist/esm/utils/token.js +1 -1
  378. package/dist/esm/utils/token.js.map +1 -1
  379. package/dist/esm/utils/tokenList.js.map +1 -1
  380. package/package.json +13 -13
  381. package/src/App.tsx +7 -7
  382. package/src/AppDefault.tsx +16 -0
  383. package/src/AppDrawer.tsx +77 -78
  384. package/src/AppDrawerContext.ts +2 -2
  385. package/src/components/AmountInput/AmountInputEndAdornment.style.ts +1 -1
  386. package/src/components/AmountInput/AmountInputEndAdornment.tsx +5 -2
  387. package/src/components/AmountInputCard/AmountInputCard.style.tsx +157 -0
  388. package/src/components/AmountInputCard/AmountInputCardPair.tsx +25 -0
  389. package/src/components/AmountInputCard/BalanceDisplay.style.tsx +9 -0
  390. package/src/components/AmountInputCard/BalanceDisplay.tsx +46 -0
  391. package/src/components/AmountInputCard/FiatValueToggle.tsx +55 -0
  392. package/src/components/AmountInputCard/PercentageChips.style.tsx +60 -0
  393. package/src/components/AmountInputCard/PercentageChips.tsx +100 -0
  394. package/src/components/AmountInputCard/ReceiveAmountCard.tsx +219 -0
  395. package/src/components/AmountInputCard/SendAmountCard.tsx +179 -0
  396. package/src/components/Avatar/Avatar.tsx +8 -3
  397. package/src/components/BaseTransactionButton/BaseTransactionButton.tsx +1 -0
  398. package/src/components/BottomSheet/BottomSheet.tsx +56 -52
  399. package/src/components/Header/CloseDrawerButton.tsx +5 -1
  400. package/src/components/Header/Header.tsx +20 -18
  401. package/src/components/Header/HeaderNavigationTabs.tsx +42 -0
  402. package/src/components/Header/HeaderTabs.tsx +48 -0
  403. package/src/components/Header/NavigationHeader.tsx +11 -8
  404. package/src/components/LimitOrderSettings/LimitOrderSettings.style.tsx +69 -0
  405. package/src/components/LimitOrderSettings/LimitOrderSettings.tsx +124 -0
  406. package/src/components/LimitPriceCard/LimitPriceCard.style.tsx +103 -0
  407. package/src/components/LimitPriceCard/LimitPriceCard.tsx +153 -0
  408. package/src/components/LimitPriceCard/LimitPricePresets.tsx +139 -0
  409. package/src/components/ReverseTokensButton/ReverseTokensButton.tsx +4 -1
  410. package/src/components/RouteCard/RouteProviderCard.tsx +113 -0
  411. package/src/components/Routes/LimitOrderRoutes.tsx +64 -0
  412. package/src/components/Routes/Routes.tsx +3 -2
  413. package/src/components/SettingsPanel/SettingsPanel.style.tsx +41 -0
  414. package/src/components/SettingsPanel/SettingsPanel.tsx +73 -0
  415. package/src/components/SettingsPanel/utils.ts +27 -0
  416. package/src/components/Skeleton/WidgetSkeleton.tsx +1 -1
  417. package/src/components/SwapButton/SwapButton.style.tsx +28 -0
  418. package/src/components/SwapButton/SwapButton.tsx +71 -0
  419. package/src/components/Tabs/NavigationTabs.tsx +3 -0
  420. package/src/components/TokenList/TokenDetailsSheet.tsx +9 -7
  421. package/src/components/TokenList/TokenDetailsSheetContent.tsx +176 -177
  422. package/src/components/TokenList/useTokenSelect.ts +2 -2
  423. package/src/components/TokenPillButton/TokenPillButton.style.tsx +50 -0
  424. package/src/components/TokenPillButton/TokenPillButton.tsx +81 -0
  425. package/src/config/version.ts +1 -1
  426. package/src/hooks/useLimitMarketRate.ts +39 -0
  427. package/src/hooks/useLinkedLimitFields.ts +74 -0
  428. package/src/hooks/useRoutes.ts +45 -4
  429. package/src/hooks/useSwapOnly.ts +2 -5
  430. package/src/hooks/useToAddressRequirements.ts +2 -2
  431. package/src/hooks/useWideVariant.ts +8 -2
  432. package/src/pages/MainPage/LimitPageContent.tsx +18 -0
  433. package/src/pages/MainPage/MainPage.tsx +43 -30
  434. package/src/pages/MainPage/MainPageActions.tsx +35 -0
  435. package/src/pages/MainPage/ReviewButton.tsx +15 -3
  436. package/src/pages/RoutePriorityPage.tsx +55 -0
  437. package/src/pages/SendToWallet/BookmarkAddressSheet.tsx +176 -185
  438. package/src/pages/SendToWallet/ConfirmAddressSheet.tsx +9 -6
  439. package/src/pages/SettingsPage/RoutePrioritySettings.tsx +14 -38
  440. package/src/pages/SettingsPage/SettingsCard/SettingCardExpandable.tsx +58 -65
  441. package/src/pages/SettingsPage/SettingsCard/SettingsAccordian.tsx +4 -4
  442. package/src/pages/SettingsPage/SlippageSettings/SlippagePage.tsx +176 -0
  443. package/src/pages/SettingsPage/SlippageSettings/SlippageSettings.style.tsx +32 -25
  444. package/src/pages/SettingsPage/SlippageSettings/SlippageSettings.tsx +14 -128
  445. package/src/pages/SettingsPage/ThemeSettings.tsx +4 -0
  446. package/src/pages/TransactionPage/ConfirmToAddressSheet.tsx +9 -6
  447. package/src/pages/TransactionPage/ExchangeRateBottomSheet.tsx +53 -58
  448. package/src/pages/TransactionPage/TokenValueBottomSheet.tsx +24 -21
  449. package/src/pages/TransactionPage/TransactionExecutionContent.tsx +8 -6
  450. package/src/providers/QueryClientProvider.tsx +2 -2
  451. package/src/providers/SDKClientProvider.tsx +3 -7
  452. package/src/providers/WidgetProvider/WidgetProvider.tsx +6 -7
  453. package/src/stores/StoreProvider.tsx +3 -10
  454. package/src/stores/bookmarks/BookmarkStore.tsx +4 -4
  455. package/src/stores/chains/ChainOrderStore.tsx +4 -4
  456. package/src/stores/form/FormStore.tsx +2 -2
  457. package/src/stores/form/URLSearchParamsBuilder.tsx +25 -3
  458. package/src/stores/form/createFormStore.ts +7 -3
  459. package/src/stores/form/getDefaultValuesFromQueryString.ts +11 -0
  460. package/src/stores/form/types.ts +14 -1
  461. package/src/stores/form/useClearAmountFields.ts +1 -0
  462. package/src/stores/form/useFormStore.ts +2 -2
  463. package/src/stores/header/useHeaderStore.tsx +3 -5
  464. package/src/stores/navigationTabs/types.ts +33 -0
  465. package/src/stores/navigationTabs/useNavigationTabLabel.ts +28 -0
  466. package/src/stores/navigationTabs/useNavigationTabsStore.tsx +113 -0
  467. package/src/stores/navigationTabs/utils.ts +196 -0
  468. package/src/stores/pinnedTokens/PinnedTokensStore.tsx +4 -4
  469. package/src/stores/routes/RouteExecutionStore.tsx +4 -4
  470. package/src/stores/settings/SettingsStore.tsx +4 -4
  471. package/src/stores/settings/createSettingsStore.ts +48 -12
  472. package/src/stores/settings/types.ts +1 -16
  473. package/src/types/events.ts +12 -0
  474. package/src/types/widget.ts +40 -1
  475. package/src/utils/format.ts +6 -2
  476. package/src/utils/limitOrder.ts +88 -0
  477. package/src/utils/navigationRoutes.ts +6 -0
  478. package/dist/esm/components/Header/SplitNavigationTabs.js +0 -33
  479. package/dist/esm/components/Header/SplitNavigationTabs.js.map +0 -1
  480. package/dist/esm/stores/settings/useSplitModeStore.js +0 -36
  481. package/dist/esm/stores/settings/useSplitModeStore.js.map +0 -1
  482. package/dist/esm/utils/variant.js.map +0 -1
  483. package/src/components/Header/SplitNavigationTabs.tsx +0 -32
  484. package/src/stores/settings/useSplitModeStore.tsx +0 -58
  485. /package/src/utils/{variant.ts → mode.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"useExplorer.js","names":[],"sources":["../../../src/hooks/useExplorer.ts"],"sourcesContent":["import type { Chain } from '@lifi/sdk'\nimport { ChainId, ChainType, isHex } from '@lifi/sdk'\nimport { useCallback } from 'react'\nimport { internalExplorerUrl } from '../config/constants.js'\nimport { useAvailableChains } from '../hooks/useAvailableChains.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\n\nconst sanitiseBaseUrl = (baseUrl: string) => baseUrl.trim().replace(/\\/+$/, '')\n\nconst explorerPathOverrides: Partial<\n Record<ChainType | ChainId, { txPath: string; addressPath: string }>\n> = {\n [ChainId.SUI]: { txPath: 'txblock', addressPath: 'coin' },\n [ChainId.LTR]: { txPath: 'logs', addressPath: 'accounts' },\n [ChainType.TVM]: { txPath: '#/transaction', addressPath: '#/address' },\n}\n\ntype TransactionLinkProps = {\n chain?: Chain | number\n txHash?: string\n txLink?: string\n}\n\nexport const useExplorer = (): {\n getTransactionLink: (props: TransactionLinkProps) => string | undefined\n getAddressLink: (address: string, chain?: Chain | number) => string\n} => {\n const { explorerUrls } = useWidgetConfig()\n const { getChainById } = useAvailableChains()\n\n const getExplorerConfig = useCallback(\n (chain?: Chain | number) => {\n const resolvedChain = Number.isFinite(chain)\n ? getChainById(chain as number)\n : (chain as Chain)\n\n const explorerUrl =\n (resolvedChain\n ? (explorerUrls?.[resolvedChain.id]?.[0] ??\n resolvedChain.metamask.blockExplorerUrls[0])\n : explorerUrls?.internal?.[0]) || internalExplorerUrl\n\n const baseUrl =\n typeof explorerUrl === 'string' ? explorerUrl : explorerUrl.url\n\n const overrides =\n explorerPathOverrides[resolvedChain?.id as ChainId] ??\n explorerPathOverrides[resolvedChain?.chainType as ChainType]\n\n const defaultTxPath = overrides?.txPath ?? 'tx'\n const defaultAddressPath = overrides?.addressPath ?? 'address'\n const txPath =\n typeof explorerUrl === 'string'\n ? defaultTxPath\n : explorerUrl.txPath || defaultTxPath\n const addressPath =\n typeof explorerUrl === 'string'\n ? defaultAddressPath\n : explorerUrl.addressPath || defaultAddressPath\n\n return {\n url: sanitiseBaseUrl(baseUrl),\n txPath,\n addressPath,\n resolvedChain,\n hasOverride: Boolean(overrides),\n }\n },\n [explorerUrls, getChainById]\n )\n\n const getTransactionLink = useCallback(\n ({ txHash, txLink, chain }: TransactionLinkProps): string | undefined => {\n if (txHash) {\n const config = getExplorerConfig(chain)\n // For EVM chains, sanity-check the transaction hash as some relayers return custom task hashes that are not visible on-chain.\n // Skip the check when a chain-specific path override is registered — that's an explicit signal the chain's\n // explorer accepts a non-hex hash (e.g. Lighter, whose hash has no 0x prefix).\n const validForEvm =\n config.resolvedChain?.chainType !== ChainType.EVM ||\n config.hasOverride ||\n isHex(txHash, { strict: true })\n if (validForEvm) {\n return `${config.url}/${config.txPath}/${txHash}`\n }\n }\n return txLink\n },\n [getExplorerConfig]\n )\n\n const getAddressLink = useCallback(\n (address: string, chain?: Chain | number) => {\n const config = getExplorerConfig(chain)\n return `${config.url}/${config.addressPath}/${address}`\n },\n [getExplorerConfig]\n )\n\n return {\n getTransactionLink,\n getAddressLink,\n }\n}\n"],"mappings":";;;;;;AAOA,MAAM,mBAAmB,YAAoB,QAAQ,KAAK,EAAE,QAAQ,QAAQ,EAAE;AAE9E,MAAM,wBAEF;EACD,QAAQ,MAAM;EAAE,QAAQ;EAAW,aAAa;CAAO;EACvD,QAAQ,MAAM;EAAE,QAAQ;EAAQ,aAAa;CAAW;EACxD,UAAU,MAAM;EAAE,QAAQ;EAAiB,aAAa;CAAY;AACvE;AAQA,MAAa,oBAGR;CACH,MAAM,EAAE,iBAAiB,gBAAgB;CACzC,MAAM,EAAE,iBAAiB,mBAAmB;CAE5C,MAAM,oBAAoB,aACvB,UAA2B;EAC1B,MAAM,gBAAgB,OAAO,SAAS,KAAK,IACvC,aAAa,KAAe,IAC3B;EAEL,MAAM,eACH,gBACI,eAAe,cAAc,MAAM,MACpC,cAAc,SAAS,kBAAkB,KACzC,cAAc,WAAW,OAAA;EAE/B,MAAM,UACJ,OAAO,gBAAgB,WAAW,cAAc,YAAY;EAE9D,MAAM,YACJ,sBAAsB,eAAe,OACrC,sBAAsB,eAAe;EAEvC,MAAM,gBAAgB,WAAW,UAAU;EAC3C,MAAM,qBAAqB,WAAW,eAAe;EACrD,MAAM,SACJ,OAAO,gBAAgB,WACnB,gBACA,YAAY,UAAU;EAC5B,MAAM,cACJ,OAAO,gBAAgB,WACnB,qBACA,YAAY,eAAe;EAEjC,OAAO;GACL,KAAK,gBAAgB,OAAO;GAC5B;GACA;GACA;GACA,aAAa,QAAQ,SAAS;EAChC;CACF,GACA,CAAC,cAAc,YAAY,CAC7B;CA8BA,OAAO;EACL,oBA7ByB,aACxB,EAAE,QAAQ,QAAQ,YAAsD;GACvE,IAAI,QAAQ;IACV,MAAM,SAAS,kBAAkB,KAAK;IAQtC,IAHE,OAAO,eAAe,cAAc,UAAU,OAC9C,OAAO,eACP,MAAM,QAAQ,EAAE,QAAQ,KAAK,CAAC,GAE9B,OAAO,GAAG,OAAO,IAAI,GAAG,OAAO,OAAO,GAAG;GAE7C;GACA,OAAO;EACT,GACA,CAAC,iBAAiB,CAYD;EACjB,gBAVqB,aACpB,SAAiB,UAA2B;GAC3C,MAAM,SAAS,kBAAkB,KAAK;GACtC,OAAO,GAAG,OAAO,IAAI,GAAG,OAAO,YAAY,GAAG;EAChD,GACA,CAAC,iBAAiB,CAKL;CACf;AACF"}
1
+ {"version":3,"file":"useExplorer.js","names":[],"sources":["../../../src/hooks/useExplorer.ts"],"sourcesContent":["import type { Chain } from '@lifi/sdk'\nimport { ChainId, ChainType, isHex } from '@lifi/sdk'\nimport { useCallback } from 'react'\nimport { internalExplorerUrl } from '../config/constants.js'\nimport { useAvailableChains } from '../hooks/useAvailableChains.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\n\nconst sanitiseBaseUrl = (baseUrl: string) => baseUrl.trim().replace(/\\/+$/, '')\n\nconst explorerPathOverrides: Partial<\n Record<ChainType | ChainId, { txPath: string; addressPath: string }>\n> = {\n [ChainId.SUI]: { txPath: 'txblock', addressPath: 'coin' },\n [ChainId.LTR]: { txPath: 'logs', addressPath: 'accounts' },\n [ChainType.TVM]: { txPath: '#/transaction', addressPath: '#/address' },\n}\n\ntype TransactionLinkProps = {\n chain?: Chain | number\n txHash?: string\n txLink?: string\n}\n\nexport const useExplorer = (): {\n getTransactionLink: (props: TransactionLinkProps) => string | undefined\n getAddressLink: (address: string, chain?: Chain | number) => string\n} => {\n const { explorerUrls } = useWidgetConfig()\n const { getChainById } = useAvailableChains()\n\n const getExplorerConfig = useCallback(\n (chain?: Chain | number) => {\n const resolvedChain = Number.isFinite(chain)\n ? getChainById(chain as number)\n : (chain as Chain)\n\n const explorerUrl =\n (resolvedChain\n ? (explorerUrls?.[resolvedChain.id]?.[0] ??\n resolvedChain.metamask.blockExplorerUrls[0])\n : explorerUrls?.internal?.[0]) || internalExplorerUrl\n\n const baseUrl =\n typeof explorerUrl === 'string' ? explorerUrl : explorerUrl.url\n\n const overrides =\n explorerPathOverrides[resolvedChain?.id as ChainId] ??\n explorerPathOverrides[resolvedChain?.chainType as ChainType]\n\n const defaultTxPath = overrides?.txPath ?? 'tx'\n const defaultAddressPath = overrides?.addressPath ?? 'address'\n const txPath =\n typeof explorerUrl === 'string'\n ? defaultTxPath\n : explorerUrl.txPath || defaultTxPath\n const addressPath =\n typeof explorerUrl === 'string'\n ? defaultAddressPath\n : explorerUrl.addressPath || defaultAddressPath\n\n return {\n url: sanitiseBaseUrl(baseUrl),\n txPath,\n addressPath,\n resolvedChain,\n hasOverride: Boolean(overrides),\n }\n },\n [explorerUrls, getChainById]\n )\n\n const getTransactionLink = useCallback(\n ({ txHash, txLink, chain }: TransactionLinkProps): string | undefined => {\n if (txHash) {\n const config = getExplorerConfig(chain)\n // For EVM chains, sanity-check the transaction hash as some relayers return custom task hashes that are not visible on-chain.\n // Skip the check when a chain-specific path override is registered — that's an explicit signal the chain's\n // explorer accepts a non-hex hash (e.g. Lighter, whose hash has no 0x prefix).\n const validForEvm =\n config.resolvedChain?.chainType !== ChainType.EVM ||\n config.hasOverride ||\n isHex(txHash, { strict: true })\n if (validForEvm) {\n return `${config.url}/${config.txPath}/${txHash}`\n }\n }\n return txLink\n },\n [getExplorerConfig]\n )\n\n const getAddressLink = useCallback(\n (address: string, chain?: Chain | number) => {\n const config = getExplorerConfig(chain)\n return `${config.url}/${config.addressPath}/${address}`\n },\n [getExplorerConfig]\n )\n\n return {\n getTransactionLink,\n getAddressLink,\n }\n}\n"],"mappings":";;;;;;AAOA,MAAM,mBAAmB,YAAoB,QAAQ,KAAK,CAAC,CAAC,QAAQ,QAAQ,EAAE;AAE9E,MAAM,wBAEF;EACD,QAAQ,MAAM;EAAE,QAAQ;EAAW,aAAa;CAAO;EACvD,QAAQ,MAAM;EAAE,QAAQ;EAAQ,aAAa;CAAW;EACxD,UAAU,MAAM;EAAE,QAAQ;EAAiB,aAAa;CAAY;AACvE;AAQA,MAAa,oBAGR;CACH,MAAM,EAAE,iBAAiB,gBAAgB;CACzC,MAAM,EAAE,iBAAiB,mBAAmB;CAE5C,MAAM,oBAAoB,aACvB,UAA2B;EAC1B,MAAM,gBAAgB,OAAO,SAAS,KAAK,IACvC,aAAa,KAAe,IAC3B;EAEL,MAAM,eACH,gBACI,eAAe,cAAc,GAAG,GAAG,MACpC,cAAc,SAAS,kBAAkB,KACzC,cAAc,WAAW,OAAA;EAE/B,MAAM,UACJ,OAAO,gBAAgB,WAAW,cAAc,YAAY;EAE9D,MAAM,YACJ,sBAAsB,eAAe,OACrC,sBAAsB,eAAe;EAEvC,MAAM,gBAAgB,WAAW,UAAU;EAC3C,MAAM,qBAAqB,WAAW,eAAe;EACrD,MAAM,SACJ,OAAO,gBAAgB,WACnB,gBACA,YAAY,UAAU;EAC5B,MAAM,cACJ,OAAO,gBAAgB,WACnB,qBACA,YAAY,eAAe;EAEjC,OAAO;GACL,KAAK,gBAAgB,OAAO;GAC5B;GACA;GACA;GACA,aAAa,QAAQ,SAAS;EAChC;CACF,GACA,CAAC,cAAc,YAAY,CAC7B;CA8BA,OAAO;EACL,oBA7ByB,aACxB,EAAE,QAAQ,QAAQ,YAAsD;GACvE,IAAI,QAAQ;IACV,MAAM,SAAS,kBAAkB,KAAK;IAQtC,IAHE,OAAO,eAAe,cAAc,UAAU,OAC9C,OAAO,eACP,MAAM,QAAQ,EAAE,QAAQ,KAAK,CAAC,GAE9B,OAAO,GAAG,OAAO,IAAI,GAAG,OAAO,OAAO,GAAG;GAE7C;GACA,OAAO;EACT,GACA,CAAC,iBAAiB,CAYD;EACjB,gBAVqB,aACpB,SAAiB,UAA2B;GAC3C,MAAM,SAAS,kBAAkB,KAAK;GACtC,OAAO,GAAG,OAAO,IAAI,GAAG,OAAO,YAAY,GAAG;EAChD,GACA,CAAC,iBAAiB,CAKL;CACf;AACF"}
@@ -1,5 +1,5 @@
1
- import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
2
1
  import { getConfigItemSets, isFormItemAllowed } from "../utils/item.js";
2
+ import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
3
3
  import { useSDKClient } from "../providers/SDKClientProvider.js";
4
4
  import { isSupportedToken } from "../utils/tokenList.js";
5
5
  import { ChainType, getWalletBalances } from "@lifi/sdk";
@@ -1 +1 @@
1
- {"version":3,"file":"useFilteredByTokenBalances.js","names":[],"sources":["../../../src/hooks/useFilteredByTokenBalances.ts"],"sourcesContent":["import {\n type BaseToken,\n ChainType,\n getWalletBalances,\n type TokenExtended,\n type WalletTokenExtended,\n} from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormType } from '../stores/form/types.js'\nimport { getConfigItemSets, isFormItemAllowed } from '../utils/item.js'\nimport { isSupportedToken } from '../utils/tokenList.js'\n\nexport const useFilteredTokensByBalance = (\n accountsWithTokens?: Record<\n string,\n { chainType: ChainType; tokens: Record<number, TokenExtended[]> }\n >,\n formType?: FormType\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const { tokens: configTokens } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const evmAddress = useMemo(() => {\n const evmAccount = Object.entries(accountsWithTokens ?? {}).find(\n ([_, { chainType }]) => chainType === ChainType.EVM\n )\n return evmAccount?.[0]\n }, [accountsWithTokens])\n\n const { data: existingBalances, isLoading } = useQuery({\n queryKey: ['existing-evm-balances', evmAddress],\n queryFn: () => getWalletBalances(sdkClient, evmAddress ?? ''),\n enabled: !!evmAddress,\n refetchInterval: 30_000, // 30 seconds\n staleTime: 30_000, // 30 seconds\n retry: false,\n })\n\n const accountsWithFilteredTokens = useMemo(() => {\n if (!accountsWithTokens) {\n return undefined\n }\n\n // Early return if no existing balances - return all tokens\n const result: Record<string, Record<number, TokenExtended[]>> = {}\n if (!existingBalances) {\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = tokens\n }\n return result\n }\n\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = {}\n\n for (const [chainIdStr, chainTokens] of Object.entries(tokens)) {\n const chainId = Number(chainIdStr)\n // Get balances for this specific chain\n const balances = existingBalances?.[chainId]\n // If no balances, RPC all tokens of the chain\n if (!balances?.length) {\n if (chainTokens.length) {\n result[address][chainId] = chainTokens\n }\n continue\n }\n\n // Optimize token matching with Set for O(1) lookup\n const balanceSet = new Set(\n balances.map((balance: WalletTokenExtended) =>\n balance.address.toLowerCase()\n )\n )\n\n // Get tokens that are in chainTokens and have balances\n const filteredTokens = chainTokens.filter((token) => {\n const tokenKey = token.address.toLowerCase()\n return balanceSet.has(tokenKey)\n })\n\n // Get tokens that are in balances but not in chainTokens\n const chainTokenSet = new Set(\n chainTokens.map((token) => token.address.toLowerCase())\n )\n\n // Get allowed addresses from config tokens\n const allowedAddressesConfig = getConfigItemSets(\n configTokens,\n (tokens: BaseToken[]) =>\n new Set(\n tokens\n .filter((t) => Number(t.chainId) === chainId)\n .map((t) => t.address.toLowerCase())\n ),\n formType\n )\n\n const additionalTokens = balances\n .filter((balance: WalletTokenExtended) => {\n const balanceKey = balance.address.toLowerCase()\n return (\n !chainTokenSet.has(balanceKey) &&\n isSupportedToken(balance) &&\n isFormItemAllowed(\n balance,\n allowedAddressesConfig,\n formType,\n (t) => t.address.toLowerCase()\n )\n )\n })\n // Mark tokens from wallet balances as unverified\n .map((token: WalletTokenExtended) => ({\n ...token,\n verified: false,\n })) as TokenExtended[]\n\n // Combine both sets of tokens - convert WalletTokenExtended to TokenAmount\n const allTokens = [\n ...filteredTokens,\n ...additionalTokens,\n ] as TokenExtended[]\n\n if (allTokens.length) {\n result[address][chainId] = allTokens\n }\n }\n }\n\n return result\n }, [accountsWithTokens, existingBalances, configTokens, formType])\n\n return { data: accountsWithFilteredTokens, isLoading }\n}\n"],"mappings":";;;;;;;;AAeA,MAAa,8BACX,oBAIA,aAIG;CACH,MAAM,EAAE,QAAQ,iBAAiB,gBAAgB;CACjD,MAAM,YAAY,aAAa;CAE/B,MAAM,aAAa,cAAc;EAI/B,OAHmB,OAAO,QAAQ,sBAAsB,CAAC,CAAC,EAAE,MACzD,CAAC,GAAG,EAAE,iBAAiB,cAAc,UAAU,GAElC,IAAI;CACtB,GAAG,CAAC,kBAAkB,CAAC;CAEvB,MAAM,EAAE,MAAM,kBAAkB,cAAc,SAAS;EACrD,UAAU,CAAC,yBAAyB,UAAU;EAC9C,eAAe,kBAAkB,WAAW,cAAc,EAAE;EAC5D,SAAS,CAAC,CAAC;EACX,iBAAiB;EACjB,WAAW;EACX,OAAO;CACT,CAAC;CAgGD,OAAO;EAAE,MA9F0B,cAAc;GAC/C,IAAI,CAAC,oBACH;GAIF,MAAM,SAA0D,CAAC;GACjE,IAAI,CAAC,kBAAkB;IACrB,KAAK,MAAM,CAAC,SAAS,EAAE,aAAa,OAAO,QAAQ,kBAAkB,GACnE,OAAO,WAAW;IAEpB,OAAO;GACT;GAEA,KAAK,MAAM,CAAC,SAAS,EAAE,aAAa,OAAO,QAAQ,kBAAkB,GAAG;IACtE,OAAO,WAAW,CAAC;IAEnB,KAAK,MAAM,CAAC,YAAY,gBAAgB,OAAO,QAAQ,MAAM,GAAG;KAC9D,MAAM,UAAU,OAAO,UAAU;KAEjC,MAAM,WAAW,mBAAmB;KAEpC,IAAI,CAAC,UAAU,QAAQ;MACrB,IAAI,YAAY,QACd,OAAO,SAAS,WAAW;MAE7B;KACF;KAGA,MAAM,aAAa,IAAI,IACrB,SAAS,KAAK,YACZ,QAAQ,QAAQ,YAAY,CAC9B,CACF;KAGA,MAAM,iBAAiB,YAAY,QAAQ,UAAU;MACnD,MAAM,WAAW,MAAM,QAAQ,YAAY;MAC3C,OAAO,WAAW,IAAI,QAAQ;KAChC,CAAC;KAGD,MAAM,gBAAgB,IAAI,IACxB,YAAY,KAAK,UAAU,MAAM,QAAQ,YAAY,CAAC,CACxD;KAGA,MAAM,yBAAyB,kBAC7B,eACC,WACC,IAAI,IACF,OACG,QAAQ,MAAM,OAAO,EAAE,OAAO,MAAM,OAAO,EAC3C,KAAK,MAAM,EAAE,QAAQ,YAAY,CAAC,CACvC,GACF,QACF;KAEA,MAAM,mBAAmB,SACtB,QAAQ,YAAiC;MACxC,MAAM,aAAa,QAAQ,QAAQ,YAAY;MAC/C,OACE,CAAC,cAAc,IAAI,UAAU,KAC7B,iBAAiB,OAAO,KACxB,kBACE,SACA,wBACA,WACC,MAAM,EAAE,QAAQ,YAAY,CAC/B;KAEJ,CAAC,EAEA,KAAK,WAAgC;MACpC,GAAG;MACH,UAAU;KACZ,EAAE;KAGJ,MAAM,YAAY,CAChB,GAAG,gBACH,GAAG,gBACL;KAEA,IAAI,UAAU,QACZ,OAAO,SAAS,WAAW;IAE/B;GACF;GAEA,OAAO;EACT,GAAG;GAAC;GAAoB;GAAkB;GAAc;EAAQ,CAExB;EAAG;CAAU;AACvD"}
1
+ {"version":3,"file":"useFilteredByTokenBalances.js","names":[],"sources":["../../../src/hooks/useFilteredByTokenBalances.ts"],"sourcesContent":["import {\n type BaseToken,\n ChainType,\n getWalletBalances,\n type TokenExtended,\n type WalletTokenExtended,\n} from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormType } from '../stores/form/types.js'\nimport { getConfigItemSets, isFormItemAllowed } from '../utils/item.js'\nimport { isSupportedToken } from '../utils/tokenList.js'\n\nexport const useFilteredTokensByBalance = (\n accountsWithTokens?: Record<\n string,\n { chainType: ChainType; tokens: Record<number, TokenExtended[]> }\n >,\n formType?: FormType\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const { tokens: configTokens } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const evmAddress = useMemo(() => {\n const evmAccount = Object.entries(accountsWithTokens ?? {}).find(\n ([_, { chainType }]) => chainType === ChainType.EVM\n )\n return evmAccount?.[0]\n }, [accountsWithTokens])\n\n const { data: existingBalances, isLoading } = useQuery({\n queryKey: ['existing-evm-balances', evmAddress],\n queryFn: () => getWalletBalances(sdkClient, evmAddress ?? ''),\n enabled: !!evmAddress,\n refetchInterval: 30_000, // 30 seconds\n staleTime: 30_000, // 30 seconds\n retry: false,\n })\n\n const accountsWithFilteredTokens = useMemo(() => {\n if (!accountsWithTokens) {\n return undefined\n }\n\n // Early return if no existing balances - return all tokens\n const result: Record<string, Record<number, TokenExtended[]>> = {}\n if (!existingBalances) {\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = tokens\n }\n return result\n }\n\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = {}\n\n for (const [chainIdStr, chainTokens] of Object.entries(tokens)) {\n const chainId = Number(chainIdStr)\n // Get balances for this specific chain\n const balances = existingBalances?.[chainId]\n // If no balances, RPC all tokens of the chain\n if (!balances?.length) {\n if (chainTokens.length) {\n result[address][chainId] = chainTokens\n }\n continue\n }\n\n // Optimize token matching with Set for O(1) lookup\n const balanceSet = new Set(\n balances.map((balance: WalletTokenExtended) =>\n balance.address.toLowerCase()\n )\n )\n\n // Get tokens that are in chainTokens and have balances\n const filteredTokens = chainTokens.filter((token) => {\n const tokenKey = token.address.toLowerCase()\n return balanceSet.has(tokenKey)\n })\n\n // Get tokens that are in balances but not in chainTokens\n const chainTokenSet = new Set(\n chainTokens.map((token) => token.address.toLowerCase())\n )\n\n // Get allowed addresses from config tokens\n const allowedAddressesConfig = getConfigItemSets(\n configTokens,\n (tokens: BaseToken[]) =>\n new Set(\n tokens\n .filter((t) => Number(t.chainId) === chainId)\n .map((t) => t.address.toLowerCase())\n ),\n formType\n )\n\n const additionalTokens = balances\n .filter((balance: WalletTokenExtended) => {\n const balanceKey = balance.address.toLowerCase()\n return (\n !chainTokenSet.has(balanceKey) &&\n isSupportedToken(balance) &&\n isFormItemAllowed(\n balance,\n allowedAddressesConfig,\n formType,\n (t) => t.address.toLowerCase()\n )\n )\n })\n // Mark tokens from wallet balances as unverified\n .map((token: WalletTokenExtended) => ({\n ...token,\n verified: false,\n })) as TokenExtended[]\n\n // Combine both sets of tokens - convert WalletTokenExtended to TokenAmount\n const allTokens = [\n ...filteredTokens,\n ...additionalTokens,\n ] as TokenExtended[]\n\n if (allTokens.length) {\n result[address][chainId] = allTokens\n }\n }\n }\n\n return result\n }, [accountsWithTokens, existingBalances, configTokens, formType])\n\n return { data: accountsWithFilteredTokens, isLoading }\n}\n"],"mappings":";;;;;;;;AAeA,MAAa,8BACX,oBAIA,aAIG;CACH,MAAM,EAAE,QAAQ,iBAAiB,gBAAgB;CACjD,MAAM,YAAY,aAAa;CAE/B,MAAM,aAAa,cAAc;EAI/B,OAHmB,OAAO,QAAQ,sBAAsB,CAAC,CAAC,CAAC,CAAC,MACzD,CAAC,GAAG,EAAE,iBAAiB,cAAc,UAAU,GAElC,CAAC,GAAG;CACtB,GAAG,CAAC,kBAAkB,CAAC;CAEvB,MAAM,EAAE,MAAM,kBAAkB,cAAc,SAAS;EACrD,UAAU,CAAC,yBAAyB,UAAU;EAC9C,eAAe,kBAAkB,WAAW,cAAc,EAAE;EAC5D,SAAS,CAAC,CAAC;EACX,iBAAiB;EACjB,WAAW;EACX,OAAO;CACT,CAAC;CAgGD,OAAO;EAAE,MA9F0B,cAAc;GAC/C,IAAI,CAAC,oBACH;GAIF,MAAM,SAA0D,CAAC;GACjE,IAAI,CAAC,kBAAkB;IACrB,KAAK,MAAM,CAAC,SAAS,EAAE,aAAa,OAAO,QAAQ,kBAAkB,GACnE,OAAO,WAAW;IAEpB,OAAO;GACT;GAEA,KAAK,MAAM,CAAC,SAAS,EAAE,aAAa,OAAO,QAAQ,kBAAkB,GAAG;IACtE,OAAO,WAAW,CAAC;IAEnB,KAAK,MAAM,CAAC,YAAY,gBAAgB,OAAO,QAAQ,MAAM,GAAG;KAC9D,MAAM,UAAU,OAAO,UAAU;KAEjC,MAAM,WAAW,mBAAmB;KAEpC,IAAI,CAAC,UAAU,QAAQ;MACrB,IAAI,YAAY,QACd,OAAO,QAAQ,CAAC,WAAW;MAE7B;KACF;KAGA,MAAM,aAAa,IAAI,IACrB,SAAS,KAAK,YACZ,QAAQ,QAAQ,YAAY,CAC9B,CACF;KAGA,MAAM,iBAAiB,YAAY,QAAQ,UAAU;MACnD,MAAM,WAAW,MAAM,QAAQ,YAAY;MAC3C,OAAO,WAAW,IAAI,QAAQ;KAChC,CAAC;KAGD,MAAM,gBAAgB,IAAI,IACxB,YAAY,KAAK,UAAU,MAAM,QAAQ,YAAY,CAAC,CACxD;KAGA,MAAM,yBAAyB,kBAC7B,eACC,WACC,IAAI,IACF,OACG,QAAQ,MAAM,OAAO,EAAE,OAAO,MAAM,OAAO,CAAC,CAC5C,KAAK,MAAM,EAAE,QAAQ,YAAY,CAAC,CACvC,GACF,QACF;KAEA,MAAM,mBAAmB,SACtB,QAAQ,YAAiC;MACxC,MAAM,aAAa,QAAQ,QAAQ,YAAY;MAC/C,OACE,CAAC,cAAc,IAAI,UAAU,KAC7B,iBAAiB,OAAO,KACxB,kBACE,SACA,wBACA,WACC,MAAM,EAAE,QAAQ,YAAY,CAC/B;KAEJ,CAAC,CAAC,CAED,KAAK,WAAgC;MACpC,GAAG;MACH,UAAU;KACZ,EAAE;KAGJ,MAAM,YAAY,CAChB,GAAG,gBACH,GAAG,gBACL;KAEA,IAAI,UAAU,QACZ,OAAO,QAAQ,CAAC,WAAW;IAE/B;GACF;GAEA,OAAO;EACT,GAAG;GAAC;GAAoB;GAAkB;GAAc;EAAQ,CAExB;EAAG;CAAU;AACvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"useFromTokenSufficiency.js","names":[],"sources":["../../../src/hooks/useFromTokenSufficiency.ts"],"sourcesContent":["import { parseUnits, type RouteExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { keepPreviousData, useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { isRouteDone } from '../stores/routes/utils.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useTokenAddressBalance } from './useTokenAddressBalance.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nconst refetchInterval = 30_000\n\nexport const useFromTokenSufficiency = (\n route?: RouteExtended\n): {\n insufficientFromToken: boolean | undefined\n isLoading: boolean\n} => {\n const [fromChainId, fromTokenAddress, fromAmount] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'fromAmount'\n )\n const { keyPrefix } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n let chainId = fromChainId\n let tokenAddress = fromTokenAddress\n if (route) {\n chainId = route.fromToken.chainId\n tokenAddress = route.fromToken.address\n }\n\n const {\n token,\n chain,\n isLoading: isTokenAddressBalanceLoading,\n } = useTokenAddressBalance(chainId, tokenAddress)\n\n const { account } = useAccount({ chainType: chain?.chainType })\n\n const { data: insufficientFromToken, isLoading } = useQuery({\n queryKey: [\n getQueryKey('from-token-sufficiency-check', keyPrefix),\n account.address,\n chainId,\n tokenAddress,\n route?.id ?? fromAmount,\n ] as const,\n queryFn: async ({ queryKey: [, accountAddress] }) => {\n if (!accountAddress || !token) {\n return\n }\n const parsedFromAmount = parseUnits(fromAmount, token.decimals)\n let currentTokenBalance = token.amount ?? 0n\n\n if (!route || isRouteDone(route)) {\n const insufficientFunds = currentTokenBalance < parsedFromAmount\n return insufficientFunds\n }\n\n const currentAction = route.steps.filter(\n (step) => step.execution?.status !== 'DONE'\n )[0]?.action\n\n if (\n token.chainId === currentAction.fromToken.chainId &&\n token.address === currentAction.fromToken.address &&\n currentTokenBalance > 0\n ) {\n const insufficientFunds = BigInt(route.fromAmount) > currentTokenBalance\n return insufficientFunds\n }\n\n const tokenBalances = await getTokenBalancesWithRetry(\n sdkClient,\n accountAddress,\n [currentAction.fromToken]\n )\n\n currentTokenBalance = tokenBalances?.[0]?.amount ?? 0n\n const insufficientFunds =\n BigInt(currentAction.fromAmount) > currentTokenBalance\n return insufficientFunds\n },\n\n enabled: Boolean(account.address && token && !isTokenAddressBalanceLoading),\n refetchInterval,\n staleTime: refetchInterval,\n placeholderData: account.address ? keepPreviousData : undefined,\n })\n\n return {\n insufficientFromToken,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,kBAAkB;AAExB,MAAa,2BACX,UAIG;CACH,MAAM,CAAC,aAAa,kBAAkB,cAAc,eAClD,aACA,aACA,YACF;CACA,MAAM,EAAE,cAAc,gBAAgB;CACtC,MAAM,YAAY,aAAa;CAE/B,IAAI,UAAU;CACd,IAAI,eAAe;CACnB,IAAI,OAAO;EACT,UAAU,MAAM,UAAU;EAC1B,eAAe,MAAM,UAAU;CACjC;CAEA,MAAM,EACJ,OACA,OACA,WAAW,iCACT,uBAAuB,SAAS,YAAY;CAEhD,MAAM,EAAE,YAAY,WAAW,EAAE,WAAW,OAAO,UAAU,CAAC;CAE9D,MAAM,EAAE,MAAM,uBAAuB,cAAc,SAAS;EAC1D,UAAU;GACR,YAAY,gCAAgC,SAAS;GACrD,QAAQ;GACR;GACA;GACA,OAAO,MAAM;EACf;EACA,SAAS,OAAO,EAAE,UAAU,GAAG,sBAAsB;GACnD,IAAI,CAAC,kBAAkB,CAAC,OACtB;GAEF,MAAM,mBAAmB,WAAW,YAAY,MAAM,QAAQ;GAC9D,IAAI,sBAAsB,MAAM,UAAU;GAE1C,IAAI,CAAC,SAAS,YAAY,KAAK,GAE7B,OAD0B,sBAAsB;GAIlD,MAAM,gBAAgB,MAAM,MAAM,QAC/B,SAAS,KAAK,WAAW,WAAW,MACvC,EAAE,IAAI;GAEN,IACE,MAAM,YAAY,cAAc,UAAU,WAC1C,MAAM,YAAY,cAAc,UAAU,WAC1C,sBAAsB,GAGtB,OAD0B,OAAO,MAAM,UAAU,IAAI;GAUvD,uBAAsB,MANM,0BAC1B,WACA,gBACA,CAAC,cAAc,SAAS,CAC1B,KAEsC,IAAI,UAAU;GAGpD,OADE,OAAO,cAAc,UAAU,IAAI;EAEvC;EAEA,SAAS,QAAQ,QAAQ,WAAW,SAAS,CAAC,4BAA4B;EAC1E;EACA,WAAW;EACX,iBAAiB,QAAQ,UAAU,mBAAmB,KAAA;CACxD,CAAC;CAED,OAAO;EACL;EACA;CACF;AACF"}
1
+ {"version":3,"file":"useFromTokenSufficiency.js","names":[],"sources":["../../../src/hooks/useFromTokenSufficiency.ts"],"sourcesContent":["import { parseUnits, type RouteExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { keepPreviousData, useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { isRouteDone } from '../stores/routes/utils.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useTokenAddressBalance } from './useTokenAddressBalance.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nconst refetchInterval = 30_000\n\nexport const useFromTokenSufficiency = (\n route?: RouteExtended\n): {\n insufficientFromToken: boolean | undefined\n isLoading: boolean\n} => {\n const [fromChainId, fromTokenAddress, fromAmount] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'fromAmount'\n )\n const { keyPrefix } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n let chainId = fromChainId\n let tokenAddress = fromTokenAddress\n if (route) {\n chainId = route.fromToken.chainId\n tokenAddress = route.fromToken.address\n }\n\n const {\n token,\n chain,\n isLoading: isTokenAddressBalanceLoading,\n } = useTokenAddressBalance(chainId, tokenAddress)\n\n const { account } = useAccount({ chainType: chain?.chainType })\n\n const { data: insufficientFromToken, isLoading } = useQuery({\n queryKey: [\n getQueryKey('from-token-sufficiency-check', keyPrefix),\n account.address,\n chainId,\n tokenAddress,\n route?.id ?? fromAmount,\n ] as const,\n queryFn: async ({ queryKey: [, accountAddress] }) => {\n if (!accountAddress || !token) {\n return\n }\n const parsedFromAmount = parseUnits(fromAmount, token.decimals)\n let currentTokenBalance = token.amount ?? 0n\n\n if (!route || isRouteDone(route)) {\n const insufficientFunds = currentTokenBalance < parsedFromAmount\n return insufficientFunds\n }\n\n const currentAction = route.steps.filter(\n (step) => step.execution?.status !== 'DONE'\n )[0]?.action\n\n if (\n token.chainId === currentAction.fromToken.chainId &&\n token.address === currentAction.fromToken.address &&\n currentTokenBalance > 0\n ) {\n const insufficientFunds = BigInt(route.fromAmount) > currentTokenBalance\n return insufficientFunds\n }\n\n const tokenBalances = await getTokenBalancesWithRetry(\n sdkClient,\n accountAddress,\n [currentAction.fromToken]\n )\n\n currentTokenBalance = tokenBalances?.[0]?.amount ?? 0n\n const insufficientFunds =\n BigInt(currentAction.fromAmount) > currentTokenBalance\n return insufficientFunds\n },\n\n enabled: Boolean(account.address && token && !isTokenAddressBalanceLoading),\n refetchInterval,\n staleTime: refetchInterval,\n placeholderData: account.address ? keepPreviousData : undefined,\n })\n\n return {\n insufficientFromToken,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,kBAAkB;AAExB,MAAa,2BACX,UAIG;CACH,MAAM,CAAC,aAAa,kBAAkB,cAAc,eAClD,aACA,aACA,YACF;CACA,MAAM,EAAE,cAAc,gBAAgB;CACtC,MAAM,YAAY,aAAa;CAE/B,IAAI,UAAU;CACd,IAAI,eAAe;CACnB,IAAI,OAAO;EACT,UAAU,MAAM,UAAU;EAC1B,eAAe,MAAM,UAAU;CACjC;CAEA,MAAM,EACJ,OACA,OACA,WAAW,iCACT,uBAAuB,SAAS,YAAY;CAEhD,MAAM,EAAE,YAAY,WAAW,EAAE,WAAW,OAAO,UAAU,CAAC;CAE9D,MAAM,EAAE,MAAM,uBAAuB,cAAc,SAAS;EAC1D,UAAU;GACR,YAAY,gCAAgC,SAAS;GACrD,QAAQ;GACR;GACA;GACA,OAAO,MAAM;EACf;EACA,SAAS,OAAO,EAAE,UAAU,GAAG,sBAAsB;GACnD,IAAI,CAAC,kBAAkB,CAAC,OACtB;GAEF,MAAM,mBAAmB,WAAW,YAAY,MAAM,QAAQ;GAC9D,IAAI,sBAAsB,MAAM,UAAU;GAE1C,IAAI,CAAC,SAAS,YAAY,KAAK,GAE7B,OAD0B,sBAAsB;GAIlD,MAAM,gBAAgB,MAAM,MAAM,QAC/B,SAAS,KAAK,WAAW,WAAW,MACvC,CAAC,CAAC,EAAE,EAAE;GAEN,IACE,MAAM,YAAY,cAAc,UAAU,WAC1C,MAAM,YAAY,cAAc,UAAU,WAC1C,sBAAsB,GAGtB,OAD0B,OAAO,MAAM,UAAU,IAAI;GAUvD,uBAAsB,MANM,0BAC1B,WACA,gBACA,CAAC,cAAc,SAAS,CAC1B,EAAA,GAEsC,EAAE,EAAE,UAAU;GAGpD,OADE,OAAO,cAAc,UAAU,IAAI;EAEvC;EAEA,SAAS,QAAQ,QAAQ,WAAW,SAAS,CAAC,4BAA4B;EAC1E;EACA,WAAW;EACX,iBAAiB,QAAQ,UAAU,mBAAmB,KAAA;CACxD,CAAC;CAED,OAAO;EACL;EACA;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useGasSufficiency.js","names":[],"sources":["../../../src/hooks/useGasSufficiency.ts"],"sourcesContent":["import type { EVMChain, RouteExtended, Token, TokenAmount } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nexport interface GasSufficiency {\n gasAmount: bigint\n tokenAmount?: bigint\n insufficientAmount?: bigint\n insufficient?: boolean\n token: Token\n chain?: EVMChain\n}\n\nconst refetchInterval = 30_000\n\nexport const useGasSufficiency = (\n route?: RouteExtended\n): {\n insufficientGas: GasSufficiency[] | undefined\n isLoading: boolean\n} => {\n const { getChainById } = useAvailableChains()\n const { account: EVMAccount, accounts } = useAccount({\n chainType: ChainType.EVM,\n })\n const { keyPrefix, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const { relevantAccounts, relevantAccountsQueryKey } = useMemo(() => {\n const chainTypes = route?.steps.reduce((acc, step) => {\n const chainType = getChainById(step.action.fromChainId)?.chainType\n if (chainType) {\n acc.add(chainType)\n }\n return acc\n }, new Set<ChainType>())\n\n const relevantAccounts = accounts.filter(\n (account) =>\n account.isConnected &&\n account.address &&\n chainTypes?.has(account.chainType)\n )\n return {\n relevantAccounts,\n relevantAccountsQueryKey: relevantAccounts\n .map((account) => account.address)\n .join(','),\n }\n }, [accounts, route?.steps, getChainById])\n\n const { isContractAddress, isLoading: isContractAddressLoading } =\n useIsContractAddress(\n EVMAccount.address,\n route?.fromChainId,\n EVMAccount.chainType\n )\n\n const { data: insufficientGas, isLoading } = useQuery<GasSufficiency[]>({\n queryKey: [\n getQueryKey('gas-sufficiency-check', keyPrefix),\n relevantAccountsQueryKey,\n route?.id,\n isContractAddress,\n ] as const,\n queryFn: async () => {\n if (!route) {\n return []\n }\n\n // Filter out steps that are relayer steps or have primaryType 'Permit' or 'Order'\n const filteredSteps = route.steps.filter(\n (step) =>\n !step.typedData?.some(\n (t) => t.primaryType === 'Permit' || t.primaryType === 'Order'\n )\n )\n\n // If all steps are filtered out, we don't need to check for gas sufficiency\n if (!filteredSteps.length) {\n return []\n }\n\n // We assume that LI.Fuel protocol always refuels the destination chain\n const hasRefuelStep = route.steps\n .flatMap((step) => step.includedSteps)\n .some((includedStep) => includedStep.tool === 'gasZip')\n\n const gasCosts = filteredSteps\n .filter((step) => step.execution?.status !== 'DONE')\n .reduce(\n (groupedGasCosts, step) => {\n // We need to avoid destination chain step sufficiency check if we have LI.Fuel protocol sub-step\n const skipDueToRefuel =\n step.action.fromChainId === route.toChainId && hasRefuelStep\n if (step.estimate.gasCosts && !skipDueToRefuel) {\n const { token } = step.estimate.gasCosts[0]\n const gasCostAmount = step.estimate.gasCosts.reduce(\n (amount, gasCost) =>\n amount + BigInt(Number(gasCost.amount).toFixed(0)),\n 0n\n )\n if (gasCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + gasCostAmount\n : gasCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n // Add fees paid in native tokens to gas sufficiency check (included: false)\n const nonIncludedFeeCosts = step.estimate.feeCosts?.filter(\n (feeCost) => !feeCost.included\n )\n if (nonIncludedFeeCosts?.length) {\n const { token } = nonIncludedFeeCosts[0]\n const feeCostAmount = nonIncludedFeeCosts.reduce(\n (amount, feeCost) =>\n amount + BigInt(Number(feeCost.amount).toFixed(0)),\n 0n\n )\n if (feeCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + feeCostAmount\n : feeCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n return groupedGasCosts\n },\n {} as Record<string, GasSufficiency>\n )\n\n // Check whether we are sending a native token\n // For native tokens we want to check for the total amount, including the network fee\n if (\n route.fromToken.address === gasCosts[route.fromChainId]?.token.address\n ) {\n gasCosts[route.fromChainId].tokenAmount =\n gasCosts[route.fromChainId]?.gasAmount + BigInt(route.fromAmount)\n }\n\n const gasCostsValues = Object.values(gasCosts)\n\n const balanceChecks = await Promise.allSettled(\n relevantAccounts.map((account) => {\n const relevantTokens = gasCostsValues\n .filter((gasCost) => gasCost.chain?.chainType === account.chainType)\n .map((item) => item.token)\n\n return getTokenBalancesWithRetry(\n sdkClient,\n account.address!,\n relevantTokens\n )\n })\n )\n\n const tokenBalances = balanceChecks\n .filter(\n (result): result is PromiseFulfilledResult<TokenAmount[]> =>\n result.status === 'fulfilled' && Boolean(result.value)\n )\n .flatMap((result) => result.value)\n\n if (!tokenBalances?.length) {\n return []\n }\n\n Object.keys(gasCosts).forEach((chainId) => {\n if (gasCosts[chainId]) {\n const gasTokenBalance =\n tokenBalances?.find(\n (t) =>\n t.chainId === gasCosts[chainId].token.chainId &&\n t.address === gasCosts[chainId].token.address\n )?.amount ?? 0n\n const insufficient =\n gasTokenBalance <= 0n ||\n gasTokenBalance < gasCosts[chainId].gasAmount ||\n gasTokenBalance < (gasCosts[chainId].tokenAmount ?? 0n)\n\n const insufficientAmount = insufficient\n ? gasCosts[chainId].tokenAmount\n ? gasCosts[chainId].tokenAmount! - gasTokenBalance\n : gasCosts[chainId].gasAmount - gasTokenBalance\n : undefined\n\n gasCosts[chainId] = {\n ...gasCosts[chainId],\n insufficient,\n insufficientAmount,\n chain: insufficient ? getChainById(Number(chainId)) : undefined,\n }\n }\n })\n\n const gasCostResult = Object.values(gasCosts).filter(\n (gasCost) => gasCost.insufficient\n )\n\n return gasCostResult\n },\n\n enabled: Boolean(\n !isContractAddress &&\n !isContractAddressLoading &&\n relevantAccounts.length > 0 &&\n route &&\n !hiddenUI?.insufficientGasMessage\n ),\n refetchInterval,\n staleTime: refetchInterval,\n })\n\n return {\n insufficientGas,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;;;AAqBA,MAAM,kBAAkB;AAExB,MAAa,qBACX,UAIG;CACH,MAAM,EAAE,iBAAiB,mBAAmB;CAC5C,MAAM,EAAE,SAAS,YAAY,aAAa,WAAW,EACnD,WAAW,UAAU,IACvB,CAAC;CACD,MAAM,EAAE,WAAW,aAAa,gBAAgB;CAChD,MAAM,YAAY,aAAa;CAE/B,MAAM,EAAE,kBAAkB,6BAA6B,cAAc;EACnE,MAAM,aAAa,OAAO,MAAM,QAAQ,KAAK,SAAS;GACpD,MAAM,YAAY,aAAa,KAAK,OAAO,WAAW,GAAG;GACzD,IAAI,WACF,IAAI,IAAI,SAAS;GAEnB,OAAO;EACT,mBAAG,IAAI,IAAe,CAAC;EAEvB,MAAM,mBAAmB,SAAS,QAC/B,YACC,QAAQ,eACR,QAAQ,WACR,YAAY,IAAI,QAAQ,SAAS,CACrC;EACA,OAAO;GACL;GACA,0BAA0B,iBACvB,KAAK,YAAY,QAAQ,OAAO,EAChC,KAAK,GAAG;EACb;CACF,GAAG;EAAC;EAAU,OAAO;EAAO;CAAY,CAAC;CAEzC,MAAM,EAAE,mBAAmB,WAAW,6BACpC,qBACE,WAAW,SACX,OAAO,aACP,WAAW,SACb;CAEF,MAAM,EAAE,MAAM,iBAAiB,cAAc,SAA2B;EACtE,UAAU;GACR,YAAY,yBAAyB,SAAS;GAC9C;GACA,OAAO;GACP;EACF;EACA,SAAS,YAAY;GACnB,IAAI,CAAC,OACH,OAAO,CAAC;GAIV,MAAM,gBAAgB,MAAM,MAAM,QAC/B,SACC,CAAC,KAAK,WAAW,MACd,MAAM,EAAE,gBAAgB,YAAY,EAAE,gBAAgB,OACzD,CACJ;GAGA,IAAI,CAAC,cAAc,QACjB,OAAO,CAAC;GAIV,MAAM,gBAAgB,MAAM,MACzB,SAAS,SAAS,KAAK,aAAa,EACpC,MAAM,iBAAiB,aAAa,SAAS,QAAQ;GAExD,MAAM,WAAW,cACd,QAAQ,SAAS,KAAK,WAAW,WAAW,MAAM,EAClD,QACE,iBAAiB,SAAS;IAEzB,MAAM,kBACJ,KAAK,OAAO,gBAAgB,MAAM,aAAa;IACjD,IAAI,KAAK,SAAS,YAAY,CAAC,iBAAiB;KAC9C,MAAM,EAAE,UAAU,KAAK,SAAS,SAAS;KACzC,MAAM,gBAAgB,KAAK,SAAS,SAAS,QAC1C,QAAQ,YACP,SAAS,OAAO,OAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,GACnD,EACF;KACA,IAAI,gBAAgB,IAClB,gBAAgB,MAAM,WAAW;MAC/B,WAAW,gBAAgB,MAAM,WAC7B,gBAAgB,MAAM,SAAS,YAAY,gBAC3C;MACJ;MACA,OAAO,aAAa,MAAM,OAAO;KACnC;IAEJ;IAEA,MAAM,sBAAsB,KAAK,SAAS,UAAU,QACjD,YAAY,CAAC,QAAQ,QACxB;IACA,IAAI,qBAAqB,QAAQ;KAC/B,MAAM,EAAE,UAAU,oBAAoB;KACtC,MAAM,gBAAgB,oBAAoB,QACvC,QAAQ,YACP,SAAS,OAAO,OAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,GACnD,EACF;KACA,IAAI,gBAAgB,IAClB,gBAAgB,MAAM,WAAW;MAC/B,WAAW,gBAAgB,MAAM,WAC7B,gBAAgB,MAAM,SAAS,YAAY,gBAC3C;MACJ;MACA,OAAO,aAAa,MAAM,OAAO;KACnC;IAEJ;IACA,OAAO;GACT,GACA,CAAC,CACH;GAIF,IACE,MAAM,UAAU,YAAY,SAAS,MAAM,cAAc,MAAM,SAE/D,SAAS,MAAM,aAAa,cAC1B,SAAS,MAAM,cAAc,YAAY,OAAO,MAAM,UAAU;GAGpE,MAAM,iBAAiB,OAAO,OAAO,QAAQ;GAgB7C,MAAM,iBAAgB,MAdM,QAAQ,WAClC,iBAAiB,KAAK,YAAY;IAChC,MAAM,iBAAiB,eACpB,QAAQ,YAAY,QAAQ,OAAO,cAAc,QAAQ,SAAS,EAClE,KAAK,SAAS,KAAK,KAAK;IAE3B,OAAO,0BACL,WACA,QAAQ,SACR,cACF;GACF,CAAC,CACH,GAGG,QACE,WACC,OAAO,WAAW,eAAe,QAAQ,OAAO,KAAK,CACzD,EACC,SAAS,WAAW,OAAO,KAAK;GAEnC,IAAI,CAAC,eAAe,QAClB,OAAO,CAAC;GAGV,OAAO,KAAK,QAAQ,EAAE,SAAS,YAAY;IACzC,IAAI,SAAS,UAAU;KACrB,MAAM,kBACJ,eAAe,MACZ,MACC,EAAE,YAAY,SAAS,SAAS,MAAM,WACtC,EAAE,YAAY,SAAS,SAAS,MAAM,OAC1C,GAAG,UAAU;KACf,MAAM,eACJ,mBAAmB,MACnB,kBAAkB,SAAS,SAAS,aACpC,mBAAmB,SAAS,SAAS,eAAe;KAEtD,MAAM,qBAAqB,eACvB,SAAS,SAAS,cAChB,SAAS,SAAS,cAAe,kBACjC,SAAS,SAAS,YAAY,kBAChC,KAAA;KAEJ,SAAS,WAAW;MAClB,GAAG,SAAS;MACZ;MACA;MACA,OAAO,eAAe,aAAa,OAAO,OAAO,CAAC,IAAI,KAAA;KACxD;IACF;GACF,CAAC;GAMD,OAJsB,OAAO,OAAO,QAAQ,EAAE,QAC3C,YAAY,QAAQ,YAGJ;EACrB;EAEA,SAAS,QACP,CAAC,qBACC,CAAC,4BACD,iBAAiB,SAAS,KAC1B,SACA,CAAC,UAAU,sBACf;EACA;EACA,WAAW;CACb,CAAC;CAED,OAAO;EACL;EACA;CACF;AACF"}
1
+ {"version":3,"file":"useGasSufficiency.js","names":[],"sources":["../../../src/hooks/useGasSufficiency.ts"],"sourcesContent":["import type { EVMChain, RouteExtended, Token, TokenAmount } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nexport interface GasSufficiency {\n gasAmount: bigint\n tokenAmount?: bigint\n insufficientAmount?: bigint\n insufficient?: boolean\n token: Token\n chain?: EVMChain\n}\n\nconst refetchInterval = 30_000\n\nexport const useGasSufficiency = (\n route?: RouteExtended\n): {\n insufficientGas: GasSufficiency[] | undefined\n isLoading: boolean\n} => {\n const { getChainById } = useAvailableChains()\n const { account: EVMAccount, accounts } = useAccount({\n chainType: ChainType.EVM,\n })\n const { keyPrefix, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const { relevantAccounts, relevantAccountsQueryKey } = useMemo(() => {\n const chainTypes = route?.steps.reduce((acc, step) => {\n const chainType = getChainById(step.action.fromChainId)?.chainType\n if (chainType) {\n acc.add(chainType)\n }\n return acc\n }, new Set<ChainType>())\n\n const relevantAccounts = accounts.filter(\n (account) =>\n account.isConnected &&\n account.address &&\n chainTypes?.has(account.chainType)\n )\n return {\n relevantAccounts,\n relevantAccountsQueryKey: relevantAccounts\n .map((account) => account.address)\n .join(','),\n }\n }, [accounts, route?.steps, getChainById])\n\n const { isContractAddress, isLoading: isContractAddressLoading } =\n useIsContractAddress(\n EVMAccount.address,\n route?.fromChainId,\n EVMAccount.chainType\n )\n\n const { data: insufficientGas, isLoading } = useQuery<GasSufficiency[]>({\n queryKey: [\n getQueryKey('gas-sufficiency-check', keyPrefix),\n relevantAccountsQueryKey,\n route?.id,\n isContractAddress,\n ] as const,\n queryFn: async () => {\n if (!route) {\n return []\n }\n\n // Filter out steps that are relayer steps or have primaryType 'Permit' or 'Order'\n const filteredSteps = route.steps.filter(\n (step) =>\n !step.typedData?.some(\n (t) => t.primaryType === 'Permit' || t.primaryType === 'Order'\n )\n )\n\n // If all steps are filtered out, we don't need to check for gas sufficiency\n if (!filteredSteps.length) {\n return []\n }\n\n // We assume that LI.Fuel protocol always refuels the destination chain\n const hasRefuelStep = route.steps\n .flatMap((step) => step.includedSteps)\n .some((includedStep) => includedStep.tool === 'gasZip')\n\n const gasCosts = filteredSteps\n .filter((step) => step.execution?.status !== 'DONE')\n .reduce(\n (groupedGasCosts, step) => {\n // We need to avoid destination chain step sufficiency check if we have LI.Fuel protocol sub-step\n const skipDueToRefuel =\n step.action.fromChainId === route.toChainId && hasRefuelStep\n if (step.estimate.gasCosts && !skipDueToRefuel) {\n const { token } = step.estimate.gasCosts[0]\n const gasCostAmount = step.estimate.gasCosts.reduce(\n (amount, gasCost) =>\n amount + BigInt(Number(gasCost.amount).toFixed(0)),\n 0n\n )\n if (gasCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + gasCostAmount\n : gasCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n // Add fees paid in native tokens to gas sufficiency check (included: false)\n const nonIncludedFeeCosts = step.estimate.feeCosts?.filter(\n (feeCost) => !feeCost.included\n )\n if (nonIncludedFeeCosts?.length) {\n const { token } = nonIncludedFeeCosts[0]\n const feeCostAmount = nonIncludedFeeCosts.reduce(\n (amount, feeCost) =>\n amount + BigInt(Number(feeCost.amount).toFixed(0)),\n 0n\n )\n if (feeCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + feeCostAmount\n : feeCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n return groupedGasCosts\n },\n {} as Record<string, GasSufficiency>\n )\n\n // Check whether we are sending a native token\n // For native tokens we want to check for the total amount, including the network fee\n if (\n route.fromToken.address === gasCosts[route.fromChainId]?.token.address\n ) {\n gasCosts[route.fromChainId].tokenAmount =\n gasCosts[route.fromChainId]?.gasAmount + BigInt(route.fromAmount)\n }\n\n const gasCostsValues = Object.values(gasCosts)\n\n const balanceChecks = await Promise.allSettled(\n relevantAccounts.map((account) => {\n const relevantTokens = gasCostsValues\n .filter((gasCost) => gasCost.chain?.chainType === account.chainType)\n .map((item) => item.token)\n\n return getTokenBalancesWithRetry(\n sdkClient,\n account.address!,\n relevantTokens\n )\n })\n )\n\n const tokenBalances = balanceChecks\n .filter(\n (result): result is PromiseFulfilledResult<TokenAmount[]> =>\n result.status === 'fulfilled' && Boolean(result.value)\n )\n .flatMap((result) => result.value)\n\n if (!tokenBalances?.length) {\n return []\n }\n\n Object.keys(gasCosts).forEach((chainId) => {\n if (gasCosts[chainId]) {\n const gasTokenBalance =\n tokenBalances?.find(\n (t) =>\n t.chainId === gasCosts[chainId].token.chainId &&\n t.address === gasCosts[chainId].token.address\n )?.amount ?? 0n\n const insufficient =\n gasTokenBalance <= 0n ||\n gasTokenBalance < gasCosts[chainId].gasAmount ||\n gasTokenBalance < (gasCosts[chainId].tokenAmount ?? 0n)\n\n const insufficientAmount = insufficient\n ? gasCosts[chainId].tokenAmount\n ? gasCosts[chainId].tokenAmount! - gasTokenBalance\n : gasCosts[chainId].gasAmount - gasTokenBalance\n : undefined\n\n gasCosts[chainId] = {\n ...gasCosts[chainId],\n insufficient,\n insufficientAmount,\n chain: insufficient ? getChainById(Number(chainId)) : undefined,\n }\n }\n })\n\n const gasCostResult = Object.values(gasCosts).filter(\n (gasCost) => gasCost.insufficient\n )\n\n return gasCostResult\n },\n\n enabled: Boolean(\n !isContractAddress &&\n !isContractAddressLoading &&\n relevantAccounts.length > 0 &&\n route &&\n !hiddenUI?.insufficientGasMessage\n ),\n refetchInterval,\n staleTime: refetchInterval,\n })\n\n return {\n insufficientGas,\n isLoading,\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { allLanguages } from "../providers/I18nProvider/constants.js";
2
2
  import { loadLocale } from "../providers/I18nProvider/i18n.js";
3
+ import { getConfigItemSets, isItemAllowedForSets } from "../utils/item.js";
3
4
  import { useSettingsActions } from "../stores/settings/useSettingsActions.js";
4
5
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
5
- import { getConfigItemSets, isItemAllowedForSets } from "../utils/item.js";
6
6
  import { useSettings } from "../stores/settings/useSettings.js";
7
7
  import { useCallback, useMemo } from "react";
8
8
  import { useTranslation } from "react-i18next";
@@ -14,7 +14,7 @@ const useLanguages = () => {
14
14
  const { setValues } = useSettingsActions();
15
15
  const sortedLanguages = useMemo(() => {
16
16
  const loadedLanguageKeys = Object.keys(i18n.store.data);
17
- const allLanguagesWithCustom = [...new Set([...allLanguages, ...loadedLanguageKeys])];
17
+ const allLanguagesWithCustom = [.../* @__PURE__ */ new Set([...allLanguages, ...loadedLanguageKeys])];
18
18
  let supportedLanguages = [];
19
19
  if (!languagesConfig) supportedLanguages = allLanguagesWithCustom;
20
20
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"useLanguages.js","names":[],"sources":["../../../src/hooks/useLanguages.ts"],"sourcesContent":["import { useCallback, useMemo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { allLanguages } from '../providers/I18nProvider/constants.js'\nimport { loadLocale } from '../providers/I18nProvider/i18n.js'\nimport type {\n LanguageKey,\n LanguageResource,\n} from '../providers/I18nProvider/types.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useSettings } from '../stores/settings/useSettings.js'\nimport { useSettingsActions } from '../stores/settings/useSettingsActions.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../utils/item.js'\n\nexport const useLanguages = (): {\n availableLanguages: LanguageKey[]\n selectedLanguageCode: LanguageKey | string\n setLanguageWithCode: (languageCode: LanguageKey) => void\n} => {\n const { i18n } = useTranslation()\n const { languages: languagesConfig, languageResources } = useWidgetConfig()\n const { language } = useSettings(['language'])\n const { setValues } = useSettingsActions()\n\n const sortedLanguages = useMemo(() => {\n const loadedLanguageKeys = Object.keys(i18n.store.data)\n // NB: custom language resources added statically to i18n might not exist in allLanguages (language files)\n const allLanguagesWithCustom = [\n ...new Set([...allLanguages, ...loadedLanguageKeys]),\n ]\n let supportedLanguages: (LanguageKey | string)[] = []\n if (!languagesConfig) {\n supportedLanguages = allLanguagesWithCustom\n } else {\n const languagesConfigSets = getConfigItemSets(\n languagesConfig,\n (languages) => new Set(languages)\n )\n supportedLanguages = allLanguagesWithCustom.filter((language) =>\n isItemAllowedForSets(language, languagesConfigSets)\n )\n }\n return supportedLanguages.sort()\n }, [languagesConfig, i18n.store.data])\n\n const handleLanguageChange = useCallback(\n async (languageKey: string) => {\n // Cache the language resource to prevent blinking\n // after switching languages and reloading the page.\n let newLanguageCache: LanguageResource | undefined\n if (\n !i18n.hasResourceBundle(languageKey, 'translation') &&\n languageKey !== 'en'\n ) {\n await loadLocale(\n languageKey as LanguageKey,\n languageResources?.[languageKey as LanguageKey]\n ).then((languageResource) => {\n i18n.addResourceBundle(\n languageKey,\n 'translation',\n languageResource,\n true,\n true\n )\n newLanguageCache = languageResource\n })\n } else {\n // If the language is already loaded, just cache the existing resource\n newLanguageCache = i18n.getResourceBundle(languageKey, 'translation')\n }\n\n // Set the new language and language cache to the settings store.\n setValues({ language: languageKey, languageCache: newLanguageCache })\n\n // Update the i18n instance to the new language.\n if (languageKey !== i18n.language) {\n await i18n.changeLanguage(languageKey)\n }\n },\n [i18n, languageResources, setValues]\n )\n\n const selectedLanguage = language || i18n.resolvedLanguage || ''\n const selectedLanguageCode = sortedLanguages.includes(selectedLanguage)\n ? selectedLanguage\n : languagesConfig?.default || 'en'\n\n return {\n availableLanguages: sortedLanguages as LanguageKey[],\n selectedLanguageCode: selectedLanguageCode,\n setLanguageWithCode: handleLanguageChange,\n }\n}\n"],"mappings":";;;;;;;;;AAaA,MAAa,qBAIR;CACH,MAAM,EAAE,SAAS,eAAe;CAChC,MAAM,EAAE,WAAW,iBAAiB,sBAAsB,gBAAgB;CAC1E,MAAM,EAAE,aAAa,YAAY,CAAC,UAAU,CAAC;CAC7C,MAAM,EAAE,cAAc,mBAAmB;CAEzC,MAAM,kBAAkB,cAAc;EACpC,MAAM,qBAAqB,OAAO,KAAK,KAAK,MAAM,IAAI;EAEtD,MAAM,yBAAyB,CAC7B,GAAG,IAAI,IAAI,CAAC,GAAG,cAAc,GAAG,kBAAkB,CAAC,CACrD;EACA,IAAI,qBAA+C,CAAC;EACpD,IAAI,CAAC,iBACH,qBAAqB;OAChB;GACL,MAAM,sBAAsB,kBAC1B,kBACC,cAAc,IAAI,IAAI,SAAS,CAClC;GACA,qBAAqB,uBAAuB,QAAQ,aAClD,qBAAqB,UAAU,mBAAmB,CACpD;EACF;EACA,OAAO,mBAAmB,KAAK;CACjC,GAAG,CAAC,iBAAiB,KAAK,MAAM,IAAI,CAAC;CAErC,MAAM,uBAAuB,YAC3B,OAAO,gBAAwB;EAG7B,IAAI;EACJ,IACE,CAAC,KAAK,kBAAkB,aAAa,aAAa,KAClD,gBAAgB,MAEhB,MAAM,WACJ,aACA,oBAAoB,YACtB,EAAE,MAAM,qBAAqB;GAC3B,KAAK,kBACH,aACA,eACA,kBACA,MACA,IACF;GACA,mBAAmB;EACrB,CAAC;OAGD,mBAAmB,KAAK,kBAAkB,aAAa,aAAa;EAItE,UAAU;GAAE,UAAU;GAAa,eAAe;EAAiB,CAAC;EAGpE,IAAI,gBAAgB,KAAK,UACvB,MAAM,KAAK,eAAe,WAAW;CAEzC,GACA;EAAC;EAAM;EAAmB;CAAS,CACrC;CAEA,MAAM,mBAAmB,YAAY,KAAK,oBAAoB;CAK9D,OAAO;EACL,oBAAoB;EACpB,sBAN2B,gBAAgB,SAAS,gBAAgB,IAClE,mBACA,iBAAiB,WAAW;EAK9B,qBAAqB;CACvB;AACF"}
1
+ {"version":3,"file":"useLanguages.js","names":[],"sources":["../../../src/hooks/useLanguages.ts"],"sourcesContent":["import { useCallback, useMemo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { allLanguages } from '../providers/I18nProvider/constants.js'\nimport { loadLocale } from '../providers/I18nProvider/i18n.js'\nimport type {\n LanguageKey,\n LanguageResource,\n} from '../providers/I18nProvider/types.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useSettings } from '../stores/settings/useSettings.js'\nimport { useSettingsActions } from '../stores/settings/useSettingsActions.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../utils/item.js'\n\nexport const useLanguages = (): {\n availableLanguages: LanguageKey[]\n selectedLanguageCode: LanguageKey | string\n setLanguageWithCode: (languageCode: LanguageKey) => void\n} => {\n const { i18n } = useTranslation()\n const { languages: languagesConfig, languageResources } = useWidgetConfig()\n const { language } = useSettings(['language'])\n const { setValues } = useSettingsActions()\n\n const sortedLanguages = useMemo(() => {\n const loadedLanguageKeys = Object.keys(i18n.store.data)\n // NB: custom language resources added statically to i18n might not exist in allLanguages (language files)\n const allLanguagesWithCustom = [\n ...new Set([...allLanguages, ...loadedLanguageKeys]),\n ]\n let supportedLanguages: (LanguageKey | string)[] = []\n if (!languagesConfig) {\n supportedLanguages = allLanguagesWithCustom\n } else {\n const languagesConfigSets = getConfigItemSets(\n languagesConfig,\n (languages) => new Set(languages)\n )\n supportedLanguages = allLanguagesWithCustom.filter((language) =>\n isItemAllowedForSets(language, languagesConfigSets)\n )\n }\n return supportedLanguages.sort()\n }, [languagesConfig, i18n.store.data])\n\n const handleLanguageChange = useCallback(\n async (languageKey: string) => {\n // Cache the language resource to prevent blinking\n // after switching languages and reloading the page.\n let newLanguageCache: LanguageResource | undefined\n if (\n !i18n.hasResourceBundle(languageKey, 'translation') &&\n languageKey !== 'en'\n ) {\n await loadLocale(\n languageKey as LanguageKey,\n languageResources?.[languageKey as LanguageKey]\n ).then((languageResource) => {\n i18n.addResourceBundle(\n languageKey,\n 'translation',\n languageResource,\n true,\n true\n )\n newLanguageCache = languageResource\n })\n } else {\n // If the language is already loaded, just cache the existing resource\n newLanguageCache = i18n.getResourceBundle(languageKey, 'translation')\n }\n\n // Set the new language and language cache to the settings store.\n setValues({ language: languageKey, languageCache: newLanguageCache })\n\n // Update the i18n instance to the new language.\n if (languageKey !== i18n.language) {\n await i18n.changeLanguage(languageKey)\n }\n },\n [i18n, languageResources, setValues]\n )\n\n const selectedLanguage = language || i18n.resolvedLanguage || ''\n const selectedLanguageCode = sortedLanguages.includes(selectedLanguage)\n ? selectedLanguage\n : languagesConfig?.default || 'en'\n\n return {\n availableLanguages: sortedLanguages as LanguageKey[],\n selectedLanguageCode: selectedLanguageCode,\n setLanguageWithCode: handleLanguageChange,\n }\n}\n"],"mappings":";;;;;;;;;AAaA,MAAa,qBAIR;CACH,MAAM,EAAE,SAAS,eAAe;CAChC,MAAM,EAAE,WAAW,iBAAiB,sBAAsB,gBAAgB;CAC1E,MAAM,EAAE,aAAa,YAAY,CAAC,UAAU,CAAC;CAC7C,MAAM,EAAE,cAAc,mBAAmB;CAEzC,MAAM,kBAAkB,cAAc;EACpC,MAAM,qBAAqB,OAAO,KAAK,KAAK,MAAM,IAAI;EAEtD,MAAM,yBAAyB,CAC7B,mBAAG,IAAI,IAAI,CAAC,GAAG,cAAc,GAAG,kBAAkB,CAAC,CACrD;EACA,IAAI,qBAA+C,CAAC;EACpD,IAAI,CAAC,iBACH,qBAAqB;OAChB;GACL,MAAM,sBAAsB,kBAC1B,kBACC,cAAc,IAAI,IAAI,SAAS,CAClC;GACA,qBAAqB,uBAAuB,QAAQ,aAClD,qBAAqB,UAAU,mBAAmB,CACpD;EACF;EACA,OAAO,mBAAmB,KAAK;CACjC,GAAG,CAAC,iBAAiB,KAAK,MAAM,IAAI,CAAC;CAErC,MAAM,uBAAuB,YAC3B,OAAO,gBAAwB;EAG7B,IAAI;EACJ,IACE,CAAC,KAAK,kBAAkB,aAAa,aAAa,KAClD,gBAAgB,MAEhB,MAAM,WACJ,aACA,oBAAoB,YACtB,CAAC,CAAC,MAAM,qBAAqB;GAC3B,KAAK,kBACH,aACA,eACA,kBACA,MACA,IACF;GACA,mBAAmB;EACrB,CAAC;OAGD,mBAAmB,KAAK,kBAAkB,aAAa,aAAa;EAItE,UAAU;GAAE,UAAU;GAAa,eAAe;EAAiB,CAAC;EAGpE,IAAI,gBAAgB,KAAK,UACvB,MAAM,KAAK,eAAe,WAAW;CAEzC,GACA;EAAC;EAAM;EAAmB;CAAS,CACrC;CAEA,MAAM,mBAAmB,YAAY,KAAK,oBAAoB;CAK9D,OAAO;EACL,oBAAoB;EACpB,sBAN2B,gBAAgB,SAAS,gBAAgB,IAClE,mBACA,iBAAiB,WAAW;EAK9B,qBAAqB;CACvB;AACF"}
@@ -0,0 +1,24 @@
1
+ import { FormKeyHelper } from "../stores/form/types.js";
2
+ import { useFieldValues } from "../stores/form/useFieldValues.js";
3
+ import { useToken } from "./useToken.js";
4
+ //#region src/hooks/useLimitMarketRate.ts
5
+ /**
6
+ * Canonical limit-order market rate (receive token per send token), derived
7
+ * from the tokens' USD prices: 1 send token ≈ sendPrice / receivePrice receive
8
+ * tokens. This is the spot ratio — what the price card's "Market" reference and
9
+ * proximity indicator compare against. Returns `undefined` until both token
10
+ * prices are known.
11
+ */
12
+ const useLimitMarketRate = () => {
13
+ const [fromChainId, fromTokenAddress, toChainId, toTokenAddress] = useFieldValues(FormKeyHelper.getChainKey("from"), FormKeyHelper.getTokenKey("from"), FormKeyHelper.getChainKey("to"), FormKeyHelper.getTokenKey("to"));
14
+ const { token: fromToken } = useToken(fromChainId, fromTokenAddress);
15
+ const { token: toToken } = useToken(toChainId, toTokenAddress);
16
+ const fromPrice = Number(fromToken?.priceUSD);
17
+ const toPrice = Number(toToken?.priceUSD);
18
+ if (!fromPrice || !toPrice || Number.isNaN(fromPrice) || Number.isNaN(toPrice)) return;
19
+ return fromPrice / toPrice;
20
+ };
21
+ //#endregion
22
+ export { useLimitMarketRate };
23
+
24
+ //# sourceMappingURL=useLimitMarketRate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLimitMarketRate.js","names":[],"sources":["../../../src/hooks/useLimitMarketRate.ts"],"sourcesContent":["import { FormKeyHelper } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useToken } from './useToken.js'\n\n/**\n * Canonical limit-order market rate (receive token per send token), derived\n * from the tokens' USD prices: 1 send token ≈ sendPrice / receivePrice receive\n * tokens. This is the spot ratio — what the price card's \"Market\" reference and\n * proximity indicator compare against. Returns `undefined` until both token\n * prices are known.\n */\nexport const useLimitMarketRate = (): number | undefined => {\n const [fromChainId, fromTokenAddress, toChainId, toTokenAddress] =\n useFieldValues(\n FormKeyHelper.getChainKey('from'),\n FormKeyHelper.getTokenKey('from'),\n FormKeyHelper.getChainKey('to'),\n FormKeyHelper.getTokenKey('to')\n )\n const { token: fromToken } = useToken(fromChainId, fromTokenAddress)\n const { token: toToken } = useToken(toChainId, toTokenAddress)\n\n const fromPrice = Number(fromToken?.priceUSD)\n const toPrice = Number(toToken?.priceUSD)\n\n // A `priceUSD` of `\"0\"` (or missing) means the price is unknown — there's no\n // meaningful spot ratio to derive, and dividing by a zero `toPrice` would be\n // `Infinity`, so the falsy guard intentionally suppresses the rate here.\n if (\n !fromPrice ||\n !toPrice ||\n Number.isNaN(fromPrice) ||\n Number.isNaN(toPrice)\n ) {\n return undefined\n }\n\n return fromPrice / toPrice\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,2BAA+C;CAC1D,MAAM,CAAC,aAAa,kBAAkB,WAAW,kBAC/C,eACE,cAAc,YAAY,MAAM,GAChC,cAAc,YAAY,MAAM,GAChC,cAAc,YAAY,IAAI,GAC9B,cAAc,YAAY,IAAI,CAChC;CACF,MAAM,EAAE,OAAO,cAAc,SAAS,aAAa,gBAAgB;CACnE,MAAM,EAAE,OAAO,YAAY,SAAS,WAAW,cAAc;CAE7D,MAAM,YAAY,OAAO,WAAW,QAAQ;CAC5C,MAAM,UAAU,OAAO,SAAS,QAAQ;CAKxC,IACE,CAAC,aACD,CAAC,WACD,OAAO,MAAM,SAAS,KACtB,OAAO,MAAM,OAAO,GAEpB;CAGF,OAAO,YAAY;AACrB"}
@@ -0,0 +1,49 @@
1
+ import { useFieldActions } from "../stores/form/useFieldActions.js";
2
+ import { FormKeyHelper } from "../stores/form/types.js";
3
+ import { useFieldValues } from "../stores/form/useFieldValues.js";
4
+ import { useToken } from "./useToken.js";
5
+ import { deriveLimitPrice, deriveReceiveAmount } from "../utils/limitOrder.js";
6
+ //#region src/hooks/useLinkedLimitFields.ts
7
+ /**
8
+ * Implements the linked-field derivation for limit orders:
9
+ * - `limitPrice = receiveAmount / sendAmount`
10
+ * - editing sendAmount recomputes receiveAmount, holding the current price
11
+ * - editing limitPrice (with a send amount set) recomputes receiveAmount
12
+ * - sendAmount never changes without an explicit user edit
13
+ *
14
+ * The receive amount (`toAmount`) is read-only in the UI — it is derived here
15
+ * from the send amount and limit price, then sent to the routes request; the
16
+ * receive card only displays the resulting quote.
17
+ *
18
+ * The limit price is NOT stored: it is purely a function of the `fromAmount`
19
+ * and `toAmount` form fields (canonical receive-per-send). The UI layer handles
20
+ * base/quote display inversion. Because it's derived, editing the send amount
21
+ * only has to preserve the pre-edit price.
22
+ */
23
+ const useLinkedLimitFields = () => {
24
+ const { setFieldValue } = useFieldActions();
25
+ const [toChainId, toTokenAddress, sendAmount, receiveAmount] = useFieldValues(FormKeyHelper.getChainKey("to"), FormKeyHelper.getTokenKey("to"), FormKeyHelper.getAmountKey("from"), FormKeyHelper.getAmountKey("to"));
26
+ const { token: toToken } = useToken(toChainId, toTokenAddress);
27
+ const limitPrice = deriveLimitPrice(sendAmount, receiveAmount);
28
+ const setSendAmount = (value) => {
29
+ setFieldValue("fromAmount", value, {
30
+ isDirty: true,
31
+ isTouched: true
32
+ });
33
+ const nextReceive = deriveReceiveAmount(value, limitPrice, toToken?.decimals);
34
+ if (nextReceive) setFieldValue("toAmount", nextReceive, { isDirty: true });
35
+ };
36
+ const setLimitPrice = (value) => {
37
+ const nextReceive = deriveReceiveAmount(sendAmount, value, toToken?.decimals);
38
+ setFieldValue("toAmount", nextReceive, { isDirty: true });
39
+ };
40
+ return {
41
+ limitPrice,
42
+ setSendAmount,
43
+ setLimitPrice
44
+ };
45
+ };
46
+ //#endregion
47
+ export { useLinkedLimitFields };
48
+
49
+ //# sourceMappingURL=useLinkedLimitFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLinkedLimitFields.js","names":[],"sources":["../../../src/hooks/useLinkedLimitFields.ts"],"sourcesContent":["import { FormKeyHelper } from '../stores/form/types.js'\nimport { useFieldActions } from '../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { deriveLimitPrice, deriveReceiveAmount } from '../utils/limitOrder.js'\nimport { useToken } from './useToken.js'\n\nexport interface LinkedLimitFields {\n limitPrice: string\n /** Set the send amount (explicit user edit); derives receiveAmount when a price is set. */\n setSendAmount: (value: string) => void\n /** Set the limit price (canonical: receive per send); derives receiveAmount when a send amount is set. */\n setLimitPrice: (value: string) => void\n}\n\n/**\n * Implements the linked-field derivation for limit orders:\n * - `limitPrice = receiveAmount / sendAmount`\n * - editing sendAmount recomputes receiveAmount, holding the current price\n * - editing limitPrice (with a send amount set) recomputes receiveAmount\n * - sendAmount never changes without an explicit user edit\n *\n * The receive amount (`toAmount`) is read-only in the UI — it is derived here\n * from the send amount and limit price, then sent to the routes request; the\n * receive card only displays the resulting quote.\n *\n * The limit price is NOT stored: it is purely a function of the `fromAmount`\n * and `toAmount` form fields (canonical receive-per-send). The UI layer handles\n * base/quote display inversion. Because it's derived, editing the send amount\n * only has to preserve the pre-edit price.\n */\nexport const useLinkedLimitFields = (): LinkedLimitFields => {\n const { setFieldValue } = useFieldActions()\n const [toChainId, toTokenAddress, sendAmount, receiveAmount] = useFieldValues(\n FormKeyHelper.getChainKey('to'),\n FormKeyHelper.getTokenKey('to'),\n FormKeyHelper.getAmountKey('from'),\n FormKeyHelper.getAmountKey('to')\n )\n const { token: toToken } = useToken(toChainId, toTokenAddress)\n\n const limitPrice = deriveLimitPrice(sendAmount, receiveAmount)\n\n const setSendAmount = (value: string): void => {\n // Hold the pre-edit price (derived from the current fields) so changing the\n // send amount rescales the receive amount instead of moving the price.\n setFieldValue('fromAmount', value, { isDirty: true, isTouched: true })\n const nextReceive = deriveReceiveAmount(\n value,\n limitPrice,\n toToken?.decimals\n )\n if (nextReceive) {\n setFieldValue('toAmount', nextReceive, { isDirty: true })\n }\n }\n\n const setLimitPrice = (value: string): void => {\n // Write unconditionally (including '') so the receive amount tracks the\n // price both ways — clearing the price clears the derived receive amount\n // instead of leaving a stale value that re-derives the old price.\n const nextReceive = deriveReceiveAmount(\n sendAmount,\n value,\n toToken?.decimals\n )\n setFieldValue('toAmount', nextReceive, { isDirty: true })\n }\n\n return {\n limitPrice,\n setSendAmount,\n setLimitPrice,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,6BAAgD;CAC3D,MAAM,EAAE,kBAAkB,gBAAgB;CAC1C,MAAM,CAAC,WAAW,gBAAgB,YAAY,iBAAiB,eAC7D,cAAc,YAAY,IAAI,GAC9B,cAAc,YAAY,IAAI,GAC9B,cAAc,aAAa,MAAM,GACjC,cAAc,aAAa,IAAI,CACjC;CACA,MAAM,EAAE,OAAO,YAAY,SAAS,WAAW,cAAc;CAE7D,MAAM,aAAa,iBAAiB,YAAY,aAAa;CAE7D,MAAM,iBAAiB,UAAwB;EAG7C,cAAc,cAAc,OAAO;GAAE,SAAS;GAAM,WAAW;EAAK,CAAC;EACrE,MAAM,cAAc,oBAClB,OACA,YACA,SAAS,QACX;EACA,IAAI,aACF,cAAc,YAAY,aAAa,EAAE,SAAS,KAAK,CAAC;CAE5D;CAEA,MAAM,iBAAiB,UAAwB;EAI7C,MAAM,cAAc,oBAClB,YACA,OACA,SAAS,QACX;EACA,cAAc,YAAY,aAAa,EAAE,SAAS,KAAK,CAAC;CAC1D;CAEA,OAAO;EACL;EACA;EACA;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteExecution.js","names":[],"sources":["../../../src/hooks/useRouteExecution.ts"],"sourcesContent":["import type { ExchangeRateUpdateParams, Route, RouteExtended } from '@lifi/sdk'\nimport { executeRoute, resumeRoute, updateRouteExecution } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useEffect, useRef } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport {\n useRouteExecutionStore,\n useRouteExecutionStoreContext,\n} from '../stores/routes/RouteExecutionStore.js'\nimport type { RouteExecutionStatus } from '../stores/routes/types.js'\nimport {\n getUpdatedAction,\n isRouteActive,\n isRouteDone,\n isRouteFailed,\n} from '../stores/routes/utils.js'\nimport { WidgetEvent } from '../types/events.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useWidgetEvents } from './useWidgetEvents.js'\n\ninterface RouteExecutionProps {\n routeId: string\n executeInBackground?: boolean\n onAcceptExchangeRateUpdate?(\n resolver: (value: boolean) => void,\n data: ExchangeRateUpdateParams\n ): void\n}\n\nexport const useRouteExecution = ({\n routeId,\n executeInBackground,\n onAcceptExchangeRateUpdate,\n}: RouteExecutionProps): {\n executeRoute: () => void\n restartRoute: () => void\n deleteRoute: () => void\n route: RouteExtended | undefined\n status: RouteExecutionStatus | undefined\n} => {\n const queryClient = useQueryClient()\n const { account } = useAccount()\n const resumedAfterMount = useRef(false)\n const { keyPrefix } = useWidgetConfig()\n const sdkClient = useSDKClient()\n const emitter = useWidgetEvents()\n const routeExecutionStoreContext = useRouteExecutionStoreContext()\n const routeExecution = useRouteExecutionStore(\n (state) => state.routes[routeId]\n )\n const [updateRoute, deleteRoute] = useRouteExecutionStore((state) => [\n state.updateRoute,\n state.deleteRoute,\n ])\n\n const updateRouteHook = (updatedRoute: Route) => {\n const routeExecution =\n routeExecutionStoreContext.getState().routes[updatedRoute.id]\n if (!routeExecution) {\n return\n }\n const clonedUpdatedRoute = structuredClone(updatedRoute)\n updateRoute(clonedUpdatedRoute)\n const action = getUpdatedAction(routeExecution.route, clonedUpdatedRoute)\n if (action) {\n emitter.emit(WidgetEvent.RouteExecutionUpdated, {\n route: clonedUpdatedRoute,\n action,\n })\n }\n const executionCompleted = isRouteDone(clonedUpdatedRoute)\n const executionFailed = isRouteFailed(clonedUpdatedRoute)\n if (executionCompleted) {\n emitter.emit(WidgetEvent.RouteExecutionCompleted, clonedUpdatedRoute)\n }\n if (executionFailed && action) {\n emitter.emit(WidgetEvent.RouteExecutionFailed, {\n route: clonedUpdatedRoute,\n action,\n })\n }\n if (executionCompleted || executionFailed) {\n const invalidateKeys = [\n [\n getQueryKey('token-balances', keyPrefix),\n clonedUpdatedRoute.fromAddress,\n clonedUpdatedRoute.fromChainId,\n ],\n [\n getQueryKey('token-balances', keyPrefix),\n clonedUpdatedRoute.toAddress,\n clonedUpdatedRoute.toChainId,\n ],\n [getQueryKey('transaction-history', keyPrefix)],\n ]\n for (const key of invalidateKeys) {\n queryClient.invalidateQueries(\n {\n queryKey: key,\n exact: false,\n refetchType: 'all',\n },\n { cancelRefetch: false }\n )\n }\n }\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Route updated.', clonedUpdatedRoute)\n }\n\n const acceptExchangeRateUpdateHook = async (\n params: ExchangeRateUpdateParams\n ) => {\n if (!onAcceptExchangeRateUpdate) {\n return false\n }\n\n const accepted = await new Promise<boolean>((resolve) =>\n onAcceptExchangeRateUpdate(resolve, params)\n )\n\n return accepted\n }\n\n const executeRouteMutation = useMutation({\n mutationFn: () => {\n if (!account.isConnected) {\n throw new Error('Account is not connected.')\n }\n if (!routeExecution?.route) {\n throw new Error('Execution route not found.')\n }\n queryClient.removeQueries({\n queryKey: [getQueryKey('routes', keyPrefix)],\n exact: false,\n })\n return executeRoute(sdkClient, routeExecution.route, {\n updateRouteHook,\n acceptExchangeRateUpdateHook,\n executeInBackground,\n ...sdkClient.config?.executionOptions,\n })\n },\n onMutate: () => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Execution started.', routeId)\n if (routeExecution) {\n emitter.emit(WidgetEvent.RouteExecutionStarted, routeExecution.route)\n }\n },\n onError: (error) => {\n console.warn('Execution failed!', routeId, error)\n },\n onSuccess: (route: Route) => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Executed successfully!', route)\n },\n })\n\n const resumeRouteMutation = useMutation({\n mutationFn: (args?: { route?: Route; executeInBackground?: boolean }) => {\n if (!account.isConnected) {\n throw new Error('Account is not connected.')\n }\n if (!routeExecution?.route) {\n throw new Error('Execution route not found.')\n }\n return resumeRoute(sdkClient, args?.route ?? routeExecution.route, {\n updateRouteHook,\n acceptExchangeRateUpdateHook,\n executeInBackground: args?.executeInBackground ?? executeInBackground,\n })\n },\n onMutate: () => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Resumed to execution.', routeId)\n },\n onError: (error) => {\n console.warn('Resumed execution failed.', routeId, error)\n },\n onSuccess: (route) => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Resumed execution successful.', route)\n },\n })\n\n const _executeRoute = useCallback(() => {\n executeRouteMutation.mutateAsync(undefined)\n }, [executeRouteMutation])\n\n const _resumeRoute = useCallback(\n (route?: Route) => {\n resumeRouteMutation.mutateAsync({ route })\n },\n [resumeRouteMutation]\n )\n\n const restartRouteMutation = useCallback(() => {\n resumeRouteMutation.mutateAsync({\n route: routeExecution?.route,\n executeInBackground: false,\n })\n }, [resumeRouteMutation, routeExecution?.route])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when routeId changes\n const deleteRouteMutation = useCallback(() => {\n deleteRoute(routeId)\n }, [routeId])\n\n // Resume route execution after page reload\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when routeId changes\n useEffect(() => {\n // Check if route is eligible for automatic resuming\n const route = routeExecutionStoreContext.getState().routes[routeId]?.route\n if (\n isRouteActive(route) &&\n account.isConnected &&\n !resumedAfterMount.current\n ) {\n resumedAfterMount.current = true\n _resumeRoute()\n }\n\n // Move execution to background on unmount\n return () => {\n const route = routeExecutionStoreContext.getState().routes[routeId]?.route\n if (!route || !isRouteActive(route)) {\n return\n }\n updateRouteExecution(route, { executeInBackground: true })\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Move route execution to background.', routeId)\n resumedAfterMount.current = false\n }\n }, [account.isConnected, routeExecutionStoreContext, routeId])\n\n return {\n executeRoute: _executeRoute,\n restartRoute: restartRouteMutation,\n deleteRoute: deleteRouteMutation,\n route: routeExecution?.route,\n status: routeExecution?.status,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useRouteExecution.js","names":[],"sources":["../../../src/hooks/useRouteExecution.ts"],"sourcesContent":["import type { ExchangeRateUpdateParams, Route, RouteExtended } from '@lifi/sdk'\nimport { executeRoute, resumeRoute, updateRouteExecution } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useCallback, useEffect, useRef } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport {\n useRouteExecutionStore,\n useRouteExecutionStoreContext,\n} from '../stores/routes/RouteExecutionStore.js'\nimport type { RouteExecutionStatus } from '../stores/routes/types.js'\nimport {\n getUpdatedAction,\n isRouteActive,\n isRouteDone,\n isRouteFailed,\n} from '../stores/routes/utils.js'\nimport { WidgetEvent } from '../types/events.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useWidgetEvents } from './useWidgetEvents.js'\n\ninterface RouteExecutionProps {\n routeId: string\n executeInBackground?: boolean\n onAcceptExchangeRateUpdate?(\n resolver: (value: boolean) => void,\n data: ExchangeRateUpdateParams\n ): void\n}\n\nexport const useRouteExecution = ({\n routeId,\n executeInBackground,\n onAcceptExchangeRateUpdate,\n}: RouteExecutionProps): {\n executeRoute: () => void\n restartRoute: () => void\n deleteRoute: () => void\n route: RouteExtended | undefined\n status: RouteExecutionStatus | undefined\n} => {\n const queryClient = useQueryClient()\n const { account } = useAccount()\n const resumedAfterMount = useRef(false)\n const { keyPrefix } = useWidgetConfig()\n const sdkClient = useSDKClient()\n const emitter = useWidgetEvents()\n const routeExecutionStoreContext = useRouteExecutionStoreContext()\n const routeExecution = useRouteExecutionStore(\n (state) => state.routes[routeId]\n )\n const [updateRoute, deleteRoute] = useRouteExecutionStore((state) => [\n state.updateRoute,\n state.deleteRoute,\n ])\n\n const updateRouteHook = (updatedRoute: Route) => {\n const routeExecution =\n routeExecutionStoreContext.getState().routes[updatedRoute.id]\n if (!routeExecution) {\n return\n }\n const clonedUpdatedRoute = structuredClone(updatedRoute)\n updateRoute(clonedUpdatedRoute)\n const action = getUpdatedAction(routeExecution.route, clonedUpdatedRoute)\n if (action) {\n emitter.emit(WidgetEvent.RouteExecutionUpdated, {\n route: clonedUpdatedRoute,\n action,\n })\n }\n const executionCompleted = isRouteDone(clonedUpdatedRoute)\n const executionFailed = isRouteFailed(clonedUpdatedRoute)\n if (executionCompleted) {\n emitter.emit(WidgetEvent.RouteExecutionCompleted, clonedUpdatedRoute)\n }\n if (executionFailed && action) {\n emitter.emit(WidgetEvent.RouteExecutionFailed, {\n route: clonedUpdatedRoute,\n action,\n })\n }\n if (executionCompleted || executionFailed) {\n const invalidateKeys = [\n [\n getQueryKey('token-balances', keyPrefix),\n clonedUpdatedRoute.fromAddress,\n clonedUpdatedRoute.fromChainId,\n ],\n [\n getQueryKey('token-balances', keyPrefix),\n clonedUpdatedRoute.toAddress,\n clonedUpdatedRoute.toChainId,\n ],\n [getQueryKey('transaction-history', keyPrefix)],\n ]\n for (const key of invalidateKeys) {\n queryClient.invalidateQueries(\n {\n queryKey: key,\n exact: false,\n refetchType: 'all',\n },\n { cancelRefetch: false }\n )\n }\n }\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Route updated.', clonedUpdatedRoute)\n }\n\n const acceptExchangeRateUpdateHook = async (\n params: ExchangeRateUpdateParams\n ) => {\n if (!onAcceptExchangeRateUpdate) {\n return false\n }\n\n const accepted = await new Promise<boolean>((resolve) =>\n onAcceptExchangeRateUpdate(resolve, params)\n )\n\n return accepted\n }\n\n const executeRouteMutation = useMutation({\n mutationFn: () => {\n if (!account.isConnected) {\n throw new Error('Account is not connected.')\n }\n if (!routeExecution?.route) {\n throw new Error('Execution route not found.')\n }\n queryClient.removeQueries({\n queryKey: [getQueryKey('routes', keyPrefix)],\n exact: false,\n })\n return executeRoute(sdkClient, routeExecution.route, {\n updateRouteHook,\n acceptExchangeRateUpdateHook,\n executeInBackground,\n ...sdkClient.config?.executionOptions,\n })\n },\n onMutate: () => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Execution started.', routeId)\n if (routeExecution) {\n emitter.emit(WidgetEvent.RouteExecutionStarted, routeExecution.route)\n }\n },\n onError: (error) => {\n console.warn('Execution failed!', routeId, error)\n },\n onSuccess: (route: Route) => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Executed successfully!', route)\n },\n })\n\n const resumeRouteMutation = useMutation({\n mutationFn: (args?: { route?: Route; executeInBackground?: boolean }) => {\n if (!account.isConnected) {\n throw new Error('Account is not connected.')\n }\n if (!routeExecution?.route) {\n throw new Error('Execution route not found.')\n }\n return resumeRoute(sdkClient, args?.route ?? routeExecution.route, {\n updateRouteHook,\n acceptExchangeRateUpdateHook,\n executeInBackground: args?.executeInBackground ?? executeInBackground,\n })\n },\n onMutate: () => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Resumed to execution.', routeId)\n },\n onError: (error) => {\n console.warn('Resumed execution failed.', routeId, error)\n },\n onSuccess: (route) => {\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Resumed execution successful.', route)\n },\n })\n\n const _executeRoute = useCallback(() => {\n executeRouteMutation.mutateAsync(undefined)\n }, [executeRouteMutation])\n\n const _resumeRoute = useCallback(\n (route?: Route) => {\n resumeRouteMutation.mutateAsync({ route })\n },\n [resumeRouteMutation]\n )\n\n const restartRouteMutation = useCallback(() => {\n resumeRouteMutation.mutateAsync({\n route: routeExecution?.route,\n executeInBackground: false,\n })\n }, [resumeRouteMutation, routeExecution?.route])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when routeId changes\n const deleteRouteMutation = useCallback(() => {\n deleteRoute(routeId)\n }, [routeId])\n\n // Resume route execution after page reload\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when routeId changes\n useEffect(() => {\n // Check if route is eligible for automatic resuming\n const route = routeExecutionStoreContext.getState().routes[routeId]?.route\n if (\n isRouteActive(route) &&\n account.isConnected &&\n !resumedAfterMount.current\n ) {\n resumedAfterMount.current = true\n _resumeRoute()\n }\n\n // Move execution to background on unmount\n return () => {\n const route = routeExecutionStoreContext.getState().routes[routeId]?.route\n if (!route || !isRouteActive(route)) {\n return\n }\n updateRouteExecution(route, { executeInBackground: true })\n // biome-ignore lint/suspicious/noConsole: logs route information\n console.log('Move route execution to background.', routeId)\n resumedAfterMount.current = false\n }\n }, [account.isConnected, routeExecutionStoreContext, routeId])\n\n return {\n executeRoute: _executeRoute,\n restartRoute: restartRouteMutation,\n deleteRoute: deleteRouteMutation,\n route: routeExecution?.route,\n status: routeExecution?.status,\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteExecutionMessage.js","names":[],"sources":["../../../src/hooks/useRouteExecutionMessage.ts"],"sourcesContent":["import type { ExecutionActionType, RouteExtended } from '@lifi/sdk'\nimport { useTranslation } from 'react-i18next'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { RouteExecutionStatus } from '../stores/routes/types.js'\nimport { getActionMessage } from '../utils/getActionMessage.js'\nimport { getErrorMessage } from '../utils/getErrorMessage.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useRouteExecutionMessage = (\n route: RouteExtended,\n status: RouteExecutionStatus\n): { title: string | undefined; message: string | undefined } => {\n const { mode, modeOptions } = useWidgetConfig()\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n\n const transactionType =\n route.fromChainId === route.toChainId ? 'swap' : 'bridge'\n\n let title: string | undefined\n let message: string | undefined\n\n switch (status) {\n case RouteExecutionStatus.Pending: {\n // Use the first executing step, not the last one — in a multi-step route\n // the active step is often not the last.\n const activeStep =\n route.steps.find(\n (s) =>\n s.execution?.status === 'PENDING' ||\n s.execution?.status === 'ACTION_REQUIRED'\n ) ?? route.steps.at(-1)\n const lastAction = activeStep?.execution?.actions?.at(-1)\n const actionMessage =\n activeStep && lastAction\n ? getActionMessage(\n t,\n activeStep,\n lastAction.type,\n lastAction.status,\n lastAction.substatus,\n mode,\n modeOptions\n )\n : undefined\n // Fall back to a generic title when the step has no action to describe yet\n // (just after a restart, or before the first action exists).\n title =\n actionMessage?.title ?? t(`main.process.${transactionType}.pending`)\n message = actionMessage?.message\n break\n }\n case RouteExecutionStatus.Done: {\n title =\n mode === 'custom'\n ? t(\n `success.title.${modeOptions?.custom?.type ?? 'checkout'}Successful`\n )\n : t(`success.title.${transactionType}Successful`)\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Partial: {\n title = t(`success.title.${transactionType}PartiallySuccessful`)\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Refunded: {\n title = t('success.title.refundIssued')\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Failed: {\n const step = route.steps.find(\n (step) => step.execution?.status === 'FAILED'\n )\n if (!step) {\n break\n }\n const action = step.execution?.actions?.find(\n (action) => action.status === 'FAILED'\n ) || {\n status: 'FAILED',\n type: 'EXECUTION' as ExecutionActionType,\n error: step.execution?.error,\n } // synthetic action to represent a failed execution with no actions\n const actionMessage = getErrorMessage(t, getChainById, step, action)\n title = actionMessage.title\n message = actionMessage.message\n break\n }\n }\n\n return { title, message }\n}\n"],"mappings":";;;;;;AAQA,MAAa,4BACX,OACA,WAC+D;CAC/D,MAAM,EAAE,MAAM,gBAAgB,gBAAgB;CAC9C,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,iBAAiB,mBAAmB;CAE5C,MAAM,kBACJ,MAAM,gBAAgB,MAAM,YAAY,SAAS;CAEnD,IAAI;CACJ,IAAI;CAEJ,QAAQ,QAAR;EACE,KAAA,GAAmC;GAGjC,MAAM,aACJ,MAAM,MAAM,MACT,MACC,EAAE,WAAW,WAAW,aACxB,EAAE,WAAW,WAAW,iBAC5B,KAAK,MAAM,MAAM,GAAG,EAAE;GACxB,MAAM,aAAa,YAAY,WAAW,SAAS,GAAG,EAAE;GACxD,MAAM,gBACJ,cAAc,aACV,iBACE,GACA,YACA,WAAW,MACX,WAAW,QACX,WAAW,WACX,MACA,WACF,IACA,KAAA;GAGN,QACE,eAAe,SAAS,EAAE,gBAAgB,gBAAgB,SAAS;GACrE,UAAU,eAAe;GACzB;EACF;EACA,KAAA;GACE,QACE,SAAS,WACL,EACE,iBAAiB,aAAa,QAAQ,QAAQ,WAAW,WAC3D,IACA,EAAE,iBAAiB,gBAAgB,WAAW;GACpD;EAEF,KAAA;GACE,QAAQ,EAAE,iBAAiB,gBAAgB,oBAAoB;GAC/D,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,GAAG,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA;GACE,QAAQ,EAAE,4BAA4B;GACtC,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,GAAG,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA,GAAkC;GAChC,MAAM,OAAO,MAAM,MAAM,MACtB,SAAS,KAAK,WAAW,WAAW,QACvC;GACA,IAAI,CAAC,MACH;GASF,MAAM,gBAAgB,gBAAgB,GAAG,cAAc,MAPxC,KAAK,WAAW,SAAS,MACrC,WAAW,OAAO,WAAW,QAChC,KAAK;IACH,QAAQ;IACR,MAAM;IACN,OAAO,KAAK,WAAW;GACzB,CACmE;GACnE,QAAQ,cAAc;GACtB,UAAU,cAAc;GACxB;EACF;CACF;CAEA,OAAO;EAAE;EAAO;CAAQ;AAC1B"}
1
+ {"version":3,"file":"useRouteExecutionMessage.js","names":[],"sources":["../../../src/hooks/useRouteExecutionMessage.ts"],"sourcesContent":["import type { ExecutionActionType, RouteExtended } from '@lifi/sdk'\nimport { useTranslation } from 'react-i18next'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { RouteExecutionStatus } from '../stores/routes/types.js'\nimport { getActionMessage } from '../utils/getActionMessage.js'\nimport { getErrorMessage } from '../utils/getErrorMessage.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useRouteExecutionMessage = (\n route: RouteExtended,\n status: RouteExecutionStatus\n): { title: string | undefined; message: string | undefined } => {\n const { mode, modeOptions } = useWidgetConfig()\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n\n const transactionType =\n route.fromChainId === route.toChainId ? 'swap' : 'bridge'\n\n let title: string | undefined\n let message: string | undefined\n\n switch (status) {\n case RouteExecutionStatus.Pending: {\n // Use the first executing step, not the last one — in a multi-step route\n // the active step is often not the last.\n const activeStep =\n route.steps.find(\n (s) =>\n s.execution?.status === 'PENDING' ||\n s.execution?.status === 'ACTION_REQUIRED'\n ) ?? route.steps.at(-1)\n const lastAction = activeStep?.execution?.actions?.at(-1)\n const actionMessage =\n activeStep && lastAction\n ? getActionMessage(\n t,\n activeStep,\n lastAction.type,\n lastAction.status,\n lastAction.substatus,\n mode,\n modeOptions\n )\n : undefined\n // Fall back to a generic title when the step has no action to describe yet\n // (just after a restart, or before the first action exists).\n title =\n actionMessage?.title ?? t(`main.process.${transactionType}.pending`)\n message = actionMessage?.message\n break\n }\n case RouteExecutionStatus.Done: {\n title =\n mode === 'custom'\n ? t(\n `success.title.${modeOptions?.custom?.type ?? 'checkout'}Successful`\n )\n : t(`success.title.${transactionType}Successful`)\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Partial: {\n title = t(`success.title.${transactionType}PartiallySuccessful`)\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Done | RouteExecutionStatus.Refunded: {\n title = t('success.title.refundIssued')\n message = t('success.message.exchangePartiallySuccessful', {\n tool: route.steps.at(-1)?.toolDetails.name,\n tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,\n })\n break\n }\n case RouteExecutionStatus.Failed: {\n const step = route.steps.find(\n (step) => step.execution?.status === 'FAILED'\n )\n if (!step) {\n break\n }\n const action = step.execution?.actions?.find(\n (action) => action.status === 'FAILED'\n ) || {\n status: 'FAILED',\n type: 'EXECUTION' as ExecutionActionType,\n error: step.execution?.error,\n } // synthetic action to represent a failed execution with no actions\n const actionMessage = getErrorMessage(t, getChainById, step, action)\n title = actionMessage.title\n message = actionMessage.message\n break\n }\n }\n\n return { title, message }\n}\n"],"mappings":";;;;;;AAQA,MAAa,4BACX,OACA,WAC+D;CAC/D,MAAM,EAAE,MAAM,gBAAgB,gBAAgB;CAC9C,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,iBAAiB,mBAAmB;CAE5C,MAAM,kBACJ,MAAM,gBAAgB,MAAM,YAAY,SAAS;CAEnD,IAAI;CACJ,IAAI;CAEJ,QAAQ,QAAR;EACE,KAAA,GAAmC;GAGjC,MAAM,aACJ,MAAM,MAAM,MACT,MACC,EAAE,WAAW,WAAW,aACxB,EAAE,WAAW,WAAW,iBAC5B,KAAK,MAAM,MAAM,GAAG,EAAE;GACxB,MAAM,aAAa,YAAY,WAAW,SAAS,GAAG,EAAE;GACxD,MAAM,gBACJ,cAAc,aACV,iBACE,GACA,YACA,WAAW,MACX,WAAW,QACX,WAAW,WACX,MACA,WACF,IACA,KAAA;GAGN,QACE,eAAe,SAAS,EAAE,gBAAgB,gBAAgB,SAAS;GACrE,UAAU,eAAe;GACzB;EACF;EACA,KAAA;GACE,QACE,SAAS,WACL,EACE,iBAAiB,aAAa,QAAQ,QAAQ,WAAW,WAC3D,IACA,EAAE,iBAAiB,gBAAgB,WAAW;GACpD;EAEF,KAAA;GACE,QAAQ,EAAE,iBAAiB,gBAAgB,oBAAoB;GAC/D,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA;GACE,QAAQ,EAAE,4BAA4B;GACtC,UAAU,EAAE,+CAA+C;IACzD,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;IACtC,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,OAAO,QAAQ;GAClD,CAAC;GACD;EAEF,KAAA,GAAkC;GAChC,MAAM,OAAO,MAAM,MAAM,MACtB,SAAS,KAAK,WAAW,WAAW,QACvC;GACA,IAAI,CAAC,MACH;GASF,MAAM,gBAAgB,gBAAgB,GAAG,cAAc,MAPxC,KAAK,WAAW,SAAS,MACrC,WAAW,OAAO,WAAW,QAChC,KAAK;IACH,QAAQ;IACR,MAAM;IACN,OAAO,KAAK,WAAW;GACzB,CACmE;GACnE,QAAQ,cAAc;GACtB,UAAU,cAAc;GACxB;EACF;CACF;CAEA,OAAO;EAAE;EAAO;CAAQ;AAC1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteRequiredAccountConnection.js","names":[],"sources":["../../../src/hooks/useRouteRequiredAccountConnection.ts"],"sourcesContent":["import type { ExtendedChain, Route } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useChain } from './useChain.js'\n\nexport const useRouteRequiredAccountConnection = (\n route?: Route,\n chain?: ExtendedChain\n): {\n connected: boolean\n missingChain?: ExtendedChain\n missingAccountAddress?: string\n} => {\n const { account, accounts } = useAccount({ chainType: chain?.chainType })\n const [toAddress] = useFieldValues('toAddress')\n const { getChainById } = useChain()\n\n return useMemo(() => {\n if (!route?.steps.length) {\n return {\n connected: account.isConnected,\n }\n }\n\n const connectedChainTypes = new Map(\n accounts\n .filter((account) => account.isConnected && account.address)\n .map((account) => [account.chainType, account])\n )\n\n if (!connectedChainTypes.size) {\n return {\n connected: false,\n }\n }\n\n for (const step of route.steps) {\n const chain = getChainById(step.action.fromChainId)\n if (!chain) {\n continue\n }\n\n const connectedAccount = connectedChainTypes.get(chain.chainType)\n const isToAddressSatisfied = toAddress\n ? connectedAccount?.address === step.action.fromAddress\n : true\n\n if (!connectedAccount || !isToAddressSatisfied) {\n return {\n connected: false,\n missingChain: chain,\n missingAccountAddress: !isToAddressSatisfied\n ? step.action.fromAddress\n : undefined,\n }\n }\n }\n\n return { connected: true }\n }, [account.isConnected, route, accounts, getChainById, toAddress])\n}\n"],"mappings":";;;;;AAMA,MAAa,qCACX,OACA,UAKG;CACH,MAAM,EAAE,SAAS,aAAa,WAAW,EAAE,WAAW,OAAO,UAAU,CAAC;CACxE,MAAM,CAAC,aAAa,eAAe,WAAW;CAC9C,MAAM,EAAE,iBAAiB,SAAS;CAElC,OAAO,cAAc;EACnB,IAAI,CAAC,OAAO,MAAM,QAChB,OAAO,EACL,WAAW,QAAQ,YACrB;EAGF,MAAM,sBAAsB,IAAI,IAC9B,SACG,QAAQ,YAAY,QAAQ,eAAe,QAAQ,OAAO,EAC1D,KAAK,YAAY,CAAC,QAAQ,WAAW,OAAO,CAAC,CAClD;EAEA,IAAI,CAAC,oBAAoB,MACvB,OAAO,EACL,WAAW,MACb;EAGF,KAAK,MAAM,QAAQ,MAAM,OAAO;GAC9B,MAAM,QAAQ,aAAa,KAAK,OAAO,WAAW;GAClD,IAAI,CAAC,OACH;GAGF,MAAM,mBAAmB,oBAAoB,IAAI,MAAM,SAAS;GAChE,MAAM,uBAAuB,YACzB,kBAAkB,YAAY,KAAK,OAAO,cAC1C;GAEJ,IAAI,CAAC,oBAAoB,CAAC,sBACxB,OAAO;IACL,WAAW;IACX,cAAc;IACd,uBAAuB,CAAC,uBACpB,KAAK,OAAO,cACZ,KAAA;GACN;EAEJ;EAEA,OAAO,EAAE,WAAW,KAAK;CAC3B,GAAG;EAAC,QAAQ;EAAa;EAAO;EAAU;EAAc;CAAS,CAAC;AACpE"}
1
+ {"version":3,"file":"useRouteRequiredAccountConnection.js","names":[],"sources":["../../../src/hooks/useRouteRequiredAccountConnection.ts"],"sourcesContent":["import type { ExtendedChain, Route } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useChain } from './useChain.js'\n\nexport const useRouteRequiredAccountConnection = (\n route?: Route,\n chain?: ExtendedChain\n): {\n connected: boolean\n missingChain?: ExtendedChain\n missingAccountAddress?: string\n} => {\n const { account, accounts } = useAccount({ chainType: chain?.chainType })\n const [toAddress] = useFieldValues('toAddress')\n const { getChainById } = useChain()\n\n return useMemo(() => {\n if (!route?.steps.length) {\n return {\n connected: account.isConnected,\n }\n }\n\n const connectedChainTypes = new Map(\n accounts\n .filter((account) => account.isConnected && account.address)\n .map((account) => [account.chainType, account])\n )\n\n if (!connectedChainTypes.size) {\n return {\n connected: false,\n }\n }\n\n for (const step of route.steps) {\n const chain = getChainById(step.action.fromChainId)\n if (!chain) {\n continue\n }\n\n const connectedAccount = connectedChainTypes.get(chain.chainType)\n const isToAddressSatisfied = toAddress\n ? connectedAccount?.address === step.action.fromAddress\n : true\n\n if (!connectedAccount || !isToAddressSatisfied) {\n return {\n connected: false,\n missingChain: chain,\n missingAccountAddress: !isToAddressSatisfied\n ? step.action.fromAddress\n : undefined,\n }\n }\n }\n\n return { connected: true }\n }, [account.isConnected, route, accounts, getChainById, toAddress])\n}\n"],"mappings":";;;;;AAMA,MAAa,qCACX,OACA,UAKG;CACH,MAAM,EAAE,SAAS,aAAa,WAAW,EAAE,WAAW,OAAO,UAAU,CAAC;CACxE,MAAM,CAAC,aAAa,eAAe,WAAW;CAC9C,MAAM,EAAE,iBAAiB,SAAS;CAElC,OAAO,cAAc;EACnB,IAAI,CAAC,OAAO,MAAM,QAChB,OAAO,EACL,WAAW,QAAQ,YACrB;EAGF,MAAM,sBAAsB,IAAI,IAC9B,SACG,QAAQ,YAAY,QAAQ,eAAe,QAAQ,OAAO,CAAC,CAC3D,KAAK,YAAY,CAAC,QAAQ,WAAW,OAAO,CAAC,CAClD;EAEA,IAAI,CAAC,oBAAoB,MACvB,OAAO,EACL,WAAW,MACb;EAGF,KAAK,MAAM,QAAQ,MAAM,OAAO;GAC9B,MAAM,QAAQ,aAAa,KAAK,OAAO,WAAW;GAClD,IAAI,CAAC,OACH;GAGF,MAAM,mBAAmB,oBAAoB,IAAI,MAAM,SAAS;GAChE,MAAM,uBAAuB,YACzB,kBAAkB,YAAY,KAAK,OAAO,cAC1C;GAEJ,IAAI,CAAC,oBAAoB,CAAC,sBACxB,OAAO;IACL,WAAW;IACX,cAAc;IACd,uBAAuB,CAAC,uBACpB,KAAK,OAAO,cACZ,KAAA;GACN;EAEJ;EAEA,OAAO,EAAE,WAAW,KAAK;CAC3B,GAAG;EAAC,QAAQ;EAAa;EAAO;EAAU;EAAc;CAAS,CAAC;AACpE"}
@@ -1,6 +1,7 @@
1
1
  import { useWidgetEvents } from "./useWidgetEvents.js";
2
2
  import "../types/events.js";
3
3
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
4
+ import { useNavigationTabsStore } from "../stores/navigationTabs/useNavigationTabsStore.js";
4
5
  import { useSwapOnly } from "./useSwapOnly.js";
5
6
  import { useSDKClient } from "../providers/SDKClientProvider.js";
6
7
  import { getQueryKey } from "../utils/queries.js";
@@ -28,6 +29,7 @@ const useRoutes = ({ observableRoute } = {}) => {
28
29
  const queryClient = useQueryClient();
29
30
  const emitter = useWidgetEvents();
30
31
  const swapOnly = useSwapOnly();
32
+ const isPrivate = useNavigationTabsStore((state) => state.activeTab === "private");
31
33
  const { disabledBridges, disabledExchanges, enabledBridges, enabledExchanges, enabledAutoRefuel, routePriority, slippage } = useSettings([
32
34
  "disabledBridges",
33
35
  "disabledExchanges",
@@ -38,7 +40,9 @@ const useRoutes = ({ observableRoute } = {}) => {
38
40
  "slippage"
39
41
  ]);
40
42
  const [fromTokenAmount] = useDebouncedWatch(500, "fromAmount");
41
- const [fromChainId, fromTokenAddress, toAddress, toTokenAmount, toChainId, toTokenAddress, contractCalls] = useFieldValues("fromChain", "fromToken", "toAddress", "toAmount", "toChain", "toToken", "contractCalls");
43
+ const [toTokenAmount] = useDebouncedWatch(500, "toAmount");
44
+ const [fromChainId, fromTokenAddress, toAddress, toChainId, toTokenAddress, contractCalls] = useFieldValues("fromChain", "fromToken", "toAddress", "toChain", "toToken", "contractCalls");
45
+ const [validUntilDuration, partiallyFillable] = useFieldValues("validUntil", "partiallyFillable");
42
46
  const { token: fromToken } = useToken(fromChainId, fromTokenAddress);
43
47
  const { token: toToken } = useToken(toChainId, toTokenAddress);
44
48
  const { chain: fromChain } = useChain(fromChainId);
@@ -48,7 +52,7 @@ const useRoutes = ({ observableRoute } = {}) => {
48
52
  const { isGaslessStep, disableMessageSigning } = useEthereumContext();
49
53
  const { account } = useAccount({ chainType: fromChain?.chainType });
50
54
  const { isBatchingSupported, isBatchingSupportedLoading } = useIsBatchingSupported(fromChain, account.address);
51
- const hasAmount = Number(fromTokenAmount) > 0 || Number(toTokenAmount) > 0;
55
+ const hasAmount = mode === "limit" ? Number(fromTokenAmount) > 0 && Number(toTokenAmount) > 0 : Number(fromTokenAmount) > 0 || Number(toTokenAmount) > 0;
52
56
  const contractCallQuoteEnabled = mode === "custom" ? Boolean(contractCalls && account.address) : true;
53
57
  const hasToAddressAndChainTypeSatisfied = !!toChain && !!toAddress && getChainTypeFromAddress(toAddress) === toChain.chainType;
54
58
  const isToAddressSatisfied = toAddress ? hasToAddressAndChainTypeSatisfied : true;
@@ -67,6 +71,8 @@ const useRoutes = ({ observableRoute } = {}) => {
67
71
  toChain?.id,
68
72
  toToken?.address,
69
73
  toTokenAmount,
74
+ validUntilDuration,
75
+ partiallyFillable,
70
76
  contractCalls,
71
77
  slippage,
72
78
  swapOnly,
@@ -82,6 +88,7 @@ const useRoutes = ({ observableRoute } = {}) => {
82
88
  feeConfig?.fee,
83
89
  disableMessageSigning,
84
90
  !!isBatchingSupported,
91
+ isPrivate,
85
92
  observableRoute?.id
86
93
  ], [
87
94
  keyPrefix,
@@ -93,6 +100,8 @@ const useRoutes = ({ observableRoute } = {}) => {
93
100
  toChain?.id,
94
101
  toToken?.address,
95
102
  toTokenAmount,
103
+ validUntilDuration,
104
+ partiallyFillable,
96
105
  contractCalls,
97
106
  slippage,
98
107
  swapOnly,
@@ -109,14 +118,15 @@ const useRoutes = ({ observableRoute } = {}) => {
109
118
  feeConfig?.fee,
110
119
  disableMessageSigning,
111
120
  isBatchingSupported,
121
+ isPrivate,
112
122
  observableRoute?.id
113
123
  ]);
114
124
  const { getIntermediateRoutes, setIntermediateRoutes } = useIntermediateRoutesStore();
115
125
  const { data, isLoading, isFetching, isFetched, dataUpdatedAt, refetch } = useQuery({
116
126
  queryKey,
117
- queryFn: async ({ queryKey: [_, fromAddress, fromChainId, fromTokenAddress, fromTokenAmount, toAddress, toChainId, toTokenAddress, toTokenAmount, contractCalls, slippage = void 0, swapOnly, disabledBridges, disabledExchanges, allowedBridges, allowedExchanges, routePriority, mode, allowSwitchChain, enabledRefuel, gasRecommendationFromAmount, configuredFee, disableMessageSigning, isBatchingSupported, _observableRouteId], signal }) => {
127
+ queryFn: async ({ queryKey: [_, fromAddress, fromChainId, fromTokenAddress, fromTokenAmount, toAddress, toChainId, toTokenAddress, toTokenAmount, validUntilDuration, partiallyFillable, contractCalls, slippage = void 0, swapOnly, disabledBridges, disabledExchanges, allowedBridges, allowedExchanges, routePriority, mode, allowSwitchChain, enabledRefuel, gasRecommendationFromAmount, configuredFee, disableMessageSigning, isBatchingSupported, isPrivate, _observableRouteId], signal }) => {
118
128
  const fromAmount = parseUnits(fromTokenAmount, fromToken.decimals);
119
- const toAmount = parseUnits(toTokenAmount, toToken.decimals);
129
+ const toAmount = toTokenAmount ? parseUnits(toTokenAmount, toToken.decimals) : void 0;
120
130
  const formattedSlippage = slippage ? Number.parseFloat(slippage) / 100 : void 0;
121
131
  const allowBridges = swapOnly ? [] : observableRoute ? observableRoute.steps.flatMap((step) => step.includedSteps.reduce((toolKeys, includedStep) => {
122
132
  if (includedStep.type === "cross") toolKeys.push(includedStep.toolDetails.key);
@@ -170,7 +180,12 @@ const useRoutes = ({ observableRoute } = {}) => {
170
180
  if (fromChainId === toChainId && fromTokenAddress === toTokenAddress && !(mode === "custom" && modeOptions?.custom?.type === "deposit")) return;
171
181
  const isObservableRelayerRoute = observableRoute?.steps?.some((step) => !!isGaslessStep?.(step, fromChain));
172
182
  const shouldUseMainRoutes = !observableRoute || !isObservableRelayerRoute;
173
- const shouldUseRelayerQuote = fromAddress && fromChain?.chainType === ChainType.EVM && fromChain.permit2 && fromChain.permit2Proxy && fromChain.relayerSupported && fromChain.nativeToken.address !== fromTokenAddress && useRelayerRoutes && !isBatchingSupported && (!observableRoute || isObservableRelayerRoute);
183
+ const shouldUseRelayerQuote = mode !== "limit" && fromAddress && fromChain?.chainType === ChainType.EVM && fromChain.permit2 && fromChain.permit2Proxy && fromChain.relayerSupported && fromChain.nativeToken.address !== fromTokenAddress && useRelayerRoutes && !isBatchingSupported && (!observableRoute || isObservableRelayerRoute);
184
+ const limitOrderRouteParams = mode === "limit" ? {
185
+ toAmount: toAmount?.toString(),
186
+ validUntil: Math.floor(Date.now() / 1e3) + validUntilDuration,
187
+ partiallyFillable
188
+ } : void 0;
174
189
  const mainRoutesPromise = shouldUseMainRoutes ? getRoutes(sdkClient, {
175
190
  fromAddress,
176
191
  fromAmount: fromAmount.toString(),
@@ -180,6 +195,7 @@ const useRoutes = ({ observableRoute } = {}) => {
180
195
  toChainId,
181
196
  toTokenAddress,
182
197
  fromAmountForGas: enabledRefuel && gasRecommendationFromAmount ? gasRecommendationFromAmount : void 0,
198
+ ...limitOrderRouteParams,
183
199
  options: {
184
200
  allowSwitchChain: mode === "refuel" ? false : allowSwitchChain,
185
201
  bridges: allowBridges?.length || disabledBridges.length ? {
@@ -193,7 +209,8 @@ const useRoutes = ({ observableRoute } = {}) => {
193
209
  order: routePriority,
194
210
  slippage: formattedSlippage,
195
211
  fee: calculatedFee || configuredFee,
196
- executionType: disableMessageSigning ? "transaction" : "all"
212
+ executionType: disableMessageSigning ? "transaction" : "all",
213
+ ...isPrivate && { private: true }
197
214
  }
198
215
  }, { signal }) : Promise.resolve(null);
199
216
  const relayerQuotePromise = shouldUseRelayerQuote ? getRelayerQuote(sdkClient, {