@@ -18,7 +18,6 @@ struct SendConfirmationView: View {
1818 @State private var showingBiometricError = false
1919 @State private var biometricErrorMessage = " "
2020 @State private var transactionFee : Int = 0
21- @State private var shouldUseSendAll : Bool = false
2221 @State private var currentWarning : WarningType ?
2322 @State private var pendingWarnings : [ WarningType ] = [ ]
2423 @State private var warningContinuation : CheckedContinuation < Bool , Error > ?
@@ -485,8 +484,7 @@ struct SendConfirmationView: View {
485484 }
486485 } else if app. selectedWalletToPayFrom == . onchain, let invoice = app. scannedOnchainInvoice {
487486 let amount = wallet. sendAmountSats ?? invoice. amountSatoshis
488- // Use sendAll if explicitly MAX or if change would be dust
489- let useMaxAmount = wallet. isMaxAmountSend || shouldUseSendAll
487+ let useMaxAmount = await shouldUseMaxOnchainSend ( address: invoice. address, amountSats: amount)
490488 let txid = try await wallet. send ( address: invoice. address, sats: amount, isMaxAmount: useMaxAmount)
491489
492490 // Create pre-activity metadata for tags and activity address
@@ -621,6 +619,28 @@ struct SendConfirmationView: View {
621619 return true
622620 }
623621
622+ private func shouldUseMaxOnchainSend( address: String , amountSats: UInt64 , feeRate: UInt32 ? = nil ) async -> Bool {
623+ guard wallet. isMaxAmountSend else { return false }
624+ guard let rate = feeRate ?? wallet. selectedFeeRateSatsPerVByte else { return false }
625+
626+ do {
627+ let currentMaxSendable = try await wallet. calculateMaxSendableAmount ( address: address, satsPerVByte: rate)
628+ let matchesCurrentMax = amountSats == currentMaxSendable
629+
630+ if !matchesCurrentMax {
631+ Logger . warn (
632+ " Ignoring stale max on-chain send flag: amount= \( amountSats) , currentMaxSendable= \( currentMaxSendable) " ,
633+ context: " SendConfirmationView "
634+ )
635+ }
636+
637+ return matchesCurrentMax
638+ } catch {
639+ Logger . error ( " Failed to verify max on-chain send amount: \( error) " , context: " SendConfirmationView " )
640+ return false
641+ }
642+ }
643+
624644 private func createPreActivityMetadata(
625645 paymentId: String ,
626646 paymentHash: String ? = nil ,
@@ -741,43 +761,31 @@ struct SendConfirmationView: View {
741761 }
742762
743763 do {
744- // Fee for normal send (recipient + change outputs) - used to check if change would be dust
745- let normalFee = try await wallet. calculateTotalFee (
746- address: address,
747- amountSats: amountSats,
748- satsPerVByte: feeRate,
749- utxosToSpend: wallet. selectedUtxos
750- )
751- let totalInput = wallet. selectedUtxos? . reduce ( 0 ) { $0 + $1. valueSats }
752- ?? UInt64 ( wallet. spendableOnchainBalanceSats)
753- let useSendAll = DustChangeHelper . shouldUseSendAllToAvoidDust (
754- totalInput: totalInput,
755- amountSats: amountSats,
756- normalFee: normalFee
757- )
758-
759- if useSendAll {
760- // Change would be dust - use sendAll and add dust to fee
764+ if await shouldUseMaxOnchainSend ( address: address, amountSats: amountSats, feeRate: feeRate) {
761765 let sendAllFee = try await wallet. estimateSendAllFee (
762766 address: address,
763767 satsPerVByte: feeRate
764768 )
765769 await MainActor . run {
766770 transactionFee = Int ( sendAllFee)
767- shouldUseSendAll = true
768- }
769- } else {
770- // Normal send with change output
771- await MainActor . run {
772- transactionFee = Int ( normalFee)
773- shouldUseSendAll = false
774771 }
772+ return
773+ }
774+
775+ // Fee for normal send (recipient + change outputs).
776+ let normalFee = try await wallet. calculateTotalFee (
777+ address: address,
778+ amountSats: amountSats,
779+ satsPerVByte: feeRate,
780+ utxosToSpend: wallet. selectedUtxos
781+ )
782+ await MainActor . run {
783+ transactionFee = Int ( normalFee)
775784 }
776785 } catch {
777786 Logger . error ( " Failed to calculate actual fee: \( error) " )
778787 await MainActor . run {
779788 transactionFee = 0
780- shouldUseSendAll = false
781789 app. toast ( type: . error, title: t ( " other__try_again " ) )
782790 }
783791 }
0 commit comments