@lifi/widget 1.25.1 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/cjs/components/ActiveSwaps/ActiveSwapItem.js +6 -3
  2. package/cjs/components/GasSufficiencyMessage/GasSufficiencyMessage.js +1 -1
  3. package/cjs/components/Header/NavigationHeader.js +1 -1
  4. package/cjs/components/Header/WalletHeader.js +1 -1
  5. package/cjs/components/ReverseTokensButton/ReverseTokensButton.style.js +1 -1
  6. package/cjs/components/Step/CircularProgress.d.ts +3 -3
  7. package/cjs/components/Step/CircularProgress.js +10 -9
  8. package/cjs/components/Step/CircularProgress.style.d.ts +12 -3
  9. package/cjs/components/Step/CircularProgress.style.js +26 -10
  10. package/cjs/components/Step/DestinationWalletAddress.d.ts +7 -0
  11. package/cjs/components/Step/DestinationWalletAddress.js +32 -0
  12. package/cjs/components/Step/GasStepProcess.d.ts +5 -0
  13. package/cjs/components/Step/GasStepProcess.js +24 -0
  14. package/cjs/components/Step/Step.d.ts +1 -0
  15. package/cjs/components/Step/Step.js +18 -6
  16. package/cjs/components/Step/StepList.d.ts +3 -0
  17. package/cjs/components/Step/StepList.js +20 -0
  18. package/cjs/components/Step/StepProcess.js +2 -2
  19. package/cjs/components/Step/index.d.ts +1 -0
  20. package/cjs/components/Step/index.js +1 -0
  21. package/cjs/components/SwapButton/SwapButton.js +1 -1
  22. package/cjs/components/SwapRouteCard/SwapRouteNotFoundCard.js +1 -1
  23. package/cjs/config/sentry.js +1 -1
  24. package/cjs/config/version.d.ts +1 -1
  25. package/cjs/config/version.js +1 -1
  26. package/cjs/hooks/useChains.js +4 -1
  27. package/cjs/hooks/useProcessMessage.js +47 -5
  28. package/cjs/hooks/useRouteExecution.d.ts +8 -2
  29. package/cjs/hooks/useRouteExecution.js +14 -5
  30. package/cjs/hooks/useSwapRoutes.d.ts +2 -2
  31. package/cjs/hooks/useSwapRoutes.js +7 -0
  32. package/cjs/hooks/useTokenBalance.js +2 -2
  33. package/cjs/hooks/useTools.js +2 -0
  34. package/cjs/i18n/en.json +44 -28
  35. package/cjs/pages/SwapDetailsPage/SwapDetailsPage.js +10 -15
  36. package/cjs/pages/SwapHistoryPage/SwapHistoryEmpty.js +1 -1
  37. package/cjs/pages/SwapPage/ExchangeRateBottomSheet.d.ts +15 -0
  38. package/cjs/pages/SwapPage/ExchangeRateBottomSheet.js +71 -0
  39. package/cjs/pages/SwapPage/StatusBottomSheet.js +20 -4
  40. package/cjs/pages/SwapPage/StatusBottomSheet.style.js +4 -4
  41. package/cjs/pages/SwapPage/SwapPage.js +12 -14
  42. package/cjs/pages/SwapPage/TokenValueBottomSheet.js +3 -2
  43. package/cjs/utils/navigationRoutes.js +1 -0
  44. package/components/ActiveSwaps/ActiveSwapItem.js +6 -3
  45. package/components/GasSufficiencyMessage/GasSufficiencyMessage.js +1 -1
  46. package/components/Header/NavigationHeader.js +2 -2
  47. package/components/Header/WalletHeader.js +1 -1
  48. package/components/ReverseTokensButton/ReverseTokensButton.style.js +1 -1
  49. package/components/Step/CircularProgress.d.ts +3 -3
  50. package/components/Step/CircularProgress.js +12 -11
  51. package/components/Step/CircularProgress.style.d.ts +12 -3
  52. package/components/Step/CircularProgress.style.js +27 -11
  53. package/components/Step/DestinationWalletAddress.d.ts +7 -0
  54. package/components/Step/DestinationWalletAddress.js +28 -0
  55. package/components/Step/GasStepProcess.d.ts +5 -0
  56. package/components/Step/GasStepProcess.js +20 -0
  57. package/components/Step/Step.d.ts +1 -0
  58. package/components/Step/Step.js +18 -6
  59. package/components/Step/StepList.d.ts +3 -0
  60. package/components/Step/StepList.js +16 -0
  61. package/components/Step/StepProcess.js +2 -2
  62. package/components/Step/index.d.ts +1 -0
  63. package/components/Step/index.js +1 -0
  64. package/components/SwapButton/SwapButton.js +1 -1
  65. package/components/SwapRouteCard/SwapRouteNotFoundCard.js +1 -1
  66. package/config/sentry.js +1 -1
  67. package/config/version.d.ts +1 -1
  68. package/config/version.js +1 -1
  69. package/hooks/useChains.js +5 -2
  70. package/hooks/useProcessMessage.js +47 -5
  71. package/hooks/useRouteExecution.d.ts +8 -2
  72. package/hooks/useRouteExecution.js +15 -6
  73. package/hooks/useSwapRoutes.d.ts +2 -2
  74. package/hooks/useSwapRoutes.js +7 -0
  75. package/hooks/useTokenBalance.js +2 -2
  76. package/hooks/useTools.js +2 -0
  77. package/i18n/en.json +44 -28
  78. package/package.json +9 -9
  79. package/pages/SwapDetailsPage/SwapDetailsPage.js +14 -19
  80. package/pages/SwapHistoryPage/SwapHistoryEmpty.js +1 -1
  81. package/pages/SwapPage/ExchangeRateBottomSheet.d.ts +15 -0
  82. package/pages/SwapPage/ExchangeRateBottomSheet.js +67 -0
  83. package/pages/SwapPage/StatusBottomSheet.js +22 -6
  84. package/pages/SwapPage/StatusBottomSheet.style.js +4 -4
  85. package/pages/SwapPage/SwapPage.js +15 -17
  86. package/pages/SwapPage/TokenValueBottomSheet.js +3 -2
  87. package/tsconfig.cjs.tsbuildinfo +1 -1
  88. package/utils/navigationRoutes.js +1 -0
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ArrowForward as ArrowForwardIcon, Info as InfoIcon, Warning as WarningIcon, } from '@mui/icons-material';
2
+ import { ArrowForward as ArrowForwardIcon, ErrorRounded as ErrorIcon, InfoRounded as InfoIcon } from '@mui/icons-material';
3
3
  import { ListItemAvatar, ListItemText, Typography } from '@mui/material';
