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;
}
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);
}
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);
}
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);
}
});
}
}
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());
}
}
Aggregations