@lifi/widget 4.7.1 → 4.9.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 (214) hide show
  1. package/dist/esm/components/AmountInput/AmountInput.style.d.ts.map +1 -1
  2. package/dist/esm/components/AmountInputCard/AmountInputCardPair.js +5 -2
  3. package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -1
  4. package/dist/esm/components/Card/Card.d.ts.map +1 -1
  5. package/dist/esm/components/Card/CardIconButton.d.ts.map +1 -1
  6. package/dist/esm/components/ContractComponent/ItemPrice.d.ts.map +1 -1
  7. package/dist/esm/components/ListItem/ListItemButton.d.ts.map +1 -1
  8. package/dist/esm/components/ListItemButton.d.ts.map +1 -1
  9. package/dist/esm/components/SelectChainAndToken.js +5 -2
  10. package/dist/esm/components/SelectChainAndToken.js.map +1 -1
  11. package/dist/esm/components/SendToWallet/SendToWalletButton.js +5 -4
  12. package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
  13. package/dist/esm/components/Token/Token.d.ts.map +1 -1
  14. package/dist/esm/components/TokenList/types.d.ts.map +1 -1
  15. package/dist/esm/components/TokenList/useTokenSelect.d.ts.map +1 -1
  16. package/dist/esm/components/TokenList/useTokenSelect.js +10 -0
  17. package/dist/esm/components/TokenList/useTokenSelect.js.map +1 -1
  18. package/dist/esm/config/constants.js.map +1 -1
  19. package/dist/esm/config/version.d.ts +1 -1
  20. package/dist/esm/config/version.js +1 -1
  21. package/dist/esm/config/version.js.map +1 -1
  22. package/dist/esm/hooks/useAccountsBalancesData.js +5 -2
  23. package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
  24. package/dist/esm/hooks/useAddressValidation.d.ts +3 -2
  25. package/dist/esm/hooks/useAddressValidation.d.ts.map +1 -1
  26. package/dist/esm/hooks/useAddressValidation.js +48 -21
  27. package/dist/esm/hooks/useAddressValidation.js.map +1 -1
  28. package/dist/esm/hooks/useAvailableChains.d.ts.map +1 -1
  29. package/dist/esm/hooks/useAvailableChains.js +21 -38
  30. package/dist/esm/hooks/useAvailableChains.js.map +1 -1
  31. package/dist/esm/hooks/useFromTokenSufficiency.js +3 -3
  32. package/dist/esm/hooks/useFromTokenSufficiency.js.map +1 -1
  33. package/dist/esm/hooks/useGasRecommendation.js +3 -3
  34. package/dist/esm/hooks/useGasRecommendation.js.map +1 -1
  35. package/dist/esm/hooks/useGasRefuel.js +4 -1
  36. package/dist/esm/hooks/useGasRefuel.js.map +1 -1
  37. package/dist/esm/hooks/useGasSufficiency.js +3 -3
  38. package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
  39. package/dist/esm/hooks/useIsBatchingSupported.js +2 -2
  40. package/dist/esm/hooks/useIsBatchingSupported.js.map +1 -1
  41. package/dist/esm/hooks/useRouteExecution.js +6 -6
  42. package/dist/esm/hooks/useRouteExecution.js.map +1 -1
  43. package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
  44. package/dist/esm/hooks/useRoutes.js +18 -13
  45. package/dist/esm/hooks/useRoutes.js.map +1 -1
  46. package/dist/esm/hooks/useToAddressAutoPopulate.js +6 -8
  47. package/dist/esm/hooks/useToAddressAutoPopulate.js.map +1 -1
  48. package/dist/esm/hooks/useToAddressRequirements.d.ts +3 -2
  49. package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
  50. package/dist/esm/hooks/useToAddressRequirements.js +8 -7
  51. package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
  52. package/dist/esm/hooks/useToAddressReset.js +6 -3
  53. package/dist/esm/hooks/useToAddressReset.js.map +1 -1
  54. package/dist/esm/hooks/useTokenBalance.js +6 -5
  55. package/dist/esm/hooks/useTokenBalance.js.map +1 -1
  56. package/dist/esm/hooks/useTokenBalancesQueries.js +3 -3
  57. package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -1
  58. package/dist/esm/hooks/useTokenSearch.js +3 -3
  59. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  60. package/dist/esm/hooks/useTokens.js +15 -15
  61. package/dist/esm/hooks/useTokens.js.map +1 -1
  62. package/dist/esm/hooks/useTools.d.ts.map +1 -1
  63. package/dist/esm/hooks/useTools.js +26 -27
  64. package/dist/esm/hooks/useTools.js.map +1 -1
  65. package/dist/esm/hooks/useTransactionDetails.js +2 -2
  66. package/dist/esm/hooks/useTransactionDetails.js.map +1 -1
  67. package/dist/esm/hooks/useTransactionHistory.js +3 -3
  68. package/dist/esm/hooks/useTransactionHistory.js.map +1 -1
  69. package/dist/esm/i18n/bn.json +2 -1
  70. package/dist/esm/i18n/de.json +2 -1
  71. package/dist/esm/i18n/en.json +2 -1
  72. package/dist/esm/i18n/es.json +2 -1
  73. package/dist/esm/i18n/fr.json +2 -1
  74. package/dist/esm/i18n/hi.json +2 -1
  75. package/dist/esm/i18n/id.json +2 -1
  76. package/dist/esm/i18n/it.json +2 -1
  77. package/dist/esm/i18n/ja.json +2 -1
  78. package/dist/esm/i18n/ko.json +2 -1
  79. package/dist/esm/i18n/pl.json +2 -1
  80. package/dist/esm/i18n/pt.json +2 -1
  81. package/dist/esm/i18n/th.json +2 -1
  82. package/dist/esm/i18n/tr.json +2 -1
  83. package/dist/esm/i18n/uk.json +2 -1
  84. package/dist/esm/i18n/vi.json +2 -1
  85. package/dist/esm/i18n/zh.json +2 -1
  86. package/dist/esm/index.d.ts +5 -1
  87. package/dist/esm/index.js +3 -1
  88. package/dist/esm/pages/RoutesPage/RoutesPage.style.d.ts.map +1 -1
  89. package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js +7 -4
  90. package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js.map +1 -1
  91. package/dist/esm/pages/SendToWallet/BookmarksPage.js +35 -31
  92. package/dist/esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
  93. package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js +4 -3
  94. package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
  95. package/dist/esm/pages/SendToWallet/RecentWalletsPage.js +43 -39
  96. package/dist/esm/pages/SendToWallet/RecentWalletsPage.js.map +1 -1
  97. package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js +32 -26
  98. package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js.map +1 -1
  99. package/dist/esm/pages/SendToWallet/SendToWalletPage.js +5 -10
  100. package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
  101. package/dist/esm/providers/I18nProvider/types.d.ts.map +1 -1
  102. package/dist/esm/providers/WalletProvider/WalletProvider.d.ts.map +1 -1
  103. package/dist/esm/providers/WalletProvider/WalletProvider.js +14 -2
  104. package/dist/esm/providers/WalletProvider/WalletProvider.js.map +1 -1
  105. package/dist/esm/providers/WidgetProvider/WidgetProvider.d.ts.map +1 -1
  106. package/dist/esm/providers/WidgetProvider/WidgetProvider.js +15 -11
  107. package/dist/esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
  108. package/dist/esm/providers/WidgetProvider/types.d.ts +2 -0
  109. package/dist/esm/providers/WidgetProvider/types.d.ts.map +1 -1
  110. package/dist/esm/queries/getChains.d.ts +38 -0
  111. package/dist/esm/queries/getChains.d.ts.map +1 -0
  112. package/dist/esm/queries/getChains.js +51 -0
  113. package/dist/esm/queries/getChains.js.map +1 -0
  114. package/dist/esm/queries/getTools.d.ts +26 -0
  115. package/dist/esm/queries/getTools.d.ts.map +1 -0
  116. package/dist/esm/queries/getTools.js +30 -0
  117. package/dist/esm/queries/getTools.js.map +1 -0
  118. package/dist/esm/queries/index.d.ts +4 -0
  119. package/dist/esm/queries/index.js +3 -0
  120. package/dist/esm/queries/types.d.ts +25 -0
  121. package/dist/esm/queries/types.d.ts.map +1 -0
  122. package/dist/esm/shared.d.ts +2 -1
  123. package/dist/esm/shared.js +2 -1
  124. package/dist/esm/stores/StoreProvider.d.ts.map +1 -1
  125. package/dist/esm/stores/StoreProvider.js +16 -17
  126. package/dist/esm/stores/StoreProvider.js.map +1 -1
  127. package/dist/esm/stores/bookmarks/types.d.ts +3 -0
  128. package/dist/esm/stores/bookmarks/types.d.ts.map +1 -1
  129. package/dist/esm/stores/chains/ChainOrderStore.d.ts.map +1 -1
  130. package/dist/esm/stores/chains/ChainOrderStore.js +4 -1
  131. package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
  132. package/dist/esm/stores/form/FormStore.js +3 -2
  133. package/dist/esm/stores/form/FormStore.js.map +1 -1
  134. package/dist/esm/stores/form/URLSearchParamsBuilder.js +7 -3
  135. package/dist/esm/stores/form/URLSearchParamsBuilder.js.map +1 -1
  136. package/dist/esm/stores/form/getDefaultValuesFromQueryString.js +4 -1
  137. package/dist/esm/stores/form/getDefaultValuesFromQueryString.js.map +1 -1
  138. package/dist/esm/stores/header/useHeaderStore.d.ts +1 -1
  139. package/dist/esm/stores/header/useHeaderStore.d.ts.map +1 -1
  140. package/dist/esm/stores/header/useHeaderStore.js.map +1 -1
  141. package/dist/esm/themes/createTheme.d.ts.map +1 -1
  142. package/dist/esm/types/events.d.ts.map +1 -1
  143. package/dist/esm/types/token.d.ts.map +1 -1
  144. package/dist/esm/types/widget.d.ts +30 -0
  145. package/dist/esm/types/widget.d.ts.map +1 -1
  146. package/dist/esm/types/widget.js.map +1 -1
  147. package/dist/esm/utils/chainType.js +32 -1
  148. package/dist/esm/utils/chainType.js.map +1 -1
  149. package/dist/esm/utils/customReceiver.js +6 -1
  150. package/dist/esm/utils/customReceiver.js.map +1 -1
  151. package/dist/esm/utils/queries.js.map +1 -1
  152. package/dist/esm/utils/scopeKeys.d.ts +6 -0
  153. package/dist/esm/utils/scopeKeys.d.ts.map +1 -0
  154. package/dist/esm/utils/scopeKeys.js +8 -0
  155. package/dist/esm/utils/scopeKeys.js.map +1 -0
  156. package/package.json +15 -7
  157. package/src/components/AmountInputCard/AmountInputCardPair.tsx +6 -2
  158. package/src/components/SelectChainAndToken.tsx +5 -1
  159. package/src/components/SendToWallet/SendToWalletButton.tsx +13 -8
  160. package/src/components/TokenList/useTokenSelect.ts +15 -0
  161. package/src/config/constants.ts +3 -0
  162. package/src/config/version.ts +1 -1
  163. package/src/hooks/useAccountsBalancesData.ts +6 -2
  164. package/src/hooks/useAddressValidation.ts +87 -32
  165. package/src/hooks/useAvailableChains.test.tsx +170 -0
  166. package/src/hooks/useAvailableChains.ts +29 -47
  167. package/src/hooks/useFromTokenSufficiency.ts +2 -2
  168. package/src/hooks/useGasRecommendation.ts +2 -2
  169. package/src/hooks/useGasRefuel.ts +11 -1
  170. package/src/hooks/useGasSufficiency.ts +2 -2
  171. package/src/hooks/useIsBatchingSupported.ts +2 -2
  172. package/src/hooks/useRouteExecution.ts +5 -5
  173. package/src/hooks/useRoutes.ts +28 -23
  174. package/src/hooks/useToAddressAutoPopulate.ts +13 -17
  175. package/src/hooks/useToAddressRequirements.ts +19 -4
  176. package/src/hooks/useToAddressReset.ts +13 -4
  177. package/src/hooks/useTokenBalance.ts +10 -5
  178. package/src/hooks/useTokenBalancesQueries.ts +3 -3
  179. package/src/hooks/useTokenSearch.ts +7 -3
  180. package/src/hooks/useTokens.ts +13 -14
  181. package/src/hooks/useTools.sharedEntry.test.tsx +155 -0
  182. package/src/hooks/useTools.ts +42 -37
  183. package/src/hooks/useTransactionDetails.ts +3 -3
  184. package/src/hooks/useTransactionHistory.ts +2 -2
  185. package/src/index.ts +2 -1
  186. package/src/pages/SendToWallet/BookmarkAddressSheet.tsx +5 -1
  187. package/src/pages/SendToWallet/BookmarksPage.tsx +42 -52
  188. package/src/pages/SendToWallet/ConnectedWalletsPage.tsx +4 -14
  189. package/src/pages/SendToWallet/RecentWalletsPage.tsx +59 -66
  190. package/src/pages/SendToWallet/SendToConfiguredWalletPage.tsx +45 -50
  191. package/src/pages/SendToWallet/SendToWalletPage.tsx +4 -16
  192. package/src/providers/WalletProvider/WalletProvider.tsx +28 -3
  193. package/src/providers/WidgetProvider/WidgetProvider.test.tsx +73 -0
  194. package/src/providers/WidgetProvider/WidgetProvider.tsx +28 -14
  195. package/src/providers/WidgetProvider/types.ts +2 -0
  196. package/src/queries/getChains.ts +93 -0
  197. package/src/queries/getTools.ts +62 -0
  198. package/src/queries/index.ts +30 -0
  199. package/src/queries/sharedCache.test.tsx +223 -0
  200. package/src/queries/types.ts +38 -0
  201. package/src/shared.ts +1 -0
  202. package/src/stores/StoreProvider.test.tsx +107 -0
  203. package/src/stores/StoreProvider.tsx +8 -6
  204. package/src/stores/bookmarks/types.ts +3 -0
  205. package/src/stores/chains/ChainOrderStore.tsx +4 -1
  206. package/src/stores/form/FormStore.tsx +2 -0
  207. package/src/stores/form/URLSearchParamsBuilder.tsx +4 -2
  208. package/src/stores/form/getDefaultValuesFromQueryString.ts +19 -0
  209. package/src/stores/header/useHeaderStore.tsx +3 -4
  210. package/src/types/widget.ts +30 -0
  211. package/src/utils/chainType.ts +73 -1
  212. package/src/utils/customReceiver.ts +36 -0
  213. package/src/utils/queries.ts +1 -0
  214. package/src/utils/scopeKeys.ts +18 -0
