@lifi/widget 1.11.3 → 1.12.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 (50) hide show
  1. package/AppDrawer.style.d.ts +1 -1
  2. package/AppDrawer.style.js +6 -2
  3. package/AppProvider.d.ts +4 -0
  4. package/AppProvider.js +5 -2
  5. package/components/Header/Header.js +4 -1
  6. package/components/NotFound.js +2 -1
  7. package/components/ReverseTokensButton/ReverseTokensButton.style.d.ts +1 -1
  8. package/components/Step/Step.js +4 -1
  9. package/components/Step/StepProcess.style.d.ts +1 -1
  10. package/components/StepActions/StepActions.js +4 -2
  11. package/components/SwapButton/SwapButton.js +11 -4
  12. package/components/SwapButton/SwapButton.style.d.ts +1 -1
  13. package/components/SwapInput/SwapInput.style.d.ts +1 -1
  14. package/components/SwapInput/SwapInputAdornment.style.d.ts +1 -1
  15. package/components/SwapRouteCard/SwapRouteCard.js +2 -2
  16. package/components/SwapRouteCard/SwapRouteCard.style.js +4 -1
  17. package/components/SwapRouteCard/SwapRouteCardSkeleton.js +2 -2
  18. package/components/SwapRouteCard/SwapRouteNotFoundCard.js +7 -8
  19. package/components/TokenList/TokenList.js +2 -1
  20. package/components/TokenList/TokenList.style.d.ts +2 -2
  21. package/config/lifi.d.ts +1 -1
  22. package/config/lifi.js +2 -8
  23. package/config/theme.js +14 -11
  24. package/config/version.d.ts +1 -1
  25. package/config/version.js +1 -1
  26. package/hooks/useGasSufficiency.js +11 -4
  27. package/hooks/useRouteExecution.js +31 -17
  28. package/hooks/useSwapRoutes.js +2 -2
  29. package/hooks/useTokenBalance.js +1 -1
  30. package/hooks/useTokenBalances.d.ts +4 -2
  31. package/hooks/useTokenBalances.js +23 -11
  32. package/i18n/en/translation.json +8 -4
  33. package/i18n/index.d.ts +4 -0
  34. package/package.json +13 -13
  35. package/pages/MainPage/SwapRoutes.js +3 -3
  36. package/pages/MainPage/SwapRoutes.style.d.ts +1 -1
  37. package/pages/SelectWalletPage/SelectWalletPage.style.d.ts +2 -2
  38. package/pages/SettingsPage/ColorSchemeButtonGroup.style.d.ts +1 -1
  39. package/pages/SwapHistoryPage/SwapHistoryEmpty.js +1 -1
  40. package/pages/SwapHistoryPage/SwapHistoryPage.js +19 -3
  41. package/pages/SwapRoutesPage/SwapRoutesPage.js +3 -3
  42. package/pages/SwapRoutesPage/SwapRoutesPage.style.d.ts +1 -1
  43. package/providers/WalletProvider/WalletProvider.d.ts +11 -1
  44. package/providers/WalletProvider/WalletProvider.js +24 -33
  45. package/providers/WidgetProvider/WidgetProvider.js +5 -2
  46. package/stores/route/types.d.ts +1 -0
  47. package/stores/route/useRouteStore.js +3 -12
  48. package/types/widget.d.ts +1 -1
  49. package/utils/colors.d.ts +1 -0
  50. package/utils/colors.js +5 -0
