Search in sources :

Example 1 with Transaction

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

the class SimpleElectrumServerRpc method getVerboseTransactions.

@Override
public Map<String, VerboseTransaction> getVerboseTransactions(Transport transport, Set<String> txids, String scriptHash) {
    JsonRpcClient client = new JsonRpcClient(transport);
    Map<String, VerboseTransaction> result = new LinkedHashMap<>();
    for (String txid : txids) {
        try {
            // The server may return an error if the transaction has not yet been broadcasted - this is a valid state so only try once
            VerboseTransaction verboseTransaction = new RetryLogic<VerboseTransaction>(1, RETRY_DELAY, IllegalStateException.class).getResult(() -> client.createRequest().returnAs(VerboseTransaction.class).method("blockchain.transaction.get").id(idCounter.incrementAndGet()).params(txid, true).execute());
            result.put(txid, verboseTransaction);
        } catch (Exception e) {
            // electrs-esplora does not currently support the verbose parameter, so try to fetch an incomplete VerboseTransaction without it
            // Note that without the script hash associated with the transaction, we can't get a block height as there is no way in the Electrum RPC protocol to do this
            // We mark this VerboseTransaction as incomplete by assigning it a Sha256Hash.ZERO_HASH blockhash
            log.debug("Error retrieving transaction: " + txid + " (" + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()) + ")");
            try {
                String rawTxHex = client.createRequest().returnAs(String.class).method("blockchain.transaction.get").id(idCounter.incrementAndGet()).params(txid).execute();
                Transaction tx = new Transaction(Utils.hexToBytes(rawTxHex));
                String id = tx.getTxId().toString();
                int height = 0;
                if (scriptHash != null) {
                    ScriptHashTx[] scriptHashTxes = client.createRequest().returnAs(ScriptHashTx[].class).method("blockchain.scripthash.get_history").id(idCounter.incrementAndGet()).params(scriptHash).execute();
                    for (ScriptHashTx scriptHashTx : scriptHashTxes) {
                        if (scriptHashTx.tx_hash.equals(id)) {
                            height = scriptHashTx.height;
                            break;
                        }
                    }
                }
                VerboseTransaction verboseTransaction = new VerboseTransaction();
                verboseTransaction.txid = id;
                verboseTransaction.hex = rawTxHex;
                verboseTransaction.confirmations = (height <= 0 ? 0 : AppServices.getCurrentBlockHeight() - height + 1);
                verboseTransaction.blockhash = Sha256Hash.ZERO_HASH.toString();
                result.put(txid, verboseTransaction);
            } catch (Exception ex) {
            // ignore
            }
        }
    }
    return result;
}
Also used : Transaction(com.sparrowwallet.drongo.protocol.Transaction) JsonRpcClient(com.github.arteam.simplejsonrpc.client.JsonRpcClient) JsonRpcException(com.github.arteam.simplejsonrpc.client.exception.JsonRpcException)

Example 2 with Transaction

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

the class Payjoin method getSingleInputFee.

private long getSingleInputFee() {
    Transaction transaction = psbt.extractTransaction();
    double feeRate = psbt.getFee().doubleValue() / transaction.getVirtualSize();
    int vSize = 68;
    if (transaction.getInputs().size() > 0) {
        TransactionInput input = transaction.getInputs().get(0);
        vSize = input.getLength() * Transaction.WITNESS_SCALE_FACTOR;
        vSize += input.getWitness() != null ? input.getWitness().getLength() : 0;
        vSize = (int) Math.ceil((double) vSize / Transaction.WITNESS_SCALE_FACTOR);
    }
    return (long) (vSize * feeRate);
}
Also used : Transaction(com.sparrowwallet.drongo.protocol.Transaction) TransactionInput(com.sparrowwallet.drongo.protocol.TransactionInput)

Example 3 with Transaction

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

the class PaymentController method initializeView.

