@lifi/widget 1.16.1 → 1.17.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 (119) hide show
  1. package/AppProvider.js +1 -1
  2. package/README.md +1 -1
  3. package/cjs/AppProvider.js +1 -1
  4. package/cjs/components/ChainSelect/ChainSelect.style.js +4 -4
  5. package/cjs/components/ChainSelect/useChainSelect.d.ts +2 -2
  6. package/cjs/components/GasSufficiencyMessage/GasSufficiencyMessage.js +3 -3
  7. package/cjs/components/Header/useHeaderActionStore.d.ts +0 -2
  8. package/cjs/components/Header/useHeaderActionStore.js +1 -5
  9. package/cjs/components/SwapButton/SwapButton.js +3 -23
  10. package/cjs/components/TokenList/TokenList.js +1 -1
  11. package/cjs/components/TokenList/TokenList.style.js +4 -3
  12. package/cjs/components/TokenList/TokenListItem.js +1 -1
  13. package/cjs/components/TokenList/TokenNotFound.d.ts +2 -1
  14. package/cjs/components/TokenList/TokenNotFound.js +12 -2
  15. package/cjs/components/TokenList/types.d.ts +2 -2
  16. package/cjs/config/version.d.ts +1 -1
  17. package/cjs/config/version.js +1 -1
  18. package/cjs/hooks/useChains.js +21 -8
  19. package/cjs/hooks/useFeaturedTokens.d.ts +1 -1
  20. package/cjs/hooks/useFeaturedTokens.js +5 -2
  21. package/cjs/hooks/useGasSufficiency.d.ts +1 -1
  22. package/cjs/hooks/useGasSufficiency.js +30 -21
  23. package/cjs/hooks/useToken.d.ts +0 -1
  24. package/cjs/hooks/useToken.js +1 -2
  25. package/cjs/hooks/useTokenBalances.d.ts +1 -2
  26. package/cjs/hooks/useTokenBalances.js +1 -2
  27. package/cjs/hooks/useTokens.d.ts +1 -2
  28. package/cjs/hooks/useTokens.js +30 -8
  29. package/cjs/hooks/useTools.js +8 -3
  30. package/cjs/i18n/en/translation.json +2 -3
  31. package/cjs/i18n/index.d.ts +1 -2
  32. package/cjs/pages/MainPage/MainSwapButton.js +1 -1
  33. package/cjs/pages/SettingsPage/AdvancedPreferences.js +1 -1
  34. package/cjs/pages/SettingsPage/GasPriceSelect.js +1 -1
  35. package/cjs/pages/SettingsPage/RoutePrioritySelect.js +1 -1
  36. package/cjs/pages/SettingsPage/ShowDestinationWallet.js +1 -1
  37. package/cjs/pages/SettingsPage/SlippageInput.js +1 -1
  38. package/cjs/pages/SwapDetailsPage/SwapDetailsPage.js +2 -3
  39. package/cjs/pages/SwapHistoryPage/SwapHistoryPage.js +2 -3
  40. package/cjs/pages/SwapPage/SwapPage.js +11 -2
  41. package/cjs/pages/SwapRoutesPage/SwapRoutesPage.js +4 -3
  42. package/cjs/providers/SwapFormProvider/SwapFormProvider.js +4 -58
  43. package/cjs/providers/SwapFormProvider/types.d.ts +5 -5
  44. package/cjs/providers/WalletProvider/WalletProvider.js +57 -1
  45. package/cjs/providers/WidgetProvider/index.d.ts +1 -0
  46. package/cjs/providers/WidgetProvider/index.js +1 -0
  47. package/cjs/providers/WidgetProvider/utils.d.ts +4 -0
  48. package/cjs/providers/WidgetProvider/utils.js +13 -0
  49. package/cjs/stores/chains/index.d.ts +0 -1
  50. package/cjs/stores/chains/index.js +0 -1
  51. package/cjs/stores/chains/types.d.ts +1 -1
  52. package/cjs/stores/chains/useChainOrderStore.js +17 -14
  53. package/cjs/stores/settings/index.d.ts +0 -1
  54. package/cjs/stores/settings/index.js +0 -1
  55. package/cjs/stores/settings/useAppearance.js +3 -1
  56. package/cjs/types/widget.d.ts +29 -22
  57. package/components/ChainSelect/ChainSelect.style.js +4 -4
  58. package/components/ChainSelect/useChainSelect.d.ts +2 -2
  59. package/components/GasSufficiencyMessage/GasSufficiencyMessage.js +3 -3
  60. package/components/Header/useHeaderActionStore.d.ts +0 -2
  61. package/components/Header/useHeaderActionStore.js +0 -3
  62. package/components/SwapButton/SwapButton.js +5 -25
  63. package/components/TokenList/TokenList.js +1 -1
  64. package/components/TokenList/TokenList.style.js +4 -3
  65. package/components/TokenList/TokenListItem.js +1 -1
  66. package/components/TokenList/TokenNotFound.d.ts +2 -1
  67. package/components/TokenList/TokenNotFound.js +12 -2
  68. package/components/TokenList/types.d.ts +2 -2
  69. package/config/version.d.ts +1 -1
  70. package/config/version.js +1 -1
  71. package/hooks/useChains.js +23 -10
  72. package/hooks/useFeaturedTokens.d.ts +1 -1
  73. package/hooks/useFeaturedTokens.js +5 -2
  74. package/hooks/useGasSufficiency.d.ts +1 -1
  75. package/hooks/useGasSufficiency.js +32 -23
  76. package/hooks/useToken.d.ts +0 -1
  77. package/hooks/useToken.js +1 -2
  78. package/hooks/useTokenBalances.d.ts +1 -2
  79. package/hooks/useTokenBalances.js +1 -2
  80. package/hooks/useTokens.d.ts +1 -2
  81. package/hooks/useTokens.js +31 -9
  82. package/hooks/useTools.js +9 -4
  83. package/i18n/en/translation.json +2 -3
  84. package/i18n/index.d.ts +1 -2
  85. package/package.json +4 -4
  86. package/pages/MainPage/MainSwapButton.js +1 -1
  87. package/pages/SettingsPage/AdvancedPreferences.js +2 -2
  88. package/pages/SettingsPage/GasPriceSelect.js +2 -2
  89. package/pages/SettingsPage/RoutePrioritySelect.js +2 -2
  90. package/pages/SettingsPage/ShowDestinationWallet.js +2 -2
  91. package/pages/SettingsPage/SlippageInput.js +2 -2
  92. package/pages/SwapDetailsPage/SwapDetailsPage.js +3 -4
  93. package/pages/SwapHistoryPage/SwapHistoryPage.js +3 -4
  94. package/pages/SwapPage/SwapPage.js +11 -2
  95. package/pages/SwapRoutesPage/SwapRoutesPage.js +5 -4
  96. package/providers/SwapFormProvider/SwapFormProvider.js +4 -58
  97. package/providers/SwapFormProvider/types.d.ts +5 -5
  98. package/providers/WalletProvider/WalletProvider.js +58 -2
  99. package/providers/WidgetProvider/index.d.ts +1 -0
  100. package/providers/WidgetProvider/index.js +1 -0
  101. package/providers/WidgetProvider/utils.d.ts +4 -0
  102. package/providers/WidgetProvider/utils.js +9 -0
  103. package/stores/chains/index.d.ts +0 -1
  104. package/stores/chains/index.js +0 -1
  105. package/stores/chains/types.d.ts +1 -1
  106. package/stores/chains/useChainOrderStore.js +17 -14
  107. package/stores/settings/index.d.ts +0 -1
  108. package/stores/settings/index.js +0 -1
  109. package/stores/settings/useAppearance.js +3 -1
  110. package/tsconfig.cjs.tsbuildinfo +1 -1
  111. package/types/widget.d.ts +29 -22
  112. package/cjs/stores/chains/useInitializeChainOrder.d.ts +0 -1
  113. package/cjs/stores/chains/useInitializeChainOrder.js +0 -12
  114. package/cjs/stores/settings/useSetSettings.d.ts +0 -5
  115. package/cjs/stores/settings/useSetSettings.js +0 -12
  116. package/stores/chains/useInitializeChainOrder.d.ts +0 -1
  117. package/stores/chains/useInitializeChainOrder.js +0 -5
  118. package/stores/settings/useSetSettings.d.ts +0 -5
  119. package/stores/settings/useSetSettings.js +0 -5
