@lifi/widget 3.21.4-alpha.0 → 3.22.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 +20 -0
- package/dist/esm/AppProvider.js +2 -3
- package/dist/esm/AppProvider.js.map +1 -1
- package/dist/esm/components/AppContainer.js +23 -22
- package/dist/esm/components/AppContainer.js.map +1 -1
- package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js +12 -7
- package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
- package/dist/esm/components/BaseTransactionButton/types.d.ts +2 -0
- package/dist/esm/components/ChainSelect/ChainSelect.js +3 -1
- package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
- package/dist/esm/components/ChainSelect/ChainSelect.style.d.ts +3 -1
- package/dist/esm/components/ChainSelect/ChainSelect.style.js +23 -9
- package/dist/esm/components/ChainSelect/ChainSelect.style.js.map +1 -1
- package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.d.ts +8 -0
- package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.js +20 -0
- package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.js.map +1 -0
- package/dist/esm/components/Messages/WarningMessages.js +3 -0
- package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
- package/dist/esm/components/Messages/useMessageQueue.js +15 -4
- package/dist/esm/components/Messages/useMessageQueue.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCard.js +3 -3
- package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
- package/dist/esm/components/TokenList/TokenListItem.js +2 -2
- package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/config/version.js.map +1 -1
- package/dist/esm/hooks/useAvailableChains.js +3 -2
- package/dist/esm/hooks/useAvailableChains.js.map +1 -1
- package/dist/esm/hooks/useExplorer.d.ts +0 -1
- package/dist/esm/hooks/useExplorer.js +26 -31
- package/dist/esm/hooks/useExplorer.js.map +1 -1
- package/dist/esm/hooks/useFromTokenSufficiency.js +4 -1
- package/dist/esm/hooks/useFromTokenSufficiency.js.map +1 -1
- package/dist/esm/hooks/useGasRecommendation.js +9 -1
- package/dist/esm/hooks/useGasRecommendation.js.map +1 -1
- package/dist/esm/hooks/useGasSufficiency.js +50 -16
- package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
- package/dist/esm/hooks/useIsBatchingSupported.js +8 -1
- package/dist/esm/hooks/useIsBatchingSupported.js.map +1 -1
- package/dist/esm/hooks/useIsContractAddress.js +1 -1
- package/dist/esm/hooks/useIsContractAddress.js.map +1 -1
- package/dist/esm/hooks/useRouteExecution.js +10 -4
- package/dist/esm/hooks/useRouteExecution.js.map +1 -1
- package/dist/esm/hooks/useRouteRequiredAccountConnection.d.ts +10 -0
- package/dist/esm/hooks/useRouteRequiredAccountConnection.js +45 -0
- package/dist/esm/hooks/useRouteRequiredAccountConnection.js.map +1 -0
- package/dist/esm/hooks/useRoutes.d.ts +1 -1
- package/dist/esm/hooks/useRoutes.js +13 -4
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/hooks/useTokenBalance.js +12 -3
- package/dist/esm/hooks/useTokenBalance.js.map +1 -1
- package/dist/esm/hooks/useTokenBalances.js +4 -1
- package/dist/esm/hooks/useTokenBalances.js.map +1 -1
- package/dist/esm/hooks/useTokenSearch.js +5 -2
- package/dist/esm/hooks/useTokenSearch.js.map +1 -1
- package/dist/esm/hooks/useTokens.js +3 -2
- package/dist/esm/hooks/useTokens.js.map +1 -1
- package/dist/esm/hooks/useTools.js +3 -2
- package/dist/esm/hooks/useTools.js.map +1 -1
- package/dist/esm/hooks/useTransactionDetails.js +9 -4
- package/dist/esm/hooks/useTransactionDetails.js.map +1 -1
- package/dist/esm/hooks/useTransactionHistory.js +7 -1
- package/dist/esm/hooks/useTransactionHistory.js.map +1 -1
- package/dist/esm/i18n/en.json +6 -4
- package/dist/esm/pages/MainPage/ReviewButton.js +1 -1
- package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js +1 -1
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
- package/dist/esm/pages/TransactionPage/StatusBottomSheet.js +26 -43
- package/dist/esm/pages/TransactionPage/StatusBottomSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.d.ts +0 -1
- package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.js +4 -11
- package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.js.map +1 -1
- package/dist/esm/providers/QueryClientProvider.d.ts +2 -0
- package/dist/esm/providers/QueryClientProvider.js +9 -0
- package/dist/esm/providers/QueryClientProvider.js.map +1 -0
- package/dist/esm/providers/WalletProvider/SuiBaseProvider.js +3 -8
- package/dist/esm/providers/WalletProvider/SuiBaseProvider.js.map +1 -1
- package/dist/esm/stores/form/FormStore.js +5 -12
- package/dist/esm/stores/form/FormStore.js.map +1 -1
- package/dist/esm/stores/form/useFormRef.js +1 -7
- package/dist/esm/stores/form/useFormRef.js.map +1 -1
- package/dist/esm/types/widget.d.ts +6 -1
- package/dist/esm/utils/queries.d.ts +1 -0
- package/dist/esm/utils/queries.js +2 -0
- package/dist/esm/utils/queries.js.map +1 -0
- package/dist/esm/utils/timer.js +8 -1
- package/dist/esm/utils/timer.js.map +1 -1
- package/package.json +11 -11
- package/package.json.tmp +10 -10
- package/src/AppProvider.tsx +2 -3
- package/src/components/AppContainer.tsx +24 -23
- package/src/components/BaseTransactionButton/BaseTransactionButton.tsx +15 -6
- package/src/components/BaseTransactionButton/types.ts +3 -0
- package/src/components/ChainSelect/ChainSelect.style.tsx +25 -9
- package/src/components/ChainSelect/ChainSelect.tsx +4 -1
- package/src/components/Messages/MissingRouteRequiredAccountMessage.tsx +44 -0
- package/src/components/Messages/WarningMessages.tsx +9 -0
- package/src/components/Messages/useMessageQueue.ts +17 -4
- package/src/components/RouteCard/RouteCard.tsx +3 -3
- package/src/components/TokenList/TokenListItem.tsx +2 -2
- package/src/config/version.ts +1 -1
- package/src/hooks/useAvailableChains.ts +4 -2
- package/src/hooks/useExplorer.ts +35 -36
- package/src/hooks/useFromTokenSufficiency.ts +4 -1
- package/src/hooks/useGasRecommendation.ts +9 -1
- package/src/hooks/useGasSufficiency.ts +76 -22
- package/src/hooks/useIsBatchingSupported.ts +9 -1
- package/src/hooks/useIsContractAddress.ts +1 -1
- package/src/hooks/useRouteExecution.ts +10 -4
- package/src/hooks/useRouteRequiredAccountConnection.ts +58 -0
- package/src/hooks/useRoutes.ts +13 -7
- package/src/hooks/useTokenBalance.ts +12 -3
- package/src/hooks/useTokenBalances.ts +4 -1
- package/src/hooks/useTokenSearch.ts +5 -2
- package/src/hooks/useTokens.ts +3 -2
- package/src/hooks/useTools.ts +3 -2
- package/src/hooks/useTransactionDetails.ts +13 -4
- package/src/hooks/useTransactionHistory.ts +7 -1
- package/src/i18n/en.json +6 -4
- package/src/pages/MainPage/ReviewButton.tsx +1 -0
- package/src/pages/TransactionPage/StartTransactionButton.tsx +1 -0
- package/src/pages/TransactionPage/StatusBottomSheet.style.tsx +4 -12
- package/src/pages/TransactionPage/StatusBottomSheet.tsx +47 -77
- package/src/providers/QueryClientProvider.tsx +20 -0
- package/src/providers/WalletProvider/SuiBaseProvider.tsx +3 -9
- package/src/stores/form/FormStore.tsx +4 -15
- package/src/stores/form/useFormRef.ts +1 -8
- package/src/types/widget.ts +10 -2
- package/src/utils/queries.ts +2 -0
- package/src/utils/timer.ts +8 -1
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { Box, styled } from '@mui/material'
|
|
2
2
|
import { Card } from '../../components/Card/Card.js'
|
|
3
|
+
import { maxChainsToShow } from '../../stores/chains/createChainOrderStore.js'
|
|
4
|
+
|
|
5
|
+
const chainCardWidthPx = 52
|
|
6
|
+
const chainCardHeightPx = 56
|
|
7
|
+
|
|
8
|
+
// Chain grid layout settings:
|
|
9
|
+
// These should remain consistent with `maxChainsToShow` to ensure
|
|
10
|
+
// proper row/column distribution in the grid layout logic.
|
|
11
|
+
const maxRows = 2
|
|
12
|
+
const maxChainsPerRow = Math.ceil(maxChainsToShow / maxRows)
|
|
3
13
|
|
|
4
14
|
export const ChainCard = styled(Card)({
|
|
5
15
|
display: 'grid',
|
|
6
16
|
placeItems: 'center',
|
|
7
|
-
minWidth:
|
|
8
|
-
height:
|
|
17
|
+
minWidth: chainCardWidthPx,
|
|
18
|
+
height: chainCardHeightPx,
|
|
9
19
|
})
|
|
10
20
|
|
|
11
|
-
export const ChainContainer = styled(Box
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
export const ChainContainer = styled(Box, {
|
|
22
|
+
shouldForwardProp: (prop) => prop !== 'itemCount',
|
|
23
|
+
})<{ itemCount: number }>(({ theme, itemCount }) => {
|
|
24
|
+
const rowCount = Math.min(Math.ceil(itemCount / maxChainsPerRow), maxRows)
|
|
25
|
+
const columnsPerRow = Math.ceil(itemCount / rowCount)
|
|
26
|
+
return {
|
|
27
|
+
display: 'grid',
|
|
28
|
+
gridTemplateColumns: `repeat(${rowCount > 1 ? columnsPerRow : 'auto-fit'}, minmax(${chainCardWidthPx}px, 1fr))`,
|
|
29
|
+
gridTemplateRows: `repeat(${rowCount}, ${chainCardHeightPx}px)`,
|
|
30
|
+
justifyContent: 'space-between',
|
|
31
|
+
gap: theme.spacing(1.5),
|
|
32
|
+
}
|
|
33
|
+
})
|
|
@@ -50,8 +50,11 @@ export const ChainSelect = ({ formType }: FormTypeProps) => {
|
|
|
50
50
|
// When there is less than 10 chains we don't care about the order
|
|
51
51
|
const chainsToShow = chainsToHide > 0 ? getChains() : chains
|
|
52
52
|
|
|
53
|
+
// Number of tiles to show in the grid
|
|
54
|
+
const tilesCount = (chainsToShow?.length ?? 0) + (chainsToHide > 0 ? 1 : 0)
|
|
55
|
+
|
|
53
56
|
return (
|
|
54
|
-
<ChainContainer>
|
|
57
|
+
<ChainContainer itemCount={tilesCount}>
|
|
55
58
|
{isLoading
|
|
56
59
|
? Array.from({ length: maxChainsToOrder }).map((_, index) => (
|
|
57
60
|
<Skeleton
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ExtendedChain } from '@lifi/sdk'
|
|
2
|
+
import Wallet from '@mui/icons-material/Wallet'
|
|
3
|
+
import type { BoxProps } from '@mui/material'
|
|
4
|
+
import { Typography } from '@mui/material'
|
|
5
|
+
import { useTranslation } from 'react-i18next'
|
|
6
|
+
import { shortenAddress } from '../../utils/wallet.js'
|
|
7
|
+
import { AlertMessage } from './AlertMessage.js'
|
|
8
|
+
|
|
9
|
+
interface MissingRouteRequiredAccountMessageProps extends BoxProps {
|
|
10
|
+
chain?: ExtendedChain
|
|
11
|
+
address?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const MissingRouteRequiredAccountMessage: React.FC<
|
|
15
|
+
MissingRouteRequiredAccountMessageProps
|
|
16
|
+
> = ({ chain, address, ...props }) => {
|
|
17
|
+
const { t } = useTranslation()
|
|
18
|
+
|
|
19
|
+
if (!chain) {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<AlertMessage
|
|
25
|
+
title={
|
|
26
|
+
<Typography
|
|
27
|
+
variant="body2"
|
|
28
|
+
sx={{
|
|
29
|
+
px: 1,
|
|
30
|
+
color: 'text.primary',
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
{t('info.message.missingRouteRequiredAccount', {
|
|
34
|
+
chainName: chain.name,
|
|
35
|
+
address: address ? `(${shortenAddress(address)})` : '',
|
|
36
|
+
})}
|
|
37
|
+
</Typography>
|
|
38
|
+
}
|
|
39
|
+
icon={<Wallet />}
|
|
40
|
+
multiline
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -4,6 +4,7 @@ import { Collapse } from '@mui/material'
|
|
|
4
4
|
import { AccountNotDeployedMessage } from './AccountNotDeployedMessage.js'
|
|
5
5
|
import { FundsSufficiencyMessage } from './FundsSufficiencyMessage.js'
|
|
6
6
|
import { GasSufficiencyMessage } from './GasSufficiencyMessage.js'
|
|
7
|
+
import { MissingRouteRequiredAccountMessage } from './MissingRouteRequiredAccountMessage.js'
|
|
7
8
|
import { ToAddressRequiredMessage } from './ToAddressRequiredMessage.js'
|
|
8
9
|
import { useMessageQueue } from './useMessageQueue.js'
|
|
9
10
|
|
|
@@ -21,6 +22,14 @@ export const WarningMessages: React.FC<WarningMessagesProps> = ({
|
|
|
21
22
|
|
|
22
23
|
const getMessage = () => {
|
|
23
24
|
switch (messages[0]?.id) {
|
|
25
|
+
case 'MISSING_ROUTE_REQUIRED_ACCOUNT':
|
|
26
|
+
return (
|
|
27
|
+
<MissingRouteRequiredAccountMessage
|
|
28
|
+
chain={messages[0].props?.chain}
|
|
29
|
+
address={messages[0].props?.address}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
24
33
|
case 'INSUFFICIENT_FUNDS':
|
|
25
34
|
return <FundsSufficiencyMessage {...props} />
|
|
26
35
|
case 'INSUFFICIENT_GAS':
|
|
@@ -2,6 +2,7 @@ import type { Route } from '@lifi/sdk'
|
|
|
2
2
|
import { useMemo } from 'react'
|
|
3
3
|
import { useFromTokenSufficiency } from '../../hooks/useFromTokenSufficiency.js'
|
|
4
4
|
import { useGasSufficiency } from '../../hooks/useGasSufficiency.js'
|
|
5
|
+
import { useRouteRequiredAccountConnection } from '../../hooks/useRouteRequiredAccountConnection.js'
|
|
5
6
|
import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js'
|
|
6
7
|
|
|
7
8
|
interface QueuedMessage {
|
|
@@ -21,21 +22,31 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => {
|
|
|
21
22
|
useFromTokenSufficiency(route)
|
|
22
23
|
const { insufficientGas, isLoading: isGasSufficiencyLoading } =
|
|
23
24
|
useGasSufficiency(route)
|
|
25
|
+
const { missingChain, missingAccountAddress } =
|
|
26
|
+
useRouteRequiredAccountConnection(route)
|
|
24
27
|
|
|
25
28
|
const messageQueue = useMemo(() => {
|
|
26
29
|
const queue: QueuedMessage[] = []
|
|
27
30
|
|
|
31
|
+
if (missingChain) {
|
|
32
|
+
queue.push({
|
|
33
|
+
id: 'MISSING_ROUTE_REQUIRED_ACCOUNT',
|
|
34
|
+
priority: 1,
|
|
35
|
+
props: { chain: missingChain, address: missingAccountAddress },
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
28
39
|
if (insufficientFromToken) {
|
|
29
40
|
queue.push({
|
|
30
41
|
id: 'INSUFFICIENT_FUNDS',
|
|
31
|
-
priority:
|
|
42
|
+
priority: 2,
|
|
32
43
|
})
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
if (insufficientGas?.length) {
|
|
36
47
|
queue.push({
|
|
37
48
|
id: 'INSUFFICIENT_GAS',
|
|
38
|
-
priority:
|
|
49
|
+
priority: 3,
|
|
39
50
|
props: { insufficientGas },
|
|
40
51
|
})
|
|
41
52
|
}
|
|
@@ -43,14 +54,14 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => {
|
|
|
43
54
|
if (accountNotDeployedAtDestination && !allowInteraction) {
|
|
44
55
|
queue.push({
|
|
45
56
|
id: 'ACCOUNT_NOT_DEPLOYED',
|
|
46
|
-
priority:
|
|
57
|
+
priority: 4,
|
|
47
58
|
})
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
if (requiredToAddress && !toAddress) {
|
|
51
62
|
queue.push({
|
|
52
63
|
id: 'TO_ADDRESS_REQUIRED',
|
|
53
|
-
priority:
|
|
64
|
+
priority: 5,
|
|
54
65
|
})
|
|
55
66
|
}
|
|
56
67
|
|
|
@@ -62,6 +73,8 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => {
|
|
|
62
73
|
accountNotDeployedAtDestination,
|
|
63
74
|
requiredToAddress,
|
|
64
75
|
toAddress,
|
|
76
|
+
missingChain,
|
|
77
|
+
missingAccountAddress,
|
|
65
78
|
])
|
|
66
79
|
|
|
67
80
|
return {
|
|
@@ -26,13 +26,13 @@ export const RouteCard: React.FC<
|
|
|
26
26
|
route,
|
|
27
27
|
active,
|
|
28
28
|
variant = 'default',
|
|
29
|
-
expanded:
|
|
29
|
+
expanded: defaultExpanded,
|
|
30
30
|
...other
|
|
31
31
|
}) => {
|
|
32
32
|
const { t } = useTranslation()
|
|
33
33
|
const { subvariant, subvariantOptions, routeLabels, hiddenUI } =
|
|
34
34
|
useWidgetConfig()
|
|
35
|
-
const [cardExpanded, setCardExpanded] = useState(
|
|
35
|
+
const [cardExpanded, setCardExpanded] = useState(defaultExpanded)
|
|
36
36
|
|
|
37
37
|
const handleExpand: MouseEventHandler<HTMLButtonElement> = (e) => {
|
|
38
38
|
e.stopPropagation()
|
|
@@ -103,7 +103,7 @@ export const RouteCard: React.FC<
|
|
|
103
103
|
HiddenUI.RouteTokenDescription
|
|
104
104
|
)}
|
|
105
105
|
/>
|
|
106
|
-
{!
|
|
106
|
+
{!defaultExpanded ? (
|
|
107
107
|
<CardIconButton onClick={handleExpand} size="small">
|
|
108
108
|
{cardExpanded ? (
|
|
109
109
|
<ExpandLess fontSize="inherit" />
|
|
@@ -85,7 +85,7 @@ export const TokenListItemButton: React.FC<TokenListItemButtonProps> = ({
|
|
|
85
85
|
isBalanceLoading,
|
|
86
86
|
}) => {
|
|
87
87
|
const { t } = useTranslation()
|
|
88
|
-
const {
|
|
88
|
+
const { getAddressLink } = useExplorer()
|
|
89
89
|
|
|
90
90
|
const container = useRef(null)
|
|
91
91
|
const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined)
|
|
@@ -184,7 +184,7 @@ export const TokenListItemButton: React.FC<TokenListItemButtonProps> = ({
|
|
|
184
184
|
<IconButton
|
|
185
185
|
size="small"
|
|
186
186
|
LinkComponent={Link}
|
|
187
|
-
href={
|
|
187
|
+
href={getAddressLink(tokenAddress!, chain)}
|
|
188
188
|
target="_blank"
|
|
189
189
|
rel="nofollow noreferrer"
|
|
190
190
|
onClick={(e) => e.stopPropagation()}
|
package/src/config/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = '@lifi/widget'
|
|
2
|
-
export const version = '3.
|
|
2
|
+
export const version = '3.22.0'
|
|
@@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query'
|
|
|
4
4
|
import { useCallback } from 'react'
|
|
5
5
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
6
6
|
import { isItemAllowed } from '../utils/item.js'
|
|
7
|
+
import { getQueryKey } from '../utils/queries.js'
|
|
7
8
|
|
|
8
9
|
export type GetChainById = (
|
|
9
10
|
chainId?: number,
|
|
@@ -18,11 +19,12 @@ const supportedChainTypes = [
|
|
|
18
19
|
]
|
|
19
20
|
|
|
20
21
|
export const useAvailableChains = (chainTypes?: ChainType[]) => {
|
|
21
|
-
const { chains } = useWidgetConfig()
|
|
22
|
+
const { chains, keyPrefix } = useWidgetConfig()
|
|
22
23
|
// const { providers } = useHasExternalWalletProvider();
|
|
24
|
+
|
|
23
25
|
const { data, isLoading } = useQuery({
|
|
24
26
|
queryKey: [
|
|
25
|
-
'chains',
|
|
27
|
+
getQueryKey('chains', keyPrefix),
|
|
26
28
|
// providers,
|
|
27
29
|
chains?.types,
|
|
28
30
|
chains?.allow,
|
package/src/hooks/useExplorer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Chain
|
|
1
|
+
import type { Chain } from '@lifi/sdk'
|
|
2
2
|
import { ChainId } from '@lifi/sdk'
|
|
3
3
|
import { lifiExplorerUrl } from '../config/constants.js'
|
|
4
4
|
import { useAvailableChains } from '../hooks/useAvailableChains.js'
|
|
@@ -21,16 +21,37 @@ export const useExplorer = () => {
|
|
|
21
21
|
const { explorerUrls } = useWidgetConfig()
|
|
22
22
|
const { getChainById } = useAvailableChains()
|
|
23
23
|
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
?
|
|
27
|
-
: chain
|
|
24
|
+
const getExplorerConfig = (chain?: Chain | number) => {
|
|
25
|
+
const resolvedChain = Number.isFinite(chain)
|
|
26
|
+
? getChainById(chain as number)
|
|
27
|
+
: (chain as Chain)
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const explorerUrl =
|
|
30
|
+
(resolvedChain
|
|
31
|
+
? (explorerUrls?.[resolvedChain.id]?.[0] ??
|
|
32
|
+
resolvedChain.metamask.blockExplorerUrls[0])
|
|
33
|
+
: explorerUrls?.internal?.[0]) || lifiExplorerUrl
|
|
34
|
+
|
|
35
|
+
const url = typeof explorerUrl === 'string' ? explorerUrl : explorerUrl.url
|
|
36
|
+
|
|
37
|
+
const defaultTxPath = resolvedChain?.id === ChainId.SUI ? 'txblock' : 'tx'
|
|
38
|
+
const defaultAddressPath =
|
|
39
|
+
resolvedChain?.id === ChainId.SUI ? 'coin' : 'address'
|
|
40
|
+
const txPath =
|
|
41
|
+
typeof explorerUrl === 'string'
|
|
42
|
+
? defaultTxPath
|
|
43
|
+
: explorerUrl.txPath || defaultTxPath
|
|
44
|
+
const addressPath =
|
|
45
|
+
typeof explorerUrl === 'string'
|
|
46
|
+
? defaultAddressPath
|
|
47
|
+
: explorerUrl.addressPath || defaultAddressPath
|
|
31
48
|
|
|
32
|
-
|
|
33
|
-
|
|
49
|
+
return {
|
|
50
|
+
url: sanitiseBaseUrl(url),
|
|
51
|
+
txPath,
|
|
52
|
+
addressPath,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
34
55
|
|
|
35
56
|
const getTransactionLink = ({
|
|
36
57
|
txHash,
|
|
@@ -40,40 +61,18 @@ export const useExplorer = () => {
|
|
|
40
61
|
if (!txHash && txLink) {
|
|
41
62
|
return txLink
|
|
42
63
|
}
|
|
43
|
-
if (!chain) {
|
|
44
|
-
const baseUrl = explorerUrls?.internal?.[0]
|
|
45
|
-
? sanitiseBaseUrl(explorerUrls?.internal[0])
|
|
46
|
-
: lifiExplorerUrl
|
|
47
|
-
return `${baseUrl}/tx/${txHash}`
|
|
48
|
-
}
|
|
49
|
-
const resolvedChain = resolveChain(chain)
|
|
50
|
-
const txPathSegment = resolvedChain?.id === ChainId.SUI ? 'txblock' : 'tx'
|
|
51
|
-
return `${resolvedChain ? getBaseUrl(resolvedChain) : lifiExplorerUrl}/${txPathSegment}/${txHash}`
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const getAddressLink = (address: string, chain?: Chain | number) => {
|
|
55
|
-
if (!chain) {
|
|
56
|
-
const baseUrl = explorerUrls?.internal?.[0]
|
|
57
|
-
? sanitiseBaseUrl(explorerUrls?.internal[0])
|
|
58
|
-
: lifiExplorerUrl
|
|
59
|
-
return `${baseUrl}/address/${address}`
|
|
60
|
-
}
|
|
61
64
|
|
|
62
|
-
const
|
|
63
|
-
return `${
|
|
65
|
+
const config = getExplorerConfig(chain)
|
|
66
|
+
return `${config.url}/${config.txPath}/${txHash}`
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
return link.replace('address', 'coin')
|
|
70
|
-
}
|
|
71
|
-
return link
|
|
69
|
+
const getAddressLink = (address: string, chain?: Chain | number) => {
|
|
70
|
+
const config = getExplorerConfig(chain)
|
|
71
|
+
return `${config.url}/${config.addressPath}/${address}`
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
return {
|
|
75
75
|
getTransactionLink,
|
|
76
76
|
getAddressLink,
|
|
77
|
-
getTokenAddressLink,
|
|
78
77
|
}
|
|
79
78
|
}
|
|
@@ -2,8 +2,10 @@ import type { RouteExtended } from '@lifi/sdk'
|
|
|
2
2
|
import { useAccount } from '@lifi/wallet-management'
|
|
3
3
|
import { keepPreviousData, useQuery } from '@tanstack/react-query'
|
|
4
4
|
import { parseUnits } from 'viem'
|
|
5
|
+
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
5
6
|
import { useFieldValues } from '../stores/form/useFieldValues.js'
|
|
6
7
|
import { isRouteDone } from '../stores/routes/utils.js'
|
|
8
|
+
import { getQueryKey } from '../utils/queries.js'
|
|
7
9
|
import { useTokenAddressBalance } from './useTokenAddressBalance.js'
|
|
8
10
|
import { getTokenBalancesWithRetry } from './useTokenBalance.js'
|
|
9
11
|
|
|
@@ -15,6 +17,7 @@ export const useFromTokenSufficiency = (route?: RouteExtended) => {
|
|
|
15
17
|
'fromToken',
|
|
16
18
|
'fromAmount'
|
|
17
19
|
)
|
|
20
|
+
const { keyPrefix } = useWidgetConfig()
|
|
18
21
|
|
|
19
22
|
let chainId = fromChainId
|
|
20
23
|
let tokenAddress = fromTokenAddress
|
|
@@ -33,7 +36,7 @@ export const useFromTokenSufficiency = (route?: RouteExtended) => {
|
|
|
33
36
|
|
|
34
37
|
const { data: insufficientFromToken, isLoading } = useQuery({
|
|
35
38
|
queryKey: [
|
|
36
|
-
'from-token-sufficiency-check',
|
|
39
|
+
getQueryKey('from-token-sufficiency-check', keyPrefix),
|
|
37
40
|
account.address,
|
|
38
41
|
chainId,
|
|
39
42
|
tokenAddress,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ChainId, getGasRecommendation } from '@lifi/sdk'
|
|
2
2
|
import { useQuery } from '@tanstack/react-query'
|
|
3
|
+
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
4
|
+
import { getQueryKey } from '../utils/queries.js'
|
|
3
5
|
import { useAvailableChains } from './useAvailableChains.js'
|
|
4
6
|
|
|
5
7
|
const refetchInterval = 60_000
|
|
@@ -10,6 +12,7 @@ export const useGasRecommendation = (
|
|
|
10
12
|
fromToken?: string
|
|
11
13
|
) => {
|
|
12
14
|
const { chains } = useAvailableChains()
|
|
15
|
+
const { keyPrefix } = useWidgetConfig()
|
|
13
16
|
|
|
14
17
|
const checkRecommendationLiFuel =
|
|
15
18
|
Boolean(toChainId) &&
|
|
@@ -21,7 +24,12 @@ export const useGasRecommendation = (
|
|
|
21
24
|
Boolean(toChainId) && !fromChain && !fromToken && Boolean(chains?.length)
|
|
22
25
|
|
|
23
26
|
return useQuery({
|
|
24
|
-
queryKey: [
|
|
27
|
+
queryKey: [
|
|
28
|
+
getQueryKey('gas-recommendation', keyPrefix),
|
|
29
|
+
toChainId,
|
|
30
|
+
fromChain,
|
|
31
|
+
fromToken,
|
|
32
|
+
],
|
|
25
33
|
queryFn: async ({
|
|
26
34
|
queryKey: [_, toChainId, fromChain, fromToken],
|
|
27
35
|
signal,
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import type { EVMChain, RouteExtended, Token } from '@lifi/sdk'
|
|
2
|
-
import { isRelayerStep } from '@lifi/sdk'
|
|
1
|
+
import type { EVMChain, RouteExtended, Token, TokenAmount } from '@lifi/sdk'
|
|
2
|
+
import { ChainType, isRelayerStep } from '@lifi/sdk'
|
|
3
3
|
import { useAccount } from '@lifi/wallet-management'
|
|
4
4
|
import { useQuery } from '@tanstack/react-query'
|
|
5
|
+
import { useMemo } from 'react'
|
|
6
|
+
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
7
|
+
import { getQueryKey } from '../utils/queries.js'
|
|
5
8
|
import { useAvailableChains } from './useAvailableChains.js'
|
|
6
9
|
import { useIsContractAddress } from './useIsContractAddress.js'
|
|
7
10
|
import { getTokenBalancesWithRetry } from './useTokenBalance.js'
|
|
@@ -19,30 +22,64 @@ const refetchInterval = 30_000
|
|
|
19
22
|
|
|
20
23
|
export const useGasSufficiency = (route?: RouteExtended) => {
|
|
21
24
|
const { getChainById } = useAvailableChains()
|
|
22
|
-
const { account } = useAccount({
|
|
23
|
-
chainType:
|
|
25
|
+
const { account: EVMAccount, accounts } = useAccount({
|
|
26
|
+
chainType: ChainType.EVM,
|
|
24
27
|
})
|
|
28
|
+
const { keyPrefix } = useWidgetConfig()
|
|
29
|
+
|
|
30
|
+
const { relevantAccounts, relevantAccountsQueryKey } = useMemo(() => {
|
|
31
|
+
const chainTypes = route?.steps.reduce((acc, step) => {
|
|
32
|
+
const chainType = getChainById(step.action.fromChainId)?.chainType
|
|
33
|
+
if (chainType) {
|
|
34
|
+
acc.add(chainType)
|
|
35
|
+
}
|
|
36
|
+
return acc
|
|
37
|
+
}, new Set<ChainType>())
|
|
38
|
+
|
|
39
|
+
const relevantAccounts = accounts.filter(
|
|
40
|
+
(account) =>
|
|
41
|
+
account.isConnected &&
|
|
42
|
+
account.address &&
|
|
43
|
+
chainTypes?.has(account.chainType)
|
|
44
|
+
)
|
|
45
|
+
return {
|
|
46
|
+
relevantAccounts,
|
|
47
|
+
relevantAccountsQueryKey: relevantAccounts
|
|
48
|
+
.map((account) => account.address)
|
|
49
|
+
.join(','),
|
|
50
|
+
}
|
|
51
|
+
}, [accounts, route?.steps, getChainById])
|
|
25
52
|
|
|
26
53
|
const { isContractAddress, isLoading: isContractAddressLoading } =
|
|
27
|
-
useIsContractAddress(
|
|
54
|
+
useIsContractAddress(
|
|
55
|
+
EVMAccount.address,
|
|
56
|
+
route?.fromChainId,
|
|
57
|
+
EVMAccount.chainType
|
|
58
|
+
)
|
|
28
59
|
|
|
29
60
|
const { data: insufficientGas, isLoading } = useQuery({
|
|
30
61
|
queryKey: [
|
|
31
|
-
'gas-sufficiency-check',
|
|
32
|
-
|
|
62
|
+
getQueryKey('gas-sufficiency-check', keyPrefix),
|
|
63
|
+
relevantAccountsQueryKey,
|
|
33
64
|
route?.id,
|
|
34
65
|
isContractAddress,
|
|
35
66
|
] as const,
|
|
36
|
-
queryFn: async (
|
|
67
|
+
queryFn: async () => {
|
|
37
68
|
if (!route) {
|
|
38
69
|
return
|
|
39
70
|
}
|
|
40
71
|
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
72
|
+
// Filter out steps that are relayer steps or have primaryType 'Permit' or 'Order'
|
|
73
|
+
const filteredSteps = route.steps.filter(
|
|
74
|
+
(step) =>
|
|
75
|
+
!isRelayerStep(step) &&
|
|
76
|
+
!step.typedData?.some(
|
|
77
|
+
(t) => t.primaryType === 'Permit' || t.primaryType === 'Order'
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
// If all steps are filtered out, we don't need to check for gas sufficiency
|
|
82
|
+
if (!filteredSteps.length) {
|
|
46
83
|
return
|
|
47
84
|
}
|
|
48
85
|
|
|
@@ -51,7 +88,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
|
|
|
51
88
|
.flatMap((step) => step.includedSteps)
|
|
52
89
|
.some((includedStep) => includedStep.tool === 'gasZip')
|
|
53
90
|
|
|
54
|
-
const gasCosts =
|
|
91
|
+
const gasCosts = filteredSteps
|
|
55
92
|
.filter((step) => !step.execution || step.execution.status !== 'DONE')
|
|
56
93
|
.reduce(
|
|
57
94
|
(groupedGasCosts, step) => {
|
|
@@ -70,6 +107,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
|
|
|
70
107
|
? groupedGasCosts[token.chainId].gasAmount + gasCostAmount
|
|
71
108
|
: gasCostAmount,
|
|
72
109
|
token,
|
|
110
|
+
chain: getChainById(token.chainId),
|
|
73
111
|
}
|
|
74
112
|
}
|
|
75
113
|
// Add fees paid in native tokens to gas sufficiency check (included: false)
|
|
@@ -88,11 +126,12 @@ export const useGasSufficiency = (route?: RouteExtended) => {
|
|
|
88
126
|
? groupedGasCosts[token.chainId].gasAmount + feeCostAmount
|
|
89
127
|
: feeCostAmount,
|
|
90
128
|
token,
|
|
91
|
-
|
|
129
|
+
chain: getChainById(token.chainId),
|
|
130
|
+
}
|
|
92
131
|
}
|
|
93
132
|
return groupedGasCosts
|
|
94
133
|
},
|
|
95
|
-
{} as Record<
|
|
134
|
+
{} as Record<string, GasSufficiency>
|
|
96
135
|
)
|
|
97
136
|
|
|
98
137
|
// Check whether we are sending a native token
|
|
@@ -104,15 +143,30 @@ export const useGasSufficiency = (route?: RouteExtended) => {
|
|
|
104
143
|
gasCosts[route.fromChainId]?.gasAmount + BigInt(route.fromAmount)
|
|
105
144
|
}
|
|
106
145
|
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
146
|
+
const gasCostsValues = Object.values(gasCosts)
|
|
147
|
+
|
|
148
|
+
const balanceChecks = await Promise.allSettled(
|
|
149
|
+
relevantAccounts.map((account) => {
|
|
150
|
+
const relevantTokens = gasCostsValues
|
|
151
|
+
.filter((gasCost) => gasCost.chain?.chainType === account.chainType)
|
|
152
|
+
.map((item) => item.token)
|
|
153
|
+
|
|
154
|
+
return getTokenBalancesWithRetry(account.address!, relevantTokens)
|
|
155
|
+
})
|
|
110
156
|
)
|
|
111
157
|
|
|
158
|
+
const tokenBalances = balanceChecks
|
|
159
|
+
.filter(
|
|
160
|
+
(result): result is PromiseFulfilledResult<TokenAmount[]> =>
|
|
161
|
+
result.status === 'fulfilled' && Boolean(result.value)
|
|
162
|
+
)
|
|
163
|
+
.flatMap((result) => result.value)
|
|
164
|
+
|
|
112
165
|
if (!tokenBalances?.length) {
|
|
113
166
|
return
|
|
114
167
|
}
|
|
115
|
-
|
|
168
|
+
|
|
169
|
+
Object.keys(gasCosts).forEach((chainId) => {
|
|
116
170
|
if (gasCosts[chainId]) {
|
|
117
171
|
const gasTokenBalance =
|
|
118
172
|
tokenBalances?.find(
|
|
@@ -135,7 +189,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
|
|
|
135
189
|
...gasCosts[chainId],
|
|
136
190
|
insufficient,
|
|
137
191
|
insufficientAmount,
|
|
138
|
-
chain: insufficient ? getChainById(chainId) : undefined,
|
|
192
|
+
chain: insufficient ? getChainById(Number(chainId)) : undefined,
|
|
139
193
|
}
|
|
140
194
|
}
|
|
141
195
|
})
|
|
@@ -150,7 +204,7 @@ export const useGasSufficiency = (route?: RouteExtended) => {
|
|
|
150
204
|
enabled: Boolean(
|
|
151
205
|
!isContractAddress &&
|
|
152
206
|
!isContractAddressLoading &&
|
|
153
|
-
|
|
207
|
+
relevantAccounts.length > 0 &&
|
|
154
208
|
route
|
|
155
209
|
),
|
|
156
210
|
refetchInterval,
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { ChainType, isBatchingSupported } from '@lifi/sdk'
|
|
2
2
|
import type { ExtendedChain } from '@lifi/sdk'
|
|
3
3
|
import { useQuery } from '@tanstack/react-query'
|
|
4
|
+
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
5
|
+
import { getQueryKey } from '../utils/queries.js'
|
|
4
6
|
|
|
5
7
|
export function useIsBatchingSupported(
|
|
6
8
|
chain?: ExtendedChain,
|
|
7
9
|
address?: string
|
|
8
10
|
) {
|
|
11
|
+
const { keyPrefix } = useWidgetConfig()
|
|
12
|
+
|
|
9
13
|
const enabled = Boolean(
|
|
10
14
|
chain && chain.chainType === ChainType.EVM && !!address
|
|
11
15
|
)
|
|
12
16
|
const { data, isLoading } = useQuery({
|
|
13
|
-
queryKey: [
|
|
17
|
+
queryKey: [
|
|
18
|
+
getQueryKey('isBatchingSupported', keyPrefix),
|
|
19
|
+
chain?.id,
|
|
20
|
+
address,
|
|
21
|
+
],
|
|
14
22
|
queryFn: () => {
|
|
15
23
|
return isBatchingSupported({ chainId: chain!.id })
|
|
16
24
|
},
|