Huge commit. Multiple fixes. Refactored commands. Invitations, resources, template inspection, mnemonic stuff, cli utils, pretty printing, remove unreserve on start, fix connectino requirement for invitations, format cashAddress to lockingBytecode on send, lots and lots of other stuff.
This commit is contained in:
@@ -17,7 +17,6 @@ import { useBlockableInput } from '../hooks/useInputLayer.js';
|
||||
import { useInvitation } from '../hooks/useInvitations.js';
|
||||
import { colors, logoSmall, formatSatoshis, formatHex } from '../theme.js';
|
||||
import { copyToClipboard } from '../utils/clipboard.js';
|
||||
import type { XOInvitation } from '@xo-cash/types';
|
||||
|
||||
/**
|
||||
* Action menu items.
|
||||
|
||||
@@ -58,6 +58,7 @@ const menuItems: ListItemData<string>[] = [
|
||||
{ key: 'import', label: 'Import Invitation', value: 'import' },
|
||||
{ key: 'invitations', label: 'View Invitations', value: 'invitations' },
|
||||
{ key: 'new-address', label: 'Generate New Address', value: 'new-address' },
|
||||
{ key: 'unreserve-all', label: 'Unreserve All Resources', value: 'unreserve-all' },
|
||||
{ key: 'refresh', label: 'Refresh', value: 'refresh' },
|
||||
];
|
||||
|
||||
@@ -160,6 +161,21 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
refresh();
|
||||
}, [refresh]);
|
||||
|
||||
// Keep wallet state in sync with invitation lifecycle and updates.
|
||||
useEffect(() => {
|
||||
if (!appService) return;
|
||||
|
||||
const onWalletStateChanged = () => {
|
||||
void refresh();
|
||||
};
|
||||
|
||||
appService.on('wallet-state-changed', onWalletStateChanged);
|
||||
|
||||
return () => {
|
||||
appService.off('wallet-state-changed', onWalletStateChanged);
|
||||
};
|
||||
}, [appService, refresh]);
|
||||
|
||||
/**
|
||||
* Generates a new receiving address and displays it as a QR code.
|
||||
*/
|
||||
@@ -211,6 +227,25 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
}
|
||||
}, [appService, setStatus, showError, refresh]);
|
||||
|
||||
/**
|
||||
* Unreserves all reserved UTXOs and refreshes the wallet state.
|
||||
*/
|
||||
const unreserveAll = useCallback(async () => {
|
||||
if (!appService) {
|
||||
showError('AppService not initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setStatus('Unreserving all resources...');
|
||||
const count = await appService.unreserveAllResources();
|
||||
showInfo(`Unreserved ${count} resource(s)`);
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
showError(`Failed to unreserve resources: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}, [appService, setStatus, showError, showInfo, refresh]);
|
||||
|
||||
/**
|
||||
* Handles menu action.
|
||||
*/
|
||||
@@ -228,11 +263,14 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
case 'new-address':
|
||||
generateNewAddress();
|
||||
break;
|
||||
case 'unreserve-all':
|
||||
unreserveAll();
|
||||
break;
|
||||
case 'refresh':
|
||||
refresh();
|
||||
break;
|
||||
}
|
||||
}, [navigate, generateNewAddress, refresh]);
|
||||
}, [navigate, generateNewAddress, unreserveAll, refresh]);
|
||||
|
||||
/**
|
||||
* Handle menu item activation.
|
||||
|
||||
@@ -142,7 +142,7 @@ export function InputsSelectStep({
|
||||
setFocusedIndex(prev => Math.max(0, prev - 1));
|
||||
} else if (key.downArrow || input === 'j') {
|
||||
setFocusedIndex(prev => Math.min(utxos.length - 1, prev + 1));
|
||||
} else if (input === ' ' || (key.return && utxos.length > 0)) {
|
||||
} else if (input === ' ') {
|
||||
if (utxos.length > 0) toggleSelection(focusedIndex);
|
||||
} else if (input === 'a') {
|
||||
setUtxos(prev => prev.map(u => ({ ...u, selected: true })));
|
||||
|
||||
Reference in New Issue
Block a user