@@ -1,6 +1,4 @@
1
- /// <reference types="react" />
2
1
  import type { HeaderActionStore } from './types';
3
2
  export declare const useHeaderActionStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<HeaderActionStore>, "setState"> & {
4
3
  setState(nextStateOrUpdater: HeaderActionStore | Partial<HeaderActionStore> | ((state: import("immer/dist/internal").WritableDraft<HeaderActionStore>) => void), shouldReplace?: boolean | undefined): void;
5
4
  }>;
6
- export declare const useSetHeaderAction: () => (element?: import("react").ReactNode) => () => void;
@@ -14,6 +14,3 @@ export const useHeaderActionStore = create()(immer((set, get) => ({
14
14
  });
15
15
  },
16
16
  })));
17
- export const useSetHeaderAction = () => {
18
- return useHeaderActionStore((state) => state.setAction);
19
- };
@@ -8,51 +8,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
- import { ChainId } from '@lifi/sdk';
12
11
  import { Button } from '@mui/material';
13
- import { useWatch } from 'react-hook-form';
14
12
  import { useTranslation } from 'react-i18next';
15
13
  import { useNavigate } from 'react-router-dom';
16
- import { useChains, useGasSufficiency } from '../../hooks';
17
- import { SwapFormKeyHelper, useWallet, useWidgetConfig } from '../../providers';
14
+ import { useGasSufficiency } from '../../hooks';
15
+ import { useWallet, useWidgetConfig } from '../../providers';
18
16
  import { navigationRoutes } from '../../utils';
