cake_wallet/cw_bitcoin/lib/pending_bitcoin_transaction.dart
Rafael fd9018bcc4
Cw 598 fixes for electrum based wallets (#1344)
* fix: address book addresses, bch builder, exchange all fee estimation, bch coin control

* feat: new error framework for Electrum messages

* build: cw_bitcoin.dart

* feat: error improvements, localization, fix exchange amount mismatch

* chore: misc comment & print [skip ci]

* feat: refactor & simplify sendAll vs regular tx estimation and creation

- Since there were so many conditions inside a single function to alter its behavior if sendAll or not, it is easier and more readable to have separate sendAll and estimateTx functions that behave separately

* fix: wrong LTC dust

* feat: fee rate confirmation

* fix: wrong createTrade value when isSendAll is enabled

* fix bitcoin cash address parsing [skip ci]

* fix: form no amount validator, address book with multiple entries, exchange all below min error

* fix: improve string, fix sending with dust inputs at the top

* fix: two change outputs when re-estimating

* fix: sendAll with a little dust adds fees

* chore: sanity check [skip ci]

* fix: if the fee is higher than estimated

* Minor enhancement [skip ci]

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
2024-03-29 20:51:34 +02:00

91 lines
2.7 KiB
Dart

import 'package:cw_bitcoin/exceptions.dart';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_bitcoin/electrum.dart';
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/electrum_transaction_info.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/wallet_type.dart';
class PendingBitcoinTransaction with PendingTransaction {
PendingBitcoinTransaction(this._tx, this.type,
{required this.electrumClient,
required this.amount,
required this.fee,
required this.feeRate,
this.network,
required this.hasChange,
required this.isSendAll})
: _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
final WalletType type;
final BtcTransaction _tx;
final ElectrumClient electrumClient;
final int amount;
final int fee;
final String feeRate;
final BasedUtxoNetwork? network;
final bool hasChange;
final bool isSendAll;
@override
String get id => _tx.txId();
@override
String get hex => _tx.serialize();
@override
String get amountFormatted => bitcoinAmountToString(amount: amount);
@override
String get feeFormatted => bitcoinAmountToString(amount: fee);
@override
int? get outputCount => _tx.outputs.length;
final List<void Function(ElectrumTransactionInfo transaction)> _listeners;
@override
Future<void> commit() async {
int? callId;
final result = await electrumClient.broadcastTransaction(
transactionRaw: hex, network: network, idCallback: (id) => callId = id);
if (result.isEmpty) {
if (callId != null) {
final error = electrumClient.getErrorMessage(callId!);
if (error.contains("dust")) {
if (hasChange) {
throw BitcoinTransactionCommitFailedDustChange();
} else if (!isSendAll) {
throw BitcoinTransactionCommitFailedDustOutput();
} else {
throw BitcoinTransactionCommitFailedDustOutputSendAll();
}
}
if (error.contains("bad-txns-vout-negative")) {
throw BitcoinTransactionCommitFailedVoutNegative();
}
}
throw BitcoinTransactionCommitFailed();
}
_listeners.forEach((listener) => listener(transactionInfo()));
}
void addListener(void Function(ElectrumTransactionInfo transaction) listener) =>
_listeners.add(listener);
ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type,
id: id,
height: 0,
amount: amount,
direction: TransactionDirection.outgoing,
date: DateTime.now(),
isPending: true,
confirmations: 0,
fee: fee);
}