@lifi/wallet-management
Version:
LI.FI Wallet Management solution.
173 lines • 10.8 kB
JavaScript
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