@@ -1 +1 @@
1
- {"version":3,"file":"useAvailableChains.js","names":[],"sources":["../../../src/hooks/useAvailableChains.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { ChainType, createClient, getChains } from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { WidgetConfig } from '../types/widget.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../utils/item.js'\nimport { getQueryKey } from '../utils/queries.js'\n\ntype GetChainById = (\n chainId?: number,\n chains?: ExtendedChain[]\n) => ExtendedChain | undefined\n\nconst supportedChainTypes = [\n ChainType.EVM,\n ChainType.SVM,\n ChainType.UTXO,\n ChainType.MVM,\n ChainType.TVM,\n ChainType.STL,\n]\n\nexport const useAvailableChains = (\n chainTypes?: ChainType[],\n widgetConfig?: WidgetConfig\n): {\n chains: ExtendedChain[] | undefined\n getChainById: GetChainById\n isLoading: boolean\n} => {\n const { chains: internalChains, keyPrefix: internalKeyPrefix } =\n useWidgetConfig()\n const internalClient = useSDKClient()\n\n const externalClient = useMemo(() => {\n if (!widgetConfig) {\n return undefined\n }\n return createClient({\n ...widgetConfig.sdkConfig,\n apiKey: widgetConfig.apiKey,\n integrator: widgetConfig.integrator ?? window?.location.hostname,\n })\n }, [widgetConfig])\n\n // Overwrite widget config if passed as param\n const keyPrefix = widgetConfig?.keyPrefix ?? internalKeyPrefix\n const chains = widgetConfig?.chains ?? internalChains\n\n const { data, isLoading } = useQuery({\n queryKey: [\n getQueryKey('chains', keyPrefix),\n chains?.types,\n chains?.allow,\n chains?.deny,\n chains?.from,\n chains?.to,\n !!externalClient,\n ] as const,\n queryFn: async ({ queryKey: [, chainTypesConfig] }) => {\n const chainsConfigSets = getConfigItemSets(\n chainTypesConfig,\n (chains) => new Set(chains)\n )\n const chainTypesRequest = supportedChainTypes.filter((chainType) =>\n isItemAllowedForSets(chainType, chainsConfigSets)\n )\n const client = externalClient ?? internalClient\n const availableChains = await getChains(client, {\n chainTypes: chainTypes || chainTypesRequest,\n })\n client.setChains(availableChains)\n return availableChains\n },\n refetchInterval: 300_000,\n staleTime: 300_000,\n })\n\n // Ensure the current internal client always has chains, even when:\n // - the query result came from cache (external call populated it first)\n // - the client was recreated due to config changes (stale closure in queryFn)\n useEffect(() => {\n if (data && !externalClient) {\n internalClient.setChains(data)\n }\n }, [data, externalClient, internalClient])\n\n const getChainById: GetChainById = useCallback(\n (chainId?: number, chains: ExtendedChain[] | undefined = data) => {\n if (!chainId) {\n return\n }\n const chain = chains?.find((chain) => chain.id === chainId)\n // if (!chain) {\n // throw new Error('Chain not found or chainId is invalid.');\n // }\n return chain\n },\n [data]\n )\n\n return {\n chains: data,\n getChainById,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;AAeA,MAAM,sBAAsB;CAC1B,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;AACZ;AAEA,MAAa,sBACX,YACA,iBAKG;CACH,MAAM,EAAE,QAAQ,gBAAgB,WAAW,sBACzC,gBAAgB;CAClB,MAAM,iBAAiB,aAAa;CAEpC,MAAM,iBAAiB,cAAc;EACnC,IAAI,CAAC,cACH;EAEF,OAAO,aAAa;GAClB,GAAG,aAAa;GAChB,QAAQ,aAAa;GACrB,YAAY,aAAa,cAAc,QAAQ,SAAS;EAC1D,CAAC;CACH,GAAG,CAAC,YAAY,CAAC;CAGjB,MAAM,YAAY,cAAc,aAAa;CAC7C,MAAM,SAAS,cAAc,UAAU;CAEvC,MAAM,EAAE,MAAM,cAAc,SAAS;EACnC,UAAU;GACR,YAAY,UAAU,SAAS;GAC/B,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,CAAC,CAAC;EACJ;EACA,SAAS,OAAO,EAAE,UAAU,GAAG,wBAAwB;GACrD,MAAM,mBAAmB,kBACvB,mBACC,WAAW,IAAI,IAAI,MAAM,CAC5B;GACA,MAAM,oBAAoB,oBAAoB,QAAQ,cACpD,qBAAqB,WAAW,gBAAgB,CAClD;GACA,MAAM,SAAS,kBAAkB;GACjC,MAAM,kBAAkB,MAAM,UAAU,QAAQ,EAC9C,YAAY,cAAc,kBAC5B,CAAC;GACD,OAAO,UAAU,eAAe;GAChC,OAAO;EACT;EACA,iBAAiB;EACjB,WAAW;CACb,CAAC;CAKD,gBAAgB;EACd,IAAI,QAAQ,CAAC,gBACX,eAAe,UAAU,IAAI;CAEjC,GAAG;EAAC;EAAM;EAAgB;CAAc,CAAC;CAgBzC,OAAO;EACL,QAAQ;EACR,cAhBiC,aAChC,SAAkB,SAAsC,SAAS;GAChE,IAAI,CAAC,SACH;GAMF,OAJc,QAAQ,MAAM,UAAU,MAAM,OAAO,OAAO;EAK5D,GACA,CAAC,IAAI,CAKM;EACX;CACF;AACF"}
1
+ {"version":3,"file":"useAvailableChains.js","names":[],"sources":["../../../src/hooks/useAvailableChains.ts"],"sourcesContent":["import type { ChainType, ExtendedChain } from '@lifi/sdk'\nimport { createClient } from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport {\n getChainsQueryOptions,\n supportedChainTypes,\n} from '../queries/getChains.js'\nimport type { WidgetConfig } from '../types/widget.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../utils/item.js'\nimport { resolveQueryScopeKey } from '../utils/scopeKeys.js'\n\ntype GetChainById = (\n chainId?: number,\n chains?: ExtendedChain[]\n) => ExtendedChain | undefined\n\nconst refetchInterval = 300_000\n\nexport const useAvailableChains = (\n chainTypes?: ChainType[],\n widgetConfig?: WidgetConfig\n): {\n chains: ExtendedChain[] | undefined\n getChainById: GetChainById\n isLoading: boolean\n} => {\n const { chains: internalChains, queryScopeKey: internalQueryScopeKey } =\n useWidgetConfig()\n const internalClient = useSDKClient()\n\n const externalClient = useMemo(() => {\n if (!widgetConfig) {\n return undefined\n }\n return createClient({\n ...widgetConfig.sdkConfig,\n apiKey: widgetConfig.apiKey,\n integrator: widgetConfig.integrator ?? window?.location.hostname,\n })\n }, [widgetConfig])\n\n // Overwrite widget config if passed as param\n const client = externalClient ?? internalClient\n const chains = widgetConfig?.chains ?? internalChains\n const queryScopeKey = widgetConfig\n ? resolveQueryScopeKey(widgetConfig)\n : internalQueryScopeKey\n\n const typeSets = getConfigItemSets(chains?.types, (types) => new Set(types))\n const requestedTypes =\n chainTypes ??\n supportedChainTypes.filter((type) => isItemAllowedForSets(type, typeSets))\n\n const { data, dataUpdatedAt, isLoading } = useQuery(\n getChainsQueryOptions(client, {\n chainTypes: requestedTypes,\n scopeKey: queryScopeKey,\n query: { refetchInterval, staleTime: refetchInterval },\n })\n )\n\n // A host may fill the entry; key on dataUpdatedAt, as a refetch keeps data.\n useEffect(() => {\n if (data && dataUpdatedAt) {\n client.setChains(data)\n }\n }, [data, dataUpdatedAt, client])\n\n const getChainById: GetChainById = useCallback(\n (chainId?: number, chains: ExtendedChain[] | undefined = data) => {\n if (!chainId) {\n return\n }\n const chain = chains?.find((chain) => chain.id === chainId)\n // if (!chain) {\n // throw new Error('Chain not found or chainId is invalid.');\n // }\n return chain\n },\n [data]\n )\n\n return {\n chains: data,\n getChainById,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;AAmBA,MAAM,kBAAkB;AAExB,MAAa,sBACX,YACA,iBAKG;CACH,MAAM,EAAE,QAAQ,gBAAgB,eAAe,0BAC7C,gBAAgB;CAClB,MAAM,iBAAiB,aAAa;CAcpC,MAAM,SAZiB,cAAc;EACnC,IAAI,CAAC,cACH;EAEF,OAAO,aAAa;GAClB,GAAG,aAAa;GAChB,QAAQ,aAAa;GACrB,YAAY,aAAa,cAAc,QAAQ,SAAS;EAC1D,CAAC;CACH,GAAG,CAAC,YAAY,CAGY,KAAK;CACjC,MAAM,SAAS,cAAc,UAAU;CACvC,MAAM,gBAAgB,eAClB,qBAAqB,YAAY,IACjC;CAEJ,MAAM,WAAW,kBAAkB,QAAQ,QAAQ,UAAU,IAAI,IAAI,KAAK,CAAC;CAC3E,MAAM,iBACJ,cACA,oBAAoB,QAAQ,SAAS,qBAAqB,MAAM,QAAQ,CAAC;CAE3E,MAAM,EAAE,MAAM,eAAe,cAAc,SACzC,sBAAsB,QAAQ;EAC5B,YAAY;EACZ,UAAU;EACV,OAAO;GAAE;GAAiB,WAAW;EAAgB;CACvD,CAAC,CACH;CAGA,gBAAgB;EACd,IAAI,QAAQ,eACV,OAAO,UAAU,IAAI;CAEzB,GAAG;EAAC;EAAM;EAAe;CAAM,CAAC;CAgBhC,OAAO;EACL,QAAQ;EACR,cAhBiC,aAChC,SAAkB,SAAsC,SAAS;GAChE,IAAI,CAAC,SACH;GAMF,OAJc,QAAQ,MAAM,UAAU,MAAM,OAAO,OAAO;EAK5D,GACA,CAAC,IAAI,CAKM;EACX;CACF;AACF"}
@@ -1,8 +1,8 @@
1
1
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
2
2
  import { useSDKClient } from "../providers/SDKClientProvider.js";
3
- import { getQueryKey } from "../utils/queries.js";
4
3
  import { useFieldValues } from "../stores/form/useFieldValues.js";
5
4
  import { isRouteDone } from "../stores/routes/utils.js";
5
+ import { getQueryKey } from "../utils/queries.js";
6
6
  import { getTokenBalancesWithRetry } from "./useTokenBalance.js";
7
7
  import { useTokenAddressBalance } from "./useTokenAddressBalance.js";
8
8
  import { parseUnits } from "@lifi/sdk";
@@ -12,7 +12,7 @@ import { useAccount } from "@lifi/wallet-management";
12
12
  const refetchInterval = 3e4;
13
13
  const useFromTokenSufficiency = (route) => {
14
14
  const [fromChainId, fromTokenAddress, fromAmount] = useFieldValues("fromChain", "fromToken", "fromAmount");
15
- const { keyPrefix } = useWidgetConfig();
15
+ const { storageScopeKey } = useWidgetConfig();
16
16
  const sdkClient = useSDKClient();
17
17
  let chainId = fromChainId;
18
18
  let tokenAddress = fromTokenAddress;
@@ -24,7 +24,7 @@ const useFromTokenSufficiency = (route) => {
24
24
  const { account } = useAccount({ chainType: chain?.chainType });
25
25
  const { data: insufficientFromToken, isLoading } = useQuery({
26
26
  queryKey: [
27
- getQueryKey("from-token-sufficiency-check", keyPrefix),
27
+ getQueryKey("from-token-sufficiency-check", storageScopeKey),
28
28
  account.address,
29
29
  chainId,
30
30
  tokenAddress,
@@ -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,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
+ {"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 { storageScopeKey } = 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', storageScopeKey),\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,oBAAoB,gBAAgB;CAC5C,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,eAAe;GAC3D,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,20 +1,20 @@
1
1
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
2
2
  import { useSDKClient } from "../providers/SDKClientProvider.js";
3
- import { getQueryKey } from "../utils/queries.js";
4
3
  import { useAvailableChains } from "./useAvailableChains.js";
4
+ import { getQueryKey } from "../utils/queries.js";
5
5
  import { getGasRecommendation } from "@lifi/sdk";
6
6
  import { useQuery } from "@tanstack/react-query";
7
7
  //#region src/hooks/useGasRecommendation.ts
8
8
  const refetchInterval = 6e4;
9
9
  const useGasRecommendation = (toChainId, fromChain, fromToken) => {
10
10
  const { chains } = useAvailableChains();
11
- const { keyPrefix, hiddenUI } = useWidgetConfig();
11
+ const { storageScopeKey, hiddenUI } = useWidgetConfig();
12
12
  const sdkClient = useSDKClient();
13
13
  const checkRecommendationLiFuel = Boolean(toChainId) && Boolean(fromChain) && Boolean(fromToken) && Boolean(chains?.length);
14
14
  const checkRecommendationMaxButton = Boolean(toChainId) && !fromChain && !fromToken && Boolean(chains?.length);
15
15
  return useQuery({
16
16
  queryKey: [
17
- getQueryKey("gas-recommendation", keyPrefix),
17
+ getQueryKey("gas-recommendation", storageScopeKey),
18
18
  toChainId,
19
19
  fromChain,
20
20
  fromToken
@@ -1 +1 @@
1
- {"version":3,"file":"useGasRecommendation.js","names":[],"sources":["../../../src/hooks/useGasRecommendation.ts"],"sourcesContent":["import { type ChainId, getGasRecommendation } from '@lifi/sdk'\nimport type { UseQueryResult } from '@tanstack/react-query'\nimport { useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nconst refetchInterval = 60_000\n\nexport const useGasRecommendation = (\n toChainId?: ChainId,\n fromChain?: ChainId,\n fromToken?: string\n): UseQueryResult<Awaited<ReturnType<typeof getGasRecommendation>> | null> => {\n const { chains } = useAvailableChains()\n const { keyPrefix, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const checkRecommendationLiFuel =\n Boolean(toChainId) &&\n Boolean(fromChain) &&\n Boolean(fromToken) &&\n Boolean(chains?.length)\n\n const checkRecommendationMaxButton =\n Boolean(toChainId) && !fromChain && !fromToken && Boolean(chains?.length)\n\n return useQuery({\n queryKey: [\n getQueryKey('gas-recommendation', keyPrefix),\n toChainId,\n fromChain,\n fromToken,\n ],\n queryFn: async ({\n queryKey: [_, toChainId, fromChain, fromToken],\n signal,\n }) => {\n if (!chains?.some((chain) => chain.id === toChainId)) {\n return null\n }\n const gasRecommendation = await getGasRecommendation(\n sdkClient,\n {\n chainId: toChainId as ChainId,\n fromChain: fromChain as ChainId,\n fromToken: fromToken as string,\n },\n { signal }\n )\n return gasRecommendation\n },\n enabled:\n (checkRecommendationLiFuel || checkRecommendationMaxButton) &&\n !hiddenUI?.gasRefuelMessage,\n refetchInterval,\n staleTime: refetchInterval,\n })\n}\n"],"mappings":";;;;;;;AAQA,MAAM,kBAAkB;AAExB,MAAa,wBACX,WACA,WACA,cAC4E;CAC5E,MAAM,EAAE,WAAW,mBAAmB;CACtC,MAAM,EAAE,WAAW,aAAa,gBAAgB;CAChD,MAAM,YAAY,aAAa;CAE/B,MAAM,4BACJ,QAAQ,SAAS,KACjB,QAAQ,SAAS,KACjB,QAAQ,SAAS,KACjB,QAAQ,QAAQ,MAAM;CAExB,MAAM,+BACJ,QAAQ,SAAS,KAAK,CAAC,aAAa,CAAC,aAAa,QAAQ,QAAQ,MAAM;CAE1E,OAAO,SAAS;EACd,UAAU;GACR,YAAY,sBAAsB,SAAS;GAC3C;GACA;GACA;EACF;EACA,SAAS,OAAO,EACd,UAAU,CAAC,GAAG,WAAW,WAAW,YACpC,aACI;GACJ,IAAI,CAAC,QAAQ,MAAM,UAAU,MAAM,OAAO,SAAS,GACjD,OAAO;GAWT,OAAO,MATyB,qBAC9B,WACA;IACE,SAAS;IACE;IACA;GACb,GACA,EAAE,OAAO,CACX;EAEF;EACA,UACG,6BAA6B,iCAC9B,CAAC,UAAU;EACb;EACA,WAAW;CACb,CAAC;AACH"}
1
+ {"version":3,"file":"useGasRecommendation.js","names":[],"sources":["../../../src/hooks/useGasRecommendation.ts"],"sourcesContent":["import { type ChainId, getGasRecommendation } from '@lifi/sdk'\nimport type { UseQueryResult } from '@tanstack/react-query'\nimport { useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nconst refetchInterval = 60_000\n\nexport const useGasRecommendation = (\n toChainId?: ChainId,\n fromChain?: ChainId,\n fromToken?: string\n): UseQueryResult<Awaited<ReturnType<typeof getGasRecommendation>> | null> => {\n const { chains } = useAvailableChains()\n const { storageScopeKey, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const checkRecommendationLiFuel =\n Boolean(toChainId) &&\n Boolean(fromChain) &&\n Boolean(fromToken) &&\n Boolean(chains?.length)\n\n const checkRecommendationMaxButton =\n Boolean(toChainId) && !fromChain && !fromToken && Boolean(chains?.length)\n\n return useQuery({\n queryKey: [\n getQueryKey('gas-recommendation', storageScopeKey),\n toChainId,\n fromChain,\n fromToken,\n ],\n queryFn: async ({\n queryKey: [_, toChainId, fromChain, fromToken],\n signal,\n }) => {\n if (!chains?.some((chain) => chain.id === toChainId)) {\n return null\n }\n const gasRecommendation = await getGasRecommendation(\n sdkClient,\n {\n chainId: toChainId as ChainId,\n fromChain: fromChain as ChainId,\n fromToken: fromToken as string,\n },\n { signal }\n )\n return gasRecommendation\n },\n enabled:\n (checkRecommendationLiFuel || checkRecommendationMaxButton) &&\n !hiddenUI?.gasRefuelMessage,\n refetchInterval,\n staleTime: refetchInterval,\n })\n}\n"],"mappings":";;;;;;;AAQA,MAAM,kBAAkB;AAExB,MAAa,wBACX,WACA,WACA,cAC4E;CAC5E,MAAM,EAAE,WAAW,mBAAmB;CACtC,MAAM,EAAE,iBAAiB,aAAa,gBAAgB;CACtD,MAAM,YAAY,aAAa;CAE/B,MAAM,4BACJ,QAAQ,SAAS,KACjB,QAAQ,SAAS,KACjB,QAAQ,SAAS,KACjB,QAAQ,QAAQ,MAAM;CAExB,MAAM,+BACJ,QAAQ,SAAS,KAAK,CAAC,aAAa,CAAC,aAAa,QAAQ,QAAQ,MAAM;CAE1E,OAAO,SAAS;EACd,UAAU;GACR,YAAY,sBAAsB,eAAe;GACjD;GACA;GACA;EACF;EACA,SAAS,OAAO,EACd,UAAU,CAAC,GAAG,WAAW,WAAW,YACpC,aACI;GACJ,IAAI,CAAC,QAAQ,MAAM,UAAU,MAAM,OAAO,SAAS,GACjD,OAAO;GAWT,OAAO,MATyB,qBAC9B,WACA;IACE,SAAS;IACE;IACA;GACb,GACA,EAAE,OAAO,CACX;EAEF;EACA,UACG,6BAA6B,iCAC9B,CAAC,UAAU;EACb;EACA,WAAW;CACb,CAAC;AACH"}
@@ -5,6 +5,7 @@ import { useGasRecommendation } from "./useGasRecommendation.js";
5
5
  import { useIsContractAddress } from "./useIsContractAddress.js";
6
6
  import { useTokenBalance } from "./useTokenBalance.js";
7
7
  import { useMemo } from "react";
8
+ import { useAddressForChain } from "@lifi/widget-provider";
8
9
  import { useAccount } from "@lifi/wallet-management";
9
10
  //#region src/hooks/useGasRefuel.ts
10
11
  const useGasRefuel = () => {
@@ -14,7 +15,9 @@ const useGasRefuel = () => {
14
15
  const toChain = getChainById(toChainId);
15
16
  const fromChain = getChainById(fromChainId);
16
17
  const { account: toAccount } = useAccount({ chainType: toChain?.chainType });
17
- const effectiveToAddress = toAddress || toAccount?.address;
18
+ const { isAddressForChain } = useAddressForChain();
19
+ const toAccountAddress = toAccount?.address && toChain && isAddressForChain(toAccount.address, toChain) ? toAccount.address : void 0;
20
+ const effectiveToAddress = toAddress || toAccountAddress;
18
21
  const { isContractAddress: isToContractAddress } = useIsContractAddress(effectiveToAddress, toChainId, toChain?.chainType);
19
22
  const { token: destinationNativeToken } = useTokenBalance(effectiveToAddress, toChainId ? toChain?.nativeToken : void 0);
20
23
  const { data: gasRecommendation, isLoading } = useGasRecommendation(toChainId, fromChainId, fromTokenAddress);
@@ -1 +1 @@
1
- {"version":3,"file":"useGasRefuel.js","names":[],"sources":["../../../src/hooks/useGasRefuel.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useGasRecommendation } from './useGasRecommendation.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { useTokenBalance } from './useTokenBalance.js'\n\nexport const useGasRefuel = (): {\n enabled: boolean\n availble: boolean | undefined\n isLoading: boolean\n chain: ExtendedChain | undefined\n fromAmount: string | undefined\n} => {\n const { getChainById } = useAvailableChains()\n const { hiddenUI } = useWidgetConfig()\n const [fromChainId, fromTokenAddress, toChainId, toAddress] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'toChain',\n 'toAddress'\n )\n\n const toChain = getChainById(toChainId)\n const fromChain = getChainById(fromChainId)\n\n const { account: toAccount } = useAccount({ chainType: toChain?.chainType })\n\n const effectiveToAddress = toAddress || toAccount?.address\n\n const { isContractAddress: isToContractAddress } = useIsContractAddress(\n effectiveToAddress,\n toChainId,\n toChain?.chainType\n )\n\n const { token: destinationNativeToken } = useTokenBalance(\n effectiveToAddress,\n toChainId ? toChain?.nativeToken : undefined\n )\n\n const { data: gasRecommendation, isLoading } = useGasRecommendation(\n toChainId,\n fromChainId,\n fromTokenAddress\n )\n\n // When we bridge between ecosystems we need to be sure toAddress is set\n const isChainTypeSatisfied =\n fromChain?.chainType !== toChain?.chainType ? Boolean(toAddress) : true\n\n // We should not refuel to the contract address\n const isToAddressSatisfied = effectiveToAddress && !isToContractAddress\n\n const enabled = useMemo(() => {\n if (\n // Same chain refuel is not allowed since users need gas on source chain to initiate transaction\n // We allow refuel when bridging to native token since bridging routes may require gas for destination swaps\n fromChainId === toChainId ||\n !gasRecommendation?.available ||\n !gasRecommendation?.recommended ||\n !destinationNativeToken ||\n !isChainTypeSatisfied ||\n !isToAddressSatisfied ||\n hiddenUI?.gasRefuelMessage\n ) {\n return false\n }\n const tokenBalance = destinationNativeToken.amount ?? 0n\n\n // Check if the user balance < 50% of the recommended amount\n const recommendedAmount = BigInt(gasRecommendation.recommended.amount) / 2n\n\n const insufficientGas = tokenBalance < recommendedAmount\n return insufficientGas\n }, [\n fromChainId,\n gasRecommendation,\n isChainTypeSatisfied,\n isToAddressSatisfied,\n destinationNativeToken,\n toChainId,\n hiddenUI,\n ])\n\n return {\n enabled: enabled,\n availble: gasRecommendation?.available,\n isLoading: isLoading,\n chain: toChain,\n fromAmount: gasRecommendation?.available\n ? gasRecommendation.fromAmount\n : undefined,\n }\n}\n"],"mappings":";;;;;;;;;AAUA,MAAa,qBAMR;CACH,MAAM,EAAE,iBAAiB,mBAAmB;CAC5C,MAAM,EAAE,aAAa,gBAAgB;CACrC,MAAM,CAAC,aAAa,kBAAkB,WAAW,aAAa,eAC5D,aACA,aACA,WACA,WACF;CAEA,MAAM,UAAU,aAAa,SAAS;CACtC,MAAM,YAAY,aAAa,WAAW;CAE1C,MAAM,EAAE,SAAS,cAAc,WAAW,EAAE,WAAW,SAAS,UAAU,CAAC;CAE3E,MAAM,qBAAqB,aAAa,WAAW;CAEnD,MAAM,EAAE,mBAAmB,wBAAwB,qBACjD,oBACA,WACA,SAAS,SACX;CAEA,MAAM,EAAE,OAAO,2BAA2B,gBACxC,oBACA,YAAY,SAAS,cAAc,KAAA,CACrC;CAEA,MAAM,EAAE,MAAM,mBAAmB,cAAc,qBAC7C,WACA,aACA,gBACF;CAGA,MAAM,uBACJ,WAAW,cAAc,SAAS,YAAY,QAAQ,SAAS,IAAI;CAGrE,MAAM,uBAAuB,sBAAsB,CAAC;CAiCpD,OAAO;EACL,SAhCc,cAAc;GAC5B,IAGE,gBAAgB,aAChB,CAAC,mBAAmB,aACpB,CAAC,mBAAmB,eACpB,CAAC,0BACD,CAAC,wBACD,CAAC,wBACD,UAAU,kBAEV,OAAO;GAQT,QANqB,uBAAuB,UAAU,MAG5B,OAAO,kBAAkB,YAAY,MAAM,IAAI;EAI3E,GAAG;GACD;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAGiB;EACf,UAAU,mBAAmB;EAClB;EACX,OAAO;EACP,YAAY,mBAAmB,YAC3B,kBAAkB,aAClB,KAAA;CACN;AACF"}
1
+ {"version":3,"file":"useGasRefuel.js","names":[],"sources":["../../../src/hooks/useGasRefuel.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useAddressForChain } from '@lifi/widget-provider'\nimport { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useGasRecommendation } from './useGasRecommendation.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { useTokenBalance } from './useTokenBalance.js'\n\nexport const useGasRefuel = (): {\n enabled: boolean\n availble: boolean | undefined\n isLoading: boolean\n chain: ExtendedChain | undefined\n fromAmount: string | undefined\n} => {\n const { getChainById } = useAvailableChains()\n const { hiddenUI } = useWidgetConfig()\n const [fromChainId, fromTokenAddress, toChainId, toAddress] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'toChain',\n 'toAddress'\n )\n\n const toChain = getChainById(toChainId)\n const fromChain = getChainById(fromChainId)\n\n const { account: toAccount } = useAccount({ chainType: toChain?.chainType })\n const { isAddressForChain } = useAddressForChain()\n\n // A shared chain type is not a shared format: a Bitcoin account cannot receive on ZEC.\n const toAccountAddress =\n toAccount?.address &&\n toChain &&\n isAddressForChain(toAccount.address, toChain)\n ? toAccount.address\n : undefined\n\n const effectiveToAddress = toAddress || toAccountAddress\n\n const { isContractAddress: isToContractAddress } = useIsContractAddress(\n effectiveToAddress,\n toChainId,\n toChain?.chainType\n )\n\n const { token: destinationNativeToken } = useTokenBalance(\n effectiveToAddress,\n toChainId ? toChain?.nativeToken : undefined\n )\n\n const { data: gasRecommendation, isLoading } = useGasRecommendation(\n toChainId,\n fromChainId,\n fromTokenAddress\n )\n\n // When we bridge between ecosystems we need to be sure toAddress is set\n const isChainTypeSatisfied =\n fromChain?.chainType !== toChain?.chainType ? Boolean(toAddress) : true\n\n // We should not refuel to the contract address\n const isToAddressSatisfied = effectiveToAddress && !isToContractAddress\n\n const enabled = useMemo(() => {\n if (\n // Same chain refuel is not allowed since users need gas on source chain to initiate transaction\n // We allow refuel when bridging to native token since bridging routes may require gas for destination swaps\n fromChainId === toChainId ||\n !gasRecommendation?.available ||\n !gasRecommendation?.recommended ||\n !destinationNativeToken ||\n !isChainTypeSatisfied ||\n !isToAddressSatisfied ||\n hiddenUI?.gasRefuelMessage\n ) {\n return false\n }\n const tokenBalance = destinationNativeToken.amount ?? 0n\n\n // Check if the user balance < 50% of the recommended amount\n const recommendedAmount = BigInt(gasRecommendation.recommended.amount) / 2n\n\n const insufficientGas = tokenBalance < recommendedAmount\n return insufficientGas\n }, [\n fromChainId,\n gasRecommendation,\n isChainTypeSatisfied,\n isToAddressSatisfied,\n destinationNativeToken,\n toChainId,\n hiddenUI,\n ])\n\n return {\n enabled: enabled,\n availble: gasRecommendation?.available,\n isLoading: isLoading,\n chain: toChain,\n fromAmount: gasRecommendation?.available\n ? gasRecommendation.fromAmount\n : undefined,\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAa,qBAMR;CACH,MAAM,EAAE,iBAAiB,mBAAmB;CAC5C,MAAM,EAAE,aAAa,gBAAgB;CACrC,MAAM,CAAC,aAAa,kBAAkB,WAAW,aAAa,eAC5D,aACA,aACA,WACA,WACF;CAEA,MAAM,UAAU,aAAa,SAAS;CACtC,MAAM,YAAY,aAAa,WAAW;CAE1C,MAAM,EAAE,SAAS,cAAc,WAAW,EAAE,WAAW,SAAS,UAAU,CAAC;CAC3E,MAAM,EAAE,sBAAsB,mBAAmB;CAGjD,MAAM,mBACJ,WAAW,WACX,WACA,kBAAkB,UAAU,SAAS,OAAO,IACxC,UAAU,UACV,KAAA;CAEN,MAAM,qBAAqB,aAAa;CAExC,MAAM,EAAE,mBAAmB,wBAAwB,qBACjD,oBACA,WACA,SAAS,SACX;CAEA,MAAM,EAAE,OAAO,2BAA2B,gBACxC,oBACA,YAAY,SAAS,cAAc,KAAA,CACrC;CAEA,MAAM,EAAE,MAAM,mBAAmB,cAAc,qBAC7C,WACA,aACA,gBACF;CAGA,MAAM,uBACJ,WAAW,cAAc,SAAS,YAAY,QAAQ,SAAS,IAAI;CAGrE,MAAM,uBAAuB,sBAAsB,CAAC;CAiCpD,OAAO;EACL,SAhCc,cAAc;GAC5B,IAGE,gBAAgB,aAChB,CAAC,mBAAmB,aACpB,CAAC,mBAAmB,eACpB,CAAC,0BACD,CAAC,wBACD,CAAC,wBACD,UAAU,kBAEV,OAAO;GAQT,QANqB,uBAAuB,UAAU,MAG5B,OAAO,kBAAkB,YAAY,MAAM,IAAI;EAI3E,GAAG;GACD;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAGiB;EACf,UAAU,mBAAmB;EAClB;EACX,OAAO;EACP,YAAY,mBAAmB,YAC3B,kBAAkB,aAClB,KAAA;CACN;AACF"}
@@ -1,7 +1,7 @@
1
1
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
2
2
  import { useSDKClient } from "../providers/SDKClientProvider.js";
3
- import { getQueryKey } from "../utils/queries.js";
4
3
  import { useAvailableChains } from "./useAvailableChains.js";
4
+ import { getQueryKey } from "../utils/queries.js";
5
5
  import { useIsContractAddress } from "./useIsContractAddress.js";
6
6
  import { getTokenBalancesWithRetry } from "./useTokenBalance.js";
7
7
  import { getSelfFundedGasAmount } from "../utils/gas.js";
@@ -14,7 +14,7 @@ const refetchInterval = 3e4;
14
14
  const useGasSufficiency = (route) => {
15
15
  const { getChainById } = useAvailableChains();
16
16
  const { account: EVMAccount, accounts } = useAccount({ chainType: ChainType.EVM });
17
- const { keyPrefix, hiddenUI } = useWidgetConfig();
17
+ const { storageScopeKey, hiddenUI } = useWidgetConfig();
18
18
  const sdkClient = useSDKClient();
19
19
  const { relevantAccounts, relevantAccountsQueryKey } = useMemo(() => {
20
20
  const chainTypes = route?.steps.reduce((acc, step) => {
@@ -35,7 +35,7 @@ const useGasSufficiency = (route) => {
35
35
  const { isContractAddress, isLoading: isContractAddressLoading } = useIsContractAddress(EVMAccount.address, route?.fromChainId, EVMAccount.chainType);
36
36
  const { data: insufficientGas, isLoading } = useQuery({
37
37
  queryKey: [
38
- getQueryKey("gas-sufficiency-check", keyPrefix),
38
+ getQueryKey("gas-sufficiency-check", storageScopeKey),
39
39
  relevantAccountsQueryKey,
40
40
  route?.id,
41
41
  isContractAddress
@@ -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 { getSelfFundedGasAmount } from '../utils/gas.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 // A previous step can deliver this step's gas token (XLM bridged to\n // Stellar), so the user does not have to hold it up front\n const selfFundedGasAmount = getSelfFundedGasAmount(\n route,\n step,\n getChainById(token.chainId)?.chainType\n )\n if (gasCostAmount > 0n && gasCostAmount > selfFundedGasAmount) {\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":";;;;;;;;;;;;AAsBA,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,CAAC,EAAE;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,CAAC,CACjC,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,CAAC,CACrC,MAAM,iBAAiB,aAAa,SAAS,QAAQ;GAExD,MAAM,WAAW,cACd,QAAQ,SAAS,KAAK,WAAW,WAAW,MAAM,CAAC,CACnD,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,CAAC,CAAC,QAAQ,CAAC,CAAC,GACnD,EACF;KAGA,MAAM,sBAAsB,uBAC1B,OACA,MACA,aAAa,MAAM,OAAO,CAAC,EAAE,SAC/B;KACA,IAAI,gBAAgB,MAAM,gBAAgB,qBACxC,gBAAgB,MAAM,WAAW;MAC/B,WAAW,gBAAgB,MAAM,WAC7B,gBAAgB,MAAM,QAAQ,CAAC,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,CAAC,CAAC,QAAQ,CAAC,CAAC,GACnD,EACF;KACA,IAAI,gBAAgB,IAClB,gBAAgB,MAAM,WAAW;MAC/B,WAAW,gBAAgB,MAAM,WAC7B,gBAAgB,MAAM,QAAQ,CAAC,YAAY,gBAC3C;MACJ;MACA,OAAO,aAAa,MAAM,OAAO;KACnC;IAEJ;IACA,OAAO;GACT,GACA,CAAC,CACH;GAIF,IACE,MAAM,UAAU,YAAY,SAAS,MAAM,YAAY,EAAE,MAAM,SAE/D,SAAS,MAAM,YAAY,CAAC,cAC1B,SAAS,MAAM,YAAY,EAAE,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,CAAC,CACnE,KAAK,SAAS,KAAK,KAAK;IAE3B,OAAO,0BACL,WACA,QAAQ,SACR,cACF;GACF,CAAC,CACH,EAAA,CAGG,QACE,WACC,OAAO,WAAW,eAAe,QAAQ,OAAO,KAAK,CACzD,CAAC,CACA,SAAS,WAAW,OAAO,KAAK;GAEnC,IAAI,CAAC,eAAe,QAClB,OAAO,CAAC;GAGV,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,YAAY;IACzC,IAAI,SAAS,UAAU;KACrB,MAAM,kBACJ,eAAe,MACZ,MACC,EAAE,YAAY,SAAS,QAAQ,CAAC,MAAM,WACtC,EAAE,YAAY,SAAS,QAAQ,CAAC,MAAM,OAC1C,CAAC,EAAE,UAAU;KACf,MAAM,eACJ,mBAAmB,MACnB,kBAAkB,SAAS,QAAQ,CAAC,aACpC,mBAAmB,SAAS,QAAQ,CAAC,eAAe;KAEtD,MAAM,qBAAqB,eACvB,SAAS,QAAQ,CAAC,cAChB,SAAS,QAAQ,CAAC,cAAe,kBACjC,SAAS,QAAQ,CAAC,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,CAAC,CAAC,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 { getSelfFundedGasAmount } from '../utils/gas.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 { storageScopeKey, 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', storageScopeKey),\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 // A previous step can deliver this step's gas token (XLM bridged to\n // Stellar), so the user does not have to hold it up front\n const selfFundedGasAmount = getSelfFundedGasAmount(\n route,\n step,\n getChainById(token.chainId)?.chainType\n )\n if (gasCostAmount > 0n && gasCostAmount > selfFundedGasAmount) {\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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"}
@@ -6,13 +6,13 @@ import { useQuery } from "@tanstack/react-query";
6
6
  import { useEthereumContext } from "@lifi/widget-provider";
7
7
  //#region src/hooks/useIsBatchingSupported.ts
8
8
  function useIsBatchingSupported(chain, address) {
9
- const { keyPrefix } = useWidgetConfig();
9
+ const { storageScopeKey } = useWidgetConfig();
10
10
  const sdkClient = useSDKClient();
11
11
  const { isBatchingSupported } = useEthereumContext();
12
12
  const enabled = Boolean(chain && chain.chainType === ChainType.EVM && !!address);
13
13
  const { data, isLoading } = useQuery({
14
14
  queryKey: [
15
- getQueryKey("isBatchingSupported", keyPrefix),
15
+ getQueryKey("isBatchingSupported", storageScopeKey),
16
16
  chain?.id,
17
17
  address
18
18
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"useIsBatchingSupported.js","names":[],"sources":["../../../src/hooks/useIsBatchingSupported.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport { useEthereumContext } from '@lifi/widget-provider'\nimport { useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getQueryKey } from '../utils/queries.js'\n\nexport function useIsBatchingSupported(\n chain?: ExtendedChain,\n address?: string\n): {\n isBatchingSupported: boolean | undefined\n isBatchingSupportedLoading: boolean\n} {\n const { keyPrefix } = useWidgetConfig()\n const sdkClient = useSDKClient()\n const { isBatchingSupported } = useEthereumContext()\n\n const enabled = Boolean(\n chain && chain.chainType === ChainType.EVM && !!address\n )\n const { data, isLoading } = useQuery({\n queryKey: [\n getQueryKey('isBatchingSupported', keyPrefix),\n chain?.id,\n address,\n ],\n queryFn: () => {\n return (\n isBatchingSupported?.(sdkClient, {\n chainId: chain!.id,\n skipReady: true,\n }) ?? false\n )\n },\n enabled,\n staleTime: 3_600_000,\n retry: false,\n })\n\n return {\n isBatchingSupported: data,\n isBatchingSupportedLoading: enabled && isLoading,\n }\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,uBACd,OACA,SAIA;CACA,MAAM,EAAE,cAAc,gBAAgB;CACtC,MAAM,YAAY,aAAa;CAC/B,MAAM,EAAE,wBAAwB,mBAAmB;CAEnD,MAAM,UAAU,QACd,SAAS,MAAM,cAAc,UAAU,OAAO,CAAC,CAAC,OAClD;CACA,MAAM,EAAE,MAAM,cAAc,SAAS;EACnC,UAAU;GACR,YAAY,uBAAuB,SAAS;GAC5C,OAAO;GACP;EACF;EACA,eAAe;GACb,OACE,sBAAsB,WAAW;IAC/B,SAAS,MAAO;IAChB,WAAW;GACb,CAAC,KAAK;EAEV;EACA;EACA,WAAW;EACX,OAAO;CACT,CAAC;CAED,OAAO;EACL,qBAAqB;EACrB,4BAA4B,WAAW;CACzC;AACF"}
1
+ {"version":3,"file":"useIsBatchingSupported.js","names":[],"sources":["../../../src/hooks/useIsBatchingSupported.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport { useEthereumContext } from '@lifi/widget-provider'\nimport { useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getQueryKey } from '../utils/queries.js'\n\nexport function useIsBatchingSupported(\n chain?: ExtendedChain,\n address?: string\n): {\n isBatchingSupported: boolean | undefined\n isBatchingSupportedLoading: boolean\n} {\n const { storageScopeKey } = useWidgetConfig()\n const sdkClient = useSDKClient()\n const { isBatchingSupported } = useEthereumContext()\n\n const enabled = Boolean(\n chain && chain.chainType === ChainType.EVM && !!address\n )\n const { data, isLoading } = useQuery({\n queryKey: [\n getQueryKey('isBatchingSupported', storageScopeKey),\n chain?.id,\n address,\n ],\n queryFn: () => {\n return (\n isBatchingSupported?.(sdkClient, {\n chainId: chain!.id,\n skipReady: true,\n }) ?? false\n )\n },\n enabled,\n staleTime: 3_600_000,\n retry: false,\n })\n\n return {\n isBatchingSupported: data,\n isBatchingSupportedLoading: enabled && isLoading,\n }\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,uBACd,OACA,SAIA;CACA,MAAM,EAAE,oBAAoB,gBAAgB;CAC5C,MAAM,YAAY,aAAa;CAC/B,MAAM,EAAE,wBAAwB,mBAAmB;CAEnD,MAAM,UAAU,QACd,SAAS,MAAM,cAAc,UAAU,OAAO,CAAC,CAAC,OAClD;CACA,MAAM,EAAE,MAAM,cAAc,SAAS;EACnC,UAAU;GACR,YAAY,uBAAuB,eAAe;GAClD,OAAO;GACP;EACF;EACA,eAAe;GACb,OACE,sBAAsB,WAAW;IAC/B,SAAS,MAAO;IAChB,WAAW;GACb,CAAC,KAAK;EAEV;EACA;EACA,WAAW;EACX,OAAO;CACT,CAAC;CAED,OAAO;EACL,qBAAqB;EACrB,4BAA4B,WAAW;CACzC;AACF"}
@@ -2,9 +2,9 @@ import { useWidgetEvents } from "./useWidgetEvents.js";
2
2
  import "../types/events.js";
3
3
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
4
4
  import { useSDKClient } from "../providers/SDKClientProvider.js";
5
- import { getQueryKey } from "../utils/queries.js";
6
5
  import { getUpdatedAction, isRouteActive, isRouteDone, isRouteFailed } from "../stores/routes/utils.js";
7
6
  import { useRouteExecutionStore, useRouteExecutionStoreContext } from "../stores/routes/RouteExecutionStore.js";
7
+ import { getQueryKey } from "../utils/queries.js";
8
8
  import { executeRoute, resumeRoute, updateRouteExecution } from "@lifi/sdk";
9
9
  import { useCallback, useEffect, useRef } from "react";
10
10
  import { useMutation, useQueryClient } from "@tanstack/react-query";
@@ -14,7 +14,7 @@ const useRouteExecution = ({ routeId, executeInBackground, onAcceptExchangeRateU
14
14
  const queryClient = useQueryClient();
15
15
  const { account } = useAccount();
16
16
  const resumedAfterMount = useRef(false);
17
- const { keyPrefix } = useWidgetConfig();
17
+ const { storageScopeKey } = useWidgetConfig();
18
18
  const sdkClient = useSDKClient();
19
19
  const emitter = useWidgetEvents();
20
20
  const routeExecutionStoreContext = useRouteExecutionStoreContext();
@@ -40,16 +40,16 @@ const useRouteExecution = ({ routeId, executeInBackground, onAcceptExchangeRateU
40
40
  if (executionCompleted || executionFailed) {
41
41
  const invalidateKeys = [
42
42
  [
43
- getQueryKey("token-balances", keyPrefix),
43
+ getQueryKey("token-balances", storageScopeKey),
44
44
  clonedUpdatedRoute.fromAddress,
45
45
  clonedUpdatedRoute.fromChainId
46
46
  ],
47
47
  [
48
- getQueryKey("token-balances", keyPrefix),
48
+ getQueryKey("token-balances", storageScopeKey),
49
49
  clonedUpdatedRoute.toAddress,
50
50
  clonedUpdatedRoute.toChainId
51
51
  ],
52
- [getQueryKey("transaction-history", keyPrefix)]
52
+ [getQueryKey("transaction-history", storageScopeKey)]
53
53
  ];
54
54
  for (const key of invalidateKeys) queryClient.invalidateQueries({
55
55
  queryKey: key,
@@ -68,7 +68,7 @@ const useRouteExecution = ({ routeId, executeInBackground, onAcceptExchangeRateU
68
68
  if (!account.isConnected) throw new Error("Account is not connected.");
69
69
  if (!routeExecution?.route) throw new Error("Execution route not found.");
70
70
  queryClient.removeQueries({
71
- queryKey: [getQueryKey("routes", keyPrefix)],
71
+ queryKey: [getQueryKey("routes", storageScopeKey)],
72
72
  exact: false
73
73
  });
74
74
  return executeRoute(sdkClient, routeExecution.route, {
@@ -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 { storageScopeKey } = 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', storageScopeKey),\n clonedUpdatedRoute.fromAddress,\n clonedUpdatedRoute.fromChainId,\n ],\n [\n getQueryKey('token-balances', storageScopeKey),\n clonedUpdatedRoute.toAddress,\n clonedUpdatedRoute.toChainId,\n ],\n [getQueryKey('transaction-history', storageScopeKey)],\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', storageScopeKey)],\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":"useRoutes.d.ts","names":[],"sources":["../../../src/hooks/useRoutes.ts"],"mappings":";;UA4CU;EACR,kBAAkB;;;;;EAKlB;;;;;EAKA;;qBAGW,cACX,iBACA,kBACA,kBAAkB,4BACjB;EACD,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,SAAS;EACT;EACA,qBAAqB,OAAO"}
1
+ {"version":3,"file":"useRoutes.d.ts","names":[],"sources":["../../../src/hooks/useRoutes.ts"],"mappings":";;UA6CU;EACR,kBAAkB;;;;;EAKlB;;;;;EAKA;;qBAGW,cACX,iBACA,kBACA,kBAAkB,4BACjB;EACD,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,SAAS;EACT;EACA,qBAAqB,OAAO"}
@@ -4,12 +4,12 @@ import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
4
4
  import { useNavigationTabsStore } from "../stores/navigationTabs/useNavigationTabsStore.js";
5
5
  import { useSwapOnly } from "./useSwapOnly.js";
6
6
  import { useSDKClient } from "../providers/SDKClientProvider.js";
7
- import { getQueryKey } from "../utils/queries.js";
8
7
  import { useFieldValues } from "../stores/form/useFieldValues.js";
9
8
  import { useIntermediateRoutesStore } from "../stores/routes/useIntermediateRoutesStore.js";
10
9
  import { useSetExecutableRoute } from "../stores/routes/useSetExecutableRoute.js";
11
10
  import { useSettings } from "../stores/settings/useSettings.js";
12
- import { isCustomReceiverBlocked } from "../utils/customReceiver.js";
11
+ import { canQuoteWithToAddress, isCustomReceiverBlocked, isSignerInvalidReceiver } from "../utils/customReceiver.js";
12
+ import { getQueryKey } from "../utils/queries.js";
13
13
  import { updateTokenInCache } from "../utils/token.js";
14
14
  import { useChain } from "./useChain.js";
15
15
  import { useDebouncedWatch } from "./useDebouncedWatch.js";
@@ -19,12 +19,12 @@ import { useToken } from "./useToken.js";
19
19
  import { ChainType, LiFiErrorCode, convertQuoteToRoute, getContractCallsQuote, getRelayerQuote, getRoutes, parseUnits } from "@lifi/sdk";
20
20
  import { useCallback, useMemo } from "react";
21
21
  import { keepPreviousData, useQuery, useQueryClient } from "@tanstack/react-query";
22
- import { useChainTypeFromAddress, useEthereumContext } from "@lifi/widget-provider";
22
+ import { useAddressForChain, useEthereumContext } from "@lifi/widget-provider";
23
23
  import { useAccount } from "@lifi/wallet-management";
24
24
  //#region src/hooks/useRoutes.ts
25
25
  const refetchTime = 6e4;
26
26
  const useRoutes = ({ observableRoute, quoteFromAddress, keepPreviousData: keepPreviousDataEnabled } = {}) => {
27
- const { mode, modeOptions, contractTool, bridges, exchanges, feeConfig, useRelayerRoutes, keyPrefix } = useWidgetConfig();
27
+ const { mode, modeOptions, contractTool, bridges, exchanges, feeConfig, useRelayerRoutes, storageScopeKey } = useWidgetConfig();
28
28
  const sdkClient = useSDKClient();
29
29
  const setExecutableRoute = useSetExecutableRoute();
30
30
  const queryClient = useQueryClient();
@@ -49,16 +49,21 @@ const useRoutes = ({ observableRoute, quoteFromAddress, keepPreviousData: keepPr
49
49
  const { chain: fromChain } = useChain(fromChainId);
50
50
  const { chain: toChain } = useChain(toChainId);
51
51
  const { enabled: enabledRefuel, fromAmount: gasRecommendationFromAmount } = useGasRefuel();
52
- const { getChainTypeFromAddress } = useChainTypeFromAddress();
52
+ const { isAddressForChain } = useAddressForChain();
53
53
  const { isGaslessStep, disableMessageSigning } = useEthereumContext();
54
54
  const { account } = useAccount({ chainType: fromChain?.chainType });
55
55
  const { isBatchingSupported, isBatchingSupportedLoading } = useIsBatchingSupported(fromChain, account.address);
56
56
  const hasAmount = mode === "limit" ? Number(fromTokenAmount) > 0 && Number(toTokenAmount) > 0 : Number(fromTokenAmount) > 0 || Number(toTokenAmount) > 0;
57
57
  const customType = mode === "custom" ? modeOptions?.custom?.type : void 0;
58
58
  const contractCallQuoteEnabled = mode === "custom" && Boolean(contractCalls?.length) ? Boolean(account.address) : mode !== "custom" || customType === "deposit";
59
- const effectiveFromAddress = account.address ?? quoteFromAddress;
60
- const hasToAddressAndChainTypeSatisfied = !!toChain && !!toAddress && getChainTypeFromAddress(toAddress) === toChain.chainType;
61
- const isToAddressSatisfied = toAddress ? hasToAddressAndChainTypeSatisfied : true;
59
+ const effectiveFromAddress = isSignerInvalidReceiver({
60
+ signerAddress: account.address,
61
+ toAddress,
62
+ fromChain,
63
+ toChain,
64
+ isAddressForChain
65
+ }) ? quoteFromAddress : account.address ?? quoteFromAddress;
66
+ const isToAddressSatisfied = canQuoteWithToAddress(toAddress, toChain, isAddressForChain);
62
67
  const customReceiverBlocked = isCustomReceiverBlocked({
63
68
  fromChainType: fromChain?.chainType,
64
69
  toChainType: toChain?.chainType,
@@ -71,7 +76,7 @@ const useRoutes = ({ observableRoute, quoteFromAddress, keepPreviousData: keepPr
71
76
  const allowSwitchChain = sdkClient.config?.routeOptions?.allowSwitchChain;
72
77
  const isEnabled = Boolean(Number(fromChain?.id)) && Boolean(Number(toChain?.id)) && Boolean(fromToken?.address) && Boolean(toToken?.address) && !Number.isNaN(slippage) && hasAmount && isToAddressSatisfied && !customReceiverBlocked && contractCallQuoteEnabled && !isBatchingSupportedLoading;
73
78
  const queryKey = useMemo(() => [
74
- getQueryKey("routes", keyPrefix),
79
+ getQueryKey("routes", storageScopeKey),
75
80
  effectiveFromAddress,
76
81
  fromChain?.id,
77
82
  fromToken?.address,
@@ -100,7 +105,7 @@ const useRoutes = ({ observableRoute, quoteFromAddress, keepPreviousData: keepPr
100
105
  isPrivate,
101
106
  observableRoute?.id
102
107
  ], [
103
- keyPrefix,
108
+ storageScopeKey,
104
109
  effectiveFromAddress,
105
110
  fromChain?.id,
106
111
  fromToken?.address,
@@ -247,13 +252,13 @@ const useRoutes = ({ observableRoute, quoteFromAddress, keepPreviousData: keepPr
247
252
  if (routesResult?.routes[0] && fromAddress) {
248
253
  const { fromToken, toToken } = routesResult.routes[0];
249
254
  [fromToken, toToken].forEach((token) => {
250
- queryClient.setQueriesData({ queryKey: [getQueryKey("tokens", keyPrefix)] }, (data) => updateTokenInCache(data, token));
255
+ queryClient.setQueriesData({ queryKey: [getQueryKey("tokens", storageScopeKey)] }, (data) => updateTokenInCache(data, token));
251
256
  queryClient.setQueriesData({
252
- queryKey: [getQueryKey("tokens-search", keyPrefix)],
257
+ queryKey: [getQueryKey("tokens-search", storageScopeKey)],
253
258
  exact: false
254
259
  }, (data) => updateTokenInCache(data, token));
255
260
  queryClient.setQueriesData({ queryKey: [
256
- getQueryKey("token-balances", keyPrefix),
261
+ getQueryKey("token-balances", storageScopeKey),
257
262
  fromAddress,
258
263
  token.chainId
259
264
  ] }, (data) => {