diff --git a/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java index 33f9fd88..43f30d65 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/PrivateKeySweepDialog.java @@ -68,6 +68,7 @@ public class PrivateKeySweepDialog extends Dialog { private final ComboBox toWallet; private final FeeRangeSlider feeRange; private final CopyableLabel feeRate; + private final UnlabeledToggleSwitch ignoreDust; private SilentPaymentAddress silentPaymentAddress; public PrivateKeySweepDialog(Wallet wallet) { @@ -170,7 +171,12 @@ public class PrivateKeySweepDialog extends Dialog { feeRange.setFeeRate(AppServices.getDefaultFeeRate()); updateFeeRate(); - fieldset.getChildren().addAll(keyField, keyScriptTypeField, addressField, toAddressField, feeRangeField, feeRateField); + Field useDustLimitField = new Field(); + useDustLimitField.setText("Ignore dust:"); + ignoreDust = new UnlabeledToggleSwitch(); + useDustLimitField.getInputs().add(ignoreDust); + + fieldset.getChildren().addAll(keyField, keyScriptTypeField, addressField, toAddressField, feeRangeField, feeRateField, useDustLimitField); form.getChildren().add(fieldset); dialogPane.setContent(form); @@ -383,7 +389,15 @@ public class PrivateKeySweepDialog extends Dialog { ElectrumServer.AddressUtxosService addressUtxosService = new ElectrumServer.AddressUtxosService(fromAddress, since); addressUtxosService.setOnSucceeded(successEvent -> { - createTransaction(privateKey.getKey(), scriptType, addressUtxosService.getValue(), payment); + List utxos = addressUtxosService.getValue(); + if(ignoreDust.isSelected()) { + utxos = removeDust(utxos); + if(utxos.isEmpty()) { + AppServices.showErrorDialog("No outputs to sweep", "All of the unspent outputs for this private key have been ignored as dust."); + return; + } + } + createTransaction(privateKey.getKey(), scriptType, utxos, payment); }); addressUtxosService.setOnFailed(failedEvent -> { Throwable rootCause = Throwables.getRootCause(failedEvent.getSource().getException()); @@ -403,6 +417,11 @@ public class PrivateKeySweepDialog extends Dialog { } } + private List removeDust(List txOutputs) { + long dustAttackThreshold = Config.get().getDustAttackThreshold(); + return txOutputs.stream().filter(txOutput -> txOutput.getValue() > dustAttackThreshold).collect(Collectors.toList()); + } + private void createTransaction(ECKey privKey, ScriptType scriptType, List txOutputs, Payment payment) { Address destAddress = payment instanceof SilentPayment silentPayment ? computeSilentPaymentAddress(privKey, scriptType, txOutputs, silentPayment) : payment.getAddress(); ECKey pubKey = ECKey.fromPublicOnly(privKey);