19
17
  export const SwapButton = ({ onClick, currentRoute, text, disable, }) => {
20
- var _a;
21
18
  const { t } = useTranslation();
22
19
  const navigate = useNavigate();
23
- const { getChainById } = useChains();
24
20
  const config = useWidgetConfig();
25
- const { account, switchChain, connect: walletConnect } = useWallet();
21
+ const { account, connect } = useWallet();
26
22
  const { insufficientFunds, insufficientGas } = useGasSufficiency(currentRoute);
27
- const [chainId] = useWatch({
28
- name: [SwapFormKeyHelper.getChainKey('from')],
29
- });
30
- // Allow switching chain only if execution is not started
31
- const switchChainAllowed = ((_a = getChainById(chainId || ChainId.ETH)) === null || _a === void 0 ? void 0 : _a.id) !== account.chainId &&
32
- currentRoute &&
33
- !currentRoute.steps.some((step) => step.execution);
34
23
  const handleSwapButtonClick = () => __awaiter(void 0, void 0, void 0, function* () {
35
24
  if (!account.isActive) {
36
25
  if (config.walletManagement) {
37
- yield walletConnect();
26
+ yield connect();
38
27
  }
39
28
  else {
40
29
  navigate(navigationRoutes.selectWallet);
41
30
  }
42
31
  }
43
- else if (switchChainAllowed) {
44
- yield switchChain(chainId);
45
- // check that the current route exists in the up to date route list
46
- }
47
32
  else {
48
33
  onClick === null || onClick === void 0 ? void 0 : onClick();
49
34
  }
50
35
  });
51
36
  const getButtonText = () => {
52
37
  if (account.isActive) {
53
- if (switchChainAllowed) {
54
- return t(`button.switchChain`);
55
- }
56
38
  if (!currentRoute) {
57
39
  return t(`button.swap`);
58
40
  }
@@ -60,7 +42,5 @@ export const SwapButton = ({ onClick, currentRoute, text, disable, }) => {
60
42
  }
61
43
  return t(`button.connectWallet`);
62
44
  };
63
- return (_jsx(Button, Object.assign({ variant: "contained", color: account.isActive ? 'primary' : 'success', onClick: handleSwapButtonClick, disabled: currentRoute &&
64
- !switchChainAllowed &&
65
- (insufficientFunds || !!insufficientGas.length || disable), fullWidth: true }, { children: getButtonText() })));
45
+ return (_jsx(Button, Object.assign({ variant: "contained", color: account.isActive ? 'primary' : 'success', onClick: handleSwapButtonClick, disabled: insufficientFunds || !!(insufficientGas === null || insufficientGas === void 0 ? void 0 : insufficientGas.length) || disable, fullWidth: true }, { children: getButtonText() })));
66
46
  };
@@ -50,5 +50,5 @@ export const TokenList = ({ formType, height, onClick, }) => {
50
50
  }
51
51
  onClick === null || onClick === void 0 ? void 0 : onClick();
52
52
  }, [formType, getValues, onClick, setValue]);
53
- return (_jsxs(Box, Object.assign({ ref: parentRef, style: { height, overflow: 'auto' } }, { children: [!tokens.length && !isLoading ? _jsx(TokenNotFound, {}) : null, _jsx(VirtualizedTokenList, { tokens: tokens, featuredTokensLength: featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.length, scrollElementRef: parentRef, chainId: selectedChainId, isLoading: isLoading, isBalanceLoading: isBalanceLoading, showBalance: account.isActive, showFeatured: !tokenSearchFilter, onClick: handleTokenClick })] })));
53
+ return (_jsxs(Box, Object.assign({ ref: parentRef, style: { height, overflow: 'auto' } }, { children: [!tokens.length && !isLoading ? (_jsx(TokenNotFound, { formType: formType })) : null, _jsx(VirtualizedTokenList, { tokens: tokens, featuredTokensLength: featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.length, scrollElementRef: parentRef, chainId: selectedChainId, isLoading: isLoading, isBalanceLoading: isBalanceLoading, showBalance: account.isActive, showFeatured: !tokenSearchFilter, onClick: handleTokenClick })] })));
54
54
  };
@@ -4,7 +4,8 @@ import { styled } from '@mui/material/styles';
4
4
  import { getContrastAlphaColor } from '../../utils';
5
5
  export const ListItemButton = styled(MuiListItemButton)(({ theme }) => ({
6
6
  borderRadius: theme.shape.borderRadiusSecondary,
7
- paddingLeft: theme.spacing(2),
7
+ paddingLeft: theme.spacing(1.5),
8
+ paddingRight: theme.spacing(1.5),
8
9
  height: 64,
9
10
  width: '100%',
10
11
  '&:hover': {
@@ -18,8 +19,8 @@ export const ListItem = styled(MuiListItem)(({ theme }) => ({
18
19
  height: 64,
19
20
  flexDirection: 'column',
20
21
  alignItems: 'flex-start',
21
- padding: theme.spacing(0, 3),
22
+ padding: theme.spacing(0, 1.5),
22
23
  [`.${listItemSecondaryActionClasses.root}`]: {
23
- right: theme.spacing(5),
24
+ right: theme.spacing(3),
24
25
  },
25
26
  }));
@@ -16,7 +16,7 @@ export const TokenListItem = memo(({ onClick, size, start, token, showBalance, i
16
16
  }) }))) : null] })))) : null] })), endAdornment] })));
17
17
  });
18
18
  export const TokenListItemSkeleton = () => {
19
- return (_jsxs(ListItem, Object.assign({ secondaryAction: _jsx(TokenAmountSkeleton, {}), disablePadding: true, sx: { position: 'relative', flexDirection: 'row', alignItems: 'center' } }, { children: [_jsx(ListItemAvatar, { children: _jsx(Skeleton, { variant: "circular", width: 32, height: 32, sx: { marginLeft: 2, marginRight: 2 } }) }), _jsx(ListItemText, { primary: _jsx(Skeleton, { variant: "text", width: 48, height: 20 }), secondary: _jsx(Skeleton, { variant: "text", width: 96, height: 20 }) })] })));
19
+ return (_jsxs(ListItem, Object.assign({ secondaryAction: _jsx(TokenAmountSkeleton, {}), disablePadding: true, sx: { position: 'relative', flexDirection: 'row', alignItems: 'center' } }, { children: [_jsx(ListItemAvatar, { children: _jsx(Skeleton, { variant: "circular", width: 32, height: 32, sx: { marginLeft: 1.5, marginRight: 2 } }) }), _jsx(ListItemText, { primary: _jsx(Skeleton, { variant: "text", width: 48, height: 20 }), secondary: _jsx(Skeleton, { variant: "text", width: 96, height: 20 }) })] })));
20
20
  };
