mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-11-05 11:56:37 +00:00
adapt to use declarative style to for consolidation payments
This commit is contained in:
parent
0974918cff
commit
092267339a
9 changed files with 74 additions and 35 deletions
2
drongo
2
drongo
|
|
@ -1 +1 @@
|
||||||
Subproject commit 286e04ad25de8f5739a70ac353ee073eace5e873
|
Subproject commit 4e68815fa977a45a7caddead35e5d0f90f5e8fd6
|
||||||
|
|
@ -727,7 +727,7 @@ public class TransactionDiagram extends GridPane {
|
||||||
recipientLabel.getStyleClass().add("output-label");
|
recipientLabel.getStyleClass().add("output-label");
|
||||||
recipientLabel.getStyleClass().add(labelledPayment ? "payment-label" : "recipient-label");
|
recipientLabel.getStyleClass().add(labelledPayment ? "payment-label" : "recipient-label");
|
||||||
Wallet toWallet = walletTx.getToWallet(AppServices.get().getOpenWallets().keySet(), payment);
|
Wallet toWallet = walletTx.getToWallet(AppServices.get().getOpenWallets().keySet(), payment);
|
||||||
WalletNode toNode = walletTx.getWallet() != null && !walletTx.getWallet().isBip47() ? walletTx.getAddressNodeMap().get(payment.getAddress()) : null;
|
WalletNode toNode = payment instanceof WalletNodePayment walletNodePayment ? walletNodePayment.getWalletNode() : null;
|
||||||
Wallet toBip47Wallet = getBip47SendWallet(payment);
|
Wallet toBip47Wallet = getBip47SendWallet(payment);
|
||||||
DnsPayment dnsPayment = DnsPaymentCache.getDnsPayment(payment);
|
DnsPayment dnsPayment = DnsPaymentCache.getDnsPayment(payment);
|
||||||
Tooltip recipientTooltip = new Tooltip((toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ")
|
Tooltip recipientTooltip = new Tooltip((toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ")
|
||||||
|
|
|
||||||
|
|
@ -90,20 +90,20 @@ public class TransactionDiagramLabel extends HBox {
|
||||||
outputLabels.add(mixOutputLabel);
|
outputLabels.add(mixOutputLabel);
|
||||||
}
|
}
|
||||||
} else if(walletTx.getPayments().size() >= 5 && walletTx.getPayments().stream().mapToLong(Payment::getAmount).distinct().count() <= 1 && walletTx.getWallet() != null
|
} else if(walletTx.getPayments().size() >= 5 && walletTx.getPayments().stream().mapToLong(Payment::getAmount).distinct().count() <= 1 && walletTx.getWallet() != null
|
||||||
&& walletTx.getWallet().getStandardAccountType() == StandardAccount.WHIRLPOOL_POSTMIX && walletTx.getPayments().stream().anyMatch(walletTx::isConsolidationSend)) {
|
&& walletTx.getWallet().getStandardAccountType() == StandardAccount.WHIRLPOOL_POSTMIX && !walletTx.getWalletNodePayments().isEmpty()) {
|
||||||
OutputLabel remixOutputLabel = getRemixOutputLabel(transactionDiagram, walletTx.getPayments());
|
OutputLabel remixOutputLabel = getRemixOutputLabel(transactionDiagram, walletTx.getPayments());
|
||||||
if(remixOutputLabel != null) {
|
if(remixOutputLabel != null) {
|
||||||
outputLabels.add(remixOutputLabel);
|
outputLabels.add(remixOutputLabel);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
List<Payment> payments = walletTx.getPayments().stream().filter(payment -> payment.getType() == Payment.Type.DEFAULT && !walletTx.isConsolidationSend(payment)).collect(Collectors.toList());
|
List<Payment> payments = walletTx.getExternalPayments().stream().filter(payment -> payment.getType() == Payment.Type.DEFAULT).collect(Collectors.toList());
|
||||||
List<OutputLabel> paymentLabels = payments.stream().map(payment -> getOutputLabel(transactionDiagram, payment)).collect(Collectors.toList());
|
List<OutputLabel> paymentLabels = payments.stream().map(payment -> getOutputLabel(transactionDiagram, payment)).collect(Collectors.toList());
|
||||||
if(walletTx.getSelectedUtxos().values().stream().allMatch(Objects::isNull)) {
|
if(walletTx.getSelectedUtxos().values().stream().allMatch(Objects::isNull)) {
|
||||||
paymentLabels.sort(Comparator.comparingInt(paymentLabel -> (paymentLabel.text.startsWith("Receive") ? 0 : 1)));
|
paymentLabels.sort(Comparator.comparingInt(paymentLabel -> (paymentLabel.text.startsWith("Receive") ? 0 : 1)));
|
||||||
}
|
}
|
||||||
outputLabels.addAll(paymentLabels);
|
outputLabels.addAll(paymentLabels);
|
||||||
|
|
||||||
List<Payment> consolidations = walletTx.getPayments().stream().filter(payment -> payment.getType() == Payment.Type.DEFAULT && walletTx.isConsolidationSend(payment)).collect(Collectors.toList());
|
List<Payment> consolidations = walletTx.getWalletNodePayments().stream().filter(payment -> payment.getType() == Payment.Type.DEFAULT).collect(Collectors.toList());
|
||||||
outputLabels.addAll(consolidations.stream().map(consolidation -> getOutputLabel(transactionDiagram, consolidation)).collect(Collectors.toList()));
|
outputLabels.addAll(consolidations.stream().map(consolidation -> getOutputLabel(transactionDiagram, consolidation)).collect(Collectors.toList()));
|
||||||
|
|
||||||
List<Payment> mixes = walletTx.getPayments().stream().filter(payment -> payment.getType() == Payment.Type.MIX || payment.getType() == Payment.Type.FAKE_MIX).collect(Collectors.toList());
|
List<Payment> mixes = walletTx.getPayments().stream().filter(payment -> payment.getType() == Payment.Type.MIX || payment.getType() == Payment.Type.FAKE_MIX).collect(Collectors.toList());
|
||||||
|
|
@ -203,7 +203,7 @@ public class TransactionDiagramLabel extends HBox {
|
||||||
private OutputLabel getOutputLabel(TransactionDiagram transactionDiagram, Payment payment) {
|
private OutputLabel getOutputLabel(TransactionDiagram transactionDiagram, Payment payment) {
|
||||||
WalletTransaction walletTx = transactionDiagram.getWalletTransaction();
|
WalletTransaction walletTx = transactionDiagram.getWalletTransaction();
|
||||||
Wallet toWallet = walletTx.getToWallet(AppServices.get().getOpenWallets().keySet(), payment);
|
Wallet toWallet = walletTx.getToWallet(AppServices.get().getOpenWallets().keySet(), payment);
|
||||||
WalletNode toNode = walletTx.getWallet() != null && !walletTx.getWallet().isBip47() ? walletTx.getAddressNodeMap().get(payment.getAddress()) : null;
|
WalletNode toNode = payment instanceof WalletNodePayment walletNodePayment ? walletNodePayment.getWalletNode() : null;
|
||||||
|
|
||||||
Glyph glyph = GlyphUtils.getOutputGlyph(transactionDiagram.getWalletTransaction(), payment);
|
Glyph glyph = GlyphUtils.getOutputGlyph(transactionDiagram.getWalletTransaction(), payment);
|
||||||
String text = (toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ") + transactionDiagram.getSatsValue(payment.getAmount()) + " sats to " + payment;
|
String text = (toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ") + transactionDiagram.getSatsValue(payment.getAmount()) + " sats to " + payment;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.sparrowwallet.sparrow.glyphfont;
|
package com.sparrowwallet.sparrow.glyphfont;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.wallet.Payment;
|
import com.sparrowwallet.drongo.wallet.Payment;
|
||||||
|
import com.sparrowwallet.drongo.wallet.WalletNodePayment;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletTransaction;
|
import com.sparrowwallet.drongo.wallet.WalletTransaction;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.control.TransactionDiagram;
|
import com.sparrowwallet.sparrow.control.TransactionDiagram;
|
||||||
|
|
@ -15,7 +16,7 @@ public class GlyphUtils {
|
||||||
return getFakeMixGlyph();
|
return getFakeMixGlyph();
|
||||||
} else if(payment.getType().equals(Payment.Type.ANCHOR)) {
|
} else if(payment.getType().equals(Payment.Type.ANCHOR)) {
|
||||||
return getAnchorGlyph();
|
return getAnchorGlyph();
|
||||||
} else if(walletTx.isConsolidationSend(payment)) {
|
} else if(payment instanceof WalletNodePayment) {
|
||||||
return getConsolidationGlyph();
|
return getConsolidationGlyph();
|
||||||
} else if(walletTx.isPremixSend(payment)) {
|
} else if(walletTx.isPremixSend(payment)) {
|
||||||
return getPremixGlyph();
|
return getPremixGlyph();
|
||||||
|
|
|
||||||
|
|
@ -643,19 +643,20 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
List<Payment> payments = new ArrayList<>();
|
List<Payment> payments = new ArrayList<>();
|
||||||
List<WalletTransaction.Output> outputs = new ArrayList<>();
|
List<WalletTransaction.Output> outputs = new ArrayList<>();
|
||||||
Map<WalletNode, Long> changeMap = new LinkedHashMap<>();
|
Map<WalletNode, Long> changeMap = new LinkedHashMap<>();
|
||||||
|
Map<Script, WalletNode> receiveOutputScripts = wallet.getWalletOutputScripts(KeyPurpose.RECEIVE);
|
||||||
Map<Script, WalletNode> changeOutputScripts = wallet.getWalletOutputScripts(wallet.getChangeKeyPurpose());
|
Map<Script, WalletNode> changeOutputScripts = wallet.getWalletOutputScripts(wallet.getChangeKeyPurpose());
|
||||||
for(TransactionOutput txOutput : headersForm.getTransaction().getOutputs()) {
|
for(TransactionOutput txOutput : headersForm.getTransaction().getOutputs()) {
|
||||||
WalletNode changeNode = changeOutputScripts.get(txOutput.getScript());
|
WalletNode changeNode = changeOutputScripts.get(txOutput.getScript());
|
||||||
if(changeNode != null) {
|
if(changeNode != null) {
|
||||||
if(headersForm.getTransaction().getOutputs().size() == 4 && headersForm.getTransaction().getOutputs().stream().anyMatch(txo -> txo != txOutput && txo.getValue() == txOutput.getValue())) {
|
if(headersForm.getTransaction().getOutputs().size() == 4 && headersForm.getTransaction().getOutputs().stream().anyMatch(txo -> txo != txOutput && txo.getValue() == txOutput.getValue())) {
|
||||||
if(selectedTxos.values().stream().allMatch(Objects::nonNull)) {
|
if(selectedTxos.values().stream().allMatch(Objects::nonNull)) {
|
||||||
payments.add(new Payment(txOutput.getScript().getToAddress(), ".." + changeNode + " (Fake Mix)", txOutput.getValue(), false, Payment.Type.FAKE_MIX));
|
payments.add(new WalletNodePayment(changeNode, ".." + changeNode + " (Fake Mix)", txOutput.getValue(), false, Payment.Type.FAKE_MIX));
|
||||||
} else {
|
} else {
|
||||||
payments.add(new Payment(txOutput.getScript().getToAddress(), ".." + changeNode + " (Mix)", txOutput.getValue(), false, Payment.Type.MIX));
|
payments.add(new WalletNodePayment(changeNode, ".." + changeNode + " (Mix)", txOutput.getValue(), false, Payment.Type.MIX));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(changeMap.containsKey(changeNode)) {
|
if(changeMap.containsKey(changeNode)) {
|
||||||
payments.add(new Payment(txOutput.getScript().getToAddress(), headersForm.getName(), txOutput.getValue(), false, Payment.Type.DEFAULT));
|
payments.add(new WalletNodePayment(changeNode, headersForm.getName(), txOutput.getValue(), false, Payment.Type.DEFAULT));
|
||||||
} else {
|
} else {
|
||||||
changeMap.put(changeNode, txOutput.getValue());
|
changeMap.put(changeNode, txOutput.getValue());
|
||||||
}
|
}
|
||||||
|
|
@ -672,12 +673,18 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
BlockTransactionHashIndex receivedTxo = walletTxos.keySet().stream().filter(txo -> txo.getHash().equals(txOutput.getHash()) && txo.getIndex() == txOutput.getIndex()).findFirst().orElse(null);
|
BlockTransactionHashIndex receivedTxo = walletTxos.keySet().stream().filter(txo -> txo.getHash().equals(txOutput.getHash()) && txo.getIndex() == txOutput.getIndex()).findFirst().orElse(null);
|
||||||
String label = headersForm.getName() == null || (headersForm.getName().startsWith("[") && headersForm.getName().endsWith("]") && headersForm.getName().length() == 8) ? null : headersForm.getName();
|
String label = headersForm.getName() == null || (headersForm.getName().startsWith("[") && headersForm.getName().endsWith("]") && headersForm.getName().length() == 8) ? null : headersForm.getName();
|
||||||
Address address = txOutput.getScript().getToAddress();
|
Address address = txOutput.getScript().getToAddress();
|
||||||
|
WalletNode receiveNode = receiveOutputScripts.get(txOutput.getScript());
|
||||||
SilentPaymentAddress silentPaymentAddress = headersForm.getSilentPaymentAddress(txOutput);
|
SilentPaymentAddress silentPaymentAddress = headersForm.getSilentPaymentAddress(txOutput);
|
||||||
label = receivedTxo != null ? receivedTxo.getLabel() : label;
|
label = receivedTxo != null ? receivedTxo.getLabel() : label;
|
||||||
if(address != null || silentPaymentAddress != null) {
|
if(address != null || silentPaymentAddress != null) {
|
||||||
Payment payment = (silentPaymentAddress == null ?
|
Payment payment;
|
||||||
new Payment(address, label, txOutput.getValue(), false, paymentType) :
|
if(silentPaymentAddress != null) {
|
||||||
new SilentPayment(silentPaymentAddress, address, label, txOutput.getValue(), false));
|
payment = new SilentPayment(silentPaymentAddress, address, label, txOutput.getValue(), false);
|
||||||
|
} else if(receiveNode != null) {
|
||||||
|
payment = new WalletNodePayment(receiveNode, label, txOutput.getValue(), false, paymentType);
|
||||||
|
} else {
|
||||||
|
payment = new Payment(address, label, txOutput.getValue(), false, paymentType);
|
||||||
|
}
|
||||||
WalletTransaction createdTx = AppServices.get().getCreatedTransaction(selectedTxos.keySet());
|
WalletTransaction createdTx = AppServices.get().getCreatedTransaction(selectedTxos.keySet());
|
||||||
if(createdTx != null) {
|
if(createdTx != null) {
|
||||||
Optional<String> optLabel = createdTx.getPayments().stream()
|
Optional<String> optLabel = createdTx.getPayments().stream()
|
||||||
|
|
@ -689,8 +696,13 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
payments.add(payment);
|
payments.add(payment);
|
||||||
outputs.add(payment instanceof SilentPayment silentPayment ? new WalletTransaction.SilentPaymentOutput(txOutput, silentPayment) :
|
if(payment instanceof SilentPayment silentPayment) {
|
||||||
new WalletTransaction.PaymentOutput(txOutput, payment));
|
outputs.add(new WalletTransaction.SilentPaymentOutput(txOutput, silentPayment));
|
||||||
|
} else if(payment instanceof WalletNodePayment walletNodePayment) {
|
||||||
|
outputs.add(new WalletTransaction.ConsolidationOutput(txOutput, walletNodePayment, walletNodePayment.getAmount()));
|
||||||
|
} else {
|
||||||
|
outputs.add(new WalletTransaction.PaymentOutput(txOutput, payment));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
outputs.add(new WalletTransaction.NonAddressOutput(txOutput));
|
outputs.add(new WalletTransaction.NonAddressOutput(txOutput));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,13 +126,14 @@ public class OutputController extends TransactionFormController implements Initi
|
||||||
WalletTransaction.Output output = outputs.get(outputForm.getIndex());
|
WalletTransaction.Output output = outputs.get(outputForm.getIndex());
|
||||||
if(output instanceof WalletTransaction.NonAddressOutput) {
|
if(output instanceof WalletTransaction.NonAddressOutput) {
|
||||||
outputFieldset.setText(baseText);
|
outputFieldset.setText(baseText);
|
||||||
} else if(output instanceof WalletTransaction.SilentPaymentOutput silentPaymentOutput) {
|
} else if(output instanceof WalletTransaction.SilentPaymentOutput) {
|
||||||
outputFieldset.setText(baseText + " - Silent Payment");
|
outputFieldset.setText(baseText + " - Silent Payment");
|
||||||
|
} else if(output instanceof WalletTransaction.ConsolidationOutput) {
|
||||||
|
outputFieldset.setText(baseText + " - Consolidation");
|
||||||
} else if(output instanceof WalletTransaction.PaymentOutput paymentOutput) {
|
} else if(output instanceof WalletTransaction.PaymentOutput paymentOutput) {
|
||||||
Payment payment = paymentOutput.getPayment();
|
Payment payment = paymentOutput.getPayment();
|
||||||
Wallet toWallet = walletTx.getToWallet(AppServices.get().getOpenWallets().keySet(), payment);
|
Wallet toWallet = walletTx.getToWallet(AppServices.get().getOpenWallets().keySet(), payment);
|
||||||
WalletNode toNode = walletTx.getWallet() != null && !walletTx.getWallet().isBip47() ? walletTx.getAddressNodeMap().get(payment.getAddress()) : null;
|
outputFieldset.setText(baseText + (toWallet == null ? " - Payment" : " - Received to " + toWallet.getFullDisplayName()));
|
||||||
outputFieldset.setText(baseText + (toWallet == null ? (toNode != null ? " - Consolidation" : " - Payment") : " - Received to " + toWallet.getFullDisplayName()));
|
|
||||||
} else if(output instanceof WalletTransaction.ChangeOutput changeOutput) {
|
} else if(output instanceof WalletTransaction.ChangeOutput changeOutput) {
|
||||||
outputFieldset.setText(baseText + " - Change to " + changeOutput.getWalletNode().toString());
|
outputFieldset.setText(baseText + " - Change to " + changeOutput.getWalletNode().toString());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,10 @@ public class OutputForm extends IndexedTransactionForm {
|
||||||
Payment payment = paymentOutput.getPayment();
|
Payment payment = paymentOutput.getPayment();
|
||||||
return new Label(payment.getLabel() != null && payment.getType() != Payment.Type.FAKE_MIX && payment.getType() != Payment.Type.MIX ? payment.getLabel() : payment.toString(),
|
return new Label(payment.getLabel() != null && payment.getType() != Payment.Type.FAKE_MIX && payment.getType() != Payment.Type.MIX ? payment.getLabel() : payment.toString(),
|
||||||
GlyphUtils.getOutputGlyph(getWalletTransaction(), payment));
|
GlyphUtils.getOutputGlyph(getWalletTransaction(), payment));
|
||||||
|
} else if(output instanceof WalletTransaction.ConsolidationOutput consolidationOutput) {
|
||||||
|
Payment payment = consolidationOutput.getWalletNodePayment();
|
||||||
|
return new Label(payment.getLabel() != null && payment.getType() != Payment.Type.FAKE_MIX && payment.getType() != Payment.Type.MIX ? payment.getLabel() : payment.toString(),
|
||||||
|
GlyphUtils.getOutputGlyph(getWalletTransaction(), payment));
|
||||||
} else if(output instanceof WalletTransaction.ChangeOutput changeOutput) {
|
} else if(output instanceof WalletTransaction.ChangeOutput changeOutput) {
|
||||||
return new Label("Change", GlyphUtils.getChangeGlyph());
|
return new Label("Change", GlyphUtils.getChangeGlyph());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,8 @@ public class PaymentController extends WalletFormController implements Initializ
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final ObjectProperty<WalletNode> consolidationNodeProperty = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
private final ObjectProperty<PayNym> payNymProperty = new SimpleObjectProperty<>();
|
private final ObjectProperty<PayNym> payNymProperty = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
private final ObjectProperty<SilentPaymentAddress> silentPaymentAddressProperty = new SimpleObjectProperty<>();
|
private final ObjectProperty<SilentPaymentAddress> silentPaymentAddressProperty = new SimpleObjectProperty<>();
|
||||||
|
|
@ -168,6 +170,10 @@ public class PaymentController extends WalletFormController implements Initializ
|
||||||
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
|
||||||
address.leftProperty().set(null);
|
address.leftProperty().set(null);
|
||||||
|
|
||||||
|
if(consolidationNodeProperty.get() != null && !newValue.equals(consolidationNodeProperty.get().getAddress().toString())) {
|
||||||
|
consolidationNodeProperty.set(null);
|
||||||
|
}
|
||||||
|
|
||||||
if(payNymProperty.get() != null && !newValue.equals(payNymProperty.get().nymName())) {
|
if(payNymProperty.get() != null && !newValue.equals(payNymProperty.get().nymName())) {
|
||||||
payNymProperty.set(null);
|
payNymProperty.set(null);
|
||||||
}
|
}
|
||||||
|
|
@ -259,6 +265,17 @@ public class PaymentController extends WalletFormController implements Initializ
|
||||||
//ignore, not a silent payment address
|
//ignore, not a silent payment address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Address toAddress = Address.fromString(newValue);
|
||||||
|
WalletNode walletNode = sendController.getWalletNode(toAddress);
|
||||||
|
if(walletNode != null) {
|
||||||
|
consolidationNodeProperty.set(walletNode);
|
||||||
|
}
|
||||||
|
label.requestFocus();
|
||||||
|
} catch(Exception e) {
|
||||||
|
//ignore, not an address
|
||||||
|
}
|
||||||
|
|
||||||
revalidateAmount();
|
revalidateAmount();
|
||||||
maxButton.setDisable(!isMaxButtonEnabled());
|
maxButton.setDisable(!isMaxButtonEnabled());
|
||||||
sendController.updateTransaction();
|
sendController.updateTransaction();
|
||||||
|
|
@ -658,8 +675,11 @@ public class PaymentController extends WalletFormController implements Initializ
|
||||||
if(!label.getText().isEmpty() && value != null && value >= getRecipientDustThreshold()) {
|
if(!label.getText().isEmpty() && value != null && value >= getRecipientDustThreshold()) {
|
||||||
Payment payment;
|
Payment payment;
|
||||||
SilentPaymentAddress silentPaymentAddress = silentPaymentAddressProperty.get();
|
SilentPaymentAddress silentPaymentAddress = silentPaymentAddressProperty.get();
|
||||||
|
WalletNode consolidationNode = consolidationNodeProperty.get();
|
||||||
if(silentPaymentAddress != null) {
|
if(silentPaymentAddress != null) {
|
||||||
payment = new SilentPayment(silentPaymentAddress, label.getText(), value, sendAll);
|
payment = new SilentPayment(silentPaymentAddress, label.getText(), value, sendAll);
|
||||||
|
} else if(consolidationNode != null) {
|
||||||
|
payment = new WalletNodePayment(consolidationNode, label.getText(), value, sendAll);
|
||||||
} else {
|
} else {
|
||||||
payment = new Payment(recipientAddress, label.getText(), value, sendAll);
|
payment = new Payment(recipientAddress, label.getText(), value, sendAll);
|
||||||
}
|
}
|
||||||
|
|
@ -718,6 +738,7 @@ public class PaymentController extends WalletFormController implements Initializ
|
||||||
setSendMax(false);
|
setSendMax(false);
|
||||||
|
|
||||||
dustAmountProperty.set(false);
|
dustAmountProperty.set(false);
|
||||||
|
consolidationNodeProperty.set(null);
|
||||||
payNymProperty.set(null);
|
payNymProperty.set(null);
|
||||||
dnsPaymentProperty.set(null);
|
dnsPaymentProperty.set(null);
|
||||||
silentPaymentAddressProperty.set(null);
|
silentPaymentAddressProperty.set(null);
|
||||||
|
|
@ -728,8 +749,7 @@ public class PaymentController extends WalletFormController implements Initializ
|
||||||
if(utxoSelector == null) {
|
if(utxoSelector == null) {
|
||||||
MaxUtxoSelector maxUtxoSelector = new MaxUtxoSelector();
|
MaxUtxoSelector maxUtxoSelector = new MaxUtxoSelector();
|
||||||
sendController.utxoSelectorProperty().set(maxUtxoSelector);
|
sendController.utxoSelectorProperty().set(maxUtxoSelector);
|
||||||
} else if(utxoSelector instanceof PresetUtxoSelector && !isValidAddressAndLabel() && sendController.getPaymentTabs().getTabs().size() == 1) {
|
} else if(utxoSelector instanceof PresetUtxoSelector presetUtxoSelector && !isValidAddressAndLabel() && sendController.getPaymentTabs().getTabs().size() == 1) {
|
||||||
PresetUtxoSelector presetUtxoSelector = (PresetUtxoSelector)utxoSelector;
|
|
||||||
Payment payment = new Payment(null, null, presetUtxoSelector.getPresetUtxos().stream().mapToLong(BlockTransactionHashIndex::getValue).sum(), true);
|
Payment payment = new Payment(null, null, presetUtxoSelector.getPresetUtxos().stream().mapToLong(BlockTransactionHashIndex::getValue).sum(), true);
|
||||||
setPayment(payment);
|
setPayment(payment);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
|
|
||||||
private final Set<WalletNode> excludedChangeNodes = new HashSet<>();
|
private final Set<WalletNode> excludedChangeNodes = new HashSet<>();
|
||||||
|
|
||||||
private final Map<Wallet, Map<Address, WalletNode>> addressNodeMap = new HashMap<>();
|
private final Map<Address, WalletNode> walletAddresses = new HashMap<>();
|
||||||
|
|
||||||
private final ChangeListener<String> feeListener = new ChangeListener<>() {
|
private final ChangeListener<String> feeListener = new ChangeListener<>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -619,7 +619,7 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
boolean allowRbf = (replacedTransaction == null || replacedTransaction.getTransaction().isReplaceByFee())
|
boolean allowRbf = (replacedTransaction == null || replacedTransaction.getTransaction().isReplaceByFee())
|
||||||
&& payments.stream().noneMatch(payment -> payment instanceof SilentPayment);
|
&& payments.stream().noneMatch(payment -> payment instanceof SilentPayment);
|
||||||
|
|
||||||
walletTransactionService = new WalletTransactionService(addressNodeMap, wallet, getUtxoSelectors(payments), getTxoFilters(),
|
walletTransactionService = new WalletTransactionService(wallet, getUtxoSelectors(payments), getTxoFilters(),
|
||||||
payments, opReturnsList, excludedChangeNodes,
|
payments, opReturnsList, excludedChangeNodes,
|
||||||
feeRate, getMinimumFeeRate(), minRelayFeeRate, userFee,
|
feeRate, getMinimumFeeRate(), minRelayFeeRate, userFee,
|
||||||
currentBlockHeight, groupByAddress, includeMempoolOutputs, replacedTransaction, allowRbf);
|
currentBlockHeight, groupByAddress, includeMempoolOutputs, replacedTransaction, allowRbf);
|
||||||
|
|
@ -684,7 +684,6 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class WalletTransactionService extends Service<WalletTransaction> {
|
private static class WalletTransactionService extends Service<WalletTransaction> {
|
||||||
private final Map<Wallet, Map<Address, WalletNode>> addressNodeMap;
|
|
||||||
private final Wallet wallet;
|
private final Wallet wallet;
|
||||||
private final List<UtxoSelector> utxoSelectors;
|
private final List<UtxoSelector> utxoSelectors;
|
||||||
private final List<TxoFilter> txoFilters;
|
private final List<TxoFilter> txoFilters;
|
||||||
|
|
@ -702,13 +701,11 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
private final boolean allowRbf;
|
private final boolean allowRbf;
|
||||||
private boolean ignoreResult;
|
private boolean ignoreResult;
|
||||||
|
|
||||||
public WalletTransactionService(Map<Wallet, Map<Address, WalletNode>> addressNodeMap,
|
public WalletTransactionService(Wallet wallet, List<UtxoSelector> utxoSelectors, List<TxoFilter> txoFilters,
|
||||||
Wallet wallet, List<UtxoSelector> utxoSelectors, List<TxoFilter> txoFilters,
|
|
||||||
List<Payment> payments, List<byte[]> opReturns, Set<WalletNode> excludedChangeNodes,
|
List<Payment> payments, List<byte[]> opReturns, Set<WalletNode> excludedChangeNodes,
|
||||||
double feeRate, double longTermFeeRate, double minRelayFeeRate, Long fee,
|
double feeRate, double longTermFeeRate, double minRelayFeeRate, Long fee,
|
||||||
Integer currentBlockHeight, boolean groupByAddress, boolean includeMempoolOutputs,
|
Integer currentBlockHeight, boolean groupByAddress, boolean includeMempoolOutputs,
|
||||||
BlockTransaction replacedTransaction, boolean allowRbf) {
|
BlockTransaction replacedTransaction, boolean allowRbf) {
|
||||||
this.addressNodeMap = addressNodeMap;
|
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
this.utxoSelectors = utxoSelectors;
|
this.utxoSelectors = utxoSelectors;
|
||||||
this.txoFilters = txoFilters;
|
this.txoFilters = txoFilters;
|
||||||
|
|
@ -759,11 +756,8 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
private WalletTransaction getWalletTransaction() throws InsufficientFundsException {
|
private WalletTransaction getWalletTransaction() throws InsufficientFundsException {
|
||||||
try {
|
try {
|
||||||
updateMessage("Selecting UTXOs...");
|
updateMessage("Selecting UTXOs...");
|
||||||
WalletTransaction walletTransaction = wallet.createWalletTransaction(utxoSelectors, txoFilters, payments, opReturns, excludedChangeNodes,
|
return wallet.createWalletTransaction(utxoSelectors, txoFilters, payments, opReturns, excludedChangeNodes,
|
||||||
feeRate, longTermFeeRate, minRelayFeeRate, fee, currentBlockHeight, groupByAddress, includeMempoolOutputs, allowRbf);
|
feeRate, longTermFeeRate, minRelayFeeRate, fee, currentBlockHeight, groupByAddress, includeMempoolOutputs, allowRbf);
|
||||||
updateMessage("Deriving keys...");
|
|
||||||
walletTransaction.updateAddressNodeMap(addressNodeMap, walletTransaction.getWallet());
|
|
||||||
return walletTransaction;
|
|
||||||
} finally {
|
} finally {
|
||||||
updateMessage("");
|
updateMessage("");
|
||||||
}
|
}
|
||||||
|
|
@ -1131,7 +1125,7 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
|
|
||||||
paymentCodeProperty.set(null);
|
paymentCodeProperty.set(null);
|
||||||
|
|
||||||
addressNodeMap.clear();
|
walletAddresses.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UtxoSelector getUtxoSelector() {
|
public UtxoSelector getUtxoSelector() {
|
||||||
|
|
@ -1209,13 +1203,20 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
WalletTransaction walletTransaction = walletTransactionProperty.get();
|
WalletTransaction walletTransaction = walletTransactionProperty.get();
|
||||||
Set<WalletNode> nodes = new LinkedHashSet<>(walletTransaction.getSelectedUtxos().values());
|
Set<WalletNode> nodes = new LinkedHashSet<>(walletTransaction.getSelectedUtxos().values());
|
||||||
nodes.addAll(walletTransaction.getChangeMap().keySet());
|
nodes.addAll(walletTransaction.getChangeMap().keySet());
|
||||||
Map<Address, WalletNode> addressNodeMap = walletTransaction.getAddressNodeMap();
|
nodes.addAll(walletTransaction.getWalletNodePayments().stream().map(WalletNodePayment::getWalletNode).collect(Collectors.toList()));
|
||||||
nodes.addAll(addressNodeMap.values().stream().filter(Objects::nonNull).collect(Collectors.toList()));
|
|
||||||
|
|
||||||
//All wallet nodes applicable to this transaction are stored so when the subscription status for one is updated, the history for all can be fetched in one atomic update
|
//All wallet nodes applicable to this transaction are stored so when the subscription status for one is updated, the history for all can be fetched in one atomic update
|
||||||
walletForm.addWalletTransactionNodes(nodes);
|
walletForm.addWalletTransactionNodes(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WalletNode getWalletNode(Address address) {
|
||||||
|
if(walletAddresses.isEmpty()) {
|
||||||
|
walletAddresses.putAll(getWalletForm().getWallet().getWalletAddresses());
|
||||||
|
}
|
||||||
|
|
||||||
|
return walletAddresses.get(address);
|
||||||
|
}
|
||||||
|
|
||||||
public void broadcastNotification(ActionEvent event) {
|
public void broadcastNotification(ActionEvent event) {
|
||||||
Wallet wallet = getWalletForm().getWallet();
|
Wallet wallet = getWalletForm().getWallet();
|
||||||
Storage storage = AppServices.get().getOpenWallets().get(wallet);
|
Storage storage = AppServices.get().getOpenWallets().get(wallet);
|
||||||
|
|
@ -1667,12 +1668,12 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
public PrivacyAnalysisTooltip(WalletTransaction walletTransaction) {
|
public PrivacyAnalysisTooltip(WalletTransaction walletTransaction) {
|
||||||
List<Payment> payments = walletTransaction.getPayments();
|
List<Payment> payments = walletTransaction.getPayments();
|
||||||
List<Payment> userPayments = payments.stream().filter(payment -> payment.getType() != Payment.Type.FAKE_MIX).collect(Collectors.toList());
|
List<Payment> userPayments = payments.stream().filter(payment -> payment.getType() != Payment.Type.FAKE_MIX).collect(Collectors.toList());
|
||||||
Map<Address, WalletNode> walletAddresses = walletTransaction.getAddressNodeMap();
|
List<WalletNodePayment> walletNodePayments = walletTransaction.getWalletNodePayments();
|
||||||
OptimizationStrategy optimizationStrategy = getPreferredOptimizationStrategy();
|
OptimizationStrategy optimizationStrategy = getPreferredOptimizationStrategy();
|
||||||
boolean fakeMixPresent = payments.stream().anyMatch(payment -> payment.getType() == Payment.Type.FAKE_MIX);
|
boolean fakeMixPresent = payments.stream().anyMatch(payment -> payment.getType() == Payment.Type.FAKE_MIX);
|
||||||
boolean roundPaymentAmounts = userPayments.stream().anyMatch(payment -> payment.getAmount() % 100 == 0);
|
boolean roundPaymentAmounts = userPayments.stream().anyMatch(payment -> payment.getAmount() % 100 == 0);
|
||||||
boolean mixedAddressTypes = userPayments.stream().anyMatch(payment -> payment.getAddress().getScriptType() != getWalletForm().getWallet().getFreshNode(KeyPurpose.RECEIVE).getAddress().getScriptType());
|
boolean mixedAddressTypes = userPayments.stream().anyMatch(payment -> payment.getAddress().getScriptType() != getWalletForm().getWallet().getFreshNode(KeyPurpose.RECEIVE).getAddress().getScriptType());
|
||||||
boolean addressReuse = userPayments.stream().anyMatch(payment -> walletAddresses.get(payment.getAddress()) != null && !walletAddresses.get(payment.getAddress()).getTransactionOutputs().isEmpty());
|
boolean addressReuse = walletNodePayments.stream().anyMatch(walletNodePayment -> !walletNodePayment.getWalletNode().getTransactionOutputs().isEmpty());
|
||||||
boolean payjoinPresent = userPayments.stream().anyMatch(payment -> AppServices.getPayjoinURI(payment.getAddress()) != null);
|
boolean payjoinPresent = userPayments.stream().anyMatch(payment -> AppServices.getPayjoinURI(payment.getAddress()) != null);
|
||||||
|
|
||||||
if(optimizationStrategy == OptimizationStrategy.PRIVACY) {
|
if(optimizationStrategy == OptimizationStrategy.PRIVACY) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue