import React, { useEffect, useState } from 'react' import { Box, Text } from 'ink' import type { Address } from 'viem' import { useWallets } from '../hooks/index.js' import { Header, List, Spinner, KeyValue } from '../components/index.js' import { theme } from '../theme.js' import { shortenAddress } from '../../utils/ethereum.js' import { getBalances, formatBalance } from '../../utils/balance.js' import { getConfigStore } from '../../storage/config-store.js' export interface WalletListScreenProps { /** * Optional callback when the screen is ready to exit */ onExit?: () => void } /** * WalletListScreen displays all imported wallets with their details. * This replaces the imperative console.log implementation in commands/wallet/list.ts * * Features: * - Shows all wallets with active state indicators * - Displays full address and shortened address * - Shows last used timestamp * - Empty state for no wallets */ export function WalletListScreen({ onExit }: WalletListScreenProps): React.ReactElement { const { wallets, activeWallet, loading, error } = useWallets() const [balances, setBalances] = useState>(new Map()) const [balancesLoading, setBalancesLoading] = useState(true) // Fetch balances for all wallets useEffect(() => { if (!loading && wallets.length > 0) { const configStore = getConfigStore() const defaultChain = configStore.getDefaultChain() const addresses = wallets.map((w) => w.address as Address) getBalances(addresses, defaultChain) .then((balanceMap) => { setBalances(balanceMap) setBalancesLoading(false) }) .catch(() => { setBalancesLoading(false) }) } else if (!loading) { setBalancesLoading(false) } }, [wallets, loading]) // Auto-exit after rendering and balances loaded useEffect(() => { if (!loading && !balancesLoading && onExit) { onExit() } }, [loading, balancesLoading, onExit]) // Loading state if (loading) { return } // Error state if (error) { return ( Error: {error} ) } // Empty state if (wallets.length === 0) { return (
No wallets found Use "safe wallet import" to import a wallet from private key Use "safe wallet import-ledger" to import a Ledger hardware wallet ) } // Wallet list const configStore = getConfigStore() const defaultChain = configStore.getDefaultChain() return (
{balancesLoading && !loading ? ( Fetching balances... ) : null} wallet.id} renderItem={(wallet, _index, isActive) => { const items = [ { key: 'Type', value: wallet.type === 'ledger' ? '🔐 Ledger' : '🔑 Private Key', }, { key: 'Address', value: wallet.address }, { key: 'Short', value: shortenAddress(wallet.address) }, ] // Add balance if loaded if (!balancesLoading) { const balance = balances.get(wallet.address as Address) if (balance !== undefined) { items.push({ key: 'Balance', value: formatBalance(balance, defaultChain.currency), }) } } // Add derivation path for Ledger wallets if (wallet.type === 'ledger') { items.push({ key: 'Path', value: wallet.derivationPath, }) } items.push({ key: 'Last used', value: wallet.lastUsed ? new Date(wallet.lastUsed).toLocaleString() : 'Never', }) return ( {wallet.name} ) }} /> {/* Footer */} {activeWallet && ( Active wallet: {activeWallet.name} )} Total: {wallets.length} wallet(s) {!balancesLoading && ( Balances shown on {defaultChain.name} )} ) }