fix: sp input calc (#1756)

This commit is contained in:
Rafael
2024-10-19 02:24:15 +03:00
committed by GitHub
parent 5c2735be42
commit 7faca38cfa
+37 -8
View File
@@ -784,6 +784,7 @@ abstract class ElectrumWalletBase
Future<EstimatedTxResult> estimateTxForAmount(
int credentialsAmount,
List<BitcoinOutput> outputs,
List<BitcoinOutput> updatedOutputs,
int feeRate, {
int? inputsCount,
String? memo,
@@ -812,6 +813,7 @@ abstract class ElectrumWalletBase
return estimateTxForAmount(
credentialsAmount,
outputs,
updatedOutputs,
feeRate,
inputsCount: utxoDetails.utxos.length + 1,
memo: memo,
@@ -824,19 +826,30 @@ abstract class ElectrumWalletBase
}
final changeAddress = await walletAddresses.getChangeAddress(
outputs: outputs,
outputs: updatedOutputs,
utxoDetails: utxoDetails,
);
final address = RegexUtils.addressTypeFromStr(changeAddress, network);
updatedOutputs.add(BitcoinOutput(
address: address,
value: BigInt.from(amountLeftForChangeAndFee),
isChange: true,
));
outputs.add(BitcoinOutput(
address: address,
value: BigInt.from(amountLeftForChangeAndFee),
isChange: true,
));
// calcFee updates the silent payment outputs to calculate the tx size accounting
// for taproot addresses, but if more inputs are needed to make up for fees,
// the silent payment outputs need to be recalculated for the new inputs
var temp = outputs.map((output) => output).toList();
int fee = await calcFee(
utxos: utxoDetails.utxos,
outputs: outputs,
// Always take only not updated bitcoin outputs here so for every estimation
// the SP outputs are re-generated to the proper taproot addresses
outputs: temp,
network: network,
memo: memo,
feeRate: feeRate,
@@ -844,18 +857,25 @@ abstract class ElectrumWalletBase
vinOutpoints: utxoDetails.vinOutpoints,
);
updatedOutputs.clear();
updatedOutputs.addAll(temp);
if (fee == 0) {
throw BitcoinTransactionNoFeeException();
}
int amount = credentialsAmount;
final lastOutput = outputs.last;
final lastOutput = updatedOutputs.last;
final amountLeftForChange = amountLeftForChangeAndFee - fee;
print(amountLeftForChangeAndFee);
if (!_isBelowDust(amountLeftForChange)) {
// Here, lastOutput already is change, return the amount left without the fee to the user's address.
updatedOutputs[updatedOutputs.length - 1] = BitcoinOutput(
address: lastOutput.address,
value: BigInt.from(amountLeftForChange),
isSilentPayment: lastOutput.isSilentPayment,
isChange: true,
);
outputs[outputs.length - 1] = BitcoinOutput(
address: lastOutput.address,
value: BigInt.from(amountLeftForChange),
@@ -864,6 +884,7 @@ abstract class ElectrumWalletBase
);
} else {
// If has change that is lower than dust, will end up with tx rejected by network rules, so estimate again without the added change
updatedOutputs.removeLast();
outputs.removeLast();
// Still has inputs to spend before failing
@@ -871,16 +892,18 @@ abstract class ElectrumWalletBase
return estimateTxForAmount(
credentialsAmount,
outputs,
updatedOutputs,
feeRate,
inputsCount: utxoDetails.utxos.length + 1,
memo: memo,
hasSilentPayment: hasSilentPayment,
useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins,
coinTypeToSpendFrom: coinTypeToSpendFrom,
);
}
final estimatedSendAll = await estimateSendAllTx(
outputs,
updatedOutputs,
feeRate,
memo: memo,
coinTypeToSpendFrom: coinTypeToSpendFrom,
@@ -913,10 +936,12 @@ abstract class ElectrumWalletBase
if (spendingAllCoins) {
throw BitcoinTransactionWrongBalanceException();
} else {
updatedOutputs.removeLast();
outputs.removeLast();
return estimateTxForAmount(
credentialsAmount,
outputs,
updatedOutputs,
feeRate,
inputsCount: utxoDetails.utxos.length + 1,
memo: memo,
@@ -1029,6 +1054,9 @@ abstract class ElectrumWalletBase
: feeRate(transactionCredentials.priority!);
EstimatedTxResult estimatedTx;
final updatedOutputs =
outputs.map((e) => BitcoinOutput(address: e.address, value: e.value)).toList();
if (sendAll) {
estimatedTx = await estimateSendAllTx(
outputs,
@@ -1042,6 +1070,7 @@ abstract class ElectrumWalletBase
estimatedTx = await estimateTxForAmount(
credentialsAmount,
outputs,
updatedOutputs,
feeRateInt,
memo: memo,
hasSilentPayment: hasSilentPayment,
@@ -1052,7 +1081,7 @@ abstract class ElectrumWalletBase
if (walletInfo.isHardwareWallet) {
final transaction = await buildHardwareWalletTransaction(
utxos: estimatedTx.utxos,
outputs: outputs,
outputs: updatedOutputs,
publicKeys: estimatedTx.publicKeys,
fee: BigInt.from(estimatedTx.fee),
network: network,
@@ -1092,7 +1121,7 @@ abstract class ElectrumWalletBase
} else {
txb = BitcoinTransactionBuilder(
utxos: estimatedTx.utxos,
outputs: outputs,
outputs: updatedOutputs,
fee: BigInt.from(estimatedTx.fee),
network: network,
memo: estimatedTx.memo,