diff --git a/src/components/AmountInput.tsx b/src/components/AmountInput.tsx index c4addeb6..c8aae140 100644 --- a/src/components/AmountInput.tsx +++ b/src/components/AmountInput.tsx @@ -51,10 +51,12 @@ export const AmountInput = forwardRef( onEndEditing() } // Default formatting behavior - const formattedValue = numbro(value).format({ - thousandSeparated: true, - mantissa: getCurrency(unit).mantissa - }) + const formattedValue = typeof value === "undefined" + ? "" + : numbro(value).format({ + thousandSeparated: true, + mantissa: getCurrency(unit).mantissa + }) onChangeText(formattedValue) } diff --git a/src/screens/SendScreen.tsx b/src/screens/SendScreen.tsx index f17c5ba3..af39e014 100644 --- a/src/screens/SendScreen.tsx +++ b/src/screens/SendScreen.tsx @@ -1417,113 +1417,199 @@ export const SendScreen = observer(function SendScreen({ route }: Props) { ) -const SelectProofsBlock = observer(function (props: { - mintBalanceToSendFrom: MintBalance - unit: MintUnit - selectedProofs: Proof[] - // isLockedToPubkey: boolean - toggleProofSelectorModal: any - toggleSelectedProof: any - // toggleIsLockedToPubkey: any - resetSelectedProofs: any - onOfflineSendConfirm: any - }) { +const SelectProofsBlock = observer(function (props: { + mintBalanceToSendFrom: MintBalance + unit: MintUnit + selectedProofs: Proof[] + // isLockedToPubkey: boolean + toggleProofSelectorModal: any + toggleSelectedProof: any + // toggleIsLockedToPubkey: any + resetSelectedProofs: any + onOfflineSendConfirm: any +}) { - const {proofsStore} = useStores() - const hintColor = useThemeColor('textDim') - const statusColor = useThemeColor('header') + const { proofsStore } = useStores() + const hintColor = useThemeColor('textDim') + const statusColor = useThemeColor('header') + const amountInputColor = useThemeColor('amountInput') - - const onCancel = function () { + const [requestedAmount, setRequestedAmount] = useState('0'); + + + const onCancel = function () { + props.resetSelectedProofs() + props.toggleProofSelectorModal() + } + + function onAmountEndEditing() { + try { + if (requestedAmount.trim() === "") return; + const precision = getCurrency(props.unit).precision + const requestedAmountInt = round(toNumber(requestedAmount) * precision, 0) + + if (typeof requestedAmountInt !== "number" || Number.isNaN(requestedAmountInt) || requestedAmountInt === 0) { + return; + } + + const availableProofs = proofsStore.getByMint( + props.mintBalanceToSendFrom.mintUrl, + { isPending: false, unit: props.unit } + ) + + // First try to find exact match + const exactMatch = CashuUtils.findExactMatch(requestedAmountInt, availableProofs) + + if (exactMatch) { + // Clear current selection and set the exact match props.resetSelectedProofs() - props.toggleProofSelectorModal() + exactMatch.forEach(proof => props.toggleSelectedProof(proof)) + } else { + // If no exact match, use findMinExcess as fallback + const minExcessMatch = CashuUtils.findMinExcess(requestedAmountInt, availableProofs, 'SMALL') + + if (minExcessMatch && minExcessMatch.length > 0) { + // Clear current selection and set the min excess match + props.resetSelectedProofs() + minExcessMatch.forEach(proof => props.toggleSelectedProof(proof)) + } + } + } catch (e: any) { + // Handle error if needed + console.error('Error finding proof selection:', e) } - - return ( - - - - - - - - - - data={proofsStore.getByMint(props.mintBalanceToSendFrom.mintUrl, {isPending: false, unit: props.unit})} - renderItem={({ item }) => { - const isSelected = props.selectedProofs.some( - p => p.secret === item.secret - ) + } - return ( -