@lifi/widget 4.8.0 → 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 (115) hide show
  1. package/dist/esm/components/AmountInputCard/AmountInputCardPair.js +5 -2
  2. package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -1
  3. package/dist/esm/components/SelectChainAndToken.js +5 -2
  4. package/dist/esm/components/SelectChainAndToken.js.map +1 -1
  5. package/dist/esm/components/SendToWallet/SendToWalletButton.js +5 -4
  6. package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
  7. package/dist/esm/components/TokenList/useTokenSelect.d.ts.map +1 -1
  8. package/dist/esm/components/TokenList/useTokenSelect.js +10 -0
  9. package/dist/esm/components/TokenList/useTokenSelect.js.map +1 -1
  10. package/dist/esm/config/constants.js.map +1 -1
  11. package/dist/esm/config/version.d.ts +1 -1
  12. package/dist/esm/config/version.js +1 -1
  13. package/dist/esm/config/version.js.map +1 -1
  14. package/dist/esm/hooks/useAccountsBalancesData.js +5 -2
  15. package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
  16. package/dist/esm/hooks/useAddressValidation.d.ts +3 -2
  17. package/dist/esm/hooks/useAddressValidation.d.ts.map +1 -1
  18. package/dist/esm/hooks/useAddressValidation.js +48 -21
  19. package/dist/esm/hooks/useAddressValidation.js.map +1 -1
  20. package/dist/esm/hooks/useGasRefuel.js +4 -1
  21. package/dist/esm/hooks/useGasRefuel.js.map +1 -1
  22. package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
  23. package/dist/esm/hooks/useRoutes.js +11 -6
  24. package/dist/esm/hooks/useRoutes.js.map +1 -1
  25. package/dist/esm/hooks/useToAddressAutoPopulate.js +6 -8
  26. package/dist/esm/hooks/useToAddressAutoPopulate.js.map +1 -1
  27. package/dist/esm/hooks/useToAddressRequirements.d.ts +3 -2
  28. package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
  29. package/dist/esm/hooks/useToAddressRequirements.js +8 -7
  30. package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
  31. package/dist/esm/hooks/useToAddressReset.js +6 -3
  32. package/dist/esm/hooks/useToAddressReset.js.map +1 -1
  33. package/dist/esm/hooks/useTokenBalance.js +2 -1
  34. package/dist/esm/hooks/useTokenBalance.js.map +1 -1
  35. package/dist/esm/hooks/useTokens.js +1 -1
  36. package/dist/esm/i18n/bn.json +2 -1
  37. package/dist/esm/i18n/de.json +2 -1
  38. package/dist/esm/i18n/en.json +2 -1
  39. package/dist/esm/i18n/es.json +2 -1
  40. package/dist/esm/i18n/fr.json +2 -1
  41. package/dist/esm/i18n/hi.json +2 -1
  42. package/dist/esm/i18n/id.json +2 -1
  43. package/dist/esm/i18n/it.json +2 -1
  44. package/dist/esm/i18n/ja.json +2 -1
  45. package/dist/esm/i18n/ko.json +2 -1
  46. package/dist/esm/i18n/pl.json +2 -1
  47. package/dist/esm/i18n/pt.json +2 -1
  48. package/dist/esm/i18n/th.json +2 -1
  49. package/dist/esm/i18n/tr.json +2 -1
  50. package/dist/esm/i18n/uk.json +2 -1
  51. package/dist/esm/i18n/vi.json +2 -1
  52. package/dist/esm/i18n/zh.json +2 -1
  53. package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js +7 -4
  54. package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js.map +1 -1
  55. package/dist/esm/pages/SendToWallet/BookmarksPage.js +35 -31
  56. package/dist/esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
  57. package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js +4 -3
  58. package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
  59. package/dist/esm/pages/SendToWallet/RecentWalletsPage.js +43 -39
  60. package/dist/esm/pages/SendToWallet/RecentWalletsPage.js.map +1 -1
  61. package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js +32 -26
  62. package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js.map +1 -1
  63. package/dist/esm/pages/SendToWallet/SendToWalletPage.js +5 -10
  64. package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
  65. package/dist/esm/providers/WalletProvider/WalletProvider.d.ts.map +1 -1
  66. package/dist/esm/providers/WalletProvider/WalletProvider.js +14 -2
  67. package/dist/esm/providers/WalletProvider/WalletProvider.js.map +1 -1
  68. package/dist/esm/providers/WidgetProvider/WidgetProvider.d.ts.map +1 -1
  69. package/dist/esm/providers/WidgetProvider/WidgetProvider.js +10 -14
  70. package/dist/esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
  71. package/dist/esm/stores/bookmarks/types.d.ts +3 -0
  72. package/dist/esm/stores/bookmarks/types.d.ts.map +1 -1
  73. package/dist/esm/stores/chains/ChainOrderStore.d.ts.map +1 -1
  74. package/dist/esm/stores/chains/ChainOrderStore.js +4 -1
  75. package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
  76. package/dist/esm/stores/form/FormStore.js +3 -2
  77. package/dist/esm/stores/form/FormStore.js.map +1 -1
  78. package/dist/esm/stores/form/URLSearchParamsBuilder.js +7 -3
  79. package/dist/esm/stores/form/URLSearchParamsBuilder.js.map +1 -1
  80. package/dist/esm/stores/form/getDefaultValuesFromQueryString.js +4 -1
  81. package/dist/esm/stores/form/getDefaultValuesFromQueryString.js.map +1 -1
  82. package/dist/esm/utils/chainType.js +32 -1
  83. package/dist/esm/utils/chainType.js.map +1 -1
  84. package/dist/esm/utils/customReceiver.js +6 -1
  85. package/dist/esm/utils/customReceiver.js.map +1 -1
  86. package/package.json +7 -7
  87. package/src/components/AmountInputCard/AmountInputCardPair.tsx +6 -2
  88. package/src/components/SelectChainAndToken.tsx +5 -1
  89. package/src/components/SendToWallet/SendToWalletButton.tsx +13 -8
  90. package/src/components/TokenList/useTokenSelect.ts +15 -0
  91. package/src/config/constants.ts +3 -0
  92. package/src/config/version.ts +1 -1
  93. package/src/hooks/useAccountsBalancesData.ts +6 -2
  94. package/src/hooks/useAddressValidation.ts +87 -32
  95. package/src/hooks/useGasRefuel.ts +11 -1
  96. package/src/hooks/useRoutes.ts +23 -18
  97. package/src/hooks/useToAddressAutoPopulate.ts +13 -17
  98. package/src/hooks/useToAddressRequirements.ts +19 -4
  99. package/src/hooks/useToAddressReset.ts +13 -4
  100. package/src/hooks/useTokenBalance.ts +6 -1
  101. package/src/pages/SendToWallet/BookmarkAddressSheet.tsx +5 -1
  102. package/src/pages/SendToWallet/BookmarksPage.tsx +42 -52
  103. package/src/pages/SendToWallet/ConnectedWalletsPage.tsx +4 -14
  104. package/src/pages/SendToWallet/RecentWalletsPage.tsx +59 -66
  105. package/src/pages/SendToWallet/SendToConfiguredWalletPage.tsx +45 -50
  106. package/src/pages/SendToWallet/SendToWalletPage.tsx +4 -16
  107. package/src/providers/WalletProvider/WalletProvider.tsx +28 -3
  108. package/src/providers/WidgetProvider/WidgetProvider.tsx +20 -19
  109. package/src/stores/bookmarks/types.ts +3 -0
  110. package/src/stores/chains/ChainOrderStore.tsx +4 -1
  111. package/src/stores/form/FormStore.tsx +2 -0
  112. package/src/stores/form/URLSearchParamsBuilder.tsx +4 -2
  113. package/src/stores/form/getDefaultValuesFromQueryString.ts +19 -0
  114. package/src/utils/chainType.ts +73 -1
  115. package/src/utils/customReceiver.ts +36 -0
@@ -1,4 +1,6 @@
1
+ import { isDestinationAllowedAsSource } from "../../utils/chainType.js";
1
2
  import { useWidgetConfig } from "../../providers/WidgetProvider/WidgetProvider.js";
3
+ import { useFieldValues } from "../../stores/form/useFieldValues.js";
2
4
  import { CardContainer } from "./AmountInputCard.style.js";
3
5
  import { LimitPriceCard } from "../LimitPriceCard/LimitPriceCard.js";
4
6
  import { SwapButton } from "../SwapButton/SwapButton.js";
@@ -7,8 +9,9 @@ import { SendAmountCard } from "./SendAmountCard.js";
7
9
  import { jsx, jsxs } from "react/jsx-runtime";
8
10
  //#region src/components/AmountInputCard/AmountInputCardPair.tsx
