diff --git a/drongo b/drongo index 4da2c024..3e91bdb4 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 4da2c024d4fbe3ecbca9772a0761def6d5269c38 +Subproject commit 3e91bdb46cd235247550b2b579285a05609c0837 diff --git a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java index 639152d3..af77b4b6 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java @@ -213,7 +213,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { verboseTransaction.blockhash = Sha256Hash.ZERO_HASH.toString(); result.put(txid, verboseTransaction); } catch(Exception ex) { - throw new ElectrumServerRpcException("Error retrieving transaction: ", ex); + //ignore } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java index 07daaa95..8fac7034 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java @@ -25,6 +25,7 @@ import com.sparrowwallet.sparrow.wallet.HashIndexEntry; import com.sparrowwallet.sparrow.wallet.TransactionEntry; import javafx.application.Platform; import javafx.collections.FXCollections; +import javafx.collections.ObservableMap; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; @@ -415,17 +416,17 @@ public class HeadersController extends TransactionFormController implements Init } }); - headersForm.signingWalletProperty().addListener((observable, oldValue, signingWallet) -> { - initializeSignButton(signingWallet); - updateSignedKeystores(signingWallet); - - int threshold = signingWallet.getDefaultPolicy().getNumSignaturesRequired(); - signaturesProgressBar.initialize(headersForm.getSignatureKeystoreMap(), threshold); - }); - Platform.runLater(this::requestOpenWallets); } + headersForm.signingWalletProperty().addListener((observable, oldValue, signingWallet) -> { + initializeSignButton(signingWallet); + updateSignedKeystores(signingWallet); + + int threshold = signingWallet.getDefaultPolicy().getNumSignaturesRequired(); + signaturesProgressBar.initialize(headersForm.getSignatureKeystoreMap(), threshold); + }); + blockchainForm.setDynamicUpdate(this); } @@ -756,7 +757,7 @@ public class HeadersController extends TransactionFormController implements Init } private void updateSignedKeystores(Wallet signingWallet) { - Map> signedKeystoresMap = signingWallet.getSignedKeystores(headersForm.getPsbt()); + Map> signedKeystoresMap = headersForm.getPsbt() == null ? signingWallet.getSignedKeystores(headersForm.getTransaction()) : signingWallet.getSignedKeystores(headersForm.getPsbt()); Optional> optSignedKeystores = signedKeystoresMap.values().stream().filter(map -> !map.isEmpty()).min(Comparator.comparingInt(Map::size)); optSignedKeystores.ifPresent(signedKeystores -> { headersForm.getSignatureKeystoreMap().keySet().retainAll(signedKeystores.keySet()); @@ -781,7 +782,9 @@ public class HeadersController extends TransactionFormController implements Init public void broadcastTransaction(ActionEvent event) { broadcastButton.setDisable(true); - extractTransaction(event); + if(headersForm.getPsbt() != null) { + extractTransaction(event); + } if(headersForm.getSigningWallet() instanceof FinalizingPSBTWallet) { //Ensure the script hashes of the UTXOs in FinalizingPSBTWallet are subscribed to @@ -818,6 +821,21 @@ public class HeadersController extends TransactionFormController implements Init } }); transactionMempoolService.start(); + } else { + Sha256Hash txid = headersForm.getTransaction().getTxId(); + ElectrumServer.TransactionReferenceService transactionReferenceService = new ElectrumServer.TransactionReferenceService(Set.of(txid)); + transactionReferenceService.setOnSucceeded(successEvent -> { + Map transactionMap = transactionReferenceService.getValue(); + BlockTransaction blockTransaction = transactionMap.get(txid); + if(blockTransaction != null) { + headersForm.setBlockTransaction(blockTransaction); + updateBlockchainForm(blockTransaction, AppServices.getCurrentBlockHeight()); + } + }); + transactionReferenceService.setOnFailed(failedEvent -> { + log.error("Error fetching broadcasted transaction", failedEvent.getSource().getException()); + }); + transactionReferenceService.start(); } }); broadcastTransactionService.setOnFailed(workerStateEvent -> { @@ -903,6 +921,43 @@ public class HeadersController extends TransactionFormController implements Init if(event.getTxId().equals(headersForm.getTransaction().getTxId())) { if(event.getBlockTransaction() != null && (!Sha256Hash.ZERO_HASH.equals(event.getBlockTransaction().getBlockHash()) || headersForm.getBlockTransaction() == null)) { updateBlockchainForm(event.getBlockTransaction(), AppServices.getCurrentBlockHeight()); + } else if(headersForm.getPsbt() == null) { + boolean isSigned = true; + ObservableMap signatureKeystoreMap = FXCollections.observableMap(new LinkedHashMap<>()); + for(TransactionInput txInput : headersForm.getTransaction().getInputs()) { + List signatures = txInput.hasWitness() ? txInput.getWitness().getSignatures() : txInput.getScriptSig().getSignatures(); + + if(signatures.isEmpty()) { + isSigned = false; + break; + } + + if(signatureKeystoreMap.isEmpty()) { + for(int i = 0; i < signatures.size(); i++) { + signatureKeystoreMap.put(signatures.get(i), new Keystore("Keystore " + (i+1))); + } + } + } + + if(isSigned) { + blockchainForm.setVisible(false); + signaturesForm.setVisible(true); + broadcastButtonBox.setVisible(true); + viewFinalButton.setDisable(true); + + if(headersForm.getSigningWallet() == null) { + for(Wallet wallet : AppServices.get().getOpenWallets().keySet()) { + if(wallet.canSign(headersForm.getTransaction())) { + headersForm.setSigningWallet(wallet); + break; + } + } + } + + if(headersForm.getSigningWallet() == null) { + signaturesProgressBar.initialize(signatureKeystoreMap, signatureKeystoreMap.size()); + } + } } Long feeAmt = calculateFee(event.getInputTransactions());