21
21
  export const TokenAmountSkeleton = () => {
22
22
  return (_jsxs(Box, Object.assign({ sx: {
@@ -1,2 +1,3 @@
1
1
  /// <reference types="react" />
2
- export declare const TokenNotFound: React.FC;
2
+ import type { SwapFormTypeProps } from '../../providers';
3
+ export declare const TokenNotFound: React.FC<SwapFormTypeProps>;
@@ -1,9 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { SearchOff as SearchOffIcon } from '@mui/icons-material';
3
3
  import { Box, Typography } from '@mui/material';
4
+ import { useWatch } from 'react-hook-form';
4
5
  import { useTranslation } from 'react-i18next';
5
- export const TokenNotFound = () => {
6
+ import { useChains } from '../../hooks';
7
+ import { SwapFormKeyHelper } from '../../providers';
8
+ export const TokenNotFound = ({ formType }) => {
9
+ var _a;
6
10
  const { t } = useTranslation();
11
+ const [selectedChainId] = useWatch({
12
+ name: [SwapFormKeyHelper.getChainKey(formType)],
13
+ });
14
+ const { getChainById } = useChains();
7
15
  return (_jsxs(Box, Object.assign({ sx: {
8
16
  display: 'flex',
9
17
  justifyContent: 'center',
@@ -11,5 +19,7 @@ export const TokenNotFound = () => {
11
19
  flexDirection: 'column',
12
20
  flex: 1,
13
21
  padding: 3,
14
- } }, { children: [_jsx(Typography, Object.assign({ fontSize: 48, lineHeight: 1 }, { children: _jsx(SearchOffIcon, { fontSize: "inherit" }) })), _jsx(Typography, Object.assign({ fontSize: 14, color: "text.secondary", textAlign: "center", mt: 2, px: 2 }, { children: t('swap.couldntFindTokens') }))] })));
22
+ } }, { children: [_jsx(Typography, Object.assign({ fontSize: 48, lineHeight: 1 }, { children: _jsx(SearchOffIcon, { fontSize: "inherit" }) })), _jsx(Typography, Object.assign({ fontSize: 14, color: "text.secondary", textAlign: "center", mt: 2, px: 2 }, { children: t('swap.info.message.emptyTokenList', {
23
+ chainName: (_a = getChainById(selectedChainId)) === null || _a === void 0 ? void 0 : _a.name,
24
+ }) }))] })));
15
25
  };
@@ -1,9 +1,9 @@
1
1
  import type { TokenAmount } from '@lifi/sdk';
2
2
  import type { MutableRefObject } from 'react';
3
- import type { SwapFormDirection } from '../../providers';
3
+ import type { SwapFormType } from '../../providers';
4
4
  import type { Token } from '../../types';
5
5
  export interface TokenListProps {
6
- formType: SwapFormDirection;
6
+ formType: SwapFormType;
7
7
  height: number;
8
8
  onClick?(): void;
9
9
  }
@@ -1,2 +1,2 @@
1
1
  export declare const name = "@lifi/widget";
2
- export declare const version = "1.16.1";
2
+ export declare const version = "1.17.0";
package/config/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export const name = '@lifi/widget';
2
- export const version = '1.16.1';
2
+ export const version = '1.17.0';
@@ -9,24 +9,37 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { useQuery } from '@tanstack/react-query';
11
11
  import { useCallback } from 'react';
12
- import { useLiFi, useWidgetConfig } from '../providers';
13
- import { useSetChainOrder } from '../stores/chains';
12
+ import { useFormContext } from 'react-hook-form';
13
+ import { isItemAllowed, SwapFormKey, useLiFi, useWidgetConfig, } from '../providers';
14
+ import { useChainOrderStore } from '../stores/chains';
14
15
  export const useChains = () => {
15
- const { disabledChains } = useWidgetConfig();
16
+ const { disabledChains, chains } = useWidgetConfig();
16
17
  const lifi = useLiFi();
17
- const [, initializeChains] = useSetChainOrder();
18
+ const { getValues, setValue } = useFormContext();
18
19
  const { data, isLoading } = useQuery(['chains'], () => __awaiter(void 0, void 0, void 0, function* () {
19
- const chains = yield lifi.getChains();
20
- const filteredChains = chains.filter((chain) => !(disabledChains === null || disabledChains === void 0 ? void 0 : disabledChains.includes(chain.id)));
21
- initializeChains(filteredChains.map((chain) => chain.id));
22
- return filteredChains;
20
+ const availableChains = yield lifi.getChains();
21
+ const filteredChains = availableChains.filter((chain) => isItemAllowed(chain.id, chains, disabledChains));
22
+ const chainOrder = useChainOrderStore
23
+ .getState()
24
+ .initializeChains(filteredChains.map((chain) => chain.id));
25
+ const [fromChainValue, toChainValue] = getValues([
26
+ SwapFormKey.FromChain,
27
+ SwapFormKey.ToChain,
28
+ ]);
29
+ if (!fromChainValue) {
30
+ setValue(SwapFormKey.FromChain, chainOrder[0]);
31
+ }
32
+ if (!toChainValue) {
33
+ setValue(SwapFormKey.ToChain, chainOrder[0]);
34
+ }
35
+ return { availableChains, filteredChains };
23
36
  }));
24
37
  const getChainById = useCallback((chainId) => {
25
- const chain = data === null || data === void 0 ? void 0 : data.find((chain) => chain.id === chainId);
38
+ const chain = data === null || data === void 0 ? void 0 : data.availableChains.find((chain) => chain.id === chainId);
26
39
  // if (!chain) {
27
40
  // throw new Error('Chain not found or chainId is invalid.');
28
41
  // }
29
42
  return chain;
30
43
  }, [data]);
31
- return { chains: data, getChainById, isLoading };
44
+ return { chains: data === null || data === void 0 ? void 0 : data.filteredChains, getChainById, isLoading };
32
45
  };
@@ -1 +1 @@
1
- export declare const useFeaturedTokens: (selectedChainId: number) => import("@lifi/types").Token[] | undefined;
1
+ export declare const useFeaturedTokens: (selectedChainId?: number) => import("@lifi/types").Token[];
@@ -1,6 +1,9 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useWidgetConfig } from '../providers';
3
3
  export const useFeaturedTokens = (selectedChainId) => {
4
- const { featuredTokens } = useWidgetConfig();
5
- return useMemo(() => featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.filter((token) => token.chainId === selectedChainId), [featuredTokens, selectedChainId]);
4
+ const { featuredTokens, tokens } = useWidgetConfig();
5
+ return useMemo(() => {
6
+ var _a;
7
+ return [...((_a = tokens === null || tokens === void 0 ? void 0 : tokens.featured) !== null && _a !== void 0 ? _a : []), ...(featuredTokens !== null && featuredTokens !== void 0 ? featuredTokens : [])].filter((token) => token.chainId === selectedChainId);
8
+ }, [featuredTokens, selectedChainId, tokens === null || tokens === void 0 ? void 0 : tokens.featured]);
6
9
  };
@@ -9,7 +9,7 @@ interface GasSufficiency {
9
9
  chain?: EVMChain;
10
10
  }
11
11
  export declare const useGasSufficiency: (route?: Route) => {
12
- insufficientGas: GasSufficiency[];
12
+ insufficientGas: GasSufficiency[] | undefined;
13
13
  insufficientFunds: boolean;
14
14
  };
15
15
  export {};
@@ -1,10 +1,20 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import Big from 'big.js';
2
- import { useMemo } from 'react';
11
+ import { useCallback, useEffect, useMemo, useState } from 'react';
3
12
  import { useWatch } from 'react-hook-form';
4
13
  import { useChains, useDebouncedWatch } from '.';
5
- import { SwapFormKey, SwapFormKeyHelper, useWallet } from '../providers';
14
+ import { SwapFormKey, SwapFormKeyHelper, useLiFi, useWallet, } from '../providers';
6
15
  import { useTokenBalances } from './useTokenBalances';
7
16
  export const useGasSufficiency = (route) => {
17
+ const lifi = useLiFi();
8
18
  const { account } = useWallet();
9
19
  const [fromChainId, toChainId, fromToken] = useWatch({
10
20
  name: [
@@ -16,20 +26,12 @@ export const useGasSufficiency = (route) => {
16
26
  const fromAmount = useDebouncedWatch(SwapFormKey.FromAmount, 250);
17
27
  const { getChainById } = useChains();
18
28
  const { tokensWithBalance: fromChainTokenBalances } = useTokenBalances(fromChainId);
19
- const { tokensWithBalance: toChainTokenBalances } = useTokenBalances(toChainId);
20
- const insufficientGas = useMemo(() => {
29
+ const [insufficientGas, setInsufficientGas] = useState();
30
+ const checkInsufficientGas = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
21
31
  var _a;
22
- if (!account.isActive ||
23
- !route ||
24
- !fromAmount ||
25
- !fromChainTokenBalances ||
26
- !toChainTokenBalances) {
27
- return [];
32
+ if (!account.isActive || !route || !fromAmount) {
33
+ return;
28
34
  }
29
- const tokenBalancesByChain = {
30
- [fromChainId]: fromChainTokenBalances,
31
- [toChainId]: toChainTokenBalances,
32
- };
33
35
  const gasCosts = route.steps.reduce((groupedGasCosts, step) => {
34
36
  if (step.estimate.gasCosts) {
35
37
  const { token } = step.estimate.gasCosts[0];
@@ -54,30 +56,34 @@ export const useGasSufficiency = (route) => {
54
56
  route.fromToken.address === gasCosts[fromChainId].token.address) {
55
57
  gasCosts[fromChainId].tokenAmount = (_a = gasCosts[fromChainId]) === null || _a === void 0 ? void 0 : _a.gasAmount.plus(Big(fromAmount));
56
58
  }
59
+ const tokenBalances = yield lifi.getTokenBalances(account.address, Object.values(gasCosts).map((item) => item.token));
60
+ if (!(tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.length)) {
61
+ return;
62
+ }
57
63
  [fromChainId, toChainId].forEach((chainId) => {
58
- var _a, _b, _c, _d, _e, _f, _g;
64
+ var _a, _b, _c, _d, _e, _f;
59
65
  if (gasCosts[chainId]) {
60
- const gasTokenBalance = Big((_c = (_b = (_a = tokenBalancesByChain[chainId]) === null || _a === void 0 ? void 0 : _a.find((t) => t.address === gasCosts[chainId].token.address)) === null || _b === void 0 ? void 0 : _b.amount) !== null && _c !== void 0 ? _c : 0);
66
+ const gasTokenBalance = Big((_b = (_a = tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.find((t) => t.address === gasCosts[chainId].token.address)) === null || _a === void 0 ? void 0 : _a.amount) !== null && _b !== void 0 ? _b : 0);
61
67
  const insufficientFromChainGas = gasTokenBalance.lte(0) ||
62
- gasTokenBalance.lt((_d = gasCosts[chainId].gasAmount) !== null && _d !== void 0 ? _d : Big(0)) ||
63
- gasTokenBalance.lt((_e = gasCosts[chainId].tokenAmount) !== null && _e !== void 0 ? _e : Big(0));
68
+ gasTokenBalance.lt((_c = gasCosts[chainId].gasAmount) !== null && _c !== void 0 ? _c : Big(0)) ||
69
+ gasTokenBalance.lt((_d = gasCosts[chainId].tokenAmount) !== null && _d !== void 0 ? _d : Big(0));
64
70
  const insufficientFromChainGasAmount = insufficientFromChainGas
65
- ? (_g = (_f = gasCosts[chainId].tokenAmount) === null || _f === void 0 ? void 0 : _f.minus(gasTokenBalance)) !== null && _g !== void 0 ? _g : gasCosts[chainId].gasAmount.minus(gasTokenBalance)
71
+ ? (_f = (_e = gasCosts[chainId].tokenAmount) === null || _e === void 0 ? void 0 : _e.minus(gasTokenBalance)) !== null && _f !== void 0 ? _f : gasCosts[chainId].gasAmount.minus(gasTokenBalance)
66
72
  : undefined;
67
73
  gasCosts[chainId] = Object.assign(Object.assign({}, gasCosts[chainId]), { insufficient: insufficientFromChainGas, insufficientAmount: insufficientFromChainGasAmount });
68
74
  }
69
75
  });
70
76
  const gasCostResult = Object.values(gasCosts).filter((gasCost) => gasCost.insufficient);
71
- return gasCostResult;
72
- }, [
77
+ setInsufficientGas(gasCostResult);
78
+ }), [
79
+ account.address,
73
80
  account.isActive,
74
81
  fromAmount,
75
82
  fromChainId,
76
- fromChainTokenBalances,
77
83
  getChainById,
84
+ lifi,
78
85
  route,
79
86
  toChainId,
80
- toChainTokenBalances,
81
87
  ]);
82
88
  const insufficientFunds = useMemo(() => {
83
89
  var _a, _b;
@@ -90,6 +96,9 @@ export const useGasSufficiency = (route) => {
90
96
  const balance = Big((_b = (_a = fromChainTokenBalances === null || fromChainTokenBalances === void 0 ? void 0 : fromChainTokenBalances.find((t) => t.address === fromToken)) === null || _a === void 0 ? void 0 : _a.amount) !== null && _b !== void 0 ? _b : 0);
91
97
  return Big(fromAmount).gt(balance);
92
98
  }, [account.isActive, fromAmount, fromChainTokenBalances, fromToken]);
99
+ useEffect(() => {
100
+ checkInsufficientGas();
101
+ }, [checkInsufficientGas]);
93
102
  return {
94
103
  insufficientGas,
95
104
  insufficientFunds,
@@ -1,5 +1,4 @@
1
1
  export declare const useToken: (chainId: number, tokenAddress: string) => {
2
2
  token: import("..").Token | undefined;
3
3
  isLoading: boolean;
4
- isFetching: boolean;
5
4
  };
package/hooks/useToken.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useTokens } from './useTokens';
3
3
  export const useToken = (chainId, tokenAddress) => {
4
- const { tokens, isLoading, isFetching } = useTokens(chainId);
4
+ const { tokens, isLoading } = useTokens(chainId);
5
5
  const token = useMemo(() => {
6
6
  const token = tokens === null || tokens === void 0 ? void 0 : tokens.find((token) => token.address === tokenAddress && token.chainId === chainId);
7
7
  return token;
@@ -9,6 +9,5 @@ export const useToken = (chainId, tokenAddress) => {
9
9
  return {
10
10
  token,
11
11
  isLoading,
12
- isFetching,
13
12
  };
14
13
  };
@@ -2,9 +2,8 @@ import type { Token } from '../types';
2
2
  export declare const useTokenBalances: (selectedChainId: number) => {
3
3
  tokens: Token[] | undefined;
4
4
  tokensWithBalance: Token[] | undefined;
5
- featuredTokens: import("@lifi/types").Token[] | undefined;
5
+ featuredTokens: import("@lifi/types").Token[];
6
6
  isLoading: boolean;
7
7
  isBalanceLoading: boolean;
8
- isBalanceFetched: boolean;
9
8
  refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<Token[] | undefined, unknown>>;
10
9
  };
@@ -23,7 +23,7 @@ export const useTokenBalances = (selectedChainId) => {
23
23
  const { tokens, isLoading } = useTokens(selectedChainId);
24
24
  const [refetchInterval, setRefetchInterval] = useState(defaultRefetchInterval);
25
25
  const isBalanceLoadingEnabled = Boolean(account.address) && Boolean(tokens === null || tokens === void 0 ? void 0 : tokens.length);
26
- const { data: tokensWithBalance, isLoading: isBalanceLoading, isFetched: isBalanceFetched, refetch, } = useQuery(['token-balances', account.address, selectedChainId, tokens === null || tokens === void 0 ? void 0 : tokens.length], ({ queryKey: [, accountAddress] }) => __awaiter(void 0, void 0, void 0, function* () {
26
+ const { data: tokensWithBalance, isLoading: isBalanceLoading, refetch, } = useQuery(['token-balances', account.address, selectedChainId, tokens === null || tokens === void 0 ? void 0 : tokens.length], ({ queryKey: [, accountAddress] }) => __awaiter(void 0, void 0, void 0, function* () {
27
27
  if (!accountAddress || !tokens) {
28
28
  return;
29
29
  }
@@ -70,7 +70,6 @@ export const useTokenBalances = (selectedChainId) => {
70
70
  featuredTokens,
71
71
  isLoading,
72
72
  isBalanceLoading: isBalanceLoading && isBalanceLoadingEnabled,
73
- isBalanceFetched,
74
73
  refetch,
75
74
  };
76
75
  };
@@ -1,6 +1,5 @@
1
1
  import type { Token } from '../types';
2
- export declare const useTokens: (selectedChainId: number) => {
2
+ export declare const useTokens: (selectedChainId?: number) => {
3
3
  tokens: Token[] | undefined;
4
4
  isLoading: boolean;
5
- isFetching: boolean;
6
5
  };
@@ -8,26 +8,48 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { useQuery } from '@tanstack/react-query';
11
- import { useLiFi } from '../providers';
11
+ import { isItemAllowed, useLiFi, useWidgetConfig } from '../providers';
12
12
  import { useFeaturedTokens } from './useFeaturedTokens';
13
13
  export const useTokens = (selectedChainId) => {
14
+ var _a, _b, _c, _d;
14
15
  const lifi = useLiFi();
15
16
  const featuredTokens = useFeaturedTokens(selectedChainId);
16
- const { data: tokens, isLoading, isFetching, } = useQuery(['tokens', selectedChainId, featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.length], () => __awaiter(void 0, void 0, void 0, function* () {
17
- var _a, _b, _c;
18
- const data = yield lifi.getTokens({ chains: [selectedChainId] });
17
+ const { tokens, chains, disabledChains } = useWidgetConfig();
18
+ const { data, isLoading } = useQuery([
19
+ 'tokens',
20
+ selectedChainId,
21
+ featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.length,
22
+ (_a = tokens === null || tokens === void 0 ? void 0 : tokens.allow) === null || _a === void 0 ? void 0 : _a.length,
23
+ (_b = tokens === null || tokens === void 0 ? void 0 : tokens.deny) === null || _b === void 0 ? void 0 : _b.length,
24
+ (_c = chains === null || chains === void 0 ? void 0 : chains.allow) === null || _c === void 0 ? void 0 : _c.length,
25
+ (_d = chains === null || chains === void 0 ? void 0 : chains.deny) === null || _d === void 0 ? void 0 : _d.length,
26
+ ], () => __awaiter(void 0, void 0, void 0, function* () {
27
+ var _e, _f, _g, _h, _j;
28
+ const chainAllowed = selectedChainId &&
29
+ isItemAllowed(selectedChainId, chains, disabledChains);
30
+ if (!chainAllowed) {
31
+ return [];
32
+ }
33
+ let filteredTokens = (_e = tokens === null || tokens === void 0 ? void 0 : tokens.allow) === null || _e === void 0 ? void 0 : _e.filter((token) => token.chainId === selectedChainId);
34
+ if (!(filteredTokens === null || filteredTokens === void 0 ? void 0 : filteredTokens.length)) {
35
+ const data = yield lifi.getTokens({ chains: [selectedChainId] });
36
+ filteredTokens = (_f = data.tokens) === null || _f === void 0 ? void 0 : _f[selectedChainId];
37
+ }
38
+ const deniedTokenAddresses = (_g = tokens === null || tokens === void 0 ? void 0 : tokens.deny) === null || _g === void 0 ? void 0 : _g.filter((token) => token.chainId === selectedChainId).map((token) => token.address);
39
+ if (deniedTokenAddresses === null || deniedTokenAddresses === void 0 ? void 0 : deniedTokenAddresses.length) {
40
+ filteredTokens = filteredTokens === null || filteredTokens === void 0 ? void 0 : filteredTokens.filter((token) => !deniedTokenAddresses.includes(token.address));
41
+ }
19
42
  const featuredTokenAddresses = new Set(featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.map((token) => token.address));
20
43
  return [
21
- ...((_a = featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.map((token) => {
44
+ ...((_h = featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.map((token) => {
22
45
  token.featured = true;
23
46
  return token;
24
- })) !== null && _a !== void 0 ? _a : []),
25
- ...((_c = (_b = data.tokens) === null || _b === void 0 ? void 0 : _b[selectedChainId].filter((token) => !featuredTokenAddresses.has(token.address))) !== null && _c !== void 0 ? _c : []),
47
+ })) !== null && _h !== void 0 ? _h : []),
48
+ ...((_j = filteredTokens === null || filteredTokens === void 0 ? void 0 : filteredTokens.filter((token) => !featuredTokenAddresses.has(token.address))) !== null && _j !== void 0 ? _j : []),
26
49
  ];
27
50
  }));
28
51
  return {
29
- tokens,
52
+ tokens: data,
30
53
  isLoading,
31
- isFetching,
32
54
  };
33
55
  };
package/hooks/useTools.js CHANGED
@@ -1,14 +1,19 @@
1
1
  import { useQuery } from '@tanstack/react-query';
2
2
  import { useMemo } from 'react';
3
- import { useLiFi } from '../providers';
3
+ import { isItemAllowed, useLiFi, useWidgetConfig } from '../providers';
4
4
  import { useSettingsStore } from '../stores';
5
5
  export const useTools = () => {
6
6
  const lifi = useLiFi();
7
- const initializeTools = useSettingsStore((state) => state.initializeTools);
7
+ const { bridges, exchanges } = useWidgetConfig();
8
8
  const { data } = useQuery(['tools'], ({ signal }) => lifi.getTools(undefined, { signal }), {
9
9
  onSuccess(data) {
10
- initializeTools('Bridges', data.bridges.map((bridge) => bridge.key));
11
- initializeTools('Exchanges', data.exchanges.map((exchange) => exchange.key));
10
+ const { initializeTools } = useSettingsStore.getState();
11
+ initializeTools('Bridges', data.bridges
12
+ .filter((bridge) => isItemAllowed(bridge.key, bridges))
13
+ .map((bridge) => bridge.key));
14
+ initializeTools('Exchanges', data.exchanges
15
+ .filter((exchange) => isItemAllowed(exchange.key, exchanges))
16
+ .map((exchange) => exchange.key));
12
17
  },
13
18
  });
14
19
  const formattedTools = useMemo(() => ({
@@ -15,7 +15,6 @@
15
15
  },
16
16
  "button": {
17
17
  "connectWallet": "Connect wallet",
18
- "switchChain": "Switch chain",
19
18
  "swap": "Swap",
20
19
  "reviewSwap": "Review swap",
21
20
  "startSwap": "Start swap",
@@ -56,7 +55,6 @@
56
55
  "featuredTokens": "Featured tokens",
57
56
  "otherTokens": "Other tokens",
58
57
  "inProgress": "in progress",
59
- "couldntFindTokens": "We couldn't find tokens on this chain or you don't have any.",
60
58
  "stepSwap": "Swap",
61
59
  "stepBridge": "Bridge",
62
60
  "stepSwapAndBridge": "Swap and bridge",
@@ -92,7 +90,8 @@
92
90
  "message": {
93
91
  "routeNotFound": "Try another token combination.",
94
92
  "emptySwapHistory": "Swap history is only stored locally and will be deleted if you clear your browser data.",
95
- "emptyActiveSwaps": "Swaps in progress will appear here. Once completed, find them in swap history."
93
+ "emptyActiveSwaps": "Swaps in progress will appear here. Once completed, find them in swap history.",
94
+ "emptyTokenList": "We couldn't find tokens on {{chainName}} chain or you don't have any. Please try search again or choose another chain."
96
95
  }
97
96
  },
98
97
  "warning": {
package/i18n/index.d.ts CHANGED
@@ -18,7 +18,6 @@ export declare const resources: {
18
18
  };
19
19
  button: {
20
20
  connectWallet: string;
21
- switchChain: string;
22
21
  swap: string;
23
22
  reviewSwap: string;
24
23
  startSwap: string;
@@ -59,7 +58,6 @@ export declare const resources: {
59
58
  featuredTokens: string;
60
59
  otherTokens: string;
61
60
  inProgress: string;
62
- couldntFindTokens: string;
63
61
  stepSwap: string;
64
62
  stepBridge: string;
65
63
  stepSwapAndBridge: string;
@@ -96,6 +94,7 @@ export declare const resources: {
96
94
  routeNotFound: string;
97
95
  emptySwapHistory: string;
98
96
  emptyActiveSwaps: string;
97
+ emptyTokenList: string;
99
98
  };
100
99
  };
101
100
  warning: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/widget",
3
- "version": "1.16.1",
3
+ "version": "1.17.0",
4
4
  "description": "LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./index.js",
@@ -50,7 +50,7 @@
50
50
  "@sentry/integrations": "^7.12.1",
51
51
  "@sentry/react": "^7.12.1",
52
52
  "@sentry/tracing": "^7.12.1",
53
- "@tanstack/react-query": "^4.2.3",
53
+ "@tanstack/react-query": "^4.3.4",
54
54
  "@tanstack/react-virtual": "^3.0.0-beta.17",
55
55
  "big.js": "^6.2.1",
56
56
  "events": "^3.3.0",
@@ -58,8 +58,8 @@
58
58
  "immer": "^9.0.15",
59
59
  "react": "^18.2.0",
60
60
  "react-dom": "^18.2.0",
61
- "react-hook-form": "^7.34.2",
62
- "react-i18next": "^11.18.5",
61
+ "react-hook-form": "^7.35.0",
62
+ "react-i18next": "^11.18.6",
63
63
  "react-router-dom": "^6.3.0",
64
64
  "react-timer-hook": "^3.0.5",
65
65
  "zustand": "^4.1.1"
@@ -28,5 +28,5 @@ export const MainSwapButton = () => {
28
28
  });
29
29
  }
30
30
  });
31
- return (_jsx(SwapButton, { onClick: handleClick, currentRoute: currentRoute, disable: isLoading || isFetching || !currentRoute || isValidating || !isValid }));
31
+ return (_jsx(SwapButton, { onClick: handleClick, currentRoute: currentRoute, disable: isLoading || isFetching || isValidating || !isValid }));
32
32
  };
@@ -2,12 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Typography } from '@mui/material';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { Switch } from '../../components/Switch';
5
- import { useSetSettings, useSettings } from '../../stores';
5
+ import { useSettings, useSettingsStore } from '../../stores';
6
6
  import { EnabledBridgesSelect } from './EnabledBridgesSelect';
7
7
  import { EnabledExchangesSelect } from './EnabledExchangesSelect';
8
8
  export const AdvancedPreferences = () => {
9
9
  const { t } = useTranslation();
10
- const [setValue] = useSetSettings();
10
+ const setValue = useSettingsStore((state) => state.setValue);
11
11
  const { advancedPreferences } = useSettings(['advancedPreferences']);
12
12
  const handleAdvancedPreferences = (_, checked) => {
13
13
  setValue('advancedPreferences', checked);
@@ -4,10 +4,10 @@ import { FormControl, MenuItem } from '@mui/material';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { Card, CardTitle } from '../../components/Card';
6
6
  import { Select } from '../../components/Select';
7
- import { useSetSettings, useSettings } from '../../stores';
7
+ import { useSettings, useSettingsStore } from '../../stores';
8
8
  export const GasPriceSelect = () => {
9
9
  const { t } = useTranslation();
10
- const [setValue] = useSetSettings();
10
+ const setValue = useSettingsStore((state) => state.setValue);
11
11
  const { gasPrice } = useSettings(['gasPrice']);
12
12
  return (_jsxs(Card, Object.assign({ flex: 1 }, { children: [_jsx(CardTitle, { children: t(`settings.gasPrice.title`) }), _jsx(FormControl, Object.assign({ fullWidth: true }, { children: _jsxs(Select, Object.assign({ MenuProps: { elevation: 2 }, value: gasPrice, onChange: (event) => setValue('gasPrice', event.target.value), IconComponent: KeyboardArrowDownIcon, dense: true }, { children: [_jsx(MenuItem, Object.assign({ value: "slow" }, { children: t(`settings.gasPrice.slow`) })), _jsx(MenuItem, Object.assign({ value: "normal" }, { children: t(`settings.gasPrice.normal`) })), _jsx(MenuItem, Object.assign({ value: "fast" }, { children: t(`settings.gasPrice.fast`) }))] })) }))] })));
13
13
  };