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

@@ -9,6 +9,7 @@
import React, { useState, useEffect, useCallback, useRef } from 'react';
import { Box, Text } from 'ink';
import { colors, formatSatoshis } from '../../../../theme.js';
import { useSatoshisConversion } from '../../../../hooks/useSatoshisConversion.js';
import { useLayeredInput } from '../../../../hooks/useInputLayer.js';
import type { InputsSelectStepProps, SelectableUTXO } from '../types.js';
import { autoSelectGreedyUtxos, mapUnspentOutputsToSelectable } from '../../../../../utils/invitation-flow.js';
@@ -32,6 +33,7 @@ export function InputsSelectStep({
const [requiredAmount, setRequiredAmount] = useState(0n);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const { formatSatoshisToFiat } = useSatoshisConversion('USD');
const fee = DEFAULT_FEE;
@@ -42,6 +44,11 @@ export function InputsSelectStep({
const changeAmount = selectedAmount - requiredAmount - fee;
const hasEnough = selectedAmount >= requiredAmount + fee;
const getFiatSuffix = (satoshis: bigint): string => {
const fiatValue = formatSatoshisToFiat(satoshis);
return fiatValue ? ` (~${fiatValue})` : '';
};
/**
* Determine the required satoshi amount from the invitation's variables.
*/
@@ -193,18 +200,32 @@ export function InputsSelectStep({
{/* Summary bar */}
<Box flexDirection="row" marginBottom={1}>
<Text color={colors.primary} bold>Required: </Text>
<Text color={colors.text}>{formatSatoshis(requiredAmount + fee)}</Text>
<Text color={colors.text}>
{formatSatoshis(requiredAmount + fee)}
{getFiatSuffix(requiredAmount + fee)}
</Text>
<Text color={colors.textMuted}> (amount {formatSatoshis(requiredAmount)} + fee {formatSatoshis(fee)})</Text>
</Box>
<Box flexDirection="row" marginBottom={1}>
<Text color={colors.primary} bold>Selected: </Text>
<Text color={hasEnough ? colors.success : colors.error}>{formatSatoshis(selectedAmount)}</Text>
<Text color={hasEnough ? colors.success : colors.error}>
{formatSatoshis(selectedAmount)}
{getFiatSuffix(selectedAmount)}
</Text>
{hasEnough && changeAmount >= DUST_THRESHOLD && (
<Text color={colors.textMuted}> (change: {formatSatoshis(changeAmount)})</Text>
<Text color={colors.textMuted}>
{' '}
(change: {formatSatoshis(changeAmount)}
{getFiatSuffix(changeAmount)})
</Text>
)}
{!hasEnough && (
<Text color={colors.error}> need {formatSatoshis(requiredAmount + fee - selectedAmount)} more</Text>
<Text color={colors.error}>
{' '}
need {formatSatoshis(requiredAmount + fee - selectedAmount)}
{getFiatSuffix(requiredAmount + fee - selectedAmount)} more
</Text>
)}
</Box>
@@ -216,13 +237,22 @@ export function InputsSelectStep({
const txShort = utxo.outpointTransactionHash.slice(0, 8);
return (
<Text
<Box
key={`${utxo.outpointTransactionHash}:${utxo.outpointIndex}`}
color={isFocused ? colors.focus : utxo.selected ? colors.success : colors.text}
bold={isFocused}
flexDirection="column"
>
{isFocused ? '▸ ' : ' '}{checkMark} {formatSatoshis(utxo.valueSatoshis)} ({txShort}:{utxo.outpointIndex})
</Text>
<Text
color={isFocused ? colors.focus : utxo.selected ? colors.success : colors.text}
bold={isFocused}
>
{isFocused ? '▸ ' : ' '}{checkMark} {formatSatoshis(utxo.valueSatoshis)} ({txShort}:{utxo.outpointIndex})
</Text>
{formatSatoshisToFiat(utxo.valueSatoshis) && (
<Text color={colors.textMuted}>
{' '} {formatSatoshisToFiat(utxo.valueSatoshis)}
</Text>
)}
</Box>
);
})}