@Override
public void initializeView() {
    updateOpenWallets();
    openWallets.prefWidthProperty().bind(address.widthProperty());
    openWallets.valueProperty().addListener((observable, oldValue, newValue) -> {
        if (newValue == payNymWallet) {
            boolean selectLinkedOnly = sendController.getPaymentTabs().getTabs().size() > 1 || !SorobanServices.canWalletMix(sendController.getWalletForm().getWallet());
            PayNymDialog payNymDialog = new PayNymDialog(sendController.getWalletForm().getWalletId(), true, selectLinkedOnly);
            Optional<PayNym> optPayNym = payNymDialog.showAndWait();
            optPayNym.ifPresent(this::setPayNym);
        } else if (newValue != null) {
            WalletNode freshNode = newValue.getFreshNode(KeyPurpose.RECEIVE);
            Address freshAddress = freshNode.getAddress();
            address.setText(freshAddress.toString());
            label.requestFocus();
        }
    });
    openWallets.setCellFactory(c -> new ListCell<>() {

        @Override
        protected void updateItem(Wallet wallet, boolean empty) {
            super.updateItem(wallet, empty);
            if (empty || wallet == null) {
                setText(null);
                setGraphic(null);
            } else {
                setText(wallet.getFullDisplayName() + (wallet == sendController.getWalletForm().getWallet() ? " (Consolidation)" : ""));
                setGraphic(wallet == payNymWallet ? getPayNymGlyph() : null);
            }
        }
    });
    payNymProperty.addListener((observable, oldValue, payNym) -> {
        updateMixOnlyStatus(payNym);
        revalidateAmount();
    });
    address.textProperty().addListener((observable, oldValue, newValue) -> {
        address.leftProperty().set(null);
        if (payNymProperty.get() != null && !newValue.equals(payNymProperty.get().nymName())) {
            payNymProperty.set(null);
        }
        try {
            BitcoinURI bitcoinURI = new BitcoinURI(newValue);
            Platform.runLater(() -> updateFromURI(bitcoinURI));
            return;
        } catch (Exception e) {
        // ignore, not a URI
        }
        if (sendController.getWalletForm().getWallet().hasPaymentCode()) {
            try {
                PaymentCode paymentCode = new PaymentCode(newValue);
                Wallet recipientBip47Wallet = sendController.getWalletForm().getWallet().getChildWallet(paymentCode, sendController.getWalletForm().getWallet().getScriptType());
                if (recipientBip47Wallet == null && sendController.getWalletForm().getWallet().getScriptType() != ScriptType.P2PKH) {
                    recipientBip47Wallet = sendController.getWalletForm().getWallet().getChildWallet(paymentCode, ScriptType.P2PKH);
                }
                if (recipientBip47Wallet != null) {
                    PayNym payNym = PayNym.fromWallet(recipientBip47Wallet);
                    Platform.runLater(() -> setPayNym(payNym));
                } else if (!paymentCode.equals(sendController.getWalletForm().getWallet().getPaymentCode())) {
                    ButtonType previewType = new ButtonType("Preview Transaction", ButtonBar.ButtonData.YES);
                    Optional<ButtonType> optButton = AppServices.showAlertDialog("Send notification transaction?", "This payment code is not yet linked with a notification transaction. Send a notification transaction?", Alert.AlertType.CONFIRMATION, ButtonType.CANCEL, previewType);
                    if (optButton.isPresent() && optButton.get() == previewType) {
                        Payment payment = new Payment(paymentCode.getNotificationAddress(), "Link " + paymentCode.toAbbreviatedString(), MINIMUM_P2PKH_OUTPUT_SATS, false);
                        Platform.runLater(() -> EventManager.get().post(new SpendUtxoEvent(sendController.getWalletForm().getWallet(), List.of(payment), List.of(new byte[80]), paymentCode)));
                    } else {
                        Platform.runLater(() -> address.setText(""));
                    }
                }
            } catch (Exception e) {
            // ignore, not a payment code
            }
        }
        revalidateAmount();
        maxButton.setDisable(!isMaxButtonEnabled());
        sendController.updateTransaction();
        if (validationSupport != null) {
            validationSupport.setErrorDecorationEnabled(true);
        }
    });
    label.textProperty().addListener((observable, oldValue, newValue) -> {
        maxButton.setDisable(!isMaxButtonEnabled());
        sendController.getCreateButton().setDisable(sendController.getWalletTransaction() == null || newValue == null || newValue.isEmpty() || sendController.isInsufficientFeeRate());
        sendController.updateTransaction();
    });
    amount.setTextFormatter(new CoinTextFormatter());
    amount.textProperty().addListener(amountListener);
    amountUnit.getSelectionModel().select(BitcoinUnit.BTC.equals(sendController.getBitcoinUnit(Config.get().getBitcoinUnit())) ? 0 : 1);
    amountUnit.valueProperty().addListener((observable, oldValue, newValue) -> {
        Long value = getRecipientValueSats(oldValue);
        if (value != null) {
            DecimalFormat df = new DecimalFormat("#.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
            df.setMaximumFractionDigits(8);
            amount.setText(df.format(newValue.getValue(value)));
        }
    });
    maxButton.setDisable(!isMaxButtonEnabled());
    sendController.utxoSelectorProperty().addListener((observable, oldValue, newValue) -> {
        maxButton.setDisable(!isMaxButtonEnabled());
    });
    sendController.getPaymentTabs().getTabs().addListener((ListChangeListener<Tab>) c -> {
        maxButton.setDisable(!isMaxButtonEnabled());
    });
    sendController.utxoLabelSelectionProperty().addListener((observable, oldValue, newValue) -> {
        maxButton.setText("Max" + newValue);
    });
    amountStatus.managedProperty().bind(amountStatus.visibleProperty());
    amountStatus.visibleProperty().bind(sendController.insufficientInputsProperty().and(dustAmountProperty.not()).and(emptyAmountProperty.not()));
    dustStatus.managedProperty().bind(dustStatus.visibleProperty());
    dustStatus.visibleProperty().bind(dustAmountProperty);
    Optional<Tab> firstTab = sendController.getPaymentTabs().getTabs().stream().findFirst();
    if (firstTab.isPresent()) {
        PaymentController controller = (PaymentController) firstTab.get().getUserData();
        String firstLabel = controller.label.getText();
        label.setText(firstLabel);
    }
    addValidation(validationSupport);
}
Also used : Initializable(javafx.fxml.Initializable) PayNym(com.sparrowwallet.sparrow.paynym.PayNym) com.sparrowwallet.drongo.wallet(com.sparrowwallet.drongo.wallet) javafx.scene.control(javafx.scene.control) URL(java.net.URL) DecimalFormatSymbols(java.text.DecimalFormatSymbols) LoggerFactory(org.slf4j.LoggerFactory) ValidationSupport(org.controlsfx.validation.ValidationSupport) Config(com.sparrowwallet.sparrow.io.Config) PayNymAddress(com.sparrowwallet.sparrow.paynym.PayNymAddress) ExchangeSource(com.sparrowwallet.sparrow.net.ExchangeSource) ListChangeListener(javafx.collections.ListChangeListener) CurrencyRate(com.sparrowwallet.sparrow.CurrencyRate) FontAwesome5(com.sparrowwallet.sparrow.glyphfont.FontAwesome5) InvalidPaymentCodeException(com.sparrowwallet.drongo.bip47.InvalidPaymentCodeException) Collectors(java.util.stream.Collectors) BitcoinURI(com.sparrowwallet.drongo.uri.BitcoinURI) Platform(javafx.application.Platform) FXML(javafx.fxml.FXML) BooleanProperty(javafx.beans.property.BooleanProperty) KeyPurpose(com.sparrowwallet.drongo.KeyPurpose) ScriptType(com.sparrowwallet.drongo.protocol.ScriptType) PaymentCode(com.sparrowwallet.drongo.bip47.PaymentCode) Address(com.sparrowwallet.drongo.address.Address) java.util(java.util) FXCollections(javafx.collections.FXCollections) InvalidAddressException(com.sparrowwallet.drongo.address.InvalidAddressException) AppServices.showErrorDialog(com.sparrowwallet.sparrow.AppServices.showErrorDialog) Glyph(org.controlsfx.glyphfont.Glyph) TransactionOutput(com.sparrowwallet.drongo.protocol.TransactionOutput) ValidationResult(org.controlsfx.validation.ValidationResult) Subscribe(com.google.common.eventbus.Subscribe) Transaction(com.sparrowwallet.drongo.protocol.Transaction) ObjectProperty(javafx.beans.property.ObjectProperty) Logger(org.slf4j.Logger) P2PKHAddress(com.sparrowwallet.drongo.address.P2PKHAddress) com.sparrowwallet.sparrow.event(com.sparrowwallet.sparrow.event) DecimalFormat(java.text.DecimalFormat) com.sparrowwallet.sparrow.soroban(com.sparrowwallet.sparrow.soroban) BitcoinUnit(com.sparrowwallet.drongo.BitcoinUnit) PayNymDialog(com.sparrowwallet.sparrow.paynym.PayNymDialog) ActionEvent(javafx.event.ActionEvent) AppServices(com.sparrowwallet.sparrow.AppServices) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) EventManager(com.sparrowwallet.sparrow.EventManager) ECKey(com.sparrowwallet.drongo.crypto.ECKey) ObservableValue(javafx.beans.value.ObservableValue) Validator(org.controlsfx.validation.Validator) ChangeListener(javafx.beans.value.ChangeListener) com.sparrowwallet.sparrow.control(com.sparrowwallet.sparrow.control) PaymentCode(com.sparrowwallet.drongo.bip47.PaymentCode) PayNymAddress(com.sparrowwallet.sparrow.paynym.PayNymAddress) Address(com.sparrowwallet.drongo.address.Address) P2PKHAddress(com.sparrowwallet.drongo.address.P2PKHAddress) DecimalFormat(java.text.DecimalFormat) PayNym(com.sparrowwallet.sparrow.paynym.PayNym) InvalidPaymentCodeException(com.sparrowwallet.drongo.bip47.InvalidPaymentCodeException) InvalidAddressException(com.sparrowwallet.drongo.address.InvalidAddressException) PayNymDialog(com.sparrowwallet.sparrow.paynym.PayNymDialog) BitcoinURI(com.sparrowwallet.drongo.uri.BitcoinURI)