@@ -2,7 +2,7 @@
2
2
  export declare const DrawerButton: import("@emotion/styled").StyledComponent<{
3
3
  children?: import("react").ReactNode;
4
4
  classes?: Partial<import("@mui/material").ButtonClasses> | undefined;
5
- color?: "inherit" | "success" | "info" | "warning" | "error" | "primary" | "secondary" | undefined;
5
+ color?: "inherit" | "primary" | "secondary" | "error" | "warning" | "info" | "success" | undefined;
6
6
  disabled?: boolean | undefined;
7
7
  disableElevation?: boolean | undefined;
8
8
  disableFocusRipple?: boolean | undefined;
@@ -39,8 +39,12 @@ export const DrawerButton = styled(Button, {
39
39
  ? getButtonTransformWidth(drawerProps === null || drawerProps === void 0 ? void 0 : drawerProps.width, drawerProps === null || drawerProps === void 0 ? void 0 : drawerProps.maxWidth)
40
40
  : '0px'} * -1), 0, 0)`,
41
41
  transition: theme.transitions.create(['transform'], {
42
- duration: theme.transitions.duration.enteringScreen,
43
- easing: theme.transitions.easing.easeOut,
42
+ duration: open
43
+ ? theme.transitions.duration.enteringScreen
44
+ : theme.transitions.duration.leavingScreen,
45
+ easing: open
46
+ ? theme.transitions.easing.easeOut
47
+ : theme.transitions.easing.sharp,
44
48
  }),
45
49
  zIndex: 1500,
46
50
  '&:hover': {
package/AppProvider.d.ts CHANGED
@@ -5,3 +5,7 @@ export interface AppProps {
5
5
  }
6
6
  export declare const AppProvider: React.FC<PropsWithChildren<AppProps>>;
7
7
  export declare const AppRouter: React.FC<PropsWithChildren<{}>>;
8
+ export declare const TelemetryProvider: React.FC<{
9
+ children: React.ReactElement<any, any> | null;
10
+ disabled?: boolean;
11
+ }>;
package/AppProvider.js CHANGED
@@ -12,11 +12,14 @@ import { WalletProvider } from './providers/WalletProvider';
12
12
  import { WidgetProvider } from './providers/WidgetProvider';
13
13
  const QueryProvider = QueryClientProvider;
14
14
  export const AppProvider = ({ children, config, }) => {
15
- useTelemetry(config === null || config === void 0 ? void 0 : config.disableTelemetry);
16
- return (_jsx(WidgetProvider, Object.assign({ config: config }, { children: _jsx(ThemeProvider, { children: _jsx(QueryProvider, Object.assign({ client: queryClient }, { children: _jsx(WalletProvider, { children: _jsx(SwapFormProvider, { children: _jsx(AppRouter, { children: children }) }) }) })) }) })));
15
+ return (_jsx(QueryProvider, Object.assign({ client: queryClient }, { children: _jsx(TelemetryProvider, Object.assign({ disabled: config === null || config === void 0 ? void 0 : config.disableTelemetry }, { children: _jsx(WalletProvider, Object.assign({ walletManagement: config === null || config === void 0 ? void 0 : config.walletManagement }, { children: _jsx(WidgetProvider, Object.assign({ config: config }, { children: _jsx(ThemeProvider, { children: _jsx(SwapFormProvider, { children: _jsx(AppRouter, { children: children }) }) }) })) })) })) })));
17
16
  };
18
17
  export const AppRouter = ({ children }) => {
19
18
  const inRouterContext = useInRouterContext();
20
19
  const Router = inRouterContext ? Fragment : MemoryRouter;
21
20
  return _jsx(Router, { children: children });
22
21
  };
22
+ export const TelemetryProvider = ({ children, disabled }) => {
23
+ useTelemetry(disabled);
24
+ return children;
25
+ };
@@ -9,10 +9,13 @@ const stickyHeaderRoutes = [
9
9
  navigationRoutes.selectWallet,
10
10
  navigationRoutes.settings,
11
11
  navigationRoutes.swapRoutes,
12
+ navigationRoutes.swapExecution,
13
+ navigationRoutes.swapHistory,
14
+ navigationRoutes.swapDetails,
12
15
  ];
13
16
  const HeaderContainer = ({ children }) => {
14
17
  const { pathname } = useLocation();
15
- return (_jsx(Container, Object.assign({ id: ElementId.Header, sticky: stickyHeaderRoutes.includes(pathname) }, { children: children })));
18
+ return (_jsx(Container, Object.assign({ id: ElementId.Header, sticky: stickyHeaderRoutes.some((route) => pathname.includes(route)) }, { children: children })));
16
19
  };
17
20
  export const Header = () => {
18
21
  const { walletManagement } = useWidgetConfig();
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Block as BlockIcon } from '@mui/icons-material';
2
3
  import { Box, Typography } from '@mui/material';
3
4
  import { useTranslation } from 'react-i18next';
4
5
  export const NotFound = () => {
@@ -10,5 +11,5 @@ export const NotFound = () => {
10
11
  flexDirection: 'column',
11
12
  flex: 1,
12
13
  padding: 3,
13
- } }, { children: [_jsx(Typography, Object.assign({ variant: "h6" }, { children: t('tooltip.notFound.title') })), _jsx(Typography, { children: t('tooltip.notFound.text') })] })));
14
+ } }, { children: [_jsx(Typography, Object.assign({ fontSize: 48 }, { children: _jsx(BlockIcon, { fontSize: "inherit" }) })), _jsx(Typography, Object.assign({ fontSize: 18, fontWeight: 700 }, { children: t('tooltip.notFound.title') })), _jsx(Typography, Object.assign({ fontSize: 14, color: "text.secondary", textAlign: "center", mt: 2 }, { children: t('tooltip.notFound.text') }))] })));
14
15
  };
@@ -2,7 +2,7 @@
2
2
  export declare const IconButton: import("@emotion/styled").StyledComponent<{
3
3
  children?: import("react").ReactNode;
4
4
  classes?: Partial<import("@mui/material").IconButtonClasses> | undefined;
5
- color?: "inherit" | "default" | "success" | "info" | "warning" | "error" | "primary" | "secondary" | undefined;
5
+ color?: "inherit" | "default" | "primary" | "secondary" | "error" | "warning" | "info" | "success" | undefined;
6
6
  disabled?: boolean | undefined;
7
7
  disableFocusRipple?: boolean | undefined;
8
8
  edge?: false | "end" | "start" | undefined;
@@ -13,7 +13,10 @@ export const Step = ({ step, fromToken, toToken }) => {
13
13
  const getCardTitle = () => {
14
14
  switch (step.type) {
15
15
  case 'lifi':
16
- return t('swap.stepSwapAndBridge');
16
+ if (step.includedSteps.some((step) => step.type === 'cross')) {
17
+ return t('swap.stepSwapAndBridge');
18
+ }
19
+ return t('swap.stepSwap');
17
20
  case 'swap':
18
21
  return t('swap.stepSwap');
19
22
  case 'cross':
@@ -2,7 +2,7 @@
2
2
  export declare const LinkButton: import("@emotion/styled").StyledComponent<{
3
3
  children?: import("react").ReactNode;
4
4
  classes?: Partial<import("@mui/material").IconButtonClasses> | undefined;
5
- color?: "inherit" | "default" | "success" | "info" | "warning" | "error" | "primary" | "secondary" | undefined;
5
+ color?: "inherit" | "default" | "primary" | "secondary" | "error" | "warning" | "info" | "success" | undefined;
6
6
  disabled?: boolean | undefined;
7
7
  disableFocusRipple?: boolean | undefined;
8
8
  edge?: false | "end" | "start" | undefined;
@@ -21,7 +21,9 @@ import { StepAvatar, StepConnector, StepContent, StepLabel, } from './StepAction
21
21
  export const StepActions = (_a) => {
22
22
  var _b;
23
23
  var { step, dense } = _a, other = __rest(_a, ["step", "dense"]);
24
- const StepDetailsLabel = step.type === 'cross' || step.type === 'lifi'
24
+ const StepDetailsLabel = step.type === 'cross' ||
25
+ (step.type === 'lifi' &&
26
+ step.includedSteps.some((step) => step.type === 'cross'))
25
27
  ? CrossStepDetailsLabel
26
28
  : SwapStepDetailsLabel;
27
29
  const isFullView = !dense && ((_b = step.includedSteps) === null || _b === void 0 ? void 0 : _b.length) > 1;
@@ -33,7 +35,7 @@ export const StepActions = (_a) => {
33
35
  boxSizing: 'content-box',
34
36
  } }, { children: tool.toolDetails.name[0] }))) : null;
35
37
  };
36
- return (_jsxs(Box, Object.assign({}, other, { children: [_jsxs(Box, Object.assign({ sx: { display: 'flex', alignItems: 'center' }, mb: isFullView ? 1.5 : 0 }, { children: [_jsx(StepAvatar, Object.assign({ variant: step.type === 'lifi' ? 'square' : 'circular', src: step.type !== 'lifi' ? step.toolDetails.logoURI : undefined, alt: step.toolDetails.name }, { children: step.type === 'lifi' ? _jsx(LiFiToolLogo, {}) : step.toolDetails.name[0] })), _jsx(Typography, Object.assign({ ml: 2, fontSize: 18, fontWeight: "500", textTransform: "capitalize" }, { children: step.type === 'lifi'
38
+ return (_jsxs(Box, Object.assign({}, other, { children: [_jsxs(Box, Object.assign({ sx: { display: 'flex', alignItems: 'center' }, mb: isFullView ? 1.5 : 0 }, { children: [_jsx(StepAvatar, Object.assign({ variant: "circular", src: step.type !== 'lifi' ? step.toolDetails.logoURI : undefined, alt: step.toolDetails.name }, { children: step.type === 'lifi' ? _jsx(LiFiToolLogo, {}) : step.toolDetails.name[0] })), _jsx(Typography, Object.assign({ ml: 2, fontSize: 18, fontWeight: "500", textTransform: "capitalize" }, { children: step.type === 'lifi'
37
39
  ? 'LI.FI Smart Contract'
38
40
  : step.toolDetails.name }))] })), isFullView ? (_jsx(Stepper, Object.assign({ orientation: "vertical", connector: _jsx(StepConnector, {}), activeStep: -1 }, { children: step.includedSteps.map((step) => (_jsxs(MuiStep, Object.assign({ expanded: true }, { children: [_jsx(StepLabel, Object.assign({ StepIconComponent: StepIconComponent }, { children: step.type === 'cross' || step.type === 'lifi' ? (_jsx(CrossStepDetailsLabel, { step: step })) : (_jsx(SwapStepDetailsLabel, { step: step })) })), _jsx(StepContent, { children: _jsx(StepDetailsContent, { step: step }) })] }), step.id))) }))) : (_jsxs(Box, Object.assign({ ml: 6 }, { children: [_jsx(StepDetailsLabel, { step: step }), _jsx(StepDetailsContent, { step: step })] })))] })));
39
41
  };
@@ -29,7 +29,10 @@ export const SwapButton = ({ onClick, currentRoute, text, loading, }) => {
29
29
  const [chainId] = useWatch({
30
30
  name: [SwapFormKeyHelper.getChainKey('from')],
31
31
  });
32
- const isCurrentChainMatch = ((_a = getChainById(chainId || ChainId.ETH)) === null || _a === void 0 ? void 0 : _a.id) === account.chainId;
32
+ // Allow switching chain only if execution is not started
33
+ const switchChainAllowed = ((_a = getChainById(chainId || ChainId.ETH)) === null || _a === void 0 ? void 0 : _a.id) !== account.chainId &&
34
+ currentRoute &&
35
+ !currentRoute.steps.some((step) => step.execution);
33
36
  const handleSwapButtonClick = () => __awaiter(void 0, void 0, void 0, function* () {
34
37
  if (!account.isActive) {
35
38
  if (config.walletManagement) {
@@ -39,7 +42,7 @@ export const SwapButton = ({ onClick, currentRoute, text, loading, }) => {
39
42
  navigate(navigationRoutes.selectWallet);
40
43
  }
41
44
  }
42
- else if (!isCurrentChainMatch) {
45
+ else if (switchChainAllowed) {
43
46
  yield switchChain(chainId);
44
47
  // check that the current route exists in the up to date route list
45
48
  }
@@ -49,9 +52,12 @@ export const SwapButton = ({ onClick, currentRoute, text, loading, }) => {
49
52
  });
50
53
  const getButtonText = () => {
51
54
  if (account.isActive) {
52
- if (!isCurrentChainMatch) {
55
+ if (switchChainAllowed) {
53
56
  return t(`button.switchChain`);
54
57
  }
58
+ if (!currentRoute) {
59
+ return t(`button.swap`);
60
+ }
55
61
  return text || t(`button.reviewSwap`);
56
62
  }
57
63
  return t(`button.connectWallet`);
@@ -59,5 +65,6 @@ export const SwapButton = ({ onClick, currentRoute, text, loading, }) => {
59
65
  return (_jsx(Button, Object.assign({ variant: "contained", color: account.isActive ? 'primary' : 'success', onClick: handleSwapButtonClick,
60
66
  // loading={isLoading || isFetching}
61
67
  disabled: (insufficientFunds || !!insufficientGas.length || loading) &&
62
- isCurrentChainMatch, fullWidth: true }, { children: getButtonText() })));
68
+ currentRoute &&
69
+ !switchChainAllowed, fullWidth: true }, { children: getButtonText() })));
63
70
  };
@@ -17,7 +17,7 @@ export declare const Button: import("@emotion/styled").StyledComponent<{
17
17
  } & Omit<{
18
18
  children?: import("react").ReactNode;
19
19
  classes?: Partial<import("@mui/material").ButtonClasses> | undefined;
20
- color?: "inherit" | "success" | "info" | "warning" | "error" | "primary" | "secondary" | undefined;
20
+ color?: "inherit" | "primary" | "secondary" | "error" | "warning" | "info" | "success" | undefined;
21
21
  disabled?: boolean | undefined;
22
22
  disableElevation?: boolean | undefined;
23
23
  disableFocusRipple?: boolean | undefined;
@@ -4,7 +4,7 @@ export declare const minInputFontSize = 14;
4
4
  export declare const FormControl: import("@emotion/styled").StyledComponent<{
5
5
  children?: import("react").ReactNode;
6
6
  classes?: Partial<import("@mui/material").FormControlClasses> | undefined;
7
- color?: "success" | "info" | "warning" | "error" | "primary" | "secondary" | undefined;
7
+ color?: "primary" | "secondary" | "error" | "warning" | "info" | "success" | undefined;
8
8
  disabled?: boolean | undefined;
9
9
  error?: boolean | undefined;
10
10
  fullWidth?: boolean | undefined;
@@ -2,7 +2,7 @@
2
2
  export declare const Button: import("@emotion/styled").StyledComponent<{
3
3
  children?: import("react").ReactNode;
4
4
  classes?: Partial<import("@mui/material").ButtonClasses> | undefined;
5
- color?: "inherit" | "success" | "info" | "warning" | "error" | "primary" | "secondary" | undefined;
5
+ color?: "inherit" | "primary" | "secondary" | "error" | "warning" | "info" | "success" | undefined;
6
6
  disabled?: boolean | undefined;
7
7
  disableElevation?: boolean | undefined;
8
8
  disableFocusRipple?: boolean | undefined;
@@ -32,7 +32,7 @@ export const SwapRouteCard = (_a) => {
32
32
  : null, _jsxs(Box, Object.assign({ sx: {
33
33
  display: 'flex',
34
34
  justifyContent: 'space-between',
35
- } }, { children: [_jsxs(Box, { children: [_jsx(Typography, Object.assign({ fontSize: 18, fontWeight: "500" }, { children: t(`swap.currency`, { value: (_c = route.gasCostUSD) !== null && _c !== void 0 ? _c : 0 }) })), _jsx(Typography, Object.assign({ fontSize: 12, color: "text.secondary" }, { children: t(`swap.gas`) }))] }), _jsxs(Box, { children: [_jsxs(Typography, Object.assign({ fontSize: 18, fontWeight: "500", display: "flex", justifyContent: "flex-end" }, { children: ["~", (route.steps
35
+ } }, { children: [_jsxs(Box, { children: [_jsx(Typography, Object.assign({ fontSize: 18, fontWeight: "500", lineHeight: 1, pt: 0.25 }, { children: t(`swap.currency`, { value: (_c = route.gasCostUSD) !== null && _c !== void 0 ? _c : 0 }) })), _jsx(Typography, Object.assign({ fontSize: 12, color: "text.secondary", lineHeight: 1, mt: 0.5 }, { children: t(`swap.gas`) }))] }), _jsxs(Box, { children: [_jsxs(Typography, Object.assign({ fontSize: 18, fontWeight: "500", display: "flex", justifyContent: "flex-end", lineHeight: 1, pt: 0.25 }, { children: ["~", (route.steps
36
36
  .map((step) => step.estimate.executionDuration)
37
- .reduce((cumulated, x) => cumulated + x) / 60).toFixed(0)] })), _jsx(Typography, Object.assign({ fontSize: 12, color: "text.secondary", textAlign: "end" }, { children: t(`swap.minutes`) }))] })] }))] })));
37
+ .reduce((cumulated, x) => cumulated + x) / 60).toFixed(0)] })), _jsx(Typography, Object.assign({ fontSize: 12, color: "text.secondary", textAlign: "end", lineHeight: 1, mt: 0.5 }, { children: t(`swap.minutes`) }))] })] }))] })));
38
38
  };
@@ -1,3 +1,4 @@
1
+ import { getContrastTextColor } from '@lifi/widget/utils';
1
2
  import { Typography } from '@mui/material';
2
3
  import { styled } from '@mui/material/styles';
3
4
  export const Label = styled(Typography, {
@@ -11,7 +12,9 @@ export const Label = styled(Typography, {
11
12
  ? theme.palette.grey[500]
12
13
  : theme.palette.grey[600],
13
14
  borderRadius: theme.shape.borderRadiusSecondary,
14
- color: active ? theme.palette.common.white : theme.palette.text.secondary,
15
+ color: active
16
+ ? getContrastTextColor(theme, theme.palette.primary.main)
17
+ : theme.palette.text.secondary,
15
18
  padding: theme.spacing(0.75),
16
19
  fontSize: 12,
17
20
  lineHeight: 1,
@@ -20,9 +20,9 @@ export const SwapRouteCardSkeleton = (_a) => {
20
20
  } }, { children: [_jsx(Box, Object.assign({ mr: 2 }, { children: _jsx(Skeleton, { variant: "circular", width: 32, height: 32 }) })), _jsx(Skeleton, { variant: "text", width: 96, height: 32 })] })), _jsx(Box, Object.assign({ ml: 6 }, { children: _jsx(Skeleton, { variant: "text", width: 102, height: 16, sx: { borderRadius: 0.5 } }) }))] })), _jsxs(Box, Object.assign({ sx: {
21
21
  display: 'flex',
22
22
  justifyContent: 'space-between',
23
- } }, { children: [_jsxs(Box, { children: [_jsx(Skeleton, { variant: "text", width: 56, height: 27 }), _jsx(Skeleton, { variant: "text", width: 52, height: 18 })] }), _jsxs(Box, Object.assign({ sx: {
23
+ } }, { children: [_jsxs(Box, { children: [_jsx(Skeleton, { variant: "text", width: 56, height: 20 }), _jsx(Skeleton, { variant: "text", width: 52, height: 16 })] }), _jsxs(Box, Object.assign({ sx: {
24
24
  display: 'flex',
25
25
  alignItems: 'flex-end',
26
26
  flexDirection: 'column',
27
- } }, { children: [_jsx(Skeleton, { variant: "text", width: 40, height: 27 }), _jsx(Skeleton, { variant: "text", width: 48, height: 18 })] }))] }))] })));
27
+ } }, { children: [_jsx(Skeleton, { variant: "text", width: 40, height: 20 }), _jsx(Skeleton, { variant: "text", width: 48, height: 16 })] }))] }))] })));
28
28
  };
@@ -13,15 +13,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import { Route as RouteIcon } from '@mui/icons-material';
14
14
  import { Box, Typography } from '@mui/material';
15
15
  import { useTranslation } from 'react-i18next';
16
- import { Card } from '../Card';
17
16
  export const SwapRouteNotFoundCard = (_a) => {
18
17
  var { dense } = _a, other = __rest(_a, ["dense"]);
19
18
  const { t } = useTranslation();
20
- return (_jsx(Card, Object.assign({ dense: dense, indented: true }, other, { children: _jsxs(Box, Object.assign({ sx: {
21
- display: 'flex',
22
- alignItems: 'center',
23
- justifyContent: 'center',
24
- flexDirection: 'column',
25
- flex: 1,
26
- }, py: 1.375 }, { children: [_jsx(RouteIcon, { fontSize: "large" }), _jsx(Typography, Object.assign({ fontSize: 16, fontWeight: "500", mt: 2 }, { children: t('swap.info.title.routeNotFound') })), _jsx(Typography, Object.assign({ fontSize: 14, color: "text.secondary", textAlign: "center", mt: 1 }, { children: t('swap.info.message.routeNotFound') }))] })) })));
19
+ return (_jsxs(Box, Object.assign({ sx: {
20
+ display: 'flex',
21
+ alignItems: 'center',
22
+ justifyContent: 'center',
23
+ flexDirection: 'column',
24
+ flex: 1,
25
+ }, py: 2.375 }, { children: [_jsx(Typography, Object.assign({ fontSize: 48 }, { children: _jsx(RouteIcon, { fontSize: "inherit" }) })), _jsx(Typography, Object.assign({ fontSize: 18, fontWeight: 700 }, { children: t('swap.info.title.routeNotFound') })), _jsx(Typography, Object.assign({ fontSize: 14, color: "text.secondary", textAlign: "center", mt: 2 }, { children: t('swap.info.message.routeNotFound') }))] })));
27
26
  };
@@ -17,7 +17,8 @@ export const TokenList = ({ formType, height, onClick, }) => {
17
17
  name: [SwapFormKeyHelper.getChainKey(formType)],
18
18
  });
19
19
  const [searchTokensFilter] = useDebouncedWatch([SwapFormKey.SearchTokensFilter], 250);
20
- const { tokens, isLoading, isBalanceLoading } = useTokenBalances(selectedChainId);
20
+ const { tokens: tokensWithoutBalance, tokensWithBalance, isLoading, isBalanceLoading, } = useTokenBalances(selectedChainId);
21
+ const tokens = tokensWithBalance !== null && tokensWithBalance !== void 0 ? tokensWithBalance : tokensWithoutBalance;
21
22
  const chainTokens = useMemo(() => {
22
23
  var _a;
23
24
  let chainTokens = tokens !== null && tokens !== void 0 ? tokens : [];
@@ -17,7 +17,7 @@ export declare const ListItemButton: import("@emotion/styled").StyledComponent<i
17
17
  touchRippleRef?: import("react").Ref<import("@mui/material/ButtonBase/TouchRipple").TouchRippleActions> | undefined;
18
18
  }, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import("react").HTMLAttributes<HTMLDivElement>> & {
19
19
  ref?: import("react").RefObject<HTMLDivElement> | ((instance: HTMLDivElement | null) => void) | null | undefined;
20
- }, "className" | "style" | "classes" | "tabIndex" | "children" | "action" | "centerRipple" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "TouchRippleProps" | "touchRippleRef" | "alignItems" | "autoFocus" | "dense" | "selected" | "disableGutters" | "divider"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
20
+ }, "className" | "style" | "classes" | "tabIndex" | "children" | "action" | "centerRipple" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "TouchRippleProps" | "touchRippleRef" | "alignItems" | "autoFocus" | "dense" | "divider" | "selected" | "disableGutters"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
21
21
  export declare const ListItem: import("@emotion/styled").StyledComponent<{
22
22
  button?: false | undefined;
23
23
  } & import("@mui/material").ListItemBaseProps & {
@@ -29,4 +29,4 @@ export declare const ListItem: import("@emotion/styled").StyledComponent<{
29
29
  } | undefined;
30
30
  } & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "key" | keyof import("react").LiHTMLAttributes<HTMLLIElement>> & {
31
31
  ref?: ((instance: HTMLLIElement | null) => void) | import("react").RefObject<HTMLLIElement> | null | undefined;
32
- }, "button" | "className" | "style" | "classes" | "children" | "disabled" | "sx" | "alignItems" | "autoFocus" | "dense" | "components" | "componentsProps" | "selected" | "disableGutters" | "divider" | "ContainerComponent" | "ContainerProps" | "disablePadding" | "secondaryAction"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
32
+ }, "button" | "className" | "style" | "classes" | "children" | "disabled" | "sx" | "alignItems" | "autoFocus" | "dense" | "divider" | "components" | "componentsProps" | "selected" | "disableGutters" | "ContainerComponent" | "ContainerProps" | "disablePadding" | "secondaryAction"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
package/config/lifi.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import LIFI, { ConfigUpdate } from '@lifi/sdk';
2
2
  export declare const LiFi: LIFI;
3
- export declare const updateLiFiConfig: (configUpdate?: ConfigUpdate) => void;
3
+ export declare const updateLiFiConfig: (configUpdate: ConfigUpdate) => void;
package/config/lifi.js CHANGED
@@ -1,11 +1,5 @@
1
1
  import LIFI from '@lifi/sdk';
2
- const defaultConfig = {
3
- // apiUrl: env.LIFI_API_URL,
4
- // defaultRouteOptions: {
5
- // integrator: 'li.fi',
6
- // },
7
- };
8
- export const LiFi = new LIFI(defaultConfig);
2
+ export const LiFi = new LIFI();
9
3
  export const updateLiFiConfig = (configUpdate) => {
10
- LiFi.setConfig(Object.assign(Object.assign({}, defaultConfig), configUpdate));
4
+ LiFi.setConfig(configUpdate);
11
5
  };
package/config/theme.js CHANGED
@@ -31,12 +31,15 @@ const shape = {
31
31
  };
32
32
  export const createTheme = (mode, theme = {}) => {
33
33
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
34
+ const primaryMainColor = (_c = (_b = (_a = theme.palette) === null || _a === void 0 ? void 0 : _a.primary) === null || _b === void 0 ? void 0 : _b.main) !== null && _c !== void 0 ? _c : palette.primary.main;
35
+ const primaryLightColor = lighten((_f = (_e = (_d = theme.palette) === null || _d === void 0 ? void 0 : _d.primary) === null || _e === void 0 ? void 0 : _e.main) !== null && _f !== void 0 ? _f : palette.primary.main, 0.5);
36
+ const primaryDarkColor = darken((_j = (_h = (_g = theme.palette) === null || _g === void 0 ? void 0 : _g.primary) === null || _h === void 0 ? void 0 : _h.main) !== null && _j !== void 0 ? _j : palette.primary.main, 0.2);
34
37
  return createMuiTheme({
35
38
  typography: Object.assign({ fontFamily: 'Inter var, Inter, sans-serif' }, theme.typography),
36
39
  palette: Object.assign(Object.assign(Object.assign({ mode }, palette), { primary: {
37
- main: (_c = (_b = (_a = theme.palette) === null || _a === void 0 ? void 0 : _a.primary) === null || _b === void 0 ? void 0 : _b.main) !== null && _c !== void 0 ? _c : palette.primary.main,
38
- light: lighten((_f = (_e = (_d = theme.palette) === null || _d === void 0 ? void 0 : _d.primary) === null || _e === void 0 ? void 0 : _e.main) !== null && _f !== void 0 ? _f : palette.primary.main, 0.5),
39
- dark: darken((_j = (_h = (_g = theme.palette) === null || _g === void 0 ? void 0 : _g.primary) === null || _h === void 0 ? void 0 : _h.main) !== null && _j !== void 0 ? _j : palette.primary.main, 0.2),
40
+ main: primaryMainColor,
41
+ light: primaryLightColor,
42
+ dark: primaryDarkColor,
40
43
  }, secondary: {
41
44
  main: (_m = (_l = (_k = theme.palette) === null || _k === void 0 ? void 0 : _k.secondary) === null || _l === void 0 ? void 0 : _l.main) !== null && _m !== void 0 ? _m : palette.secondary.main,
42
45
  light: lighten((_q = (_p = (_o = theme.palette) === null || _o === void 0 ? void 0 : _o.secondary) === null || _p === void 0 ? void 0 : _p.main) !== null && _q !== void 0 ? _q : palette.secondary.main, 0.5),
@@ -85,18 +88,18 @@ export const createTheme = (mode, theme = {}) => {
85
88
  styleOverrides: Object.assign(Object.assign({}, (mode === 'dark'
86
89
  ? {
87
90
  outlined: {
88
- color: palette.primary.light,
89
- borderColor: palette.primary.light,
91
+ color: primaryLightColor,
92
+ borderColor: primaryLightColor,
90
93
  '&:hover': {
91
- backgroundColor: alpha(palette.primary.light, 0.08),
92
- borderColor: palette.primary.light,
94
+ backgroundColor: alpha(primaryLightColor, 0.08),
95
+ borderColor: primaryLightColor,
93
96
  },
94
97
  },
95
98
  text: {
96
- color: palette.primary.light,
99
+ color: primaryLightColor,
97
100
  '&:hover': {
98
- backgroundColor: alpha(palette.primary.light, 0.08),
99
- borderColor: palette.primary.light,
101
+ backgroundColor: alpha(primaryLightColor, 0.08),
102
+ borderColor: primaryLightColor,
100
103
  },
101
104
  },
102
105
  }
@@ -117,7 +120,7 @@ export const createTheme = (mode, theme = {}) => {
117
120
  },
118
121
  }, contained: {
119
122
  '&:hover': {
120
- color: getContrastRatio(palette.primary.main, dark.text.primary) >= 3
123
+ color: getContrastRatio(dark.text.primary, primaryMainColor) >= 3
121
124
  ? dark.text.primary
122
125
  : light.text.primary,
123
126
  },
@@ -1,2 +1,2 @@
1
1
  export declare const name = "@lifi/widget";
2
- export declare const version = "1.11.3";
2
+ export declare const version = "1.12.1";
package/config/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export const name = '@lifi/widget';
2
- export const version = '1.11.3';
2
+ export const version = '1.12.1';
@@ -15,12 +15,16 @@ export const useGasSufficiency = (route) => {
15
15
  ],
16
16
  });
17
17
  const fromAmount = useDebouncedWatch(SwapFormKey.FromAmount, 250);
18
- const { tokens: fromChainTokenBalances } = useTokenBalances(fromChainId);
19
- const { tokens: toChainTokenBalances } = useTokenBalances(toChainId);
20
18
  const { getChainById } = useChains();
19
+ const { tokensWithBalance: fromChainTokenBalances } = useTokenBalances(fromChainId);
20
+ const { tokensWithBalance: toChainTokenBalances } = useTokenBalances(toChainId);
21
21
  const insufficientGas = useMemo(() => {
22
22
  var _a;
23
- if (!account.isActive || !route || !fromAmount) {
23
+ if (!account.isActive ||
24
+ !route ||
25
+ !fromAmount ||
26
+ !fromChainTokenBalances ||
27
+ !toChainTokenBalances) {
24
28
  return [];
25
29
  }
26
30
  const tokenBalancesByChain = {
@@ -78,7 +82,10 @@ export const useGasSufficiency = (route) => {
78
82
  ]);
79
83
  const insufficientFunds = useMemo(() => {
80
84
  var _a, _b;
81
- if (!account.isActive || !fromToken || !fromAmount) {
85
+ if (!account.isActive ||
86
+ !fromToken ||
87
+ !fromAmount ||
88
+ !fromChainTokenBalances) {
82
89
  return false;
83
90
  }
84
91
  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);
@@ -20,21 +20,23 @@ export const useRouteExecution = (routeId) => {
20
20
  const routeExecution = useRouteStore((state) => state.routes[routeId]);
21
21
  const [updateRoute, restartRoute, deleteRoute] = useRouteStore((state) => [state.updateRoute, state.restartRoute, state.deleteRoute], shallow);
22
22
  const updateCallback = (updatedRoute) => {
23
- console.log('Route updated.', updatedRoute);
24
- updateRoute(deepClone(updatedRoute));
23
+ const clonedUpdatedRoute = deepClone(updatedRoute);
24
+ console.log('Route updated.', clonedUpdatedRoute);
25
+ updateRoute(clonedUpdatedRoute);
25
26
  };
26
- const switchChainHook = useCallback((requiredChainId) => __awaiter(void 0, void 0, void 0, function* () {
27
+ const switchChainHook = (requiredChainId) => __awaiter(void 0, void 0, void 0, function* () {
27
28
  if (!account.isActive || !account.signer) {
28
29
  return account.signer;
29
30
  }
30
- if ((yield account.signer.getChainId()) !== requiredChainId) {
31
+ const currentChainId = yield account.signer.getChainId();
32
+ if (currentChainId !== requiredChainId) {
31
33
  const switched = yield switchChain(requiredChainId);
32
34
  if (!switched) {
33
35
  throw new Error('Chain was not switched.');
34
36
  }
35
37
  }
36
38
  return account.signer;
37
- }), [account.isActive, account.signer, switchChain]);
39
+ });
38
40
  const executeRouteMutation = useMutation(() => {
39
41
  if (!account.signer) {
40
42
  throw Error('Account signer not found.');
@@ -112,26 +114,29 @@ export const useRouteExecution = (routeId) => {
112
114
  deleteRoute(routeId);
113
115
  // eslint-disable-next-line react-hooks/exhaustive-deps
114
116
  }, [routeId]);
117
+ // Resume route execution after page reload
115
118
  useEffect(() => {
116
- // check if route is eligible for automatic resuming
117
- const isDone = routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.route.steps.every((step) => { var _a; return ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'DONE'; });
118
- const isFailed = routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.route.steps.some((step) => { var _a; return ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'FAILED'; });
119
- const alreadyStarted = routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.route.steps.some((step) => step.execution);
120
- if (!isDone &&
121
- !isFailed &&
122
- alreadyStarted &&
123
- account.signer &&
119
+ // Check if route is eligible for automatic resuming
120
+ if (isActiveRoute(routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.route) &&
121
+ account.isActive &&
124
122
  !resumedAfterMount.current) {
125
123
  resumedAfterMount.current = true;
126
124
  resumeRoute();
127
125
  }
126
+ // eslint-disable-next-line react-hooks/exhaustive-deps
127
+ }, [account.isActive]);
128
+ useEffect(() => {
128
129
  return () => {
129
- if (routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.route) {
130
- LiFi.moveExecutionToBackground(routeExecution.route);
130
+ var _a;
131
+ const route = (_a = useRouteStore.getState().routes[routeId]) === null || _a === void 0 ? void 0 : _a.route;
132
+ if (!route || !isActiveRoute(route)) {
133
+ return;
131
134
  }
135
+ LiFi.moveExecutionToBackground(route);
136
+ console.log('Move route execution to background.', routeId);
137
+ resumedAfterMount.current = false;
132
138
  };
133
- // eslint-disable-next-line react-hooks/exhaustive-deps
134
- }, [account.signer]);
139
+ }, [routeId]);
135
140
  return {
136
141
  executeRoute,
137
142
  restartRoute: restartRouteMutation,
@@ -140,3 +145,12 @@ export const useRouteExecution = (routeId) => {
140
145
  status: routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.status,
141
146
  };
142
147
  };
148
+ const isActiveRoute = (route) => {
149
+ if (!route) {
150
+ return false;
151
+ }
152
+ const allDone = route.steps.every((step) => { var _a; return ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'DONE'; });
153
+ const isFailed = route.steps.some((step) => { var _a; return ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'FAILED'; });
154
+ const alreadyStarted = route.steps.some((step) => step.execution);
155
+ return !allDone && !isFailed && alreadyStarted;
156
+ };
@@ -40,7 +40,7 @@ export const useSwapRoutes = () => {
40
40
  // Boolean(account.address) &&
41
41
  !isNaN(fromChainId) &&
42
42
  !isNaN(toChainId) &&
43
- Boolean(fromTokenAddress) &&
43
+ Boolean(token === null || token === void 0 ? void 0 : token.address) &&
44
44
  Boolean(toTokenAddress) &&
45
45
  !isNaN(fromTokenAmount) &&
46
46
  Number(fromTokenAmount) > 0 &&
@@ -49,7 +49,7 @@ export const useSwapRoutes = () => {
49
49
  'routes',
50
50
  account.address,
51
51
  fromChainId,
52
- fromTokenAddress,
52
+ token === null || token === void 0 ? void 0 : token.address,
53
53
  fromTokenAmount,
54
54
  toChainId,
55
55
  toTokenAddress,
@@ -17,7 +17,7 @@ export const useTokenBalance = (chainId, tokenAddress) => {
17
17
  const { account } = useWallet();
18
18
  const queryClient = useQueryClient();
19
19
  const { token } = useToken(chainId, tokenAddress);
20
- const { data: tokenWithBalance, isLoading, isFetching, refetch, } = useQuery(['token', account.address, chainId, tokenAddress], ({ queryKey: [, address] }) => __awaiter(void 0, void 0, void 0, function* () {
20
+ const { data: tokenWithBalance, isLoading, isFetching, refetch, } = useQuery(['token-balance', account.address, chainId, tokenAddress], ({ queryKey: [, address] }) => __awaiter(void 0, void 0, void 0, function* () {
21
21
  if (!address || !token) {
22
22
  return null;
23
23
  }
@@ -1,7 +1,9 @@
1
1
  import { TokenAmount } from '@lifi/sdk';
2
2
  export declare const useTokenBalances: (selectedChainId: number) => {
3
- tokens: TokenAmount[] | undefined;
3
+ tokens: import("@lifi/sdk").Token[] | undefined;
4
+ tokensWithBalance: TokenAmount[] | undefined;
4
5
  isLoading: boolean;
5
6
  isBalanceLoading: boolean;
6
- updateBalances: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<TokenAmount[], unknown>>;
7
+ isBalanceFetched: boolean;
8
+ updateBalances: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<TokenAmount[] | undefined, unknown>>;
7
9
  };
@@ -8,21 +8,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { useQuery } from '@tanstack/react-query';
11
+ import { useState } from 'react';
11
12
  import { LiFi } from '../config/lifi';
12
13
  import { useWallet } from '../providers/WalletProvider';
13
14
  import { formatTokenAmount } from '../utils';
14
- import { useChains } from './useChains';
15
15
  import { useTokens } from './useTokens';
16
+ const defaultRefetchInterval = 60000;
17
+ const minRefetchInterval = 1000;
16
18
  export const useTokenBalances = (selectedChainId) => {
17
19
  const { account } = useWallet();
18
- const { chains, isLoading: isChainsLoading } = useChains();
19
20
  const { tokens, isLoading } = useTokens(selectedChainId);
20
- const isBalanceLoadingEnabled = Boolean(account.address) && Boolean(tokens) && Boolean(chains);
21
- const { data: tokensWithBalance, isLoading: isBalanceLoading, refetch, } = useQuery(['token-balances', selectedChainId, account.address], ({ queryKey: [_, chainId, account] }) => __awaiter(void 0, void 0, void 0, function* () {
22
- if (!account || !tokens) {
23
- return [];
21
+ const [refetchInterval, setRefetchInterval] = useState(defaultRefetchInterval);
22
+ const isBalanceLoadingEnabled = Boolean(account.address) && Boolean(tokens);
23
+ const { data: tokensWithBalance, isLoading: isBalanceLoading, isFetched: isBalanceFetched, refetch, } = useQuery(['token-balances', selectedChainId, account.address], ({ queryKey: [, , accountAddress] }) => __awaiter(void 0, void 0, void 0, function* () {
24
+ if (!accountAddress || !tokens) {
25
+ return;
26
+ }
27
+ const tokenBalances = yield LiFi.getTokenBalances(accountAddress, tokens);
28
+ if (!(tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.length)) {
29
+ // Sometimes RPCs (e.g. Arbitrum) don't return balances on first call
30
+ // TODO: fix and remove backplane
31
+ setRefetchInterval((interval) => interval === defaultRefetchInterval
32
+ ? minRefetchInterval
33
+ : interval * 2);
34
+ return;
24
35
  }
25
- const tokenBalances = yield LiFi.getTokenBalances(account, tokens);
26
36
  const formatedTokens = (tokenBalances.length === 0 ? tokens : tokenBalances).map((token) => {
27
37
  token.amount = formatTokenAmount(token.amount);
28
38
  return token;
@@ -40,13 +50,15 @@ export const useTokenBalances = (selectedChainId) => {
40
50
  }), {
41
51
  enabled: isBalanceLoadingEnabled,
42
52
  refetchIntervalInBackground: true,
43
- refetchInterval: 60000,
44
- staleTime: 60000,
53
+ refetchInterval,
54
+ staleTime: refetchInterval,
45
55
  });
46
56
  return {
47
- tokens: tokensWithBalance !== null && tokensWithBalance !== void 0 ? tokensWithBalance : tokens,
48
- isLoading: isLoading || isChainsLoading,
57
+ tokens,
58
+ tokensWithBalance,
59
+ isLoading,
49
60
  isBalanceLoading: isBalanceLoading && isBalanceLoadingEnabled,
61
+ isBalanceFetched,
50
62
  updateBalances: refetch,
51
63
  };
52
64
  };
@@ -14,6 +14,7 @@
14
14
  "button": {
15
15
  "connectWallet": "Connect wallet",
16
16
  "switchChain": "Switch chain",
17
+ "swap": "Swap",
17
18
  "reviewSwap": "Review swap",
18
19
  "startSwap": "Start swap",
19
20
  "restartSwap": "Restart swap",
@@ -78,16 +79,19 @@
78
79
  },
79
80
  "info": {
80
81
  "title": {
81
- "routeNotFound": "No routes available"
82
+ "routeNotFound": "No routes available",
83
+ "emptySwapHistory": "No recent swaps"
82
84
  },
83
85
  "message": {
84
- "routeNotFound": "Try another token combination."
86
+ "routeNotFound": "Try another token combination.",
87
+ "emptySwapHistory": "Swap history is only stored locally and will be deleted if you clear your browser data."
85
88
  }
86
89
  },
87
90
  "warning": {
88
91
  "title": {
89
92
  "insufficientGas": "Insufficient gas",
90
- "deleteSwap": "Delete this swap?"
93
+ "deleteSwap": "Delete this swap?",
94
+ "deleteSwapHistory": "Delete swap history?"
91
95
  },
92
96
  "message": {
93
97
  "insufficientFunds": "You don't have enough funds to execute the swap.",
@@ -161,7 +165,7 @@
161
165
  },
162
166
  "tooltip": {
163
167
  "notFound": {
164
- "title": "Sorry 🥲",
168
+ "title": "404",
165
169
  "text": "We couldn't find this page."
166
170
  },
167
171
  "progressToNextUpdate": "Displayed data will auto-refresh after {{value}} seconds. Click this circle to update manually."
package/i18n/index.d.ts CHANGED
@@ -17,6 +17,7 @@ export declare const resources: {
17
17
  button: {
18
18
  connectWallet: string;
19
19
  switchChain: string;
20
+ swap: string;
20
21
  reviewSwap: string;
21
22
  startSwap: string;
22
23
  restartSwap: string;
@@ -82,15 +83,18 @@ export declare const resources: {
82
83
  info: {
83
84
  title: {
84
85
  routeNotFound: string;
86
+ emptySwapHistory: string;
85
87
  };
86
88
  message: {
87
89
  routeNotFound: string;
90
+ emptySwapHistory: string;
88
91
  };
89
92
  };
90
93
  warning: {
91
94
  title: {
92
95
  insufficientGas: string;
93
96
  deleteSwap: string;
97
+ deleteSwapHistory: string;
94
98
  };
95
99
  message: {
96
100
  insufficientFunds: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/widget",
3
- "version": "1.11.3",
3
+ "version": "1.12.1",
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
  "sideEffects": false,
6
6
  "main": "./index.js",
@@ -37,26 +37,26 @@
37
37
  "lifi"
38
38
  ],
39
39
  "dependencies": {
40
- "@emotion/react": "^11.9.3",
41
- "@emotion/styled": "^11.9.3",
40
+ "@emotion/react": "^11.10.0",
41
+ "@emotion/styled": "^11.10.0",
42
42
  "@ethersproject/experimental": "^5.6.3",
43
43
  "@ethersproject/providers": "^5.6.8",
44
- "@lifi/sdk": "^1.0.2",
45
- "@lifi/wallet-management": "^1.1.2",
44
+ "@lifi/sdk": "^1.1.3",
45
+ "@lifi/wallet-management": "^1.1.3",
46
46
  "@mui/icons-material": "^5.8.4",
47
- "@mui/lab": "^5.0.0-alpha.92",
48
- "@mui/material": "^5.9.2",
49
- "@sentry/integrations": "^7.7.0",
50
- "@sentry/react": "^7.7.0",
51
- "@sentry/tracing": "^7.7.0",
47
+ "@mui/lab": "^5.0.0-alpha.93",
48
+ "@mui/material": "^5.9.3",
49
+ "@sentry/integrations": "^7.9.0",
50
+ "@sentry/react": "^7.9.0",
51
+ "@sentry/tracing": "^7.9.0",
52
52
  "@tanstack/react-query": "^4.0.10",
53
53
  "big.js": "^6.2.1",
54
- "i18next": "^21.8.14",
54
+ "i18next": "^21.8.16",
55
55
  "immer": "^9.0.15",
56
56
  "react": "^18.2.0",
57
57
  "react-dom": "^18.2.0",
58
- "react-hook-form": "^7.33.1",
59
- "react-i18next": "^11.18.1",
58
+ "react-hook-form": "^7.34.0",
59
+ "react-i18next": "^11.18.3",
60
60
  "react-resize-detector": "^7.1.2",
61
61
  "react-router-dom": "^6.3.0",
62
62
  "react-timer-hook": "^3.0.5",
@@ -23,8 +23,8 @@ export const SwapRoutes = (props) => {
23
23
  if (!currentRoute && !isLoading && !isFetching && !isFetched) {
24
24
  return null;
25
25
  }
26
- const routeNotFound = !currentRoute && isFetched;
27
- return (_jsxs(_Fragment, { children: [_jsxs(Card, Object.assign({}, props, { children: [_jsx(CardTitle, { children: t('swap.routes') }), _jsx(ProgressToNextUpdate, { updatedAt: dataUpdatedAt, timeToUpdate: refetchTime, isLoading: isFetching, onClick: () => refetch(), sx: {
26
+ const routeNotFound = !currentRoute && !isLoading && !isFetching;
27
+ return (_jsxs(_Fragment, { children: [_jsxs(Card, Object.assign({}, props, { children: [_jsx(CardTitle, { children: t('swap.routes') }), _jsx(ProgressToNextUpdate, { updatedAt: dataUpdatedAt || new Date().getTime(), timeToUpdate: refetchTime, isLoading: isFetching, onClick: () => refetch(), sx: {
28
28
  position: 'absolute',
29
29
  top: 8,
30
30
  right: 8,
@@ -32,5 +32,5 @@ export const SwapRoutes = (props) => {
32
32
  borderWidth: !routeNotFound && (isFetching || (routes && routes.length > 1))
33
33
  ? 1
34
34
  : 0,
35
- } }, { children: routeNotFound ? (_jsx(SwapRouteNotFoundCard, { minWidth: "100%", dense: true })) : isLoading || isFetching || !currentRoute ? (_jsxs(_Fragment, { children: [_jsx(SwapRouteCardSkeleton, { minWidth: "80%", dense: true }), _jsx(SwapRouteCardSkeleton, { minWidth: "80%", dense: true })] })) : (_jsxs(_Fragment, { children: [_jsx(SwapRouteCard, { minWidth: routes.length > 1 ? '80%' : '100%', route: currentRoute, active: true, dense: true }), routes.length > 1 ? (_jsx(SwapRouteCard, { minWidth: "80%", route: routes[1], dense: true })) : null] })) })), _jsx(Box, Object.assign({ sx: { display: 'flex', alignItems: 'center' } }, { children: !routeNotFound ? (_jsx(Box, Object.assign({ py: 1, pr: 1 }, { children: _jsx(IconButton, Object.assign({ onClick: handleCardClick, size: "medium", "aria-label": "swap-routes" }, { children: _jsx(KeyboardArrowRightIcon, {}) })) }))) : null }))] }))] })), _jsx(GasSufficiencyMessage, Object.assign({ route: !isFetching ? currentRoute : undefined }, props))] }));
35
+ } }, { children: isLoading || isFetching ? (_jsxs(_Fragment, { children: [_jsx(SwapRouteCardSkeleton, { minWidth: "80%", dense: true }), _jsx(SwapRouteCardSkeleton, { minWidth: "80%", dense: true })] })) : !currentRoute ? (_jsx(SwapRouteNotFoundCard, { minWidth: "100%", dense: true })) : (_jsxs(_Fragment, { children: [_jsx(SwapRouteCard, { minWidth: routes.length > 1 ? '80%' : '100%', route: currentRoute, active: true, dense: true }), routes.length > 1 ? (_jsx(SwapRouteCard, { minWidth: "80%", route: routes[1], dense: true })) : null] })) })), _jsx(Box, Object.assign({ sx: { display: 'flex', alignItems: 'center' } }, { children: !routeNotFound ? (_jsx(Box, Object.assign({ py: 1, pr: 1 }, { children: _jsx(IconButton, Object.assign({ onClick: handleCardClick, size: "medium", "aria-label": "swap-routes" }, { children: _jsx(KeyboardArrowRightIcon, {}) })) }))) : null }))] }))] })), _jsx(GasSufficiencyMessage, Object.assign({ route: !isFetching ? currentRoute : undefined }, props))] }));
36
36
  };
@@ -8,4 +8,4 @@ export declare const Stack: import("@emotion/styled").StyledComponent<import("@m
8
8
  sx?: import("@mui/material").SxProps<import("@mui/material").Theme> | undefined;
9
9
  } & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import("react").HTMLAttributes<HTMLDivElement>> & {
10
10
  ref?: import("react").RefObject<HTMLDivElement> | ((instance: HTMLDivElement | null) => void) | null | undefined;
11
- }, keyof import("@mui/material/OverridableComponent").CommonProps | "children" | "sx" | "ref" | "direction" | ("p" | "color" | "border" | "boxShadow" | "fontWeight" | "zIndex" | "alignContent" | "alignItems" | "alignSelf" | "bottom" | "boxSizing" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFamily" | "fontSize" | "fontStyle" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lineHeight" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "order" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "rowGap" | "textAlign" | "textOverflow" | "textTransform" | "top" | "visibility" | "whiteSpace" | "width" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderTop" | "flex" | "gap" | "gridArea" | "gridColumn" | "gridRow" | "margin" | "overflow" | "padding" | "bgcolor" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "typography" | "displayPrint") | "spacing" | "divider"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
11
+ }, keyof import("@mui/material/OverridableComponent").CommonProps | "children" | "sx" | "ref" | "direction" | ("p" | "color" | "border" | "boxShadow" | "fontWeight" | "zIndex" | "alignContent" | "alignItems" | "alignSelf" | "bottom" | "boxSizing" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFamily" | "fontSize" | "fontStyle" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lineHeight" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "order" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "rowGap" | "textAlign" | "textOverflow" | "textTransform" | "top" | "visibility" | "whiteSpace" | "width" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderTop" | "flex" | "gap" | "gridArea" | "gridColumn" | "gridRow" | "margin" | "overflow" | "padding" | "bgcolor" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "typography" | "displayPrint") | "divider" | "spacing"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
@@ -17,7 +17,7 @@ export declare const WalletListItemButton: import("@emotion/styled").StyledCompo
17
17
  touchRippleRef?: import("react").Ref<import("@mui/material/ButtonBase/TouchRipple").TouchRippleActions> | undefined;
18
18
  }, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import("react").HTMLAttributes<HTMLDivElement>> & {
19
19
  ref?: import("react").RefObject<HTMLDivElement> | ((instance: HTMLDivElement | null) => void) | null | undefined;
20
- }, "className" | "style" | "classes" | "tabIndex" | "children" | "action" | "centerRipple" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "TouchRippleProps" | "touchRippleRef" | "alignItems" | "autoFocus" | "dense" | "selected" | "disableGutters" | "divider"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
20
+ }, "className" | "style" | "classes" | "tabIndex" | "children" | "action" | "centerRipple" | "disabled" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "sx" | "TouchRippleProps" | "touchRippleRef" | "alignItems" | "autoFocus" | "dense" | "divider" | "selected" | "disableGutters"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
21
21
  export declare const WalletListItem: import("@emotion/styled").StyledComponent<{
22
22
  button?: false | undefined;
23
23
  } & import("@mui/material").ListItemBaseProps & {
@@ -29,7 +29,7 @@ export declare const WalletListItem: import("@emotion/styled").StyledComponent<{
29
29
  } | undefined;
30
30
  } & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "key" | keyof import("react").LiHTMLAttributes<HTMLLIElement>> & {
31
31
  ref?: ((instance: HTMLLIElement | null) => void) | import("react").RefObject<HTMLLIElement> | null | undefined;
32
- }, "button" | "className" | "style" | "classes" | "children" | "disabled" | "sx" | "alignItems" | "autoFocus" | "dense" | "components" | "componentsProps" | "selected" | "disableGutters" | "divider" | "ContainerComponent" | "ContainerProps" | "disablePadding" | "secondaryAction"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
32
+ }, "button" | "className" | "style" | "classes" | "children" | "disabled" | "sx" | "alignItems" | "autoFocus" | "dense" | "divider" | "components" | "componentsProps" | "selected" | "disableGutters" | "ContainerComponent" | "ContainerProps" | "disablePadding" | "secondaryAction"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
33
33
  export declare const WalletListItemText: import("@emotion/styled").StyledComponent<import("@mui/material").ListItemTextProps<import("react").ElementType<any>, import("react").ElementType<any>> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
34
34
  export declare const WalletIdentityPopoverContent: import("@emotion/styled").StyledComponent<import("@mui/system").SystemProps<import("@mui/material").Theme> & {
35
35
  align?: "inherit" | "left" | "right" | "center" | "justify" | undefined;
@@ -2,7 +2,7 @@
2
2
  export declare const ToggleButton: import("@emotion/styled").StyledComponent<{
3
3
  children?: import("react").ReactNode;
4
4
  classes?: Partial<import("@mui/material").ToggleButtonClasses> | undefined;
5
- color?: "success" | "info" | "warning" | "error" | "primary" | "secondary" | "standard" | undefined;
5
+ color?: "primary" | "secondary" | "error" | "warning" | "info" | "success" | "standard" | undefined;
6
6
  disabled?: boolean | undefined;
7
7
  disableFocusRipple?: boolean | undefined;
8
8
  fullWidth?: boolean | undefined;
@@ -10,5 +10,5 @@ export const SwapHistoryEmpty = () => {
10
10
  flexDirection: 'column',
11
11
  alignItems: 'center',
12
12
  justifyContent: 'center',
13
- } }, { children: [_jsx(Typography, Object.assign({ fontSize: 48 }, { children: _jsx(HistoryIcon, { fontSize: "inherit" }) })), _jsx(Typography, Object.assign({ fontSize: 18, fontWeight: 700 }, { children: "No recent swaps" })), _jsx(Typography, Object.assign({ fontSize: 14, color: "text.secondary", textAlign: "center", mt: 2 }, { children: "Swap history is only stored locally and will be deleted if you clear your browser data." }))] })));
13
+ } }, { children: [_jsx(Typography, Object.assign({ fontSize: 48 }, { children: _jsx(HistoryIcon, { fontSize: "inherit" }) })), _jsx(Typography, Object.assign({ fontSize: 18, fontWeight: 700 }, { children: t('swap.info.title.emptySwapHistory') })), _jsx(Typography, Object.assign({ fontSize: 14, color: "text.secondary", textAlign: "center", mt: 2 }, { children: t('swap.info.message.emptySwapHistory') }))] })));
14
14
  };
@@ -1,14 +1,30 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Container, Stack } from '@mui/material';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DeleteOutline as DeleteIcon } from '@mui/icons-material';
3
+ import { Button, Container, DialogActions, DialogContent, DialogContentText, DialogTitle, IconButton, Stack, } from '@mui/material';
4
+ import { useCallback, useEffect, useState } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { Dialog } from '../../components/Dialog';
7
+ import { useSetHeaderAction } from '../../components/Header';
3
8
  import { useWallet } from '../../providers/WalletProvider';
9
+ import { useRouteStore } from '../../stores';
4
10
  import { useSwapHistory } from '../../stores/route';
5
11
  import { SwapHistoryEmpty } from './SwapHistoryEmpty';
6
12
  import { SwapHistoryItem } from './SwapHistoryItem';
7
13
  export const SwapHistoryPage = () => {
14
+ const { t } = useTranslation();
8
15
  const { account } = useWallet();
9
16
  const swaps = useSwapHistory(account.address);
17
+ const deleteRoutes = useRouteStore((store) => store.deleteRoutes);
18
+ const setHeaderAction = useSetHeaderAction();
19
+ const [open, setOpen] = useState(false);
20
+ const toggleDialog = useCallback(() => {
21
+ setOpen((open) => !open);
22
+ }, []);
23
+ useEffect(() => {
24
+ return setHeaderAction(_jsx(IconButton, Object.assign({ size: "medium", "aria-label": "settings", edge: "end", onClick: toggleDialog }, { children: _jsx(DeleteIcon, {}) })));
25
+ }, [setHeaderAction, toggleDialog]);
10
26
  if (!swaps.length) {
11
27
  return _jsx(SwapHistoryEmpty, {});
12
28
  }
13
- return (_jsx(Container, { children: _jsx(Stack, Object.assign({ spacing: 2, mt: 1 }, { children: swaps.length ? (swaps.map(({ route }) => (_jsx(SwapHistoryItem, { route: route }, route.id)))) : (_jsx(SwapHistoryEmpty, {})) })) }));
29
+ return (_jsxs(Container, { children: [_jsx(Stack, Object.assign({ spacing: 2, mt: 1 }, { children: swaps.length ? (swaps.map(({ route }) => (_jsx(SwapHistoryItem, { route: route }, route.id)))) : (_jsx(SwapHistoryEmpty, {})) })), _jsxs(Dialog, Object.assign({ open: open, onClose: toggleDialog }, { children: [_jsx(DialogTitle, { children: t('swap.warning.title.deleteSwapHistory') }), _jsx(DialogContent, { children: _jsx(DialogContentText, { children: t('swap.warning.message.deleteSwap') }) }), _jsxs(DialogActions, { children: [_jsx(Button, Object.assign({ onClick: toggleDialog }, { children: t('button.cancel') })), _jsx(Button, Object.assign({ onClick: deleteRoutes, autoFocus: true }, { children: t('button.delete') }))] })] }))] }));
14
30
  };
@@ -28,8 +28,8 @@ export const SwapRoutesPage = () => {
28
28
  // eslint-disable-next-line react-hooks/exhaustive-deps
29
29
  }, []);
30
30
  useEffect(() => {
31
- return setHeaderAction(_jsx(ProgressToNextUpdate, { updatedAt: dataUpdatedAt, timeToUpdate: refetchTime, isLoading: isFetching, onClick: () => refetch(), sx: { marginRight: -1 }, size: "medium", edge: "end" }));
31
+ return setHeaderAction(_jsx(ProgressToNextUpdate, { updatedAt: dataUpdatedAt || new Date().getTime(), timeToUpdate: refetchTime, isLoading: isFetching, onClick: () => refetch(), sx: { marginRight: -1 }, size: "medium", edge: "end" }));
32
32
  }, [dataUpdatedAt, isFetching, refetch, refetchTime, setHeaderAction]);
33
- const routeNotFound = !(swapRoutes === null || swapRoutes === void 0 ? void 0 : swapRoutes.length) && isFetched;
34
- return (_jsx(Stack, Object.assign({ direction: "column", spacing: 2 }, { children: routeNotFound ? (_jsx(SwapRouteNotFoundCard, {})) : isLoading || isFetching ? (Array.from({ length: 3 }).map((_, index) => (_jsx(SwapRouteCardSkeleton, {}, index)))) : (swapRoutes === null || swapRoutes === void 0 ? void 0 : swapRoutes.map((route, index) => (_jsx(SwapRouteCard, { route: route, onClick: () => handleRouteClick(route) }, route.id)))) })));
33
+ const routeNotFound = !(swapRoutes === null || swapRoutes === void 0 ? void 0 : swapRoutes.length) && !isLoading && !isFetching;
34
+ return (_jsx(Stack, Object.assign({ direction: "column", spacing: 2, flex: 1 }, { children: routeNotFound ? (_jsx(SwapRouteNotFoundCard, {})) : isLoading || isFetching ? (Array.from({ length: 3 }).map((_, index) => (_jsx(SwapRouteCardSkeleton, {}, index)))) : (swapRoutes === null || swapRoutes === void 0 ? void 0 : swapRoutes.map((route) => (_jsx(SwapRouteCard, { route: route, onClick: () => handleRouteClick(route) }, route.id)))) })));
35
35
  };
@@ -8,4 +8,4 @@ export declare const Stack: import("@emotion/styled").StyledComponent<import("@m
8
8
  sx?: import("@mui/material").SxProps<import("@mui/material").Theme> | undefined;
9
9
  } & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import("react").HTMLAttributes<HTMLDivElement>> & {
10
10
  ref?: import("react").RefObject<HTMLDivElement> | ((instance: HTMLDivElement | null) => void) | null | undefined;
11
- }, keyof import("@mui/material/OverridableComponent").CommonProps | "children" | "sx" | "ref" | "direction" | ("p" | "color" | "border" | "boxShadow" | "fontWeight" | "zIndex" | "alignContent" | "alignItems" | "alignSelf" | "bottom" | "boxSizing" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFamily" | "fontSize" | "fontStyle" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lineHeight" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "order" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "rowGap" | "textAlign" | "textOverflow" | "textTransform" | "top" | "visibility" | "whiteSpace" | "width" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderTop" | "flex" | "gap" | "gridArea" | "gridColumn" | "gridRow" | "margin" | "overflow" | "padding" | "bgcolor" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "typography" | "displayPrint") | "spacing" | "divider"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
11
+ }, keyof import("@mui/material/OverridableComponent").CommonProps | "children" | "sx" | "ref" | "direction" | ("p" | "color" | "border" | "boxShadow" | "fontWeight" | "zIndex" | "alignContent" | "alignItems" | "alignSelf" | "bottom" | "boxSizing" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFamily" | "fontSize" | "fontStyle" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lineHeight" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "order" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "rowGap" | "textAlign" | "textOverflow" | "textTransform" | "top" | "visibility" | "whiteSpace" | "width" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderTop" | "flex" | "gap" | "gridArea" | "gridColumn" | "gridRow" | "margin" | "overflow" | "padding" | "bgcolor" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "typography" | "displayPrint") | "divider" | "spacing"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
@@ -1,4 +1,14 @@
1
+ import { Signer } from 'ethers';
1
2
  import { FC, PropsWithChildren } from 'react';
3
+ import { WidgetWalletManagement } from '../../types';
2
4
  import type { WalletContextProps } from './types';
3
5
  export declare const useWallet: () => WalletContextProps;
4
- export declare const WalletProvider: FC<PropsWithChildren<{}>>;
6
+ export declare const WalletProvider: FC<PropsWithChildren<{
7
+ walletManagement?: WidgetWalletManagement;
8
+ }>>;
9
+ export declare const extractAccountFromSigner: (signer?: Signer) => Promise<{
10
+ address: string | undefined;
11
+ isActive: boolean;
12
+ signer: Signer | undefined;
13
+ chainId: number | undefined;
14
+ }>;
@@ -8,9 +8,8 @@ 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 { addChain as walletAddChain, switchChain as walletSwitchChain, switchChainAndAddToken, useLifiWalletManagement, } from '@lifi/wallet-management';
11
+ import { addChain as walletAddChain, switchChain as walletSwitchChain, switchChainAndAddToken, useLiFiWalletManagement, } from '@lifi/wallet-management';
12
12
  import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from 'react';
13
- import { useWidgetConfig } from '../WidgetProvider';
14
13
  const stub = () => {
15
14
  throw new Error('You forgot to wrap your component in <WalletProvider>.');
16
15
  };
@@ -24,65 +23,57 @@ const initialContext = {
24
23
  };
25
24
  const WalletContext = createContext(initialContext);
26
25
  export const useWallet = () => useContext(WalletContext);
27
- export const WalletProvider = ({ children }) => {
28
- const config = useWidgetConfig();
29
- const { connect: walletManagementConnect, disconnect: walletManagementDisconnect, signer, } = useLifiWalletManagement();
26
+ export const WalletProvider = ({ children, walletManagement }) => {
27
+ const { connect: walletManagementConnect, disconnect: walletManagementDisconnect, signer, } = useLiFiWalletManagement();
30
28
  const [account, setAccount] = useState({});
31
29
  const connect = useCallback((wallet) => __awaiter(void 0, void 0, void 0, function* () {
32
- if (config.walletManagement) {
33
- const signer = yield config.walletManagement.connect();
30
+ if (walletManagement) {
31
+ const signer = yield walletManagement.connect();
34
32
  const account = yield extractAccountFromSigner(signer);
35
33
  setAccount(account);
36
34
  return;
37
35
  }
38
36
  yield walletManagementConnect(wallet);
39
- }), [config.walletManagement, walletManagementConnect]);
37
+ }), [walletManagement, walletManagementConnect]);
40
38
  const disconnect = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
41
- if (config.walletManagement) {
42
- yield config.walletManagement.disconnect();
39
+ if (walletManagement) {
40
+ yield walletManagement.disconnect();
43
41
  setAccount({});
44
42
  return;
45
43
  }
46
44
  yield walletManagementDisconnect();
47
- }), [config.walletManagement, walletManagementDisconnect]);
45
+ }), [walletManagement, walletManagementDisconnect]);
48
46
  // only for injected wallets
49
47
  const switchChain = useCallback((chainId) => __awaiter(void 0, void 0, void 0, function* () {
50
- var _a;
51
- if ((_a = config.walletManagement) === null || _a === void 0 ? void 0 : _a.switchChain) {
52
- const signer = yield config.walletManagement.switchChain(chainId);
48
+ if (walletManagement === null || walletManagement === void 0 ? void 0 : walletManagement.switchChain) {
49
+ const signer = yield walletManagement.switchChain(chainId);
53
50
  const account = yield extractAccountFromSigner(signer);
54
51
  setAccount(account);
52
+ return true;
55
53
  }
56
54
  return walletSwitchChain(chainId);
57
- }), [config.walletManagement]);
55
+ }), [walletManagement]);
58
56
  const addChain = useCallback((chainId) => __awaiter(void 0, void 0, void 0, function* () {
59
- var _b;
60
- if ((_b = config.walletManagement) === null || _b === void 0 ? void 0 : _b.addChain) {
61
- return config.walletManagement.addChain(chainId);
57
+ if (walletManagement === null || walletManagement === void 0 ? void 0 : walletManagement.addChain) {
58
+ return walletManagement.addChain(chainId);
62
59
  }
63
60
  return walletAddChain(chainId);
64
- }), [config.walletManagement]);
61
+ }), [walletManagement]);
65
62
  const addToken = useCallback((chainId, token) => __awaiter(void 0, void 0, void 0, function* () {
66
- var _c;
67
- if ((_c = config.walletManagement) === null || _c === void 0 ? void 0 : _c.addToken) {
68
- return config.walletManagement.addToken(token, chainId);
63
+ if (walletManagement === null || walletManagement === void 0 ? void 0 : walletManagement.addToken) {
64
+ return walletManagement.addToken(token, chainId);
69
65
  }
70
66
  return switchChainAndAddToken(chainId, token);
71
- }), [config.walletManagement]);
67
+ }), [walletManagement]);
72
68
  // keep account information up to date
73
69
  useEffect(() => {
74
70
  const updateAccount = () => __awaiter(void 0, void 0, void 0, function* () {
75
- if (config.walletManagement) {
76
- const account = yield extractAccountFromSigner(config.walletManagement.signer);
77
- setAccount(account);
78
- }
79
- else {
80
- const account = yield extractAccountFromSigner(signer);
81
- setAccount(account);
82
- }
71
+ var _a;
72
+ const account = yield extractAccountFromSigner((_a = walletManagement === null || walletManagement === void 0 ? void 0 : walletManagement.signer) !== null && _a !== void 0 ? _a : signer);
73
+ setAccount(account);
83
74
  });
84
75
  updateAccount();
85
- }, [signer, config.walletManagement]);
76
+ }, [signer, walletManagement]);
86
77
  const value = useMemo(() => ({
87
78
  connect,
88
79
  disconnect,
@@ -93,7 +84,7 @@ export const WalletProvider = ({ children }) => {
93
84
  }), [account, addChain, addToken, connect, disconnect, switchChain]);
94
85
  return (_jsx(WalletContext.Provider, Object.assign({ value: value }, { children: children })));
95
86
  };
96
- const extractAccountFromSigner = (signer) => __awaiter(void 0, void 0, void 0, function* () {
87
+ export const extractAccountFromSigner = (signer) => __awaiter(void 0, void 0, void 0, function* () {
97
88
  return ({
98
89
  address: (yield (signer === null || signer === void 0 ? void 0 : signer.getAddress())) || undefined,
99
90
  isActive: (signer && !!(yield signer.getAddress()) === null) || !!signer,
@@ -13,6 +13,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import { ChainId, getChainByKey } from '@lifi/sdk';
14
14
  import { createContext, useContext, useEffect, useMemo } from 'react';
15
15
  import { updateLiFiConfig } from '../../config/lifi';
16
+ import { useWallet } from '../WalletProvider';
16
17
  const stub = () => {
17
18
  throw new Error('You forgot to wrap your component in <WidgetProvider>.');
18
19
  };
@@ -23,13 +24,15 @@ const WidgetContext = createContext(initialContext);
23
24
  export const useWidgetConfig = () => useContext(WidgetContext);
24
25
  export const WidgetProvider = (_a) => {
25
26
  var { children } = _a, _b = _a.config, _c = _b === void 0 ? {} : _b, { fromChain, fromToken, toChain, toToken, integrator } = _c, config = __rest(_c, ["fromChain", "fromToken", "toChain", "toToken", "integrator"]);
27
+ const { account } = useWallet();
26
28
  const value = useMemo(() => {
29
+ var _a;
27
30
  try {
28
31
  return Object.assign(Object.assign({}, config), { fromChain: typeof fromChain === 'number'
29
32
  ? fromChain
30
33
  : typeof fromChain === 'string'
31
34
  ? getChainByKey(fromChain.toLowerCase()).id
32
- : ChainId.ETH, toChain: typeof toChain === 'number'
35
+ : (_a = account.chainId) !== null && _a !== void 0 ? _a : ChainId.ETH, toChain: typeof toChain === 'number'
33
36
  ? toChain
34
37
  : typeof toChain === 'string'
35
38
  ? getChainByKey(toChain.toLowerCase()).id
@@ -39,7 +42,7 @@ export const WidgetProvider = (_a) => {
39
42
  console.warn(e);
40
43
  return config;
41
44
  }
42
- }, [config, fromChain, fromToken, toChain, toToken]);
45
+ }, [account.chainId, config, fromChain, fromToken, toChain, toToken]);
43
46
  useEffect(() => {
44
47
  updateLiFiConfig({
45
48
  defaultRouteOptions: {
@@ -5,6 +5,7 @@ export interface RouteExecutionStore {
5
5
  updateRoute: (route: Route) => void;
6
6
  restartRoute: (routeId: string) => void;
7
7
  deleteRoute: (routeId: string) => void;
8
+ deleteRoutes: () => void;
8
9
  }
9
10
  export declare type RouteExecutionStatus = 'error' | 'idle' | 'loading' | 'success';
10
11
  export interface RouteExecution {
@@ -35,18 +35,6 @@ export const useRouteStore = create()(persist(immer((set) => ({
35
35
  }
36
36
  }),
37
37
  restartRoute: (routeId) => set((state) => {
38
- var _a;
39
- (_a = state.routes[routeId]) === null || _a === void 0 ? void 0 : _a.route.steps.forEach((step) => {
40
- var _a, _b;
41
- const stepHasFailed = ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'FAILED';
42
- // check if the step has been cancelled which is a "failed" state
43
- const stepHasBeenCancelled = (_b = step.execution) === null || _b === void 0 ? void 0 : _b.process.some((process) => process.status === 'CANCELLED');
44
- if (step.execution && (stepHasFailed || stepHasBeenCancelled)) {
45
- step.execution.status = 'RESUME';
46
- // remove last (failed) process
47
- step.execution.process.pop();
48
- }
49
- });
50
38
  state.routes[routeId].status = 'loading';
51
39
  }),
52
40
  deleteRoute: (routeId) => set((state) => {
@@ -54,6 +42,9 @@ export const useRouteStore = create()(persist(immer((set) => ({
54
42
  delete state.routes[routeId];
55
43
  }
56
44
  }),
45
+ deleteRoutes: () => set((state) => {
46
+ state.routes = {};
47
+ }),
57
48
  })), {
58
49
  name: 'li.fi-widget-routes',
59
50
  partialize: (state) => ({ routes: state.routes }),
package/types/widget.d.ts CHANGED
@@ -5,7 +5,7 @@ import { Signer } from 'ethers';
5
5
  import { CSSProperties } from 'react';
6
6
  export declare type Appearance = PaletteMode | 'auto';
7
7
  export declare type ThemeConfig = {
8
- palette?: PaletteOptions;
8
+ palette?: Pick<PaletteOptions, 'primary' | 'secondary'>;
9
9
  shape?: Shape;
10
10
  typography?: TypographyOptions;
11
11
  };
package/utils/colors.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import { Theme } from '@mui/material';
2
2
  export declare const getContrastAlphaColor: (theme: Theme, alpha: string | number) => string;
3
+ export declare const getContrastTextColor: (theme: Theme, background?: string) => string;
package/utils/colors.js CHANGED
@@ -1,3 +1,8 @@
1
+ import { getContrastRatio } from '@mui/material/styles';
2
+ import { dark, light } from '@mui/material/styles/createPalette';
1
3
  export const getContrastAlphaColor = (theme, alpha) => theme.palette.mode === 'light'
2
4
  ? `rgb(0 0 0 / ${alpha})`
3
5
  : `rgb(255 255 255 / ${alpha})`;
6
+ export const getContrastTextColor = (theme, background) => getContrastRatio(dark.text.primary, background !== null && background !== void 0 ? background : theme.palette.primary.main) >= 3
7
+ ? dark.text.primary
8
+ : light.text.primary;