4
4
  import { useNavigate } from 'react-router-dom';
5
5
  import { useProcessMessage, useRouteExecution } from '../../hooks';
@@ -11,7 +11,10 @@ import { ListItem, ListItemButton } from './ActiveSwaps.style';
11
11
  export const ActiveSwapItem = ({ routeId, dense }) => {
12
12
  var _a;
13
13
  const navigate = useNavigate();
14
- const { route, status } = useRouteExecution(routeId, true);
14
+ const { route, status } = useRouteExecution({
15
+ routeId,
16
+ executeInBackground: true,
17
+ });
15
18
  // TODO: replace with ES2023 findLast
16
19
  const lastActiveStep = route === null || route === void 0 ? void 0 : route.steps.slice().reverse().find((step) => step.execution);
17
20
  const lastActiveProcess = (_a = lastActiveStep === null || lastActiveStep === void 0 ? void 0 : lastActiveStep.execution) === null || _a === void 0 ? void 0 : _a.process.at(-1);
@@ -27,7 +30,7 @@ export const ActiveSwapItem = ({ routeId, dense }) => {
27
30
  case 'ACTION_REQUIRED':
28
31
  return _jsx(InfoIcon, { color: "info", fontSize: "small" });
29
32
  case 'FAILED':
30
- return _jsx(WarningIcon, { color: "error", fontSize: "small" });
33
+ return _jsx(ErrorIcon, { color: "error", fontSize: "small" });
31
34
  default:
32
35
  return (_jsx(Typography, Object.assign({ fontSize: 14, fontWeight: 500 }, { children: _jsx(StepTimer, { step: lastActiveStep, hideInProgress: true }) })));
33
36
  }
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { WarningAmber as WarningIcon } from '@mui/icons-material';
13
+ import { WarningAmberRounded as WarningIcon } from '@mui/icons-material';
14
14
  import { Box, Collapse, Typography } from '@mui/material';
15
15
  import { useTranslation } from 'react-i18next';
16
16
  import { useGasSufficiency } from '../../hooks';
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ArrowBack as ArrowBackIcon, History as HistoryIcon, SettingsOutlined as SettingsIcon, } from '@mui/icons-material';
2
+ import { ArrowBack as ArrowBackIcon, ReceiptLongRounded as HistoryIcon, SettingsOutlined as SettingsIcon } from '@mui/icons-material';
3
3
  import { Box, IconButton, Tooltip, Typography } from '@mui/material';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { Route, Routes, useLocation } from 'react-router-dom';
6
6
  import { useNavigateBack } from '../../hooks';
7
7
  import { useWallet, useWidgetConfig } from '../../providers';
8
- import { backButtonRoutes, navigationRoutes, navigationRoutesValues, } from '../../utils';
8
+ import { backButtonRoutes, navigationRoutes, navigationRoutesValues } from '../../utils';
9
9
  import { HeaderAppBar } from './Header.style';
10
10
  import { useHeaderActionStore } from './useHeaderActionStore';
