UNPKG

@lifi/wallet-management

Version:

LI.FI Wallet Management solution.

173 lines 10.8 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { ChainType } from '@lifi/sdk'; import ArrowBack from '@mui/icons-material/ArrowBack'; import Close from '@mui/icons-material/Close'; import { Box, Collapse, DialogContent, DialogTitle, Fade, IconButton, List, Typography, } from '@mui/material'; import { useMemo, useReducer, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { useAccount } from '../hooks/useAccount.js'; import { useCombinedWallets } from '../hooks/useCombinedWallets.js'; import { ElementId } from '../utils/elements.js'; import { getConnectorId } from '../utils/getConnectorId.js'; import { getSortedByTags } from '../utils/getSortedByTags.js'; import { getConnectorTagType, getWalletTagType } from '../utils/walletTags.js'; import { CardListItemButton } from './CardListItemButton.js'; import { EVMListItemButton } from './EVMListItemButton.js'; import { SuiListItemButton } from './SuiListItemButton.js'; import { SVMListItemButton } from './SVMListItemButton.js'; import { UTXOListItemButton } from './UTXOListItemButton.js'; import { WalletInfoDisplay } from './WalletInfoDisplay.js'; import { WalletMenuContentEmpty } from './WalletMenuContentEmpty.js'; function reducer(state, action) { switch (action.type) { case 'SHOW_WALLET_LIST': return { ...state, view: 'wallet-list' }; case 'SHOW_MULTI_ECOSYSTEM': return { view: 'multi-ecosystem', selectedWalletId: action.id }; case 'SHOW_CONNECTING': return { view: 'connecting', selectedWalletId: action.id }; case 'HANDLE_ERROR': if (action.error?.message?.includes('pending')) { return { view: 'connecting', selectedWalletId: action.id }; } return { view: 'wallet-list', selectedWalletId: action.id }; default: return state; } } export const WalletMenuContent = ({ onClose, walletChainArgs, }) => { const { t } = useTranslation(); const { installedWallets } = useCombinedWallets(); const selectedWalletRef = useRef(null); const { accounts } = useAccount(); const connectedConnectorIds = useMemo(() => { return accounts .filter((account) => account.isConnected) .map((account) => getConnectorId(account.connector, account.chainType)) .filter(Boolean); }, [accounts]); const [state, dispatch] = useReducer(reducer, { view: 'wallet-list' }); const handleMultiEcosystem = (id) => { dispatch({ type: 'SHOW_MULTI_ECOSYSTEM', id }); }; const handleConnecting = (id) => { dispatch({ type: 'SHOW_CONNECTING', id }); }; const handleBack = () => { dispatch({ type: 'SHOW_WALLET_LIST' }); }; const handleError = (id, error) => { dispatch({ type: 'HANDLE_ERROR', id, error }); }; const walletChainLabel = useMemo(() => { if (!walletChainArgs) { return undefined; } if (walletChainArgs.chain) { return walletChainArgs.chain.name; } return walletChainArgs.chainType; }, [walletChainArgs]); const filteredWallets = useMemo(() => { if (!walletChainArgs) { return installedWallets; } const targetChainType = walletChainArgs.chain?.chainType ?? walletChainArgs.chainType; return installedWallets .map((wallet) => { const filteredConnectors = wallet.connectors.filter((c) => c.chainType === targetChainType); return filteredConnectors.length ? { ...wallet, connectors: filteredConnectors } : null; }) .filter(Boolean); }, [installedWallets, walletChainArgs]); const isMultiEcosystem = state.view === 'multi-ecosystem'; const isConnecting = state.view === 'connecting'; // We need to preserve selectedWallet between re-renders to avoid empty state once wallet is connected let selectedWallet = state.selectedWalletId ? filteredWallets.find((wallet) => wallet.id === state.selectedWalletId) : null; selectedWalletRef.current = selectedWallet || selectedWalletRef.current; selectedWallet = selectedWalletRef.current; const filteredWalletsWithTagTypes = useMemo(() => getSortedByTags(filteredWallets .filter((wallet) => wallet.connectors?.length) .map((wallet) => { return { ...wallet, tagType: getWalletTagType(wallet, connectedConnectorIds), }; })), [filteredWallets, connectedConnectorIds]); const getWalletButton = (id, name, chainType, connector, ecosystemSelection, tagType) => { const key = `${name}${ecosystemSelection ? `-${chainType}` : ''}`; switch (chainType) { case ChainType.UTXO: return (_jsx(UTXOListItemButton, { ecosystemSelection: ecosystemSelection, tagType: tagType, connector: connector, onConnected: onClose, onConnecting: () => handleConnecting(id), onError: (error) => handleError(id, error) }, key)); case ChainType.EVM: return (_jsx(EVMListItemButton, { ecosystemSelection: ecosystemSelection, tagType: tagType, connector: connector, onConnected: onClose, onConnecting: () => handleConnecting(id), onError: (error) => handleError(id, error) }, key)); case ChainType.SVM: return (_jsx(SVMListItemButton, { ecosystemSelection: ecosystemSelection, tagType: tagType, walletAdapter: connector, onConnected: onClose, onConnecting: () => handleConnecting(id), onError: (error) => handleError(id, error) }, key)); case ChainType.MVM: return (_jsx(SuiListItemButton, { ecosystemSelection: ecosystemSelection, tagType: tagType, wallet: connector, onConnected: onClose, onConnecting: () => handleConnecting(id), onError: (error) => handleError(id, error) }, key)); default: return null; } }; const selectedWalletConnectors = useMemo(() => { return getSortedByTags(selectedWallet?.connectors?.map((connector) => { const connectorId = getConnectorId(connector.connector, connector.chainType); return { ...connector, tagType: connectorId ? getConnectorTagType(connectorId, connectedConnectorIds.includes(connectorId)) : undefined, }; }) || []); }, [selectedWallet, connectedConnectorIds]); return (_jsxs(_Fragment, { children: [_jsxs(DialogTitle, { sx: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: 2, }, children: [isMultiEcosystem || isConnecting ? (_jsx(IconButton, { onClick: handleBack, children: _jsx(ArrowBack, {}) })) : (_jsx(Box, { sx: { height: 40, width: 40, } })), _jsx(Typography, { sx: { fontWeight: 700, fontSize: '18px', margin: 'auto', }, children: isMultiEcosystem ? t('title.selectEcosystem') : isConnecting ? t('title.connecting') : walletChainLabel ? t('title.selectWalletWithChain', { chainLabel: walletChainLabel, }) : t('title.selectWallet') }), _jsx(IconButton, { onClick: onClose, children: _jsx(Close, {}) })] }), _jsxs(DialogContent, { sx: { padding: 3 }, id: ElementId.WalletModalContent, children: [_jsx(Collapse, { in: state.view === 'wallet-list', timeout: { appear: 225, enter: 225, exit: 225 }, children: _jsx(Fade, { in: state.view === 'wallet-list', timeout: { appear: 225, enter: 100, exit: 225 }, children: _jsx(List, { component: "div", sx: { padding: 0, display: 'flex', flexDirection: 'column', gap: '8px', }, children: filteredWalletsWithTagTypes.length ? (filteredWalletsWithTagTypes.map(({ id, name, icon, connectors, tagType }) => { if (connectors.length === 1) { const { chainType, connector } = connectors[0]; return getWalletButton(getConnectorId(connector, chainType), name, chainType, connector, false, tagType); } return (_jsx(CardListItemButton, { onClick: () => handleMultiEcosystem(id), title: name, icon: icon ?? '', tagType: tagType }, name)); })) : (_jsx(WalletMenuContentEmpty, {})) }) }) }), _jsx(Collapse, { in: state.view === 'multi-ecosystem', timeout: { appear: 225, enter: 225, exit: 225 }, children: _jsx(Fade, { in: state.view === 'multi-ecosystem', timeout: { appear: 225, enter: 225, exit: 100 }, children: _jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 4, }, children: [_jsx(WalletInfoDisplay, { selectedWallet: selectedWallet, message: t('message.multipleEcosystems', { walletName: selectedWallet?.name, }) }), _jsx(List, { sx: { padding: 0, display: 'flex', flexDirection: 'column', gap: '8px', }, children: selectedWalletConnectors.map(({ chainType, tagType, connector }) => getWalletButton(state.selectedWalletId, selectedWallet?.name || '', chainType, connector, true, tagType)) })] }) }) }), _jsx(Collapse, { in: state.view === 'connecting', timeout: { appear: 225, enter: 225, exit: 225 }, children: _jsx(Fade, { in: state.view === 'connecting', timeout: { appear: 225, enter: 225, exit: 100 }, children: _jsx("div", { children: _jsx(WalletInfoDisplay, { selectedWallet: selectedWallet, title: t('title.waitingForWallet', { walletName: selectedWallet?.name, }), message: t('message.connecting') }) }) }) })] })] })); }; //# sourceMappingURL=WalletMenuContent.js.map