Add oracle rates

This commit is contained in:
2026-04-27 08:42:51 +00:00
parent dbfb2c68d2
commit 7ad17a7c0e
17 changed files with 884 additions and 25 deletions

View File

@@ -13,6 +13,7 @@ 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 { useSatoshisConversion } from '../hooks/useSatoshisConversion.js';
import { useInputLayer, useLayeredInput, useBlockableInput, useIsInputCaptured } from '../hooks/useInputLayer.js';
import { colors, formatSatoshis, formatHex, logoSmall } from '../theme.js';
import type { HistoryItem } from '../../services/history.js';
@@ -108,6 +109,12 @@ export function WalletStateScreen(): React.ReactElement {
const { navigate } = useNavigation();
const { appService, showError, showInfo } = useAppContext();
const { setStatus } = useStatus();
const {
currencyCode,
fiatPerBchRate,
formattedFiatPerBchRate,
formatSatoshisToFiat,
} = useSatoshisConversion('USD');
// State
const [balance, setBalance] = useState<{ totalSatoshis: bigint; utxoCount: number } | null>(null);
@@ -297,6 +304,26 @@ export function WalletStateScreen(): React.ReactElement {
});
}, [history]);
/**
* Fiat values are memoized so we only recompute when balance or rate changes.
*/
const formattedUsdPerBchRate = useMemo(() => {
return formattedFiatPerBchRate;
}, [formattedFiatPerBchRate]);
const formattedUsdBalance = useMemo(() => {
if (!balance || fiatPerBchRate === null) {
return null;
}
return formatSatoshisToFiat(balance.totalSatoshis);
}, [balance, fiatPerBchRate, formatSatoshisToFiat]);
const getFiatSuffix = useCallback((satoshis: bigint): string => {
const fiatValue = formatSatoshisToFiat(satoshis);
return fiatValue ? ` (~${fiatValue})` : '';
}, [formatSatoshisToFiat]);
// Screen input — automatically blocked when any dialog/overlay is capturing.
const isCaptured = useIsInputCaptured();
@@ -335,11 +362,16 @@ export function WalletStateScreen(): React.ReactElement {
}
if (row.type === 'invitation_input') {
const inputSatoshis = row.utxo?.valueSatoshis;
const inputFiatSuffix = inputSatoshis !== undefined
? getFiatSuffix(inputSatoshis)
: '';
return (
<Box flexDirection="row" justifyContent="space-between">
<Box>
<Text color={itemColor}>
{indicator}{groupingPrefix}[Input] {row.label}
{inputFiatSuffix}
</Text>
{row.description && <Text color={colors.textMuted}> {row.description}</Text>}
</Box>
@@ -355,6 +387,7 @@ export function WalletStateScreen(): React.ReactElement {
<Box flexDirection="row">
<Text color={itemColor}>
{indicator}{groupingPrefix}[Output] {formatSatoshis(sats)}
{getFiatSuffix(sats)}
</Text>
{row.description && <Text color={colors.textMuted}> {row.description}</Text>}
</Box>
@@ -369,7 +402,10 @@ export function WalletStateScreen(): React.ReactElement {
return (
<Box flexDirection="row" justifyContent="space-between">
<Box flexDirection="row">
<Text color={itemColor}>{indicator}{formatSatoshis(sats)}</Text>
<Text color={itemColor}>
{indicator}{formatSatoshis(sats)}
{getFiatSuffix(sats)}
</Text>
{row.description && <Text color={colors.textMuted}> {row.description}{reservedTag}</Text>}
</Box>
{dateStr && <Text color={colors.textMuted}>{dateStr}</Text>}
@@ -386,7 +422,7 @@ export function WalletStateScreen(): React.ReactElement {
{dateStr && <Text color={colors.textMuted}>{dateStr}</Text>}
</Box>
);
}, []);
}, [getFiatSuffix]);
return (
<Box flexDirection="column" flexGrow={1}>
@@ -418,6 +454,20 @@ export function WalletStateScreen(): React.ReactElement {
<Text color={colors.success} bold>
{formatSatoshis(balance.totalSatoshis)}
</Text>
{formattedUsdBalance ? (
<Text color={colors.info}>
Approx. Fiat ({currencyCode}): {formattedUsdBalance}
</Text>
) : (
<Text color={colors.textMuted}>
Approx. Fiat ({currencyCode}): Waiting for BCH/{currencyCode} rate...
</Text>
)}
{formattedUsdPerBchRate && (
<Text color={colors.textMuted}>
1 BCH = {formattedUsdPerBchRate}
</Text>
)}
<Text color={colors.textMuted}>
UTXOs: {balance.utxoCount}
</Text>