11
11
  export const NavigationHeader = () => {
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
- import { ContentCopy as ContentCopyIcon, ExpandMore as ExpandMoreIcon, PowerSettingsNew as PowerSettingsIcon, WalletOutlined as WalletOutlinedIcon, } from '@mui/icons-material';
11
+ import { ContentCopy as ContentCopyIcon, ExpandMore as ExpandMoreIcon, PowerSettingsNewRounded as PowerSettingsIcon, WalletOutlined as WalletOutlinedIcon } from '@mui/icons-material';
12
12
  import { Avatar, MenuItem } from '@mui/material';
13
13
  import { useState } from 'react';
14
14
  import { useTranslation } from 'react-i18next';
@@ -6,7 +6,7 @@ export const IconButton = styled(MuiIconButton)(({ theme }) => ({
6
6
  borderColor: theme.palette.mode === 'light'
7
7
  ? theme.palette.grey[300]
8
8
  : theme.palette.grey[800],
9
- zIndex: 1200,
9
+ zIndex: 1100,
10
10
  padding: theme.spacing(0.5),
11
11
  '&:hover': {
12
12
  backgroundColor: theme.palette.mode === 'light'
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import type { Status } from '@lifi/sdk';
3
- export declare function CircularProgress({ status }: {
4
- status: Status;
2
+ import type { Process } from '@lifi/sdk';
3
+ export declare function CircularProgress({ process }: {
4
+ process: Process;
5
5
  }): JSX.Element;
@@ -1,19 +1,20 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Done as DoneIcon, Info as InfoIcon, Warning as WarningIcon } from '@mui/icons-material';
3
- import { Box } from '@mui/material';
4
- import { CircularProgress as CircularProgressStyled, CircularProgressPending } from './CircularProgress.style';
5
- export function CircularProgress({ status }) {
6
- return (_jsxs(Box, Object.assign({ sx: {
7
- display: 'grid',
8
- position: 'relative',
9
- placeItems: 'center',
10
- } }, { children: [_jsx(CircularProgressStyled, { variant: "determinate", status: status, size: 32, thickness: 3, value: 100 }), status === 'STARTED' || status === 'PENDING' ? (_jsx(CircularProgressPending, { size: 32, thickness: 3 })) : null, status === 'ACTION_REQUIRED' ? (_jsx(InfoIcon, { color: "info", sx: {
2
+ import { Done as DoneIcon, ErrorRounded as ErrorIcon, InfoRounded as InfoIcon, WarningRounded as WarningIcon } from '@mui/icons-material';
3
+ import { darken } from '@mui/material/styles';
4
+ import { CircularIcon, CircularProgressPending } from './CircularProgress.style';
5
+ export function CircularProgress({ process }) {
6
+ return (_jsxs(CircularIcon, Object.assign({ status: process.status, substatus: process.substatus }, { children: [process.status === 'STARTED' || process.status === 'PENDING' ? (_jsx(CircularProgressPending, { size: 32, thickness: 3 })) : null, process.status === 'ACTION_REQUIRED' ? (_jsx(InfoIcon, { color: "info", sx: {
11
7
  position: 'absolute',
12
8
  fontSize: '1rem',
13
- } })) : null, status === 'DONE' ? (_jsx(DoneIcon, { color: "success", sx: {
9
+ } })) : null, process.status === 'DONE' &&
10
+ (process.substatus === 'PARTIAL' || process.substatus === 'REFUNDED') ? (_jsx(WarningIcon, { sx: (theme) => ({
14
11
  position: 'absolute',
15
12
  fontSize: '1rem',
16
- } })) : null, status === 'FAILED' ? (_jsx(WarningIcon, { color: "error", sx: {
13
+ color: darken(theme.palette.warning.main, 0.32),
14
+ }) })) : process.status === 'DONE' ? (_jsx(DoneIcon, { color: "success", sx: {
15
+ position: 'absolute',
16
+ fontSize: '1rem',
17
+ } })) : null, process.status === 'FAILED' ? (_jsx(ErrorIcon, { color: "error", sx: {
17
18
  position: 'absolute',
18
19
  fontSize: '1rem',
19
20
  } })) : null] })));
@@ -1,6 +1,15 @@
1
- import type { Status } from '@lifi/sdk';
2
- import type { Theme } from '@mui/material';
3
- export declare const CircularProgress: import("@emotion/styled").StyledComponent<import("@mui/material").CircularProgressProps & import("@mui/system").MUIStyledCommonProps<Theme> & {
1
+ /// <reference types="react" />
2
+ import type { Status, Substatus } from '@lifi/sdk';
3
+ import { Theme } from '@mui/material';
4
+ export declare const CircularIcon: import("@emotion/styled").StyledComponent<import("@mui/system").SystemProps<Theme> & {
5
+ children?: import("react").ReactNode;
6
+ component?: import("react").ElementType<any> | undefined;
7
+ ref?: import("react").Ref<unknown> | undefined;
8
+ sx?: import("@mui/material").SxProps<Theme> | undefined;
9
+ } & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import("react").HTMLAttributes<HTMLDivElement>> & {
10
+ ref?: import("react").RefObject<HTMLDivElement> | ((instance: HTMLDivElement | null) => void) | null | undefined;
11
+ }, keyof import("@mui/material/OverridableComponent").CommonProps | "children" | "sx" | "ref" | ("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") | "component"> & import("@mui/system").MUIStyledCommonProps<Theme> & {
4
12
  status: Status;
13
+ substatus?: Substatus | undefined;
5
14
  }, {}, {}>;
6
15
  export declare const CircularProgressPending: import("@emotion/styled").StyledComponent<import("@mui/material").CircularProgressProps & import("@mui/system").MUIStyledCommonProps<Theme>, {}, {}>;
@@ -1,6 +1,6 @@
1
- import { CircularProgress as MuiCircularProgress } from '@mui/material';
1
+ import { Box, CircularProgress as MuiCircularProgress } from '@mui/material';
2
2
  import { circularProgressClasses } from '@mui/material/CircularProgress';
3
- import { keyframes, styled } from '@mui/material/styles';
3
+ import { alpha, keyframes, styled } from '@mui/material/styles';
4
4
  const circleAnimation = keyframes({
5
5
  '0%': {
6
6
  strokeDashoffset: 129,
@@ -15,22 +15,38 @@ const circleAnimation = keyframes({
15
15
  transform: 'rotate(360deg)',
16
16
  },
17
17
  });
18
- const getStatusColor = (status, theme) => {
18
+ const getStatusColor = (theme, status, substatus) => {
19
19
  switch (status) {
20
20
  case 'ACTION_REQUIRED':
21
- return theme.palette.info.main;
21
+ return alpha(theme.palette.info.main, 0.12);
22
22
  case 'DONE':
23
- return theme.palette.success.main;
23
+ if (substatus === 'PARTIAL' || substatus === 'REFUNDED') {
24
+ return alpha(theme.palette.warning.main, 0.48);
25
+ }
26
+ return alpha(theme.palette.success.main, 0.12);
24
27
  case 'FAILED':
25
- return theme.palette.error.main;
28
+ return alpha(theme.palette.error.main, 0.12);
26
29
  default:
27
30
  return theme.palette.grey[theme.palette.mode === 'light' ? 300 : 800];
28
31
  }
29
32
  };
30
- export const CircularProgress = styled(MuiCircularProgress, {
31
- shouldForwardProp: (prop) => prop !== 'status',
32
- })(({ theme, status }) => ({
33
- color: getStatusColor(status, theme),
33
+ export const CircularIcon = styled(Box, {
34
+ shouldForwardProp: (prop) => !['status', 'substatus'].includes(prop),
35
+ })(({ theme, status, substatus }) => ({
36
+ backgroundColor: ['ACTION_REQUIRED', 'DONE', 'FAILED'].includes(status)
37
+ ? getStatusColor(theme, status, substatus)
38
+ : theme.palette.background.paper,
39
+ borderStyle: 'solid',
40
+ borderColor: getStatusColor(theme, status, substatus),
41
+ borderWidth: !['ACTION_REQUIRED', 'DONE', 'FAILED'].includes(status)
42
+ ? 2
43
+ : 0,
44
+ display: 'grid',
45
+ position: 'relative',
46
+ placeItems: 'center',
47
+ width: 32,
48
+ height: 32,
49
+ borderRadius: '50%',
34
50
  }));
35
51
  export const CircularProgressPending = styled(MuiCircularProgress)(({ theme }) => ({
36
52
  color: theme.palette.mode === 'light'
@@ -38,7 +54,7 @@ export const CircularProgressPending = styled(MuiCircularProgress)(({ theme }) =
38
54
  : theme.palette.primary.light,
39
55
  animationDuration: '3s',
40
56
  position: 'absolute',
41
- left: 0,
57
+ left: '-2px',
42
58
  [`.${circularProgressClasses.circle}`]: {
43
59
  animationDuration: '2s',
44
60
  animationTimingFunction: 'linear',
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import type { Step } from '@lifi/sdk';
3
+ export declare const DestinationWalletAddress: React.FC<{
4
+ step: Step;
5
+ toAddress: string;
6
+ toAddressLink: string;
7
+ }>;
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { LinkRounded as LinkIcon, WalletOutlined as WalletOutlinedIcon } from '@mui/icons-material';
3
+ import { Box, Link, Typography } from '@mui/material';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { CircularIcon } from './CircularProgress.style';
6
+ import { LinkButton } from './StepProcess.style';
7
+ export const DestinationWalletAddress = ({ step, toAddress, toAddressLink }) => {
8
+ var _a;
9
+ const { t } = useTranslation();
10
+ const isDone = ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'DONE';
11
+ return (_jsx(Box, Object.assign({ px: 2, py: 1 }, { children: _jsxs(Box, Object.assign({ sx: {
12
+ display: 'flex',
13
+ alignItems: 'center',
14
+ } }, { children: [_jsx(CircularIcon, Object.assign({ status: isDone ? 'DONE' : 'NOT_STARTED' }, { children: _jsx(WalletOutlinedIcon, { color: isDone ? 'success' : 'inherit', sx: {
15
+ position: 'absolute',
16
+ fontSize: '1rem',
17
+ } }) })), _jsx(Typography, Object.assign({ ml: 2, fontSize: 14, fontWeight: 400 }, { children: isDone
18
+ ? t('swap.sentToAddress', {
19
+ address: toAddress,
20
+ })
21
+ : t('swap.sendToAddress', {
22
+ address: toAddress,
23
+ }) })), _jsx(Box, Object.assign({ ml: 2, sx: {
24
+ display: 'flex',
25
+ flex: 1,
26
+ justifyContent: 'flex-end',
27
+ } }, { children: _jsx(LinkButton, Object.assign({ size: "small", edge: "end", LinkComponent: Link, href: toAddressLink, target: "_blank", rel: "nofollow noreferrer" }, { children: _jsx(LinkIcon, {}) })) }))] })) })));
28
+ };
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ import type { Step } from '@lifi/sdk';
3
+ export declare const GasStepProcess: React.FC<{
4
+ step: Step;
5
+ }>;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { EvStationOutlined as EvStationIcon } from '@mui/icons-material';
3
+ import { Box, Typography } from '@mui/material';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { CircularIcon } from './CircularProgress.style';
6
+ export const GasStepProcess = ({ step }) => {
7
+ var _a, _b, _c, _d;
8
+ const { t } = useTranslation();
9
+ const isDone = ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'DONE';
10
+ return (_jsx(Box, Object.assign({ px: 2, py: 1 }, { children: _jsxs(Box, Object.assign({ sx: {
11
+ display: 'flex',
12
+ alignItems: 'center',
13
+ } }, { children: [_jsx(CircularIcon, Object.assign({ status: isDone ? 'DONE' : 'NOT_STARTED' }, { children: _jsx(EvStationIcon, { color: isDone ? 'success' : 'inherit', sx: {
14
+ position: 'absolute',
15
+ fontSize: '1rem',
16
+ } }) })), _jsxs(Typography, Object.assign({ ml: 2, fontSize: 14, fontWeight: 400 }, { children: [t('format.currency', {
17
+ value: (_d = (((_b = step.execution) === null || _b === void 0 ? void 0 : _b.gasAmountUSD) ||
18
+ ((_c = step.estimate.gasCosts) === null || _c === void 0 ? void 0 : _c.reduce((amount, gasCost) => amount + parseFloat(gasCost.amountUSD || '0'), 0)))) !== null && _d !== void 0 ? _d : 0,
19
+ }), ' ', isDone ? t('swap.gasFeePaid') : t('swap.gasFeeEstimated')] }))] })) })));
20
+ };
@@ -4,4 +4,5 @@ export declare const Step: React.FC<{
4
4
  step: StepType;
5
5
  fromToken?: TokenAmount;
6
6
  toToken?: TokenAmount;
7
+ toAddress?: string;
7
8
  }>;
@@ -4,19 +4,27 @@ import { useTranslation } from 'react-i18next';
4
4
  import { Card, CardTitle } from '../../components/Card';
5
5
  import { StepActions } from '../../components/StepActions';
6
6
  import { Token } from '../../components/Token';
7
+ import { useChains } from '../../hooks';
8
+ import { shortenWalletAddress } from '../../utils';
9
+ import { DestinationWalletAddress } from './DestinationWalletAddress';
10
+ import { GasStepProcess } from './GasStepProcess';
7
11
  import { StepProcess } from './StepProcess';
8
12
  import { StepTimer } from './StepTimer';
9
- export const Step = ({ step, fromToken, toToken }) => {
10
- var _a, _b;
13
+ export const Step = ({ step, fromToken, toToken, toAddress }) => {
14
+ var _a, _b, _c;
11
15
  const { t } = useTranslation();
16
+ const { getChainById } = useChains();
12
17
  const stepHasError = (_a = step.execution) === null || _a === void 0 ? void 0 : _a.process.some((process) => process.status === 'FAILED');
13
18
  const getCardTitle = () => {
14
19
  switch (step.type) {
15
20
  case 'lifi':
16
- if (step.includedSteps.some((step) => step.type === 'cross')) {
17
- return t('swap.stepSwapAndBridge');
21
+ if (step.includedSteps.every((step) => step.type === 'cross')) {
22
+ return t('swap.stepBridge');
18
23
  }
19
- return t('swap.stepSwap');
24
+ if (step.includedSteps.every((step) => step.type === 'swap')) {
25
+ return t('swap.stepSwap');
26
+ }
27
+ return t('swap.stepSwapAndBridge');
20
28
  case 'swap':
21
29
  return t('swap.stepSwap');
22
30
  case 'cross':
@@ -25,8 +33,12 @@ export const Step = ({ step, fromToken, toToken }) => {
25
33
  return t('swap.stepSwap');
26
34
  }
27
35
  };
36
+ const formattedToAddress = shortenWalletAddress(toAddress);
37
+ const toAddressLink = toAddress
38
+ ? `${(_b = getChainById(step.action.toChainId)) === null || _b === void 0 ? void 0 : _b.metamask.blockExplorerUrls[0]}address/${toAddress}`
39
+ : undefined;
28
40
  return (_jsxs(Card, Object.assign({ variant: stepHasError ? 'error' : 'default' }, { children: [_jsxs(Box, Object.assign({ sx: {
29
41
  display: 'flex',
30
42
  flex: 1,
31
- } }, { children: [_jsx(CardTitle, Object.assign({ flex: 1 }, { children: getCardTitle() })), _jsx(CardTitle, Object.assign({ sx: { fontWeight: 500 } }, { children: _jsx(StepTimer, { step: step }) }))] })), _jsxs(Box, Object.assign({ py: 1 }, { children: [fromToken ? _jsx(Token, { token: fromToken, px: 2, py: 1 }) : null, _jsx(StepActions, { step: step, px: 2, py: 1, dense: true }), (_b = step.execution) === null || _b === void 0 ? void 0 : _b.process.map((process, index) => (_jsx(StepProcess, { step: step, process: process }, index))), toToken ? _jsx(Token, { token: toToken, px: 2, py: 1 }) : null] }))] })));
43
+ } }, { children: [_jsx(CardTitle, Object.assign({ flex: 1 }, { children: getCardTitle() })), _jsx(CardTitle, Object.assign({ sx: { fontWeight: 500 } }, { children: _jsx(StepTimer, { step: step }) }))] })), _jsxs(Box, Object.assign({ py: 1 }, { children: [fromToken ? _jsx(Token, { token: fromToken, px: 2, py: 1 }) : null, _jsx(StepActions, { step: step, px: 2, py: 1, dense: true }), (_c = step.execution) === null || _c === void 0 ? void 0 : _c.process.map((process, index) => (_jsx(StepProcess, { step: step, process: process }, index))), _jsx(GasStepProcess, { step: step }), formattedToAddress && toAddressLink ? (_jsx(DestinationWalletAddress, { step: step, toAddress: formattedToAddress, toAddressLink: toAddressLink })) : null, toToken ? _jsx(Token, { token: toToken, px: 2, py: 1 }) : null] }))] })));
32
44
  };
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ import { Route } from '@lifi/sdk';
3
+ export declare const getStepList: (route?: Route) => JSX.Element[] | undefined;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment } from 'react';
3
+ import { StepDivider } from '../../components/StepDivider';
4
+ import { Step } from './Step';
5
+ export const getStepList = (route) => route === null || route === void 0 ? void 0 : route.steps.map((step, index, steps) => {
6
+ var _a, _b, _c, _d, _e;
7
+ const lastIndex = steps.length - 1;
8
+ const fromToken = index === 0
9
+ ? Object.assign(Object.assign({}, step.action.fromToken), { amount: step.action.fromAmount }) : undefined;
10
+ const toToken = index === lastIndex
11
+ ? Object.assign(Object.assign({}, ((_b = (_a = step.execution) === null || _a === void 0 ? void 0 : _a.toToken) !== null && _b !== void 0 ? _b : (_c = step.action) === null || _c === void 0 ? void 0 : _c.toToken)), { amount: (_e = (_d = step.execution) === null || _d === void 0 ? void 0 : _d.toAmount) !== null && _e !== void 0 ? _e : step.estimate.toAmount }) : undefined;
12
+ const toAddress = index === lastIndex && route.fromAddress !== route.toAddress
13
+ ? route.toAddress
14
+ : undefined;
15
+ return (_jsxs(Fragment, { children: [_jsx(Step, { step: step, fromToken: fromToken, toToken: toToken, toAddress: toAddress }), steps.length > 1 && index !== steps.length - 1 ? (_jsx(StepDivider, {})) : null] }, step.id));
16
+ });
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Link as LinkIcon } from '@mui/icons-material';
2
+ import { LinkRounded as LinkIcon } from '@mui/icons-material';
3
3
  import { Box, Link, Typography } from '@mui/material';
4
4
  import { useProcessMessage } from '../../hooks';
5
5
  import { CircularProgress } from './CircularProgress';
@@ -9,7 +9,7 @@ export const StepProcess = ({ step, process }) => {
9
9
  return (_jsxs(Box, Object.assign({ px: 2, py: 1 }, { children: [_jsxs(Box, Object.assign({ sx: {
10
10
  display: 'flex',
11
11
  alignItems: 'center',
12
- } }, { children: [_jsx(CircularProgress, { status: process.status }), _jsx(Typography, Object.assign({ ml: 2, fontSize: 14, fontWeight: process.error ? 600 : 400 }, { children: title })), process.txLink ? (_jsx(Box, Object.assign({ ml: 2, sx: {
12
+ } }, { children: [_jsx(CircularProgress, { process: process }), _jsx(Typography, Object.assign({ ml: 2, fontSize: 14, fontWeight: process.error ? 600 : 400 }, { children: title })), process.txLink ? (_jsx(Box, Object.assign({ ml: 2, sx: {
13
13
  display: 'flex',
14
14
  flex: 1,
15
15
  justifyContent: 'flex-end',
@@ -1 +1,2 @@
1
1
  export * from './Step';
2
+ export * from './StepList';
@@ -1 +1,2 @@
1
1
  export * from './Step';
2
+ export * from './StepList';
@@ -48,5 +48,5 @@ export const SwapButton = forwardRef(({ onClick, currentRoute, text, disable, en
48
48
  }
49
49
  return t(`button.connectWallet`);
50
50
  };
51
- return (_jsx(LoadingButton, Object.assign({ variant: "contained", color: account.isActive ? 'primary' : 'success', onClick: handleSwapButtonClick, disabled: insufficientFunds || !!(insufficientGas === null || insufficientGas === void 0 ? void 0 : insufficientGas.length) || disable, loading: enableLoading && (loading || isGasSufficiencyLoading), loadingPosition: "center", fullWidth: true, ref: ref }, { children: getButtonText() })));
51
+ return (_jsx(LoadingButton, Object.assign({ variant: "contained", color: "primary", onClick: handleSwapButtonClick, disabled: insufficientFunds || !!(insufficientGas === null || insufficientGas === void 0 ? void 0 : insufficientGas.length) || disable, loading: enableLoading && (loading || isGasSufficiencyLoading), loadingPosition: "center", fullWidth: true, ref: ref }, { children: getButtonText() })));
52
52
  });
@@ -10,5 +10,5 @@ export const SwapRouteNotFoundCard = () => {
10
10
  justifyContent: 'center',
11
11
  flexDirection: 'column',
12
12
  flex: 1,
13
- }, 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') }))] })));
13
+ }, py: 1.625 }, { 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') }))] })));
14
14
  };
package/config/sentry.js CHANGED
@@ -27,7 +27,7 @@ export const initSentry = (enabled) => __awaiter(void 0, void 0, void 0, functio
27
27
  levels: ['error'],
28
28
  }),
29
29
  ],
30
- sampleRate: 1,
30
+ sampleRate: 0.25,
31
31
  tracesSampleRate: 0.2,
32
32
  enabled,
33
33
  environment: process.env.NODE_ENV,
@@ -1,2 +1,2 @@
1
1
  export declare const name = "@lifi/widget";
2
- export declare const version = "1.25.1";
2
+ export declare const version = "1.26.0";
package/config/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export const name = '@lifi/widget';
2
- export const version = '1.25.1';
2
+ export const version = '1.26.0';
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { useQuery } from '@tanstack/react-query';
11
11
  import { useCallback } from 'react';
12
12
  import { useFormContext } from 'react-hook-form';
13
- import { isItemAllowed, SwapFormKey, useLiFi, useWidgetConfig, } from '../providers';
13
+ import { isItemAllowed, SwapFormKey, useLiFi, useWidgetConfig } from '../providers';
14
14
  import { useChainOrderStore } from '../stores';
15
15
  export const useChains = () => {
16
16
  const { disabledChains, chains } = useWidgetConfig();
@@ -33,7 +33,10 @@ export const useChains = () => {
33
33
  setValue(SwapFormKey.ToChain, chainOrder[0]);
34
34
  }
35
35
  return { availableChains, filteredChains };
36
- }));
36
+ }), {
37
+ refetchInterval: 180000,
38
+ staleTime: 180000,
39
+ });
37
40
  const getChainById = useCallback((chainId) => {
38
41
  const chain = data === null || data === void 0 ? void 0 : data.availableChains.find((chain) => chain.id === chainId);
39
42
  // if (!chain) {
@@ -10,7 +10,7 @@ export const useProcessMessage = (step, process) => {
10
10
  }
11
11
  return getProcessMessage(t, getChainById, step, process);
12
12
  };
13
- const processMessages = {
13
+ const processStatusMessages = {
14
14
  TOKEN_ALLOWANCE: {
15
15
  STARTED: (t) => t(`swap.process.tokenAllowance.started`),
16
16
  PENDING: (t) => t(`swap.process.tokenAllowance.pending`),
@@ -38,8 +38,34 @@ const processMessages = {
38
38
  },
39
39
  TRANSACTION: {},
40
40
  };
41
+ const processSubstatusMessages = {
42
+ PENDING: {
43
+ // BRIDGE_NOT_AVAILABLE: 'Bridge communication is temporarily unavailable.',
44
+ // CHAIN_NOT_AVAILABLE: 'RPC communication is temporarily unavailable.',
45
+ // REFUND_IN_PROGRESS:
46
+ // "The refund has been requested and it's being processed",
47
+ // WAIT_DESTINATION_TRANSACTION:
48
+ // 'The bridge off-chain logic is being executed. Wait for the transaction to appear on the destination chain.',
49
+ // WAIT_SOURCE_CONFIRMATIONS:
50
+ // 'The bridge deposit has been received. The bridge is waiting for more confirmations to start the off-chain logic.',
51
+ },
52
+ DONE: {
53
+ // COMPLETED: 'The transfer is complete.',
54
+ PARTIAL: (t) => t(`swap.process.receivingChain.partial`),
55
+ REFUNDED: (t) => t(`swap.process.receivingChain.partial`),
56
+ },
57
+ FAILED: {
58
+ // TODO: should be moved to failed status
59
+ // NOT_PROCESSABLE_REFUND_NEEDED:
60
+ // 'The transfer cannot be completed successfully. A refund operation is required.',
61
+ // UNKNOWN_ERROR:
62
+ // 'An unexpected error occurred. Please seek assistance in the LI.FI discord server.',
63
+ },
64
+ INVALID: {},
65
+ NOT_FOUND: {},
66
+ };
41
67
  export function getProcessMessage(t, getChainById, step, process) {
42
- var _a, _b, _c, _d;
68
+ var _a, _b, _c, _d, _e, _f, _g;
43
69
  if (process.error && process.status === 'FAILED') {
44
70
  const getTransactionNotSentMessage = () => {
45
71
  var _a, _b;
@@ -52,10 +78,18 @@ export function getProcessMessage(t, getChainById, step, process) {
52
78
  let title = '';
53
79
  let message = '';
54
80
  switch (process.error.code) {
81
+ case LifiErrorCode.BalanceError:
82
+ title = t(`swap.error.title.balanceIsTooLow`);
83
+ message = getTransactionNotSentMessage();
84
+ break;
55
85
  case LifiErrorCode.ChainSwitchError:
56
86
  title = t(`swap.error.title.chainSwitch`);
57
87
  message = getTransactionNotSentMessage();
58
88
  break;
89
+ case LifiErrorCode.GasLimitError:
90
+ title = t(`swap.error.title.gasLimitIsTooLow`);
91
+ message = getTransactionNotSentMessage();
92
+ break;
59
93
  case LifiErrorCode.TransactionFailed:
60
94
  title = t(`swap.error.title.transactionFailed`);
61
95
  message = t(`swap.error.message.transactionFailed`);
@@ -68,9 +102,13 @@ export function getProcessMessage(t, getChainById, step, process) {
68
102
  title = t(`swap.error.title.transactionUnprepared`);
69
103
  message = getTransactionNotSentMessage();
70
104
  break;
105
+ case LifiErrorCode.TransactionCanceled:
106
+ title = t(`swap.error.title.transactionCanceled`);
107
+ message = getTransactionNotSentMessage();
108
+ break;
71
109
  case LifiErrorCode.SlippageError:
72
- title = t(`swap.error.title.slippageTooLarge`);
73
- message = t(`swap.error.message.slippageTooLarge`);
110
+ title = t(`swap.error.title.slippageNotMet`);
111
+ message = t(`swap.error.message.slippageThreshold`);
74
112
  break;
75
113
  case LifiErrorCode.TransactionRejected:
76
114
  title = t(`swap.error.title.transactionRejected`);
@@ -80,15 +118,19 @@ export function getProcessMessage(t, getChainById, step, process) {
80
118
  chainName: (_b = (_a = getChainById(step.action.fromChainId)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '',
81
119
  });
82
120
  break;
121
+ case LifiErrorCode.ProviderUnavailable:
83
122
  default:
84
123
  title = t(`swap.error.title.unknown`);
85
124
  if (process.txLink) {
86
125
  message = t(`swap.error.message.transactionFailed`);
87
126
  }
127
+ else {
128
+ message = t(`swap.error.message.unknown`);
129
+ }
88
130
  break;
89
131
  }
90
132
  return { title, message };
91
133
  }
92
- const title = (_d = (_c = processMessages[process.type]) === null || _c === void 0 ? void 0 : _c[process.status]) === null || _d === void 0 ? void 0 : _d.call(_c, t);
134
+ const title = (_e = (_d = (_c = processSubstatusMessages[process.status]) === null || _c === void 0 ? void 0 : _c[process.substatus]) === null || _d === void 0 ? void 0 : _d.call(_c, t)) !== null && _e !== void 0 ? _e : (_g = (_f = processStatusMessages[process.type]) === null || _f === void 0 ? void 0 : _f[process.status]) === null || _g === void 0 ? void 0 : _g.call(_f, t);
93
135
  return { title };
94
136
  }
@@ -1,8 +1,14 @@
1
- import type { Route } from '@lifi/sdk';
2
- export declare const useRouteExecution: (routeId: string, executeInBackground?: boolean) => {
1
+ import type { ExchangeRateUpdateParams, Route } from '@lifi/sdk';
2
+ interface RouteExecutionProps {
3
+ routeId: string;
4
+ executeInBackground?: boolean;
5
+ onAcceptExchangeRateUpdate?(resolver: (value: boolean) => void, data: ExchangeRateUpdateParams): void;
6
+ }
7
+ export declare const useRouteExecution: ({ routeId, executeInBackground, onAcceptExchangeRateUpdate, }: RouteExecutionProps) => {
3
8
  executeRoute: () => void;
4
9
  restartRoute: () => void;
5
10
  deleteRoute: () => void;
6
11
  route: Route | undefined;
7
12
  status: import("../stores").RouteExecutionStatus | undefined;
8
13
  };
14
+ export {};
@@ -11,11 +11,11 @@ import { useMutation } from '@tanstack/react-query';
11
11
  import { useCallback, useEffect, useRef } from 'react';
12
12
  import shallow from 'zustand/shallow';
13
13
  import { useLiFi, useWallet } from '../providers';
14
- import { getUpdatedProcess, isRouteActive, isRouteDone, isRouteFailed, useRouteExecutionStore, } from '../stores';
14
+ import { getUpdatedProcess, isRouteActive, isRouteDone, isRouteFailed, useRouteExecutionStore } from '../stores';
15
15
  import { WidgetEvent } from '../types/events';
16
16
  import { deepClone } from '../utils';
17
17
  import { useWidgetEvents } from './useWidgetEvents';
18
- export const useRouteExecution = (routeId, executeInBackground) => {
18
+ export const useRouteExecution = ({ routeId, executeInBackground, onAcceptExchangeRateUpdate, }) => {
19
19
  const lifi = useLiFi();
20
20
  const { account, switchChain } = useWallet();
21
21
  const resumedAfterMount = useRef(false);
@@ -60,6 +60,13 @@ export const useRouteExecution = (routeId, executeInBackground) => {
60
60
  }
61
61
  return account.signer;
62
62
  });
63
+ const acceptExchangeRateUpdateHook = (params) => __awaiter(void 0, void 0, void 0, function* () {
64
+ if (!onAcceptExchangeRateUpdate) {
65
+ return false;
66
+ }
67
+ const accepted = yield new Promise((resolve) => onAcceptExchangeRateUpdate(resolve, params));
68
+ return accepted;
69
+ });
63
70
  const executeRouteMutation = useMutation(() => {
64
71
  if (!account.signer) {
65
72
  throw Error('Account signer not found.');
@@ -70,6 +77,7 @@ export const useRouteExecution = (routeId, executeInBackground) => {
70
77
  return lifi.executeRoute(account.signer, routeExecution.route, {
71
78
  updateCallback,
72
79
  switchChainHook,
80
+ acceptExchangeRateUpdateHook,
73
81
  infiniteApproval: false,
74
82
  executeInBackground,
75
83
  });
@@ -91,6 +99,7 @@ export const useRouteExecution = (routeId, executeInBackground) => {
91
99
  return lifi.resumeRoute(account.signer, resumedRoute !== null && resumedRoute !== void 0 ? resumedRoute : routeExecution.route, {
92
100
  updateCallback,
93
101
  switchChainHook,
102
+ acceptExchangeRateUpdateHook,
94
103
  infiniteApproval: false,
95
104
  executeInBackground,
96
105
  });
@@ -101,8 +110,8 @@ export const useRouteExecution = (routeId, executeInBackground) => {
101
110
  });
102
111
  const executeRoute = useCallback(() => {
103
112
  executeRouteMutation.mutateAsync(undefined, {
104
- onError: () => {
105
- console.warn('Execution failed!', routeId);
113
+ onError: (error) => {
114
+ console.warn('Execution failed!', routeId, error);
106
115
  // Notification.showNotification(NotificationType.SwapExecution_ERROR);
107
116
  },
108
117
  onSuccess: (route) => {
@@ -113,8 +122,8 @@ export const useRouteExecution = (routeId, executeInBackground) => {
113
122
  }, [executeRouteMutation, routeId]);
114
123
  const resumeRoute = useCallback((route) => {
115
124
  resumeRouteMutation.mutateAsync(route, {
116
- onError: () => {
117
- console.warn('Resumed execution failed.', routeId);
125
+ onError: (error) => {
126
+ console.warn('Resumed execution failed.', routeId, error);
118
127
  },
119
128
  onSuccess: (route) => {
120
129
  console.log('Resumed execution successful.', route);