@lifi/widget 3.0.1 → 3.1.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.
- package/CHANGELOG.md +18 -2
- package/README.md +24 -5
- package/_esm/components/Card/CardIconButton.js +1 -0
- package/_esm/components/Card/CardIconButton.js.map +1 -1
- package/_esm/components/Card/CardLabel.d.ts +1 -1
- package/_esm/components/Card/CardLabel.js +8 -12
- package/_esm/components/Card/CardLabel.js.map +1 -1
- package/_esm/components/ChainSelect/ChainSelect.js +1 -1
- package/_esm/components/ChainSelect/ChainSelect.js.map +1 -1
- package/_esm/components/FeeBreakdownTooltip.d.ts +12 -0
- package/_esm/components/FeeBreakdownTooltip.js +13 -0
- package/_esm/components/FeeBreakdownTooltip.js.map +1 -0
- package/_esm/components/Header/CloseDrawerButton.js +1 -1
- package/_esm/components/Header/CloseDrawerButton.js.map +1 -1
- package/_esm/components/Header/SettingsButton.js +1 -1
- package/_esm/components/Header/SettingsButton.js.map +1 -1
- package/_esm/components/Header/TransactionHistoryButton.js +1 -1
- package/_esm/components/Header/TransactionHistoryButton.js.map +1 -1
- package/_esm/components/IconTypography.d.ts +3 -0
- package/_esm/components/IconTypography.js +8 -0
- package/_esm/components/IconTypography.js.map +1 -0
- package/_esm/components/PoweredBy/PoweredBy.js +1 -1
- package/_esm/components/PoweredBy/PoweredBy.js.map +1 -1
- package/_esm/components/ProgressToNextUpdate.js +1 -1
- package/_esm/components/ProgressToNextUpdate.js.map +1 -1
- package/_esm/components/RouteCard/RouteCard.js +7 -16
- package/_esm/components/RouteCard/RouteCard.js.map +1 -1
- package/_esm/components/RouteCard/RouteCard.style.d.ts +0 -3
- package/_esm/components/RouteCard/RouteCard.style.js +1 -7
- package/_esm/components/RouteCard/RouteCard.style.js.map +1 -1
- package/_esm/components/RouteCard/RouteCardEssentials.js +13 -14
- package/_esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
- package/_esm/components/RouteCard/RouteCardEssentialsExpanded.js +4 -20
- package/_esm/components/RouteCard/RouteCardEssentialsExpanded.js.map +1 -1
- package/_esm/components/RouteCard/types.d.ts +1 -6
- package/_esm/components/Routes/RoutesExpanded.js +2 -4
- package/_esm/components/Routes/RoutesExpanded.js.map +1 -1
- package/_esm/components/SendToWallet/SendToWalletExpandButton.js +1 -1
- package/_esm/components/SendToWallet/SendToWalletExpandButton.js.map +1 -1
- package/_esm/components/Step/Step.d.ts +1 -0
- package/_esm/components/Step/Step.js +2 -2
- package/_esm/components/Step/Step.js.map +1 -1
- package/_esm/components/Step/StepList.js +16 -7
- package/_esm/components/Step/StepList.js.map +1 -1
- package/_esm/components/Step/StepTimer.js +3 -3
- package/_esm/components/Step/StepTimer.js.map +1 -1
- package/_esm/components/StepActions/StepActions.js +5 -4
- package/_esm/components/StepActions/StepActions.js.map +1 -1
- package/_esm/components/Token/Token.d.ts +2 -0
- package/_esm/components/Token/Token.js +22 -8
- package/_esm/components/Token/Token.js.map +1 -1
- package/_esm/components/Token/Token.style.js +1 -0
- package/_esm/components/Token/Token.style.js.map +1 -1
- package/_esm/components/TokenRate.d.ts +7 -0
- package/_esm/components/TokenRate.js +41 -0
- package/_esm/components/TokenRate.js.map +1 -0
- package/_esm/components/TransactionDetails.d.ts +7 -0
- package/_esm/components/TransactionDetails.js +46 -0
- package/_esm/components/TransactionDetails.js.map +1 -0
- package/_esm/config/version.d.ts +1 -1
- package/_esm/config/version.js +1 -1
- package/_esm/hooks/timer/useInterval.d.ts +1 -0
- package/_esm/hooks/timer/useInterval.js +18 -0
- package/_esm/hooks/timer/useInterval.js.map +1 -0
- package/_esm/hooks/timer/useTimer.d.ts +18 -0
- package/_esm/hooks/timer/useTimer.js +61 -0
- package/_esm/hooks/timer/useTimer.js.map +1 -0
- package/_esm/hooks/timer/utils.d.ts +11 -0
- package/_esm/hooks/timer/utils.js +46 -0
- package/_esm/hooks/timer/utils.js.map +1 -0
- package/_esm/hooks/useAccount.js +4 -5
- package/_esm/hooks/useAccount.js.map +1 -1
- package/_esm/hooks/useAvailableChains.js +1 -0
- package/_esm/hooks/useAvailableChains.js.map +1 -1
- package/_esm/hooks/useGasRecommendation.js +1 -0
- package/_esm/hooks/useGasRecommendation.js.map +1 -1
- package/_esm/hooks/useRoutes.d.ts +4 -2
- package/_esm/hooks/useRoutes.js +17 -10
- package/_esm/hooks/useRoutes.js.map +1 -1
- package/_esm/hooks/useTokens.js +1 -0
- package/_esm/hooks/useTokens.js.map +1 -1
- package/_esm/hooks/useTools.js +1 -0
- package/_esm/hooks/useTools.js.map +1 -1
- package/_esm/hooks/useTransactionDetails.d.ts +1 -1
- package/_esm/hooks/useTransactionDetails.js +1 -1
- package/_esm/hooks/useTransactionDetails.js.map +1 -1
- package/_esm/hooks/useTransactionHistory.js.map +1 -1
- package/_esm/i18n/en.json +14 -20
- package/_esm/i18n/index.js +15 -15
- package/_esm/i18n/index.js.map +1 -1
- package/_esm/index.d.ts +2 -1
- package/_esm/index.js +1 -4
- package/_esm/index.js.map +1 -1
- package/_esm/pages/MainPage/ReviewButton.js +2 -4
- package/_esm/pages/MainPage/ReviewButton.js.map +1 -1
- package/_esm/pages/RoutesPage/RoutesPage.js +2 -4
- package/_esm/pages/RoutesPage/RoutesPage.js.map +1 -1
- package/_esm/pages/SelectEnabledToolsPage.js +1 -1
- package/_esm/pages/SelectEnabledToolsPage.js.map +1 -1
- package/_esm/pages/SendToWallet/SendToWalletPage.js +1 -1
- package/_esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
- package/_esm/pages/SettingsPage/ThemeSettings.js +1 -1
- package/_esm/pages/SettingsPage/ThemeSettings.js.map +1 -1
- package/_esm/pages/TransactionDetailsPage/TransactionDetailsPage.js +5 -7
- package/_esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
- package/_esm/pages/TransactionHistoryPage/TransactionHistoryItem.js +2 -2
- package/_esm/pages/TransactionHistoryPage/TransactionHistoryItem.js.map +1 -1
- package/_esm/pages/TransactionPage/ExchangeRateBottomSheet.js +2 -2
- package/_esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
- package/_esm/pages/TransactionPage/RouteTracker.d.ts +7 -0
- package/_esm/pages/TransactionPage/RouteTracker.js +39 -0
- package/_esm/pages/TransactionPage/RouteTracker.js.map +1 -0
- package/_esm/pages/TransactionPage/StartTransactionButton.d.ts +0 -1
- package/_esm/pages/TransactionPage/StartTransactionButton.js +0 -9
- package/_esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
- package/_esm/pages/TransactionPage/TransactionPage.js +10 -21
- package/_esm/pages/TransactionPage/TransactionPage.js.map +1 -1
- package/_esm/pages/TransactionPage/types.d.ts +0 -1
- package/_esm/providers/I18nProvider/I18nProvider.js +2 -0
- package/_esm/providers/I18nProvider/I18nProvider.js.map +1 -1
- package/_esm/providers/I18nProvider/currencyExtendedFormatter.d.ts +1 -0
- package/_esm/providers/I18nProvider/currencyExtendedFormatter.js +13 -0
- package/_esm/providers/I18nProvider/currencyExtendedFormatter.js.map +1 -0
- package/_esm/providers/WalletProvider/EVMBaseProvider.js +18 -12
- package/_esm/providers/WalletProvider/EVMBaseProvider.js.map +1 -1
- package/_esm/stores/routes/createRouteExecutionStore.js +2 -2
- package/_esm/stores/routes/createRouteExecutionStore.js.map +1 -1
- package/_esm/stores/routes/types.d.ts +1 -1
- package/_esm/stores/routes/useSetExecutableRoute.d.ts +1 -1
- package/_esm/themes/createTheme.js +6 -0
- package/_esm/themes/createTheme.js.map +1 -1
- package/_esm/types/widget.d.ts +1 -2
- package/_esm/utils/converters.js +5 -13
- package/_esm/utils/converters.js.map +1 -1
- package/_esm/utils/fees.d.ts +3 -3
- package/_esm/utils/fees.js +18 -13
- package/_esm/utils/fees.js.map +1 -1
- package/_esm/utils/format.d.ts +13 -4
- package/_esm/utils/format.js +51 -13
- package/_esm/utils/format.js.map +1 -1
- package/components/Card/CardIconButton.tsx +1 -0
- package/components/Card/CardLabel.tsx +13 -29
- package/components/ChainSelect/ChainSelect.tsx +1 -9
- package/components/FeeBreakdownTooltip.tsx +66 -0
- package/components/Header/CloseDrawerButton.tsx +1 -1
- package/components/Header/SettingsButton.tsx +1 -1
- package/components/Header/TransactionHistoryButton.tsx +1 -1
- package/components/IconTypography.ts +9 -0
- package/components/PoweredBy/PoweredBy.tsx +1 -1
- package/components/ProgressToNextUpdate.tsx +0 -3
- package/components/RouteCard/RouteCard.style.ts +1 -9
- package/components/RouteCard/RouteCard.tsx +15 -71
- package/components/RouteCard/RouteCardEssentials.tsx +52 -81
- package/components/RouteCard/RouteCardEssentialsExpanded.tsx +17 -107
- package/components/RouteCard/types.ts +1 -7
- package/components/Routes/RoutesExpanded.tsx +3 -4
- package/components/SendToWallet/SendToWalletExpandButton.tsx +1 -6
- package/components/Step/Step.tsx +11 -2
- package/components/Step/StepList.tsx +19 -10
- package/components/Step/StepTimer.tsx +9 -6
- package/components/StepActions/StepActions.tsx +11 -14
- package/components/Token/Token.style.tsx +1 -0
- package/components/Token/Token.tsx +49 -9
- package/components/TokenRate.tsx +79 -0
- package/components/TransactionDetails.tsx +182 -0
- package/config/version.ts +1 -1
- package/hooks/timer/useInterval.ts +21 -0
- package/hooks/timer/useTimer.ts +91 -0
- package/hooks/timer/utils.ts +54 -0
- package/hooks/useAccount.ts +8 -5
- package/hooks/useAvailableChains.ts +2 -1
- package/hooks/useGasRecommendation.ts +1 -0
- package/hooks/useRoutes.ts +23 -13
- package/hooks/useTokens.ts +1 -0
- package/hooks/useTools.ts +2 -1
- package/hooks/useTransactionDetails.ts +3 -3
- package/hooks/useTransactionHistory.ts +1 -1
- package/i18n/en.json +14 -20
- package/i18n/index.ts +15 -15
- package/index.ts +2 -5
- package/package.json +15 -16
- package/pages/MainPage/ReviewButton.tsx +2 -4
- package/pages/RoutesPage/RoutesPage.tsx +3 -4
- package/pages/SelectEnabledToolsPage.tsx +1 -1
- package/pages/SendToWallet/SendToWalletPage.tsx +1 -1
- package/pages/SettingsPage/ThemeSettings.tsx +1 -1
- package/pages/TransactionDetailsPage/TransactionDetailsPage.tsx +9 -20
- package/pages/TransactionHistoryPage/TransactionHistoryItem.tsx +3 -5
- package/pages/TransactionPage/ExchangeRateBottomSheet.tsx +0 -2
- package/pages/TransactionPage/RouteTracker.tsx +68 -0
- package/pages/TransactionPage/StartTransactionButton.tsx +0 -24
- package/pages/TransactionPage/TransactionPage.tsx +21 -48
- package/pages/TransactionPage/types.ts +0 -1
- package/providers/I18nProvider/I18nProvider.tsx +6 -0
- package/providers/I18nProvider/currencyExtendedFormatter.ts +15 -0
- package/providers/WalletProvider/EVMBaseProvider.tsx +13 -7
- package/stores/routes/createRouteExecutionStore.ts +2 -2
- package/stores/routes/types.ts +1 -1
- package/themes/createTheme.ts +6 -0
- package/types/widget.ts +1 -2
- package/utils/converters.ts +5 -13
- package/utils/fees.ts +23 -24
- package/utils/format.ts +67 -20
- package/_esm/components/Insurance/Insurance.d.ts +0 -2
- package/_esm/components/Insurance/Insurance.js +0 -8
- package/_esm/components/Insurance/Insurance.js.map +0 -1
- package/_esm/components/Insurance/InsuranceCard.d.ts +0 -2
- package/_esm/components/Insurance/InsuranceCard.js +0 -36
- package/_esm/components/Insurance/InsuranceCard.js.map +0 -1
- package/_esm/components/Insurance/InsuranceCollapsed.d.ts +0 -2
- package/_esm/components/Insurance/InsuranceCollapsed.js +0 -29
- package/_esm/components/Insurance/InsuranceCollapsed.js.map +0 -1
- package/_esm/components/Insurance/types.d.ts +0 -19
- package/_esm/components/Insurance/types.js +0 -2
- package/_esm/components/Insurance/types.js.map +0 -1
- package/_esm/components/StepActions/StepFeeBreakdown.d.ts +0 -4
- package/_esm/components/StepActions/StepFeeBreakdown.js +0 -42
- package/_esm/components/StepActions/StepFeeBreakdown.js.map +0 -1
- package/_esm/icons/InsuraceLogo.d.ts +0 -2
- package/_esm/icons/InsuraceLogo.js +0 -8
- package/_esm/icons/InsuraceLogo.js.map +0 -1
- package/components/Insurance/Insurance.tsx +0 -22
- package/components/Insurance/InsuranceCard.tsx +0 -119
- package/components/Insurance/InsuranceCollapsed.tsx +0 -59
- package/components/Insurance/types.ts +0 -24
- package/components/StepActions/StepFeeBreakdown.tsx +0 -108
- package/icons/InsuraceLogo.tsx +0 -46
|
@@ -12,19 +12,27 @@ export const getStepList = (
|
|
|
12
12
|
const lastIndex = steps.length - 1;
|
|
13
13
|
const fromToken: TokenAmount | undefined =
|
|
14
14
|
index === 0
|
|
15
|
-
? { ...step.action.fromToken, amount: BigInt(step.action.fromAmount) }
|
|
16
|
-
: undefined;
|
|
17
|
-
const toToken: TokenAmount | undefined =
|
|
18
|
-
index === lastIndex
|
|
19
15
|
? {
|
|
20
|
-
...
|
|
21
|
-
amount: step.
|
|
22
|
-
? BigInt(step.execution.toAmount)
|
|
23
|
-
: subvariant === 'custom'
|
|
24
|
-
? BigInt(route.toAmount)
|
|
25
|
-
: BigInt(step.estimate.toAmount),
|
|
16
|
+
...step.action.fromToken,
|
|
17
|
+
amount: BigInt(step.action.fromAmount),
|
|
26
18
|
}
|
|
27
19
|
: undefined;
|
|
20
|
+
let toToken: TokenAmount | undefined;
|
|
21
|
+
let impactToken: TokenAmount | undefined;
|
|
22
|
+
if (index === lastIndex) {
|
|
23
|
+
toToken = {
|
|
24
|
+
...(step.execution?.toToken ?? step.action.toToken),
|
|
25
|
+
amount: step.execution?.toAmount
|
|
26
|
+
? BigInt(step.execution.toAmount)
|
|
27
|
+
: subvariant === 'custom'
|
|
28
|
+
? BigInt(route.toAmount)
|
|
29
|
+
: BigInt(step.estimate.toAmount),
|
|
30
|
+
};
|
|
31
|
+
impactToken = {
|
|
32
|
+
...steps[0].action.fromToken,
|
|
33
|
+
amount: BigInt(steps[0].action.fromAmount),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
28
36
|
const toAddress =
|
|
29
37
|
index === lastIndex && route.fromAddress !== route.toAddress
|
|
30
38
|
? route.toAddress
|
|
@@ -35,6 +43,7 @@ export const getStepList = (
|
|
|
35
43
|
step={step}
|
|
36
44
|
fromToken={fromToken}
|
|
37
45
|
toToken={toToken}
|
|
46
|
+
impactToken={impactToken}
|
|
38
47
|
toAddress={toAddress}
|
|
39
48
|
/>
|
|
40
49
|
{steps.length > 1 && index !== steps.length - 1 ? (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LiFiStepExtended } from '@lifi/sdk';
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
|
-
import { useTimer } from '
|
|
4
|
+
import { useTimer } from '../../hooks/timer/useTimer.js';
|
|
5
5
|
|
|
6
6
|
const getExpiryTimestamp = (step: LiFiStepExtended) =>
|
|
7
7
|
new Date(
|
|
@@ -52,11 +52,14 @@ export const StepTimer: React.FC<{
|
|
|
52
52
|
]);
|
|
53
53
|
|
|
54
54
|
if (!isExecutionStarted) {
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
return Math.ceil(step.estimate.executionDuration / 60).toLocaleString(
|
|
56
|
+
i18n.language,
|
|
57
|
+
{
|
|
58
|
+
style: 'unit',
|
|
59
|
+
unit: 'minute',
|
|
60
|
+
unitDisplay: 'narrow',
|
|
61
|
+
},
|
|
62
|
+
);
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
const isTimerExpired = isExpired || (!minutes && !seconds);
|
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
StepLabel,
|
|
27
27
|
StepLabelTypography,
|
|
28
28
|
} from './StepActions.style.js';
|
|
29
|
-
import { StepFeeBreakdown } from './StepFeeBreakdown.js';
|
|
30
29
|
import { StepFees } from './StepFees.js';
|
|
31
30
|
import type {
|
|
32
31
|
IncludedStepsProps,
|
|
@@ -74,22 +73,21 @@ export const StepActions: React.FC<StepActionsProps> = ({
|
|
|
74
73
|
</Badge>
|
|
75
74
|
<Box flex={1}>
|
|
76
75
|
<Typography fontSize={18} fontWeight={600} lineHeight={1.3334} ml={2}>
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
{toolDetails.name?.includes('LI.FI')
|
|
77
|
+
? toolDetails.name
|
|
78
|
+
: t(`main.stepDetails`, {
|
|
79
|
+
tool: toolDetails.name,
|
|
80
|
+
})}
|
|
80
81
|
</Typography>
|
|
81
|
-
<
|
|
82
|
-
timeout={225}
|
|
83
|
-
in={dense && !cardExpanded}
|
|
84
|
-
mountOnEnter
|
|
85
|
-
unmountOnExit
|
|
86
|
-
>
|
|
87
|
-
<StepFees ml={2} step={step} />
|
|
88
|
-
</Collapse>
|
|
82
|
+
<StepFees ml={2} step={step} />
|
|
89
83
|
</Box>
|
|
90
84
|
{dense ? (
|
|
91
85
|
<CardIconButton onClick={handleExpand} size="small">
|
|
92
|
-
{cardExpanded ?
|
|
86
|
+
{cardExpanded ? (
|
|
87
|
+
<ExpandLess fontSize="inherit" />
|
|
88
|
+
) : (
|
|
89
|
+
<ExpandMore fontSize="inherit" />
|
|
90
|
+
)}
|
|
93
91
|
</CardIconButton>
|
|
94
92
|
) : null}
|
|
95
93
|
</Box>
|
|
@@ -100,7 +98,6 @@ export const StepActions: React.FC<StepActionsProps> = ({
|
|
|
100
98
|
subvariant={subvariant}
|
|
101
99
|
subvariantOptions={subvariantOptions}
|
|
102
100
|
/>
|
|
103
|
-
<StepFeeBreakdown step={step} />
|
|
104
101
|
</Collapse>
|
|
105
102
|
) : (
|
|
106
103
|
<IncludedSteps
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/* eslint-disable react/no-array-index-key */
|
|
2
2
|
import type { LiFiStep, TokenAmount } from '@lifi/sdk';
|
|
3
3
|
import type { BoxProps } from '@mui/material';
|
|
4
|
-
import { Box, Grow, Skeleton } from '@mui/material';
|
|
4
|
+
import { Box, Grow, Skeleton, Tooltip } from '@mui/material';
|
|
5
5
|
import type { FC, PropsWithChildren, ReactElement } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { useChain } from '../../hooks/useChain.js';
|
|
8
8
|
import { useToken } from '../../hooks/useToken.js';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
convertToSubscriptFormat,
|
|
11
|
+
formatTokenAmount,
|
|
12
|
+
formatTokenPrice,
|
|
13
|
+
} from '../../utils/format.js';
|
|
10
14
|
import { AvatarBadgedSkeleton } from '../Avatar/Avatar.js';
|
|
11
15
|
import { TokenAvatar } from '../Avatar/TokenAvatar.js';
|
|
12
16
|
import { SmallAvatar } from '../SmallAvatar.js';
|
|
@@ -15,6 +19,8 @@ import { TextSecondary, TextSecondaryContainer } from './Token.style.js';
|
|
|
15
19
|
|
|
16
20
|
interface TokenProps {
|
|
17
21
|
token: TokenAmount;
|
|
22
|
+
impactToken?: TokenAmount;
|
|
23
|
+
enableImpactTokenTooltip?: boolean;
|
|
18
24
|
step?: LiFiStep;
|
|
19
25
|
stepVisible?: boolean;
|
|
20
26
|
disableDescription?: boolean;
|
|
@@ -49,6 +55,8 @@ export const TokenFallback: FC<TokenProps & BoxProps> = ({
|
|
|
49
55
|
|
|
50
56
|
export const TokenBase: FC<TokenProps & BoxProps> = ({
|
|
51
57
|
token,
|
|
58
|
+
impactToken,
|
|
59
|
+
enableImpactTokenTooltip,
|
|
52
60
|
step,
|
|
53
61
|
stepVisible,
|
|
54
62
|
disableDescription,
|
|
@@ -69,11 +77,29 @@ export const TokenBase: FC<TokenProps & BoxProps> = ({
|
|
|
69
77
|
);
|
|
70
78
|
}
|
|
71
79
|
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
80
|
+
const tokenAmount = formatTokenAmount(token.amount, token.decimals);
|
|
81
|
+
const tokenPrice = formatTokenPrice(tokenAmount, token.priceUSD);
|
|
82
|
+
|
|
83
|
+
let priceImpact;
|
|
84
|
+
if (impactToken) {
|
|
85
|
+
const impactTokenAmount = formatTokenAmount(
|
|
86
|
+
impactToken.amount,
|
|
87
|
+
impactToken.decimals,
|
|
88
|
+
);
|
|
89
|
+
const impactTokenPrice =
|
|
90
|
+
formatTokenPrice(impactTokenAmount, impactToken.priceUSD) || 0.01;
|
|
91
|
+
|
|
92
|
+
const impact = (tokenPrice / impactTokenPrice - 1) * 100;
|
|
93
|
+
|
|
94
|
+
priceImpact = convertToSubscriptFormat(impact, {
|
|
95
|
+
notation: 'standard',
|
|
96
|
+
roundingPriority: 'morePrecision',
|
|
97
|
+
maximumSignificantDigits: 2,
|
|
98
|
+
maximumFractionDigits: 2,
|
|
99
|
+
useGrouping: false,
|
|
100
|
+
roundingMode: 'trunc',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
77
103
|
|
|
78
104
|
const tokenOnChain = !disableDescription ? (
|
|
79
105
|
<TextSecondary>
|
|
@@ -101,16 +127,30 @@ export const TokenBase: FC<TokenProps & BoxProps> = ({
|
|
|
101
127
|
}}
|
|
102
128
|
>
|
|
103
129
|
{t('format.number', {
|
|
104
|
-
value:
|
|
130
|
+
value: tokenAmount,
|
|
105
131
|
})}
|
|
106
132
|
</TextFitter>
|
|
107
133
|
</Box>
|
|
108
134
|
<TextSecondaryContainer component="span">
|
|
109
135
|
<TextSecondary>
|
|
110
136
|
{t(`format.currency`, {
|
|
111
|
-
value:
|
|
137
|
+
value: tokenPrice,
|
|
112
138
|
})}
|
|
113
139
|
</TextSecondary>
|
|
140
|
+
{impactToken ? (
|
|
141
|
+
<TextSecondary px={0.5} dot>
|
|
142
|
+
•
|
|
143
|
+
</TextSecondary>
|
|
144
|
+
) : null}
|
|
145
|
+
{impactToken ? (
|
|
146
|
+
enableImpactTokenTooltip ? (
|
|
147
|
+
<Tooltip title={t('tooltip.priceImpact')} sx={{ cursor: 'help' }}>
|
|
148
|
+
<TextSecondary>{priceImpact}%</TextSecondary>
|
|
149
|
+
</Tooltip>
|
|
150
|
+
) : (
|
|
151
|
+
<TextSecondary>{priceImpact}%</TextSecondary>
|
|
152
|
+
)
|
|
153
|
+
) : null}
|
|
114
154
|
{!disableDescription ? (
|
|
115
155
|
<TextSecondary px={0.5} dot>
|
|
116
156
|
•
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { RouteExtended } from '@lifi/sdk';
|
|
2
|
+
import type { TypographyProps } from '@mui/material';
|
|
3
|
+
import { Typography } from '@mui/material';
|
|
4
|
+
import type { MouseEventHandler } from 'react';
|
|
5
|
+
import { formatUnits } from 'viem';
|
|
6
|
+
import { create } from 'zustand';
|
|
7
|
+
import {
|
|
8
|
+
convertToSubscriptFormat,
|
|
9
|
+
precisionFormatter,
|
|
10
|
+
} from '../utils/format.js';
|
|
11
|
+
|
|
12
|
+
interface TokenRateProps extends TypographyProps {
|
|
13
|
+
route: RouteExtended;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface TokenRateState {
|
|
17
|
+
isForward: boolean;
|
|
18
|
+
toggleIsForward(): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const useTokenRateStore = create<TokenRateState>((set) => ({
|
|
22
|
+
isForward: true,
|
|
23
|
+
toggleIsForward: () => set((state) => ({ isForward: !state.isForward })),
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
export const TokenRate: React.FC<TokenRateProps> = ({ route, ...props }) => {
|
|
27
|
+
const { isForward, toggleIsForward } = useTokenRateStore();
|
|
28
|
+
|
|
29
|
+
const toggleRate: MouseEventHandler<HTMLSpanElement> = (e) => {
|
|
30
|
+
e.stopPropagation();
|
|
31
|
+
toggleIsForward();
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const lastStep = route.steps.at(-1);
|
|
35
|
+
|
|
36
|
+
const fromToken = {
|
|
37
|
+
...route.fromToken,
|
|
38
|
+
amount: BigInt(route.fromAmount),
|
|
39
|
+
};
|
|
40
|
+
const toToken = {
|
|
41
|
+
...(lastStep?.execution?.toToken ??
|
|
42
|
+
lastStep?.action.toToken ??
|
|
43
|
+
route.toToken),
|
|
44
|
+
amount: lastStep?.execution?.toAmount
|
|
45
|
+
? BigInt(lastStep.execution.toAmount)
|
|
46
|
+
: BigInt(route.toAmount),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const fromToRate =
|
|
50
|
+
parseFloat(formatUnits(toToken.amount!, toToken.decimals)) /
|
|
51
|
+
parseFloat(formatUnits(fromToken.amount!, fromToken.decimals));
|
|
52
|
+
const toFromRate =
|
|
53
|
+
parseFloat(formatUnits(fromToken.amount!, fromToken.decimals)) /
|
|
54
|
+
parseFloat(formatUnits(toToken.amount!, toToken.decimals));
|
|
55
|
+
|
|
56
|
+
const rateText = isForward
|
|
57
|
+
? `1 ${fromToken.symbol} ≈ ${convertToSubscriptFormat(fromToRate)} ${toToken.symbol}`
|
|
58
|
+
: `1 ${toToken.symbol} ≈ ${convertToSubscriptFormat(toFromRate)} ${fromToken.symbol}`;
|
|
59
|
+
|
|
60
|
+
const rateTitle = isForward
|
|
61
|
+
? `1 ${fromToken.symbol} ≈ ${precisionFormatter.format(fromToRate)} ${toToken.symbol}`
|
|
62
|
+
: `1 ${toToken.symbol} ≈ ${precisionFormatter.format(toFromRate)} ${fromToken.symbol}`;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Typography
|
|
66
|
+
fontSize={14}
|
|
67
|
+
lineHeight={1.429}
|
|
68
|
+
color="text.secondary"
|
|
69
|
+
fontWeight="500"
|
|
70
|
+
onClick={toggleRate}
|
|
71
|
+
role="button"
|
|
72
|
+
sx={{ cursor: 'pointer' }}
|
|
73
|
+
title={rateTitle}
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
{rateText}
|
|
77
|
+
</Typography>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import type { RouteExtended } from '@lifi/sdk';
|
|
2
|
+
import {
|
|
3
|
+
ExpandLess,
|
|
4
|
+
ExpandMore,
|
|
5
|
+
LocalGasStationRounded,
|
|
6
|
+
} from '@mui/icons-material';
|
|
7
|
+
import type { CardProps } from '@mui/material';
|
|
8
|
+
import { Box, Collapse, Tooltip, Typography } from '@mui/material';
|
|
9
|
+
import { useState } from 'react';
|
|
10
|
+
import { useTranslation } from 'react-i18next';
|
|
11
|
+
import { isRouteDone } from '../stores/routes/utils.js';
|
|
12
|
+
import { getFeeCostsBreakdown, getGasCostsBreakdown } from '../utils/fees.js';
|
|
13
|
+
import {
|
|
14
|
+
convertToSubscriptFormat,
|
|
15
|
+
formatTokenAmount,
|
|
16
|
+
formatTokenPrice,
|
|
17
|
+
} from '../utils/format.js';
|
|
18
|
+
import { Card } from './Card/Card.js';
|
|
19
|
+
import { CardIconButton } from './Card/CardIconButton.js';
|
|
20
|
+
import { FeeBreakdownTooltip } from './FeeBreakdownTooltip.js';
|
|
21
|
+
import { IconTypography } from './IconTypography.js';
|
|
22
|
+
import { TokenRate } from './TokenRate.js';
|
|
23
|
+
|
|
24
|
+
interface TransactionDetailsProps extends CardProps {
|
|
25
|
+
route: RouteExtended;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const TransactionDetails: React.FC<TransactionDetailsProps> = ({
|
|
29
|
+
route,
|
|
30
|
+
...props
|
|
31
|
+
}) => {
|
|
32
|
+
const { t } = useTranslation();
|
|
33
|
+
const [cardExpanded, setCardExpanded] = useState(false);
|
|
34
|
+
|
|
35
|
+
const toggleCard = () => {
|
|
36
|
+
setCardExpanded((cardExpanded) => !cardExpanded);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const gasCosts = getGasCostsBreakdown(route);
|
|
40
|
+
const feeCosts = getFeeCostsBreakdown(route, false);
|
|
41
|
+
const gasCostUSD = gasCosts.reduce(
|
|
42
|
+
(sum, gasCost) => sum + gasCost.amountUSD,
|
|
43
|
+
0,
|
|
44
|
+
);
|
|
45
|
+
const feeCostUSD = feeCosts.reduce(
|
|
46
|
+
(sum, feeCost) => sum + feeCost.amountUSD,
|
|
47
|
+
0,
|
|
48
|
+
);
|
|
49
|
+
const fees = gasCostUSD + feeCostUSD;
|
|
50
|
+
|
|
51
|
+
const fromTokenAmount = formatTokenAmount(
|
|
52
|
+
BigInt(route.fromAmount),
|
|
53
|
+
route.fromToken.decimals,
|
|
54
|
+
);
|
|
55
|
+
const fromTokenPrice = formatTokenPrice(
|
|
56
|
+
fromTokenAmount,
|
|
57
|
+
route.fromToken.priceUSD,
|
|
58
|
+
);
|
|
59
|
+
const toTokenAmount = formatTokenAmount(
|
|
60
|
+
BigInt(route.toAmount),
|
|
61
|
+
route.toToken.decimals,
|
|
62
|
+
);
|
|
63
|
+
const toTokenPrice =
|
|
64
|
+
formatTokenPrice(toTokenAmount, route.toToken.priceUSD) || 0.01;
|
|
65
|
+
|
|
66
|
+
const impact = (toTokenPrice / fromTokenPrice - 1) * 100;
|
|
67
|
+
|
|
68
|
+
const priceImpact = convertToSubscriptFormat(impact, {
|
|
69
|
+
notation: 'standard',
|
|
70
|
+
roundingPriority: 'morePrecision',
|
|
71
|
+
maximumSignificantDigits: 2,
|
|
72
|
+
maximumFractionDigits: 2,
|
|
73
|
+
useGrouping: false,
|
|
74
|
+
roundingMode: 'trunc',
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Card selectionColor="secondary" {...props}>
|
|
79
|
+
<Box display="flex" alignItems="center" px={2} py={1.75}>
|
|
80
|
+
<Box display="flex" flex={1} alignItems="center" justifyContent="left">
|
|
81
|
+
<TokenRate route={route} />
|
|
82
|
+
</Box>
|
|
83
|
+
<FeeBreakdownTooltip
|
|
84
|
+
route={route}
|
|
85
|
+
gasCosts={gasCosts}
|
|
86
|
+
feeCosts={feeCosts}
|
|
87
|
+
>
|
|
88
|
+
<Box
|
|
89
|
+
display="flex"
|
|
90
|
+
alignItems="center"
|
|
91
|
+
onClick={toggleCard}
|
|
92
|
+
role="button"
|
|
93
|
+
sx={{ cursor: 'pointer' }}
|
|
94
|
+
px={1}
|
|
95
|
+
>
|
|
96
|
+
<IconTypography mr={0.5} fontSize={16}>
|
|
97
|
+
<LocalGasStationRounded fontSize="inherit" />
|
|
98
|
+
</IconTypography>
|
|
99
|
+
<Typography
|
|
100
|
+
fontSize={14}
|
|
101
|
+
color="text.primary"
|
|
102
|
+
fontWeight="600"
|
|
103
|
+
lineHeight={1.429}
|
|
104
|
+
>
|
|
105
|
+
{t(`format.currency`, { value: fees })}
|
|
106
|
+
</Typography>
|
|
107
|
+
</Box>
|
|
108
|
+
</FeeBreakdownTooltip>
|
|
109
|
+
<CardIconButton onClick={toggleCard} size="small">
|
|
110
|
+
{cardExpanded ? (
|
|
111
|
+
<ExpandLess fontSize="inherit" />
|
|
112
|
+
) : (
|
|
113
|
+
<ExpandMore fontSize="inherit" />
|
|
114
|
+
)}
|
|
115
|
+
</CardIconButton>
|
|
116
|
+
</Box>
|
|
117
|
+
<Collapse timeout={225} in={cardExpanded} mountOnEnter>
|
|
118
|
+
<Box px={2} pb={2}>
|
|
119
|
+
<Box display="flex" justifyContent="space-between" mb={0.5}>
|
|
120
|
+
<Typography variant="body2">{t('main.fees.network')}</Typography>
|
|
121
|
+
<FeeBreakdownTooltip route={route} feeCosts={[]}>
|
|
122
|
+
<Typography variant="body2">
|
|
123
|
+
{t(`format.currency`, {
|
|
124
|
+
value: gasCostUSD,
|
|
125
|
+
})}
|
|
126
|
+
</Typography>
|
|
127
|
+
</FeeBreakdownTooltip>
|
|
128
|
+
</Box>
|
|
129
|
+
{feeCosts.length ? (
|
|
130
|
+
<Box display="flex" justifyContent="space-between" mb={0.5}>
|
|
131
|
+
<Typography variant="body2">{t('main.fees.provider')}</Typography>
|
|
132
|
+
<FeeBreakdownTooltip
|
|
133
|
+
route={route}
|
|
134
|
+
gasCosts={[]}
|
|
135
|
+
feeCosts={feeCosts}
|
|
136
|
+
>
|
|
137
|
+
<Typography variant="body2">
|
|
138
|
+
{t(`format.currency`, {
|
|
139
|
+
value: feeCostUSD,
|
|
140
|
+
})}
|
|
141
|
+
</Typography>
|
|
142
|
+
</FeeBreakdownTooltip>
|
|
143
|
+
</Box>
|
|
144
|
+
) : null}
|
|
145
|
+
<Box display="flex" justifyContent="space-between" mb={0.5}>
|
|
146
|
+
<Typography variant="body2">{t('main.priceImpact')}</Typography>
|
|
147
|
+
<Tooltip title={t('tooltip.priceImpact')} sx={{ cursor: 'help' }}>
|
|
148
|
+
<Typography variant="body2">{priceImpact}%</Typography>
|
|
149
|
+
</Tooltip>
|
|
150
|
+
</Box>
|
|
151
|
+
{!isRouteDone(route) ? (
|
|
152
|
+
<>
|
|
153
|
+
<Box display="flex" justifyContent="space-between" mb={0.5}>
|
|
154
|
+
<Typography variant="body2">{t('main.maxSlippage')}</Typography>
|
|
155
|
+
<Typography variant="body2">
|
|
156
|
+
{route.steps[0].action.slippage * 100}%
|
|
157
|
+
</Typography>
|
|
158
|
+
</Box>
|
|
159
|
+
<Box display="flex" justifyContent="space-between">
|
|
160
|
+
<Typography variant="body2">{t('main.minReceived')}</Typography>
|
|
161
|
+
<Tooltip
|
|
162
|
+
title={t('tooltip.minReceived')}
|
|
163
|
+
sx={{ cursor: 'help' }}
|
|
164
|
+
>
|
|
165
|
+
<Typography variant="body2">
|
|
166
|
+
{t('format.number', {
|
|
167
|
+
value: formatTokenAmount(
|
|
168
|
+
BigInt(route.toAmountMin),
|
|
169
|
+
route.toToken.decimals,
|
|
170
|
+
),
|
|
171
|
+
})}{' '}
|
|
172
|
+
{route.toToken.symbol}
|
|
173
|
+
</Typography>
|
|
174
|
+
</Tooltip>
|
|
175
|
+
</Box>
|
|
176
|
+
</>
|
|
177
|
+
) : null}
|
|
178
|
+
</Box>
|
|
179
|
+
</Collapse>
|
|
180
|
+
</Card>
|
|
181
|
+
);
|
|
182
|
+
};
|
package/config/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = '@lifi/widget';
|
|
2
|
-
export const version = '3.0
|
|
2
|
+
export const version = '3.1.0';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useInterval(callback: Function, delay: number) {
|
|
4
|
+
const callbacRef = useRef<Function>();
|
|
5
|
+
|
|
6
|
+
// update callback function with current render callback that has access to latest props and state
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
callbacRef.current = callback;
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!delay) {
|
|
13
|
+
return () => {};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const interval = setInterval(() => {
|
|
17
|
+
callbacRef.current && callbacRef.current();
|
|
18
|
+
}, delay);
|
|
19
|
+
return () => clearInterval(interval);
|
|
20
|
+
}, [delay]);
|
|
21
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
import { useInterval } from './useInterval.js';
|
|
3
|
+
import {
|
|
4
|
+
getDelayFromExpiryTimestamp,
|
|
5
|
+
getSecondsFromExpiry,
|
|
6
|
+
getTimeFromSeconds,
|
|
7
|
+
validateOnExpire,
|
|
8
|
+
} from './utils.js';
|
|
9
|
+
|
|
10
|
+
const DEFAULT_DELAY = 1000;
|
|
11
|
+
|
|
12
|
+
interface UseTimerProps {
|
|
13
|
+
expiryTimestamp: Date;
|
|
14
|
+
onExpire: Function;
|
|
15
|
+
autoStart?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// This implementation was taken from the common js project - https://www.npmjs.com/package/react-timer-hook
|
|
19
|
+
// modified to work in the Widget codebase with Typescript
|
|
20
|
+
export function useTimer({
|
|
21
|
+
expiryTimestamp: expiry,
|
|
22
|
+
onExpire,
|
|
23
|
+
autoStart = true,
|
|
24
|
+
}: UseTimerProps) {
|
|
25
|
+
const [expiryTimestamp, setExpiryTimestamp] = useState(expiry);
|
|
26
|
+
const [seconds, setSeconds] = useState(getSecondsFromExpiry(expiryTimestamp));
|
|
27
|
+
const [isRunning, setIsRunning] = useState(autoStart);
|
|
28
|
+
const [didStart, setDidStart] = useState(autoStart);
|
|
29
|
+
const [delay, setDelay] = useState(
|
|
30
|
+
getDelayFromExpiryTimestamp(expiryTimestamp, DEFAULT_DELAY),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const handleExpire = useCallback(() => {
|
|
34
|
+
validateOnExpire(onExpire) && onExpire();
|
|
35
|
+
setIsRunning(false);
|
|
36
|
+
setDelay(0);
|
|
37
|
+
}, [onExpire]);
|
|
38
|
+
|
|
39
|
+
const pause = useCallback(() => {
|
|
40
|
+
setIsRunning(false);
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
const restart = useCallback(
|
|
44
|
+
(newExpiryTimestamp: Date, newAutoStart = true) => {
|
|
45
|
+
setDelay(getDelayFromExpiryTimestamp(newExpiryTimestamp, DEFAULT_DELAY));
|
|
46
|
+
setDidStart(newAutoStart);
|
|
47
|
+
setIsRunning(newAutoStart);
|
|
48
|
+
setExpiryTimestamp(newExpiryTimestamp);
|
|
49
|
+
setSeconds(getSecondsFromExpiry(newExpiryTimestamp));
|
|
50
|
+
},
|
|
51
|
+
[],
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const resume = useCallback(() => {
|
|
55
|
+
const time = new Date();
|
|
56
|
+
time.setMilliseconds(time.getMilliseconds() + seconds * 1000);
|
|
57
|
+
restart(time);
|
|
58
|
+
}, [seconds, restart]);
|
|
59
|
+
|
|
60
|
+
const start = useCallback(() => {
|
|
61
|
+
if (didStart) {
|
|
62
|
+
setSeconds(getSecondsFromExpiry(expiryTimestamp));
|
|
63
|
+
setIsRunning(true);
|
|
64
|
+
} else {
|
|
65
|
+
resume();
|
|
66
|
+
}
|
|
67
|
+
}, [expiryTimestamp, didStart, resume]);
|
|
68
|
+
|
|
69
|
+
useInterval(
|
|
70
|
+
() => {
|
|
71
|
+
if (delay !== DEFAULT_DELAY) {
|
|
72
|
+
setDelay(DEFAULT_DELAY);
|
|
73
|
+
}
|
|
74
|
+
const secondsValue = getSecondsFromExpiry(expiryTimestamp);
|
|
75
|
+
setSeconds(secondsValue);
|
|
76
|
+
if (secondsValue <= 0) {
|
|
77
|
+
handleExpire();
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
isRunning ? delay : 0,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
...getTimeFromSeconds(seconds),
|
|
85
|
+
start,
|
|
86
|
+
pause,
|
|
87
|
+
resume,
|
|
88
|
+
restart,
|
|
89
|
+
isRunning,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export function getTimeFromSeconds(secs: number) {
|
|
2
|
+
const totalSeconds = Math.ceil(secs);
|
|
3
|
+
const days = Math.floor(totalSeconds / (60 * 60 * 24));
|
|
4
|
+
const hours = Math.floor((totalSeconds % (60 * 60 * 24)) / (60 * 60));
|
|
5
|
+
const minutes = Math.floor((totalSeconds % (60 * 60)) / 60);
|
|
6
|
+
const seconds = Math.floor(totalSeconds % 60);
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
totalSeconds,
|
|
10
|
+
seconds,
|
|
11
|
+
minutes,
|
|
12
|
+
hours,
|
|
13
|
+
days,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getSecondsFromExpiry(expiry: Date, shouldRound?: boolean) {
|
|
18
|
+
const now = new Date().getTime();
|
|
19
|
+
const milliSecondsDistance = expiry.getTime() - now;
|
|
20
|
+
if (milliSecondsDistance > 0) {
|
|
21
|
+
const val = milliSecondsDistance / 1000;
|
|
22
|
+
return shouldRound ? Math.round(val) : val;
|
|
23
|
+
}
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function validateExpiryTimestamp(expiryTimestamp: Date) {
|
|
28
|
+
const isValid = new Date(expiryTimestamp).getTime() > 0;
|
|
29
|
+
if (!isValid) {
|
|
30
|
+
console.warn('useTimer Invalid expiryTimestamp settings', expiryTimestamp); // eslint-disable-line
|
|
31
|
+
}
|
|
32
|
+
return isValid;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function validateOnExpire(onExpire: Function) {
|
|
36
|
+
const isValid = onExpire && typeof onExpire === 'function';
|
|
37
|
+
if (onExpire && !isValid) {
|
|
38
|
+
console.warn('useTimer Invalid onExpire settings function', onExpire);
|
|
39
|
+
}
|
|
40
|
+
return isValid;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getDelayFromExpiryTimestamp(
|
|
44
|
+
expiryTimestamp: Date,
|
|
45
|
+
defaultDelay: number,
|
|
46
|
+
) {
|
|
47
|
+
if (!validateExpiryTimestamp(expiryTimestamp)) {
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const seconds = getSecondsFromExpiry(expiryTimestamp);
|
|
52
|
+
const extraMilliSeconds = Math.floor((seconds - Math.floor(seconds)) * 1000);
|
|
53
|
+
return extraMilliSeconds > 0 ? extraMilliSeconds : defaultDelay;
|
|
54
|
+
}
|