9
11
  const AmountInputCardPair = (props) => {
10
- const { mode } = useWidgetConfig();
11
- const showSwapButton = mode !== "refuel";
12
+ const { mode, chains } = useWidgetConfig();
13
+ const [toChainId] = useFieldValues("toChain");
14
+ const showSwapButton = mode !== "refuel" && isDestinationAllowedAsSource(toChainId, chains);
12
15
  return /* @__PURE__ */ jsxs(CardContainer, {
13
16
  ...props,
14
17
  children: [
@@ -1 +1 @@
1
- {"version":3,"file":"AmountInputCardPair.js","names":[],"sources":["../../../../src/components/AmountInputCard/AmountInputCardPair.tsx"],"sourcesContent":["import type { BoxProps } from '@mui/material'\nimport type React from 'react'\nimport type { JSX } from 'react'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { LimitPriceCard } from '../LimitPriceCard/LimitPriceCard.js'\nimport { SwapButton } from '../SwapButton/SwapButton.js'\nimport { CardContainer } from './AmountInputCard.style.js'\nimport { ReceiveAmountCard } from './ReceiveAmountCard.js'\nimport { SendAmountCard } from './SendAmountCard.js'\n\nexport const AmountInputCardPair: React.FC<BoxProps> = (props): JSX.Element => {\n // Refuel's destination is fixed to native gas, so reversing from/to is\n // meaningless — hide the swap button (and the notch mask it sits in).\n const { mode } = useWidgetConfig()\n const showSwapButton = mode !== 'refuel'\n\n return (\n <CardContainer {...props}>\n {mode === 'limit' ? <LimitPriceCard sx={{ marginBottom: 1 }} /> : null}\n <SendAmountCard mask={showSwapButton} />\n <SwapButton sx={{ visibility: showSwapButton ? 'visible' : 'hidden' }} />\n <ReceiveAmountCard mask={showSwapButton} />\n </CardContainer>\n )\n}\n"],"mappings":";;;;;;;;AAUA,MAAa,uBAA2C,UAAuB;CAG7E,MAAM,EAAE,SAAS,gBAAgB;CACjC,MAAM,iBAAiB,SAAS;CAEhC,OACE,qBAAC,eAAD;EAAe,GAAI;EAAnB,UAAA;GACG,SAAS,UAAU,oBAAC,gBAAD,EAAgB,IAAI,EAAE,cAAc,EAAE,EAAI,CAAA,IAAI;GAClE,oBAAC,gBAAD,EAAgB,MAAM,eAAiB,CAAA;GACvC,oBAAC,YAAD,EAAY,IAAI,EAAE,YAAY,iBAAiB,YAAY,SAAS,EAAI,CAAA;GACxE,oBAAC,mBAAD,EAAmB,MAAM,eAAiB,CAAA;EAC7B;;AAEnB"}
1
+ {"version":3,"file":"AmountInputCardPair.js","names":[],"sources":["../../../../src/components/AmountInputCard/AmountInputCardPair.tsx"],"sourcesContent":["import type { BoxProps } from '@mui/material'\nimport type React from 'react'\nimport type { JSX } from 'react'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { isDestinationAllowedAsSource } from '../../utils/chainType.js'\nimport { LimitPriceCard } from '../LimitPriceCard/LimitPriceCard.js'\nimport { SwapButton } from '../SwapButton/SwapButton.js'\nimport { CardContainer } from './AmountInputCard.style.js'\nimport { ReceiveAmountCard } from './ReceiveAmountCard.js'\nimport { SendAmountCard } from './SendAmountCard.js'\n\nexport const AmountInputCardPair: React.FC<BoxProps> = (props): JSX.Element => {\n // Refuel's destination is fixed to native gas, so reversing from/to is\n // meaningless — hide the swap button (and the notch mask it sits in).\n const { mode, chains } = useWidgetConfig()\n const [toChainId] = useFieldValues('toChain')\n const showSwapButton =\n mode !== 'refuel' && isDestinationAllowedAsSource(toChainId, chains)\n\n return (\n <CardContainer {...props}>\n {mode === 'limit' ? <LimitPriceCard sx={{ marginBottom: 1 }} /> : null}\n <SendAmountCard mask={showSwapButton} />\n <SwapButton sx={{ visibility: showSwapButton ? 'visible' : 'hidden' }} />\n <ReceiveAmountCard mask={showSwapButton} />\n </CardContainer>\n )\n}\n"],"mappings":";;;;;;;;;;AAYA,MAAa,uBAA2C,UAAuB;CAG7E,MAAM,EAAE,MAAM,WAAW,gBAAgB;CACzC,MAAM,CAAC,aAAa,eAAe,SAAS;CAC5C,MAAM,iBACJ,SAAS,YAAY,6BAA6B,WAAW,MAAM;CAErE,OACE,qBAAC,eAAD;EAAe,GAAI;EAAnB,UAAA;GACG,SAAS,UAAU,oBAAC,gBAAD,EAAgB,IAAI,EAAE,cAAc,EAAE,EAAI,CAAA,IAAI;GAClE,oBAAC,gBAAD,EAAgB,MAAM,eAAiB,CAAA;GACvC,oBAAC,YAAD,EAAY,IAAI,EAAE,YAAY,iBAAiB,YAAY,SAAS,EAAI,CAAA;GACxE,oBAAC,mBAAD,EAAmB,MAAM,eAAiB,CAAA;EAC7B;;AAEnB"}
@@ -1,4 +1,6 @@
1
+ import { isDestinationAllowedAsSource } from "../utils/chainType.js";
1
2
  import { useWidgetConfig } from "../providers/WidgetProvider/WidgetProvider.js";
3
+ import { useFieldValues } from "../stores/form/useFieldValues.js";
2
4
  import { ReverseTokensButtonEmpty } from "./ReverseTokensButton/ReverseTokensButton.style.js";
3
5
  import { ReverseTokensButton } from "./ReverseTokensButton/ReverseTokensButton.js";
4
6
  import { SelectTokenButton } from "./SelectTokenButton/SelectTokenButton.js";
@@ -6,8 +8,9 @@ import { Box } from "@mui/material";
6
8
  import { jsx, jsxs } from "react/jsx-runtime";
7
9
  //#region src/components/SelectChainAndToken.tsx
8
10
  const SelectChainAndToken = (props) => {
9
- const { disabledUI, hiddenUI, mode } = useWidgetConfig();
10
- const hiddenReverse = mode === "refuel" || disabledUI?.fromToken || disabledUI?.toToken || hiddenUI?.fromToken || hiddenUI?.toToken || hiddenUI?.reverseTokensButton;
11
+ const { disabledUI, hiddenUI, mode, chains } = useWidgetConfig();
12
+ const [toChainId] = useFieldValues("toChain");
13
+ const hiddenReverse = mode === "refuel" || !isDestinationAllowedAsSource(toChainId, chains) || disabledUI?.fromToken || disabledUI?.toToken || hiddenUI?.fromToken || hiddenUI?.toToken || hiddenUI?.reverseTokensButton;
11
14
  const hiddenFromToken = hiddenUI?.fromToken;
12
15
  const hiddenToToken = mode === "custom" || hiddenUI?.toToken;
13
16
  const showReverseButton = !hiddenToToken && !hiddenFromToken;
@@ -1 +1 @@
1
- {"version":3,"file":"SelectChainAndToken.js","names":[],"sources":["../../../src/components/SelectChainAndToken.tsx"],"sourcesContent":["import type { BoxProps } from '@mui/material'\nimport { Box } from '@mui/material'\nimport { ReverseTokensButton } from '../components/ReverseTokensButton/ReverseTokensButton.js'\nimport { SelectTokenButton } from '../components/SelectTokenButton/SelectTokenButton.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { ReverseTokensButtonEmpty } from './ReverseTokensButton/ReverseTokensButton.style.js'\n\nexport const SelectChainAndToken: React.FC<BoxProps> = (props) => {\n const { disabledUI, hiddenUI, mode } = useWidgetConfig()\n\n const hiddenReverse =\n mode === 'refuel' ||\n disabledUI?.fromToken ||\n disabledUI?.toToken ||\n hiddenUI?.fromToken ||\n hiddenUI?.toToken ||\n hiddenUI?.reverseTokensButton\n\n const hiddenFromToken = hiddenUI?.fromToken\n const hiddenToToken = mode === 'custom' || hiddenUI?.toToken\n\n const showReverseButton = !hiddenToToken && !hiddenFromToken\n\n return (\n <Box {...props} sx={{ display: 'flex', ...props.sx }}>\n {!hiddenFromToken ? (\n <SelectTokenButton formType=\"from\" hiddenReverse={hiddenReverse} />\n ) : null}\n {showReverseButton ? (\n !hiddenReverse ? (\n <ReverseTokensButton />\n ) : (\n <ReverseTokensButtonEmpty />\n )\n ) : null}\n {!hiddenToToken ? (\n <SelectTokenButton formType=\"to\" hiddenReverse={hiddenReverse} />\n ) : null}\n </Box>\n )\n}\n"],"mappings":";;;;;;;AAOA,MAAa,uBAA2C,UAAU;CAChE,MAAM,EAAE,YAAY,UAAU,SAAS,gBAAgB;CAEvD,MAAM,gBACJ,SAAS,YACT,YAAY,aACZ,YAAY,WACZ,UAAU,aACV,UAAU,WACV,UAAU;CAEZ,MAAM,kBAAkB,UAAU;CAClC,MAAM,gBAAgB,SAAS,YAAY,UAAU;CAErD,MAAM,oBAAoB,CAAC,iBAAiB,CAAC;CAE7C,OACE,qBAAC,KAAD;EAAK,GAAI;EAAO,IAAI;GAAE,SAAS;GAAQ,GAAG,MAAM;EAAG;EAAnD,UAAA;GACG,CAAC,kBACA,oBAAC,mBAAD;IAAmB,UAAS;IAAsB;GAAgB,CAAA,IAChE;GACH,oBACC,CAAC,gBACC,oBAAC,qBAAD,CAAsB,CAAA,IAEtB,oBAAC,0BAAD,CAA2B,CAAA,IAE3B;GACH,CAAC,gBACA,oBAAC,mBAAD;IAAmB,UAAS;IAAoB;GAAgB,CAAA,IAC9D;EACD;;AAET"}
1
+ {"version":3,"file":"SelectChainAndToken.js","names":[],"sources":["../../../src/components/SelectChainAndToken.tsx"],"sourcesContent":["import type { BoxProps } from '@mui/material'\nimport { Box } from '@mui/material'\nimport { ReverseTokensButton } from '../components/ReverseTokensButton/ReverseTokensButton.js'\nimport { SelectTokenButton } from '../components/SelectTokenButton/SelectTokenButton.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { isDestinationAllowedAsSource } from '../utils/chainType.js'\nimport { ReverseTokensButtonEmpty } from './ReverseTokensButton/ReverseTokensButton.style.js'\n\nexport const SelectChainAndToken: React.FC<BoxProps> = (props) => {\n const { disabledUI, hiddenUI, mode, chains } = useWidgetConfig()\n const [toChainId] = useFieldValues('toChain')\n\n const hiddenReverse =\n mode === 'refuel' ||\n !isDestinationAllowedAsSource(toChainId, chains) ||\n disabledUI?.fromToken ||\n disabledUI?.toToken ||\n hiddenUI?.fromToken ||\n hiddenUI?.toToken ||\n hiddenUI?.reverseTokensButton\n\n const hiddenFromToken = hiddenUI?.fromToken\n const hiddenToToken = mode === 'custom' || hiddenUI?.toToken\n\n const showReverseButton = !hiddenToToken && !hiddenFromToken\n\n return (\n <Box {...props} sx={{ display: 'flex', ...props.sx }}>\n {!hiddenFromToken ? (\n <SelectTokenButton formType=\"from\" hiddenReverse={hiddenReverse} />\n ) : null}\n {showReverseButton ? (\n !hiddenReverse ? (\n <ReverseTokensButton />\n ) : (\n <ReverseTokensButtonEmpty />\n )\n ) : null}\n {!hiddenToToken ? (\n <SelectTokenButton formType=\"to\" hiddenReverse={hiddenReverse} />\n ) : null}\n </Box>\n )\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,uBAA2C,UAAU;CAChE,MAAM,EAAE,YAAY,UAAU,MAAM,WAAW,gBAAgB;CAC/D,MAAM,CAAC,aAAa,eAAe,SAAS;CAE5C,MAAM,gBACJ,SAAS,YACT,CAAC,6BAA6B,WAAW,MAAM,KAC/C,YAAY,aACZ,YAAY,WACZ,UAAU,aACV,UAAU,WACV,UAAU;CAEZ,MAAM,kBAAkB,UAAU;CAClC,MAAM,gBAAgB,SAAS,YAAY,UAAU;CAErD,MAAM,oBAAoB,CAAC,iBAAiB,CAAC;CAE7C,OACE,qBAAC,KAAD;EAAK,GAAI;EAAO,IAAI;GAAE,SAAS;GAAQ,GAAG,MAAM;EAAG;EAAnD,UAAA;GACG,CAAC,kBACA,oBAAC,mBAAD;IAAmB,UAAS;IAAsB;GAAgB,CAAA,IAChE;GACH,oBACC,CAAC,gBACC,oBAAC,qBAAD,CAAsB,CAAA,IAEtB,oBAAC,0BAAD,CAA2B,CAAA,IAE3B;GACH,CAAC,gBACA,oBAAC,mBAAD;IAAmB,UAAS;IAAoB;GAAgB,CAAA,IAC9D;EACD;;AAET"}
@@ -1,3 +1,4 @@
1
+ import { defaultChainIdsByType } from "../../utils/chainType.js";
1
2
  import { useWidgetConfig } from "../../providers/WidgetProvider/WidgetProvider.js";
2
3
  import { navigationRoutes } from "../../utils/navigationRoutes.js";
3
4
  import { useBookmarkActions } from "../../stores/bookmarks/useBookmarkActions.js";
@@ -5,7 +6,6 @@ import { useBookmarks } from "../../stores/bookmarks/useBookmarks.js";
5
6
  import { useFieldActions } from "../../stores/form/useFieldActions.js";
6
7
  import { useFieldValues } from "../../stores/form/useFieldValues.js";
7
8
  import { Card as Card$1 } from "../Card/Card.js";
8
- import { defaultChainIdsByType } from "../../utils/chainType.js";
9
9
  import { useToAddressRequirements } from "../../hooks/useToAddressRequirements.js";
10
10
  import { CardIconButton } from "../Card/CardIconButton.js";
11
11
  import { shortenAddress } from "../../utils/wallet.js";
@@ -31,14 +31,15 @@ const SendToWalletButton = ({ onEditAddress, onClearAddress, requireAddress, ...
31
31
  const { selectedBookmark } = useBookmarks();
32
32
  const { setSelectedBookmark } = useBookmarkActions();
33
33
  const { accounts } = useAccount();
34
- const { getChainTypeFromAddress } = useChainTypeFromAddress();
34
+ const { getChainFromAddress } = useChainTypeFromAddress();
35
35
  const { requiredToAddress } = useToAddressRequirements();
36
36
  const disabledToAddress = disabledUI?.toAddress;
37
37
  const hiddenToAddress = hiddenUI?.toAddress;
38
38
  const address = toAddressFieldValue ? shortenAddress(toAddressFieldValue) : t("sendToWallet.enterAddress", { context: "short" });
39
39
  const matchingConnectedAccount = accounts.find((account) => account.address === toAddressFieldValue);
40
- const chainType = !matchingConnectedAccount ? selectedBookmark?.chainType || (toAddressFieldValue ? getChainTypeFromAddress(toAddressFieldValue) : void 0) : void 0;
41
- const chainId = toChainId && toTokenAddress ? toChainId : matchingConnectedAccount ? matchingConnectedAccount.chainId : chainType ? defaultChainIdsByType[chainType] : void 0;
40
+ const detectedChain = !matchingConnectedAccount && selectedBookmark?.chainId === void 0 && toAddressFieldValue ? getChainFromAddress(toAddressFieldValue) : void 0;
41
+ const chainType = !matchingConnectedAccount ? selectedBookmark?.chainType || detectedChain?.chainType : void 0;
42
+ const chainId = toChainId && toTokenAddress ? toChainId : matchingConnectedAccount ? matchingConnectedAccount.chainId : selectedBookmark?.chainId ?? detectedChain?.chainId ?? (chainType ? defaultChainIdsByType[chainType] : void 0);
42
43
  const isConnectedAccount = selectedBookmark?.isConnectedAccount && matchingConnectedAccount?.isConnected;
43
44
  const connectedAccountName = matchingConnectedAccount?.connector?.name;
44
45
  const bookmarkName = selectedBookmark?.name;
@@ -1 +1 @@
1
- {"version":3,"file":"SendToWalletButton.js","names":["Card"],"sources":["../../../../src/components/SendToWallet/SendToWalletButton.tsx"],"sourcesContent":["import { useAccount } from '@lifi/wallet-management'\nimport { useChainTypeFromAddress } from '@lifi/widget-provider'\nimport CloseRounded from '@mui/icons-material/CloseRounded'\nimport WarningRounded from '@mui/icons-material/WarningRounded'\nimport { Box, Collapse } from '@mui/material'\nimport { useNavigate } from '@tanstack/react-router'\nimport { type MouseEventHandler, useEffect, useRef } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js'\nimport { useBookmarks } from '../../stores/bookmarks/useBookmarks.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { defaultChainIdsByType } from '../../utils/chainType.js'\nimport { navigationRoutes } from '../../utils/navigationRoutes.js'\nimport { shortenAddress } from '../../utils/wallet.js'\nimport { AccountAvatar } from '../Avatar/AccountAvatar.js'\nimport type { CardProps } from '../Card/Card.js'\nimport { Card } from '../Card/Card.js'\nimport { CardIconButton } from '../Card/CardIconButton.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport {\n SendToWalletCardHeader,\n SendToWalletCardTitleRow,\n SendToWalletRequiredLabel,\n SendToWalletRequiredLabelText,\n} from './SendToWalletButton.style.js'\n\nexport const SendToWalletButton: React.FC<\n CardProps & {\n onEditAddress?: (() => void) | null\n onClearAddress?: () => void\n // Keep the card visible (and flag it required when empty) even when the\n // widget's own toAddress requirement is off, e.g. a user-settable checkout\n // recipient that must be filled before continuing.\n requireAddress?: boolean\n }\n> = ({ onEditAddress, onClearAddress, requireAddress, ...props }) => {\n const { t } = useTranslation()\n const navigate = useNavigate()\n const { disabledUI, hiddenUI, toAddress, toAddresses, mode, modeOptions } =\n useWidgetConfig()\n const [toAddressFieldValue, toChainId, toTokenAddress] = useFieldValues(\n 'toAddress',\n 'toChain',\n 'toToken'\n )\n const { setFieldValue } = useFieldActions()\n const { selectedBookmark } = useBookmarks()\n const { setSelectedBookmark } = useBookmarkActions()\n const { accounts } = useAccount()\n const { getChainTypeFromAddress } = useChainTypeFromAddress()\n const { requiredToAddress } = useToAddressRequirements()\n const disabledToAddress = disabledUI?.toAddress\n const hiddenToAddress = hiddenUI?.toAddress\n\n const address = toAddressFieldValue\n ? shortenAddress(toAddressFieldValue)\n : t('sendToWallet.enterAddress', {\n context: 'short',\n })\n\n const matchingConnectedAccount = accounts.find(\n (account) => account.address === toAddressFieldValue\n )\n\n const chainType = !matchingConnectedAccount\n ? selectedBookmark?.chainType ||\n (toAddressFieldValue\n ? getChainTypeFromAddress(toAddressFieldValue)\n : undefined)\n : undefined\n\n const chainId =\n toChainId && toTokenAddress\n ? toChainId\n : matchingConnectedAccount\n ? matchingConnectedAccount.chainId\n : chainType\n ? defaultChainIdsByType[chainType]\n : undefined\n\n const isConnectedAccount =\n selectedBookmark?.isConnectedAccount &&\n matchingConnectedAccount?.isConnected\n const connectedAccountName = matchingConnectedAccount?.connector?.name\n const bookmarkName = selectedBookmark?.name\n\n const headerTitle = isConnectedAccount\n ? connectedAccountName || address\n : bookmarkName || connectedAccountName || address\n\n const headerSubheader =\n isConnectedAccount || bookmarkName || connectedAccountName ? address : null\n\n const disabledForChanges = Boolean(toAddressFieldValue) && disabledToAddress\n\n // `onEditAddress === null` renders the card read-only (consumer-controlled,\n // e.g. a fixed checkout recipient); a function overrides the default route nav.\n const readOnly = onEditAddress === null || disabledForChanges\n\n const handleOnClick = () => {\n if (onEditAddress !== undefined) {\n onEditAddress?.()\n return\n }\n navigate({\n to: toAddresses?.length\n ? navigationRoutes.configuredWallets\n : navigationRoutes.sendToWallet,\n })\n }\n\n const clearSelectedBookmark: MouseEventHandler<HTMLButtonElement> = (e) => {\n e.stopPropagation()\n if (onClearAddress) {\n onClearAddress()\n return\n }\n setFieldValue('toAddress', '', { isTouched: true })\n setSelectedBookmark()\n }\n\n // The collapse opens instantly on first page load/component mount when there is an address to display\n // After which it needs an animated transition for open and closing.\n // collapseTransitionTime is used specify the transition time for opening and closing\n const collapseTransitionTime = useRef(0)\n\n // Timeout is needed here to push the collapseTransitionTime update to the back of the event loop so that it doesn't fired too quickly\n useEffect(() => {\n const timeout = setTimeout(() => {\n collapseTransitionTime.current = 225\n }, 0)\n return () => clearTimeout(timeout)\n }, [])\n\n const addressRequired = requireAddress || requiredToAddress\n const isOpenCollapse =\n !hiddenToAddress && (addressRequired || !!toAddressFieldValue)\n\n const title =\n mode === 'custom' && modeOptions?.custom?.type === 'deposit'\n ? t('header.depositTo')\n : t('header.sendToWallet')\n\n return (\n <Collapse\n timeout={collapseTransitionTime.current as number}\n in={isOpenCollapse}\n mountOnEnter\n unmountOnExit\n >\n <Card\n role=\"button\"\n onClick={readOnly ? undefined : handleOnClick}\n sx={{ width: '100%', ...props.sx }}\n >\n <SendToWalletCardTitleRow>\n <CardTitle sx={{ p: 0 }}>{title}</CardTitle>\n {addressRequired && !toAddressFieldValue ? (\n <SendToWalletRequiredLabel variant=\"warning\">\n <WarningRounded sx={{ fontSize: 14 }} />\n <SendToWalletRequiredLabelText type=\"icon\">\n {t('sendToWallet.required')}\n </SendToWalletRequiredLabelText>\n </SendToWalletRequiredLabel>\n ) : null}\n </SendToWalletCardTitleRow>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <SendToWalletCardHeader\n avatar={\n <AccountAvatar\n chainId={chainId}\n account={matchingConnectedAccount}\n toAddress={toAddress}\n empty={!toAddressFieldValue}\n />\n }\n title={headerTitle}\n subheader={headerSubheader}\n selected={!!toAddressFieldValue || disabledToAddress}\n action={\n toAddressFieldValue && !readOnly ? (\n <CardIconButton onClick={clearSelectedBookmark} size=\"small\">\n <CloseRounded fontSize=\"inherit\" />\n </CardIconButton>\n ) : null\n }\n />\n </Box>\n </Card>\n </Collapse>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SendToWalletButton.js","names":["Card"],"sources":["../../../../src/components/SendToWallet/SendToWalletButton.tsx"],"sourcesContent":["import { useAccount } from '@lifi/wallet-management'\nimport { useChainTypeFromAddress } from '@lifi/widget-provider'\nimport CloseRounded from '@mui/icons-material/CloseRounded'\nimport WarningRounded from '@mui/icons-material/WarningRounded'\nimport { Box, Collapse } from '@mui/material'\nimport { useNavigate } from '@tanstack/react-router'\nimport { type MouseEventHandler, useEffect, useRef } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js'\nimport { useBookmarks } from '../../stores/bookmarks/useBookmarks.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { defaultChainIdsByType } from '../../utils/chainType.js'\nimport { navigationRoutes } from '../../utils/navigationRoutes.js'\nimport { shortenAddress } from '../../utils/wallet.js'\nimport { AccountAvatar } from '../Avatar/AccountAvatar.js'\nimport type { CardProps } from '../Card/Card.js'\nimport { Card } from '../Card/Card.js'\nimport { CardIconButton } from '../Card/CardIconButton.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport {\n SendToWalletCardHeader,\n SendToWalletCardTitleRow,\n SendToWalletRequiredLabel,\n SendToWalletRequiredLabelText,\n} from './SendToWalletButton.style.js'\n\nexport const SendToWalletButton: React.FC<\n CardProps & {\n onEditAddress?: (() => void) | null\n onClearAddress?: () => void\n // Keep the card visible (and flag it required when empty) even when the\n // widget's own toAddress requirement is off, e.g. a user-settable checkout\n // recipient that must be filled before continuing.\n requireAddress?: boolean\n }\n> = ({ onEditAddress, onClearAddress, requireAddress, ...props }) => {\n const { t } = useTranslation()\n const navigate = useNavigate()\n const { disabledUI, hiddenUI, toAddress, toAddresses, mode, modeOptions } =\n useWidgetConfig()\n const [toAddressFieldValue, toChainId, toTokenAddress] = useFieldValues(\n 'toAddress',\n 'toChain',\n 'toToken'\n )\n const { setFieldValue } = useFieldActions()\n const { selectedBookmark } = useBookmarks()\n const { setSelectedBookmark } = useBookmarkActions()\n const { accounts } = useAccount()\n const { getChainFromAddress } = useChainTypeFromAddress()\n const { requiredToAddress } = useToAddressRequirements()\n const disabledToAddress = disabledUI?.toAddress\n const hiddenToAddress = hiddenUI?.toAddress\n\n const address = toAddressFieldValue\n ? shortenAddress(toAddressFieldValue)\n : t('sendToWallet.enterAddress', {\n context: 'short',\n })\n\n const matchingConnectedAccount = accounts.find(\n (account) => account.address === toAddressFieldValue\n )\n\n // A bookmark from the config or the URL may carry no chainId.\n const detectedChain =\n !matchingConnectedAccount &&\n selectedBookmark?.chainId === undefined &&\n toAddressFieldValue\n ? getChainFromAddress(toAddressFieldValue)\n : undefined\n\n const chainType = !matchingConnectedAccount\n ? selectedBookmark?.chainType || detectedChain?.chainType\n : undefined\n\n const chainId =\n toChainId && toTokenAddress\n ? toChainId\n : matchingConnectedAccount\n ? matchingConnectedAccount.chainId\n : (selectedBookmark?.chainId ??\n detectedChain?.chainId ??\n (chainType ? defaultChainIdsByType[chainType] : undefined))\n\n const isConnectedAccount =\n selectedBookmark?.isConnectedAccount &&\n matchingConnectedAccount?.isConnected\n const connectedAccountName = matchingConnectedAccount?.connector?.name\n const bookmarkName = selectedBookmark?.name\n\n const headerTitle = isConnectedAccount\n ? connectedAccountName || address\n : bookmarkName || connectedAccountName || address\n\n const headerSubheader =\n isConnectedAccount || bookmarkName || connectedAccountName ? address : null\n\n const disabledForChanges = Boolean(toAddressFieldValue) && disabledToAddress\n\n // `onEditAddress === null` renders the card read-only (consumer-controlled,\n // e.g. a fixed checkout recipient); a function overrides the default route nav.\n const readOnly = onEditAddress === null || disabledForChanges\n\n const handleOnClick = () => {\n if (onEditAddress !== undefined) {\n onEditAddress?.()\n return\n }\n navigate({\n to: toAddresses?.length\n ? navigationRoutes.configuredWallets\n : navigationRoutes.sendToWallet,\n })\n }\n\n const clearSelectedBookmark: MouseEventHandler<HTMLButtonElement> = (e) => {\n e.stopPropagation()\n if (onClearAddress) {\n onClearAddress()\n return\n }\n setFieldValue('toAddress', '', { isTouched: true })\n setSelectedBookmark()\n }\n\n // The collapse opens instantly on first page load/component mount when there is an address to display\n // After which it needs an animated transition for open and closing.\n // collapseTransitionTime is used specify the transition time for opening and closing\n const collapseTransitionTime = useRef(0)\n\n // Timeout is needed here to push the collapseTransitionTime update to the back of the event loop so that it doesn't fired too quickly\n useEffect(() => {\n const timeout = setTimeout(() => {\n collapseTransitionTime.current = 225\n }, 0)\n return () => clearTimeout(timeout)\n }, [])\n\n const addressRequired = requireAddress || requiredToAddress\n const isOpenCollapse =\n !hiddenToAddress && (addressRequired || !!toAddressFieldValue)\n\n const title =\n mode === 'custom' && modeOptions?.custom?.type === 'deposit'\n ? t('header.depositTo')\n : t('header.sendToWallet')\n\n return (\n <Collapse\n timeout={collapseTransitionTime.current as number}\n in={isOpenCollapse}\n mountOnEnter\n unmountOnExit\n >\n <Card\n role=\"button\"\n onClick={readOnly ? undefined : handleOnClick}\n sx={{ width: '100%', ...props.sx }}\n >\n <SendToWalletCardTitleRow>\n <CardTitle sx={{ p: 0 }}>{title}</CardTitle>\n {addressRequired && !toAddressFieldValue ? (\n <SendToWalletRequiredLabel variant=\"warning\">\n <WarningRounded sx={{ fontSize: 14 }} />\n <SendToWalletRequiredLabelText type=\"icon\">\n {t('sendToWallet.required')}\n </SendToWalletRequiredLabelText>\n </SendToWalletRequiredLabel>\n ) : null}\n </SendToWalletCardTitleRow>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <SendToWalletCardHeader\n avatar={\n <AccountAvatar\n chainId={chainId}\n account={matchingConnectedAccount}\n toAddress={toAddress}\n empty={!toAddressFieldValue}\n />\n }\n title={headerTitle}\n subheader={headerSubheader}\n selected={!!toAddressFieldValue || disabledToAddress}\n action={\n toAddressFieldValue && !readOnly ? (\n <CardIconButton onClick={clearSelectedBookmark} size=\"small\">\n <CloseRounded fontSize=\"inherit\" />\n </CardIconButton>\n ) : null\n }\n />\n </Box>\n </Card>\n </Collapse>\n )\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useTokenSelect.d.ts","names":[],"sources":["../../../../src/components/TokenList/useTokenSelect.ts"],"mappings":";;qBAaa,iBACX,UAAU,UACV,2BACG,sBAAsB"}
1
+ {"version":3,"file":"useTokenSelect.d.ts","names":[],"sources":["../../../../src/components/TokenList/useTokenSelect.ts"],"mappings":";;qBAea,iBACX,UAAU,UACV,2BACG,sBAAsB"}
@@ -3,7 +3,9 @@ import "../../types/events.js";
3
3
  import { isItemAllowed } from "../../utils/item.js";
4
4
  import { useWidgetConfig } from "../../providers/WidgetProvider/WidgetProvider.js";
5
5
  import { useSplitMode } from "../../stores/navigationTabs/useNavigationTabsStore.js";
6
+ import { useAvailableChains } from "../../hooks/useAvailableChains.js";
6
7
  import { useFieldActions } from "../../stores/form/useFieldActions.js";
8
+ import { useToAddressReset } from "../../hooks/useToAddressReset.js";
7
9
  import { useChainOrderStore } from "../../stores/chains/ChainOrderStore.js";
8
10
  import { FormKeyHelper } from "../../stores/form/types.js";
9
11
  import { useToAddressAutoPopulate } from "../../hooks/useToAddressAutoPopulate.js";
@@ -15,9 +17,12 @@ const useTokenSelect = (formType, onClick) => {
15
17
  const emitter = useWidgetEvents();
16
18
  const { setFieldValue, getFieldValues } = useFieldActions();
17
19
  const autoPopulateToAddress = useToAddressAutoPopulate();
20
+ const { tryResetToAddress } = useToAddressReset();
21
+ const { getChainById } = useAvailableChains();
18
22
  const [setChain, setIsAllNetworks] = useChainOrderStore((state) => [state.setChain, state.setIsAllNetworks]);
19
23
  const tokenKey = FormKeyHelper.getTokenKey(formType);
20
24
  return useCallback((tokenAddress, chainId) => {
25
+ const [toChainIdBefore] = getFieldValues("toChain");
21
26
  setFieldValue(tokenKey, tokenAddress, {
22
27
  isDirty: true,
23
28
  isTouched: true
@@ -43,6 +48,9 @@ const useTokenSelect = (formType, onClick) => {
43
48
  });
44
49
  setChain(selectedChainId, oppositeFormType);
45
50
  }
51
+ const [toChainId] = getFieldValues("toChain");
52
+ const toChain = getChainById(toChainId);
53
+ if (toChainId !== toChainIdBefore && toChain) tryResetToAddress(toChain);
46
54
  autoPopulateToAddress({
47
55
  formType,
48
56
  selectedToAddress,
@@ -58,6 +66,8 @@ const useTokenSelect = (formType, onClick) => {
58
66
  onClick?.();
59
67
  }, [
60
68
  autoPopulateToAddress,
69
+ tryResetToAddress,
70
+ getChainById,
61
71
  disabledUI,
62
72
  emitter,
63
73
  formType,
@@ -1 +1 @@
1
- {"version":3,"file":"useTokenSelect.js","names":[],"sources":["../../../../src/components/TokenList/useTokenSelect.ts"],"sourcesContent":["import { useCallback } from 'react'\nimport { useToAddressAutoPopulate } from '../../hooks/useToAddressAutoPopulate.js'\nimport { useWidgetEvents } from '../../hooks/useWidgetEvents.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js'\nimport type { FormType } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useSplitMode } from '../../stores/navigationTabs/useNavigationTabsStore.js'\nimport { WidgetEvent } from '../../types/events.js'\nimport type { DisabledUIConfig } from '../../types/widget.js'\nimport { isItemAllowed } from '../../utils/item.js'\n\nexport const useTokenSelect = (\n formType: FormType,\n onClick?: () => void\n): ((tokenAddress: string, chainId?: number) => void) => {\n const { mode, disabledUI, chains: chainsConfig } = useWidgetConfig()\n const splitMode = useSplitMode()\n const emitter = useWidgetEvents()\n const { setFieldValue, getFieldValues } = useFieldActions()\n const autoPopulateToAddress = useToAddressAutoPopulate()\n const [setChain, setIsAllNetworks] = useChainOrderStore((state) => [\n state.setChain,\n state.setIsAllNetworks,\n ])\n\n const tokenKey = FormKeyHelper.getTokenKey(formType)\n\n return useCallback(\n (tokenAddress: string, chainId?: number) => {\n setFieldValue(tokenKey, tokenAddress, { isDirty: true, isTouched: true })\n const selectedChainId =\n chainId ?? getFieldValues(FormKeyHelper.getChainKey(formType))[0]\n // Set chain again to trigger URL builder update\n setFieldValue(FormKeyHelper.getChainKey(formType), selectedChainId, {\n isDirty: true,\n isTouched: true,\n })\n const amountKey = FormKeyHelper.getAmountKey(formType)\n if (!disabledUI?.[amountKey as keyof DisabledUIConfig]) {\n setFieldValue(amountKey, '')\n }\n const oppositeFormType = formType === 'from' ? 'to' : 'from'\n const [\n selectedOppositeTokenAddress,\n selectedOppositeChainId,\n selectedToAddress,\n ] = getFieldValues(\n FormKeyHelper.getTokenKey(oppositeFormType),\n FormKeyHelper.getChainKey(oppositeFormType),\n 'toAddress'\n )\n\n // TODO: remove when we enable same chain/token transfers\n const isSameTokenTransfer =\n selectedOppositeTokenAddress === tokenAddress &&\n selectedOppositeChainId === selectedChainId\n\n const isBridgeToSameChain =\n mode === 'split' &&\n splitMode === 'bridge' &&\n selectedOppositeChainId === selectedChainId\n\n if ((isSameTokenTransfer || isBridgeToSameChain) && mode !== 'custom') {\n setFieldValue(FormKeyHelper.getTokenKey(oppositeFormType), '', {\n isDirty: true,\n isTouched: true,\n })\n }\n\n // If no opposite token is selected, synchronize the opposite chain\n // to match the currently selected chain (if allowed).\n // In default exchange mode, also collapse \"All Networks\" on the opposite\n // side - same-chain swap is the most common action.\n if (\n !selectedOppositeTokenAddress &&\n selectedChainId &&\n isItemAllowed(selectedChainId, chainsConfig?.[oppositeFormType])\n ) {\n const isDefaultExchange = !mode || mode === 'default'\n if (isDefaultExchange) {\n setIsAllNetworks(false, oppositeFormType)\n }\n setFieldValue(\n FormKeyHelper.getChainKey(oppositeFormType),\n selectedChainId,\n {\n isDirty: true,\n isTouched: true,\n }\n )\n setChain(selectedChainId, oppositeFormType)\n }\n\n // Automatically populate toAddress field if bridging across ecosystems and compatible wallet is connected\n autoPopulateToAddress({\n formType,\n selectedToAddress,\n selectedChainId,\n selectedOppositeChainId,\n selectedOppositeTokenAddress,\n })\n\n const eventToEmit =\n formType === 'from'\n ? WidgetEvent.SourceChainTokenSelected\n : WidgetEvent.DestinationChainTokenSelected\n\n if (selectedChainId) {\n emitter.emit(eventToEmit, {\n chainId: selectedChainId,\n tokenAddress,\n })\n }\n\n onClick?.()\n },\n [\n autoPopulateToAddress,\n disabledUI,\n emitter,\n formType,\n getFieldValues,\n onClick,\n setChain,\n setIsAllNetworks,\n setFieldValue,\n mode,\n splitMode,\n tokenKey,\n chainsConfig,\n ]\n )\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,kBACX,UACA,YACuD;CACvD,MAAM,EAAE,MAAM,YAAY,QAAQ,iBAAiB,gBAAgB;CACnE,MAAM,YAAY,aAAa;CAC/B,MAAM,UAAU,gBAAgB;CAChC,MAAM,EAAE,eAAe,mBAAmB,gBAAgB;CAC1D,MAAM,wBAAwB,yBAAyB;CACvD,MAAM,CAAC,UAAU,oBAAoB,oBAAoB,UAAU,CACjE,MAAM,UACN,MAAM,gBACR,CAAC;CAED,MAAM,WAAW,cAAc,YAAY,QAAQ;CAEnD,OAAO,aACJ,cAAsB,YAAqB;EAC1C,cAAc,UAAU,cAAc;GAAE,SAAS;GAAM,WAAW;EAAK,CAAC;EACxE,MAAM,kBACJ,WAAW,eAAe,cAAc,YAAY,QAAQ,CAAC,CAAC,CAAC;EAEjE,cAAc,cAAc,YAAY,QAAQ,GAAG,iBAAiB;GAClE,SAAS;GACT,WAAW;EACb,CAAC;EACD,MAAM,YAAY,cAAc,aAAa,QAAQ;EACrD,IAAI,CAAC,aAAa,YAChB,cAAc,WAAW,EAAE;EAE7B,MAAM,mBAAmB,aAAa,SAAS,OAAO;EACtD,MAAM,CACJ,8BACA,yBACA,qBACE,eACF,cAAc,YAAY,gBAAgB,GAC1C,cAAc,YAAY,gBAAgB,GAC1C,WACF;EAYA,KARE,iCAAiC,gBACjC,4BAA4B,mBAG5B,SAAS,WACT,cAAc,YACd,4BAA4B,oBAEsB,SAAS,UAC3D,cAAc,cAAc,YAAY,gBAAgB,GAAG,IAAI;GAC7D,SAAS;GACT,WAAW;EACb,CAAC;EAOH,IACE,CAAC,gCACD,mBACA,cAAc,iBAAiB,eAAe,iBAAiB,GAC/D;GAEA,IAD0B,CAAC,QAAQ,SAAS,WAE1C,iBAAiB,OAAO,gBAAgB;GAE1C,cACE,cAAc,YAAY,gBAAgB,GAC1C,iBACA;IACE,SAAS;IACT,WAAW;GACb,CACF;GACA,SAAS,iBAAiB,gBAAgB;EAC5C;EAGA,sBAAsB;GACpB;GACA;GACA;GACA;GACA;EACF,CAAC;EAED,MAAM,cACJ,aAAa,SAAA,6BAAA;EAIf,IAAI,iBACF,QAAQ,KAAK,aAAa;GACxB,SAAS;GACT;EACF,CAAC;EAGH,UAAU;CACZ,GACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;AACF"}
1
+ {"version":3,"file":"useTokenSelect.js","names":[],"sources":["../../../../src/components/TokenList/useTokenSelect.ts"],"sourcesContent":["import { useCallback } from 'react'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport { useToAddressAutoPopulate } from '../../hooks/useToAddressAutoPopulate.js'\nimport { useToAddressReset } from '../../hooks/useToAddressReset.js'\nimport { useWidgetEvents } from '../../hooks/useWidgetEvents.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js'\nimport type { FormType } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useSplitMode } from '../../stores/navigationTabs/useNavigationTabsStore.js'\nimport { WidgetEvent } from '../../types/events.js'\nimport type { DisabledUIConfig } from '../../types/widget.js'\nimport { isItemAllowed } from '../../utils/item.js'\n\nexport const useTokenSelect = (\n formType: FormType,\n onClick?: () => void\n): ((tokenAddress: string, chainId?: number) => void) => {\n const { mode, disabledUI, chains: chainsConfig } = useWidgetConfig()\n const splitMode = useSplitMode()\n const emitter = useWidgetEvents()\n const { setFieldValue, getFieldValues } = useFieldActions()\n const autoPopulateToAddress = useToAddressAutoPopulate()\n const { tryResetToAddress } = useToAddressReset()\n const { getChainById } = useAvailableChains()\n const [setChain, setIsAllNetworks] = useChainOrderStore((state) => [\n state.setChain,\n state.setIsAllNetworks,\n ])\n\n const tokenKey = FormKeyHelper.getTokenKey(formType)\n\n return useCallback(\n (tokenAddress: string, chainId?: number) => {\n const [toChainIdBefore] = getFieldValues('toChain')\n setFieldValue(tokenKey, tokenAddress, { isDirty: true, isTouched: true })\n const selectedChainId =\n chainId ?? getFieldValues(FormKeyHelper.getChainKey(formType))[0]\n // Set chain again to trigger URL builder update\n setFieldValue(FormKeyHelper.getChainKey(formType), selectedChainId, {\n isDirty: true,\n isTouched: true,\n })\n const amountKey = FormKeyHelper.getAmountKey(formType)\n if (!disabledUI?.[amountKey as keyof DisabledUIConfig]) {\n setFieldValue(amountKey, '')\n }\n const oppositeFormType = formType === 'from' ? 'to' : 'from'\n const [\n selectedOppositeTokenAddress,\n selectedOppositeChainId,\n selectedToAddress,\n ] = getFieldValues(\n FormKeyHelper.getTokenKey(oppositeFormType),\n FormKeyHelper.getChainKey(oppositeFormType),\n 'toAddress'\n )\n\n // TODO: remove when we enable same chain/token transfers\n const isSameTokenTransfer =\n selectedOppositeTokenAddress === tokenAddress &&\n selectedOppositeChainId === selectedChainId\n\n const isBridgeToSameChain =\n mode === 'split' &&\n splitMode === 'bridge' &&\n selectedOppositeChainId === selectedChainId\n\n if ((isSameTokenTransfer || isBridgeToSameChain) && mode !== 'custom') {\n setFieldValue(FormKeyHelper.getTokenKey(oppositeFormType), '', {\n isDirty: true,\n isTouched: true,\n })\n }\n\n // If no opposite token is selected, synchronize the opposite chain\n // to match the currently selected chain (if allowed).\n // In default exchange mode, also collapse \"All Networks\" on the opposite\n // side - same-chain swap is the most common action.\n if (\n !selectedOppositeTokenAddress &&\n selectedChainId &&\n isItemAllowed(selectedChainId, chainsConfig?.[oppositeFormType])\n ) {\n const isDefaultExchange = !mode || mode === 'default'\n if (isDefaultExchange) {\n setIsAllNetworks(false, oppositeFormType)\n }\n setFieldValue(\n FormKeyHelper.getChainKey(oppositeFormType),\n selectedChainId,\n {\n isDirty: true,\n isTouched: true,\n }\n )\n setChain(selectedChainId, oppositeFormType)\n }\n\n // A token from \"All networks\" moves the destination without the chain select,\n // which resets a receiver the new chain cannot take.\n const [toChainId] = getFieldValues('toChain')\n const toChain = getChainById(toChainId)\n if (toChainId !== toChainIdBefore && toChain) {\n tryResetToAddress(toChain)\n }\n\n // Automatically populate toAddress field if bridging across ecosystems and compatible wallet is connected\n autoPopulateToAddress({\n formType,\n selectedToAddress,\n selectedChainId,\n selectedOppositeChainId,\n selectedOppositeTokenAddress,\n })\n\n const eventToEmit =\n formType === 'from'\n ? WidgetEvent.SourceChainTokenSelected\n : WidgetEvent.DestinationChainTokenSelected\n\n if (selectedChainId) {\n emitter.emit(eventToEmit, {\n chainId: selectedChainId,\n tokenAddress,\n })\n }\n\n onClick?.()\n },\n [\n autoPopulateToAddress,\n tryResetToAddress,\n getChainById,\n disabledUI,\n emitter,\n formType,\n getFieldValues,\n onClick,\n setChain,\n setIsAllNetworks,\n setFieldValue,\n mode,\n splitMode,\n tokenKey,\n chainsConfig,\n ]\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,MAAa,kBACX,UACA,YACuD;CACvD,MAAM,EAAE,MAAM,YAAY,QAAQ,iBAAiB,gBAAgB;CACnE,MAAM,YAAY,aAAa;CAC/B,MAAM,UAAU,gBAAgB;CAChC,MAAM,EAAE,eAAe,mBAAmB,gBAAgB;CAC1D,MAAM,wBAAwB,yBAAyB;CACvD,MAAM,EAAE,sBAAsB,kBAAkB;CAChD,MAAM,EAAE,iBAAiB,mBAAmB;CAC5C,MAAM,CAAC,UAAU,oBAAoB,oBAAoB,UAAU,CACjE,MAAM,UACN,MAAM,gBACR,CAAC;CAED,MAAM,WAAW,cAAc,YAAY,QAAQ;CAEnD,OAAO,aACJ,cAAsB,YAAqB;EAC1C,MAAM,CAAC,mBAAmB,eAAe,SAAS;EAClD,cAAc,UAAU,cAAc;GAAE,SAAS;GAAM,WAAW;EAAK,CAAC;EACxE,MAAM,kBACJ,WAAW,eAAe,cAAc,YAAY,QAAQ,CAAC,CAAC,CAAC;EAEjE,cAAc,cAAc,YAAY,QAAQ,GAAG,iBAAiB;GAClE,SAAS;GACT,WAAW;EACb,CAAC;EACD,MAAM,YAAY,cAAc,aAAa,QAAQ;EACrD,IAAI,CAAC,aAAa,YAChB,cAAc,WAAW,EAAE;EAE7B,MAAM,mBAAmB,aAAa,SAAS,OAAO;EACtD,MAAM,CACJ,8BACA,yBACA,qBACE,eACF,cAAc,YAAY,gBAAgB,GAC1C,cAAc,YAAY,gBAAgB,GAC1C,WACF;EAYA,KARE,iCAAiC,gBACjC,4BAA4B,mBAG5B,SAAS,WACT,cAAc,YACd,4BAA4B,oBAEsB,SAAS,UAC3D,cAAc,cAAc,YAAY,gBAAgB,GAAG,IAAI;GAC7D,SAAS;GACT,WAAW;EACb,CAAC;EAOH,IACE,CAAC,gCACD,mBACA,cAAc,iBAAiB,eAAe,iBAAiB,GAC/D;GAEA,IAD0B,CAAC,QAAQ,SAAS,WAE1C,iBAAiB,OAAO,gBAAgB;GAE1C,cACE,cAAc,YAAY,gBAAgB,GAC1C,iBACA;IACE,SAAS;IACT,WAAW;GACb,CACF;GACA,SAAS,iBAAiB,gBAAgB;EAC5C;EAIA,MAAM,CAAC,aAAa,eAAe,SAAS;EAC5C,MAAM,UAAU,aAAa,SAAS;EACtC,IAAI,cAAc,mBAAmB,SACnC,kBAAkB,OAAO;EAI3B,sBAAsB;GACpB;GACA;GACA;GACA;GACA;EACF,CAAC;EAED,MAAM,cACJ,aAAa,SAAA,6BAAA;EAIf,IAAI,iBACF,QAAQ,KAAK,aAAa;GACxB,SAAS;GACT;EACF,CAAC;EAGH,UAAU;CACZ,GACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":[],"sources":["../../../src/config/constants.ts"],"sourcesContent":["export const defaultMaxHeight = 686\n\nexport const internalExplorerUrl = 'https://scan.li.fi'\n"],"mappings":";AAAA,MAAa,mBAAmB;AAEhC,MAAa,sBAAsB"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../../src/config/constants.ts"],"sourcesContent":["export const defaultMaxHeight = 686\n\nexport const internalExplorerUrl = 'https://scan.li.fi'\n\n// Fits the longest Zcash unified address in the official test vectors (509 characters).\nexport const addressInputMaxLength = 512\n"],"mappings":";AAAA,MAAa,mBAAmB;AAEhC,MAAa,sBAAsB"}
@@ -1,5 +1,5 @@
1
1
  //#region src/config/version.d.ts
2
2
  export declare const name = "@lifi/widget";
3
- export declare const version = "4.8.0";
3
+ export declare const version = "4.9.0";
4
4
  //#endregion
5
5
  //# sourceMappingURL=version.d.ts.map
@@ -1,6 +1,6 @@
1
1
  //#region src/config/version.ts
2
2
  const name = "@lifi/widget";
3
- const version = "4.8.0";
3
+ const version = "4.9.0";
4
4
  //#endregion
5
5
  export { name, version };
6
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.8.0'\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
1
+ {"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.9.0'\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
@@ -1,5 +1,6 @@
1
1
  import { useChains } from "./useChains.js";
2
2
  import { useMemo } from "react";
3
+ import { useAddressForChain } from "@lifi/widget-provider";
3
4
  import { useAccount } from "@lifi/wallet-management";
4
5
  //#region src/hooks/useAccountsBalancesData.ts
5
6
  const useAccountsBalancesData = (selectedChainId, formType, isAllNetworks, allTokens) => {
@@ -19,6 +20,7 @@ const useAccountsBalancesData = (selectedChainId, formType, isAllNetworks, allTo
19
20
  currentChain
20
21
  ]);
21
22
  const { accounts: allAccounts, account: currentAccount } = useAccount(isAllNetworks ? void 0 : { chainType: currentChain?.chainType });
23
+ const { isAddressForChain } = useAddressForChain();
22
24
  const accounts = useMemo(() => {
23
25
  return isAllNetworks ? allAccounts : currentAccount ? [currentAccount] : void 0;
24
26
  }, [
@@ -31,7 +33,7 @@ const useAccountsBalancesData = (selectedChainId, formType, isAllNetworks, allTo
31
33
  if (!chains || !allTokens || !accounts?.length) return;
32
34
  return accounts?.filter((account) => account.address).reduce((acc, account) => {
33
35
  if (account.address) {
34
- const accountChains = chains?.filter((chain) => account.chainType === chain?.chainType);
36
+ const accountChains = chains?.filter((chain) => account.chainType === chain?.chainType && isAddressForChain(account.address, chain));
35
37
  if (accountChains) {
36
38
  const chainIdSet = new Set(accountChains.map((chain) => chain.id));
37
39
  acc[account.address] = Object.entries(allTokens).reduce((tokenAcc, [chainIdStr, tokens]) => {
@@ -46,7 +48,8 @@ const useAccountsBalancesData = (selectedChainId, formType, isAllNetworks, allTo
46
48
  }, [
47
49
  accounts,
48
50
  chains,
49
- allTokens
51
+ allTokens,
52
+ isAddressForChain
50
53
  ]),
51
54
  isLoading: isChainsLoading
52
55
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useAccountsBalancesData.js","names":[],"sources":["../../../src/hooks/useAccountsBalancesData.ts"],"sourcesContent":["import type { TokenExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport type { FormType } from '../stores/form/types.js'\nimport { useChains } from './useChains.js'\n\nexport const useAccountsBalancesData = (\n selectedChainId?: number,\n formType?: FormType,\n isAllNetworks?: boolean,\n allTokens?: Record<number, TokenExtended[]>\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const {\n chains: allChains,\n isLoading: isChainsLoading,\n getChainById,\n } = useChains(formType)\n const currentChain = useMemo(() => {\n return selectedChainId\n ? getChainById(selectedChainId, allChains)\n : undefined\n }, [selectedChainId, allChains, getChainById])\n const chains = useMemo(() => {\n return isAllNetworks ? allChains : currentChain ? [currentChain] : undefined\n }, [allChains, isAllNetworks, currentChain])\n\n const { accounts: allAccounts, account: currentAccount } = useAccount(\n isAllNetworks ? undefined : { chainType: currentChain?.chainType }\n )\n const accounts = useMemo(() => {\n return isAllNetworks\n ? allAccounts\n : currentAccount\n ? [currentAccount]\n : undefined\n }, [allAccounts, currentAccount, isAllNetworks])\n\n const accountsWithTokens = useMemo(() => {\n if (!chains || !allTokens || !accounts?.length) {\n return undefined\n }\n return accounts\n ?.filter((account) => account.address)\n .reduce(\n (acc, account) => {\n if (account.address) {\n const accountChains = chains?.filter(\n (chain) => account.chainType === chain?.chainType\n )\n if (accountChains) {\n const chainIdSet = new Set(accountChains.map((chain) => chain.id))\n acc[account.address] = Object.entries(allTokens).reduce(\n (tokenAcc, [chainIdStr, tokens]) => {\n const chainId = Number(chainIdStr)\n if (chainIdSet.has(chainId)) {\n tokenAcc[chainId] = tokens\n }\n return tokenAcc\n },\n {} as Record<number, TokenExtended[]>\n )\n }\n }\n return acc\n },\n {} as Record<string, Record<number, TokenExtended[]>>\n )\n }, [accounts, chains, allTokens])\n\n return {\n data: accountsWithTokens,\n isLoading: isChainsLoading,\n }\n}\n"],"mappings":";;;;AAMA,MAAa,2BACX,iBACA,UACA,eACA,cAIG;CACH,MAAM,EACJ,QAAQ,WACR,WAAW,iBACX,iBACE,UAAU,QAAQ;CACtB,MAAM,eAAe,cAAc;EACjC,OAAO,kBACH,aAAa,iBAAiB,SAAS,IACvC,KAAA;CACN,GAAG;EAAC;EAAiB;EAAW;CAAY,CAAC;CAC7C,MAAM,SAAS,cAAc;EAC3B,OAAO,gBAAgB,YAAY,eAAe,CAAC,YAAY,IAAI,KAAA;CACrE,GAAG;EAAC;EAAW;EAAe;CAAY,CAAC;CAE3C,MAAM,EAAE,UAAU,aAAa,SAAS,mBAAmB,WACzD,gBAAgB,KAAA,IAAY,EAAE,WAAW,cAAc,UAAU,CACnE;CACA,MAAM,WAAW,cAAc;EAC7B,OAAO,gBACH,cACA,iBACE,CAAC,cAAc,IACf,KAAA;CACR,GAAG;EAAC;EAAa;EAAgB;CAAa,CAAC;CAkC/C,OAAO;EACL,MAjCyB,cAAc;GACvC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,QACtC;GAEF,OAAO,UACH,QAAQ,YAAY,QAAQ,OAAO,CAAC,CACrC,QACE,KAAK,YAAY;IAChB,IAAI,QAAQ,SAAS;KACnB,MAAM,gBAAgB,QAAQ,QAC3B,UAAU,QAAQ,cAAc,OAAO,SAC1C;KACA,IAAI,eAAe;MACjB,MAAM,aAAa,IAAI,IAAI,cAAc,KAAK,UAAU,MAAM,EAAE,CAAC;MACjE,IAAI,QAAQ,WAAW,OAAO,QAAQ,SAAS,CAAC,CAAC,QAC9C,UAAU,CAAC,YAAY,YAAY;OAClC,MAAM,UAAU,OAAO,UAAU;OACjC,IAAI,WAAW,IAAI,OAAO,GACxB,SAAS,WAAW;OAEtB,OAAO;MACT,GACA,CAAC,CACH;KACF;IACF;IACA,OAAO;GACT,GACA,CAAC,CACH;EACJ,GAAG;GAAC;GAAU;GAAQ;EAAS,CAGN;EACvB,WAAW;CACb;AACF"}
1
+ {"version":3,"file":"useAccountsBalancesData.js","names":[],"sources":["../../../src/hooks/useAccountsBalancesData.ts"],"sourcesContent":["import type { TokenExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useAddressForChain } from '@lifi/widget-provider'\nimport { useMemo } from 'react'\nimport type { FormType } from '../stores/form/types.js'\nimport { useChains } from './useChains.js'\n\nexport const useAccountsBalancesData = (\n selectedChainId?: number,\n formType?: FormType,\n isAllNetworks?: boolean,\n allTokens?: Record<number, TokenExtended[]>\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const {\n chains: allChains,\n isLoading: isChainsLoading,\n getChainById,\n } = useChains(formType)\n const currentChain = useMemo(() => {\n return selectedChainId\n ? getChainById(selectedChainId, allChains)\n : undefined\n }, [selectedChainId, allChains, getChainById])\n const chains = useMemo(() => {\n return isAllNetworks ? allChains : currentChain ? [currentChain] : undefined\n }, [allChains, isAllNetworks, currentChain])\n\n const { accounts: allAccounts, account: currentAccount } = useAccount(\n isAllNetworks ? undefined : { chainType: currentChain?.chainType }\n )\n const { isAddressForChain } = useAddressForChain()\n const accounts = useMemo(() => {\n return isAllNetworks\n ? allAccounts\n : currentAccount\n ? [currentAccount]\n : undefined\n }, [allAccounts, currentAccount, isAllNetworks])\n\n const accountsWithTokens = useMemo(() => {\n if (!chains || !allTokens || !accounts?.length) {\n return undefined\n }\n return accounts\n ?.filter((account) => account.address)\n .reduce(\n (acc, account) => {\n if (account.address) {\n const accountChains = chains?.filter(\n (chain) =>\n account.chainType === chain?.chainType &&\n isAddressForChain(account.address as string, chain)\n )\n if (accountChains) {\n const chainIdSet = new Set(accountChains.map((chain) => chain.id))\n acc[account.address] = Object.entries(allTokens).reduce(\n (tokenAcc, [chainIdStr, tokens]) => {\n const chainId = Number(chainIdStr)\n if (chainIdSet.has(chainId)) {\n tokenAcc[chainId] = tokens\n }\n return tokenAcc\n },\n {} as Record<number, TokenExtended[]>\n )\n }\n }\n return acc\n },\n {} as Record<string, Record<number, TokenExtended[]>>\n )\n }, [accounts, chains, allTokens, isAddressForChain])\n\n return {\n data: accountsWithTokens,\n isLoading: isChainsLoading,\n }\n}\n"],"mappings":";;;;;AAOA,MAAa,2BACX,iBACA,UACA,eACA,cAIG;CACH,MAAM,EACJ,QAAQ,WACR,WAAW,iBACX,iBACE,UAAU,QAAQ;CACtB,MAAM,eAAe,cAAc;EACjC,OAAO,kBACH,aAAa,iBAAiB,SAAS,IACvC,KAAA;CACN,GAAG;EAAC;EAAiB;EAAW;CAAY,CAAC;CAC7C,MAAM,SAAS,cAAc;EAC3B,OAAO,gBAAgB,YAAY,eAAe,CAAC,YAAY,IAAI,KAAA;CACrE,GAAG;EAAC;EAAW;EAAe;CAAY,CAAC;CAE3C,MAAM,EAAE,UAAU,aAAa,SAAS,mBAAmB,WACzD,gBAAgB,KAAA,IAAY,EAAE,WAAW,cAAc,UAAU,CACnE;CACA,MAAM,EAAE,sBAAsB,mBAAmB;CACjD,MAAM,WAAW,cAAc;EAC7B,OAAO,gBACH,cACA,iBACE,CAAC,cAAc,IACf,KAAA;CACR,GAAG;EAAC;EAAa;EAAgB;CAAa,CAAC;CAoC/C,OAAO;EACL,MAnCyB,cAAc;GACvC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,QACtC;GAEF,OAAO,UACH,QAAQ,YAAY,QAAQ,OAAO,CAAC,CACrC,QACE,KAAK,YAAY;IAChB,IAAI,QAAQ,SAAS;KACnB,MAAM,gBAAgB,QAAQ,QAC3B,UACC,QAAQ,cAAc,OAAO,aAC7B,kBAAkB,QAAQ,SAAmB,KAAK,CACtD;KACA,IAAI,eAAe;MACjB,MAAM,aAAa,IAAI,IAAI,cAAc,KAAK,UAAU,MAAM,EAAE,CAAC;MACjE,IAAI,QAAQ,WAAW,OAAO,QAAQ,SAAS,CAAC,CAAC,QAC9C,UAAU,CAAC,YAAY,YAAY;OAClC,MAAM,UAAU,OAAO,UAAU;OACjC,IAAI,WAAW,IAAI,OAAO,GACxB,SAAS,WAAW;OAEtB,OAAO;MACT,GACA,CAAC,CACH;KACF;IACF;IACA,OAAO;GACT,GACA,CAAC,CACH;EACJ,GAAG;GAAC;GAAU;GAAQ;GAAW;EAAiB,CAGzB;EACvB,WAAW;CACb;AACF"}
@@ -1,4 +1,4 @@
1
- import { Chain, ChainType } from "@lifi/sdk";
1
+ import { Chain, ChainId, ChainType } from "@lifi/sdk";
2
2
  //#region src/hooks/useAddressValidation.d.ts
3
3
  export declare enum AddressType {
4
4
  Address = 0,
@@ -6,13 +6,14 @@ export declare enum AddressType {
6
6
  }
7
7
  type ValidationArgs = {
8
8
  value: string;
9
- chainType?: ChainType;
9
+ /** Strict: the receiver must be valid on this chain. */
10
10
  chain?: Chain;
11
11
  };
12
12
  type ValidResponse = {
13
13
  address: string;
14
14
  addressType: AddressType;
15
15
  chainType: ChainType;
16
+ chainId?: ChainId;
16
17
  isValid: true;
17
18
  };
18
19
  type InvalidResponse = {
@@ -1 +1 @@
1
- {"version":3,"file":"useAddressValidation.d.ts","names":[],"sources":["../../../src/hooks/useAddressValidation.ts"],"mappings":";;oBAOY;EACV;EACA;;KAGG;EACH;EACA,YAAY;EACZ,QAAQ;;KAGL;EACH;EACA,aAAa;EACb,WAAW;EACX;;KAGG;EACH;EACA;;qBAGW;EACX,kBACE,MAAM,mBACH,QAAQ,gBAAgB;EAC7B"}
1
+ {"version":3,"file":"useAddressValidation.d.ts","names":[],"sources":["../../../src/hooks/useAddressValidation.ts"],"mappings":";;oBAUY;EACV;EACA;;KAGG;EACH;;EAEA,QAAQ;;KAGL;EACH;EACA,aAAa;EACb,WAAW;EACX,UAAU;EACV;;KAGG;EACH;EACA;;qBAGW;EACX,kBACE,MAAM,mBACH,QAAQ,gBAAgB;EAC7B"}
@@ -1,8 +1,8 @@
1
1
  import { useSDKClient } from "../providers/SDKClientProvider.js";
2
- import { getNameServiceAddress } from "@lifi/sdk";
2
+ import { ChainId, getNameServiceAddress } from "@lifi/sdk";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import { useMutation } from "@tanstack/react-query";
5
- import { useChainTypeFromAddress } from "@lifi/widget-provider";
5
+ import { useAddressForChain, useChainTypeFromAddress } from "@lifi/widget-provider";
6
6
  //#region src/hooks/useAddressValidation.ts
7
7
  let AddressType = /* @__PURE__ */ function(AddressType) {
8
8
  AddressType[AddressType["Address"] = 0] = "Address";
@@ -11,28 +11,55 @@ let AddressType = /* @__PURE__ */ function(AddressType) {
11
11
  }({});
12
12
  const useAddressValidation = () => {
13
13
  const { t } = useTranslation();
14
- const { getChainTypeFromAddress } = useChainTypeFromAddress();
14
+ const { getChainFromAddress } = useChainTypeFromAddress();
15
+ const { isAddressForChain } = useAddressForChain();
15
16
  const sdkClient = useSDKClient();
16
- const { mutateAsync: validateAddress, isPending: isValidating } = useMutation({ mutationFn: async ({ value, chainType, chain }) => {
17
+ const validFor = (address, addressType, chain) => ({
18
+ address,
19
+ addressType,
20
+ chainType: chain.chainType,
21
+ chainId: getChainFromAddress(address)?.chainId,
22
+ isValid: true
23
+ });
24
+ const validateForChain = async (value, chain) => {
25
+ if (isAddressForChain(value, chain)) return validFor(value, 0, chain);
26
+ if (getChainFromAddress(value)) return {
27
+ isValid: false,
28
+ error: t("error.title.walletChainTypeInvalid", { chainName: chain.name })
29
+ };
30
+ const resolved = await getNameServiceAddress(sdkClient, value, chain.chainType);
31
+ if (resolved && isAddressForChain(resolved, chain)) return validFor(resolved, 1, chain);
32
+ return {
33
+ isValid: false,
34
+ error: chain.id === ChainId.ZEC ? t("error.title.zcashAddressInvalid") : t("error.title.walletAddressInvalid", {
35
+ context: "chain",
36
+ chainName: chain.name
37
+ })
38
+ };
39
+ };
40
+ const validateWithoutChain = async (value) => {
41
+ const detected = getChainFromAddress(value);
42
+ if (detected) return {
43
+ address: value,
44
+ addressType: 0,
45
+ ...detected,
46
+ isValid: true
47
+ };
48
+ const address = await getNameServiceAddress(sdkClient, value);
49
+ const resolved = address ? getChainFromAddress(address) : void 0;
50
+ if (address && resolved) return {
51
+ address,
52
+ addressType: 1,
53
+ ...resolved,
54
+ isValid: true
55
+ };
56
+ };
57
+ const { mutateAsync: validateAddress, isPending: isValidating } = useMutation({ mutationFn: async ({ value, chain }) => {
17
58
  try {
18
59
  if (!value) throw new Error();
19
- const _chainType = getChainTypeFromAddress(value);
20
- if (_chainType) return {
21
- address: value,
22
- addressType: 0,
23
- chainType: _chainType,
24
- isValid: true
25
- };
26
- const address = await getNameServiceAddress(sdkClient, value, chainType);
27
- if (address) {
28
- const _chainType = getChainTypeFromAddress(address);
29
- if (_chainType) return {
30
- address,
31
- addressType: 1,
32
- chainType: _chainType,
33
- isValid: true
34
- };
35
- }
60
+ if (chain) return await validateForChain(value, chain);
61
+ const result = await validateWithoutChain(value);
62
+ if (result) return result;
36
63
  throw new Error();
37
64
  } catch (_) {
38
65
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"useAddressValidation.js","names":[],"sources":["../../../src/hooks/useAddressValidation.ts"],"sourcesContent":["import type { Chain, ChainType } from '@lifi/sdk'\nimport { getNameServiceAddress } from '@lifi/sdk'\nimport { useChainTypeFromAddress } from '@lifi/widget-provider'\nimport { useMutation } from '@tanstack/react-query'\nimport { useTranslation } from 'react-i18next'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\n\nexport enum AddressType {\n Address = 0,\n NameService = 1,\n}\n\ntype ValidationArgs = {\n value: string\n chainType?: ChainType\n chain?: Chain\n}\n\ntype ValidResponse = {\n address: string\n addressType: AddressType\n chainType: ChainType\n isValid: true\n}\n\ntype InvalidResponse = {\n error: string\n isValid: false\n}\n\nexport const useAddressValidation = (): {\n validateAddress: (\n args: ValidationArgs\n ) => Promise<ValidResponse | InvalidResponse>\n isValidating: boolean\n} => {\n const { t } = useTranslation()\n const { getChainTypeFromAddress } = useChainTypeFromAddress()\n const sdkClient = useSDKClient()\n\n const { mutateAsync: validateAddress, isPending: isValidating } = useMutation(\n {\n mutationFn: async ({\n value,\n chainType,\n chain,\n }: ValidationArgs): Promise<ValidResponse | InvalidResponse> => {\n try {\n if (!value) {\n throw new Error()\n }\n\n const _chainType = getChainTypeFromAddress(value)\n if (_chainType) {\n return {\n address: value,\n addressType: AddressType.Address,\n chainType: _chainType,\n isValid: true,\n }\n }\n\n const address = await getNameServiceAddress(\n sdkClient,\n value,\n chainType\n )\n\n if (address) {\n const _chainType = getChainTypeFromAddress(address)\n if (_chainType) {\n return {\n address: address,\n addressType: AddressType.NameService,\n chainType: _chainType,\n isValid: true,\n }\n }\n }\n\n throw new Error()\n } catch (_) {\n return {\n isValid: false,\n error: t(\n 'error.title.walletAddressInvalid',\n chain?.name\n ? { context: 'chain', chainName: chain.name }\n : undefined\n ),\n }\n }\n },\n }\n )\n\n return {\n validateAddress,\n isValidating,\n }\n}\n"],"mappings":";;;;;;AAOA,IAAY,cAAL,yBAAA,aAAA;CACL,YAAA,YAAA,aAAA,KAAA;CACA,YAAA,YAAA,iBAAA,KAAA;;AACF,EAAA,CAAA,CAAA;AAoBA,MAAa,6BAKR;CACH,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,4BAA4B,wBAAwB;CAC5D,MAAM,YAAY,aAAa;CAE/B,MAAM,EAAE,aAAa,iBAAiB,WAAW,iBAAiB,YAChE,EACE,YAAY,OAAO,EACjB,OACA,WACA,YAC8D;EAC9D,IAAI;GACF,IAAI,CAAC,OACH,MAAM,IAAI,MAAM;GAGlB,MAAM,aAAa,wBAAwB,KAAK;GAChD,IAAI,YACF,OAAO;IACL,SAAS;IACT,aAAA;IACA,WAAW;IACX,SAAS;GACX;GAGF,MAAM,UAAU,MAAM,sBACpB,WACA,OACA,SACF;GAEA,IAAI,SAAS;IACX,MAAM,aAAa,wBAAwB,OAAO;IAClD,IAAI,YACF,OAAO;KACI;KACT,aAAA;KACA,WAAW;KACX,SAAS;IACX;GAEJ;GAEA,MAAM,IAAI,MAAM;EAClB,SAAS,GAAG;GACV,OAAO;IACL,SAAS;IACT,OAAO,EACL,oCACA,OAAO,OACH;KAAE,SAAS;KAAS,WAAW,MAAM;IAAK,IAC1C,KAAA,CACN;GACF;EACF;CACF,EACF,CACF;CAEA,OAAO;EACL;EACA;CACF;AACF"}
1
+ {"version":3,"file":"useAddressValidation.js","names":[],"sources":["../../../src/hooks/useAddressValidation.ts"],"sourcesContent":["import type { Chain, ChainType } from '@lifi/sdk'\nimport { ChainId, getNameServiceAddress } from '@lifi/sdk'\nimport {\n useAddressForChain,\n useChainTypeFromAddress,\n} from '@lifi/widget-provider'\nimport { useMutation } from '@tanstack/react-query'\nimport { useTranslation } from 'react-i18next'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\n\nexport enum AddressType {\n Address = 0,\n NameService = 1,\n}\n\ntype ValidationArgs = {\n value: string\n /** Strict: the receiver must be valid on this chain. */\n chain?: Chain\n}\n\ntype ValidResponse = {\n address: string\n addressType: AddressType\n chainType: ChainType\n chainId?: ChainId\n isValid: true\n}\n\ntype InvalidResponse = {\n error: string\n isValid: false\n}\n\nexport const useAddressValidation = (): {\n validateAddress: (\n args: ValidationArgs\n ) => Promise<ValidResponse | InvalidResponse>\n isValidating: boolean\n} => {\n const { t } = useTranslation()\n const { getChainFromAddress } = useChainTypeFromAddress()\n const { isAddressForChain } = useAddressForChain()\n const sdkClient = useSDKClient()\n\n const validFor = (\n address: string,\n addressType: AddressType,\n chain: Chain\n ): ValidResponse => ({\n address,\n addressType,\n chainType: chain.chainType,\n chainId: getChainFromAddress(address)?.chainId,\n isValid: true,\n })\n\n const validateForChain = async (\n value: string,\n chain: Chain\n ): Promise<ValidResponse | InvalidResponse> => {\n if (isAddressForChain(value, chain)) {\n return validFor(value, AddressType.Address, chain)\n }\n // A recognised address is no name to resolve.\n if (getChainFromAddress(value)) {\n return {\n isValid: false,\n error: t('error.title.walletChainTypeInvalid', {\n chainName: chain.name,\n }),\n }\n }\n const resolved = await getNameServiceAddress(\n sdkClient,\n value,\n chain.chainType\n )\n if (resolved && isAddressForChain(resolved, chain)) {\n return validFor(resolved, AddressType.NameService, chain)\n }\n return {\n isValid: false,\n error:\n chain.id === ChainId.ZEC\n ? t('error.title.zcashAddressInvalid')\n : t('error.title.walletAddressInvalid', {\n context: 'chain',\n chainName: chain.name,\n }),\n }\n }\n\n const validateWithoutChain = async (\n value: string\n ): Promise<ValidResponse | undefined> => {\n const detected = getChainFromAddress(value)\n if (detected) {\n return {\n address: value,\n addressType: AddressType.Address,\n ...detected,\n isValid: true,\n }\n }\n const address = await getNameServiceAddress(sdkClient, value)\n const resolved = address ? getChainFromAddress(address) : undefined\n if (address && resolved) {\n return {\n address,\n addressType: AddressType.NameService,\n ...resolved,\n isValid: true,\n }\n }\n return undefined\n }\n\n const { mutateAsync: validateAddress, isPending: isValidating } = useMutation(\n {\n mutationFn: async ({\n value,\n chain,\n }: ValidationArgs): Promise<ValidResponse | InvalidResponse> => {\n try {\n if (!value) {\n throw new Error()\n }\n if (chain) {\n return await validateForChain(value, chain)\n }\n const result = await validateWithoutChain(value)\n if (result) {\n return result\n }\n throw new Error()\n } catch (_) {\n return {\n isValid: false,\n error: t(\n 'error.title.walletAddressInvalid',\n chain?.name\n ? { context: 'chain', chainName: chain.name }\n : undefined\n ),\n }\n }\n },\n }\n )\n\n return {\n validateAddress,\n isValidating,\n }\n}\n"],"mappings":";;;;;;AAUA,IAAY,cAAL,yBAAA,aAAA;CACL,YAAA,YAAA,aAAA,KAAA;CACA,YAAA,YAAA,iBAAA,KAAA;;AACF,EAAA,CAAA,CAAA;AAqBA,MAAa,6BAKR;CACH,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,wBAAwB,wBAAwB;CACxD,MAAM,EAAE,sBAAsB,mBAAmB;CACjD,MAAM,YAAY,aAAa;CAE/B,MAAM,YACJ,SACA,aACA,WACmB;EACnB;EACA;EACA,WAAW,MAAM;EACjB,SAAS,oBAAoB,OAAO,CAAC,EAAE;EACvC,SAAS;CACX;CAEA,MAAM,mBAAmB,OACvB,OACA,UAC6C;EAC7C,IAAI,kBAAkB,OAAO,KAAK,GAChC,OAAO,SAAS,OAAA,GAA4B,KAAK;EAGnD,IAAI,oBAAoB,KAAK,GAC3B,OAAO;GACL,SAAS;GACT,OAAO,EAAE,sCAAsC,EAC7C,WAAW,MAAM,KACnB,CAAC;EACH;EAEF,MAAM,WAAW,MAAM,sBACrB,WACA,OACA,MAAM,SACR;EACA,IAAI,YAAY,kBAAkB,UAAU,KAAK,GAC/C,OAAO,SAAS,UAAA,GAAmC,KAAK;EAE1D,OAAO;GACL,SAAS;GACT,OACE,MAAM,OAAO,QAAQ,MACjB,EAAE,iCAAiC,IACnC,EAAE,oCAAoC;IACpC,SAAS;IACT,WAAW,MAAM;GACnB,CAAC;EACT;CACF;CAEA,MAAM,uBAAuB,OAC3B,UACuC;EACvC,MAAM,WAAW,oBAAoB,KAAK;EAC1C,IAAI,UACF,OAAO;GACL,SAAS;GACT,aAAA;GACA,GAAG;GACH,SAAS;EACX;EAEF,MAAM,UAAU,MAAM,sBAAsB,WAAW,KAAK;EAC5D,MAAM,WAAW,UAAU,oBAAoB,OAAO,IAAI,KAAA;EAC1D,IAAI,WAAW,UACb,OAAO;GACL;GACA,aAAA;GACA,GAAG;GACH,SAAS;EACX;CAGJ;CAEA,MAAM,EAAE,aAAa,iBAAiB,WAAW,iBAAiB,YAChE,EACE,YAAY,OAAO,EACjB,OACA,YAC8D;EAC9D,IAAI;GACF,IAAI,CAAC,OACH,MAAM,IAAI,MAAM;GAElB,IAAI,OACF,OAAO,MAAM,iBAAiB,OAAO,KAAK;GAE5C,MAAM,SAAS,MAAM,qBAAqB,KAAK;GAC/C,IAAI,QACF,OAAO;GAET,MAAM,IAAI,MAAM;EAClB,SAAS,GAAG;GACV,OAAO;IACL,SAAS;IACT,OAAO,EACL,oCACA,OAAO,OACH;KAAE,SAAS;KAAS,WAAW,MAAM;IAAK,IAC1C,KAAA,CACN;GACF;EACF;CACF,EACF,CACF;CAEA,OAAO;EACL;EACA;CACF;AACF"}
@@ -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 +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"}
@@ -8,7 +8,7 @@ import { useFieldValues } from "../stores/form/useFieldValues.js";
8
8
  import { useIntermediateRoutesStore } from "../stores/routes/useIntermediateRoutesStore.js";
9
9
  import { useSetExecutableRoute } from "../stores/routes/useSetExecutableRoute.js";
10
10
  import { useSettings } from "../stores/settings/useSettings.js";
11
- import { isCustomReceiverBlocked } from "../utils/customReceiver.js";
11
+ import { canQuoteWithToAddress, isCustomReceiverBlocked, isSignerInvalidReceiver } from "../utils/customReceiver.js";
12
12
  import { getQueryKey } from "../utils/queries.js";
13
13
  import { updateTokenInCache } from "../utils/token.js";
14
14
  import { useChain } from "./useChain.js";
@@ -19,7 +19,7 @@ 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;
@@ -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,