Example 4 with Transaction

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

the class SendController method sorobanInitiated.

@Subscribe
public void sorobanInitiated(SorobanInitiatedEvent event) {
    if (event.getWallet().equals(getWalletForm().getWallet())) {
        if (!AppServices.onlineProperty().get()) {
            Optional<ButtonType> optButtonType = AppServices.showErrorDialog("Cannot Mix Offline", "Sparrow needs to be connected to a server to perform collaborative mixes. Try to connect?", ButtonType.CANCEL, ButtonType.OK);
            if (optButtonType.isPresent() && optButtonType.get() == ButtonType.OK) {
                AppServices.onlineProperty().set(true);
            }
            return;
        }
        Platform.runLater(() -> {
            InitiatorDialog initiatorDialog = new InitiatorDialog(getWalletForm().getWalletId(), getWalletForm().getWallet(), walletTransactionProperty.get());
            if (Config.get().isSameAppMixing()) {
                initiatorDialog.initModality(Modality.NONE);
            }
            Optional<Transaction> optTransaction = initiatorDialog.showAndWait();
            if (optTransaction.isPresent()) {
                clear(null);
            }
        });
    }
}
Also used : InitiatorDialog(com.sparrowwallet.sparrow.soroban.InitiatorDialog) Transaction(com.sparrowwallet.drongo.protocol.Transaction) Subscribe(com.google.common.eventbus.Subscribe)

