@lifi/widget 1.0.0 → 1.1.1

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 (36) hide show
  1. package/README.md +19 -0
  2. package/components/ProgressToNextUpdate/ProgressToNextUpdate.js +9 -11
  3. package/components/SwapButton/ButtonTooltip.d.ts +1 -0
  4. package/components/SwapInput/SwapInputAdornment.d.ts +1 -0
  5. package/components/SwapRouteCard/SwapRouteCard.js +5 -1
  6. package/components/SwapRouteCard/SwapRouteCard.style.js +2 -2
  7. package/components/SwapRoutes/SwapRoutes.js +1 -1
  8. package/components/TokenList/TokenList.js +10 -3
  9. package/config/env.d.ts +0 -9
  10. package/config/env.js +1 -17
  11. package/hooks/useChains.js +2 -2
  12. package/hooks/useDebouncedWatch.js +7 -2
  13. package/hooks/useRouteExecution/useRouteExecution.js +3 -3
  14. package/hooks/useSwapRoutes.js +17 -8
  15. package/i18n/en/translation.json +8 -4
  16. package/i18n/index.d.ts +8 -4
  17. package/lifi.js +1 -4
  18. package/package.json +20 -8
  19. package/pages/SelectTokenPage/ChainSelect.d.ts +1 -0
  20. package/pages/SelectTokenPage/SearchTokenInput.d.ts +1 -0
  21. package/pages/SelectTokenPage/SelectTokenPage.js +9 -2
  22. package/pages/SelectWalletPage/SelectWalletPage.d.ts +1 -0
  23. package/pages/SettingsPage/AdvancedPreferences.d.ts +1 -0
  24. package/pages/SettingsPage/GasPriceSelect.d.ts +1 -0
  25. package/pages/SettingsPage/GasPriceSelect.js +2 -2
  26. package/pages/SettingsPage/RoutePrioritySelect.js +3 -2
  27. package/pages/SettingsPage/SettingsPage.d.ts +1 -0
  28. package/pages/SettingsPage/SlippageInput.d.ts +1 -0
  29. package/pages/SwapPage/CircularProgress.d.ts +1 -0
  30. package/providers/SwapFormProvider/SwapFormProvider.d.ts +7 -0
  31. package/providers/SwapFormProvider/SwapFormProvider.js +4 -3
  32. package/providers/SwapFormProvider/types.d.ts +2 -1
  33. package/providers/WidgetProvider/WidgetProvider.js +5 -4
  34. package/types/widget.d.ts +1 -1
  35. package/config/rpcs.d.ts +0 -1
  36. package/config/rpcs.js +0 -20
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # @lifi/widget
2
+
3
+ LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.
4
+
5
+ ## Installation
6
+
7
+ Install the package in your project directory with:
8
+
9
+ ```sh
10
+ // with npm
11
+ npm install @lifi/widget
12
+
13
+ // with yarn
14
+ yarn add @lifi/widget
15
+ ```
16
+
17
+ ## Documentation
18
+
19
+ [The documentation.](https://docs.li.fi/)
@@ -2,20 +2,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, CircularProgress, IconButton, Tooltip, } from '@mui/material';
3
3
  import { useEffect, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
- const calculateTime = (updatedAt, timeToUpdate) => {
6
- if (updatedAt === 0) {
7
- return 0;
8
- }
9
- const progress = ((Date.now() - updatedAt) / timeToUpdate) * 100;
10
- return Math.min(100, progress);
11
- };
5
+ const getProgressValue = (updatedAt, timeToUpdate) => updatedAt
6
+ ? Math.min(100, ((Date.now() - updatedAt) / timeToUpdate) * 100)
7
+ : 0;
8
+ const getSecondsToUpdate = (updatedAt, timeToUpdate) => Math.max(Math.round((timeToUpdate - (Date.now() - updatedAt)) / 1000), 0);
12
9
  export const ProgressToNextUpdate = ({ updatedAt, timeToUpdate, isLoading, onClick, sx }) => {
13
10
  const { t } = useTranslation();
14
- const [value, setValue] = useState(() => calculateTime(updatedAt, timeToUpdate));
11
+ const [value, setValue] = useState(() => getProgressValue(updatedAt, timeToUpdate));
15
12
  useEffect(() => {
13
+ setValue(getProgressValue(updatedAt, timeToUpdate));
16
14
  const id = setInterval(() => {
17
- const time = calculateTime(updatedAt, timeToUpdate);
18
- setValue(calculateTime(updatedAt, timeToUpdate));
15
+ const time = getProgressValue(updatedAt, timeToUpdate);
16
+ setValue(time);
19
17
  if (time >= 100) {
20
18
  clearInterval(id);
21
19
  }
@@ -28,7 +26,7 @@ export const ProgressToNextUpdate = ({ updatedAt, timeToUpdate, isLoading, onCli
28
26
  }
29
27
  }, [isLoading]);
30
28
  return (_jsx(IconButton, Object.assign({ onClick: onClick, sx: sx, disabled: isLoading }, { children: _jsx(Tooltip, Object.assign({ title: t('tooltip.progressToNextUpdate', {
31
- value: Math.round((timeToUpdate - (Date.now() - updatedAt)) / 1000),
29
+ value: getSecondsToUpdate(updatedAt, timeToUpdate),
32
30
  }), placement: "top", enterDelay: 250, arrow: true }, { children: _jsxs(Box, Object.assign({ sx: {
33
31
  display: 'grid',
34
32
  position: 'relative',
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  export declare const ButtonTooltip: ({ title, children, }: {
2
3
  title?: string | undefined;
3
4
  children: JSX.Element;
@@ -1,2 +1,3 @@
1
+ /// <reference types="react" />
1
2
  import { SwapFormTypeProps } from '../../providers/SwapFormProvider';
2
3
  export declare const SwapInputAdornment: ({ formType }: SwapFormTypeProps) => JSX.Element;
@@ -17,13 +17,17 @@ import { StepActions } from '../StepActions';
17
17
  import { StepToken } from '../StepToken';
18
18
  import { Card, Check, Label } from './SwapRouteCard.style';
19
19
  export const SwapRouteCard = (_a) => {
20
+ var _b;
20
21
  var { route, active, dense } = _a, other = __rest(_a, ["route", "active", "dense"]);
21
22
  const { t } = useTranslation();
23
+ const label = ((_b = route.tags) === null || _b === void 0 ? void 0 : _b.length)
24
+ ? t(`swap.tags.${route.tags[0].toLowerCase()}`).toUpperCase()
25
+ : t(`swap.tags.general`).toUpperCase();
22
26
  return (_jsx(Card, Object.assign({ active: active, dense: dense }, other, { children: _jsxs(Box, { children: [_jsxs(Box, Object.assign({ sx: {
23
27
  display: 'flex',
24
28
  alignItems: 'center',
25
29
  justifyContent: 'space-between',
26
- }, mb: 2 }, { children: [_jsx(Label, { children: "GENERAL" }), active ? (_jsx(Check, { children: _jsx(CheckIcon, { fontSize: "inherit" }) })) : null] })), _jsx(StepToken, { token: Object.assign(Object.assign({}, route.toToken), { amount: route.toAmount }), mb: 2 }), !dense
30
+ }, mb: 2 }, { children: [_jsx(Label, { children: label }), active ? (_jsx(Check, { children: _jsx(CheckIcon, { fontSize: "inherit" }) })) : null] })), _jsx(StepToken, { token: Object.assign(Object.assign({}, route.toToken), { amount: route.toAmount }), mb: 2 }), !dense
27
31
  ? route.steps.map((step) => (_jsx(StepActions, { step: step, mb: 2 }, step.id)))
28
32
  : null, _jsxs(Box, Object.assign({ sx: {
29
33
  display: 'flex',
@@ -49,9 +49,9 @@ export const Label = styled(Typography, {
49
49
  : theme.palette.mode === 'light'
50
50
  ? theme.palette.common.black
51
51
  : theme.palette.grey[300],
52
- padding: theme.spacing(0.5, 0.75),
52
+ padding: theme.spacing(0.75),
53
53
  fontSize: 12,
54
- lineHeight: 1.2,
54
+ lineHeight: 1,
55
55
  fontWeight: '600',
56
56
  height: 24,
57
57
  letterSpacing: '0.05rem',
@@ -29,5 +29,5 @@ export const SwapRoutes = (props) => {
29
29
  } }), _jsxs(Box, Object.assign({ sx: { display: 'flex', alignItems: 'center' } }, { children: [_jsx(Stack, Object.assign({ direction: "row", py: 2, pl: 2, pr: 1 }, { children: isLoading || isFetching || !currentRoute ? (_jsx(Skeleton, { variant: "rectangular", width: "100%", height: 181, sx: (theme) => ({
30
30
  borderRadius: theme.shape.borderRadiusSecondary / theme.shape.borderRadius,
31
31
  minWidth: '100%',
32
- }) })) : (_jsx(SwapRouteCard, { minWidth: "100%", route: currentRoute, active: true, dense: true }, currentRoute.id)) })), _jsx(Box, Object.assign({ py: 1, pr: 1 }, { children: _jsx(IconButton, Object.assign({ onClick: handleCardClick, size: "medium", "aria-label": "swap-routes" }, { children: _jsx(KeyboardArrowRightIcon, {}) })) }))] }))] })));
32
+ }) })) : (_jsx(SwapRouteCard, { minWidth: "100%", route: currentRoute, active: true, dense: true })) })), _jsx(Box, Object.assign({ py: 1, pr: 1 }, { children: _jsx(IconButton, Object.assign({ onClick: handleCardClick, size: "medium", "aria-label": "swap-routes" }, { children: _jsx(KeyboardArrowRightIcon, {}) })) }))] }))] })));
33
33
  };
@@ -12,12 +12,12 @@ import { createTokenAmountSkeletons, skeletonKey } from './utils';
12
12
  export const TokenList = ({ formType, height, onClick, }) => {
13
13
  const { t } = useTranslation();
14
14
  const { account } = useWallet();
15
- const { setValue } = useFormContext();
15
+ const { setValue, getValues } = useFormContext();
16
16
  const [selectedChainId] = useWatch({
17
17
  name: [SwapFormKeyHelper.getChainKey(formType)],
18
18
  });
19
19
  const [searchTokensFilter] = useDebouncedWatch([SwapFormKey.SearchTokensFilter], 250);
20
- const { tokens, isLoading, isFetching } = useTokenBalances(selectedChainId);
20
+ const { tokens, isLoading } = useTokenBalances(selectedChainId);
21
21
  const chainTokens = useMemo(() => {
22
22
  var _a;
23
23
  let chainTokens = tokens !== null && tokens !== void 0 ? tokens : [];
@@ -46,8 +46,15 @@ export const TokenList = ({ formType, height, onClick, }) => {
46
46
  const handleTokenClick = useCallback((tokenAddress) => {
47
47
  setValue(SwapFormKeyHelper.getTokenKey(formType), tokenAddress);
48
48
  setValue(SwapFormKeyHelper.getAmountKey(formType), '');
49
+ const oppositeFormType = formType === 'from' ? 'to' : 'from';
50
+ const [selectedOppositeToken] = getValues([
51
+ SwapFormKeyHelper.getTokenKey(oppositeFormType),
52
+ ]);
53
+ if (selectedOppositeToken === tokenAddress) {
54
+ setValue(SwapFormKeyHelper.getTokenKey(oppositeFormType), '');
55
+ }
49
56
  onClick === null || onClick === void 0 ? void 0 : onClick();
50
- }, [formType, onClick, setValue]);
57
+ }, [formType, getValues, onClick, setValue]);
51
58
  return (_jsxs(Box, Object.assign({ ref: parentRef, style: { height, overflow: 'auto' } }, { children: [!virtualItems.length ? (_jsx(Typography, Object.assign({ variant: "body1", align: "center", py: 2, px: 3 }, { children: t('swap.couldntFindTokens') }))) : null, _jsx(List, Object.assign({ style: { height: totalSize }, disablePadding: true }, { children: virtualItems.map((item) => {
52
59
  const token = chainTokens[item.index];
53
60
  if (token.name.includes(skeletonKey)) {
package/config/env.d.ts CHANGED
@@ -1,12 +1,3 @@
1
1
  export declare const env: {
2
2
  LIFI_API_URL: string;
3
- LIFI_RPC_URL_MAINNET: string;
4
- LIFI_RPC_URL_ROPSTEN: string;
5
- LIFI_RPC_URL_RINKEBY: string;
6
- LIFI_RPC_URL_GORLI: string;
7
- LIFI_RPC_URL_KOVAN: string;
8
- LIFI_RPC_URL_ARBITRUM_RINKEBY: string;
9
- LIFI_RPC_URL_OPTIMISM_KOVAN: string;
10
- LIFI_RPC_URL_POLYGON_MUMBAI: string;
11
- LIFI_RPC_URL_BSC_TESTNET: string;
12
3
  };
package/config/env.js CHANGED
@@ -1,19 +1,3 @@
1
1
  export const env = {
2
- LIFI_API_URL: 'https://li.quest/v1/',
3
- // RPC - Mainnet (overwrites)
4
- LIFI_RPC_URL_MAINNET: 'https://speedy-nodes-nyc.moralis.io/5ed6053dc39eba789ff466c9/eth/mainnet',
5
- // LIFI_RPC_URL_POLYGON:
6
- // LIFI_RPC_URL_BSC:
7
- // LIFI_RPC_URL_XDAI:
8
- // LIFI_RPC_URL_FANTOM:
9
- // LIFI_RPC_URL_ARBITRUM:
10
- // RPC - Testnet (overwrites)
11
- LIFI_RPC_URL_ROPSTEN: 'https://ropsten.infura.io/v3/c7fe4abb5bbc466cb56038efbb0b9930',
12
- LIFI_RPC_URL_RINKEBY: 'https://rinkeby.infura.io/v3/c7fe4abb5bbc466cb56038efbb0b9930',
13
- LIFI_RPC_URL_GORLI: 'https://goerli.infura.io/v3/c7fe4abb5bbc466cb56038efbb0b9930',
14
- LIFI_RPC_URL_KOVAN: 'https://kovan.infura.io/v3/c7fe4abb5bbc466cb56038efbb0b9930',
15
- LIFI_RPC_URL_ARBITRUM_RINKEBY: 'https://arbitrum-rinkeby.infura.io/v3/c7fe4abb5bbc466cb56038efbb0b9930',
16
- LIFI_RPC_URL_OPTIMISM_KOVAN: 'https://optimism-kovan.infura.io/v3/c7fe4abb5bbc466cb56038efbb0b9930',
17
- LIFI_RPC_URL_POLYGON_MUMBAI: 'https://rpc-mumbai.maticvigil.com/v1/e4dadaac060844094a667194c20f79cc9bb0bc59',
18
- LIFI_RPC_URL_BSC_TESTNET: 'https://data-seed-prebsc-1-s2.binance.org:8545',
2
+ LIFI_API_URL: 'https://li.quest/v1/', // 'https://developkub.li.finance/v1/',
19
3
  };
@@ -23,10 +23,10 @@ import { useQuery } from 'react-query';
23
23
  import { LiFi } from '../lifi';
24
24
  import { useWidgetConfig } from '../providers/WidgetProvider';
25
25
  export const useChains = () => {
26
- const { enabledChains } = useWidgetConfig();
26
+ const { disabledChains } = useWidgetConfig();
27
27
  const _a = useQuery(['chains'], () => __awaiter(void 0, void 0, void 0, function* () {
28
28
  const chains = yield LiFi.getChains();
29
- return chains.filter((chain) => enabledChains.includes(chain.id));
29
+ return chains.filter((chain) => !(disabledChains === null || disabledChains === void 0 ? void 0 : disabledChains.includes(chain.id)));
30
30
  })), { data } = _a, other = __rest(_a, ["data"]);
31
31
  const getChainById = useCallback((chainId) => {
32
32
  const chain = data === null || data === void 0 ? void 0 : data.find((chain) => chain.id === chainId);
@@ -5,18 +5,23 @@ export const useDebouncedWatch = (name, delay) => {
5
5
  name,
6
6
  });
7
7
  const [debouncedValue, setDebouncedValue] = useState(watchedValue);
8
+ const debouncedValueRef = useRef();
8
9
  const isMounted = useRef(false);
9
10
  useEffect(() => {
10
11
  if (isMounted.current) {
11
12
  const hasWatchedValue = Array.isArray(watchedValue)
12
13
  ? watchedValue.some((value) => value)
13
- : watchedValue;
14
- if (hasWatchedValue) {
14
+ : Boolean(watchedValue);
15
+ const hasDebouncedValue = Array.isArray(debouncedValueRef.current)
16
+ ? debouncedValueRef.current.some((value) => value)
17
+ : Boolean(debouncedValueRef.current);
18
+ if (hasWatchedValue && hasDebouncedValue) {
15
19
  const handler = setTimeout(() => {
16
20
  setDebouncedValue(watchedValue);
17
21
  }, delay);
18
22
  return () => clearTimeout(handler);
19
23
  }
24
+ debouncedValueRef.current = watchedValue;
20
25
  setDebouncedValue(watchedValue);
21
26
  return undefined;
22
27
  }
@@ -15,9 +15,9 @@ import { useWallet } from '../../providers/WalletProvider';
15
15
  import { deepClone } from '../../utils/deepClone';
16
16
  import { useRouteStore } from './useRouteStore';
17
17
  export const useRouteExecution = (routeId) => {
18
+ const { account, switchChain } = useWallet();
18
19
  const { route, status } = useRouteStore((state) => state.routes[routeId]);
19
20
  const [updateRoute, restartRoute, removeRoute] = useRouteStore((state) => [state.updateRoute, state.restartRoute, state.removeRoute], shallow);
20
- const { account, switchChain } = useWallet();
21
21
  const updateCallback = (updatedRoute) => {
22
22
  console.log('Route updated.', updatedRoute);
23
23
  updateRoute(deepClone(updatedRoute));
@@ -104,9 +104,9 @@ export const useRouteExecution = (routeId) => {
104
104
  }, [resumeRouteMutation, routeId]);
105
105
  const restartRouteMutation = useCallback(() => {
106
106
  restartRoute(routeId);
107
- resumeRoute(useRouteStore.getState().routes[routeId].route);
107
+ resumeRoute(route);
108
108
  // eslint-disable-next-line react-hooks/exhaustive-deps
109
- }, [resumeRoute, routeId]);
109
+ }, [resumeRoute, route, routeId]);
110
110
  const removeRouteMutation = useCallback(() => {
111
111
  removeRoute(routeId);
112
112
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { useEffect } from 'react';
11
11
  import { useWatch } from 'react-hook-form';
12
- import { useQuery } from 'react-query';
12
+ import { useQuery, useQueryClient } from 'react-query';
13
13
  import { useDebouncedWatch, useToken } from '.';
14
14
  import { LiFi } from '../lifi';
15
15
  import { SwapFormKey } from '../providers/SwapFormProvider';
@@ -17,9 +17,11 @@ import { useWallet } from '../providers/WalletProvider';
17
17
  import { useCurrentRoute } from './useRouteExecution';
18
18
  const refetchTime = 60000;
19
19
  export const useSwapRoutes = () => {
20
+ var _a;
20
21
  const { account } = useWallet();
22
+ const queryClient = useQueryClient();
21
23
  const [currentRoute, setCurrentRoute] = useCurrentRoute();
22
- const [fromChainId, fromTokenAddress, toChainId, toTokenAddress, slippage, enabledBridges, enabledExchanges,] = useWatch({
24
+ const [fromChainId, fromTokenAddress, toChainId, toTokenAddress, slippage, enabledBridges, enabledExchanges, routePriority,] = useWatch({
23
25
  name: [
24
26
  SwapFormKey.FromChain,
25
27
  SwapFormKey.FromToken,
@@ -28,6 +30,7 @@ export const useSwapRoutes = () => {
28
30
  SwapFormKey.Slippage,
29
31
  SwapFormKey.EnabledBridges,
30
32
  SwapFormKey.EnabledExchanges,
33
+ SwapFormKey.RoutePriority,
31
34
  ],
32
35
  });
33
36
  const [fromTokenAmount] = useDebouncedWatch([SwapFormKey.FromAmount], 500);
@@ -40,7 +43,7 @@ export const useSwapRoutes = () => {
40
43
  Boolean(fromTokenAmount) &&
41
44
  !isNaN(fromTokenAmount) &&
42
45
  !isNaN(slippage);
43
- const { data, isLoading, isFetching, dataUpdatedAt, refetch } = useQuery([
46
+ const queryKey = [
44
47
  'routes',
45
48
  account.address,
46
49
  fromChainId,
@@ -51,13 +54,19 @@ export const useSwapRoutes = () => {
51
54
  slippage,
52
55
  enabledBridges,
53
56
  enabledExchanges,
54
- ], ({ queryKey: [_, address, fromChainId, fromTokenAddress, fromTokenAmount, toChainId, toTokenAddress, slippage, enabledBridges, enabledExchanges,], signal, }) => __awaiter(void 0, void 0, void 0, function* () {
55
- var _a;
57
+ routePriority,
58
+ ];
59
+ const previousDataUpdatedAt = (_a = queryClient.getQueryState(queryKey)) === null || _a === void 0 ? void 0 : _a.dataUpdatedAt;
60
+ const refetchInterval = previousDataUpdatedAt
61
+ ? Math.min(Math.abs(refetchTime - (Date.now() - previousDataUpdatedAt)), refetchTime)
62
+ : refetchTime;
63
+ const { data, isLoading, isFetching, dataUpdatedAt, refetch } = useQuery(queryKey, ({ queryKey: [_, address, fromChainId, fromTokenAddress, fromTokenAmount, toChainId, toTokenAddress, slippage, enabledBridges, enabledExchanges, routePriority,], signal, }) => __awaiter(void 0, void 0, void 0, function* () {
64
+ var _b;
56
65
  return LiFi.getRoutes({
57
66
  fromChainId,
58
67
  // TODO: simplify
59
68
  fromAmount: (Number(fromTokenAmount) *
60
- Math.pow(10, ((_a = token === null || token === void 0 ? void 0 : token.decimals) !== null && _a !== void 0 ? _a : 0))).toFixed(0),
69
+ Math.pow(10, ((_b = token === null || token === void 0 ? void 0 : token.decimals) !== null && _b !== void 0 ? _b : 0))).toFixed(0),
61
70
  fromTokenAddress,
62
71
  toChainId,
63
72
  toTokenAddress,
@@ -71,14 +80,14 @@ export const useSwapRoutes = () => {
71
80
  exchanges: {
72
81
  allow: enabledExchanges,
73
82
  },
83
+ order: routePriority,
74
84
  },
75
85
  }, { signal });
76
86
  }), {
77
87
  enabled: isEnabled,
78
88
  refetchIntervalInBackground: true,
79
- refetchInterval: refetchTime,
89
+ refetchInterval,
80
90
  staleTime: refetchTime,
81
- // TODO: probably should be removed
82
91
  cacheTime: refetchTime,
83
92
  });
84
93
  useEffect(() => {
@@ -58,6 +58,13 @@
58
58
  "networkIsBusy": "Network is busy...",
59
59
  "crossStepDetails": "Bridge {{from}} to {{to}} via {{tool}}",
60
60
  "swapStepDetails": "Swap on {{value}}",
61
+ "tags": {
62
+ "recommended": "Recommended",
63
+ "fastest": "Fast",
64
+ "cheapest": "Cheap",
65
+ "safest": "Safe",
66
+ "general": "General"
67
+ },
61
68
  "success": {
62
69
  "title": {
63
70
  "fundsReceived": "Funds received"
@@ -110,10 +117,7 @@
110
117
  }
111
118
  },
112
119
  "settings": {
113
- "routePriority": {
114
- "title": "Route priority",
115
- "recommended": "Recommended"
116
- },
120
+ "routePriority": "Route priority",
117
121
  "slippage": "Slippage",
118
122
  "gasPrice": {
119
123
  "title": "Gas price",
package/i18n/index.d.ts CHANGED
@@ -61,6 +61,13 @@ export declare const resources: {
61
61
  networkIsBusy: string;
62
62
  crossStepDetails: string;
63
63
  swapStepDetails: string;
64
+ tags: {
65
+ recommended: string;
66
+ fastest: string;
67
+ cheapest: string;
68
+ safest: string;
69
+ general: string;
70
+ };
64
71
  success: {
65
72
  title: {
66
73
  fundsReceived: string;
@@ -113,10 +120,7 @@ export declare const resources: {
113
120
  };
114
121
  };
115
122
  settings: {
116
- routePriority: {
117
- title: string;
118
- recommended: string;
119
- };
123
+ routePriority: string;
120
124
  slippage: string;
121
125
  gasPrice: {
122
126
  title: string;
package/lifi.js CHANGED
@@ -1,9 +1,6 @@
1
1
  import LIFI from '@lifinance/sdk';
2
- import { env } from './config/env';
3
- import { getRpcs } from './config/rpcs';
4
2
  export const LiFi = new LIFI({
5
- apiUrl: env.LIFI_API_URL,
6
- rpcs: getRpcs(),
3
+ // apiUrl: env.LIFI_API_URL,
7
4
  defaultRouteOptions: {
8
5
  integrator: 'li.fi',
9
6
  },
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@lifi/widget",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
+ "description": "LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.",
4
5
  "sideEffects": false,
5
6
  "main": "./index.js",
6
7
  "module": "./index.js",
@@ -14,7 +15,6 @@
14
15
  "access": "public"
15
16
  },
16
17
  "author": "Eugene Chybisov <eugene@li.finance>",
17
- "license": "UNLICENSED",
18
18
  "homepage": "https://github.com/lifinance/widget",
19
19
  "repository": {
20
20
  "type": "git",
@@ -23,18 +23,30 @@
23
23
  "bugs": {
24
24
  "url": "https://github.com/lifinance/widget/issues"
25
25
  },
26
+ "keywords": [
27
+ "widget",
28
+ "lifi-widget",
29
+ "bridge",
30
+ "swap",
31
+ "cross-chain",
32
+ "multi-chain",
33
+ "metamask",
34
+ "ethereum",
35
+ "web3",
36
+ "lifi"
37
+ ],
26
38
  "dependencies": {
27
39
  "@emotion/react": "^11.9.0",
28
40
  "@emotion/styled": "^11.8.1",
29
41
  "@ethersproject/experimental": "^5.6.2",
30
42
  "@ethersproject/providers": "^5.6.8",
31
- "@lifi/wallet-management": "^1.0.0",
32
- "@lifinance/sdk": "^1.0.0-beta.8",
33
- "@mui/icons-material": "^5.8.2",
34
- "@mui/lab": "^5.0.0-alpha.84",
35
- "@mui/material": "^5.8.2",
43
+ "@lifi/wallet-management": "^1.0.1",
44
+ "@lifinance/sdk": "^1.0.0-beta.11",
45
+ "@mui/icons-material": "^5.8.3",
46
+ "@mui/lab": "^5.0.0-alpha.85",
47
+ "@mui/material": "^5.8.3",
36
48
  "big.js": "^6.2.0",
37
- "i18next": "^21.8.7",
49
+ "i18next": "^21.8.9",
38
50
  "immer": "^9.0.14",
39
51
  "react": "^18.1.0",
40
52
  "react-dom": "^18.1.0",
@@ -1,2 +1,3 @@
1
+ /// <reference types="react" />
1
2
  import { SwapFormTypeProps } from '../../providers/SwapFormProvider';
2
3
  export declare const ChainSelect: ({ formType }: SwapFormTypeProps) => JSX.Element;
@@ -1 +1,2 @@
1
+ /// <reference types="react" />
1
2
  export declare const SearchTokenInput: () => JSX.Element;
@@ -1,16 +1,23 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Container } from '@mui/material';
3
+ import { useLayoutEffect, useRef, useState } from 'react';
3
4
  import { useNavigate } from 'react-router-dom';
4
5
  import { TokenList } from '../../components/TokenList';
5
6
  import { useContentHeight, useScrollableOverflowHidden } from '../../hooks';
6
7
  import { ChainSelect } from './ChainSelect';
7
8
  import { SearchTokenInput } from './SearchTokenInput';
8
9
  export const SelectTokenPage = ({ formType, }) => {
9
- const navigate = useNavigate();
10
10
  useScrollableOverflowHidden();
11
+ const navigate = useNavigate();
12
+ const headerRef = useRef(null);
11
13
  const contentHeight = useContentHeight();
14
+ const [headerHeight, setHeaderHeight] = useState(0);
12
15
  const handleTokenClick = () => {
13
16
  navigate(-1);
14
17
  };
15
- return (_jsxs(Container, Object.assign({ disableGutters: true }, { children: [_jsxs(Box, Object.assign({ pt: 1, pb: 2, px: 3 }, { children: [_jsx(ChainSelect, { formType: formType }), _jsx(Box, Object.assign({ mt: 2 }, { children: _jsx(SearchTokenInput, {}) }))] })), _jsx(TokenList, { height: contentHeight - 184, onClick: handleTokenClick, formType: formType })] })));
18
+ useLayoutEffect(() => {
19
+ var _a, _b;
20
+ setHeaderHeight(contentHeight - ((_b = (_a = headerRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0));
21
+ }, [contentHeight]);
22
+ return (_jsxs(Container, Object.assign({ disableGutters: true }, { children: [_jsxs(Box, Object.assign({ pt: 1, pb: 2, px: 3, ref: headerRef }, { children: [_jsx(ChainSelect, { formType: formType }), _jsx(Box, Object.assign({ mt: 2 }, { children: _jsx(SearchTokenInput, {}) }))] })), _jsx(TokenList, { height: headerHeight, onClick: handleTokenClick, formType: formType })] })));
16
23
  };
@@ -1 +1,2 @@
1
+ /// <reference types="react" />
1
2
  export declare const SelectWalletPage: () => JSX.Element;
@@ -1 +1,2 @@
1
+ /// <reference types="react" />
1
2
  export declare const AdvancedPreferences: () => JSX.Element;
@@ -1 +1,2 @@
1
+ /// <reference types="react" />
1
2
  export declare const GasPriceSelect: () => JSX.Element;
@@ -5,9 +5,9 @@ import { useFormContext } from 'react-hook-form';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { CardContainer, CardTitle } from '../../components/Card';
7
7
  import { Select } from '../../components/Select';
8
- import { SwapFormKey } from '../../providers/SwapFormProvider';
8
+ import { formDefaultValues, SwapFormKey, } from '../../providers/SwapFormProvider';
9
9
  export const GasPriceSelect = () => {
10
10
  const { t } = useTranslation();
11
11
  const { register } = useFormContext();
12
- return (_jsxs(CardContainer, Object.assign({ flex: 1 }, { children: [_jsx(CardTitle, { children: t(`settings.gasPrice.title`) }), _jsx(FormControl, Object.assign({ fullWidth: true }, { children: _jsxs(Select, Object.assign({ defaultValue: "normal", MenuProps: { elevation: 2 }, inputProps: Object.assign({}, register(SwapFormKey.GasPrice)), 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`) }))] })) }))] })));
12
+ return (_jsxs(CardContainer, Object.assign({ flex: 1 }, { children: [_jsx(CardTitle, { children: t(`settings.gasPrice.title`) }), _jsx(FormControl, Object.assign({ fullWidth: true }, { children: _jsxs(Select, Object.assign({ defaultValue: formDefaultValues.gasPrice, MenuProps: { elevation: 2 }, inputProps: Object.assign({}, register(SwapFormKey.GasPrice)), 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
  };
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Orders } from '@lifinance/sdk';
2
3
  import { KeyboardArrowDown as KeyboardArrowDownIcon } from '@mui/icons-material';
3
4
  import { FormControl, MenuItem } from '@mui/material';
4
5
  import { useFormContext } from 'react-hook-form';
5
6
  import { useTranslation } from 'react-i18next';
6
7
  import { CardContainer, CardTitle } from '../../components/Card';
7
8
  import { Select } from '../../components/Select';
8
- import { SwapFormKey } from '../../providers/SwapFormProvider';
9
+ import { formDefaultValues, SwapFormKey, } from '../../providers/SwapFormProvider';
9
10
  export const RoutePrioritySelect = () => {
10
11
  const { t } = useTranslation();
11
12
  const { register } = useFormContext();
12
- return (_jsxs(CardContainer, { children: [_jsx(CardTitle, { children: t(`settings.routePriority.title`) }), _jsx(FormControl, Object.assign({ fullWidth: true }, { children: _jsx(Select, Object.assign({ defaultValue: 1, MenuProps: { elevation: 2 }, inputProps: Object.assign({}, register(SwapFormKey.RoutePriority)), IconComponent: KeyboardArrowDownIcon, dense: true }, { children: _jsx(MenuItem, Object.assign({ value: 1 }, { children: t(`settings.routePriority.recommended`) })) })) }))] }));
13
+ return (_jsxs(CardContainer, { children: [_jsx(CardTitle, { children: t(`settings.routePriority`) }), _jsx(FormControl, Object.assign({ fullWidth: true }, { children: _jsx(Select, Object.assign({ defaultValue: formDefaultValues.routePriority, MenuProps: { elevation: 2 }, inputProps: Object.assign({}, register(SwapFormKey.RoutePriority)), IconComponent: KeyboardArrowDownIcon, dense: true }, { children: Orders.map((order) => (_jsx(MenuItem, Object.assign({ value: order }, { children: t(`swap.tags.${order.toLowerCase()}`) }), order))) })) }))] }));
13
14
  };
@@ -1 +1,2 @@
1
+ /// <reference types="react" />
1
2
  export declare const SettingsPage: () => JSX.Element;
@@ -1 +1,2 @@
1
+ /// <reference types="react" />
1
2
  export declare const SlippageInput: () => JSX.Element;
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import { Status } from '@lifinance/sdk';
2
3
  export declare function CircularProgress({ status }: {
3
4
  status: Status;
@@ -1,2 +1,9 @@
1
1
  /// <reference types="react" />
2
+ export declare const formDefaultValues: {
3
+ fromAmount: string;
4
+ gasPrice: string;
5
+ slippage: string;
6
+ searchTokensFilter: string;
7
+ routePriority: "RECOMMENDED" | "FASTEST" | "CHEAPEST" | "SAFEST";
8
+ };
2
9
  export declare const SwapFormProvider: React.FC<React.PropsWithChildren<{}>>;
@@ -2,18 +2,19 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { FormProvider, useForm } from 'react-hook-form';
3
3
  import { useWidgetConfig } from '../WidgetProvider';
4
4
  import { SwapFormKey } from './types';
5
- const defaultValues = {
5
+ export const formDefaultValues = {
6
6
  [SwapFormKey.FromAmount]: '',
7
7
  [SwapFormKey.GasPrice]: 'normal',
8
8
  [SwapFormKey.Slippage]: '3',
9
9
  [SwapFormKey.SearchTokensFilter]: '',
10
+ [SwapFormKey.RoutePriority]: 'RECOMMENDED',
10
11
  };
11
12
  export const SwapFormProvider = ({ children, }) => {
12
13
  var _a;
13
14
  const { fromChain, fromToken, fromAmount, toChain, toToken } = useWidgetConfig();
14
15
  const methods = useForm({
15
- defaultValues: Object.assign(Object.assign({}, defaultValues), { fromChain,
16
- fromToken, fromAmount: (_a = fromAmount === null || fromAmount === void 0 ? void 0 : fromAmount.toPrecision()) !== null && _a !== void 0 ? _a : defaultValues.fromAmount, toChain,
16
+ defaultValues: Object.assign(Object.assign({}, formDefaultValues), { fromChain,
17
+ fromToken, fromAmount: (_a = fromAmount === null || fromAmount === void 0 ? void 0 : fromAmount.toPrecision()) !== null && _a !== void 0 ? _a : formDefaultValues.fromAmount, toChain,
17
18
  toToken }),
18
19
  });
19
20
  return _jsx(FormProvider, Object.assign({}, methods, { children: children }));
@@ -1,3 +1,4 @@
1
+ import { Order } from '@lifinance/sdk';
1
2
  export declare enum SwapFormKey {
2
3
  BridgePrioritization = "bridgePrioritization",
3
4
  EnabledBridges = "enabledBridges",
@@ -26,7 +27,7 @@ export declare type SwapFormValues = {
26
27
  [SwapFormKey.IsAddressConfirmed]: boolean;
27
28
  [SwapFormKey.IsSendToRecipient]: boolean;
28
29
  [SwapFormKey.RecipientsAddress]: string;
29
- [SwapFormKey.RoutePriority]: string;
30
+ [SwapFormKey.RoutePriority]: Order;
30
31
  [SwapFormKey.SearchTokensFilter]: string;
31
32
  [SwapFormKey.Slippage]: string;
32
33
  [SwapFormKey.ToChain]: number;
@@ -16,24 +16,25 @@ const stub = () => {
16
16
  throw new Error('You forgot to wrap your component in <WidgetProvider>.');
17
17
  };
18
18
  const initialContext = {
19
- enabledChains: [],
19
+ disabledChains: [],
20
20
  };
21
21
  const WidgetContext = createContext(initialContext);
22
22
  export const useWidgetConfig = () => useContext(WidgetContext);
23
23
  export const WidgetProvider = (_a) => {
24
24
  var { children } = _a, _b = _a.config, { fromChain, toChain } = _b, other = __rest(_b, ["fromChain", "toChain"]);
25
25
  const value = useMemo(() => {
26
+ var _a, _b;
26
27
  const config = Object.assign({}, other);
27
28
  try {
28
29
  return Object.assign(Object.assign({}, config), { fromChain: typeof fromChain === 'number'
29
30
  ? fromChain
30
31
  : typeof fromChain === 'string'
31
- ? getChainByKey(fromChain).id
32
+ ? getChainByKey(fromChain.toLowerCase()).id
32
33
  : ChainId.ETH, toChain: typeof toChain === 'number'
33
34
  ? toChain
34
35
  : typeof toChain === 'string'
35
- ? getChainByKey(toChain).id
36
- : ChainId.ETH });
36
+ ? getChainByKey(toChain.toLowerCase()).id
37
+ : ChainId.ETH, fromToken: (_a = config.fromToken) === null || _a === void 0 ? void 0 : _a.toLowerCase(), toToken: (_b = config.toToken) === null || _b === void 0 ? void 0 : _b.toLowerCase() });
37
38
  }
38
39
  catch (e) {
39
40
  console.warn(e);
package/types/widget.d.ts CHANGED
@@ -15,7 +15,7 @@ export interface WidgetConfig {
15
15
  fromToken?: string;
16
16
  toChain?: `${ChainKey}` | number;
17
17
  toToken?: string;
18
- enabledChains: number[];
18
+ disabledChains?: number[];
19
19
  disableInternalWalletManagement?: boolean;
20
20
  walletCallbacks?: {
21
21
  connect: {
package/config/rpcs.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare const getRpcs: () => Record<number, string[]>;
package/config/rpcs.js DELETED
@@ -1,20 +0,0 @@
1
- import { ChainId } from '@lifinance/sdk';
2
- import { env } from './env';
3
- const rpcs = {
4
- [ChainId.ETH]: [env.LIFI_RPC_URL_MAINNET],
5
- // [ChainId.POL]: [env.LIFI_RPC_URL_POLYGON],
6
- // [ChainId.BSC]: [env.LIFI_RPC_URL_BSC],
7
- // [ChainId.DAI]: [env.LIFI_RPC_URL_XDAI],
8
- // [ChainId.FTM]: [env.LIFI_RPC_URL_FANTOM],
9
- // [ChainId.ARB]: [env.LIFI_RPC_URL_ARBITRUM],
10
- // Testnet
11
- [ChainId.ROP]: [env.LIFI_RPC_URL_ROPSTEN],
12
- [ChainId.RIN]: [env.LIFI_RPC_URL_RINKEBY],
13
- [ChainId.GOR]: [env.LIFI_RPC_URL_GORLI],
14
- [ChainId.KOV]: [env.LIFI_RPC_URL_KOVAN],
15
- [ChainId.ARBT]: [env.LIFI_RPC_URL_ARBITRUM_RINKEBY],
16
- [ChainId.OPTT]: [env.LIFI_RPC_URL_OPTIMISM_KOVAN],
17
- [ChainId.MUM]: [env.LIFI_RPC_URL_POLYGON_MUMBAI],
18
- [ChainId.BSCT]: [env.LIFI_RPC_URL_BSC_TESTNET],
19
- };
20
- export const getRpcs = () => Object.fromEntries(Object.entries(rpcs).filter(([_, value]) => !value));