Search in sources :

Example 1 with TransactionOutPoint

use of com.sparrowwallet.drongo.protocol.TransactionOutPoint in project sparrow by sparrowwallet.

the class SendController method broadcastNotification.

public void broadcastNotification(Wallet decryptedWallet) {
    try {
        PaymentCode paymentCode = decryptedWallet.getPaymentCode();
        PaymentCode externalPaymentCode = paymentCodeProperty.get();
        WalletTransaction walletTransaction = walletTransactionProperty.get();
        WalletNode input0Node = walletTransaction.getSelectedUtxos().entrySet().iterator().next().getValue();
        Keystore keystore = input0Node.getWallet().isNested() ? decryptedWallet.getChildWallet(input0Node.getWallet().getName()).getKeystores().get(0) : decryptedWallet.getKeystores().get(0);
        ECKey input0Key = keystore.getKey(input0Node);
        TransactionOutPoint input0Outpoint = walletTransaction.getTransaction().getInputs().iterator().next().getOutpoint();
        SecretPoint secretPoint = new SecretPoint(input0Key.getPrivKeyBytes(), externalPaymentCode.getNotificationKey().getPubKey());
        byte[] blindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), input0Outpoint.bitcoinSerialize());
        byte[] blindedPaymentCode = PaymentCode.blind(paymentCode.getPayload(), blindingMask);
        List<UtxoSelector> utxoSelectors = List.of(new PresetUtxoSelector(walletTransaction.getSelectedUtxos().keySet(), true));
        Long userFee = userFeeSet.get() ? getFeeValueSats() : null;
        double feeRate = getUserFeeRate();
        Integer currentBlockHeight = AppServices.getCurrentBlockHeight();
        boolean groupByAddress = Config.get().isGroupByAddress();
        boolean includeMempoolOutputs = Config.get().isIncludeMempoolOutputs();
        boolean includeSpentMempoolOutputs = includeSpentMempoolOutputsProperty.get();
        WalletTransaction finalWalletTx = decryptedWallet.createWalletTransaction(utxoSelectors, getUtxoFilters(), walletTransaction.getPayments(), List.of(blindedPaymentCode), excludedChangeNodes, feeRate, getMinimumFeeRate(), userFee, currentBlockHeight, groupByAddress, includeMempoolOutputs, includeSpentMempoolOutputs);
        PSBT psbt = finalWalletTx.createPSBT();
        decryptedWallet.sign(psbt);
        decryptedWallet.finalise(psbt);
        Transaction transaction = psbt.extractTransaction();
        ServiceProgressDialog.ProxyWorker proxyWorker = new ServiceProgressDialog.ProxyWorker();
        ElectrumServer.BroadcastTransactionService broadcastTransactionService = new ElectrumServer.BroadcastTransactionService(transaction);
        broadcastTransactionService.setOnSucceeded(successEvent -> {
            ElectrumServer.TransactionMempoolService transactionMempoolService = new ElectrumServer.TransactionMempoolService(walletTransaction.getWallet(), transaction.getTxId(), new HashSet<>(walletTransaction.getSelectedUtxos().values()));
            transactionMempoolService.setDelay(Duration.seconds(2));
            transactionMempoolService.setPeriod(Duration.seconds(5));
            transactionMempoolService.setRestartOnFailure(false);
            transactionMempoolService.setOnSucceeded(mempoolWorkerStateEvent -> {
                Set<String> scriptHashes = transactionMempoolService.getValue();
                if (!scriptHashes.isEmpty()) {
                    transactionMempoolService.cancel();
                    clear(null);
                    if (Config.get().isUsePayNym()) {
                        proxyWorker.setMessage("Finding PayNym...");
                        AppServices.getPayNymService().getPayNym(externalPaymentCode.toString()).subscribe(payNym -> {
                            proxyWorker.end();
                            addChildWallets(walletTransaction.getWallet(), externalPaymentCode, transaction, payNym);
                        }, error -> {
                            proxyWorker.end();
                            addChildWallets(walletTransaction.getWallet(), externalPaymentCode, transaction, null);
                        });
                    } else {
                        proxyWorker.end();
                        addChildWallets(walletTransaction.getWallet(), externalPaymentCode, transaction, null);
                    }
                }
                if (transactionMempoolService.getIterationCount() > 5 && transactionMempoolService.isRunning()) {
                    transactionMempoolService.cancel();
                    proxyWorker.end();
                    log.error("Timeout searching for broadcasted notification transaction");
                    AppServices.showErrorDialog("Timeout searching for broadcasted transaction", "The transaction was broadcast but the server did not register it in the mempool. It is safe to try broadcasting again.");
                }
            });
            transactionMempoolService.setOnFailed(mempoolWorkerStateEvent -> {
                transactionMempoolService.cancel();
                proxyWorker.end();
                log.error("Error searching for broadcasted notification transaction", mempoolWorkerStateEvent.getSource().getException());
                AppServices.showErrorDialog("Timeout searching for broadcasted transaction", "The transaction was broadcast but the server did not register it in the mempool. It is safe to try broadcasting again.");
            });
            proxyWorker.setMessage("Receiving notification transaction...");
            transactionMempoolService.start();
        });
        broadcastTransactionService.setOnFailed(failedEvent -> {
            proxyWorker.end();
            log.error("Error broadcasting notification transaction", failedEvent.getSource().getException());
            AppServices.showErrorDialog("Error broadcasting notification transaction", failedEvent.getSource().getException().getMessage());
        });
        ServiceProgressDialog progressDialog = new ServiceProgressDialog("Broadcast", "Broadcast Notification Transaction", "/image/paynym.png", proxyWorker);
        AppServices.moveToActiveWindowScreen(progressDialog);
        proxyWorker.setMessage("Broadcasting notification transaction...");
        proxyWorker.start();
        broadcastTransactionService.start();
    } catch (Exception e) {
        log.error("Error creating notification transaction", e);
        AppServices.showErrorDialog("Error creating notification transaction", e.getMessage());
    }
}
Also used : ECKey(com.sparrowwallet.drongo.crypto.ECKey) SecureString(com.sparrowwallet.drongo.SecureString) SecretPoint(com.sparrowwallet.drongo.bip47.SecretPoint) PaymentCode(com.sparrowwallet.drongo.bip47.PaymentCode) InvalidAddressException(com.sparrowwallet.drongo.address.InvalidAddressException) IOException(java.io.IOException) PSBT(com.sparrowwallet.drongo.psbt.PSBT) Transaction(com.sparrowwallet.drongo.protocol.Transaction) TransactionOutPoint(com.sparrowwallet.drongo.protocol.TransactionOutPoint)

Aggregations

SecureString (com.sparrowwallet.drongo.SecureString)1 InvalidAddressException (com.sparrowwallet.drongo.address.InvalidAddressException)1 PaymentCode (com.sparrowwallet.drongo.bip47.PaymentCode)1 SecretPoint (com.sparrowwallet.drongo.bip47.SecretPoint)1 ECKey (com.sparrowwallet.drongo.crypto.ECKey)1 Transaction (com.sparrowwallet.drongo.protocol.Transaction)1 TransactionOutPoint (com.sparrowwallet.drongo.protocol.TransactionOutPoint)1 PSBT (com.sparrowwallet.drongo.psbt.PSBT)1 IOException (java.io.IOException)1