rbf fixes issues sum utxo and fee calculation (#1625)

* total out amount issue

* fix empty inputs and outputs addresses for new tx

* fix sum value of utxo not spending

* Update configure.dart

* Update electrum_wallet.dart

* receiving address

* review fixes
This commit is contained in:
Serhii
2024-08-23 16:19:42 +03:00
committed by GitHub
parent d01199bd04
commit 4c2d061363
6 changed files with 132 additions and 78 deletions
+3 -2
View File
@@ -398,9 +398,10 @@ class CWBitcoin extends Bitcoin {
}
@override
Future<bool> canReplaceByFee(Object wallet, String transactionHash) async {
Future<bool> canReplaceByFee(Object wallet, Object transactionInfo) async {
final bitcoinWallet = wallet as ElectrumWallet;
return bitcoinWallet.canReplaceByFee(transactionHash);
final tx = transactionInfo as ElectrumTransactionInfo;
return bitcoinWallet.canReplaceByFee(tx);
}
@override
+29 -15
View File
@@ -18,6 +18,7 @@ import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cw_core/exceptions.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
@@ -392,25 +393,38 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
@action
Future<void> replaceByFee(String txId, String newFee) async {
Future<void> replaceByFee(TransactionInfo tx, String newFee) async {
state = IsExecutingState();
final isSufficient = await bitcoin!.isChangeSufficientForFee(wallet, txId, newFee);
try {
final isSufficient = await bitcoin!.isChangeSufficientForFee(wallet, tx.id, newFee);
if (!isSufficient) {
state = AwaitingConfirmationState(
title: S.current.confirm_fee_deduction,
message: S.current.confirm_fee_deduction_content,
onConfirm: () async {
pendingTransaction = await bitcoin!.replaceByFee(wallet, txId, newFee);
state = ExecutedSuccessfullyState();
},
onCancel: () {
state = FailureState('Insufficient change for fee');
});
} else {
pendingTransaction = await bitcoin!.replaceByFee(wallet, txId, newFee);
if (!isSufficient) {
state = AwaitingConfirmationState(
title: S.current.confirm_fee_deduction,
message: S.current.confirm_fee_deduction_content,
onConfirm: () async => await _executeReplaceByFee(tx, newFee),
onCancel: () => state = FailureState('Insufficient change for fee'));
} else {
await _executeReplaceByFee(tx, newFee);
}
} catch (e) {
state = FailureState(e.toString());
}
}
Future<void> _executeReplaceByFee(TransactionInfo tx, String newFee) async {
clearOutputs();
final output = outputs.first;
output.address = tx.outputAddresses?.first ?? '';
try {
pendingTransaction = await bitcoin!.replaceByFee(wallet, tx.id, newFee);
state = ExecutedSuccessfullyState();
} catch (e) {
state = FailureState(e.toString());
}
}
@@ -52,7 +52,7 @@ abstract class TransactionDetailsViewModelBase with Store {
case WalletType.bitcoin:
_addElectrumListItems(tx, dateFormat);
_addBumpFeesListItems(tx);
_checkForRBF();
_checkForRBF(tx);
break;
case WalletType.litecoin:
case WalletType.bitcoinCash:
@@ -349,12 +349,15 @@ abstract class TransactionDetailsViewModelBase with Store {
void _addBumpFeesListItems(TransactionInfo tx) {
transactionPriority = bitcoin!.getBitcoinTransactionPriorityMedium();
final inputsCount = (transactionInfo.inputAddresses?.isEmpty ?? true)
? 1
: transactionInfo.inputAddresses!.length;
final outputsCount = (transactionInfo.outputAddresses?.isEmpty ?? true)
? 1
: transactionInfo.outputAddresses!.length;
newFee = bitcoin!.getFeeAmountForPriority(
wallet,
bitcoin!.getBitcoinTransactionPriorityMedium(),
transactionInfo.inputAddresses?.length ?? 1,
transactionInfo.outputAddresses?.length ?? 1);
wallet, bitcoin!.getBitcoinTransactionPriorityMedium(), inputsCount, outputsCount);
RBFListItems.add(StandartListItem(title: S.current.old_fee, value: tx.feeFormatted() ?? '0.0'));
@@ -383,12 +386,12 @@ abstract class TransactionDetailsViewModelBase with Store {
return setNewFee(value: sliderValue, priority: transactionPriority!);
}));
if (transactionInfo.inputAddresses != null) {
if (transactionInfo.inputAddresses != null && transactionInfo.inputAddresses!.isNotEmpty) {
RBFListItems.add(StandardExpandableListItem(
title: S.current.inputs, expandableItems: transactionInfo.inputAddresses!));
}
if (transactionInfo.outputAddresses != null) {
if (transactionInfo.outputAddresses != null && transactionInfo.outputAddresses!.isNotEmpty) {
RBFListItems.add(StandardExpandableListItem(
title: S.current.outputs, expandableItems: transactionInfo.outputAddresses!));
}
@@ -416,10 +419,10 @@ abstract class TransactionDetailsViewModelBase with Store {
}
@action
Future<void> _checkForRBF() async {
Future<void> _checkForRBF(TransactionInfo tx) async {
if (wallet.type == WalletType.bitcoin &&
transactionInfo.direction == TransactionDirection.outgoing) {
if (await bitcoin!.canReplaceByFee(wallet, transactionInfo.id)) {
if (await bitcoin!.canReplaceByFee(wallet, tx)) {
_canReplaceByFee = true;
}
}
@@ -441,7 +444,7 @@ abstract class TransactionDetailsViewModelBase with Store {
return bitcoin!.formatterBitcoinAmountToString(amount: newFee);
}
void replaceByFee(String newFee) => sendViewModel.replaceByFee(transactionInfo.id, newFee);
void replaceByFee(String newFee) => sendViewModel.replaceByFee(transactionInfo, newFee,);
@computed
String get pendingTransactionFiatAmountValueFormatted => sendViewModel.isFiatDisabled