Massive changes. I dont know what happens. Rewrote the action wizard again. Fixed several bugs related to the utxo selection. QR codes were added for address. Add support for data results. Experiment with other methods of role extraction
This commit is contained in:
@@ -10,12 +10,14 @@
|
||||
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { Box, Text, useInput } from 'ink';
|
||||
import { ScrollableList, type ListItemData } from '../components/List.js';
|
||||
import { QRCode } from '../components/QRCode.js';
|
||||
import { useNavigation } from '../hooks/useNavigation.js';
|
||||
import { useAppContext, useStatus } from '../hooks/useAppContext.js';
|
||||
import { useAppContext, useStatus, useDialog } from '../hooks/useAppContext.js';
|
||||
import { colors, formatSatoshis, formatHex, logoSmall } from '../theme.js';
|
||||
import type { HistoryItem } from '../../services/history.js';
|
||||
|
||||
import { generateTemplateIdentifier } from '@xo-cash/engine';
|
||||
import { hexToBin, lockingBytecodeToCashAddress } from '@bitauth/libauth';
|
||||
|
||||
// Import utility functions
|
||||
import {
|
||||
@@ -71,6 +73,7 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
const { navigate } = useNavigation();
|
||||
const { appService, showError, showInfo } = useAppContext();
|
||||
const { setStatus } = useStatus();
|
||||
const { setDialog } = useDialog();
|
||||
|
||||
// State
|
||||
const [balance, setBalance] = useState<{ totalSatoshis: bigint; utxoCount: number } | null>(null);
|
||||
@@ -80,6 +83,9 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
const [selectedHistoryIndex, setSelectedHistoryIndex] = useState(0);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
/** Cash address to display in the QR code dialog (null when dialog is hidden). */
|
||||
const [qrAddress, setQrAddress] = useState<string | null>(null);
|
||||
|
||||
/**
|
||||
* Refreshes wallet state.
|
||||
*/
|
||||
@@ -122,7 +128,7 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
}, [refresh]);
|
||||
|
||||
/**
|
||||
* Generates a new receiving address.
|
||||
* Generates a new receiving address and displays it as a QR code.
|
||||
*/
|
||||
const generateNewAddress = useCallback(async () => {
|
||||
if (!appService) {
|
||||
@@ -145,21 +151,33 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
// Generate the template identifier
|
||||
const templateId = generateTemplateIdentifier(p2pkhTemplate);
|
||||
|
||||
// Generate the locking bytecode
|
||||
const lockingBytecode = await appService.engine.generateLockingBytecode(
|
||||
// Generate the locking bytecode (returned as a hex string)
|
||||
const lockingBytecodeHex = await appService.engine.generateLockingBytecode(
|
||||
templateId,
|
||||
'receiveOutput',
|
||||
'receiver',
|
||||
);
|
||||
|
||||
showInfo(`New address generated!\n\nLocking bytecode:\n${formatHex(lockingBytecode, 40)}`);
|
||||
// Convert the locking bytecode to a BCH cash address for display and QR encoding.
|
||||
const result = lockingBytecodeToCashAddress({ bytecode: hexToBin(lockingBytecodeHex), prefix: 'bitcoincash' });
|
||||
|
||||
if (typeof result === 'string') {
|
||||
showError(`Failed to encode address: ${result}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(result);
|
||||
|
||||
setQrAddress(result.address);
|
||||
setDialog({ visible: true, type: 'custom', message: '' });
|
||||
setStatus('Address generated');
|
||||
|
||||
// Refresh to show updated state
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
showError(`Failed to generate address: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}, [appService, setStatus, showInfo, showError, refresh]);
|
||||
}, [appService, setStatus, showError, refresh]);
|
||||
|
||||
/**
|
||||
* Handles menu action.
|
||||
@@ -209,8 +227,16 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
});
|
||||
}, [history]);
|
||||
|
||||
// Handle keyboard navigation between panels
|
||||
// Handle keyboard navigation between panels and QR dialog dismissal
|
||||
useInput((input, key) => {
|
||||
if (qrAddress) {
|
||||
if (key.escape || key.return) {
|
||||
setQrAddress(null);
|
||||
setDialog(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.tab) {
|
||||
setFocusedPanel(prev => prev === 'menu' ? 'history' : 'menu');
|
||||
}
|
||||
@@ -400,6 +426,26 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
Tab: Switch focus • Enter: Select • ↑↓: Navigate • Esc: Back
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* QR Code dialog overlay for generated addresses */}
|
||||
{qrAddress && (
|
||||
<Box
|
||||
position="absolute"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
width="100%"
|
||||
>
|
||||
<QRCode
|
||||
value={qrAddress}
|
||||
dialog
|
||||
dialogTitle="Receive Address"
|
||||
showValue
|
||||
/>
|
||||
<Box justifyContent="center" marginTop={1}>
|
||||
<Text color={colors.textMuted}>Press Enter or Esc to close</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user