/** * Seed Input Screen - Initial screen for wallet seed phrase entry. * * Allows users to enter their BIP39 seed phrase to initialize the wallet. */ import React, { useState, useCallback } from 'react'; import { Box, Text, useInput } from 'ink'; import TextInput from '../components/TextInput.js'; import { Button } from '../components/Button.js'; import { useNavigation } from '../hooks/useNavigation.js'; import { useAppContext, useStatus } from '../hooks/useAppContext.js'; import { colors, logo } from '../theme.js'; /** * Status message type. */ type StatusType = 'idle' | 'loading' | 'error' | 'success'; /** * Seed Input Screen Component. * Provides seed phrase entry for wallet initialization. */ export function SeedInputScreen(): React.ReactElement { const { navigate } = useNavigation(); const { initializeWallet } = useAppContext(); const { setStatus } = useStatus(); // State const [seedPhrase, setSeedPhrase] = useState(''); const [statusMessage, setStatusMessage] = useState(''); const [statusType, setStatusType] = useState('idle'); const [focusedElement, setFocusedElement] = useState<'input' | 'button'>('input'); const [isSubmitting, setIsSubmitting] = useState(false); /** * Shows a status message with the given type. */ const showStatus = useCallback((message: string, type: StatusType) => { setStatusMessage(message); setStatusType(type); }, []); /** * Handles seed phrase submission. */ const handleSubmit = useCallback(async () => { const seed = seedPhrase.trim(); // Basic validation if (!seed) { showStatus('Please enter your seed phrase', 'error'); return; } const wordCount = seed.split(/\s+/).length; if (wordCount !== 12 && wordCount !== 24) { showStatus(`Invalid seed phrase. Expected 12 or 24 words, got ${wordCount}`, 'error'); return; } // Show loading status showStatus('Initializing wallet...', 'loading'); setStatus('Initializing wallet...'); setIsSubmitting(true); try { // Initialize wallet and create AppService await initializeWallet(seed); showStatus('Wallet initialized successfully!', 'success'); setStatus('Wallet ready'); // Clear sensitive data before navigating setSeedPhrase(''); // Navigate to wallet state screen setTimeout(() => { navigate('wallet'); }, 500); } catch (error) { const message = error instanceof Error ? error.message : 'Failed to initialize wallet'; showStatus(message, 'error'); setStatus('Initialization failed'); setIsSubmitting(false); } }, [seedPhrase, initializeWallet, navigate, showStatus, setStatus]); // Handle keyboard navigation useInput((input, key) => { if (isSubmitting) return; // Tab to switch focus if (key.tab) { setFocusedElement(prev => prev === 'input' ? 'button' : 'input'); } // Enter on button submits if (key.return && focusedElement === 'button') { handleSubmit(); } }); // Get status color const statusColor = statusType === 'error' ? colors.error : statusType === 'success' ? colors.success : statusType === 'loading' ? colors.info : colors.textMuted; // Get border color based on status const inputBorderColor = statusType === 'error' ? colors.error : statusType === 'success' ? colors.success : focusedElement === 'input' ? colors.focus : colors.border; return ( {/* Logo */} {logo} {/* Title */} Welcome to XO Wallet CLI Enter your seed phrase to get started {/* Spacer */} {/* Input section */} Seed Phrase (12 or 24 words): {/* Status message */} {statusMessage && ( {statusType === 'loading' && '⏳ '} {statusType === 'error' && '✗ '} {statusType === 'success' && '✓ '} {statusMessage} )} {/* Submit button */}