diff --git a/drongo b/drongo index 7facf4ca..c0333df6 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 7facf4ca371f8df16f6da60913b45d375d5593a8 +Subproject commit c0333df629682472925279de60b6c172ab3290ac diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index f8ba6462..3a7927aa 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -1539,7 +1539,7 @@ public class AppController implements Initializable { bitcoinUnit = wallet.getAutoUnit(); } - sendToManyDialog = new SendToManyDialog(bitcoinUnit, Config.get().getUnitFormat(), initialPayments); + sendToManyDialog = new SendToManyDialog(wallet, bitcoinUnit, Config.get().getUnitFormat(), initialPayments); sendToManyDialog.initModality(Modality.NONE); Optional> optPayments = sendToManyDialog.showAndWait(); sendToManyDialog = null; diff --git a/src/main/java/com/sparrowwallet/sparrow/AppServices.java b/src/main/java/com/sparrowwallet/sparrow/AppServices.java index 6339d266..3fab2342 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppServices.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppServices.java @@ -1136,7 +1136,7 @@ public class AppServices { if(wallet != null) { final Wallet sendingWallet = wallet; EventManager.get().post(new SendActionEvent(sendingWallet, new ArrayList<>(sendingWallet.getSpendableUtxos().keySet()), true)); - Platform.runLater(() -> EventManager.get().post(new SendPaymentsEvent(sendingWallet, List.of(bitcoinURI.toPayment()), bitcoinURI))); + Platform.runLater(() -> EventManager.get().post(new SendPaymentsEvent(sendingWallet, List.of(bitcoinURI.toPayment(sendingWallet)), bitcoinURI))); } } catch(Exception e) { showErrorDialog("Not a valid bitcoin URI", e.getMessage()); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/SendToManyDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/SendToManyDialog.java index 6932e149..ce611257 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/SendToManyDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/SendToManyDialog.java @@ -13,6 +13,7 @@ import com.sparrowwallet.drongo.silentpayments.SilentPayment; import com.sparrowwallet.drongo.silentpayments.SilentPaymentAddress; import com.sparrowwallet.drongo.uri.BitcoinURIParseException; import com.sparrowwallet.drongo.wallet.Payment; +import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.UnitFormat; @@ -47,13 +48,15 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; public class SendToManyDialog extends Dialog> { + private final Wallet wallet; private final BitcoinUnit bitcoinUnit; private final UnitFormat unitFormat; private final UnitFormatDoubleCellType amountCellType; private final SpreadsheetView spreadsheetView; public static final SendToAddressCellType SEND_TO_ADDRESS = new SendToAddressCellType(); - public SendToManyDialog(BitcoinUnit bitcoinUnit, UnitFormat unitFormat, List payments) { + public SendToManyDialog(Wallet wallet, BitcoinUnit bitcoinUnit, UnitFormat unitFormat, List payments) { + this.wallet = wallet; this.bitcoinUnit = bitcoinUnit; this.unitFormat = unitFormat == null ? UnitFormat.DOT : unitFormat; this.amountCellType = new UnitFormatDoubleCellType(this.unitFormat); @@ -557,26 +560,29 @@ public class SendToManyDialog extends Dialog> { return payment instanceof SilentPayment ? new SendToAddress(((SilentPayment)payment).getSilentPaymentAddress()) : new SendToAddress(payment.getAddress()); } - public Payment toPayment(String label, long value, boolean sendMax) throws DnsPaymentValidationException, IOException, ExecutionException, InterruptedException, BitcoinURIParseException { + public Payment toPayment(Wallet wallet, String label, long value, boolean sendMax) throws DnsPaymentValidationException, IOException, ExecutionException, InterruptedException, BitcoinURIParseException { if(hrn != null) { DnsPayment dnsPayment = DnsPaymentCache.getDnsPayment(hrn); if(dnsPayment == null) { DnsPaymentResolver resolver = new DnsPaymentResolver(hrn); Optional optDnsPayment = resolver.resolve(AppServices.getProxy()); - if(optDnsPayment.isPresent()) { - dnsPayment = optDnsPayment.get(); - if(dnsPayment.hasAddress()) { - DnsPaymentCache.putDnsPayment(dnsPayment.bitcoinURI().getAddress(), dnsPayment); - } else if(dnsPayment.hasSilentPaymentAddress()) { - DnsPaymentCache.putDnsPayment(dnsPayment.bitcoinURI().getSilentPaymentAddress(), dnsPayment); - } - return getPayment(optDnsPayment.get(), label, value, sendMax); - } else { + if(optDnsPayment.isEmpty()) { throw new IllegalArgumentException("Payment to " + hrn + " could not be resolved."); } - } else { - return getPayment(dnsPayment, label, value, sendMax); + + dnsPayment = optDnsPayment.get(); } + + //Cached under the address this payment will be looked up by, which is how its proof chain reaches the PSBT output. A name found by + //hrn alone can be held under the other address, having been resolved for a wallet of the other silent payments capability + Payment payment = getPayment(wallet, dnsPayment, label, value, sendMax); + if(payment instanceof SilentPayment silentPayment) { + DnsPaymentCache.putDnsPayment(silentPayment.getSilentPaymentAddress(), dnsPayment); + } else { + DnsPaymentCache.putDnsPayment(payment.getAddress(), dnsPayment); + } + + return payment; } if(silentPaymentAddress != null) { @@ -586,11 +592,11 @@ public class SendToManyDialog extends Dialog> { } } - private static Payment getPayment(DnsPayment dnsPayment, String label, long value, boolean sendMax) { - if(dnsPayment.hasAddress()) { - return new Payment(dnsPayment.bitcoinURI().getAddress(), label, value, sendMax); - } else if(dnsPayment.hasSilentPaymentAddress()) { + private static Payment getPayment(Wallet wallet, DnsPayment dnsPayment, String label, long value, boolean sendMax) { + if(dnsPayment.hasSilentPaymentAddress() && (!dnsPayment.hasAddress() || wallet.canSendSilentPayments())) { return new SilentPayment(dnsPayment.bitcoinURI().getSilentPaymentAddress(), label, value, sendMax); + } else if(dnsPayment.hasAddress()) { + return new Payment(dnsPayment.bitcoinURI().getAddress(), label, value, sendMax); } else { throw new IllegalArgumentException("Payment to " + dnsPayment + " has no associated address."); } @@ -650,7 +656,7 @@ public class SendToManyDialog extends Dialog> { } if(sendToAddress != null && value != null) { - payments.add(sendToAddress.toPayment(label, bitcoinUnit.getSatsValue(value), false)); + payments.add(sendToAddress.toPayment(wallet, label, bitcoinUnit.getSatsValue(value), false)); } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java index ac35f564..33eec388 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java @@ -467,11 +467,11 @@ public class PaymentController extends WalletFormController implements Initializ } public void setDnsPayment(DnsPayment dnsPayment) { - if(dnsPayment.hasAddress()) { - DnsPaymentCache.putDnsPayment(dnsPayment.bitcoinURI().getAddress(), dnsPayment); - } else if(dnsPayment.hasSilentPaymentAddress()) { + if(dnsPayment.hasSilentPaymentAddress() && (!dnsPayment.hasAddress() || sendController.getWalletForm().getWallet().canSendSilentPayments())) { DnsPaymentCache.putDnsPayment(dnsPayment.bitcoinURI().getSilentPaymentAddress(), dnsPayment); setSilentPaymentAddress(dnsPayment.bitcoinURI().getSilentPaymentAddress()); + } else if(dnsPayment.hasAddress()) { + DnsPaymentCache.putDnsPayment(dnsPayment.bitcoinURI().getAddress(), dnsPayment); } else { AppServices.showWarningDialog("No Address Provided", "The DNS payment instruction for " + dnsPayment.hrn() + " resolved correctly but did not contain a bitcoin address."); return; @@ -827,10 +827,11 @@ public class PaymentController extends WalletFormController implements Initializ } private void updateFromURI(BitcoinURI bitcoinURI) { - if(bitcoinURI.getAddress() != null) { - address.setText(bitcoinURI.getAddress().toString()); - } else if(bitcoinURI.getSilentPaymentAddress() != null) { + //A URI carrying both publishes the address in its body as a fallback for a sender which cannot pay the silent payment address in its query + if(bitcoinURI.getSilentPaymentAddress() != null && (bitcoinURI.getAddress() == null || sendController.getWalletForm().getWallet().canSendSilentPayments())) { address.setText(bitcoinURI.getSilentPaymentAddress().getAddress()); + } else if(bitcoinURI.getAddress() != null) { + address.setText(bitcoinURI.getAddress().toString()); } if(bitcoinURI.getLabel() != null) { label.setText(bitcoinURI.getLabel());