import type { WalletSummary } from '../shared'; import { useState } from 'react'; import { Loader2, TriangleAlert } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { useWalletLifecycle } from '../useWalletData'; // Delete a wallet. For a seeded wallet this destroys the only copy of the key material Officer holds, so // the sidecar demands the passphrase even when the wallet is currently unlocked — an open session must not // be enough to erase a seed. Typing the wallet's name is the second check against the wrong row, and it is // sent rather than merely enforced here: a wallet with no seed has no passphrase gate, so without it the // only thing standing between a node wallet and deletion was a dialog anything could route around. type DeleteWalletDialogProps = { open: boolean; onOpenChange: (open: boolean) => void; wallet: WalletSummary; onDeleted?: () => void; }; export const DeleteWalletDialog = ({ open, onOpenChange, wallet, onDeleted }: DeleteWalletDialogProps) => { const { remove } = useWalletLifecycle(); // Never persisted: no localStorage, no sessionStorage, no React Query cache, no URL. const [passphrase, setPassphrase] = useState(''); const [confirmName, setConfirmName] = useState(''); const close = () => { setPassphrase(''); setConfirmName(''); onOpenChange(false); }; const nameMatches = confirmName.trim() === wallet.name; const canSubmit = nameMatches && (!wallet.hasSeed || !!passphrase) && !remove.isPending; const submit = async (ev: React.FormEvent) => { ev.preventDefault(); if (!canSubmit) return; try { await remove.mutateAsync({ walletId: wallet.id, confirmName: confirmName.trim(), passphrase: wallet.hasSeed ? passphrase : undefined, }); close(); onDeleted?.(); } finally { setPassphrase(''); } }; return ( (next ? onOpenChange(true) : close())}>
Delete {wallet.name} {wallet.hasSeed ? 'This erases the encrypted seed. Without your written-down recovery phrase the coins are gone for good.' : 'This removes the connection to that node. Nothing on the node itself is touched.'}
setConfirmName(ev.target.value)} />
{wallet.hasSeed && (
{/* Controlled input → request body → cleared. Never written to any store. */} setPassphrase(ev.target.value)} />
)}
); };