@lifi/widget 4.0.0-beta.17 → 4.0.0-beta.18
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/dist/esm/components/AmountInput/AmountInput.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInputStartAdornment.js.map +1 -1
- package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
- package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
- package/dist/esm/components/ChainSelect/useChainSelect.js.map +1 -1
- package/dist/esm/components/Chains/AllChainsAvatar.js +1 -1
- package/dist/esm/components/Chains/AllChainsAvatar.js.map +1 -1
- package/dist/esm/components/Chains/SelectChainContent.js.map +1 -1
- package/dist/esm/components/Dialog/Dialog.js.map +1 -1
- package/dist/esm/components/Expansion/Expansion.js.map +1 -1
- package/dist/esm/components/IconCircle/IconCircle.js.map +1 -1
- package/dist/esm/components/ReverseTokensButton/ReverseTokensButton.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
- package/dist/esm/components/SendToWallet/SendToWalletButton.js +1 -1
- package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
- package/dist/esm/components/Skeleton/WidgetSkeleton.js.map +1 -1
- package/dist/esm/components/Step/Step.js.map +1 -1
- package/dist/esm/components/Step/StepActions.js.map +1 -1
- package/dist/esm/components/Tabs/Tabs.style.js.map +1 -1
- package/dist/esm/components/Timer/StepTimer.js.map +1 -1
- package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
- package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
- package/dist/esm/components/TransactionCard/ActiveTransactionCard.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/timer/time.js.map +1 -1
- package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
- package/dist/esm/hooks/useActionMessage.js +2 -2
- package/dist/esm/hooks/useActionMessage.js.map +1 -1
- package/dist/esm/hooks/useAddressActivity.js.map +1 -1
- package/dist/esm/hooks/useAvailableChains.js.map +1 -1
- package/dist/esm/hooks/useChain.js.map +1 -1
- package/dist/esm/hooks/useChains.js.map +1 -1
- package/dist/esm/hooks/useDebouncedWatch.js.map +1 -1
- package/dist/esm/hooks/useFilteredByTokenBalances.js.map +1 -1
- package/dist/esm/hooks/useFromAmountThreshold.js.map +1 -1
- package/dist/esm/hooks/useFromTokenSufficiency.js.map +1 -1
- package/dist/esm/hooks/useGasRecommendation.js.map +1 -1
- package/dist/esm/hooks/useGasRefuel.js.map +1 -1
- package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
- package/dist/esm/hooks/useIsContractAddress.js.map +1 -1
- package/dist/esm/hooks/useListHeight.js.map +1 -1
- package/dist/esm/hooks/useLongPress.js.map +1 -1
- package/dist/esm/hooks/useNavigateBack.js.map +1 -1
- package/dist/esm/hooks/useRouteExecution.js +0 -2
- package/dist/esm/hooks/useRouteExecution.js.map +1 -1
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/hooks/useScrollableContainer.js.map +1 -1
- package/dist/esm/hooks/useSwapOnly.js.map +1 -1
- package/dist/esm/hooks/useToAddressAutoPopulate.js.map +1 -1
- package/dist/esm/hooks/useToAddressReset.js.map +1 -1
- package/dist/esm/hooks/useTokenBalance.js.map +1 -1
- package/dist/esm/hooks/useTokenBalances.js.map +1 -1
- package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -1
- package/dist/esm/hooks/useTokenSearch.js.map +1 -1
- package/dist/esm/hooks/useTokens.js.map +1 -1
- package/dist/esm/hooks/useTransactionDetails.js.map +1 -1
- package/dist/esm/hooks/useTransactionHistory.js.map +1 -1
- package/dist/esm/hooks/useTransactionList.js.map +1 -1
- package/dist/esm/hooks/useWidgetEvents.js.map +1 -1
- package/dist/esm/i18n/bn.json +3 -0
- package/dist/esm/i18n/de.json +3 -0
- package/dist/esm/i18n/es.json +3 -0
- package/dist/esm/i18n/fr.json +3 -0
- package/dist/esm/i18n/hi.json +3 -0
- package/dist/esm/i18n/id.json +3 -0
- package/dist/esm/i18n/it.json +3 -0
- package/dist/esm/i18n/ja.json +3 -0
- package/dist/esm/i18n/ko.json +3 -0
- package/dist/esm/i18n/pl.json +3 -0
- package/dist/esm/i18n/pt.json +3 -0
- package/dist/esm/i18n/th.json +3 -0
- package/dist/esm/i18n/tr.json +3 -0
- package/dist/esm/i18n/uk.json +3 -0
- package/dist/esm/i18n/vi.json +3 -0
- package/dist/esm/i18n/zh.json +3 -0
- package/dist/esm/pages/SelectChainPage/SelectChainPage.js.map +1 -1
- package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SmallBalanceFilterSettings.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/StepActionRow.js +2 -2
- package/dist/esm/pages/TransactionDetailsPage/StepActionRow.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/StepActionsList.js +11 -5
- package/dist/esm/pages/TransactionDetailsPage/StepActionsList.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionPage.js.map +1 -1
- package/dist/esm/providers/I18nProvider/I18nProvider.js.map +1 -1
- package/dist/esm/providers/I18nProvider/i18n.js.map +1 -1
- package/dist/esm/providers/QueryClientProvider.js.map +1 -1
- package/dist/esm/providers/ThemeProvider/ThemeProvider.js.map +1 -1
- package/dist/esm/providers/WalletProvider/WalletProvider.js.map +1 -1
- package/dist/esm/providers/WalletProvider/useExternalWalletProvider.js.map +1 -1
- package/dist/esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
- package/dist/esm/stores/bookmarks/useBookmarkActions.js.map +1 -1
- package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
- package/dist/esm/stores/chains/useChainOrder.js.map +1 -1
- package/dist/esm/stores/form/URLSearchParamsBuilder.js.map +1 -1
- package/dist/esm/stores/form/createFormStore.js.map +1 -1
- package/dist/esm/stores/form/useFieldActions.js.map +1 -1
- package/dist/esm/stores/form/useFieldValues.js.map +1 -1
- package/dist/esm/stores/form/useTouchedFields.js.map +1 -1
- package/dist/esm/stores/header/useHeaderStore.js.map +1 -1
- package/dist/esm/stores/routes/RouteExecutionStore.js.map +1 -1
- package/dist/esm/stores/routes/createRouteExecutionStore.js.map +1 -1
- package/dist/esm/stores/routes/useRouteExecutionIndicator.js.map +1 -1
- package/dist/esm/stores/routes/utils.js.map +1 -1
- package/dist/esm/stores/settings/SettingsStore.js.map +1 -1
- package/dist/esm/stores/settings/useSettingsActions.js.map +1 -1
- package/dist/esm/stores/settings/useSplitSubvariantStore.js.map +1 -1
- package/dist/esm/utils/converters.js.map +1 -1
- package/dist/esm/utils/format.js.map +1 -1
- package/dist/esm/utils/timer.js.map +1 -1
- package/dist/esm/utils/token.js.map +1 -1
- package/package.json +8 -8
- package/src/components/Chains/AllChainsAvatar.tsx +1 -1
- package/src/components/SendToWallet/SendToWalletButton.tsx +1 -1
- package/src/config/version.ts +1 -1
- package/src/hooks/useActionMessage.ts +4 -3
- package/src/hooks/useRouteExecution.ts +0 -2
- package/src/pages/TransactionDetailsPage/StepActionRow.tsx +3 -2
- package/src/pages/TransactionDetailsPage/StepActionsList.tsx +19 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepTimer.js","names":[],"sources":["../../../../src/components/Timer/StepTimer.tsx"],"sourcesContent":["import type { LiFiStepExtended } from '@lifi/sdk'\nimport type { JSX } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useExecutionTimer } from '../../hooks/timer/useExecutionTimer.js'\nimport { TimerContent } from './TimerContent.js'\n\nexport const getExpiryTimestamp = (step: LiFiStepExtended): Date => {\n const execution = step?.execution\n if (!execution) {\n return new Date()\n }\n const expiry = new Date(\n (execution.signedAt ?? Date.now()) + step.estimate.executionDuration * 1000\n )\n return expiry\n}\n\nexport const StepTimer: React.FC<{\n step: LiFiStepExtended\n hideInProgress?: boolean\n}> = ({ step, hideInProgress }) => {\n const { i18n } = useTranslation()\n\n if (\n step.execution?.status === 'DONE' ||\n step.execution?.status === 'FAILED'\n ) {\n return null\n }\n\n if (!step.execution?.signedAt) {\n const showSeconds = step.estimate.executionDuration < 60\n const duration = showSeconds\n ? Math.floor(step.estimate.executionDuration)\n : Math.floor(step.estimate.executionDuration / 60)\n return (\n <TimerContent>\n {duration.toLocaleString(i18n.language, {\n style: 'unit',\n unit: showSeconds ? 'second' : 'minute',\n unitDisplay: 'narrow',\n })}\n </TimerContent>\n )\n }\n\n return (\n <ExecutionTimer\n expiryTimestamp={getExpiryTimestamp(step)}\n hideInProgress={hideInProgress}\n />\n )\n}\n\nexport const ExecutionTimerText = ({\n expiryTimestamp,\n}: {\n expiryTimestamp: Date\n}): string | null => {\n const { formatted } = useExecutionTimer(expiryTimestamp)\n return formatted\n}\n\nexport const ExecutionTimer = ({\n expiryTimestamp,\n hideInProgress,\n}: {\n expiryTimestamp: Date\n hideInProgress?: boolean\n}): JSX.Element | string | null => {\n const { t } = useTranslation()\n const { formatted, isTimerExpired } = useExecutionTimer(expiryTimestamp)\n\n if (isTimerExpired) {\n if (hideInProgress) {\n return null\n }\n return t('main.inProgress')\n }\n\n return <TimerContent>{formatted}</TimerContent>\n}\n"],"mappings":";;;;;AAMA,MAAa,sBAAsB,SAAiC;CAClE,MAAM,YAAY,MAAM;AACxB,KAAI,CAAC,UACH,wBAAO,IAAI,MAAM;AAKnB,
|
|
1
|
+
{"version":3,"file":"StepTimer.js","names":[],"sources":["../../../../src/components/Timer/StepTimer.tsx"],"sourcesContent":["import type { LiFiStepExtended } from '@lifi/sdk'\nimport type { JSX } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useExecutionTimer } from '../../hooks/timer/useExecutionTimer.js'\nimport { TimerContent } from './TimerContent.js'\n\nexport const getExpiryTimestamp = (step: LiFiStepExtended): Date => {\n const execution = step?.execution\n if (!execution) {\n return new Date()\n }\n const expiry = new Date(\n (execution.signedAt ?? Date.now()) + step.estimate.executionDuration * 1000\n )\n return expiry\n}\n\nexport const StepTimer: React.FC<{\n step: LiFiStepExtended\n hideInProgress?: boolean\n}> = ({ step, hideInProgress }) => {\n const { i18n } = useTranslation()\n\n if (\n step.execution?.status === 'DONE' ||\n step.execution?.status === 'FAILED'\n ) {\n return null\n }\n\n if (!step.execution?.signedAt) {\n const showSeconds = step.estimate.executionDuration < 60\n const duration = showSeconds\n ? Math.floor(step.estimate.executionDuration)\n : Math.floor(step.estimate.executionDuration / 60)\n return (\n <TimerContent>\n {duration.toLocaleString(i18n.language, {\n style: 'unit',\n unit: showSeconds ? 'second' : 'minute',\n unitDisplay: 'narrow',\n })}\n </TimerContent>\n )\n }\n\n return (\n <ExecutionTimer\n expiryTimestamp={getExpiryTimestamp(step)}\n hideInProgress={hideInProgress}\n />\n )\n}\n\nexport const ExecutionTimerText = ({\n expiryTimestamp,\n}: {\n expiryTimestamp: Date\n}): string | null => {\n const { formatted } = useExecutionTimer(expiryTimestamp)\n return formatted\n}\n\nexport const ExecutionTimer = ({\n expiryTimestamp,\n hideInProgress,\n}: {\n expiryTimestamp: Date\n hideInProgress?: boolean\n}): JSX.Element | string | null => {\n const { t } = useTranslation()\n const { formatted, isTimerExpired } = useExecutionTimer(expiryTimestamp)\n\n if (isTimerExpired) {\n if (hideInProgress) {\n return null\n }\n return t('main.inProgress')\n }\n\n return <TimerContent>{formatted}</TimerContent>\n}\n"],"mappings":";;;;;AAMA,MAAa,sBAAsB,SAAiC;CAClE,MAAM,YAAY,MAAM;AACxB,KAAI,CAAC,UACH,wBAAO,IAAI,MAAM;AAKnB,QAAO,IAHY,MAChB,UAAU,YAAY,KAAK,KAAK,IAAI,KAAK,SAAS,oBAAoB,IAE5D;;AAGf,MAAa,aAGP,EAAE,MAAM,qBAAqB;CACjC,MAAM,EAAE,SAAS,gBAAgB;AAEjC,KACE,KAAK,WAAW,WAAW,UAC3B,KAAK,WAAW,WAAW,SAE3B,QAAO;AAGT,KAAI,CAAC,KAAK,WAAW,UAAU;EAC7B,MAAM,cAAc,KAAK,SAAS,oBAAoB;AAItD,SACE,oBAAC,cAAD,EAAA,WAJe,cACb,KAAK,MAAM,KAAK,SAAS,kBAAkB,GAC3C,KAAK,MAAM,KAAK,SAAS,oBAAoB,GAAG,EAGtC,eAAe,KAAK,UAAU;GACtC,OAAO;GACP,MAAM,cAAc,WAAW;GAC/B,aAAa;GACd,CAAC,EACW,CAAA;;AAInB,QACE,oBAAC,gBAAD;EACE,iBAAiB,mBAAmB,KAAK;EACzB;EAChB,CAAA;;AAIN,MAAa,sBAAsB,EACjC,sBAGmB;CACnB,MAAM,EAAE,cAAc,kBAAkB,gBAAgB;AACxD,QAAO;;AAGT,MAAa,kBAAkB,EAC7B,iBACA,qBAIiC;CACjC,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,EAAE,WAAW,mBAAmB,kBAAkB,gBAAgB;AAExE,KAAI,gBAAgB;AAClB,MAAI,eACF,QAAO;AAET,SAAO,EAAE,kBAAkB;;AAG7B,QAAO,oBAAC,cAAD,EAAA,UAAe,WAAyB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenListItem.js","names":["ListItem","IconButton","ListItemButton"],"sources":["../../../../src/components/TokenList/TokenListItem.tsx"],"sourcesContent":["import type { StaticToken } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'\nimport WarningRounded from '@mui/icons-material/WarningRounded'\nimport {\n Avatar,\n Box,\n ListItemAvatar,\n ListItemText,\n listItemSecondaryActionClasses,\n Skeleton,\n Slide,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport type { JSX, MouseEventHandler } from 'react'\nimport { memo, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useLongPress } from '../../hooks/useLongPress.js'\nimport { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'\nimport { shortenAddress } from '../../utils/wallet.js'\nimport { TokenAvatar } from '../Avatar/TokenAvatar.js'\nimport { ListItemButton } from '../ListItem/ListItemButton.js'\nimport { PinTokenButton } from './PinTokenButton.js'\nimport { IconButton, ListItem } from './TokenList.style.js'\nimport type {\n TokenListItemAvatarProps,\n TokenListItemButtonProps,\n TokenListItemProps,\n} from './types.js'\n\nexport const TokenListItem: React.FC<TokenListItemProps> = memo(\n ({\n onClick,\n size,\n start,\n token,\n chain,\n isBalanceLoading,\n startAdornment,\n endAdornment,\n selected,\n onShowTokenDetails,\n }) => {\n return (\n <ListItem\n style={{\n height: `${size}px`,\n transform: `translateY(${start}px)`,\n padding: 0,\n }}\n >\n {startAdornment}\n <TokenListItemButton\n token={token}\n isBalanceLoading={isBalanceLoading}\n onClick={onClick}\n chain={chain}\n selected={selected}\n onShowTokenDetails={onShowTokenDetails}\n />\n {endAdornment}\n </ListItem>\n )\n }\n)\n\nconst TokenListItemAvatar = memo(({ token }: TokenListItemAvatarProps) => {\n const [isImageLoading, setIsImageLoading] = useState(true)\n\n return (\n <Avatar\n src={token.logoURI}\n alt={token.symbol}\n sx={(theme) =>\n isImageLoading ? { bgcolor: theme.vars.palette.grey[300] } : null\n }\n onLoad={() => setIsImageLoading(false)}\n >\n {token.symbol?.[0]}\n </Avatar>\n )\n})\n\ninterface OpenTokenDetailsButtonProps {\n tokenAddress: string | undefined\n withoutContractAddress: boolean\n chainId: number\n onClick: (\n tokenAddress: string,\n withoutContractAddress: boolean,\n chainId: number\n ) => void\n}\n\nconst OpenTokenDetailsButton = ({\n tokenAddress,\n withoutContractAddress,\n chainId,\n onClick,\n}: OpenTokenDetailsButtonProps) => {\n if (!tokenAddress) {\n return null\n }\n return (\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation()\n e.currentTarget.blur() // Remove focus to prevent accessibility issues when opening drawer\n onClick(tokenAddress, withoutContractAddress, chainId)\n }}\n >\n <InfoOutlinedIcon />\n </IconButton>\n )\n}\n\nconst TokenListItemButton: React.FC<TokenListItemButtonProps> = memo(\n ({\n onClick,\n token,\n chain,\n isBalanceLoading,\n selected,\n onShowTokenDetails,\n }) => {\n const { t } = useTranslation()\n const container = useRef(null)\n const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined)\n const [showAddress, setShowAddress] = useState(false)\n\n const withoutContractAddress = chain?.chainType === ChainType.UTXO\n\n const onMouseEnter = () => {\n timeoutId.current = setTimeout(() => {\n if (token.address) {\n setShowAddress(true)\n }\n }, 350)\n }\n\n const onMouseLeave = () => {\n clearTimeout(timeoutId.current)\n if (showAddress) {\n setShowAddress(false)\n }\n }\n\n const handleClick: MouseEventHandler<HTMLDivElement> = (e) => {\n e.stopPropagation()\n onClick?.(token.address, token.chainId)\n }\n\n const tokenAmount = useMemo(\n () => formatTokenAmount(token.amount, token.decimals),\n [token.amount, token.decimals]\n )\n\n const tokenPrice = useMemo(\n () => formatTokenPrice(token.amount, token.priceUSD, token.decimals),\n [token.amount, token.priceUSD, token.decimals]\n )\n\n const longPressEvents = useLongPress(() =>\n onShowTokenDetails(token.address, withoutContractAddress, token.chainId)\n )\n\n return (\n <ListItemButton\n onClick={handleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n {...longPressEvents}\n dense\n selected={selected}\n sx={{\n height: 60,\n marginBottom: '4px',\n }}\n >\n <ListItemAvatar>\n {chain ? (\n <TokenAvatar\n token={token as StaticToken}\n chain={chain}\n tokenAvatarSize={40}\n chainAvatarSize={16}\n />\n ) : (\n <TokenListItemAvatar token={token} />\n )}\n </ListItemAvatar>\n <ListItemText\n primary={\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n {token.symbol}\n {!token.verified && (\n <Tooltip\n title={t('warning.message.unverifiedToken')}\n placement=\"top\"\n arrow\n >\n <WarningRounded\n sx={{\n display: 'flex',\n fontSize: 16,\n color: 'warning.main',\n cursor: 'help',\n }}\n />\n </Tooltip>\n )}\n </Box>\n }\n slotProps={{\n secondary: {\n component: 'div',\n },\n }}\n secondary={\n withoutContractAddress ? (\n <Box\n ref={container}\n sx={{\n height: 20,\n display: 'flex',\n }}\n >\n <Box\n sx={{\n pt: 0.25,\n }}\n >\n {token.name}\n </Box>\n <Box\n sx={{\n position: 'relative',\n }}\n >\n <Slide\n direction=\"up\"\n in={showAddress}\n container={container.current}\n style={{\n position: 'absolute',\n }}\n appear={false}\n mountOnEnter\n >\n <Box>\n <OpenTokenDetailsButton\n tokenAddress={token.address}\n withoutContractAddress={withoutContractAddress}\n chainId={token.chainId}\n onClick={onShowTokenDetails}\n />\n <PinTokenButton\n chainId={token.chainId}\n tokenAddress={token.address}\n />\n </Box>\n </Slide>\n </Box>\n </Box>\n ) : (\n <Box\n ref={container}\n sx={{\n position: 'relative',\n height: 20,\n }}\n >\n <Slide\n direction=\"down\"\n in={!showAddress}\n container={container.current}\n style={{\n position: 'absolute',\n }}\n appear={false}\n >\n <Box\n sx={{\n pt: 0.25,\n }}\n >\n {token.name}\n </Box>\n </Slide>\n <Slide\n direction=\"up\"\n in={showAddress}\n container={container.current}\n style={{\n position: 'absolute',\n }}\n appear={false}\n mountOnEnter\n >\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 0.5,\n }}\n >\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n pt: 0.125,\n }}\n >\n {shortenAddress(token.address)}\n </Box>\n <Box>\n <OpenTokenDetailsButton\n tokenAddress={token.address}\n withoutContractAddress={withoutContractAddress}\n chainId={token.chainId}\n onClick={onShowTokenDetails}\n />\n <PinTokenButton\n chainId={token.chainId}\n tokenAddress={token.address}\n />\n </Box>\n </Box>\n </Slide>\n </Box>\n )\n }\n />\n {isBalanceLoading ? (\n <TokenAmountSkeleton />\n ) : (\n <Box sx={{ textAlign: 'right' }}>\n {token.amount ? (\n <Typography\n noWrap\n sx={{\n fontWeight: 600,\n }}\n title={tokenAmount}\n >\n {t('format.tokenAmount', {\n value: tokenAmount,\n })}\n </Typography>\n ) : null}\n {token.amount && token.priceUSD ? (\n <Typography\n data-price={token.priceUSD}\n sx={{\n fontWeight: 500,\n fontSize: 12,\n color: 'text.secondary',\n }}\n >\n {t('format.currency', {\n value: tokenPrice,\n })}\n </Typography>\n ) : null}\n </Box>\n )}\n </ListItemButton>\n )\n }\n)\n\nexport const TokenListItemSkeleton = (): JSX.Element => {\n return (\n <ListItem\n secondaryAction={<TokenAmountSkeleton />}\n disablePadding\n sx={(theme) => ({\n position: 'relative',\n flexDirection: 'row',\n alignItems: 'center',\n padding: 0,\n [`& .${listItemSecondaryActionClasses.root}`]: {\n right: theme.spacing(1.5),\n },\n })}\n >\n <ListItemAvatar>\n <Skeleton\n variant=\"circular\"\n width={40}\n height={40}\n sx={{ marginLeft: 1.5, marginRight: 2 }}\n />\n </ListItemAvatar>\n <ListItemText\n primary={<Skeleton variant=\"text\" width={56} height={24} />}\n secondary={<Skeleton variant=\"text\" width={96} height={16} />}\n />\n </ListItem>\n )\n}\n\nconst TokenAmountSkeleton: React.FC = () => {\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-end',\n }}\n >\n <Skeleton variant=\"text\" width={56} height={24} />\n <Skeleton variant=\"text\" width={48} height={16} />\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TokenListItem.js","names":["ListItem","IconButton","ListItemButton"],"sources":["../../../../src/components/TokenList/TokenListItem.tsx"],"sourcesContent":["import type { StaticToken } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'\nimport WarningRounded from '@mui/icons-material/WarningRounded'\nimport {\n Avatar,\n Box,\n ListItemAvatar,\n ListItemText,\n listItemSecondaryActionClasses,\n Skeleton,\n Slide,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport type { JSX, MouseEventHandler } from 'react'\nimport { memo, useMemo, useRef, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useLongPress } from '../../hooks/useLongPress.js'\nimport { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'\nimport { shortenAddress } from '../../utils/wallet.js'\nimport { TokenAvatar } from '../Avatar/TokenAvatar.js'\nimport { ListItemButton } from '../ListItem/ListItemButton.js'\nimport { PinTokenButton } from './PinTokenButton.js'\nimport { IconButton, ListItem } from './TokenList.style.js'\nimport type {\n TokenListItemAvatarProps,\n TokenListItemButtonProps,\n TokenListItemProps,\n} from './types.js'\n\nexport const TokenListItem: React.FC<TokenListItemProps> = memo(\n ({\n onClick,\n size,\n start,\n token,\n chain,\n isBalanceLoading,\n startAdornment,\n endAdornment,\n selected,\n onShowTokenDetails,\n }) => {\n return (\n <ListItem\n style={{\n height: `${size}px`,\n transform: `translateY(${start}px)`,\n padding: 0,\n }}\n >\n {startAdornment}\n <TokenListItemButton\n token={token}\n isBalanceLoading={isBalanceLoading}\n onClick={onClick}\n chain={chain}\n selected={selected}\n onShowTokenDetails={onShowTokenDetails}\n />\n {endAdornment}\n </ListItem>\n )\n }\n)\n\nconst TokenListItemAvatar = memo(({ token }: TokenListItemAvatarProps) => {\n const [isImageLoading, setIsImageLoading] = useState(true)\n\n return (\n <Avatar\n src={token.logoURI}\n alt={token.symbol}\n sx={(theme) =>\n isImageLoading ? { bgcolor: theme.vars.palette.grey[300] } : null\n }\n onLoad={() => setIsImageLoading(false)}\n >\n {token.symbol?.[0]}\n </Avatar>\n )\n})\n\ninterface OpenTokenDetailsButtonProps {\n tokenAddress: string | undefined\n withoutContractAddress: boolean\n chainId: number\n onClick: (\n tokenAddress: string,\n withoutContractAddress: boolean,\n chainId: number\n ) => void\n}\n\nconst OpenTokenDetailsButton = ({\n tokenAddress,\n withoutContractAddress,\n chainId,\n onClick,\n}: OpenTokenDetailsButtonProps) => {\n if (!tokenAddress) {\n return null\n }\n return (\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation()\n e.currentTarget.blur() // Remove focus to prevent accessibility issues when opening drawer\n onClick(tokenAddress, withoutContractAddress, chainId)\n }}\n >\n <InfoOutlinedIcon />\n </IconButton>\n )\n}\n\nconst TokenListItemButton: React.FC<TokenListItemButtonProps> = memo(\n ({\n onClick,\n token,\n chain,\n isBalanceLoading,\n selected,\n onShowTokenDetails,\n }) => {\n const { t } = useTranslation()\n const container = useRef(null)\n const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined)\n const [showAddress, setShowAddress] = useState(false)\n\n const withoutContractAddress = chain?.chainType === ChainType.UTXO\n\n const onMouseEnter = () => {\n timeoutId.current = setTimeout(() => {\n if (token.address) {\n setShowAddress(true)\n }\n }, 350)\n }\n\n const onMouseLeave = () => {\n clearTimeout(timeoutId.current)\n if (showAddress) {\n setShowAddress(false)\n }\n }\n\n const handleClick: MouseEventHandler<HTMLDivElement> = (e) => {\n e.stopPropagation()\n onClick?.(token.address, token.chainId)\n }\n\n const tokenAmount = useMemo(\n () => formatTokenAmount(token.amount, token.decimals),\n [token.amount, token.decimals]\n )\n\n const tokenPrice = useMemo(\n () => formatTokenPrice(token.amount, token.priceUSD, token.decimals),\n [token.amount, token.priceUSD, token.decimals]\n )\n\n const longPressEvents = useLongPress(() =>\n onShowTokenDetails(token.address, withoutContractAddress, token.chainId)\n )\n\n return (\n <ListItemButton\n onClick={handleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n {...longPressEvents}\n dense\n selected={selected}\n sx={{\n height: 60,\n marginBottom: '4px',\n }}\n >\n <ListItemAvatar>\n {chain ? (\n <TokenAvatar\n token={token as StaticToken}\n chain={chain}\n tokenAvatarSize={40}\n chainAvatarSize={16}\n />\n ) : (\n <TokenListItemAvatar token={token} />\n )}\n </ListItemAvatar>\n <ListItemText\n primary={\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n {token.symbol}\n {!token.verified && (\n <Tooltip\n title={t('warning.message.unverifiedToken')}\n placement=\"top\"\n arrow\n >\n <WarningRounded\n sx={{\n display: 'flex',\n fontSize: 16,\n color: 'warning.main',\n cursor: 'help',\n }}\n />\n </Tooltip>\n )}\n </Box>\n }\n slotProps={{\n secondary: {\n component: 'div',\n },\n }}\n secondary={\n withoutContractAddress ? (\n <Box\n ref={container}\n sx={{\n height: 20,\n display: 'flex',\n }}\n >\n <Box\n sx={{\n pt: 0.25,\n }}\n >\n {token.name}\n </Box>\n <Box\n sx={{\n position: 'relative',\n }}\n >\n <Slide\n direction=\"up\"\n in={showAddress}\n container={container.current}\n style={{\n position: 'absolute',\n }}\n appear={false}\n mountOnEnter\n >\n <Box>\n <OpenTokenDetailsButton\n tokenAddress={token.address}\n withoutContractAddress={withoutContractAddress}\n chainId={token.chainId}\n onClick={onShowTokenDetails}\n />\n <PinTokenButton\n chainId={token.chainId}\n tokenAddress={token.address}\n />\n </Box>\n </Slide>\n </Box>\n </Box>\n ) : (\n <Box\n ref={container}\n sx={{\n position: 'relative',\n height: 20,\n }}\n >\n <Slide\n direction=\"down\"\n in={!showAddress}\n container={container.current}\n style={{\n position: 'absolute',\n }}\n appear={false}\n >\n <Box\n sx={{\n pt: 0.25,\n }}\n >\n {token.name}\n </Box>\n </Slide>\n <Slide\n direction=\"up\"\n in={showAddress}\n container={container.current}\n style={{\n position: 'absolute',\n }}\n appear={false}\n mountOnEnter\n >\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 0.5,\n }}\n >\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n pt: 0.125,\n }}\n >\n {shortenAddress(token.address)}\n </Box>\n <Box>\n <OpenTokenDetailsButton\n tokenAddress={token.address}\n withoutContractAddress={withoutContractAddress}\n chainId={token.chainId}\n onClick={onShowTokenDetails}\n />\n <PinTokenButton\n chainId={token.chainId}\n tokenAddress={token.address}\n />\n </Box>\n </Box>\n </Slide>\n </Box>\n )\n }\n />\n {isBalanceLoading ? (\n <TokenAmountSkeleton />\n ) : (\n <Box sx={{ textAlign: 'right' }}>\n {token.amount ? (\n <Typography\n noWrap\n sx={{\n fontWeight: 600,\n }}\n title={tokenAmount}\n >\n {t('format.tokenAmount', {\n value: tokenAmount,\n })}\n </Typography>\n ) : null}\n {token.amount && token.priceUSD ? (\n <Typography\n data-price={token.priceUSD}\n sx={{\n fontWeight: 500,\n fontSize: 12,\n color: 'text.secondary',\n }}\n >\n {t('format.currency', {\n value: tokenPrice,\n })}\n </Typography>\n ) : null}\n </Box>\n )}\n </ListItemButton>\n )\n }\n)\n\nexport const TokenListItemSkeleton = (): JSX.Element => {\n return (\n <ListItem\n secondaryAction={<TokenAmountSkeleton />}\n disablePadding\n sx={(theme) => ({\n position: 'relative',\n flexDirection: 'row',\n alignItems: 'center',\n padding: 0,\n [`& .${listItemSecondaryActionClasses.root}`]: {\n right: theme.spacing(1.5),\n },\n })}\n >\n <ListItemAvatar>\n <Skeleton\n variant=\"circular\"\n width={40}\n height={40}\n sx={{ marginLeft: 1.5, marginRight: 2 }}\n />\n </ListItemAvatar>\n <ListItemText\n primary={<Skeleton variant=\"text\" width={56} height={24} />}\n secondary={<Skeleton variant=\"text\" width={96} height={16} />}\n />\n </ListItem>\n )\n}\n\nconst TokenAmountSkeleton: React.FC = () => {\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-end',\n }}\n >\n <Skeleton variant=\"text\" width={56} height={24} />\n <Skeleton variant=\"text\" width={48} height={16} />\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualizedTokenList.js","names":["List"],"sources":["../../../../src/components/TokenList/VirtualizedTokenList.tsx"],"sourcesContent":["import { Typography } from '@mui/material'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport type { FC } from 'react'\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport type { TokenAmount } from '../../types/token.js'\nimport { TokenDetailsSheet } from './TokenDetailsSheet.js'\nimport { List } from './TokenList.style.js'\nimport { TokenListItem, TokenListItemSkeleton } from './TokenListItem.js'\nimport type {\n TokenDetailsSheetBase,\n VirtualizedTokenListProps,\n} from './types.js'\n\nconst tokenItemHeight = 64 // 60 + 4px margin-bottom\n\nexport const VirtualizedTokenList: FC<VirtualizedTokenListProps> = ({\n tokens,\n scrollElementRef,\n chainId,\n selectedTokenAddress,\n isLoading,\n isBalanceLoading,\n showCategories,\n showPinnedTokens,\n onClick,\n isAllNetworks,\n}) => {\n const { t } = useTranslation()\n\n const { chains } = useAvailableChains()\n\n // Create Set for O(1) chain lookup instead of O(n) find\n const chainsSet = useMemo(() => {\n if (!chains) {\n return undefined\n }\n return new Map(chains.map((chain) => [chain.id, chain]))\n }, [chains])\n\n const tokenDetailsSheetRef = useRef<TokenDetailsSheetBase>(null)\n\n const onShowTokenDetails = useCallback(\n (tokenAddress: string, noContractAddress: boolean, chainId: number) => {\n tokenDetailsSheetRef.current?.open(\n tokenAddress,\n noContractAddress,\n chainId\n )\n },\n []\n )\n\n const getItemKey = useCallback(\n (index: number) => {\n const token = tokens[index]\n return `${token.chainId}-${token.address}-${index}`\n },\n [tokens]\n )\n\n const estimateSize = useCallback(\n (index: number) => {\n const currentToken = tokens[index]\n const previousToken = tokens[index - 1]\n let size = tokenItemHeight\n\n // Pinned tokens (always shown, even in all networks mode)\n if (currentToken.pinned && index === 0) {\n size += 24\n }\n if (previousToken?.pinned && !currentToken.pinned) {\n size += 32\n }\n\n if (!showCategories) {\n return size\n }\n\n if (currentToken.featured && !currentToken.pinned && index === 0) {\n size += 24\n }\n\n // Category transition (excluding pinned tokens)\n const isNotPinned = !currentToken.pinned && !previousToken?.pinned\n if (\n isNotPinned &&\n ((previousToken?.amount && !currentToken.amount) ||\n (previousToken?.featured && !currentToken.featured) ||\n (previousToken?.popular && !currentToken.popular))\n ) {\n size += 32\n }\n\n return size\n },\n [tokens, showCategories]\n )\n\n const virtualizerConfig = useMemo(\n () => ({\n count: tokens.length,\n overscan: 5,\n getScrollElement: () => scrollElementRef.current,\n estimateSize,\n getItemKey,\n }),\n [tokens.length, estimateSize, getItemKey, scrollElementRef]\n )\n\n const { getVirtualItems, getTotalSize, scrollToIndex, measure } =\n useVirtualizer(virtualizerConfig)\n\n // Address the issue of disappearing tokens on rerender\n useEffect(() => {\n if (scrollElementRef.current) {\n measure()\n }\n }, [measure, scrollElementRef.current])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when chainId changes\n useEffect(() => {\n // Scroll to the top of the list when switching the chains\n if (getVirtualItems().length) {\n scrollToIndex(0, { align: 'start' })\n }\n // Close the token details sheet when switching the chains\n tokenDetailsSheetRef.current?.close()\n }, [scrollToIndex, isAllNetworks, chainId, getVirtualItems])\n\n return (\n <>\n <List\n className=\"long-list\"\n style={{ height: getTotalSize() }}\n disablePadding\n >\n {getVirtualItems().map((item) => {\n const currentToken = tokens[item.index]\n const previousToken: TokenAmount | undefined = tokens[item.index - 1]\n const chain = chainsSet?.get(currentToken.chainId)\n\n const isNotPinned = !currentToken.pinned\n const isFirstPinnedToken = currentToken.pinned && item.index === 0\n const isTransitionFromPinned = previousToken?.pinned && isNotPinned\n\n // Category transitions (excluding pinned)\n const isTransitionFromFeatured =\n previousToken?.featured && !currentToken.featured && isNotPinned\n const isTransitionFromMyTokens =\n previousToken?.amount && !currentToken.amount && isNotPinned\n const isTransitionFromPopular =\n previousToken?.popular && !currentToken.popular && isNotPinned\n\n // Determine which category label to show\n const startAdornmentLabel = (() => {\n if (showPinnedTokens && isFirstPinnedToken) {\n return t('main.pinnedTokens')\n }\n if (showPinnedTokens && !showCategories && isTransitionFromPinned) {\n return t('main.allTokens')\n }\n if (!showCategories) {\n return null\n }\n\n if (\n (isTransitionFromPinned && currentToken.featured) ||\n (currentToken.featured && isNotPinned && item.index === 0)\n ) {\n return t('main.featuredTokens')\n }\n if (\n (isTransitionFromFeatured || isTransitionFromPinned) &&\n currentToken.amount &&\n isNotPinned\n ) {\n return t('main.myTokens')\n }\n if (\n (isTransitionFromFeatured ||\n isTransitionFromMyTokens ||\n isTransitionFromPinned) &&\n currentToken.popular &&\n isNotPinned\n ) {\n return t('main.popularTokens')\n }\n if (\n isTransitionFromMyTokens ||\n isTransitionFromFeatured ||\n isTransitionFromPinned ||\n isTransitionFromPopular\n ) {\n return t('main.allTokens')\n }\n return null\n })()\n\n const isSelected =\n selectedTokenAddress === currentToken.address &&\n chainId === currentToken.chainId\n\n return (\n <TokenListItem\n key={item.key}\n onClick={onClick}\n size={item.size}\n start={item.start}\n token={currentToken}\n chain={isAllNetworks ? chain : undefined}\n selected={isSelected}\n onShowTokenDetails={onShowTokenDetails}\n isBalanceLoading={isBalanceLoading}\n startAdornment={\n startAdornmentLabel ? (\n <Typography\n sx={{\n fontSize: 14,\n fontWeight: 600,\n lineHeight: '16px',\n px: 1.5,\n pt:\n isFirstPinnedToken ||\n (currentToken.featured &&\n isNotPinned &&\n item.index === 0)\n ? 0\n : 1,\n pb: 1,\n }}\n >\n {startAdornmentLabel}\n </Typography>\n ) : null\n }\n />\n )\n })}\n </List>\n <TokenDetailsSheet ref={tokenDetailsSheetRef} />\n {isLoading && (\n <List disablePadding sx={{ cursor: 'default' }}>\n {Array.from({ length: 3 }).map((_, index) => (\n <TokenListItemSkeleton key={index} />\n ))}\n </List>\n )}\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VirtualizedTokenList.js","names":["List"],"sources":["../../../../src/components/TokenList/VirtualizedTokenList.tsx"],"sourcesContent":["import { Typography } from '@mui/material'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport type { FC } from 'react'\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport type { TokenAmount } from '../../types/token.js'\nimport { TokenDetailsSheet } from './TokenDetailsSheet.js'\nimport { List } from './TokenList.style.js'\nimport { TokenListItem, TokenListItemSkeleton } from './TokenListItem.js'\nimport type {\n TokenDetailsSheetBase,\n VirtualizedTokenListProps,\n} from './types.js'\n\nconst tokenItemHeight = 64 // 60 + 4px margin-bottom\n\nexport const VirtualizedTokenList: FC<VirtualizedTokenListProps> = ({\n tokens,\n scrollElementRef,\n chainId,\n selectedTokenAddress,\n isLoading,\n isBalanceLoading,\n showCategories,\n showPinnedTokens,\n onClick,\n isAllNetworks,\n}) => {\n const { t } = useTranslation()\n\n const { chains } = useAvailableChains()\n\n // Create Set for O(1) chain lookup instead of O(n) find\n const chainsSet = useMemo(() => {\n if (!chains) {\n return undefined\n }\n return new Map(chains.map((chain) => [chain.id, chain]))\n }, [chains])\n\n const tokenDetailsSheetRef = useRef<TokenDetailsSheetBase>(null)\n\n const onShowTokenDetails = useCallback(\n (tokenAddress: string, noContractAddress: boolean, chainId: number) => {\n tokenDetailsSheetRef.current?.open(\n tokenAddress,\n noContractAddress,\n chainId\n )\n },\n []\n )\n\n const getItemKey = useCallback(\n (index: number) => {\n const token = tokens[index]\n return `${token.chainId}-${token.address}-${index}`\n },\n [tokens]\n )\n\n const estimateSize = useCallback(\n (index: number) => {\n const currentToken = tokens[index]\n const previousToken = tokens[index - 1]\n let size = tokenItemHeight\n\n // Pinned tokens (always shown, even in all networks mode)\n if (currentToken.pinned && index === 0) {\n size += 24\n }\n if (previousToken?.pinned && !currentToken.pinned) {\n size += 32\n }\n\n if (!showCategories) {\n return size\n }\n\n if (currentToken.featured && !currentToken.pinned && index === 0) {\n size += 24\n }\n\n // Category transition (excluding pinned tokens)\n const isNotPinned = !currentToken.pinned && !previousToken?.pinned\n if (\n isNotPinned &&\n ((previousToken?.amount && !currentToken.amount) ||\n (previousToken?.featured && !currentToken.featured) ||\n (previousToken?.popular && !currentToken.popular))\n ) {\n size += 32\n }\n\n return size\n },\n [tokens, showCategories]\n )\n\n const virtualizerConfig = useMemo(\n () => ({\n count: tokens.length,\n overscan: 5,\n getScrollElement: () => scrollElementRef.current,\n estimateSize,\n getItemKey,\n }),\n [tokens.length, estimateSize, getItemKey, scrollElementRef]\n )\n\n const { getVirtualItems, getTotalSize, scrollToIndex, measure } =\n useVirtualizer(virtualizerConfig)\n\n // Address the issue of disappearing tokens on rerender\n useEffect(() => {\n if (scrollElementRef.current) {\n measure()\n }\n }, [measure, scrollElementRef.current])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when chainId changes\n useEffect(() => {\n // Scroll to the top of the list when switching the chains\n if (getVirtualItems().length) {\n scrollToIndex(0, { align: 'start' })\n }\n // Close the token details sheet when switching the chains\n tokenDetailsSheetRef.current?.close()\n }, [scrollToIndex, isAllNetworks, chainId, getVirtualItems])\n\n return (\n <>\n <List\n className=\"long-list\"\n style={{ height: getTotalSize() }}\n disablePadding\n >\n {getVirtualItems().map((item) => {\n const currentToken = tokens[item.index]\n const previousToken: TokenAmount | undefined = tokens[item.index - 1]\n const chain = chainsSet?.get(currentToken.chainId)\n\n const isNotPinned = !currentToken.pinned\n const isFirstPinnedToken = currentToken.pinned && item.index === 0\n const isTransitionFromPinned = previousToken?.pinned && isNotPinned\n\n // Category transitions (excluding pinned)\n const isTransitionFromFeatured =\n previousToken?.featured && !currentToken.featured && isNotPinned\n const isTransitionFromMyTokens =\n previousToken?.amount && !currentToken.amount && isNotPinned\n const isTransitionFromPopular =\n previousToken?.popular && !currentToken.popular && isNotPinned\n\n // Determine which category label to show\n const startAdornmentLabel = (() => {\n if (showPinnedTokens && isFirstPinnedToken) {\n return t('main.pinnedTokens')\n }\n if (showPinnedTokens && !showCategories && isTransitionFromPinned) {\n return t('main.allTokens')\n }\n if (!showCategories) {\n return null\n }\n\n if (\n (isTransitionFromPinned && currentToken.featured) ||\n (currentToken.featured && isNotPinned && item.index === 0)\n ) {\n return t('main.featuredTokens')\n }\n if (\n (isTransitionFromFeatured || isTransitionFromPinned) &&\n currentToken.amount &&\n isNotPinned\n ) {\n return t('main.myTokens')\n }\n if (\n (isTransitionFromFeatured ||\n isTransitionFromMyTokens ||\n isTransitionFromPinned) &&\n currentToken.popular &&\n isNotPinned\n ) {\n return t('main.popularTokens')\n }\n if (\n isTransitionFromMyTokens ||\n isTransitionFromFeatured ||\n isTransitionFromPinned ||\n isTransitionFromPopular\n ) {\n return t('main.allTokens')\n }\n return null\n })()\n\n const isSelected =\n selectedTokenAddress === currentToken.address &&\n chainId === currentToken.chainId\n\n return (\n <TokenListItem\n key={item.key}\n onClick={onClick}\n size={item.size}\n start={item.start}\n token={currentToken}\n chain={isAllNetworks ? chain : undefined}\n selected={isSelected}\n onShowTokenDetails={onShowTokenDetails}\n isBalanceLoading={isBalanceLoading}\n startAdornment={\n startAdornmentLabel ? (\n <Typography\n sx={{\n fontSize: 14,\n fontWeight: 600,\n lineHeight: '16px',\n px: 1.5,\n pt:\n isFirstPinnedToken ||\n (currentToken.featured &&\n isNotPinned &&\n item.index === 0)\n ? 0\n : 1,\n pb: 1,\n }}\n >\n {startAdornmentLabel}\n </Typography>\n ) : null\n }\n />\n )\n })}\n </List>\n <TokenDetailsSheet ref={tokenDetailsSheetRef} />\n {isLoading && (\n <List disablePadding sx={{ cursor: 'default' }}>\n {Array.from({ length: 3 }).map((_, index) => (\n <TokenListItemSkeleton key={index} />\n ))}\n </List>\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;;;;AAeA,MAAM,kBAAkB;AAExB,MAAa,wBAAuD,EAClE,QACA,kBACA,SACA,sBACA,WACA,kBACA,gBACA,kBACA,SACA,oBACI;CACJ,MAAM,EAAE,MAAM,gBAAgB;CAE9B,MAAM,EAAE,WAAW,oBAAoB;CAGvC,MAAM,YAAY,cAAc;AAC9B,MAAI,CAAC,OACH;AAEF,SAAO,IAAI,IAAI,OAAO,KAAK,UAAU,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IACvD,CAAC,OAAO,CAAC;CAEZ,MAAM,uBAAuB,OAA8B,KAAK;CAEhE,MAAM,qBAAqB,aACxB,cAAsB,mBAA4B,YAAoB;AACrE,uBAAqB,SAAS,KAC5B,cACA,mBACA,QACD;IAEH,EAAE,CACH;CAED,MAAM,aAAa,aAChB,UAAkB;EACjB,MAAM,QAAQ,OAAO;AACrB,SAAO,GAAG,MAAM,QAAQ,GAAG,MAAM,QAAQ,GAAG;IAE9C,CAAC,OAAO,CACT;CAED,MAAM,eAAe,aAClB,UAAkB;EACjB,MAAM,eAAe,OAAO;EAC5B,MAAM,gBAAgB,OAAO,QAAQ;EACrC,IAAI,OAAO;AAGX,MAAI,aAAa,UAAU,UAAU,EACnC,SAAQ;AAEV,MAAI,eAAe,UAAU,CAAC,aAAa,OACzC,SAAQ;AAGV,MAAI,CAAC,eACH,QAAO;AAGT,MAAI,aAAa,YAAY,CAAC,aAAa,UAAU,UAAU,EAC7D,SAAQ;AAKV,MADoB,CAAC,aAAa,UAAU,CAAC,eAAe,WAGxD,eAAe,UAAU,CAAC,aAAa,UACtC,eAAe,YAAY,CAAC,aAAa,YACzC,eAAe,WAAW,CAAC,aAAa,SAE3C,SAAQ;AAGV,SAAO;IAET,CAAC,QAAQ,eAAe,CACzB;CAaD,MAAM,EAAE,iBAAiB,cAAc,eAAe,YACpD,eAZwB,eACjB;EACL,OAAO,OAAO;EACd,UAAU;EACV,wBAAwB,iBAAiB;EACzC;EACA;EACD,GACD;EAAC,OAAO;EAAQ;EAAc;EAAY;EAAiB,CAI3B,CAAC;AAGnC,iBAAgB;AACd,MAAI,iBAAiB,QACnB,UAAS;IAEV,CAAC,SAAS,iBAAiB,QAAQ,CAAC;AAGvC,iBAAgB;AAEd,MAAI,iBAAiB,CAAC,OACpB,eAAc,GAAG,EAAE,OAAO,SAAS,CAAC;AAGtC,uBAAqB,SAAS,OAAO;IACpC;EAAC;EAAe;EAAe;EAAS;EAAgB,CAAC;AAE5D,QACE,qBAAA,YAAA,EAAA,UAAA;EACE,oBAACA,QAAD;GACE,WAAU;GACV,OAAO,EAAE,QAAQ,cAAc,EAAE;GACjC,gBAAA;aAEC,iBAAiB,CAAC,KAAK,SAAS;IAC/B,MAAM,eAAe,OAAO,KAAK;IACjC,MAAM,gBAAyC,OAAO,KAAK,QAAQ;IACnE,MAAM,QAAQ,WAAW,IAAI,aAAa,QAAQ;IAElD,MAAM,cAAc,CAAC,aAAa;IAClC,MAAM,qBAAqB,aAAa,UAAU,KAAK,UAAU;IACjE,MAAM,yBAAyB,eAAe,UAAU;IAGxD,MAAM,2BACJ,eAAe,YAAY,CAAC,aAAa,YAAY;IACvD,MAAM,2BACJ,eAAe,UAAU,CAAC,aAAa,UAAU;IACnD,MAAM,0BACJ,eAAe,WAAW,CAAC,aAAa,WAAW;IAGrD,MAAM,6BAA6B;AACjC,SAAI,oBAAoB,mBACtB,QAAO,EAAE,oBAAoB;AAE/B,SAAI,oBAAoB,CAAC,kBAAkB,uBACzC,QAAO,EAAE,iBAAiB;AAE5B,SAAI,CAAC,eACH,QAAO;AAGT,SACG,0BAA0B,aAAa,YACvC,aAAa,YAAY,eAAe,KAAK,UAAU,EAExD,QAAO,EAAE,sBAAsB;AAEjC,UACG,4BAA4B,2BAC7B,aAAa,UACb,YAEA,QAAO,EAAE,gBAAgB;AAE3B,UACG,4BACC,4BACA,2BACF,aAAa,WACb,YAEA,QAAO,EAAE,qBAAqB;AAEhC,SACE,4BACA,4BACA,0BACA,wBAEA,QAAO,EAAE,iBAAiB;AAE5B,YAAO;QACL;IAEJ,MAAM,aACJ,yBAAyB,aAAa,WACtC,YAAY,aAAa;AAE3B,WACE,oBAAC,eAAD;KAEW;KACT,MAAM,KAAK;KACX,OAAO,KAAK;KACZ,OAAO;KACP,OAAO,gBAAgB,QAAQ,KAAA;KAC/B,UAAU;KACU;KACF;KAClB,gBACE,sBACE,oBAAC,YAAD;MACE,IAAI;OACF,UAAU;OACV,YAAY;OACZ,YAAY;OACZ,IAAI;OACJ,IACE,sBACC,aAAa,YACZ,eACA,KAAK,UAAU,IACb,IACA;OACN,IAAI;OACL;gBAEA;MACU,CAAA,GACX;KAEN,EA/BK,KAAK,IA+BV;KAEJ;GACG,CAAA;EACP,oBAAC,mBAAD,EAAmB,KAAK,sBAAwB,CAAA;EAC/C,aACC,oBAACA,QAAD;GAAM,gBAAA;GAAe,IAAI,EAAE,QAAQ,WAAW;aAC3C,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,UACjC,oBAAC,uBAAD,EAAqC,EAAT,MAAS,CACrC;GACG,CAAA;EAER,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActiveTransactionCard.js","names":["Card"],"sources":["../../../../src/components/TransactionCard/ActiveTransactionCard.tsx"],"sourcesContent":["import type { RouteExtended } from '@lifi/sdk'\nimport DeleteOutline from '@mui/icons-material/DeleteOutlined'\nimport { Box, Tooltip, Typography } from '@mui/material'\nimport type { JSX, MouseEvent } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useActionMessage } from '../../hooks/useActionMessage.js'\nimport { RouteExecutionStatus } from '../../stores/routes/types.js'\nimport { Card } from '../Card/Card.js'\nimport { IconCircle } from '../IconCircle/IconCircle.js'\nimport { RouteTokens } from '../RouteCard/RouteTokens.js'\nimport { CircularProgressPending } from '../Step/CircularProgress.style.js'\nimport { ExecutionTimerText, getExpiryTimestamp } from '../Timer/StepTimer.js'\nimport {\n DeleteButton,\n PendingCircle,\n StatusRow,\n} from './ActiveTransactionCard.style.js'\n\ninterface ActiveTransactionCardProps {\n route: RouteExtended\n status?: RouteExecutionStatus\n onClick: () => void\n onDelete: (e: MouseEvent) => void\n}\n\nexport const ActiveTransactionCard = ({\n route,\n status,\n onClick,\n onDelete,\n}: ActiveTransactionCardProps): JSX.Element => {\n const { t } = useTranslation()\n\n const lastActiveStep = route.steps.findLast((step) => step.execution)\n const lastActiveAction = lastActiveStep?.execution?.actions?.at(-1)\n const { title } = useActionMessage(lastActiveStep, lastActiveAction)\n\n const isFailed = status === RouteExecutionStatus.Failed\n\n const statusIcon = (() => {\n if (isFailed) {\n return <IconCircle status=\"error\" size={24} />\n }\n if (\n ['ACTION_REQUIRED', 'MESSAGE_REQUIRED', 'RESET_REQUIRED'].includes(\n lastActiveAction?.status ?? ''\n )\n ) {\n return <IconCircle status=\"info\" size={24} />\n }\n return (\n <PendingCircle>\n <CircularProgressPending size={24} sx={{ top: -2, left: -2 }} />\n </PendingCircle>\n )\n })()\n\n return (\n <Card onClick={onClick} indented>\n <StatusRow sx={{ mb: 1.5 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>\n {statusIcon}\n <Typography sx={{ fontSize: 12, fontWeight: 500 }}>\n {title}\n </Typography>\n </Box>\n {isFailed ? (\n <Tooltip title={t('button.clearTransaction')}>\n <DeleteButton size=\"small\" onClick={onDelete}>\n <DeleteOutline sx={{ fontSize: 16 }} />\n </DeleteButton>\n </Tooltip>\n ) : lastActiveStep?.execution?.signedAt ? (\n <Typography sx={{ fontSize: 12, fontWeight: 600 }}>\n <ExecutionTimerText\n expiryTimestamp={getExpiryTimestamp(lastActiveStep)}\n />\n </Typography>\n ) : null}\n </StatusRow>\n <RouteTokens route={route} />\n </Card>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAyBA,MAAa,yBAAyB,EACpC,OACA,QACA,SACA,eAC6C;CAC7C,MAAM,EAAE,MAAM,gBAAgB;CAE9B,MAAM,iBAAiB,MAAM,MAAM,UAAU,SAAS,KAAK,UAAU;CACrE,MAAM,mBAAmB,gBAAgB,WAAW,SAAS,GAAG,GAAG;CACnE,MAAM,EAAE,UAAU,iBAAiB,gBAAgB,iBAAiB;CAEpE,MAAM,WAAW,WAAA;AAoBjB,QACE,qBAACA,QAAD;EAAe;EAAS,UAAA;YAAxB,CACE,qBAAC,WAAD;GAAW,IAAI,EAAE,IAAI,KAAK;aAA1B,CACE,qBAAC,KAAD;IAAK,IAAI;KAAE,SAAS;KAAQ,YAAY;KAAU,KAAK;KAAK;cAA5D,QArBoB;AACxB,SAAI,SACF,QAAO,oBAAC,YAAD;MAAY,QAAO;MAAQ,MAAM;MAAM,CAAA;AAEhD,SACE;MAAC;MAAmB;MAAoB;MAAiB,CAAC,SACxD,kBAAkB,UAAU,GAC7B,CAED,QAAO,oBAAC,YAAD;MAAY,QAAO;MAAO,MAAM;MAAM,CAAA;AAE/C,YACE,oBAAC,eAAD,EAAA,UACE,oBAAC,yBAAD;MAAyB,MAAM;MAAI,IAAI;OAAE,KAAK;OAAI,MAAM;OAAI;MAAI,CAAA,EAClD,CAAA;
|
|
1
|
+
{"version":3,"file":"ActiveTransactionCard.js","names":["Card"],"sources":["../../../../src/components/TransactionCard/ActiveTransactionCard.tsx"],"sourcesContent":["import type { RouteExtended } from '@lifi/sdk'\nimport DeleteOutline from '@mui/icons-material/DeleteOutlined'\nimport { Box, Tooltip, Typography } from '@mui/material'\nimport type { JSX, MouseEvent } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useActionMessage } from '../../hooks/useActionMessage.js'\nimport { RouteExecutionStatus } from '../../stores/routes/types.js'\nimport { Card } from '../Card/Card.js'\nimport { IconCircle } from '../IconCircle/IconCircle.js'\nimport { RouteTokens } from '../RouteCard/RouteTokens.js'\nimport { CircularProgressPending } from '../Step/CircularProgress.style.js'\nimport { ExecutionTimerText, getExpiryTimestamp } from '../Timer/StepTimer.js'\nimport {\n DeleteButton,\n PendingCircle,\n StatusRow,\n} from './ActiveTransactionCard.style.js'\n\ninterface ActiveTransactionCardProps {\n route: RouteExtended\n status?: RouteExecutionStatus\n onClick: () => void\n onDelete: (e: MouseEvent) => void\n}\n\nexport const ActiveTransactionCard = ({\n route,\n status,\n onClick,\n onDelete,\n}: ActiveTransactionCardProps): JSX.Element => {\n const { t } = useTranslation()\n\n const lastActiveStep = route.steps.findLast((step) => step.execution)\n const lastActiveAction = lastActiveStep?.execution?.actions?.at(-1)\n const { title } = useActionMessage(lastActiveStep, lastActiveAction)\n\n const isFailed = status === RouteExecutionStatus.Failed\n\n const statusIcon = (() => {\n if (isFailed) {\n return <IconCircle status=\"error\" size={24} />\n }\n if (\n ['ACTION_REQUIRED', 'MESSAGE_REQUIRED', 'RESET_REQUIRED'].includes(\n lastActiveAction?.status ?? ''\n )\n ) {\n return <IconCircle status=\"info\" size={24} />\n }\n return (\n <PendingCircle>\n <CircularProgressPending size={24} sx={{ top: -2, left: -2 }} />\n </PendingCircle>\n )\n })()\n\n return (\n <Card onClick={onClick} indented>\n <StatusRow sx={{ mb: 1.5 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>\n {statusIcon}\n <Typography sx={{ fontSize: 12, fontWeight: 500 }}>\n {title}\n </Typography>\n </Box>\n {isFailed ? (\n <Tooltip title={t('button.clearTransaction')}>\n <DeleteButton size=\"small\" onClick={onDelete}>\n <DeleteOutline sx={{ fontSize: 16 }} />\n </DeleteButton>\n </Tooltip>\n ) : lastActiveStep?.execution?.signedAt ? (\n <Typography sx={{ fontSize: 12, fontWeight: 600 }}>\n <ExecutionTimerText\n expiryTimestamp={getExpiryTimestamp(lastActiveStep)}\n />\n </Typography>\n ) : null}\n </StatusRow>\n <RouteTokens route={route} />\n </Card>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAyBA,MAAa,yBAAyB,EACpC,OACA,QACA,SACA,eAC6C;CAC7C,MAAM,EAAE,MAAM,gBAAgB;CAE9B,MAAM,iBAAiB,MAAM,MAAM,UAAU,SAAS,KAAK,UAAU;CACrE,MAAM,mBAAmB,gBAAgB,WAAW,SAAS,GAAG,GAAG;CACnE,MAAM,EAAE,UAAU,iBAAiB,gBAAgB,iBAAiB;CAEpE,MAAM,WAAW,WAAA;AAoBjB,QACE,qBAACA,QAAD;EAAe;EAAS,UAAA;YAAxB,CACE,qBAAC,WAAD;GAAW,IAAI,EAAE,IAAI,KAAK;aAA1B,CACE,qBAAC,KAAD;IAAK,IAAI;KAAE,SAAS;KAAQ,YAAY;KAAU,KAAK;KAAK;cAA5D,QArBoB;AACxB,SAAI,SACF,QAAO,oBAAC,YAAD;MAAY,QAAO;MAAQ,MAAM;MAAM,CAAA;AAEhD,SACE;MAAC;MAAmB;MAAoB;MAAiB,CAAC,SACxD,kBAAkB,UAAU,GAC7B,CAED,QAAO,oBAAC,YAAD;MAAY,QAAO;MAAO,MAAM;MAAM,CAAA;AAE/C,YACE,oBAAC,eAAD,EAAA,UACE,oBAAC,yBAAD;MAAyB,MAAM;MAAI,IAAI;OAAE,KAAK;OAAI,MAAM;OAAI;MAAI,CAAA,EAClD,CAAA;QAQD,EACX,oBAAC,YAAD;KAAY,IAAI;MAAE,UAAU;MAAI,YAAY;MAAK;eAC9C;KACU,CAAA,CACT;OACL,WACC,oBAAC,SAAD;IAAS,OAAO,EAAE,0BAA0B;cAC1C,oBAAC,cAAD;KAAc,MAAK;KAAQ,SAAS;eAClC,oBAAC,eAAD,EAAe,IAAI,EAAE,UAAU,IAAI,EAAI,CAAA;KAC1B,CAAA;IACP,CAAA,GACR,gBAAgB,WAAW,WAC7B,oBAAC,YAAD;IAAY,IAAI;KAAE,UAAU;KAAI,YAAY;KAAK;cAC/C,oBAAC,oBAAD,EACE,iBAAiB,mBAAmB,eAAe,EACnD,CAAA;IACS,CAAA,GACX,KACM;MACZ,oBAAC,aAAD,EAAoB,OAAS,CAAA,CACxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.0.0-beta.
|
|
1
|
+
{"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.0.0-beta.18'\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.js","names":[],"sources":["../../../../src/hooks/timer/time.ts"],"sourcesContent":["export type TimeFromMillisecondsType = {\n totalMilliseconds: number\n totalSeconds: number\n milliseconds: number\n seconds: number\n minutes: number\n hours: number\n days: number\n}\n\nexport function getTimeFromMilliseconds(\n millisecs: number,\n isCountDown = true\n): TimeFromMillisecondsType {\n const totalSeconds = isCountDown\n ? Math.ceil(millisecs / 1000)\n : Math.floor(millisecs / 1000)\n const days = Math.floor(totalSeconds / (60 * 60 * 24))\n const hours = Math.floor((totalSeconds % (60 * 60 * 24)) / (60 * 60))\n const minutes = Math.floor((totalSeconds % (60 * 60)) / 60)\n const seconds = Math.floor(totalSeconds % 60)\n const milliseconds = Math.floor(millisecs % 1000)\n\n return {\n totalMilliseconds: millisecs,\n totalSeconds,\n milliseconds,\n seconds,\n minutes,\n hours,\n days,\n }\n}\n\nexport function getMillisecondsFromExpiry(expiry: Date): number {\n const now = Date.now()\n const milliSecondsDistance = expiry?.getTime() - now\n return milliSecondsDistance > 0 ? milliSecondsDistance : 0\n}\n"],"mappings":";AAUA,SAAgB,wBACd,WACA,cAAc,MACY;CAC1B,MAAM,eAAe,cACjB,KAAK,KAAK,YAAY,IAAK,GAC3B,KAAK,MAAM,YAAY,IAAK;CAChC,MAAM,OAAO,KAAK,MAAM,gBAAgB,OAAU,IAAI;CACtD,MAAM,QAAQ,KAAK,MAAO,gBAAgB,OAAU,MAAQ,KAAS;CACrE,MAAM,UAAU,KAAK,MAAO,eAAgB,OAAY,GAAG;CAC3D,MAAM,UAAU,KAAK,MAAM,eAAe,GAAG;AAG7C,QAAO;EACL,mBAAmB;EACnB;EACA,cALmB,KAAK,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"time.js","names":[],"sources":["../../../../src/hooks/timer/time.ts"],"sourcesContent":["export type TimeFromMillisecondsType = {\n totalMilliseconds: number\n totalSeconds: number\n milliseconds: number\n seconds: number\n minutes: number\n hours: number\n days: number\n}\n\nexport function getTimeFromMilliseconds(\n millisecs: number,\n isCountDown = true\n): TimeFromMillisecondsType {\n const totalSeconds = isCountDown\n ? Math.ceil(millisecs / 1000)\n : Math.floor(millisecs / 1000)\n const days = Math.floor(totalSeconds / (60 * 60 * 24))\n const hours = Math.floor((totalSeconds % (60 * 60 * 24)) / (60 * 60))\n const minutes = Math.floor((totalSeconds % (60 * 60)) / 60)\n const seconds = Math.floor(totalSeconds % 60)\n const milliseconds = Math.floor(millisecs % 1000)\n\n return {\n totalMilliseconds: millisecs,\n totalSeconds,\n milliseconds,\n seconds,\n minutes,\n hours,\n days,\n }\n}\n\nexport function getMillisecondsFromExpiry(expiry: Date): number {\n const now = Date.now()\n const milliSecondsDistance = expiry?.getTime() - now\n return milliSecondsDistance > 0 ? milliSecondsDistance : 0\n}\n"],"mappings":";AAUA,SAAgB,wBACd,WACA,cAAc,MACY;CAC1B,MAAM,eAAe,cACjB,KAAK,KAAK,YAAY,IAAK,GAC3B,KAAK,MAAM,YAAY,IAAK;CAChC,MAAM,OAAO,KAAK,MAAM,gBAAgB,OAAU,IAAI;CACtD,MAAM,QAAQ,KAAK,MAAO,gBAAgB,OAAU,MAAQ,KAAS;CACrE,MAAM,UAAU,KAAK,MAAO,eAAgB,OAAY,GAAG;CAC3D,MAAM,UAAU,KAAK,MAAM,eAAe,GAAG;AAG7C,QAAO;EACL,mBAAmB;EACnB;EACA,cALmB,KAAK,MAAM,YAAY,IAK9B;EACZ;EACA;EACA;EACA;EACD;;AAGH,SAAgB,0BAA0B,QAAsB;CAC9D,MAAM,MAAM,KAAK,KAAK;CACtB,MAAM,uBAAuB,QAAQ,SAAS,GAAG;AACjD,QAAO,uBAAuB,IAAI,uBAAuB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAccountsBalancesData.js","names":[],"sources":["../../../src/hooks/useAccountsBalancesData.ts"],"sourcesContent":["import type { ChainType, TokenExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport type { FormType } from '../stores/form/types.js'\nimport { useChains } from './useChains.js'\nimport { useFilteredTokensByBalance } from './useFilteredByTokenBalances.js'\n\nexport const useAccountsBalancesData = (\n selectedChainId?: number,\n formType?: FormType,\n isAllNetworks?: boolean,\n allTokens?: Record<number, TokenExtended[]>\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const { data: accountsWithTokens, isLoading: isAccountsLoading } =\n useAccountsData(selectedChainId, formType, isAllNetworks, allTokens)\n\n // Filter out EVM tokens that do not have balances\n const { data: filteredTokens, isLoading: isCachedBalancesLoading } =\n useFilteredTokensByBalance(accountsWithTokens, formType)\n\n return {\n data: filteredTokens,\n isLoading: isAccountsLoading || isCachedBalancesLoading,\n }\n}\n\nconst useAccountsData = (\n selectedChainId?: number,\n formType?: FormType,\n isAllNetworks?: boolean,\n allTokens?: Record<number, TokenExtended[]>\n) => {\n const {\n chains: allChains,\n isLoading: isChainsLoading,\n getChainById,\n } = useChains(formType)\n const currentChain = useMemo(() => {\n return selectedChainId\n ? getChainById(selectedChainId, allChains)\n : undefined\n }, [selectedChainId, allChains, getChainById])\n const chains = useMemo(() => {\n return isAllNetworks ? allChains : currentChain ? [currentChain] : undefined\n }, [allChains, isAllNetworks, currentChain])\n\n const { accounts: allAccounts, account: currentAccount } = useAccount(\n isAllNetworks ? undefined : { chainType: currentChain?.chainType }\n )\n const accounts = useMemo(() => {\n return isAllNetworks\n ? allAccounts\n : currentAccount\n ? [currentAccount]\n : undefined\n }, [allAccounts, currentAccount, isAllNetworks])\n\n const accountsWithTokens = useMemo(() => {\n if (!chains || !allTokens || !accounts?.length) {\n return undefined\n }\n return accounts\n ?.filter((account) => account.address)\n .reduce(\n (acc, account) => {\n if (account.address) {\n const accountChains = chains?.filter(\n (chain) => account.chainType === chain?.chainType\n )\n if (accountChains) {\n const chainIdSet = new Set(accountChains.map((chain) => chain.id))\n const filteredTokens = Object.entries(allTokens).reduce(\n (tokenAcc, [chainIdStr, tokens]) => {\n const chainId = Number(chainIdStr)\n if (chainIdSet.has(chainId)) {\n tokenAcc[chainId] = tokens\n }\n return tokenAcc\n },\n {} as { [chainId: number]: TokenExtended[] }\n )\n acc[account.address] = {\n chainType: account.chainType,\n tokens: filteredTokens,\n }\n }\n }\n return acc\n },\n {} as Record<\n string,\n { chainType: ChainType; tokens: Record<number, TokenExtended[]> }\n >\n )\n }, [accounts, chains, allTokens])\n\n return {\n data: accountsWithTokens,\n isLoading: isChainsLoading,\n }\n}\n"],"mappings":";;;;;AAOA,MAAa,2BACX,iBACA,UACA,eACA,cAIG;CACH,MAAM,EAAE,MAAM,oBAAoB,WAAW,sBAC3C,gBAAgB,iBAAiB,UAAU,eAAe,UAAU;CAGtE,MAAM,EAAE,MAAM,gBAAgB,WAAW,4BACvC,2BAA2B,oBAAoB,SAAS;AAE1D,QAAO;EACL,MAAM;EACN,WAAW,qBAAqB;EACjC;;AAGH,MAAM,mBACJ,iBACA,UACA,eACA,cACG;CACH,MAAM,EACJ,QAAQ,WACR,WAAW,iBACX,iBACE,UAAU,SAAS;CACvB,MAAM,eAAe,cAAc;AACjC,SAAO,kBACH,aAAa,iBAAiB,UAAU,GACxC,KAAA;IACH;EAAC;EAAiB;EAAW;EAAa,CAAC;CAC9C,MAAM,SAAS,cAAc;AAC3B,SAAO,gBAAgB,YAAY,eAAe,CAAC,aAAa,GAAG,KAAA;IAClE;EAAC;EAAW;EAAe;EAAa,CAAC;CAE5C,MAAM,EAAE,UAAU,aAAa,SAAS,mBAAmB,WACzD,gBAAgB,KAAA,IAAY,EAAE,WAAW,cAAc,WAAW,CACnE;CACD,MAAM,WAAW,cAAc;AAC7B,SAAO,gBACH,cACA,iBACE,CAAC,eAAe,GAChB,KAAA;IACL;EAAC;EAAa;EAAgB;EAAc,CAAC;AAyChD,QAAO;EACL,MAxCyB,cAAc;AACvC,OAAI,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,OACtC;AAEF,UAAO,UACH,QAAQ,YAAY,QAAQ,QAAQ,CACrC,QACE,KAAK,YAAY;AAChB,QAAI,QAAQ,SAAS;KACnB,MAAM,gBAAgB,QAAQ,QAC3B,UAAU,QAAQ,cAAc,OAAO,UACzC;AACD,SAAI,eAAe;MACjB,MAAM,aAAa,IAAI,IAAI,cAAc,KAAK,UAAU,MAAM,GAAG,CAAC;MAClE,MAAM,iBAAiB,OAAO,QAAQ,UAAU,CAAC,QAC9C,UAAU,CAAC,YAAY,YAAY;OAClC,MAAM,UAAU,OAAO,WAAW;AAClC,WAAI,WAAW,IAAI,QAAQ,CACzB,UAAS,WAAW;AAEtB,cAAO;SAET,EAAE,CACH;AACD,UAAI,QAAQ,WAAW;OACrB,WAAW,QAAQ;OACnB,QAAQ;OACT;;;AAGL,WAAO;MAET,EAAE,CAIH;KACF;GAAC;GAAU;GAAQ;GAAU,
|
|
1
|
+
{"version":3,"file":"useAccountsBalancesData.js","names":[],"sources":["../../../src/hooks/useAccountsBalancesData.ts"],"sourcesContent":["import type { ChainType, TokenExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport type { FormType } from '../stores/form/types.js'\nimport { useChains } from './useChains.js'\nimport { useFilteredTokensByBalance } from './useFilteredByTokenBalances.js'\n\nexport const useAccountsBalancesData = (\n selectedChainId?: number,\n formType?: FormType,\n isAllNetworks?: boolean,\n allTokens?: Record<number, TokenExtended[]>\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const { data: accountsWithTokens, isLoading: isAccountsLoading } =\n useAccountsData(selectedChainId, formType, isAllNetworks, allTokens)\n\n // Filter out EVM tokens that do not have balances\n const { data: filteredTokens, isLoading: isCachedBalancesLoading } =\n useFilteredTokensByBalance(accountsWithTokens, formType)\n\n return {\n data: filteredTokens,\n isLoading: isAccountsLoading || isCachedBalancesLoading,\n }\n}\n\nconst useAccountsData = (\n selectedChainId?: number,\n formType?: FormType,\n isAllNetworks?: boolean,\n allTokens?: Record<number, TokenExtended[]>\n) => {\n const {\n chains: allChains,\n isLoading: isChainsLoading,\n getChainById,\n } = useChains(formType)\n const currentChain = useMemo(() => {\n return selectedChainId\n ? getChainById(selectedChainId, allChains)\n : undefined\n }, [selectedChainId, allChains, getChainById])\n const chains = useMemo(() => {\n return isAllNetworks ? allChains : currentChain ? [currentChain] : undefined\n }, [allChains, isAllNetworks, currentChain])\n\n const { accounts: allAccounts, account: currentAccount } = useAccount(\n isAllNetworks ? undefined : { chainType: currentChain?.chainType }\n )\n const accounts = useMemo(() => {\n return isAllNetworks\n ? allAccounts\n : currentAccount\n ? [currentAccount]\n : undefined\n }, [allAccounts, currentAccount, isAllNetworks])\n\n const accountsWithTokens = useMemo(() => {\n if (!chains || !allTokens || !accounts?.length) {\n return undefined\n }\n return accounts\n ?.filter((account) => account.address)\n .reduce(\n (acc, account) => {\n if (account.address) {\n const accountChains = chains?.filter(\n (chain) => account.chainType === chain?.chainType\n )\n if (accountChains) {\n const chainIdSet = new Set(accountChains.map((chain) => chain.id))\n const filteredTokens = Object.entries(allTokens).reduce(\n (tokenAcc, [chainIdStr, tokens]) => {\n const chainId = Number(chainIdStr)\n if (chainIdSet.has(chainId)) {\n tokenAcc[chainId] = tokens\n }\n return tokenAcc\n },\n {} as { [chainId: number]: TokenExtended[] }\n )\n acc[account.address] = {\n chainType: account.chainType,\n tokens: filteredTokens,\n }\n }\n }\n return acc\n },\n {} as Record<\n string,\n { chainType: ChainType; tokens: Record<number, TokenExtended[]> }\n >\n )\n }, [accounts, chains, allTokens])\n\n return {\n data: accountsWithTokens,\n isLoading: isChainsLoading,\n }\n}\n"],"mappings":";;;;;AAOA,MAAa,2BACX,iBACA,UACA,eACA,cAIG;CACH,MAAM,EAAE,MAAM,oBAAoB,WAAW,sBAC3C,gBAAgB,iBAAiB,UAAU,eAAe,UAAU;CAGtE,MAAM,EAAE,MAAM,gBAAgB,WAAW,4BACvC,2BAA2B,oBAAoB,SAAS;AAE1D,QAAO;EACL,MAAM;EACN,WAAW,qBAAqB;EACjC;;AAGH,MAAM,mBACJ,iBACA,UACA,eACA,cACG;CACH,MAAM,EACJ,QAAQ,WACR,WAAW,iBACX,iBACE,UAAU,SAAS;CACvB,MAAM,eAAe,cAAc;AACjC,SAAO,kBACH,aAAa,iBAAiB,UAAU,GACxC,KAAA;IACH;EAAC;EAAiB;EAAW;EAAa,CAAC;CAC9C,MAAM,SAAS,cAAc;AAC3B,SAAO,gBAAgB,YAAY,eAAe,CAAC,aAAa,GAAG,KAAA;IAClE;EAAC;EAAW;EAAe;EAAa,CAAC;CAE5C,MAAM,EAAE,UAAU,aAAa,SAAS,mBAAmB,WACzD,gBAAgB,KAAA,IAAY,EAAE,WAAW,cAAc,WAAW,CACnE;CACD,MAAM,WAAW,cAAc;AAC7B,SAAO,gBACH,cACA,iBACE,CAAC,eAAe,GAChB,KAAA;IACL;EAAC;EAAa;EAAgB;EAAc,CAAC;AAyChD,QAAO;EACL,MAxCyB,cAAc;AACvC,OAAI,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,OACtC;AAEF,UAAO,UACH,QAAQ,YAAY,QAAQ,QAAQ,CACrC,QACE,KAAK,YAAY;AAChB,QAAI,QAAQ,SAAS;KACnB,MAAM,gBAAgB,QAAQ,QAC3B,UAAU,QAAQ,cAAc,OAAO,UACzC;AACD,SAAI,eAAe;MACjB,MAAM,aAAa,IAAI,IAAI,cAAc,KAAK,UAAU,MAAM,GAAG,CAAC;MAClE,MAAM,iBAAiB,OAAO,QAAQ,UAAU,CAAC,QAC9C,UAAU,CAAC,YAAY,YAAY;OAClC,MAAM,UAAU,OAAO,WAAW;AAClC,WAAI,WAAW,IAAI,QAAQ,CACzB,UAAS,WAAW;AAEtB,cAAO;SAET,EAAE,CACH;AACD,UAAI,QAAQ,WAAW;OACrB,WAAW,QAAQ;OACnB,QAAQ;OACT;;;AAGL,WAAO;MAET,EAAE,CAIH;KACF;GAAC;GAAU;GAAQ;GAAU,CAGN;EACxB,WAAW;EACZ"}
|
|
@@ -4,13 +4,13 @@ import { getActionMessage } from "../utils/getActionMessage.js";
|
|
|
4
4
|
import { getErrorMessage } from "../utils/getErrorMessage.js";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
6
|
//#region src/hooks/useActionMessage.ts
|
|
7
|
-
const useActionMessage = (step, action) => {
|
|
7
|
+
const useActionMessage = (step, action, defaultLabelsOnly) => {
|
|
8
8
|
const { subvariant, subvariantOptions } = useWidgetConfig();
|
|
9
9
|
const { t } = useTranslation();
|
|
10
10
|
const { getChainById } = useAvailableChains();
|
|
11
11
|
if (!step || !action) return {};
|
|
12
12
|
if (action.status === "FAILED") return getErrorMessage(t, getChainById, step, action);
|
|
13
|
-
return getActionMessage(t, step, action.type, action.status, action.substatus, subvariant, subvariantOptions);
|
|
13
|
+
return getActionMessage(t, step, action.type, action.status, action.substatus, defaultLabelsOnly ? void 0 : subvariant, defaultLabelsOnly ? void 0 : subvariantOptions);
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
16
16
|
export { useActionMessage };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useActionMessage.js","names":[],"sources":["../../../src/hooks/useActionMessage.ts"],"sourcesContent":["import type { ExecutionAction, LiFiStepExtended } from '@lifi/sdk'\nimport { useTranslation } from 'react-i18next'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getActionMessage } from '../utils/getActionMessage.js'\nimport { getErrorMessage } from '../utils/getErrorMessage.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useActionMessage = (\n step?: LiFiStepExtended,\n action?: ExecutionAction\n): { title?: string; message?: string } => {\n const { subvariant, subvariantOptions } = useWidgetConfig()\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n\n if (!step || !action) {\n return {}\n }\n\n if (action.status === 'FAILED') {\n return getErrorMessage(t, getChainById, step, action)\n }\n\n return getActionMessage(\n t,\n step,\n action.type,\n action.status,\n action.substatus,\n subvariant,\n subvariantOptions\n )\n}\n"],"mappings":";;;;;;AAOA,MAAa,oBACX,MACA,
|
|
1
|
+
{"version":3,"file":"useActionMessage.js","names":[],"sources":["../../../src/hooks/useActionMessage.ts"],"sourcesContent":["import type { ExecutionAction, LiFiStepExtended } from '@lifi/sdk'\nimport { useTranslation } from 'react-i18next'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { getActionMessage } from '../utils/getActionMessage.js'\nimport { getErrorMessage } from '../utils/getErrorMessage.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useActionMessage = (\n step?: LiFiStepExtended,\n action?: ExecutionAction,\n defaultLabelsOnly?: boolean\n): { title?: string; message?: string } => {\n const { subvariant, subvariantOptions } = useWidgetConfig()\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n\n if (!step || !action) {\n return {}\n }\n\n if (action.status === 'FAILED') {\n return getErrorMessage(t, getChainById, step, action)\n }\n\n return getActionMessage(\n t,\n step,\n action.type,\n action.status,\n action.substatus,\n defaultLabelsOnly ? undefined : subvariant,\n defaultLabelsOnly ? undefined : subvariantOptions\n )\n}\n"],"mappings":";;;;;;AAOA,MAAa,oBACX,MACA,QACA,sBACyC;CACzC,MAAM,EAAE,YAAY,sBAAsB,iBAAiB;CAC3D,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,EAAE,iBAAiB,oBAAoB;AAE7C,KAAI,CAAC,QAAQ,CAAC,OACZ,QAAO,EAAE;AAGX,KAAI,OAAO,WAAW,SACpB,QAAO,gBAAgB,GAAG,cAAc,MAAM,OAAO;AAGvD,QAAO,iBACL,GACA,MACA,OAAO,MACP,OAAO,QACP,OAAO,WACP,oBAAoB,KAAA,IAAY,YAChC,oBAAoB,KAAA,IAAY,kBACjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAddressActivity.js","names":[],"sources":["../../../src/hooks/useAddressActivity.ts"],"sourcesContent":["import { ChainType } from '@lifi/sdk'\nimport { useEthereumContext } from '@lifi/widget-provider'\nimport { useQuery } from '@tanstack/react-query'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\ninterface AddressActivity {\n hasActivity: boolean\n isLoading: boolean\n isFetched: boolean\n toAddress: string | undefined\n}\nexport const useAddressActivity = (chainId?: number): AddressActivity => {\n const { getChainById } = useAvailableChains()\n const [toAddress, toChainId] = useFieldValues('toAddress', 'toChain')\n const { getTransactionCount } = useEthereumContext()\n\n const destinationChainId = chainId ?? toChainId\n const toChain = getChainById(destinationChainId)\n\n const {\n data: transactionCount,\n isLoading,\n isFetched,\n error,\n } = useQuery({\n queryKey: ['getTransactionCount', toAddress, destinationChainId],\n queryFn: async () => {\n const count = await getTransactionCount?.(destinationChainId!, toAddress!)\n return count ?? null\n },\n refetchInterval: 300_000,\n staleTime: 300_000,\n enabled:\n toChain?.chainType === ChainType.EVM &&\n !!destinationChainId &&\n !!toAddress &&\n !!getTransactionCount,\n })\n\n return {\n toAddress,\n hasActivity: Boolean(transactionCount && transactionCount > 0),\n isLoading,\n isFetched: isFetched && !error,\n }\n}\n"],"mappings":";;;;;;AAYA,MAAa,sBAAsB,YAAsC;CACvE,MAAM,EAAE,iBAAiB,oBAAoB;CAC7C,MAAM,CAAC,WAAW,aAAa,eAAe,aAAa,UAAU;CACrE,MAAM,EAAE,wBAAwB,oBAAoB;CAEpD,MAAM,qBAAqB,WAAW;CACtC,MAAM,UAAU,aAAa,mBAAmB;CAEhD,MAAM,EACJ,MAAM,kBACN,WACA,WACA,UACE,SAAS;EACX,UAAU;GAAC;GAAuB;GAAW;GAAmB;EAChE,SAAS,YAAY;AAEnB,
|
|
1
|
+
{"version":3,"file":"useAddressActivity.js","names":[],"sources":["../../../src/hooks/useAddressActivity.ts"],"sourcesContent":["import { ChainType } from '@lifi/sdk'\nimport { useEthereumContext } from '@lifi/widget-provider'\nimport { useQuery } from '@tanstack/react-query'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\ninterface AddressActivity {\n hasActivity: boolean\n isLoading: boolean\n isFetched: boolean\n toAddress: string | undefined\n}\nexport const useAddressActivity = (chainId?: number): AddressActivity => {\n const { getChainById } = useAvailableChains()\n const [toAddress, toChainId] = useFieldValues('toAddress', 'toChain')\n const { getTransactionCount } = useEthereumContext()\n\n const destinationChainId = chainId ?? toChainId\n const toChain = getChainById(destinationChainId)\n\n const {\n data: transactionCount,\n isLoading,\n isFetched,\n error,\n } = useQuery({\n queryKey: ['getTransactionCount', toAddress, destinationChainId],\n queryFn: async () => {\n const count = await getTransactionCount?.(destinationChainId!, toAddress!)\n return count ?? null\n },\n refetchInterval: 300_000,\n staleTime: 300_000,\n enabled:\n toChain?.chainType === ChainType.EVM &&\n !!destinationChainId &&\n !!toAddress &&\n !!getTransactionCount,\n })\n\n return {\n toAddress,\n hasActivity: Boolean(transactionCount && transactionCount > 0),\n isLoading,\n isFetched: isFetched && !error,\n }\n}\n"],"mappings":";;;;;;AAYA,MAAa,sBAAsB,YAAsC;CACvE,MAAM,EAAE,iBAAiB,oBAAoB;CAC7C,MAAM,CAAC,WAAW,aAAa,eAAe,aAAa,UAAU;CACrE,MAAM,EAAE,wBAAwB,oBAAoB;CAEpD,MAAM,qBAAqB,WAAW;CACtC,MAAM,UAAU,aAAa,mBAAmB;CAEhD,MAAM,EACJ,MAAM,kBACN,WACA,WACA,UACE,SAAS;EACX,UAAU;GAAC;GAAuB;GAAW;GAAmB;EAChE,SAAS,YAAY;AAEnB,UAAO,MADa,sBAAsB,oBAAqB,UAAW,IAC1D;;EAElB,iBAAiB;EACjB,WAAW;EACX,SACE,SAAS,cAAc,UAAU,OACjC,CAAC,CAAC,sBACF,CAAC,CAAC,aACF,CAAC,CAAC;EACL,CAAC;AAEF,QAAO;EACL;EACA,aAAa,QAAQ,oBAAoB,mBAAmB,EAAE;EAC9D;EACA,WAAW,aAAa,CAAC;EAC1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAvailableChains.js","names":[],"sources":["../../../src/hooks/useAvailableChains.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { ChainType, createClient, getChains } from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { WidgetConfig } from '../types/widget.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../utils/item.js'\nimport { getQueryKey } from '../utils/queries.js'\n\ntype GetChainById = (\n chainId?: number,\n chains?: ExtendedChain[]\n) => ExtendedChain | undefined\n\nconst supportedChainTypes = [\n ChainType.EVM,\n ChainType.SVM,\n ChainType.UTXO,\n ChainType.MVM,\n ChainType.TVM,\n]\n\nexport const useAvailableChains = (\n chainTypes?: ChainType[],\n widgetConfig?: WidgetConfig\n): {\n chains: ExtendedChain[] | undefined\n getChainById: GetChainById\n isLoading: boolean\n} => {\n const { chains: internalChains, keyPrefix: internalKeyPrefix } =\n useWidgetConfig()\n const internalClient = useSDKClient()\n\n const externalClient = useMemo(() => {\n if (!widgetConfig) {\n return undefined\n }\n return createClient({\n ...widgetConfig.sdkConfig,\n apiKey: widgetConfig.apiKey,\n integrator: widgetConfig.integrator ?? window?.location.hostname,\n })\n }, [widgetConfig])\n\n // Overwrite widget config if passed as param\n const keyPrefix = widgetConfig?.keyPrefix ?? internalKeyPrefix\n const chains = widgetConfig?.chains ?? internalChains\n\n const { data, isLoading } = useQuery({\n queryKey: [\n getQueryKey('chains', keyPrefix),\n chains?.types,\n chains?.allow,\n chains?.deny,\n chains?.from,\n chains?.to,\n !!externalClient,\n ] as const,\n queryFn: async ({ queryKey: [, chainTypesConfig] }) => {\n const chainsConfigSets = getConfigItemSets(\n chainTypesConfig,\n (chains) => new Set(chains)\n )\n const chainTypesRequest = supportedChainTypes.filter((chainType) =>\n isItemAllowedForSets(chainType, chainsConfigSets)\n )\n const client = externalClient ?? internalClient\n const availableChains = await getChains(client, {\n chainTypes: chainTypes || chainTypesRequest,\n })\n client.setChains(availableChains)\n return availableChains\n },\n refetchInterval: 300_000,\n staleTime: 300_000,\n })\n\n // Ensure the current internal client always has chains, even when:\n // - the query result came from cache (external call populated it first)\n // - the client was recreated due to config changes (stale closure in queryFn)\n useEffect(() => {\n if (data && !externalClient) {\n internalClient.setChains(data)\n }\n }, [data, externalClient, internalClient])\n\n const getChainById: GetChainById = useCallback(\n (chainId?: number, chains: ExtendedChain[] | undefined = data) => {\n if (!chainId) {\n return\n }\n const chain = chains?.find((chain) => chain.id === chainId)\n // if (!chain) {\n // throw new Error('Chain not found or chainId is invalid.');\n // }\n return chain\n },\n [data]\n )\n\n return {\n chains: data,\n getChainById,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;AAeA,MAAM,sBAAsB;CAC1B,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACX;AAED,MAAa,sBACX,YACA,iBAKG;CACH,MAAM,EAAE,QAAQ,gBAAgB,WAAW,sBACzC,iBAAiB;CACnB,MAAM,iBAAiB,cAAc;CAErC,MAAM,iBAAiB,cAAc;AACnC,MAAI,CAAC,aACH;AAEF,SAAO,aAAa;GAClB,GAAG,aAAa;GAChB,QAAQ,aAAa;GACrB,YAAY,aAAa,cAAc,QAAQ,SAAS;GACzD,CAAC;IACD,CAAC,aAAa,CAAC;CAGlB,MAAM,YAAY,cAAc,aAAa;CAC7C,MAAM,SAAS,cAAc,UAAU;CAEvC,MAAM,EAAE,MAAM,cAAc,SAAS;EACnC,UAAU;GACR,YAAY,UAAU,UAAU;GAChC,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,CAAC,CAAC;GACH;EACD,SAAS,OAAO,EAAE,UAAU,GAAG,wBAAwB;GACrD,MAAM,mBAAmB,kBACvB,mBACC,WAAW,IAAI,IAAI,OAAO,CAC5B;GACD,MAAM,oBAAoB,oBAAoB,QAAQ,cACpD,qBAAqB,WAAW,iBAAiB,CAClD;GACD,MAAM,SAAS,kBAAkB;GACjC,MAAM,kBAAkB,MAAM,UAAU,QAAQ,EAC9C,YAAY,cAAc,mBAC3B,CAAC;AACF,UAAO,UAAU,gBAAgB;AACjC,UAAO;;EAET,iBAAiB;EACjB,WAAW;EACZ,CAAC;AAKF,iBAAgB;AACd,MAAI,QAAQ,CAAC,eACX,gBAAe,UAAU,KAAK;IAE/B;EAAC;EAAM;EAAgB;EAAe,CAAC;AAgB1C,QAAO;EACL,QAAQ;EACR,cAhBiC,aAChC,SAAkB,SAAsC,SAAS;AAChE,OAAI,CAAC,QACH;AAMF,UAJc,QAAQ,MAAM,UAAU,MAAM,OAAO,QAAQ;KAM7D,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"useAvailableChains.js","names":[],"sources":["../../../src/hooks/useAvailableChains.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { ChainType, createClient, getChains } from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { WidgetConfig } from '../types/widget.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../utils/item.js'\nimport { getQueryKey } from '../utils/queries.js'\n\ntype GetChainById = (\n chainId?: number,\n chains?: ExtendedChain[]\n) => ExtendedChain | undefined\n\nconst supportedChainTypes = [\n ChainType.EVM,\n ChainType.SVM,\n ChainType.UTXO,\n ChainType.MVM,\n ChainType.TVM,\n]\n\nexport const useAvailableChains = (\n chainTypes?: ChainType[],\n widgetConfig?: WidgetConfig\n): {\n chains: ExtendedChain[] | undefined\n getChainById: GetChainById\n isLoading: boolean\n} => {\n const { chains: internalChains, keyPrefix: internalKeyPrefix } =\n useWidgetConfig()\n const internalClient = useSDKClient()\n\n const externalClient = useMemo(() => {\n if (!widgetConfig) {\n return undefined\n }\n return createClient({\n ...widgetConfig.sdkConfig,\n apiKey: widgetConfig.apiKey,\n integrator: widgetConfig.integrator ?? window?.location.hostname,\n })\n }, [widgetConfig])\n\n // Overwrite widget config if passed as param\n const keyPrefix = widgetConfig?.keyPrefix ?? internalKeyPrefix\n const chains = widgetConfig?.chains ?? internalChains\n\n const { data, isLoading } = useQuery({\n queryKey: [\n getQueryKey('chains', keyPrefix),\n chains?.types,\n chains?.allow,\n chains?.deny,\n chains?.from,\n chains?.to,\n !!externalClient,\n ] as const,\n queryFn: async ({ queryKey: [, chainTypesConfig] }) => {\n const chainsConfigSets = getConfigItemSets(\n chainTypesConfig,\n (chains) => new Set(chains)\n )\n const chainTypesRequest = supportedChainTypes.filter((chainType) =>\n isItemAllowedForSets(chainType, chainsConfigSets)\n )\n const client = externalClient ?? internalClient\n const availableChains = await getChains(client, {\n chainTypes: chainTypes || chainTypesRequest,\n })\n client.setChains(availableChains)\n return availableChains\n },\n refetchInterval: 300_000,\n staleTime: 300_000,\n })\n\n // Ensure the current internal client always has chains, even when:\n // - the query result came from cache (external call populated it first)\n // - the client was recreated due to config changes (stale closure in queryFn)\n useEffect(() => {\n if (data && !externalClient) {\n internalClient.setChains(data)\n }\n }, [data, externalClient, internalClient])\n\n const getChainById: GetChainById = useCallback(\n (chainId?: number, chains: ExtendedChain[] | undefined = data) => {\n if (!chainId) {\n return\n }\n const chain = chains?.find((chain) => chain.id === chainId)\n // if (!chain) {\n // throw new Error('Chain not found or chainId is invalid.');\n // }\n return chain\n },\n [data]\n )\n\n return {\n chains: data,\n getChainById,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;AAeA,MAAM,sBAAsB;CAC1B,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACV,UAAU;CACX;AAED,MAAa,sBACX,YACA,iBAKG;CACH,MAAM,EAAE,QAAQ,gBAAgB,WAAW,sBACzC,iBAAiB;CACnB,MAAM,iBAAiB,cAAc;CAErC,MAAM,iBAAiB,cAAc;AACnC,MAAI,CAAC,aACH;AAEF,SAAO,aAAa;GAClB,GAAG,aAAa;GAChB,QAAQ,aAAa;GACrB,YAAY,aAAa,cAAc,QAAQ,SAAS;GACzD,CAAC;IACD,CAAC,aAAa,CAAC;CAGlB,MAAM,YAAY,cAAc,aAAa;CAC7C,MAAM,SAAS,cAAc,UAAU;CAEvC,MAAM,EAAE,MAAM,cAAc,SAAS;EACnC,UAAU;GACR,YAAY,UAAU,UAAU;GAChC,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,CAAC,CAAC;GACH;EACD,SAAS,OAAO,EAAE,UAAU,GAAG,wBAAwB;GACrD,MAAM,mBAAmB,kBACvB,mBACC,WAAW,IAAI,IAAI,OAAO,CAC5B;GACD,MAAM,oBAAoB,oBAAoB,QAAQ,cACpD,qBAAqB,WAAW,iBAAiB,CAClD;GACD,MAAM,SAAS,kBAAkB;GACjC,MAAM,kBAAkB,MAAM,UAAU,QAAQ,EAC9C,YAAY,cAAc,mBAC3B,CAAC;AACF,UAAO,UAAU,gBAAgB;AACjC,UAAO;;EAET,iBAAiB;EACjB,WAAW;EACZ,CAAC;AAKF,iBAAgB;AACd,MAAI,QAAQ,CAAC,eACX,gBAAe,UAAU,KAAK;IAE/B;EAAC;EAAM;EAAgB;EAAe,CAAC;AAgB1C,QAAO;EACL,QAAQ;EACR,cAhBiC,aAChC,SAAkB,SAAsC,SAAS;AAChE,OAAI,CAAC,QACH;AAMF,UAJc,QAAQ,MAAM,UAAU,MAAM,OAAO,QAAQ;KAM7D,CAAC,KAAK,CAKM;EACZ;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChain.js","names":[],"sources":["../../../src/hooks/useChain.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { useMemo } from 'react'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useChain = (\n chainId?: number\n): {\n chain: ExtendedChain | undefined\n isLoading: boolean\n getChainById: (\n chainId?: number,\n chains?: ExtendedChain[]\n ) => ExtendedChain | undefined\n} => {\n const { isLoading, getChainById } = useAvailableChains()\n\n const chain = useMemo(() => getChainById(chainId), [chainId, getChainById])\n\n return {\n chain,\n isLoading,\n getChainById,\n }\n}\n"],"mappings":";;;AAIA,MAAa,YACX,YAQG;CACH,MAAM,EAAE,WAAW,iBAAiB,oBAAoB;AAIxD,QAAO;EACL,OAHY,cAAc,aAAa,QAAQ,EAAE,CAAC,SAAS,aAAa,
|
|
1
|
+
{"version":3,"file":"useChain.js","names":[],"sources":["../../../src/hooks/useChain.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { useMemo } from 'react'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useChain = (\n chainId?: number\n): {\n chain: ExtendedChain | undefined\n isLoading: boolean\n getChainById: (\n chainId?: number,\n chains?: ExtendedChain[]\n ) => ExtendedChain | undefined\n} => {\n const { isLoading, getChainById } = useAvailableChains()\n\n const chain = useMemo(() => getChainById(chainId), [chainId, getChainById])\n\n return {\n chain,\n isLoading,\n getChainById,\n }\n}\n"],"mappings":";;;AAIA,MAAa,YACX,YAQG;CACH,MAAM,EAAE,WAAW,iBAAiB,oBAAoB;AAIxD,QAAO;EACL,OAHY,cAAc,aAAa,QAAQ,EAAE,CAAC,SAAS,aAAa,CAGnE;EACL;EACA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChains.js","names":[],"sources":["../../../src/hooks/useChains.ts"],"sourcesContent":["import type { ChainType, ExtendedChain } from '@lifi/sdk'\nimport { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormType } from '../stores/form/types.js'\nimport { getConfigItemSets, isFormItemAllowed } from '../utils/item.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useChains = (\n type?: FormType,\n chainTypes?: ChainType[]\n): {\n chains: ExtendedChain[] | undefined\n getChainById: (\n chainId?: number,\n chains?: ExtendedChain[]\n ) => ExtendedChain | undefined\n isLoading: boolean\n} => {\n const { chains } = useWidgetConfig()\n const {\n chains: availableChains,\n isLoading: isLoadingAvailableChains,\n getChainById,\n } = useAvailableChains()\n\n const filteredChains = useMemo(() => {\n const chainsConfigSets = getConfigItemSets(\n chains,\n (chains) => new Set(chains),\n type\n )\n const filteredChains = type\n ? availableChains?.filter(\n (chain) =>\n isFormItemAllowed(chain.id, chainsConfigSets, type) &&\n // Check against chain types if they are provided\n (chainTypes?.includes(chain.chainType) ?? true)\n )\n : availableChains?.filter((chain) =>\n isFormItemAllowed(chain.id, chainsConfigSets)\n )\n return filteredChains\n }, [availableChains, chainTypes, chains, type])\n\n return {\n chains: filteredChains,\n getChainById,\n isLoading: isLoadingAvailableChains,\n }\n}\n"],"mappings":";;;;;AAOA,MAAa,aACX,MACA,eAQG;CACH,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,EACJ,QAAQ,iBACR,WAAW,0BACX,iBACE,oBAAoB;AAqBxB,QAAO;EACL,QApBqB,cAAc;GACnC,MAAM,mBAAmB,kBACvB,SACC,WAAW,IAAI,IAAI,OAAO,EAC3B,KACD;AAWD,UAVuB,OACnB,iBAAiB,QACd,UACC,kBAAkB,MAAM,IAAI,kBAAkB,KAAK,KAElD,YAAY,SAAS,MAAM,UAAU,IAAI,MAC7C,GACD,iBAAiB,QAAQ,UACvB,kBAAkB,MAAM,IAAI,iBAAiB,CAC9C;KAEJ;GAAC;GAAiB;GAAY;GAAQ;GAAK,
|
|
1
|
+
{"version":3,"file":"useChains.js","names":[],"sources":["../../../src/hooks/useChains.ts"],"sourcesContent":["import type { ChainType, ExtendedChain } from '@lifi/sdk'\nimport { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormType } from '../stores/form/types.js'\nimport { getConfigItemSets, isFormItemAllowed } from '../utils/item.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nexport const useChains = (\n type?: FormType,\n chainTypes?: ChainType[]\n): {\n chains: ExtendedChain[] | undefined\n getChainById: (\n chainId?: number,\n chains?: ExtendedChain[]\n ) => ExtendedChain | undefined\n isLoading: boolean\n} => {\n const { chains } = useWidgetConfig()\n const {\n chains: availableChains,\n isLoading: isLoadingAvailableChains,\n getChainById,\n } = useAvailableChains()\n\n const filteredChains = useMemo(() => {\n const chainsConfigSets = getConfigItemSets(\n chains,\n (chains) => new Set(chains),\n type\n )\n const filteredChains = type\n ? availableChains?.filter(\n (chain) =>\n isFormItemAllowed(chain.id, chainsConfigSets, type) &&\n // Check against chain types if they are provided\n (chainTypes?.includes(chain.chainType) ?? true)\n )\n : availableChains?.filter((chain) =>\n isFormItemAllowed(chain.id, chainsConfigSets)\n )\n return filteredChains\n }, [availableChains, chainTypes, chains, type])\n\n return {\n chains: filteredChains,\n getChainById,\n isLoading: isLoadingAvailableChains,\n }\n}\n"],"mappings":";;;;;AAOA,MAAa,aACX,MACA,eAQG;CACH,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,EACJ,QAAQ,iBACR,WAAW,0BACX,iBACE,oBAAoB;AAqBxB,QAAO;EACL,QApBqB,cAAc;GACnC,MAAM,mBAAmB,kBACvB,SACC,WAAW,IAAI,IAAI,OAAO,EAC3B,KACD;AAWD,UAVuB,OACnB,iBAAiB,QACd,UACC,kBAAkB,MAAM,IAAI,kBAAkB,KAAK,KAElD,YAAY,SAAS,MAAM,UAAU,IAAI,MAC7C,GACD,iBAAiB,QAAQ,UACvB,kBAAkB,MAAM,IAAI,iBAAiB,CAC9C;KAEJ;GAAC;GAAiB;GAAY;GAAQ;GAAK,CAGtB;EACtB;EACA,WAAW;EACZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDebouncedWatch.js","names":[],"sources":["../../../src/hooks/useDebouncedWatch.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\nimport type { FormFieldArray, FormFieldNames } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\n\nexport const useDebouncedWatch = <T extends FormFieldNames[]>(\n delay: number,\n ...name: T\n): FormFieldArray<T> => {\n const watchedValue = useFieldValues(...name)\n const [debouncedValue, setDebouncedValue] = useState(watchedValue)\n const debouncedValueRef = useRef<typeof watchedValue>(null)\n const isMounted = useRef(false)\n\n useEffect(() => {\n if (isMounted.current) {\n const hasWatchedValue = watchedValue.some((value) => value)\n if (hasWatchedValue) {\n const handler = setTimeout(() => {\n setDebouncedValue(watchedValue)\n }, delay)\n return () => clearTimeout(handler)\n }\n debouncedValueRef.current = watchedValue\n setDebouncedValue(watchedValue)\n return undefined\n }\n isMounted.current = true\n return undefined\n }, [delay, watchedValue])\n\n return debouncedValue\n}\n"],"mappings":";;;AAIA,MAAa,qBACX,OACA,GAAG,SACmB;CACtB,MAAM,eAAe,eAAe,GAAG,KAAK;CAC5C,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,aAAa;CAClE,MAAM,oBAAoB,OAA4B,KAAK;CAC3D,MAAM,YAAY,OAAO,MAAM;AAE/B,iBAAgB;AACd,MAAI,UAAU,SAAS;AAErB,OADwB,aAAa,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"useDebouncedWatch.js","names":[],"sources":["../../../src/hooks/useDebouncedWatch.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\nimport type { FormFieldArray, FormFieldNames } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\n\nexport const useDebouncedWatch = <T extends FormFieldNames[]>(\n delay: number,\n ...name: T\n): FormFieldArray<T> => {\n const watchedValue = useFieldValues(...name)\n const [debouncedValue, setDebouncedValue] = useState(watchedValue)\n const debouncedValueRef = useRef<typeof watchedValue>(null)\n const isMounted = useRef(false)\n\n useEffect(() => {\n if (isMounted.current) {\n const hasWatchedValue = watchedValue.some((value) => value)\n if (hasWatchedValue) {\n const handler = setTimeout(() => {\n setDebouncedValue(watchedValue)\n }, delay)\n return () => clearTimeout(handler)\n }\n debouncedValueRef.current = watchedValue\n setDebouncedValue(watchedValue)\n return undefined\n }\n isMounted.current = true\n return undefined\n }, [delay, watchedValue])\n\n return debouncedValue\n}\n"],"mappings":";;;AAIA,MAAa,qBACX,OACA,GAAG,SACmB;CACtB,MAAM,eAAe,eAAe,GAAG,KAAK;CAC5C,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,aAAa;CAClE,MAAM,oBAAoB,OAA4B,KAAK;CAC3D,MAAM,YAAY,OAAO,MAAM;AAE/B,iBAAgB;AACd,MAAI,UAAU,SAAS;AAErB,OADwB,aAAa,MAAM,UAAU,MAClC,EAAE;IACnB,MAAM,UAAU,iBAAiB;AAC/B,uBAAkB,aAAa;OAC9B,MAAM;AACT,iBAAa,aAAa,QAAQ;;AAEpC,qBAAkB,UAAU;AAC5B,qBAAkB,aAAa;AAC/B;;AAEF,YAAU,UAAU;IAEnB,CAAC,OAAO,aAAa,CAAC;AAEzB,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFilteredByTokenBalances.js","names":[],"sources":["../../../src/hooks/useFilteredByTokenBalances.ts"],"sourcesContent":["import {\n type BaseToken,\n ChainType,\n getWalletBalances,\n type TokenExtended,\n type WalletTokenExtended,\n} from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormType } from '../stores/form/types.js'\nimport { getConfigItemSets, isFormItemAllowed } from '../utils/item.js'\nimport { isSupportedToken } from '../utils/tokenList.js'\n\nexport const useFilteredTokensByBalance = (\n accountsWithTokens?: Record<\n string,\n { chainType: ChainType; tokens: Record<number, TokenExtended[]> }\n >,\n formType?: FormType\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const { tokens: configTokens } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const evmAddress = useMemo(() => {\n const evmAccount = Object.entries(accountsWithTokens ?? {}).find(\n ([_, { chainType }]) => chainType === ChainType.EVM\n )\n return evmAccount?.[0]\n }, [accountsWithTokens])\n\n const { data: existingBalances, isLoading } = useQuery({\n queryKey: ['existing-evm-balances', evmAddress],\n queryFn: () => getWalletBalances(sdkClient, evmAddress ?? ''),\n enabled: !!evmAddress,\n refetchInterval: 30_000, // 30 seconds\n staleTime: 30_000, // 30 seconds\n retry: false,\n })\n\n const accountsWithFilteredTokens = useMemo(() => {\n if (!accountsWithTokens) {\n return undefined\n }\n\n // Early return if no existing balances - return all tokens\n const result: Record<string, Record<number, TokenExtended[]>> = {}\n if (!existingBalances) {\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = tokens\n }\n return result\n }\n\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = {}\n\n for (const [chainIdStr, chainTokens] of Object.entries(tokens)) {\n const chainId = Number(chainIdStr)\n // Get balances for this specific chain\n const balances = existingBalances?.[chainId]\n // If no balances, RPC all tokens of the chain\n if (!balances?.length) {\n if (chainTokens.length) {\n result[address][chainId] = chainTokens\n }\n continue\n }\n\n // Optimize token matching with Set for O(1) lookup\n const balanceSet = new Set(\n balances.map((balance: WalletTokenExtended) =>\n balance.address.toLowerCase()\n )\n )\n\n // Get tokens that are in chainTokens and have balances\n const filteredTokens = chainTokens.filter((token) => {\n const tokenKey = token.address.toLowerCase()\n return balanceSet.has(tokenKey)\n })\n\n // Get tokens that are in balances but not in chainTokens\n const chainTokenSet = new Set(\n chainTokens.map((token) => token.address.toLowerCase())\n )\n\n // Get allowed addresses from config tokens\n const allowedAddressesConfig = getConfigItemSets(\n configTokens,\n (tokens: BaseToken[]) =>\n new Set(\n tokens\n .filter((t) => Number(t.chainId) === chainId)\n .map((t) => t.address.toLowerCase())\n ),\n formType\n )\n\n const additionalTokens = balances\n .filter((balance: WalletTokenExtended) => {\n const balanceKey = balance.address.toLowerCase()\n return (\n !chainTokenSet.has(balanceKey) &&\n isSupportedToken(balance) &&\n isFormItemAllowed(\n balance,\n allowedAddressesConfig,\n formType,\n (t) => t.address.toLowerCase()\n )\n )\n })\n // Mark tokens from wallet balances as unverified\n .map((token: WalletTokenExtended) => ({\n ...token,\n verified: false,\n })) as TokenExtended[]\n\n // Combine both sets of tokens - convert WalletTokenExtended to TokenAmount\n const allTokens = [\n ...filteredTokens,\n ...additionalTokens,\n ] as TokenExtended[]\n\n if (allTokens.length) {\n result[address][chainId] = allTokens\n }\n }\n }\n\n return result\n }, [accountsWithTokens, existingBalances, configTokens, formType])\n\n return { data: accountsWithFilteredTokens, isLoading }\n}\n"],"mappings":";;;;;;;;AAeA,MAAa,8BACX,oBAIA,aAIG;CACH,MAAM,EAAE,QAAQ,iBAAiB,iBAAiB;CAClD,MAAM,YAAY,cAAc;CAEhC,MAAM,aAAa,cAAc;AAI/B,SAHmB,OAAO,QAAQ,sBAAsB,EAAE,CAAC,CAAC,MACzD,CAAC,GAAG,EAAE,iBAAiB,cAAc,UAAU,
|
|
1
|
+
{"version":3,"file":"useFilteredByTokenBalances.js","names":[],"sources":["../../../src/hooks/useFilteredByTokenBalances.ts"],"sourcesContent":["import {\n type BaseToken,\n ChainType,\n getWalletBalances,\n type TokenExtended,\n type WalletTokenExtended,\n} from '@lifi/sdk'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormType } from '../stores/form/types.js'\nimport { getConfigItemSets, isFormItemAllowed } from '../utils/item.js'\nimport { isSupportedToken } from '../utils/tokenList.js'\n\nexport const useFilteredTokensByBalance = (\n accountsWithTokens?: Record<\n string,\n { chainType: ChainType; tokens: Record<number, TokenExtended[]> }\n >,\n formType?: FormType\n): {\n data: Record<string, Record<number, TokenExtended[]>> | undefined\n isLoading: boolean\n} => {\n const { tokens: configTokens } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const evmAddress = useMemo(() => {\n const evmAccount = Object.entries(accountsWithTokens ?? {}).find(\n ([_, { chainType }]) => chainType === ChainType.EVM\n )\n return evmAccount?.[0]\n }, [accountsWithTokens])\n\n const { data: existingBalances, isLoading } = useQuery({\n queryKey: ['existing-evm-balances', evmAddress],\n queryFn: () => getWalletBalances(sdkClient, evmAddress ?? ''),\n enabled: !!evmAddress,\n refetchInterval: 30_000, // 30 seconds\n staleTime: 30_000, // 30 seconds\n retry: false,\n })\n\n const accountsWithFilteredTokens = useMemo(() => {\n if (!accountsWithTokens) {\n return undefined\n }\n\n // Early return if no existing balances - return all tokens\n const result: Record<string, Record<number, TokenExtended[]>> = {}\n if (!existingBalances) {\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = tokens\n }\n return result\n }\n\n for (const [address, { tokens }] of Object.entries(accountsWithTokens)) {\n result[address] = {}\n\n for (const [chainIdStr, chainTokens] of Object.entries(tokens)) {\n const chainId = Number(chainIdStr)\n // Get balances for this specific chain\n const balances = existingBalances?.[chainId]\n // If no balances, RPC all tokens of the chain\n if (!balances?.length) {\n if (chainTokens.length) {\n result[address][chainId] = chainTokens\n }\n continue\n }\n\n // Optimize token matching with Set for O(1) lookup\n const balanceSet = new Set(\n balances.map((balance: WalletTokenExtended) =>\n balance.address.toLowerCase()\n )\n )\n\n // Get tokens that are in chainTokens and have balances\n const filteredTokens = chainTokens.filter((token) => {\n const tokenKey = token.address.toLowerCase()\n return balanceSet.has(tokenKey)\n })\n\n // Get tokens that are in balances but not in chainTokens\n const chainTokenSet = new Set(\n chainTokens.map((token) => token.address.toLowerCase())\n )\n\n // Get allowed addresses from config tokens\n const allowedAddressesConfig = getConfigItemSets(\n configTokens,\n (tokens: BaseToken[]) =>\n new Set(\n tokens\n .filter((t) => Number(t.chainId) === chainId)\n .map((t) => t.address.toLowerCase())\n ),\n formType\n )\n\n const additionalTokens = balances\n .filter((balance: WalletTokenExtended) => {\n const balanceKey = balance.address.toLowerCase()\n return (\n !chainTokenSet.has(balanceKey) &&\n isSupportedToken(balance) &&\n isFormItemAllowed(\n balance,\n allowedAddressesConfig,\n formType,\n (t) => t.address.toLowerCase()\n )\n )\n })\n // Mark tokens from wallet balances as unverified\n .map((token: WalletTokenExtended) => ({\n ...token,\n verified: false,\n })) as TokenExtended[]\n\n // Combine both sets of tokens - convert WalletTokenExtended to TokenAmount\n const allTokens = [\n ...filteredTokens,\n ...additionalTokens,\n ] as TokenExtended[]\n\n if (allTokens.length) {\n result[address][chainId] = allTokens\n }\n }\n }\n\n return result\n }, [accountsWithTokens, existingBalances, configTokens, formType])\n\n return { data: accountsWithFilteredTokens, isLoading }\n}\n"],"mappings":";;;;;;;;AAeA,MAAa,8BACX,oBAIA,aAIG;CACH,MAAM,EAAE,QAAQ,iBAAiB,iBAAiB;CAClD,MAAM,YAAY,cAAc;CAEhC,MAAM,aAAa,cAAc;AAI/B,SAHmB,OAAO,QAAQ,sBAAsB,EAAE,CAAC,CAAC,MACzD,CAAC,GAAG,EAAE,iBAAiB,cAAc,UAAU,IAEjC,GAAG;IACnB,CAAC,mBAAmB,CAAC;CAExB,MAAM,EAAE,MAAM,kBAAkB,cAAc,SAAS;EACrD,UAAU,CAAC,yBAAyB,WAAW;EAC/C,eAAe,kBAAkB,WAAW,cAAc,GAAG;EAC7D,SAAS,CAAC,CAAC;EACX,iBAAiB;EACjB,WAAW;EACX,OAAO;EACR,CAAC;AAgGF,QAAO;EAAE,MA9F0B,cAAc;AAC/C,OAAI,CAAC,mBACH;GAIF,MAAM,SAA0D,EAAE;AAClE,OAAI,CAAC,kBAAkB;AACrB,SAAK,MAAM,CAAC,SAAS,EAAE,aAAa,OAAO,QAAQ,mBAAmB,CACpE,QAAO,WAAW;AAEpB,WAAO;;AAGT,QAAK,MAAM,CAAC,SAAS,EAAE,aAAa,OAAO,QAAQ,mBAAmB,EAAE;AACtE,WAAO,WAAW,EAAE;AAEpB,SAAK,MAAM,CAAC,YAAY,gBAAgB,OAAO,QAAQ,OAAO,EAAE;KAC9D,MAAM,UAAU,OAAO,WAAW;KAElC,MAAM,WAAW,mBAAmB;AAEpC,SAAI,CAAC,UAAU,QAAQ;AACrB,UAAI,YAAY,OACd,QAAO,SAAS,WAAW;AAE7B;;KAIF,MAAM,aAAa,IAAI,IACrB,SAAS,KAAK,YACZ,QAAQ,QAAQ,aAAa,CAC9B,CACF;KAGD,MAAM,iBAAiB,YAAY,QAAQ,UAAU;MACnD,MAAM,WAAW,MAAM,QAAQ,aAAa;AAC5C,aAAO,WAAW,IAAI,SAAS;OAC/B;KAGF,MAAM,gBAAgB,IAAI,IACxB,YAAY,KAAK,UAAU,MAAM,QAAQ,aAAa,CAAC,CACxD;KAGD,MAAM,yBAAyB,kBAC7B,eACC,WACC,IAAI,IACF,OACG,QAAQ,MAAM,OAAO,EAAE,QAAQ,KAAK,QAAQ,CAC5C,KAAK,MAAM,EAAE,QAAQ,aAAa,CAAC,CACvC,EACH,SACD;KAED,MAAM,mBAAmB,SACtB,QAAQ,YAAiC;MACxC,MAAM,aAAa,QAAQ,QAAQ,aAAa;AAChD,aACE,CAAC,cAAc,IAAI,WAAW,IAC9B,iBAAiB,QAAQ,IACzB,kBACE,SACA,wBACA,WACC,MAAM,EAAE,QAAQ,aAAa,CAC/B;OAEH,CAED,KAAK,WAAgC;MACpC,GAAG;MACH,UAAU;MACX,EAAE;KAGL,MAAM,YAAY,CAChB,GAAG,gBACH,GAAG,iBACJ;AAED,SAAI,UAAU,OACZ,QAAO,SAAS,WAAW;;;AAKjC,UAAO;KACN;GAAC;GAAoB;GAAkB;GAAc;GAAS,CAExB;EAAE;EAAW"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFromAmountThreshold.js","names":[],"sources":["../../../src/hooks/useFromAmountThreshold.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { FormKeyHelper } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { formatTokenPrice } from '../utils/format.js'\nimport { useToken } from './useToken.js'\n\nexport const useFromAmountThreshold = (): {\n belowMinFromAmountUSD: boolean\n minFromAmountUSD: number | undefined\n} => {\n const { minFromAmountUSD } = useWidgetConfig()\n\n const [chainId, tokenAddress, fromAmount] = useFieldValues(\n FormKeyHelper.getChainKey('from'),\n FormKeyHelper.getTokenKey('from'),\n FormKeyHelper.getAmountKey('from')\n )\n const { token } = useToken(chainId, tokenAddress)\n\n const belowMinFromAmountUSD = useMemo(() => {\n const fromAmountUSD = formatTokenPrice(\n fromAmount,\n token?.priceUSD,\n token?.decimals\n )\n\n if (!minFromAmountUSD || !fromAmountUSD) {\n return false\n }\n return fromAmountUSD < minFromAmountUSD\n }, [minFromAmountUSD, fromAmount, token?.priceUSD, token?.decimals])\n\n return {\n belowMinFromAmountUSD,\n minFromAmountUSD,\n }\n}\n"],"mappings":";;;;;;;AAOA,MAAa,+BAGR;CACH,MAAM,EAAE,qBAAqB,iBAAiB;CAE9C,MAAM,CAAC,SAAS,cAAc,cAAc,eAC1C,cAAc,YAAY,OAAO,EACjC,cAAc,YAAY,OAAO,EACjC,cAAc,aAAa,OAAO,CACnC;CACD,MAAM,EAAE,UAAU,SAAS,SAAS,aAAa;AAejD,QAAO;EACL,uBAd4B,cAAc;GAC1C,MAAM,gBAAgB,iBACpB,YACA,OAAO,UACP,OAAO,SACR;AAED,OAAI,CAAC,oBAAoB,CAAC,cACxB,QAAO;AAET,UAAO,gBAAgB;KACtB;GAAC;GAAkB;GAAY,OAAO;GAAU,OAAO;GAAS,
|
|
1
|
+
{"version":3,"file":"useFromAmountThreshold.js","names":[],"sources":["../../../src/hooks/useFromAmountThreshold.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { FormKeyHelper } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { formatTokenPrice } from '../utils/format.js'\nimport { useToken } from './useToken.js'\n\nexport const useFromAmountThreshold = (): {\n belowMinFromAmountUSD: boolean\n minFromAmountUSD: number | undefined\n} => {\n const { minFromAmountUSD } = useWidgetConfig()\n\n const [chainId, tokenAddress, fromAmount] = useFieldValues(\n FormKeyHelper.getChainKey('from'),\n FormKeyHelper.getTokenKey('from'),\n FormKeyHelper.getAmountKey('from')\n )\n const { token } = useToken(chainId, tokenAddress)\n\n const belowMinFromAmountUSD = useMemo(() => {\n const fromAmountUSD = formatTokenPrice(\n fromAmount,\n token?.priceUSD,\n token?.decimals\n )\n\n if (!minFromAmountUSD || !fromAmountUSD) {\n return false\n }\n return fromAmountUSD < minFromAmountUSD\n }, [minFromAmountUSD, fromAmount, token?.priceUSD, token?.decimals])\n\n return {\n belowMinFromAmountUSD,\n minFromAmountUSD,\n }\n}\n"],"mappings":";;;;;;;AAOA,MAAa,+BAGR;CACH,MAAM,EAAE,qBAAqB,iBAAiB;CAE9C,MAAM,CAAC,SAAS,cAAc,cAAc,eAC1C,cAAc,YAAY,OAAO,EACjC,cAAc,YAAY,OAAO,EACjC,cAAc,aAAa,OAAO,CACnC;CACD,MAAM,EAAE,UAAU,SAAS,SAAS,aAAa;AAejD,QAAO;EACL,uBAd4B,cAAc;GAC1C,MAAM,gBAAgB,iBACpB,YACA,OAAO,UACP,OAAO,SACR;AAED,OAAI,CAAC,oBAAoB,CAAC,cACxB,QAAO;AAET,UAAO,gBAAgB;KACtB;GAAC;GAAkB;GAAY,OAAO;GAAU,OAAO;GAAS,CAG5C;EACrB;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFromTokenSufficiency.js","names":[],"sources":["../../../src/hooks/useFromTokenSufficiency.ts"],"sourcesContent":["import { parseUnits, type RouteExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { keepPreviousData, useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { isRouteDone } from '../stores/routes/utils.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useTokenAddressBalance } from './useTokenAddressBalance.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nconst refetchInterval = 30_000\n\nexport const useFromTokenSufficiency = (\n route?: RouteExtended\n): {\n insufficientFromToken: boolean | undefined\n isLoading: boolean\n} => {\n const [fromChainId, fromTokenAddress, fromAmount] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'fromAmount'\n )\n const { keyPrefix } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n let chainId = fromChainId\n let tokenAddress = fromTokenAddress\n if (route) {\n chainId = route.fromToken.chainId\n tokenAddress = route.fromToken.address\n }\n\n const {\n token,\n chain,\n isLoading: isTokenAddressBalanceLoading,\n } = useTokenAddressBalance(chainId, tokenAddress)\n\n const { account } = useAccount({ chainType: chain?.chainType })\n\n const { data: insufficientFromToken, isLoading } = useQuery({\n queryKey: [\n getQueryKey('from-token-sufficiency-check', keyPrefix),\n account.address,\n chainId,\n tokenAddress,\n route?.id ?? fromAmount,\n ] as const,\n queryFn: async ({ queryKey: [, accountAddress] }) => {\n if (!accountAddress || !token) {\n return\n }\n const parsedFromAmount = parseUnits(fromAmount, token.decimals)\n let currentTokenBalance = token.amount ?? 0n\n\n if (!route || isRouteDone(route)) {\n const insufficientFunds = currentTokenBalance < parsedFromAmount\n return insufficientFunds\n }\n\n const currentAction = route.steps.filter(\n (step) => !step.execution || step.execution.status !== 'DONE'\n )[0]?.action\n\n if (\n token.chainId === currentAction.fromToken.chainId &&\n token.address === currentAction.fromToken.address &&\n currentTokenBalance > 0\n ) {\n const insufficientFunds = BigInt(route.fromAmount) > currentTokenBalance\n return insufficientFunds\n }\n\n const tokenBalances = await getTokenBalancesWithRetry(\n sdkClient,\n accountAddress,\n [currentAction.fromToken]\n )\n\n currentTokenBalance = tokenBalances?.[0]?.amount ?? 0n\n const insufficientFunds =\n BigInt(currentAction.fromAmount) > currentTokenBalance\n return insufficientFunds\n },\n\n enabled: Boolean(account.address && token && !isTokenAddressBalanceLoading),\n refetchInterval,\n staleTime: refetchInterval,\n placeholderData: account.address ? keepPreviousData : undefined,\n })\n\n return {\n insufficientFromToken,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,kBAAkB;AAExB,MAAa,2BACX,UAIG;CACH,MAAM,CAAC,aAAa,kBAAkB,cAAc,eAClD,aACA,aACA,aACD;CACD,MAAM,EAAE,cAAc,iBAAiB;CACvC,MAAM,YAAY,cAAc;CAEhC,IAAI,UAAU;CACd,IAAI,eAAe;AACnB,KAAI,OAAO;AACT,YAAU,MAAM,UAAU;AAC1B,iBAAe,MAAM,UAAU;;CAGjC,MAAM,EACJ,OACA,OACA,WAAW,iCACT,uBAAuB,SAAS,aAAa;CAEjD,MAAM,EAAE,YAAY,WAAW,EAAE,WAAW,OAAO,WAAW,CAAC;CAE/D,MAAM,EAAE,MAAM,uBAAuB,cAAc,SAAS;EAC1D,UAAU;GACR,YAAY,gCAAgC,UAAU;GACtD,QAAQ;GACR;GACA;GACA,OAAO,MAAM;GACd;EACD,SAAS,OAAO,EAAE,UAAU,GAAG,sBAAsB;AACnD,OAAI,CAAC,kBAAkB,CAAC,MACtB;GAEF,MAAM,mBAAmB,WAAW,YAAY,MAAM,SAAS;GAC/D,IAAI,sBAAsB,MAAM,UAAU;AAE1C,OAAI,CAAC,SAAS,YAAY,MAAM,CAE9B,QAD0B,sBAAsB;GAIlD,MAAM,gBAAgB,MAAM,MAAM,QAC/B,SAAS,CAAC,KAAK,aAAa,KAAK,UAAU,WAAW,OACxD,CAAC,IAAI;AAEN,OACE,MAAM,YAAY,cAAc,UAAU,WAC1C,MAAM,YAAY,cAAc,UAAU,WAC1C,sBAAsB,EAGtB,QAD0B,OAAO,MAAM,WAAW,GAAG;AAUvD,
|
|
1
|
+
{"version":3,"file":"useFromTokenSufficiency.js","names":[],"sources":["../../../src/hooks/useFromTokenSufficiency.ts"],"sourcesContent":["import { parseUnits, type RouteExtended } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { keepPreviousData, useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { isRouteDone } from '../stores/routes/utils.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useTokenAddressBalance } from './useTokenAddressBalance.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nconst refetchInterval = 30_000\n\nexport const useFromTokenSufficiency = (\n route?: RouteExtended\n): {\n insufficientFromToken: boolean | undefined\n isLoading: boolean\n} => {\n const [fromChainId, fromTokenAddress, fromAmount] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'fromAmount'\n )\n const { keyPrefix } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n let chainId = fromChainId\n let tokenAddress = fromTokenAddress\n if (route) {\n chainId = route.fromToken.chainId\n tokenAddress = route.fromToken.address\n }\n\n const {\n token,\n chain,\n isLoading: isTokenAddressBalanceLoading,\n } = useTokenAddressBalance(chainId, tokenAddress)\n\n const { account } = useAccount({ chainType: chain?.chainType })\n\n const { data: insufficientFromToken, isLoading } = useQuery({\n queryKey: [\n getQueryKey('from-token-sufficiency-check', keyPrefix),\n account.address,\n chainId,\n tokenAddress,\n route?.id ?? fromAmount,\n ] as const,\n queryFn: async ({ queryKey: [, accountAddress] }) => {\n if (!accountAddress || !token) {\n return\n }\n const parsedFromAmount = parseUnits(fromAmount, token.decimals)\n let currentTokenBalance = token.amount ?? 0n\n\n if (!route || isRouteDone(route)) {\n const insufficientFunds = currentTokenBalance < parsedFromAmount\n return insufficientFunds\n }\n\n const currentAction = route.steps.filter(\n (step) => !step.execution || step.execution.status !== 'DONE'\n )[0]?.action\n\n if (\n token.chainId === currentAction.fromToken.chainId &&\n token.address === currentAction.fromToken.address &&\n currentTokenBalance > 0\n ) {\n const insufficientFunds = BigInt(route.fromAmount) > currentTokenBalance\n return insufficientFunds\n }\n\n const tokenBalances = await getTokenBalancesWithRetry(\n sdkClient,\n accountAddress,\n [currentAction.fromToken]\n )\n\n currentTokenBalance = tokenBalances?.[0]?.amount ?? 0n\n const insufficientFunds =\n BigInt(currentAction.fromAmount) > currentTokenBalance\n return insufficientFunds\n },\n\n enabled: Boolean(account.address && token && !isTokenAddressBalanceLoading),\n refetchInterval,\n staleTime: refetchInterval,\n placeholderData: account.address ? keepPreviousData : undefined,\n })\n\n return {\n insufficientFromToken,\n isLoading,\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,kBAAkB;AAExB,MAAa,2BACX,UAIG;CACH,MAAM,CAAC,aAAa,kBAAkB,cAAc,eAClD,aACA,aACA,aACD;CACD,MAAM,EAAE,cAAc,iBAAiB;CACvC,MAAM,YAAY,cAAc;CAEhC,IAAI,UAAU;CACd,IAAI,eAAe;AACnB,KAAI,OAAO;AACT,YAAU,MAAM,UAAU;AAC1B,iBAAe,MAAM,UAAU;;CAGjC,MAAM,EACJ,OACA,OACA,WAAW,iCACT,uBAAuB,SAAS,aAAa;CAEjD,MAAM,EAAE,YAAY,WAAW,EAAE,WAAW,OAAO,WAAW,CAAC;CAE/D,MAAM,EAAE,MAAM,uBAAuB,cAAc,SAAS;EAC1D,UAAU;GACR,YAAY,gCAAgC,UAAU;GACtD,QAAQ;GACR;GACA;GACA,OAAO,MAAM;GACd;EACD,SAAS,OAAO,EAAE,UAAU,GAAG,sBAAsB;AACnD,OAAI,CAAC,kBAAkB,CAAC,MACtB;GAEF,MAAM,mBAAmB,WAAW,YAAY,MAAM,SAAS;GAC/D,IAAI,sBAAsB,MAAM,UAAU;AAE1C,OAAI,CAAC,SAAS,YAAY,MAAM,CAE9B,QAD0B,sBAAsB;GAIlD,MAAM,gBAAgB,MAAM,MAAM,QAC/B,SAAS,CAAC,KAAK,aAAa,KAAK,UAAU,WAAW,OACxD,CAAC,IAAI;AAEN,OACE,MAAM,YAAY,cAAc,UAAU,WAC1C,MAAM,YAAY,cAAc,UAAU,WAC1C,sBAAsB,EAGtB,QAD0B,OAAO,MAAM,WAAW,GAAG;AAUvD,0BAAsB,MANM,0BAC1B,WACA,gBACA,CAAC,cAAc,UAAU,CAC1B,IAEqC,IAAI,UAAU;AAGpD,UADE,OAAO,cAAc,WAAW,GAAG;;EAIvC,SAAS,QAAQ,QAAQ,WAAW,SAAS,CAAC,6BAA6B;EAC3E;EACA,WAAW;EACX,iBAAiB,QAAQ,UAAU,mBAAmB,KAAA;EACvD,CAAC;AAEF,QAAO;EACL;EACA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGasRecommendation.js","names":[],"sources":["../../../src/hooks/useGasRecommendation.ts"],"sourcesContent":["import { type ChainId, getGasRecommendation } from '@lifi/sdk'\nimport type { UseQueryResult } from '@tanstack/react-query'\nimport { useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { HiddenUI } from '../types/widget.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nconst refetchInterval = 60_000\n\nexport const useGasRecommendation = (\n toChainId?: ChainId,\n fromChain?: ChainId,\n fromToken?: string\n): UseQueryResult<Awaited<ReturnType<typeof getGasRecommendation>> | null> => {\n const { chains } = useAvailableChains()\n const { keyPrefix, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const checkRecommendationLiFuel =\n Boolean(toChainId) &&\n Boolean(fromChain) &&\n Boolean(fromToken) &&\n Boolean(chains?.length)\n\n const checkRecommendationMaxButton =\n Boolean(toChainId) && !fromChain && !fromToken && Boolean(chains?.length)\n\n return useQuery({\n queryKey: [\n getQueryKey('gas-recommendation', keyPrefix),\n toChainId,\n fromChain,\n fromToken,\n ],\n queryFn: async ({\n queryKey: [_, toChainId, fromChain, fromToken],\n signal,\n }) => {\n if (!chains?.some((chain) => chain.id === toChainId)) {\n return null\n }\n const gasRecommendation = await getGasRecommendation(\n sdkClient,\n {\n chainId: toChainId as ChainId,\n fromChain: fromChain as ChainId,\n fromToken: fromToken as string,\n },\n { signal }\n )\n return gasRecommendation\n },\n enabled:\n (checkRecommendationLiFuel || checkRecommendationMaxButton) &&\n !hiddenUI?.includes(HiddenUI.GasRefuelMessage),\n refetchInterval,\n staleTime: refetchInterval,\n })\n}\n"],"mappings":";;;;;;;;AASA,MAAM,kBAAkB;AAExB,MAAa,wBACX,WACA,WACA,cAC4E;CAC5E,MAAM,EAAE,WAAW,oBAAoB;CACvC,MAAM,EAAE,WAAW,aAAa,iBAAiB;CACjD,MAAM,YAAY,cAAc;CAEhC,MAAM,4BACJ,QAAQ,UAAU,IAClB,QAAQ,UAAU,IAClB,QAAQ,UAAU,IAClB,QAAQ,QAAQ,OAAO;CAEzB,MAAM,+BACJ,QAAQ,UAAU,IAAI,CAAC,aAAa,CAAC,aAAa,QAAQ,QAAQ,OAAO;AAE3E,QAAO,SAAS;EACd,UAAU;GACR,YAAY,sBAAsB,UAAU;GAC5C;GACA;GACA;GACD;EACD,SAAS,OAAO,EACd,UAAU,CAAC,GAAG,WAAW,WAAW,YACpC,aACI;AACJ,OAAI,CAAC,QAAQ,MAAM,UAAU,MAAM,OAAO,UAAU,CAClD,QAAO;AAWT,
|
|
1
|
+
{"version":3,"file":"useGasRecommendation.js","names":[],"sources":["../../../src/hooks/useGasRecommendation.ts"],"sourcesContent":["import { type ChainId, getGasRecommendation } from '@lifi/sdk'\nimport type { UseQueryResult } from '@tanstack/react-query'\nimport { useQuery } from '@tanstack/react-query'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { HiddenUI } from '../types/widget.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\n\nconst refetchInterval = 60_000\n\nexport const useGasRecommendation = (\n toChainId?: ChainId,\n fromChain?: ChainId,\n fromToken?: string\n): UseQueryResult<Awaited<ReturnType<typeof getGasRecommendation>> | null> => {\n const { chains } = useAvailableChains()\n const { keyPrefix, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const checkRecommendationLiFuel =\n Boolean(toChainId) &&\n Boolean(fromChain) &&\n Boolean(fromToken) &&\n Boolean(chains?.length)\n\n const checkRecommendationMaxButton =\n Boolean(toChainId) && !fromChain && !fromToken && Boolean(chains?.length)\n\n return useQuery({\n queryKey: [\n getQueryKey('gas-recommendation', keyPrefix),\n toChainId,\n fromChain,\n fromToken,\n ],\n queryFn: async ({\n queryKey: [_, toChainId, fromChain, fromToken],\n signal,\n }) => {\n if (!chains?.some((chain) => chain.id === toChainId)) {\n return null\n }\n const gasRecommendation = await getGasRecommendation(\n sdkClient,\n {\n chainId: toChainId as ChainId,\n fromChain: fromChain as ChainId,\n fromToken: fromToken as string,\n },\n { signal }\n )\n return gasRecommendation\n },\n enabled:\n (checkRecommendationLiFuel || checkRecommendationMaxButton) &&\n !hiddenUI?.includes(HiddenUI.GasRefuelMessage),\n refetchInterval,\n staleTime: refetchInterval,\n })\n}\n"],"mappings":";;;;;;;;AASA,MAAM,kBAAkB;AAExB,MAAa,wBACX,WACA,WACA,cAC4E;CAC5E,MAAM,EAAE,WAAW,oBAAoB;CACvC,MAAM,EAAE,WAAW,aAAa,iBAAiB;CACjD,MAAM,YAAY,cAAc;CAEhC,MAAM,4BACJ,QAAQ,UAAU,IAClB,QAAQ,UAAU,IAClB,QAAQ,UAAU,IAClB,QAAQ,QAAQ,OAAO;CAEzB,MAAM,+BACJ,QAAQ,UAAU,IAAI,CAAC,aAAa,CAAC,aAAa,QAAQ,QAAQ,OAAO;AAE3E,QAAO,SAAS;EACd,UAAU;GACR,YAAY,sBAAsB,UAAU;GAC5C;GACA;GACA;GACD;EACD,SAAS,OAAO,EACd,UAAU,CAAC,GAAG,WAAW,WAAW,YACpC,aACI;AACJ,OAAI,CAAC,QAAQ,MAAM,UAAU,MAAM,OAAO,UAAU,CAClD,QAAO;AAWT,UAAO,MATyB,qBAC9B,WACA;IACE,SAAS;IACE;IACA;IACZ,EACD,EAAE,QAAQ,CACX;;EAGH,UACG,6BAA6B,iCAC9B,CAAC,UAAU,SAAA,mBAAmC;EAChD;EACA,WAAW;EACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGasRefuel.js","names":[],"sources":["../../../src/hooks/useGasRefuel.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { HiddenUI } from '../types/widget.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useGasRecommendation } from './useGasRecommendation.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { useTokenBalance } from './useTokenBalance.js'\n\nexport const useGasRefuel = (): {\n enabled: boolean\n availble: boolean | undefined\n isLoading: boolean\n chain: ExtendedChain | undefined\n fromAmount: string | undefined\n} => {\n const { getChainById } = useAvailableChains()\n const { hiddenUI } = useWidgetConfig()\n const [fromChainId, fromTokenAddress, toChainId, toAddress] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'toChain',\n 'toAddress'\n )\n\n const toChain = getChainById(toChainId)\n const fromChain = getChainById(fromChainId)\n\n const { account: toAccount } = useAccount({ chainType: toChain?.chainType })\n\n const effectiveToAddress = toAddress || toAccount?.address\n\n const { isContractAddress: isToContractAddress } = useIsContractAddress(\n effectiveToAddress,\n toChainId,\n toChain?.chainType\n )\n\n const { token: destinationNativeToken } = useTokenBalance(\n effectiveToAddress,\n toChainId ? toChain?.nativeToken : undefined\n )\n\n const { data: gasRecommendation, isLoading } = useGasRecommendation(\n toChainId,\n fromChainId,\n fromTokenAddress\n )\n\n // When we bridge between ecosystems we need to be sure toAddress is set\n const isChainTypeSatisfied =\n fromChain?.chainType !== toChain?.chainType ? Boolean(toAddress) : true\n\n // We should not refuel to the contract address\n const isToAddressSatisfied = effectiveToAddress && !isToContractAddress\n\n const enabled = useMemo(() => {\n if (\n // Same chain refuel is not allowed since users need gas on source chain to initiate transaction\n // We allow refuel when bridging to native token since bridging routes may require gas for destination swaps\n fromChainId === toChainId ||\n !gasRecommendation?.available ||\n !gasRecommendation?.recommended ||\n !destinationNativeToken ||\n !isChainTypeSatisfied ||\n !isToAddressSatisfied ||\n hiddenUI?.includes(HiddenUI.GasRefuelMessage)\n ) {\n return false\n }\n const tokenBalance = destinationNativeToken.amount ?? 0n\n\n // Check if the user balance < 50% of the recommended amount\n const recommendedAmount = BigInt(gasRecommendation.recommended.amount) / 2n\n\n const insufficientGas = tokenBalance < recommendedAmount\n return insufficientGas\n }, [\n fromChainId,\n gasRecommendation,\n isChainTypeSatisfied,\n isToAddressSatisfied,\n destinationNativeToken,\n toChainId,\n hiddenUI,\n ])\n\n return {\n enabled: enabled,\n availble: gasRecommendation?.available,\n isLoading: isLoading,\n chain: toChain,\n fromAmount: gasRecommendation?.available\n ? gasRecommendation.fromAmount\n : undefined,\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAa,qBAMR;CACH,MAAM,EAAE,iBAAiB,oBAAoB;CAC7C,MAAM,EAAE,aAAa,iBAAiB;CACtC,MAAM,CAAC,aAAa,kBAAkB,WAAW,aAAa,eAC5D,aACA,aACA,WACA,YACD;CAED,MAAM,UAAU,aAAa,UAAU;CACvC,MAAM,YAAY,aAAa,YAAY;CAE3C,MAAM,EAAE,SAAS,cAAc,WAAW,EAAE,WAAW,SAAS,WAAW,CAAC;CAE5E,MAAM,qBAAqB,aAAa,WAAW;CAEnD,MAAM,EAAE,mBAAmB,wBAAwB,qBACjD,oBACA,WACA,SAAS,UACV;CAED,MAAM,EAAE,OAAO,2BAA2B,gBACxC,oBACA,YAAY,SAAS,cAAc,KAAA,EACpC;CAED,MAAM,EAAE,MAAM,mBAAmB,cAAc,qBAC7C,WACA,aACA,iBACD;CAGD,MAAM,uBACJ,WAAW,cAAc,SAAS,YAAY,QAAQ,UAAU,GAAG;CAGrE,MAAM,uBAAuB,sBAAsB,CAAC;AAiCpD,QAAO;EACL,SAhCc,cAAc;AAC5B,OAGE,gBAAgB,aAChB,CAAC,mBAAmB,aACpB,CAAC,mBAAmB,eACpB,CAAC,0BACD,CAAC,wBACD,CAAC,wBACD,UAAU,SAAA,mBAAmC,CAE7C,QAAO;AAQT,WANqB,uBAAuB,UAAU,MAG5B,OAAO,kBAAkB,YAAY,OAAO,GAAG;KAIxE;GACD;GACA;GACA;GACA;GACA;GACA;GACA;GACD,
|
|
1
|
+
{"version":3,"file":"useGasRefuel.js","names":[],"sources":["../../../src/hooks/useGasRefuel.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useMemo } from 'react'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { HiddenUI } from '../types/widget.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useGasRecommendation } from './useGasRecommendation.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { useTokenBalance } from './useTokenBalance.js'\n\nexport const useGasRefuel = (): {\n enabled: boolean\n availble: boolean | undefined\n isLoading: boolean\n chain: ExtendedChain | undefined\n fromAmount: string | undefined\n} => {\n const { getChainById } = useAvailableChains()\n const { hiddenUI } = useWidgetConfig()\n const [fromChainId, fromTokenAddress, toChainId, toAddress] = useFieldValues(\n 'fromChain',\n 'fromToken',\n 'toChain',\n 'toAddress'\n )\n\n const toChain = getChainById(toChainId)\n const fromChain = getChainById(fromChainId)\n\n const { account: toAccount } = useAccount({ chainType: toChain?.chainType })\n\n const effectiveToAddress = toAddress || toAccount?.address\n\n const { isContractAddress: isToContractAddress } = useIsContractAddress(\n effectiveToAddress,\n toChainId,\n toChain?.chainType\n )\n\n const { token: destinationNativeToken } = useTokenBalance(\n effectiveToAddress,\n toChainId ? toChain?.nativeToken : undefined\n )\n\n const { data: gasRecommendation, isLoading } = useGasRecommendation(\n toChainId,\n fromChainId,\n fromTokenAddress\n )\n\n // When we bridge between ecosystems we need to be sure toAddress is set\n const isChainTypeSatisfied =\n fromChain?.chainType !== toChain?.chainType ? Boolean(toAddress) : true\n\n // We should not refuel to the contract address\n const isToAddressSatisfied = effectiveToAddress && !isToContractAddress\n\n const enabled = useMemo(() => {\n if (\n // Same chain refuel is not allowed since users need gas on source chain to initiate transaction\n // We allow refuel when bridging to native token since bridging routes may require gas for destination swaps\n fromChainId === toChainId ||\n !gasRecommendation?.available ||\n !gasRecommendation?.recommended ||\n !destinationNativeToken ||\n !isChainTypeSatisfied ||\n !isToAddressSatisfied ||\n hiddenUI?.includes(HiddenUI.GasRefuelMessage)\n ) {\n return false\n }\n const tokenBalance = destinationNativeToken.amount ?? 0n\n\n // Check if the user balance < 50% of the recommended amount\n const recommendedAmount = BigInt(gasRecommendation.recommended.amount) / 2n\n\n const insufficientGas = tokenBalance < recommendedAmount\n return insufficientGas\n }, [\n fromChainId,\n gasRecommendation,\n isChainTypeSatisfied,\n isToAddressSatisfied,\n destinationNativeToken,\n toChainId,\n hiddenUI,\n ])\n\n return {\n enabled: enabled,\n availble: gasRecommendation?.available,\n isLoading: isLoading,\n chain: toChain,\n fromAmount: gasRecommendation?.available\n ? gasRecommendation.fromAmount\n : undefined,\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAa,qBAMR;CACH,MAAM,EAAE,iBAAiB,oBAAoB;CAC7C,MAAM,EAAE,aAAa,iBAAiB;CACtC,MAAM,CAAC,aAAa,kBAAkB,WAAW,aAAa,eAC5D,aACA,aACA,WACA,YACD;CAED,MAAM,UAAU,aAAa,UAAU;CACvC,MAAM,YAAY,aAAa,YAAY;CAE3C,MAAM,EAAE,SAAS,cAAc,WAAW,EAAE,WAAW,SAAS,WAAW,CAAC;CAE5E,MAAM,qBAAqB,aAAa,WAAW;CAEnD,MAAM,EAAE,mBAAmB,wBAAwB,qBACjD,oBACA,WACA,SAAS,UACV;CAED,MAAM,EAAE,OAAO,2BAA2B,gBACxC,oBACA,YAAY,SAAS,cAAc,KAAA,EACpC;CAED,MAAM,EAAE,MAAM,mBAAmB,cAAc,qBAC7C,WACA,aACA,iBACD;CAGD,MAAM,uBACJ,WAAW,cAAc,SAAS,YAAY,QAAQ,UAAU,GAAG;CAGrE,MAAM,uBAAuB,sBAAsB,CAAC;AAiCpD,QAAO;EACL,SAhCc,cAAc;AAC5B,OAGE,gBAAgB,aAChB,CAAC,mBAAmB,aACpB,CAAC,mBAAmB,eACpB,CAAC,0BACD,CAAC,wBACD,CAAC,wBACD,UAAU,SAAA,mBAAmC,CAE7C,QAAO;AAQT,WANqB,uBAAuB,UAAU,MAG5B,OAAO,kBAAkB,YAAY,OAAO,GAAG;KAIxE;GACD;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAGiB;EAChB,UAAU,mBAAmB;EAClB;EACX,OAAO;EACP,YAAY,mBAAmB,YAC3B,kBAAkB,aAClB,KAAA;EACL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGasSufficiency.js","names":[],"sources":["../../../src/hooks/useGasSufficiency.ts"],"sourcesContent":["import type { EVMChain, RouteExtended, Token, TokenAmount } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { HiddenUI } from '../types/widget.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nexport interface GasSufficiency {\n gasAmount: bigint\n tokenAmount?: bigint\n insufficientAmount?: bigint\n insufficient?: boolean\n token: Token\n chain?: EVMChain\n}\n\nconst refetchInterval = 30_000\n\nexport const useGasSufficiency = (\n route?: RouteExtended\n): {\n insufficientGas: GasSufficiency[] | undefined\n isLoading: boolean\n} => {\n const { getChainById } = useAvailableChains()\n const { account: EVMAccount, accounts } = useAccount({\n chainType: ChainType.EVM,\n })\n const { keyPrefix, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const { relevantAccounts, relevantAccountsQueryKey } = useMemo(() => {\n const chainTypes = route?.steps.reduce((acc, step) => {\n const chainType = getChainById(step.action.fromChainId)?.chainType\n if (chainType) {\n acc.add(chainType)\n }\n return acc\n }, new Set<ChainType>())\n\n const relevantAccounts = accounts.filter(\n (account) =>\n account.isConnected &&\n account.address &&\n chainTypes?.has(account.chainType)\n )\n return {\n relevantAccounts,\n relevantAccountsQueryKey: relevantAccounts\n .map((account) => account.address)\n .join(','),\n }\n }, [accounts, route?.steps, getChainById])\n\n const { isContractAddress, isLoading: isContractAddressLoading } =\n useIsContractAddress(\n EVMAccount.address,\n route?.fromChainId,\n EVMAccount.chainType\n )\n\n const { data: insufficientGas, isLoading } = useQuery<GasSufficiency[]>({\n queryKey: [\n getQueryKey('gas-sufficiency-check', keyPrefix),\n relevantAccountsQueryKey,\n route?.id,\n isContractAddress,\n ] as const,\n queryFn: async () => {\n if (!route) {\n return []\n }\n\n // Filter out steps that are relayer steps or have primaryType 'Permit' or 'Order'\n const filteredSteps = route.steps.filter(\n (step) =>\n !step.typedData?.some(\n (t) => t.primaryType === 'Permit' || t.primaryType === 'Order'\n )\n )\n\n // If all steps are filtered out, we don't need to check for gas sufficiency\n if (!filteredSteps.length) {\n return []\n }\n\n // We assume that LI.Fuel protocol always refuels the destination chain\n const hasRefuelStep = route.steps\n .flatMap((step) => step.includedSteps)\n .some((includedStep) => includedStep.tool === 'gasZip')\n\n const gasCosts = filteredSteps\n .filter((step) => !step.execution || step.execution.status !== 'DONE')\n .reduce(\n (groupedGasCosts, step) => {\n // We need to avoid destination chain step sufficiency check if we have LI.Fuel protocol sub-step\n const skipDueToRefuel =\n step.action.fromChainId === route.toChainId && hasRefuelStep\n if (step.estimate.gasCosts && !skipDueToRefuel) {\n const { token } = step.estimate.gasCosts[0]\n const gasCostAmount = step.estimate.gasCosts.reduce(\n (amount, gasCost) =>\n amount + BigInt(Number(gasCost.amount).toFixed(0)),\n 0n\n )\n if (gasCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + gasCostAmount\n : gasCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n // Add fees paid in native tokens to gas sufficiency check (included: false)\n const nonIncludedFeeCosts = step.estimate.feeCosts?.filter(\n (feeCost) => !feeCost.included\n )\n if (nonIncludedFeeCosts?.length) {\n const { token } = nonIncludedFeeCosts[0]\n const feeCostAmount = nonIncludedFeeCosts.reduce(\n (amount, feeCost) =>\n amount + BigInt(Number(feeCost.amount).toFixed(0)),\n 0n\n )\n if (feeCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + feeCostAmount\n : feeCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n return groupedGasCosts\n },\n {} as Record<string, GasSufficiency>\n )\n\n // Check whether we are sending a native token\n // For native tokens we want to check for the total amount, including the network fee\n if (\n route.fromToken.address === gasCosts[route.fromChainId]?.token.address\n ) {\n gasCosts[route.fromChainId].tokenAmount =\n gasCosts[route.fromChainId]?.gasAmount + BigInt(route.fromAmount)\n }\n\n const gasCostsValues = Object.values(gasCosts)\n\n const balanceChecks = await Promise.allSettled(\n relevantAccounts.map((account) => {\n const relevantTokens = gasCostsValues\n .filter((gasCost) => gasCost.chain?.chainType === account.chainType)\n .map((item) => item.token)\n\n return getTokenBalancesWithRetry(\n sdkClient,\n account.address!,\n relevantTokens\n )\n })\n )\n\n const tokenBalances = balanceChecks\n .filter(\n (result): result is PromiseFulfilledResult<TokenAmount[]> =>\n result.status === 'fulfilled' && Boolean(result.value)\n )\n .flatMap((result) => result.value)\n\n if (!tokenBalances?.length) {\n return []\n }\n\n Object.keys(gasCosts).forEach((chainId) => {\n if (gasCosts[chainId]) {\n const gasTokenBalance =\n tokenBalances?.find(\n (t) =>\n t.chainId === gasCosts[chainId].token.chainId &&\n t.address === gasCosts[chainId].token.address\n )?.amount ?? 0n\n const insufficient =\n gasTokenBalance <= 0n ||\n gasTokenBalance < gasCosts[chainId].gasAmount ||\n gasTokenBalance < (gasCosts[chainId].tokenAmount ?? 0n)\n\n const insufficientAmount = insufficient\n ? gasCosts[chainId].tokenAmount\n ? gasCosts[chainId].tokenAmount! - gasTokenBalance\n : gasCosts[chainId].gasAmount - gasTokenBalance\n : undefined\n\n gasCosts[chainId] = {\n ...gasCosts[chainId],\n insufficient,\n insufficientAmount,\n chain: insufficient ? getChainById(Number(chainId)) : undefined,\n }\n }\n })\n\n const gasCostResult = Object.values(gasCosts).filter(\n (gasCost) => gasCost.insufficient\n )\n\n return gasCostResult\n },\n\n enabled: Boolean(\n !isContractAddress &&\n !isContractAddressLoading &&\n relevantAccounts.length > 0 &&\n route &&\n !hiddenUI?.includes(HiddenUI.InsufficientGasMessage)\n ),\n refetchInterval,\n staleTime: refetchInterval,\n })\n\n return {\n insufficientGas,\n isLoading,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useGasSufficiency.js","names":[],"sources":["../../../src/hooks/useGasSufficiency.ts"],"sourcesContent":["import type { EVMChain, RouteExtended, Token, TokenAmount } from '@lifi/sdk'\nimport { ChainType } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { useQuery } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useSDKClient } from '../providers/SDKClientProvider.js'\nimport { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'\nimport { HiddenUI } from '../types/widget.js'\nimport { getQueryKey } from '../utils/queries.js'\nimport { useAvailableChains } from './useAvailableChains.js'\nimport { useIsContractAddress } from './useIsContractAddress.js'\nimport { getTokenBalancesWithRetry } from './useTokenBalance.js'\n\nexport interface GasSufficiency {\n gasAmount: bigint\n tokenAmount?: bigint\n insufficientAmount?: bigint\n insufficient?: boolean\n token: Token\n chain?: EVMChain\n}\n\nconst refetchInterval = 30_000\n\nexport const useGasSufficiency = (\n route?: RouteExtended\n): {\n insufficientGas: GasSufficiency[] | undefined\n isLoading: boolean\n} => {\n const { getChainById } = useAvailableChains()\n const { account: EVMAccount, accounts } = useAccount({\n chainType: ChainType.EVM,\n })\n const { keyPrefix, hiddenUI } = useWidgetConfig()\n const sdkClient = useSDKClient()\n\n const { relevantAccounts, relevantAccountsQueryKey } = useMemo(() => {\n const chainTypes = route?.steps.reduce((acc, step) => {\n const chainType = getChainById(step.action.fromChainId)?.chainType\n if (chainType) {\n acc.add(chainType)\n }\n return acc\n }, new Set<ChainType>())\n\n const relevantAccounts = accounts.filter(\n (account) =>\n account.isConnected &&\n account.address &&\n chainTypes?.has(account.chainType)\n )\n return {\n relevantAccounts,\n relevantAccountsQueryKey: relevantAccounts\n .map((account) => account.address)\n .join(','),\n }\n }, [accounts, route?.steps, getChainById])\n\n const { isContractAddress, isLoading: isContractAddressLoading } =\n useIsContractAddress(\n EVMAccount.address,\n route?.fromChainId,\n EVMAccount.chainType\n )\n\n const { data: insufficientGas, isLoading } = useQuery<GasSufficiency[]>({\n queryKey: [\n getQueryKey('gas-sufficiency-check', keyPrefix),\n relevantAccountsQueryKey,\n route?.id,\n isContractAddress,\n ] as const,\n queryFn: async () => {\n if (!route) {\n return []\n }\n\n // Filter out steps that are relayer steps or have primaryType 'Permit' or 'Order'\n const filteredSteps = route.steps.filter(\n (step) =>\n !step.typedData?.some(\n (t) => t.primaryType === 'Permit' || t.primaryType === 'Order'\n )\n )\n\n // If all steps are filtered out, we don't need to check for gas sufficiency\n if (!filteredSteps.length) {\n return []\n }\n\n // We assume that LI.Fuel protocol always refuels the destination chain\n const hasRefuelStep = route.steps\n .flatMap((step) => step.includedSteps)\n .some((includedStep) => includedStep.tool === 'gasZip')\n\n const gasCosts = filteredSteps\n .filter((step) => !step.execution || step.execution.status !== 'DONE')\n .reduce(\n (groupedGasCosts, step) => {\n // We need to avoid destination chain step sufficiency check if we have LI.Fuel protocol sub-step\n const skipDueToRefuel =\n step.action.fromChainId === route.toChainId && hasRefuelStep\n if (step.estimate.gasCosts && !skipDueToRefuel) {\n const { token } = step.estimate.gasCosts[0]\n const gasCostAmount = step.estimate.gasCosts.reduce(\n (amount, gasCost) =>\n amount + BigInt(Number(gasCost.amount).toFixed(0)),\n 0n\n )\n if (gasCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + gasCostAmount\n : gasCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n // Add fees paid in native tokens to gas sufficiency check (included: false)\n const nonIncludedFeeCosts = step.estimate.feeCosts?.filter(\n (feeCost) => !feeCost.included\n )\n if (nonIncludedFeeCosts?.length) {\n const { token } = nonIncludedFeeCosts[0]\n const feeCostAmount = nonIncludedFeeCosts.reduce(\n (amount, feeCost) =>\n amount + BigInt(Number(feeCost.amount).toFixed(0)),\n 0n\n )\n if (feeCostAmount > 0n) {\n groupedGasCosts[token.chainId] = {\n gasAmount: groupedGasCosts[token.chainId]\n ? groupedGasCosts[token.chainId].gasAmount + feeCostAmount\n : feeCostAmount,\n token,\n chain: getChainById(token.chainId),\n }\n }\n }\n return groupedGasCosts\n },\n {} as Record<string, GasSufficiency>\n )\n\n // Check whether we are sending a native token\n // For native tokens we want to check for the total amount, including the network fee\n if (\n route.fromToken.address === gasCosts[route.fromChainId]?.token.address\n ) {\n gasCosts[route.fromChainId].tokenAmount =\n gasCosts[route.fromChainId]?.gasAmount + BigInt(route.fromAmount)\n }\n\n const gasCostsValues = Object.values(gasCosts)\n\n const balanceChecks = await Promise.allSettled(\n relevantAccounts.map((account) => {\n const relevantTokens = gasCostsValues\n .filter((gasCost) => gasCost.chain?.chainType === account.chainType)\n .map((item) => item.token)\n\n return getTokenBalancesWithRetry(\n sdkClient,\n account.address!,\n relevantTokens\n )\n })\n )\n\n const tokenBalances = balanceChecks\n .filter(\n (result): result is PromiseFulfilledResult<TokenAmount[]> =>\n result.status === 'fulfilled' && Boolean(result.value)\n )\n .flatMap((result) => result.value)\n\n if (!tokenBalances?.length) {\n return []\n }\n\n Object.keys(gasCosts).forEach((chainId) => {\n if (gasCosts[chainId]) {\n const gasTokenBalance =\n tokenBalances?.find(\n (t) =>\n t.chainId === gasCosts[chainId].token.chainId &&\n t.address === gasCosts[chainId].token.address\n )?.amount ?? 0n\n const insufficient =\n gasTokenBalance <= 0n ||\n gasTokenBalance < gasCosts[chainId].gasAmount ||\n gasTokenBalance < (gasCosts[chainId].tokenAmount ?? 0n)\n\n const insufficientAmount = insufficient\n ? gasCosts[chainId].tokenAmount\n ? gasCosts[chainId].tokenAmount! - gasTokenBalance\n : gasCosts[chainId].gasAmount - gasTokenBalance\n : undefined\n\n gasCosts[chainId] = {\n ...gasCosts[chainId],\n insufficient,\n insufficientAmount,\n chain: insufficient ? getChainById(Number(chainId)) : undefined,\n }\n }\n })\n\n const gasCostResult = Object.values(gasCosts).filter(\n (gasCost) => gasCost.insufficient\n )\n\n return gasCostResult\n },\n\n enabled: Boolean(\n !isContractAddress &&\n !isContractAddressLoading &&\n relevantAccounts.length > 0 &&\n route &&\n !hiddenUI?.includes(HiddenUI.InsufficientGasMessage)\n ),\n refetchInterval,\n staleTime: refetchInterval,\n })\n\n return {\n insufficientGas,\n isLoading,\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIsContractAddress.js","names":[],"sources":["../../../src/hooks/useIsContractAddress.ts"],"sourcesContent":["import { ChainType } from '@lifi/sdk'\nimport { useEthereumContext } from '@lifi/widget-provider'\nimport { useQuery } from '@tanstack/react-query'\n\nexport const useIsContractAddress = (\n address?: string,\n chainId?: number,\n chainType?: ChainType\n): {\n isContractAddress: boolean\n contractCode?: string\n isLoading: boolean\n isFetched: boolean\n} => {\n const { getBytecode } = useEthereumContext()\n\n const {\n data: contractCode,\n isLoading,\n isFetched,\n } = useQuery({\n queryKey: ['getBytecode', address, chainId],\n queryFn: async () => {\n const code = await getBytecode?.(chainId!, address!)\n return code ?? null\n },\n refetchInterval: 300_000,\n staleTime: 300_000,\n enabled:\n chainType === ChainType.EVM && !!chainId && !!address && !!getBytecode,\n })\n\n return {\n isContractAddress: !!contractCode,\n contractCode: contractCode ?? undefined,\n isLoading,\n isFetched,\n }\n}\n"],"mappings":";;;;AAIA,MAAa,wBACX,SACA,SACA,cAMG;CACH,MAAM,EAAE,gBAAgB,oBAAoB;CAE5C,MAAM,EACJ,MAAM,cACN,WACA,cACE,SAAS;EACX,UAAU;GAAC;GAAe;GAAS;GAAQ;EAC3C,SAAS,YAAY;AAEnB,
|
|
1
|
+
{"version":3,"file":"useIsContractAddress.js","names":[],"sources":["../../../src/hooks/useIsContractAddress.ts"],"sourcesContent":["import { ChainType } from '@lifi/sdk'\nimport { useEthereumContext } from '@lifi/widget-provider'\nimport { useQuery } from '@tanstack/react-query'\n\nexport const useIsContractAddress = (\n address?: string,\n chainId?: number,\n chainType?: ChainType\n): {\n isContractAddress: boolean\n contractCode?: string\n isLoading: boolean\n isFetched: boolean\n} => {\n const { getBytecode } = useEthereumContext()\n\n const {\n data: contractCode,\n isLoading,\n isFetched,\n } = useQuery({\n queryKey: ['getBytecode', address, chainId],\n queryFn: async () => {\n const code = await getBytecode?.(chainId!, address!)\n return code ?? null\n },\n refetchInterval: 300_000,\n staleTime: 300_000,\n enabled:\n chainType === ChainType.EVM && !!chainId && !!address && !!getBytecode,\n })\n\n return {\n isContractAddress: !!contractCode,\n contractCode: contractCode ?? undefined,\n isLoading,\n isFetched,\n }\n}\n"],"mappings":";;;;AAIA,MAAa,wBACX,SACA,SACA,cAMG;CACH,MAAM,EAAE,gBAAgB,oBAAoB;CAE5C,MAAM,EACJ,MAAM,cACN,WACA,cACE,SAAS;EACX,UAAU;GAAC;GAAe;GAAS;GAAQ;EAC3C,SAAS,YAAY;AAEnB,UAAO,MADY,cAAc,SAAU,QAAS,IACrC;;EAEjB,iBAAiB;EACjB,WAAW;EACX,SACE,cAAc,UAAU,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CAAC;EAC9D,CAAC;AAEF,QAAO;EACL,mBAAmB,CAAC,CAAC;EACrB,cAAc,gBAAgB,KAAA;EAC9B;EACA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useListHeight.js","names":[],"sources":["../../../src/hooks/useListHeight.ts"],"sourcesContent":["import { debounce, useTheme } from '@mui/material'\nimport type { RefObject } from 'react'\nimport { useLayoutEffect, useState } from 'react'\nimport {\n ElementId,\n getAppContainer,\n getHeaderElement,\n getScrollableContainer,\n} from '../utils/elements.js'\nimport { useDefaultElementId } from './useDefaultElementId.js'\n\nconst getContentHeight = (\n elementId: string,\n listParentRef: RefObject<HTMLUListElement | HTMLDivElement | null>\n) => {\n const containerElement = getScrollableContainer(elementId)\n\n const headerElement = getHeaderElement(elementId)\n\n const listParentElement = listParentRef?.current\n\n let oldHeight: string | undefined\n\n // This covers the case where in full height flex mode when the browser height is reduced\n // - this allows a virtualised list to be made smaller\n if (listParentElement) {\n oldHeight = listParentElement.style.height\n listParentElement.style.height = '0'\n }\n\n if (!containerElement || !headerElement) {\n console.warn(\n `Can't find ${ElementId.ScrollableContainer} or ${ElementId.Header} id.`\n )\n return 0\n }\n const { height: containerHeight } = containerElement.getBoundingClientRect()\n const { height: headerHeight } = headerElement.getBoundingClientRect()\n\n // This covers the case where in full height flex mode when the browser height is reduced the\n // - this allows a virtualised list to be set to minimum size\n if (listParentElement && oldHeight) {\n listParentElement.style.height = oldHeight\n }\n\n return containerHeight - headerHeight\n}\n\ninterface UseContentHeightProps {\n listParentRef: RefObject<HTMLUListElement | HTMLDivElement | null>\n headerRef?: RefObject<HTMLElement | null>\n}\n\nconst defaultMinListHeight = 360\nconst minMobileListHeight = 160\n\n// NOTE: this hook is implicitly tied to the widget height functionality in the\n// AppExpandedContainer, RelativeContainer and CssBaselineContainer components as defined in AppContainer.ts\n// CSS changes in those components can have implications for the functionality in this hook\n\nexport const useListHeight = ({\n listParentRef,\n headerRef,\n}: UseContentHeightProps): { listHeight: number } => {\n const elementId = useDefaultElementId() ?? ''\n const [contentHeight, setContentHeight] = useState<number>(0)\n const theme = useTheme()\n\n useLayoutEffect(() => {\n const handleResize = () => {\n setContentHeight(getContentHeight(elementId, listParentRef))\n }\n\n const processResize = debounce(() => handleResize(), 40)\n\n // calling this on initial mount prevents the lists resizing appearing glitchy\n handleResize()\n\n const appContainer = getAppContainer(elementId)\n\n let resizeObserver: ResizeObserver\n if (appContainer) {\n resizeObserver = new ResizeObserver(processResize)\n resizeObserver.observe(appContainer)\n }\n\n return () => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n }\n }, [elementId, listParentRef])\n\n const minListHeight =\n theme.container?.height === '100%'\n ? minMobileListHeight\n : defaultMinListHeight\n\n const listHeight = Math.max(\n contentHeight - (headerRef?.current?.offsetHeight ?? 0),\n minListHeight\n )\n\n return {\n listHeight,\n }\n}\n"],"mappings":";;;;;AAWA,MAAM,oBACJ,WACA,kBACG;CACH,MAAM,mBAAmB,uBAAuB,UAAU;CAE1D,MAAM,gBAAgB,iBAAiB,UAAU;CAEjD,MAAM,oBAAoB,eAAe;CAEzC,IAAI;AAIJ,KAAI,mBAAmB;AACrB,cAAY,kBAAkB,MAAM;AACpC,oBAAkB,MAAM,SAAS;;AAGnC,KAAI,CAAC,oBAAoB,CAAC,eAAe;AACvC,UAAQ,KACN,8DACD;AACD,SAAO;;CAET,MAAM,EAAE,QAAQ,oBAAoB,iBAAiB,uBAAuB;CAC5E,MAAM,EAAE,QAAQ,iBAAiB,cAAc,uBAAuB;AAItE,KAAI,qBAAqB,UACvB,mBAAkB,MAAM,SAAS;AAGnC,QAAO,kBAAkB;;AAQ3B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAM5B,MAAa,iBAAiB,EAC5B,eACA,gBACmD;CACnD,MAAM,YAAY,qBAAqB,IAAI;CAC3C,MAAM,CAAC,eAAe,oBAAoB,SAAiB,EAAE;CAC7D,MAAM,QAAQ,UAAU;AAExB,uBAAsB;EACpB,MAAM,qBAAqB;AACzB,oBAAiB,iBAAiB,WAAW,cAAc,CAAC;;EAG9D,MAAM,gBAAgB,eAAe,cAAc,EAAE,GAAG;AAGxD,gBAAc;EAEd,MAAM,eAAe,gBAAgB,UAAU;EAE/C,IAAI;AACJ,MAAI,cAAc;AAChB,oBAAiB,IAAI,eAAe,cAAc;AAClD,kBAAe,QAAQ,aAAa;;AAGtC,eAAa;AACX,OAAI,eACF,gBAAe,YAAY;;IAG9B,CAAC,WAAW,cAAc,CAAC;CAE9B,MAAM,gBACJ,MAAM,WAAW,WAAW,SACxB,sBACA;AAON,QAAO,EACL,YANiB,KAAK,IACtB,iBAAiB,WAAW,SAAS,gBAAgB,IACrD,
|
|
1
|
+
{"version":3,"file":"useListHeight.js","names":[],"sources":["../../../src/hooks/useListHeight.ts"],"sourcesContent":["import { debounce, useTheme } from '@mui/material'\nimport type { RefObject } from 'react'\nimport { useLayoutEffect, useState } from 'react'\nimport {\n ElementId,\n getAppContainer,\n getHeaderElement,\n getScrollableContainer,\n} from '../utils/elements.js'\nimport { useDefaultElementId } from './useDefaultElementId.js'\n\nconst getContentHeight = (\n elementId: string,\n listParentRef: RefObject<HTMLUListElement | HTMLDivElement | null>\n) => {\n const containerElement = getScrollableContainer(elementId)\n\n const headerElement = getHeaderElement(elementId)\n\n const listParentElement = listParentRef?.current\n\n let oldHeight: string | undefined\n\n // This covers the case where in full height flex mode when the browser height is reduced\n // - this allows a virtualised list to be made smaller\n if (listParentElement) {\n oldHeight = listParentElement.style.height\n listParentElement.style.height = '0'\n }\n\n if (!containerElement || !headerElement) {\n console.warn(\n `Can't find ${ElementId.ScrollableContainer} or ${ElementId.Header} id.`\n )\n return 0\n }\n const { height: containerHeight } = containerElement.getBoundingClientRect()\n const { height: headerHeight } = headerElement.getBoundingClientRect()\n\n // This covers the case where in full height flex mode when the browser height is reduced the\n // - this allows a virtualised list to be set to minimum size\n if (listParentElement && oldHeight) {\n listParentElement.style.height = oldHeight\n }\n\n return containerHeight - headerHeight\n}\n\ninterface UseContentHeightProps {\n listParentRef: RefObject<HTMLUListElement | HTMLDivElement | null>\n headerRef?: RefObject<HTMLElement | null>\n}\n\nconst defaultMinListHeight = 360\nconst minMobileListHeight = 160\n\n// NOTE: this hook is implicitly tied to the widget height functionality in the\n// AppExpandedContainer, RelativeContainer and CssBaselineContainer components as defined in AppContainer.ts\n// CSS changes in those components can have implications for the functionality in this hook\n\nexport const useListHeight = ({\n listParentRef,\n headerRef,\n}: UseContentHeightProps): { listHeight: number } => {\n const elementId = useDefaultElementId() ?? ''\n const [contentHeight, setContentHeight] = useState<number>(0)\n const theme = useTheme()\n\n useLayoutEffect(() => {\n const handleResize = () => {\n setContentHeight(getContentHeight(elementId, listParentRef))\n }\n\n const processResize = debounce(() => handleResize(), 40)\n\n // calling this on initial mount prevents the lists resizing appearing glitchy\n handleResize()\n\n const appContainer = getAppContainer(elementId)\n\n let resizeObserver: ResizeObserver\n if (appContainer) {\n resizeObserver = new ResizeObserver(processResize)\n resizeObserver.observe(appContainer)\n }\n\n return () => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n }\n }, [elementId, listParentRef])\n\n const minListHeight =\n theme.container?.height === '100%'\n ? minMobileListHeight\n : defaultMinListHeight\n\n const listHeight = Math.max(\n contentHeight - (headerRef?.current?.offsetHeight ?? 0),\n minListHeight\n )\n\n return {\n listHeight,\n }\n}\n"],"mappings":";;;;;AAWA,MAAM,oBACJ,WACA,kBACG;CACH,MAAM,mBAAmB,uBAAuB,UAAU;CAE1D,MAAM,gBAAgB,iBAAiB,UAAU;CAEjD,MAAM,oBAAoB,eAAe;CAEzC,IAAI;AAIJ,KAAI,mBAAmB;AACrB,cAAY,kBAAkB,MAAM;AACpC,oBAAkB,MAAM,SAAS;;AAGnC,KAAI,CAAC,oBAAoB,CAAC,eAAe;AACvC,UAAQ,KACN,8DACD;AACD,SAAO;;CAET,MAAM,EAAE,QAAQ,oBAAoB,iBAAiB,uBAAuB;CAC5E,MAAM,EAAE,QAAQ,iBAAiB,cAAc,uBAAuB;AAItE,KAAI,qBAAqB,UACvB,mBAAkB,MAAM,SAAS;AAGnC,QAAO,kBAAkB;;AAQ3B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAM5B,MAAa,iBAAiB,EAC5B,eACA,gBACmD;CACnD,MAAM,YAAY,qBAAqB,IAAI;CAC3C,MAAM,CAAC,eAAe,oBAAoB,SAAiB,EAAE;CAC7D,MAAM,QAAQ,UAAU;AAExB,uBAAsB;EACpB,MAAM,qBAAqB;AACzB,oBAAiB,iBAAiB,WAAW,cAAc,CAAC;;EAG9D,MAAM,gBAAgB,eAAe,cAAc,EAAE,GAAG;AAGxD,gBAAc;EAEd,MAAM,eAAe,gBAAgB,UAAU;EAE/C,IAAI;AACJ,MAAI,cAAc;AAChB,oBAAiB,IAAI,eAAe,cAAc;AAClD,kBAAe,QAAQ,aAAa;;AAGtC,eAAa;AACX,OAAI,eACF,gBAAe,YAAY;;IAG9B,CAAC,WAAW,cAAc,CAAC;CAE9B,MAAM,gBACJ,MAAM,WAAW,WAAW,SACxB,sBACA;AAON,QAAO,EACL,YANiB,KAAK,IACtB,iBAAiB,WAAW,SAAS,gBAAgB,IACrD,cAIU,EACX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLongPress.js","names":[],"sources":["../../../src/hooks/useLongPress.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\n\nexport const useLongPress = (\n callback: () => void = () => {},\n ms: number = 500\n): {\n onPointerDown: (e: React.PointerEvent) => void\n onPointerUp: () => void\n onPointerLeave: () => void\n onPointerCancel: () => void\n onPointerMove: (e: React.PointerEvent) => void\n} => {\n const timerRef = useRef<NodeJS.Timeout | null>(null)\n const isPressedRef = useRef(false)\n const startPosRef = useRef<{ x: number; y: number } | null>(null)\n\n const start = useCallback(\n (e: React.PointerEvent) => {\n isPressedRef.current = true\n startPosRef.current = { x: e.clientX, y: e.clientY }\n timerRef.current = setTimeout(() => {\n if (isPressedRef.current) {\n callback()\n }\n }, ms)\n },\n [callback, ms]\n )\n\n const clear = useCallback(() => {\n isPressedRef.current = false\n startPosRef.current = null\n if (timerRef.current) {\n clearTimeout(timerRef.current)\n }\n }, [])\n\n // Based on https://github.com/minwork/react/tree/main/packages/use-long-press\n const move = useCallback(\n (e: React.PointerEvent) => {\n if (isPressedRef.current && startPosRef.current) {\n const dx = Math.abs(e.clientX - startPosRef.current.x)\n const dy = Math.abs(e.clientY - startPosRef.current.y)\n const limit = 25\n if (dx > limit || dy > limit) {\n clear() // cancel on movement\n }\n }\n },\n [clear]\n )\n\n return {\n onPointerDown: start,\n onPointerUp: clear,\n onPointerLeave: clear,\n onPointerCancel: clear,\n onPointerMove: move,\n }\n}\n"],"mappings":";;AAEA,MAAa,gBACX,iBAA6B,IAC7B,KAAa,QAOV;CACH,MAAM,WAAW,OAA8B,KAAK;CACpD,MAAM,eAAe,OAAO,MAAM;CAClC,MAAM,cAAc,OAAwC,KAAK;CAEjE,MAAM,QAAQ,aACX,MAA0B;AACzB,eAAa,UAAU;AACvB,cAAY,UAAU;GAAE,GAAG,EAAE;GAAS,GAAG,EAAE;GAAS;AACpD,WAAS,UAAU,iBAAiB;AAClC,OAAI,aAAa,QACf,WAAU;KAEX,GAAG;IAER,CAAC,UAAU,GAAG,CACf;CAED,MAAM,QAAQ,kBAAkB;AAC9B,eAAa,UAAU;AACvB,cAAY,UAAU;AACtB,MAAI,SAAS,QACX,cAAa,SAAS,QAAQ;IAE/B,EAAE,CAAC;AAiBN,QAAO;EACL,eAAe;EACf,aAAa;EACb,gBAAgB;EAChB,iBAAiB;EACjB,eAnBW,aACV,MAA0B;AACzB,OAAI,aAAa,WAAW,YAAY,SAAS;IAC/C,MAAM,KAAK,KAAK,IAAI,EAAE,UAAU,YAAY,QAAQ,EAAE;IACtD,MAAM,KAAK,KAAK,IAAI,EAAE,UAAU,YAAY,QAAQ,EAAE;IACtD,MAAM,QAAQ;AACd,QAAI,KAAK,SAAS,KAAK,MACrB,QAAO;;KAIb,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"useLongPress.js","names":[],"sources":["../../../src/hooks/useLongPress.ts"],"sourcesContent":["import { useCallback, useRef } from 'react'\n\nexport const useLongPress = (\n callback: () => void = () => {},\n ms: number = 500\n): {\n onPointerDown: (e: React.PointerEvent) => void\n onPointerUp: () => void\n onPointerLeave: () => void\n onPointerCancel: () => void\n onPointerMove: (e: React.PointerEvent) => void\n} => {\n const timerRef = useRef<NodeJS.Timeout | null>(null)\n const isPressedRef = useRef(false)\n const startPosRef = useRef<{ x: number; y: number } | null>(null)\n\n const start = useCallback(\n (e: React.PointerEvent) => {\n isPressedRef.current = true\n startPosRef.current = { x: e.clientX, y: e.clientY }\n timerRef.current = setTimeout(() => {\n if (isPressedRef.current) {\n callback()\n }\n }, ms)\n },\n [callback, ms]\n )\n\n const clear = useCallback(() => {\n isPressedRef.current = false\n startPosRef.current = null\n if (timerRef.current) {\n clearTimeout(timerRef.current)\n }\n }, [])\n\n // Based on https://github.com/minwork/react/tree/main/packages/use-long-press\n const move = useCallback(\n (e: React.PointerEvent) => {\n if (isPressedRef.current && startPosRef.current) {\n const dx = Math.abs(e.clientX - startPosRef.current.x)\n const dy = Math.abs(e.clientY - startPosRef.current.y)\n const limit = 25\n if (dx > limit || dy > limit) {\n clear() // cancel on movement\n }\n }\n },\n [clear]\n )\n\n return {\n onPointerDown: start,\n onPointerUp: clear,\n onPointerLeave: clear,\n onPointerCancel: clear,\n onPointerMove: move,\n }\n}\n"],"mappings":";;AAEA,MAAa,gBACX,iBAA6B,IAC7B,KAAa,QAOV;CACH,MAAM,WAAW,OAA8B,KAAK;CACpD,MAAM,eAAe,OAAO,MAAM;CAClC,MAAM,cAAc,OAAwC,KAAK;CAEjE,MAAM,QAAQ,aACX,MAA0B;AACzB,eAAa,UAAU;AACvB,cAAY,UAAU;GAAE,GAAG,EAAE;GAAS,GAAG,EAAE;GAAS;AACpD,WAAS,UAAU,iBAAiB;AAClC,OAAI,aAAa,QACf,WAAU;KAEX,GAAG;IAER,CAAC,UAAU,GAAG,CACf;CAED,MAAM,QAAQ,kBAAkB;AAC9B,eAAa,UAAU;AACvB,cAAY,UAAU;AACtB,MAAI,SAAS,QACX,cAAa,SAAS,QAAQ;IAE/B,EAAE,CAAC;AAiBN,QAAO;EACL,eAAe;EACf,aAAa;EACb,gBAAgB;EAChB,iBAAiB;EACjB,eAnBW,aACV,MAA0B;AACzB,OAAI,aAAa,WAAW,YAAY,SAAS;IAC/C,MAAM,KAAK,KAAK,IAAI,EAAE,UAAU,YAAY,QAAQ,EAAE;IACtD,MAAM,KAAK,KAAK,IAAI,EAAE,UAAU,YAAY,QAAQ,EAAE;IACtD,MAAM,QAAQ;AACd,QAAI,KAAK,SAAS,KAAK,MACrB,QAAO;;KAIb,CAAC,MAAM,CAQY;EACpB"}
|