mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2026-08-10 16:43:14 +00:00
570 lines
23 KiB
Java
570 lines
23 KiB
Java
package com.sparrowwallet.sparrow.transaction;
|
|
|
|
import com.google.common.eventbus.Subscribe;
|
|
import com.sparrowwallet.drongo.KeyDerivation;
|
|
import com.sparrowwallet.drongo.address.Address;
|
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
|
import com.sparrowwallet.drongo.protocol.*;
|
|
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
|
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
|
import com.sparrowwallet.sparrow.EventManager;
|
|
import com.sparrowwallet.sparrow.control.*;
|
|
import com.sparrowwallet.sparrow.event.*;
|
|
import javafx.collections.MapChangeListener;
|
|
import javafx.fxml.FXML;
|
|
import javafx.fxml.Initializable;
|
|
import javafx.scene.control.*;
|
|
import org.controlsfx.control.ToggleSwitch;
|
|
import org.fxmisc.flowless.VirtualizedScrollPane;
|
|
import org.fxmisc.richtext.CodeArea;
|
|
import tornadofx.control.Field;
|
|
import tornadofx.control.Fieldset;
|
|
|
|
import java.net.URL;
|
|
import java.time.Duration;
|
|
import java.time.Instant;
|
|
import java.time.LocalDateTime;
|
|
import java.time.ZoneId;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.Map;
|
|
import java.util.ResourceBundle;
|
|
|
|
public class InputController extends TransactionFormController implements Initializable {
|
|
private InputForm inputForm;
|
|
|
|
@FXML
|
|
private Fieldset inputFieldset;
|
|
|
|
@FXML
|
|
private IdLabel outpoint;
|
|
|
|
@FXML
|
|
private Hyperlink linkedOutpoint;
|
|
|
|
@FXML
|
|
private CoinLabel spends;
|
|
|
|
@FXML
|
|
private CopyableLabel from;
|
|
|
|
@FXML
|
|
private AddressLabel address;
|
|
|
|
@FXML
|
|
private ScriptArea scriptSigArea;
|
|
|
|
@FXML
|
|
private VirtualizedScrollPane<CodeArea> redeemScriptScroll;
|
|
|
|
@FXML
|
|
private ScriptArea redeemScriptArea;
|
|
|
|
@FXML
|
|
private VirtualizedScrollPane<CodeArea> witnessScriptScroll;
|
|
|
|
@FXML
|
|
private ScriptArea witnessScriptArea;
|
|
|
|
@FXML
|
|
private VirtualizedScrollPane<CodeArea> witnessesScroll;
|
|
|
|
@FXML
|
|
private ScriptArea witnessesArea;
|
|
|
|
@FXML
|
|
private CopyableLabel signatures;
|
|
|
|
@FXML
|
|
private ToggleSwitch rbf;
|
|
|
|
@FXML
|
|
private ToggleGroup locktimeToggleGroup;
|
|
|
|
@FXML
|
|
private ToggleButton locktimeNoneType;
|
|
|
|
@FXML
|
|
private ToggleButton locktimeAbsoluteType;
|
|
|
|
@FXML
|
|
private ToggleButton locktimeRelativeType;
|
|
|
|
@FXML
|
|
private Fieldset locktimeFieldset;
|
|
|
|
@FXML
|
|
private Field locktimeAbsoluteField;
|
|
|
|
@FXML
|
|
private Field locktimeRelativeField;
|
|
|
|
@FXML
|
|
private CopyableLabel locktimeAbsolute;
|
|
|
|
@FXML
|
|
private Spinner<Integer> locktimeRelativeBlocks;
|
|
|
|
@FXML
|
|
private RelativeTimelockSpinner locktimeRelativeSeconds;
|
|
|
|
@FXML
|
|
private ComboBox<String> locktimeRelativeCombo;
|
|
|
|
@Override
|
|
public void initialize(URL location, ResourceBundle resources) {
|
|
EventManager.get().register(this);
|
|
}
|
|
|
|
public void initializeView() {
|
|
TransactionInput txInput = inputForm.getTransactionInput();
|
|
PSBTInput psbtInput = inputForm.getPsbtInput();
|
|
|
|
inputForm.signingWalletProperty().addListener((observable, oldValue, signingWallet) -> {
|
|
updateInputLegendFromWallet(txInput, signingWallet);
|
|
});
|
|
updateInputLegendFromWallet(txInput, inputForm.getSigningWallet());
|
|
|
|
initializeInputFields(txInput, psbtInput);
|
|
initializeScriptFields(txInput, psbtInput);
|
|
initializeStatusFields(txInput, psbtInput);
|
|
initializeLocktimeFields(txInput);
|
|
|
|
if(psbtInput != null) {
|
|
inputForm.getSignatureKeystoreMap().addListener((MapChangeListener<TransactionSignature, Keystore>) c -> {
|
|
updateSignatures(inputForm.getPsbtInput());
|
|
});
|
|
}
|
|
}
|
|
|
|
private String getLegendText(TransactionInput txInput) {
|
|
return "Input #" + txInput.getIndex();
|
|
}
|
|
|
|
private void updateInputLegendFromWallet(TransactionInput txInput, Wallet signingWallet) {
|
|
String baseText = getLegendText(txInput);
|
|
if(signingWallet != null) {
|
|
if(inputForm.isWalletTxo()) {
|
|
inputFieldset.setText(baseText + " - Wallet");
|
|
inputFieldset.setIcon(TransactionDiagram.getTxoGlyph());
|
|
} else {
|
|
inputFieldset.setText(baseText + " - Payjoin");
|
|
inputFieldset.setIcon(TransactionDiagram.getPayjoinGlyph());
|
|
}
|
|
} else {
|
|
inputFieldset.setText(baseText);
|
|
inputFieldset.setIcon(null);
|
|
}
|
|
}
|
|
|
|
private void initializeInputFields(TransactionInput txInput, PSBTInput psbtInput) {
|
|
outpoint.managedProperty().bind(outpoint.visibleProperty());
|
|
linkedOutpoint.managedProperty().bind(linkedOutpoint.visibleProperty());
|
|
|
|
if(txInput.isCoinBase()) {
|
|
outpoint.setText("Coinbase");
|
|
long totalAmt = 0;
|
|
for(TransactionOutput output : inputForm.getTransaction().getOutputs()) {
|
|
totalAmt += output.getValue();
|
|
}
|
|
spends.setValue(totalAmt);
|
|
} else if(inputForm.getInputTransactions() != null) {
|
|
updateOutpoint(inputForm.getInputTransactions());
|
|
} else {
|
|
outpoint.setVisible(true);
|
|
linkedOutpoint.setVisible(false);
|
|
outpoint.setText(txInput.getOutpoint().getHash().toString() + ":" + txInput.getOutpoint().getIndex());
|
|
}
|
|
|
|
from.setVisible(false);
|
|
if(psbtInput != null) {
|
|
TransactionOutput output = psbtInput.getUtxo();
|
|
updateSpends(output);
|
|
} else if(inputForm.getInputTransactions() != null) {
|
|
updateSpends(inputForm.getInputTransactions());
|
|
}
|
|
}
|
|
|
|
private void updateOutpoint(Map<Sha256Hash, BlockTransaction> inputTransactions) {
|
|
outpoint.setVisible(false);
|
|
linkedOutpoint.setVisible(true);
|
|
|
|
TransactionInput txInput = inputForm.getTransactionInput();
|
|
linkedOutpoint.setText(txInput.getOutpoint().getHash().toString() + ":" + txInput.getOutpoint().getIndex());
|
|
linkedOutpoint.setOnAction(event -> {
|
|
BlockTransaction linkedTransaction = inputTransactions.get(txInput.getOutpoint().getHash());
|
|
EventManager.get().post(new ViewTransactionEvent(linkedTransaction, TransactionView.OUTPUT, (int)txInput.getOutpoint().getIndex()));
|
|
});
|
|
linkedOutpoint.setContextMenu(new TransactionReferenceContextMenu(linkedOutpoint.getText()));
|
|
}
|
|
|
|
private void updateSpends(Map<Sha256Hash, BlockTransaction> inputTransactions) {
|
|
TransactionInput txInput = inputForm.getTransactionInput();
|
|
if(!txInput.isCoinBase()) {
|
|
BlockTransaction blockTransaction = inputTransactions.get(txInput.getOutpoint().getHash());
|
|
if(blockTransaction == null) {
|
|
if(inputForm.getIndex() < inputForm.getMaxInputFetched()) {
|
|
throw new IllegalStateException("Could not retrieve block transaction for input #" + inputForm.getIndex());
|
|
} else {
|
|
//Still paging
|
|
return;
|
|
}
|
|
}
|
|
|
|
TransactionOutput output = blockTransaction.getTransaction().getOutputs().get((int)txInput.getOutpoint().getIndex());
|
|
updateSpends(output);
|
|
}
|
|
}
|
|
|
|
private void updateSpends(TransactionOutput output) {
|
|
if (output != null) {
|
|
spends.setValue(output.getValue());
|
|
try {
|
|
Address[] addresses = output.getScript().getToAddresses();
|
|
from.setVisible(true);
|
|
if (addresses.length == 1) {
|
|
address.setAddress(addresses[0]);
|
|
} else {
|
|
address.setText("multiple addresses");
|
|
}
|
|
} catch (NonStandardScriptException e) {
|
|
//ignore
|
|
}
|
|
}
|
|
}
|
|
|
|
private void initializeScriptFields(TransactionInput txInput, PSBTInput psbtInput) {
|
|
initializeScriptField(scriptSigArea);
|
|
initializeScriptField(redeemScriptArea);
|
|
initializeScriptField(witnessesArea);
|
|
initializeScriptField(witnessScriptArea);
|
|
|
|
updateScriptFields(txInput, psbtInput);
|
|
}
|
|
|
|
private void updateScriptFields(TransactionInput txInput, PSBTInput psbtInput) {
|
|
//Don't use PSBT data if txInput has scriptSig or witness data. This happens when a tx has been extracted from a PSBT
|
|
if(txInput.getScriptBytes().length > 0 || txInput.hasWitness()) {
|
|
psbtInput = null;
|
|
}
|
|
|
|
scriptSigArea.clear();
|
|
redeemScriptArea.clear();
|
|
witnessesArea.clear();
|
|
witnessScriptArea.clear();
|
|
|
|
//TODO: While we immediately check if the referenced transaction output is P2SH, where this is not present getting the first nested script is not safe
|
|
Script redeemScript = txInput.getScriptSig().getFirstNestedScript();
|
|
if(redeemScript != null && inputForm.getReferencedTransactionOutput() != null) {
|
|
Script lockingScript = inputForm.getReferencedTransactionOutput().getScript();
|
|
if(!ScriptType.P2SH.isScriptType(lockingScript)) {
|
|
redeemScript = null;
|
|
}
|
|
}
|
|
|
|
if(redeemScript == null && psbtInput != null && psbtInput.getRedeemScript() != null) {
|
|
redeemScriptArea.addPSBTDecoration("PSBT Redeem Script", "non-final");
|
|
redeemScript = psbtInput.getRedeemScript();
|
|
}
|
|
if(redeemScript == null && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
|
|
redeemScriptArea.addPSBTDecoration("PSBT Final ScriptSig", "final");
|
|
redeemScript = psbtInput.getFinalScriptSig().getFirstNestedScript();
|
|
}
|
|
|
|
if(txInput.getScriptSig().isEmpty() && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
|
|
scriptSigArea.appendScript(psbtInput.getFinalScriptSig(), redeemScript, null);
|
|
scriptSigArea.addPSBTDecoration("PSBT Final ScriptSig", "final");
|
|
} else {
|
|
scriptSigArea.appendScript(txInput.getScriptSig(), redeemScript, null);
|
|
}
|
|
|
|
if(redeemScript != null) {
|
|
redeemScriptArea.setDisable(false);
|
|
redeemScriptArea.appendScript(redeemScript);
|
|
} else {
|
|
redeemScriptScroll.setDisable(true);
|
|
}
|
|
|
|
Script witnesses = null;
|
|
Script witnessScript = null;
|
|
|
|
if(txInput.hasWitness()) {
|
|
witnesses = new Script(txInput.getWitness().asScriptChunks());
|
|
witnessScript = txInput.getWitness().getWitnessScript();
|
|
} else if(psbtInput != null) {
|
|
if(psbtInput.getFinalScriptWitness() != null) {
|
|
witnesses = new Script(psbtInput.getFinalScriptWitness().asScriptChunks());
|
|
witnessScript = psbtInput.getFinalScriptWitness().getWitnessScript();
|
|
witnessesArea.addPSBTDecoration("PSBT Final ScriptWitness", "final");
|
|
witnessScriptArea.addPSBTDecoration("PSBT Final ScriptWitness", "final");
|
|
} else if(psbtInput.getWitnessScript() != null) {
|
|
witnessScript = psbtInput.getWitnessScript();
|
|
witnessScriptArea.addPSBTDecoration("PSBT Witness Script", "non-final");
|
|
}
|
|
}
|
|
|
|
if(witnesses != null) {
|
|
witnessesScroll.setDisable(false);
|
|
witnessesArea.appendScript(witnesses, null, witnessScript);
|
|
} else {
|
|
witnessesScroll.setDisable(true);
|
|
}
|
|
|
|
if(witnessScript != null) {
|
|
witnessScriptScroll.setDisable(false);
|
|
witnessScriptArea.appendScript(witnessScript);
|
|
} else {
|
|
witnessScriptScroll.setDisable(true);
|
|
}
|
|
}
|
|
|
|
private void initializeStatusFields(TransactionInput txInput, PSBTInput psbtInput) {
|
|
updateSignatures(psbtInput);
|
|
|
|
Transaction transaction = inputForm.getTransaction();
|
|
rbf.setSelected(txInput.isReplaceByFeeEnabled());
|
|
rbf.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
|
if(newValue) {
|
|
if(txInput.isAbsoluteTimeLockDisabled()) {
|
|
locktimeToggleGroup.selectToggle(locktimeAbsoluteType);
|
|
} else if(txInput.isAbsoluteTimeLocked()) {
|
|
txInput.setSequenceNumber(TransactionInput.SEQUENCE_RBF_ENABLED);
|
|
if(oldValue != null) {
|
|
EventManager.get().post(new TransactionChangedEvent(transaction));
|
|
}
|
|
}
|
|
} else {
|
|
if(txInput.isAbsoluteTimeLocked()) {
|
|
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED - 1);
|
|
if(oldValue != null) {
|
|
EventManager.get().post(new TransactionChangedEvent(transaction));
|
|
}
|
|
} else if(txInput.isRelativeTimeLocked()) {
|
|
locktimeToggleGroup.selectToggle(locktimeAbsoluteType);
|
|
}
|
|
}
|
|
});
|
|
rbf.setDisable(!inputForm.isEditable());
|
|
}
|
|
|
|
private void updateSignatures(PSBTInput psbtInput) {
|
|
signatures.setText("Unknown");
|
|
if(inputForm.getPsbtInput() != null) {
|
|
int reqSigs = -1;
|
|
if(psbtInput.getUtxo() != null && psbtInput.getSigningScript() != null) {
|
|
try {
|
|
reqSigs = psbtInput.getSigningScript().getNumRequiredSignatures();
|
|
} catch (NonStandardScriptException e) {
|
|
//TODO: Handle unusual transaction sig
|
|
}
|
|
}
|
|
|
|
int foundSigs = psbtInput.getSignatures().size();
|
|
signatures.setText(foundSigs + "/" + (reqSigs < 0 ? "?" : reqSigs));
|
|
}
|
|
}
|
|
|
|
private void initializeLocktimeFields(TransactionInput txInput) {
|
|
Transaction transaction = inputForm.getTransaction();
|
|
locktimeToggleGroup.selectedToggleProperty().addListener((ov, old_toggle, new_toggle) -> {
|
|
if(locktimeToggleGroup.getSelectedToggle() != null) {
|
|
String selection = locktimeToggleGroup.getSelectedToggle().getUserData().toString();
|
|
if(selection.equals("none")) {
|
|
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField);
|
|
locktimeFieldset.getChildren().add(locktimeAbsoluteField);
|
|
updateAbsoluteLocktimeField(transaction);
|
|
locktimeAbsoluteField.setDisable(true);
|
|
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED);
|
|
rbf.setSelected(false);
|
|
if(old_toggle != null) {
|
|
EventManager.get().post(new TransactionChangedEvent(transaction));
|
|
}
|
|
} else if(selection.equals("absolute")) {
|
|
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField);
|
|
locktimeFieldset.getChildren().add(locktimeAbsoluteField);
|
|
updateAbsoluteLocktimeField(transaction);
|
|
locktimeAbsoluteField.setDisable(false);
|
|
if(rbf.selectedProperty().getValue()) {
|
|
txInput.setSequenceNumber(TransactionInput.SEQUENCE_RBF_ENABLED);
|
|
} else {
|
|
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED - 1);
|
|
}
|
|
if(old_toggle != null) {
|
|
EventManager.get().post(new TransactionChangedEvent(transaction));
|
|
}
|
|
} else {
|
|
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField);
|
|
locktimeFieldset.getChildren().add(locktimeRelativeField);
|
|
if(locktimeRelativeCombo.getValue() == null) {
|
|
locktimeRelativeCombo.getSelectionModel().select(0);
|
|
} else {
|
|
setRelativeLocktime(txInput, transaction, old_toggle != null);
|
|
}
|
|
rbf.setSelected(true);
|
|
}
|
|
}
|
|
});
|
|
|
|
locktimeRelativeBlocks.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)TransactionInput.RELATIVE_TIMELOCK_VALUE_MASK, 0));
|
|
locktimeRelativeBlocks.managedProperty().bind(locktimeRelativeBlocks.visibleProperty());
|
|
locktimeRelativeSeconds.managedProperty().bind(locktimeRelativeSeconds.visibleProperty());
|
|
locktimeRelativeCombo.getSelectionModel().selectedItemProperty().addListener((ov, old_toggle, new_toggle) -> {
|
|
boolean blocks = locktimeRelativeCombo.getValue().equals("blocks");
|
|
locktimeRelativeSeconds.setVisible(!blocks);
|
|
locktimeRelativeBlocks.setVisible(blocks);
|
|
setRelativeLocktime(txInput, transaction, old_toggle != null);
|
|
});
|
|
|
|
locktimeRelativeType.setDisable(!transaction.isRelativeLocktimeAllowed());
|
|
if(txInput.isAbsoluteTimeLockDisabled()) {
|
|
locktimeToggleGroup.selectToggle(locktimeNoneType);
|
|
} else if(txInput.isAbsoluteTimeLocked()) {
|
|
locktimeToggleGroup.selectToggle(locktimeAbsoluteType);
|
|
} else {
|
|
if(txInput.isRelativeTimeLockedInBlocks()) {
|
|
locktimeRelativeBlocks.valueFactoryProperty().get().setValue((int)txInput.getRelativeLocktime());
|
|
locktimeRelativeCombo.getSelectionModel().select(0);
|
|
} else {
|
|
locktimeRelativeSeconds.valueFactoryProperty().get().setValue(Duration.ofSeconds(txInput.getRelativeLocktime() * TransactionInput.RELATIVE_TIMELOCK_SECONDS_INCREMENT));
|
|
locktimeRelativeCombo.getSelectionModel().select(1);
|
|
}
|
|
locktimeToggleGroup.selectToggle(locktimeRelativeType);
|
|
}
|
|
|
|
locktimeRelativeBlocks.valueProperty().addListener((obs, oldValue, newValue) -> {
|
|
setRelativeLocktime(txInput, transaction, oldValue != null);
|
|
});
|
|
locktimeRelativeSeconds.valueProperty().addListener((obs, oldValue, newValue) -> {
|
|
setRelativeLocktime(txInput, transaction, oldValue != null);
|
|
});
|
|
|
|
locktimeNoneType.setDisable(!inputForm.isEditable());
|
|
locktimeAbsoluteType.setDisable(!inputForm.isEditable());
|
|
locktimeRelativeType.setDisable(!inputForm.isEditable());
|
|
locktimeRelativeBlocks.setDisable(!inputForm.isEditable());
|
|
locktimeRelativeSeconds.setDisable(!inputForm.isEditable());
|
|
locktimeRelativeCombo.setDisable(!inputForm.isEditable());
|
|
}
|
|
|
|
private void updateAbsoluteLocktimeField(Transaction transaction) {
|
|
long locktime = transaction.getLocktime();
|
|
if(locktime < Transaction.MAX_BLOCK_LOCKTIME) {
|
|
locktimeAbsoluteField.setText("Block:");
|
|
locktimeAbsolute.setText(Long.toString(locktime));
|
|
} else {
|
|
locktimeAbsoluteField.setText("Date:");
|
|
LocalDateTime localDateTime = Instant.ofEpochSecond(locktime).atZone(ZoneId.systemDefault()).toLocalDateTime();
|
|
locktimeAbsolute.setText(DateTimeFormatter.ofPattern(HeadersController.LOCKTIME_DATE_FORMAT).format(localDateTime));
|
|
}
|
|
}
|
|
|
|
private void setRelativeLocktime(TransactionInput txInput, Transaction transaction, boolean changed) {
|
|
String relativeSelection = locktimeRelativeCombo.getValue();
|
|
if(relativeSelection.equals("blocks")) {
|
|
Integer value = locktimeRelativeBlocks.getValue();
|
|
txInput.setSequenceNumber(value & TransactionInput.RELATIVE_TIMELOCK_VALUE_MASK);
|
|
} else {
|
|
long value = locktimeRelativeSeconds.getValue().toSeconds() / TransactionInput.RELATIVE_TIMELOCK_SECONDS_INCREMENT;
|
|
txInput.setSequenceNumber((value & TransactionInput.RELATIVE_TIMELOCK_VALUE_MASK) | TransactionInput.RELATIVE_TIMELOCK_TYPE_FLAG);
|
|
}
|
|
if(changed) {
|
|
EventManager.get().post(new TransactionChangedEvent(transaction));
|
|
}
|
|
}
|
|
|
|
public void setModel(InputForm form) {
|
|
this.inputForm = form;
|
|
initializeView();
|
|
}
|
|
|
|
@Override
|
|
protected TransactionForm getTransactionForm() {
|
|
return inputForm;
|
|
}
|
|
|
|
@Override
|
|
protected String describeScriptChunk(ScriptChunk chunk) {
|
|
String chunkString = super.describeScriptChunk(chunk);
|
|
|
|
ECKey pubKey = null;
|
|
if(chunk.isSignature()) {
|
|
if(inputForm.getPsbtInput() != null) {
|
|
TransactionSignature signature = chunk.getSignature();
|
|
pubKey = inputForm.getPsbtInput().getKeyForSignature(signature);
|
|
}
|
|
} else if(chunk.isPubKey()) {
|
|
pubKey = chunk.getPubKey();
|
|
}
|
|
|
|
if(inputForm.getPsbtInput() != null) {
|
|
KeyDerivation derivation = inputForm.getPsbtInput().getKeyDerivation(pubKey);
|
|
if(derivation != null) {
|
|
return "[" + derivation.toString() + "] " + chunkString;
|
|
}
|
|
}
|
|
|
|
return chunkString;
|
|
}
|
|
|
|
@Subscribe
|
|
public void blockTransactionFetched(BlockTransactionFetchedEvent event) {
|
|
if(event.getTxId().equals(inputForm.getTransaction().getTxId()) && inputForm.getIndex() >= event.getPageStart() && inputForm.getIndex() < event.getPageEnd()) {
|
|
updateOutpoint(event.getInputTransactions());
|
|
if(inputForm.getPsbt() == null) {
|
|
updateSpends(event.getInputTransactions());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void transactionLocktimeChanged(TransactionLocktimeChangedEvent event) {
|
|
if(event.getTransaction().equals(inputForm.getTransaction())) {
|
|
locktimeAbsolute.setText(Long.toString(event.getTransaction().getLocktime()));
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void bitcoinUnitChanged(BitcoinUnitChangedEvent event) {
|
|
spends.refresh(event.getBitcoinUnit());
|
|
}
|
|
|
|
@Subscribe
|
|
public void finalizeTransaction(FinalizeTransactionEvent event) {
|
|
if(inputForm.getPsbt() == event.getPsbt()) {
|
|
rbf.setDisable(true);
|
|
locktimeNoneType.setDisable(true);
|
|
locktimeAbsoluteType.setDisable(true);
|
|
locktimeRelativeType.setDisable(true);
|
|
locktimeRelativeBlocks.setDisable(true);
|
|
locktimeRelativeSeconds.setDisable(true);
|
|
locktimeRelativeCombo.setDisable(true);
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void psbtCombined(PSBTCombinedEvent event) {
|
|
if(event.getPsbt().equals(inputForm.getPsbt())) {
|
|
updateSpends(inputForm.getPsbtInput().getUtxo());
|
|
updateScriptFields(inputForm.getTransactionInput(), inputForm.getPsbtInput());
|
|
updateSignatures(inputForm.getPsbtInput());
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void psbtFinalized(PSBTFinalizedEvent event) {
|
|
if(event.getPsbt().equals(inputForm.getPsbt())) {
|
|
updateSpends(inputForm.getPsbtInput().getUtxo());
|
|
updateScriptFields(inputForm.getTransactionInput(), inputForm.getPsbtInput());
|
|
updateSignatures(inputForm.getPsbtInput());
|
|
}
|
|
}
|
|
|
|
@Subscribe
|
|
public void transactionExtracted(TransactionExtractedEvent event) {
|
|
if(event.getPsbt().equals(inputForm.getPsbt())) {
|
|
updateScriptFields(event.getFinalTransaction().getInputs().get(inputForm.getIndex()), null);
|
|
}
|
|
}
|
|
}
|