Example 5 with Transaction

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

the class OutputsController method initialiseView.

private void initialiseView() {
    Transaction tx = outputsForm.getTransaction();
    count.setText(Integer.toString(tx.getOutputs().size()));
    long totalAmt = 0;
    for (TransactionOutput output : tx.getOutputs()) {
        totalAmt += output.getValue();
    }
    total.setValue(totalAmt);
    if (totalAmt > 0) {
        addPieData(outputsPie, tx.getOutputs());
    }
}
Also used : TransactionOutput(com.sparrowwallet.drongo.protocol.TransactionOutput) Transaction(com.sparrowwallet.drongo.protocol.Transaction)

Aggregations

Transaction (com.sparrowwallet.drongo.protocol.Transaction)11 TransactionOutput (com.sparrowwallet.drongo.protocol.TransactionOutput)4 TransactionInput (com.sparrowwallet.drongo.protocol.TransactionInput)3 Subscribe (com.google.common.eventbus.Subscribe)2 Cahoots (com.samourai.wallet.cahoots.Cahoots)2 KeyPurpose (com.sparrowwallet.drongo.KeyPurpose)2 Address (com.sparrowwallet.drongo.address.Address)2 InvalidAddressException (com.sparrowwallet.drongo.address.InvalidAddressException)2 PaymentCode (com.sparrowwallet.drongo.bip47.PaymentCode)2 ECKey (com.sparrowwallet.drongo.crypto.ECKey)2 Sha256Hash (com.sparrowwallet.drongo.protocol.Sha256Hash)2 PSBT (com.sparrowwallet.drongo.psbt.PSBT)2 PSBTParseException (com.sparrowwallet.drongo.psbt.PSBTParseException)2 com.sparrowwallet.drongo.wallet (com.sparrowwallet.drongo.wallet)2 ElectrumServer (com.sparrowwallet.sparrow.net.ElectrumServer)2 java.util (java.util)2 Collectors (java.util.stream.Collectors)2 JsonRpcClient (com.github.arteam.simplejsonrpc.client.JsonRpcClient)1 JsonRpcException (com.github.arteam.simplejsonrpc.client.exception.JsonRpcException)1 ImmutableMap (com.google.common.collect.ImmutableMap)1