warn sp dust (#2402)

* feat: warn sp dust

* Update lib/view_model/send/send_view_model.dart

* fix condition

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
rafael_xmr
2025-07-29 15:50:11 +03:00
committed by GitHub
co-authored by Omar Hatem
parent 888319dd7a
commit 10499814bb
3 changed files with 46 additions and 8 deletions
+24 -2
View File
@@ -780,7 +780,11 @@ abstract class ElectrumWalletBase
}
if (outputs.length == 1) {
outputs[0] = BitcoinOutput(address: outputs.last.address, value: BigInt.from(amount));
outputs[0] = BitcoinOutput(
address: outputs.last.address,
value: BigInt.from(amount),
isSilentPayment: hasSilentPayment,
);
}
return EstimatedTxResult(
@@ -888,7 +892,17 @@ abstract class ElectrumWalletBase
);
updatedOutputs.clear();
updatedOutputs.addAll(temp);
for (int i = 0; i < temp.length; i++) {
final output = temp[i];
final oldOutput = outputs[i];
updatedOutputs.add(BitcoinOutput(
address: output.address,
value: output.value,
isSilentPayment: oldOutput.isSilentPayment,
isChange: output.isChange,
));
}
if (fee == 0) {
throw BitcoinTransactionNoFeeException();
@@ -1088,6 +1102,14 @@ abstract class ElectrumWalletBase
);
}
for (final output in updatedOutputs) {
// TODO: get from server
// if (output.isSilentPayment && output.value.toInt() > silentPaymentsMin) {
if (output.isSilentPayment && output.value.toInt() <= 1000) {
throw BitcoinTransactionNoDustException();
}
}
if (walletInfo.isHardwareWallet) {
final transaction = await buildHardwareWalletTransaction(
utxos: estimatedTx.utxos,
+1 -1
View File
@@ -258,7 +258,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
!sendViewModel.isBatchSending && sendViewModel.shouldDisplaySendALL,
currencyValueValidator: output.sendAll
? sendViewModel.allAmountValidator
: sendViewModel.amountValidator,
: sendViewModel.amountValidator(output),
allAmountCallback: () async =>
output.setSendAll(await sendViewModel.sendingBalance),
),
+21 -5
View File
@@ -182,9 +182,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
if (pendingTransaction != null) {
final currency = pendingTransactionFeeCurrency(walletType);
final fiat = calculateFiatAmount(
price: _fiatConversationStore.prices[currency]!,
cryptoAmount: pendingTransaction!.feeFormattedValue,
);
price: _fiatConversationStore.prices[currency]!,
cryptoAmount: pendingTransaction!.feeFormattedValue,
);
return fiat;
} else {
return '0.00';
@@ -210,8 +210,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
CryptoCurrency get currency => wallet.currency;
Validator<String> get amountValidator =>
AmountValidator(currency: walletTypeToCryptoCurrency(wallet.type));
Validator<String> amountValidator(Output output) => AmountValidator(
currency: walletTypeToCryptoCurrency(wallet.type),
minValue: isSendToSilentPayments(output)
?
// TODO: get from server
// bitcoin!.silentPaymentsMinAmount
'0.00001'
: null,
);
Validator<String> get allAmountValidator => AllAmountValidator();
@@ -289,6 +296,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
// If silent payments scanning, can still send payments
(wallet.type == WalletType.bitcoin && wallet.syncStatus is SyncingSyncStatus);
bool isSendToSilentPayments(Output output) =>
wallet.type == WalletType.bitcoin &&
(RegExp(AddressValidator.silentPaymentAddressPatternMainnet).hasMatch(output.address) ||
RegExp(AddressValidator.silentPaymentAddressPatternMainnet)
.hasMatch(output.extractedAddress) ||
(output.parsedAddress.addresses.isNotEmpty &&
RegExp(AddressValidator.silentPaymentAddressPatternMainnet)
.hasMatch(output.parsedAddress.addresses[0])));
@computed
List<Template> get templates => sendTemplateViewModel.templates
.where((template) => _isEqualCurrency(template.cryptoCurrency))