diff --git a/drongo b/drongo index 0d566927..728b6ce5 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 0d56692784f5dfc50197533eb00ccf8e5c42e471 +Subproject commit 728b6ce5ef21233b5e1687d3fb4277b79eb2e4e1 diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index 8c686865..f78f4cfd 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -12,19 +12,18 @@ import com.sparrowwallet.drongo.protocol.ScriptType; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTParseException; -import com.sparrowwallet.drongo.wallet.Keystore; -import com.sparrowwallet.drongo.wallet.KeystoreSource; -import com.sparrowwallet.drongo.wallet.MnemonicException; -import com.sparrowwallet.drongo.wallet.Wallet; +import com.sparrowwallet.drongo.wallet.*; import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.event.*; import com.sparrowwallet.sparrow.io.*; import com.sparrowwallet.sparrow.preferences.PreferencesDialog; import com.sparrowwallet.sparrow.transaction.TransactionController; +import com.sparrowwallet.sparrow.wallet.HashIndexEntry; import com.sparrowwallet.sparrow.wallet.WalletController; import com.sparrowwallet.sparrow.wallet.WalletForm; import de.codecentric.centerdevice.MenuToolkit; import javafx.animation.*; +import javafx.application.Platform; import javafx.concurrent.Worker; import javafx.event.ActionEvent; import javafx.fxml.FXML; @@ -39,7 +38,6 @@ import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.util.Duration; import org.controlsfx.control.StatusBar; -import org.controlsfx.tools.Platform; import java.io.*; import java.net.URL; @@ -80,6 +78,8 @@ public class AppController implements Initializable { private ElectrumServer.ConnectionService connectionService; + public static Integer currentBlockHeight; + public static boolean showTxHexProperty; @Override @@ -190,7 +190,7 @@ public class AppController implements Initializable { } private void setOsxApplicationMenu() { - if(Platform.getCurrent().getPlatformId().toLowerCase().equals("mac")) { + if(org.controlsfx.tools.Platform.getCurrent().getPlatformId().toLowerCase().equals("mac")) { MenuToolkit tk = MenuToolkit.toolkit(); MenuItem preferences = new MenuItem("Preferences..."); preferences.setOnAction(this::openPreferences); @@ -289,6 +289,10 @@ public class AppController implements Initializable { } } + public static Integer getCurrentBlockHeight() { + return currentBlockHeight; + } + public static void showErrorDialog(String title, String content) { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle(title); @@ -519,13 +523,13 @@ public class AppController implements Initializable { private Tab addTransactionTab(String name, byte[] bytes) throws PSBTParseException, ParseException, TransactionParseException { if(PSBT.isPSBT(bytes)) { PSBT psbt = new PSBT(bytes); - return addTransactionTab(name, null, psbt); + return addTransactionTab(name, psbt); } if(Transaction.isTransaction(bytes)) { try { Transaction transaction = new Transaction(bytes); - return addTransactionTab(name, transaction, null); + return addTransactionTab(name, transaction); } catch(Exception e) { throw new TransactionParseException(e.getMessage()); } @@ -534,15 +538,34 @@ public class AppController implements Initializable { throw new ParseException("Not a valid PSBT or transaction", 0); } - private Tab addTransactionTab(String name, Transaction transaction, PSBT psbt) { + private Tab addTransactionTab(String name, Transaction transaction) { + return addTransactionTab(name, transaction, null, null); + } + + private Tab addTransactionTab(String name, PSBT psbt) { + return addTransactionTab(name, psbt.getTransaction(), psbt, null); + } + + private Tab addTransactionTab(BlockTransaction blockTransaction) { + return addTransactionTab(null, blockTransaction.getTransaction(), null, blockTransaction); + } + + private Tab addTransactionTab(String name, Transaction transaction, PSBT psbt, BlockTransaction blockTransaction) { + for(Tab tab : tabs.getTabs()) { + TabData tabData = (TabData)tab.getUserData(); + if(tabData instanceof TransactionTabData) { + TransactionTabData transactionTabData = (TransactionTabData)tabData; + if(transactionTabData.getTransaction() == transaction) { + return tab; + } + } + } + try { String tabName = name; + if(tabName == null || tabName.isEmpty()) { - if(transaction != null) { - tabName = "[" + transaction.getTxId().toString().substring(0, 6) + "]"; - } else if(psbt != null) { - tabName = "[" + psbt.getTransaction().getTxId().toString().substring(0, 6) + "]"; - } + tabName = "[" + transaction.getTxId().toString().substring(0, 6) + "]"; } Tab tab = new Tab(tabName); @@ -554,11 +577,9 @@ public class AppController implements Initializable { tab.setContent(transactionLoader.load()); TransactionController controller = transactionLoader.getController(); - if(transaction != null) { - controller.setTransaction(transaction); - } else if(psbt != null) { - controller.setPSBT(psbt); - } + controller.setPSBT(psbt); + controller.setBlockTransaction(blockTransaction); + controller.setTransaction(transaction); tabs.getTabs().add(tab); return tab; @@ -672,6 +693,7 @@ public class AppController implements Initializable { @Subscribe public void newConnection(ConnectionEvent event) { + currentBlockHeight = event.getBlockHeight(); String banner = event.getServerBanner(); String status = "Connected: " + (banner == null ? "Server" : banner.split(System.lineSeparator(), 2)[0]) + " at height " + event.getBlockHeight(); EventManager.get().post(new StatusEvent(status)); @@ -686,7 +708,21 @@ public class AppController implements Initializable { @Subscribe public void newBlock(NewBlockEvent event) { + currentBlockHeight = event.getHeight(); String status = "Updating to new block height " + event.getHeight(); EventManager.get().post(new StatusEvent(status)); } + + @Subscribe + public void viewTransaction(ViewTransactionEvent event) { + Tab tab = addTransactionTab(event.getBlockTransaction()); + tabs.getSelectionModel().select(tab); + Platform.runLater(() -> { + if(event.getHashIndexEntry().getType().equals(HashIndexEntry.Type.INPUT)) { + EventManager.get().post(new TransactionInputSelectedEvent(event.getHashIndexEntry().getHashIndex().getIndex())); + } else { + EventManager.get().post(new TransactionOutputSelectedEvent(event.getHashIndexEntry().getHashIndex().getIndex())); + } + }); + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java index a26974cb..aac1930c 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java @@ -6,7 +6,7 @@ import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.ReceiveActionEvent; import com.sparrowwallet.sparrow.event.ReceiveToEvent; -import com.sparrowwallet.sparrow.event.TransactionViewEvent; +import com.sparrowwallet.sparrow.event.ViewTransactionEvent; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import com.sparrowwallet.sparrow.wallet.Entry; import com.sparrowwallet.sparrow.wallet.HashIndexEntry; @@ -159,7 +159,7 @@ public class AddressTreeTable extends TreeTableView { searchGlyph.setFontSize(12); viewTransactionButton.setGraphic(searchGlyph); viewTransactionButton.setOnAction(event -> { - EventManager.get().post(new TransactionViewEvent(hashIndexEntry.getBlockTransaction(), hashIndexEntry)); + EventManager.get().post(new ViewTransactionEvent(hashIndexEntry.getBlockTransaction(), hashIndexEntry)); }); setGraphic(viewTransactionButton); } diff --git a/src/main/java/com/sparrowwallet/sparrow/event/TransactionInputSelectedEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/TransactionInputSelectedEvent.java new file mode 100644 index 00000000..416951fe --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/event/TransactionInputSelectedEvent.java @@ -0,0 +1,13 @@ +package com.sparrowwallet.sparrow.event; + +public class TransactionInputSelectedEvent { + private final long index; + + public TransactionInputSelectedEvent(long index) { + this.index = index; + } + + public long getIndex() { + return index; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/event/TransactionOutputSelectedEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/TransactionOutputSelectedEvent.java new file mode 100644 index 00000000..9406fcd5 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/event/TransactionOutputSelectedEvent.java @@ -0,0 +1,13 @@ +package com.sparrowwallet.sparrow.event; + +public class TransactionOutputSelectedEvent { + private final long index; + + public TransactionOutputSelectedEvent(long index) { + this.index = index; + } + + public long getIndex() { + return index; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/event/TransactionViewEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/ViewTransactionEvent.java similarity index 79% rename from src/main/java/com/sparrowwallet/sparrow/event/TransactionViewEvent.java rename to src/main/java/com/sparrowwallet/sparrow/event/ViewTransactionEvent.java index 92d1e3ed..c179ec7a 100644 --- a/src/main/java/com/sparrowwallet/sparrow/event/TransactionViewEvent.java +++ b/src/main/java/com/sparrowwallet/sparrow/event/ViewTransactionEvent.java @@ -3,15 +3,15 @@ package com.sparrowwallet.sparrow.event; import com.sparrowwallet.drongo.wallet.BlockTransaction; import com.sparrowwallet.sparrow.wallet.HashIndexEntry; -public class TransactionViewEvent { +public class ViewTransactionEvent { public final BlockTransaction blockTransaction; public final HashIndexEntry hashIndexEntry; - public TransactionViewEvent(BlockTransaction blockTransaction) { + public ViewTransactionEvent(BlockTransaction blockTransaction) { this(blockTransaction, null); } - public TransactionViewEvent(BlockTransaction blockTransaction, HashIndexEntry hashIndexEntry) { + public ViewTransactionEvent(BlockTransaction blockTransaction, HashIndexEntry hashIndexEntry) { this.blockTransaction = blockTransaction; this.hashIndexEntry = hashIndexEntry; } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java index cc64268c..76a34f9f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java @@ -1,6 +1,7 @@ package com.sparrowwallet.sparrow.transaction; import com.sparrowwallet.drongo.protocol.Transaction; +import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.CoinLabel; import com.sparrowwallet.sparrow.control.IdLabel; @@ -13,6 +14,7 @@ import tornadofx.control.DateTimePicker; import tornadofx.control.Field; import tornadofx.control.Fieldset; import com.google.common.eventbus.Subscribe; +import tornadofx.control.Form; import java.net.URL; import java.time.*; @@ -77,6 +79,15 @@ public class HeadersController extends TransactionFormController implements Init @FXML private CopyableLabel feeRate; + @FXML + private Form blockchainForm; + + @FXML + private CopyableLabel blockStatus; + + @FXML + private CopyableLabel blockHeight; + @Override public void initialize(URL location, ResourceBundle resources) { EventManager.get().register(this); @@ -97,6 +108,7 @@ public class HeadersController extends TransactionFormController implements Init tx.setVersion(newValue); EventManager.get().post(new TransactionChangedEvent(tx)); }); + version.setDisable(!headersForm.isEditable()); String type = "Legacy"; if(tx.isSegwit()) { @@ -170,6 +182,12 @@ public class HeadersController extends TransactionFormController implements Init EventManager.get().post(new TransactionChangedEvent(tx)); }); + locktimeNoneType.setDisable(!headersForm.isEditable()); + locktimeBlockType.setDisable(!headersForm.isEditable()); + locktimeDateType.setDisable(!headersForm.isEditable()); + locktimeBlock.setDisable(!headersForm.isEditable()); + locktimeDate.setDisable(!headersForm.isEditable()); + size.setText(tx.getSize() + " B"); virtualSize.setText(tx.getVirtualSize() + " vB"); @@ -183,6 +201,20 @@ public class HeadersController extends TransactionFormController implements Init double feeRateAmt = feeAmt.doubleValue() / tx.getVirtualSize(); feeRate.setText(String.format("%.2f", feeRateAmt) + " sats/vByte"); } + + blockchainForm.managedProperty().bind(blockchainForm.visibleProperty()); + blockchainForm.setVisible(headersForm.getBlockTransaction() != null); + if(headersForm.getBlockTransaction() != null) { + Integer currentHeight = AppController.getCurrentBlockHeight(); + if(currentHeight == null) { + blockStatus.setText("Unknown"); + } else { + int confirmations = currentHeight - headersForm.getBlockTransaction().getHeight() + 1; + blockStatus.setText(confirmations + " Confirmations"); + } + + blockHeight.setText(Integer.toString(headersForm.getBlockTransaction().getHeight())); + } } private void updateTxId() { diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersForm.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersForm.java index 30d7418a..a01fa823 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersForm.java @@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.transaction; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; +import com.sparrowwallet.drongo.wallet.BlockTransaction; import javafx.fxml.FXMLLoader; import javafx.scene.Node; @@ -12,6 +13,10 @@ public class HeadersForm extends TransactionForm { super(psbt); } + public HeadersForm(BlockTransaction blockTransaction) { + super(blockTransaction); + } + public HeadersForm(Transaction transaction) { super(transaction); } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java index 4a7b8ddc..fd26fab6 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java @@ -277,6 +277,7 @@ public class InputController extends TransactionFormController implements Initia } } }); + rbf.setDisable(!inputForm.isEditable()); } private void initializeLocktimeFields(TransactionInput txInput) { @@ -348,6 +349,13 @@ public class InputController extends TransactionFormController implements Initia locktimeRelativeSeconds.valueProperty().addListener((obs, oldValue, newValue) -> { setRelativeLocktime(txInput, transaction); }); + + 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) { diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java b/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java index f18cab41..9138642c 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java @@ -4,6 +4,7 @@ import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.protocol.TransactionInput; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTInput; +import com.sparrowwallet.drongo.wallet.BlockTransaction; import javafx.fxml.FXMLLoader; import javafx.scene.Node; @@ -19,6 +20,11 @@ public class InputForm extends TransactionForm { this.psbtInput = psbtInput; } + public InputForm(BlockTransaction blockTransaction, TransactionInput transactionInput) { + super(blockTransaction); + this.transactionInput = transactionInput; + } + public InputForm(Transaction transaction, TransactionInput transactionInput) { super(transaction); this.transactionInput = transactionInput; diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/InputsForm.java b/src/main/java/com/sparrowwallet/sparrow/transaction/InputsForm.java index ef5f374d..cfb31366 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/InputsForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/InputsForm.java @@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.transaction; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; +import com.sparrowwallet.drongo.wallet.BlockTransaction; import javafx.fxml.FXMLLoader; import javafx.scene.Node; @@ -12,6 +13,10 @@ public class InputsForm extends TransactionForm { super(psbt); } + public InputsForm(BlockTransaction blockTransaction) { + super(blockTransaction); + } + public InputsForm(Transaction transaction) { super(transaction); } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/OutputForm.java b/src/main/java/com/sparrowwallet/sparrow/transaction/OutputForm.java index 0d98daee..c054dbf0 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/OutputForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/OutputForm.java @@ -4,6 +4,7 @@ import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.protocol.TransactionOutput; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTOutput; +import com.sparrowwallet.drongo.wallet.BlockTransaction; import javafx.fxml.FXMLLoader; import javafx.scene.Node; @@ -19,6 +20,11 @@ public class OutputForm extends TransactionForm { this.psbtOutput = psbtOutput; } + public OutputForm(BlockTransaction blockTransaction, TransactionOutput transactionOutput) { + super(blockTransaction); + this.transactionOutput = transactionOutput; + } + public OutputForm(Transaction transaction, TransactionOutput transactionOutput) { super(transaction); this.transactionOutput = transactionOutput; diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/OutputsForm.java b/src/main/java/com/sparrowwallet/sparrow/transaction/OutputsForm.java index 74710316..6d0ba53f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/OutputsForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/OutputsForm.java @@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.transaction; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; +import com.sparrowwallet.drongo.wallet.BlockTransaction; import javafx.fxml.FXMLLoader; import javafx.scene.Node; @@ -12,6 +13,10 @@ public class OutputsForm extends TransactionForm { super(psbt); } + public OutputsForm(BlockTransaction blockTransaction) { + super(blockTransaction); + } + public OutputsForm(Transaction transaction) { super(transaction); } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java index b42ec01d..05323ac6 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java @@ -6,11 +6,10 @@ import com.sparrowwallet.drongo.protocol.*; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTInput; import com.sparrowwallet.drongo.psbt.PSBTOutput; +import com.sparrowwallet.drongo.wallet.BlockTransaction; import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.sparrow.EventManager; -import com.sparrowwallet.sparrow.event.TransactionChangedEvent; -import com.sparrowwallet.sparrow.event.TransactionTabChangedEvent; -import com.sparrowwallet.sparrow.event.TransactionTabSelectedEvent; +import com.sparrowwallet.sparrow.event.*; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.Node; @@ -26,6 +25,8 @@ import org.fxmisc.richtext.CodeArea; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; +import java.util.List; +import java.util.Optional; import java.util.ResourceBundle; public class TransactionController implements Initializable { @@ -47,6 +48,7 @@ public class TransactionController implements Initializable { private Transaction transaction; private PSBT psbt; + private BlockTransaction blockTransaction; private int selectedInputIndex = -1; private int selectedOutputIndex = -1; @@ -62,11 +64,11 @@ public class TransactionController implements Initializable { } private void initializeTxTree() { - HeadersForm headersForm = (psbt == null ? new HeadersForm(transaction) : new HeadersForm(psbt)); + HeadersForm headersForm = (psbt != null ? new HeadersForm(psbt) : (blockTransaction != null ? new HeadersForm(blockTransaction) : new HeadersForm(transaction))); TreeItem rootItem = new TreeItem<>(headersForm); rootItem.setExpanded(true); - InputsForm inputsForm = (psbt == null ? new InputsForm(transaction) : new InputsForm(psbt)); + InputsForm inputsForm = (psbt != null ? new InputsForm(psbt) : (blockTransaction != null ? new InputsForm(blockTransaction) : new InputsForm(transaction))); TreeItem inputsItem = new TreeItem<>(inputsForm); inputsItem.setExpanded(true); for (TransactionInput txInput : transaction.getInputs()) { @@ -74,12 +76,12 @@ public class TransactionController implements Initializable { if (psbt != null && psbt.getPsbtInputs().size() > txInput.getIndex()) { psbtInput = psbt.getPsbtInputs().get(txInput.getIndex()); } - InputForm inputForm = (psbt == null ? new InputForm(transaction, txInput) : new InputForm(psbt, psbtInput)); + InputForm inputForm = (psbt != null ? new InputForm(psbt, psbtInput) : (blockTransaction != null ? new InputForm(blockTransaction, txInput) : new InputForm(transaction, txInput))); TreeItem inputItem = new TreeItem<>(inputForm); inputsItem.getChildren().add(inputItem); } - OutputsForm outputsForm = (psbt == null ? new OutputsForm(transaction) : new OutputsForm(psbt)); + OutputsForm outputsForm = (psbt != null ? new OutputsForm(psbt) : (blockTransaction != null ? new OutputsForm(blockTransaction) : new OutputsForm(transaction))); TreeItem outputsItem = new TreeItem<>(outputsForm); outputsItem.setExpanded(true); for (TransactionOutput txOutput : transaction.getOutputs()) { @@ -87,7 +89,7 @@ public class TransactionController implements Initializable { if (psbt != null && psbt.getPsbtOutputs().size() > txOutput.getIndex()) { psbtOutput = psbt.getPsbtOutputs().get(txOutput.getIndex()); } - OutputForm outputForm = (psbt == null ? new OutputForm(transaction, txOutput) : new OutputForm(psbt, psbtOutput)); + OutputForm outputForm = (psbt != null ? new OutputForm(psbt, psbtOutput) : (blockTransaction != null ? new OutputForm(blockTransaction, txOutput) : new OutputForm(transaction, txOutput))); TreeItem outputItem = new TreeItem<>(outputForm); outputsItem.getChildren().add(outputItem); } @@ -229,19 +231,20 @@ public class TransactionController implements Initializable { return cursor; } - public void setPSBT(PSBT psbt) { - this.psbt = psbt; - this.transaction = psbt.getTransaction(); - - initializeView(); - } - public void setTransaction(Transaction transaction) { this.transaction = transaction; initializeView(); } + public void setPSBT(PSBT psbt) { + this.psbt = psbt; + } + + public void setBlockTransaction(BlockTransaction blockTransaction) { + this.blockTransaction = blockTransaction; + } + @Subscribe public void transactionChanged(TransactionChangedEvent event) { if(event.getTransaction().equals(transaction)) { @@ -259,4 +262,25 @@ public class TransactionController implements Initializable { public void tabChanged(TransactionTabChangedEvent event) { transactionMasterDetail.setShowDetailNode(event.isTxHexVisible()); } + + @Subscribe + public void inputSelected(TransactionInputSelectedEvent event) { + Optional> optionalInputs = txtree.getRoot().getChildren().stream().filter(item -> item.getValue() instanceof InputsForm).findFirst(); + selectItem(optionalInputs, (int)event.getIndex()); + } + + @Subscribe + public void outputSelected(TransactionOutputSelectedEvent event) { + Optional> optionalOutputs = txtree.getRoot().getChildren().stream().filter(item -> item.getValue() instanceof OutputsForm).findFirst(); + selectItem(optionalOutputs, (int)event.getIndex()); + } + + private void selectItem(Optional> optionalParent, int index) { + if(optionalParent.isPresent()) { + List> inputs = optionalParent.get().getChildren(); + if(inputs.size() > index) { + txtree.getSelectionModel().select(inputs.get(index)); + } + } + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionForm.java b/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionForm.java index 1c67b6fe..3fa79924 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionForm.java @@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.transaction; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; +import com.sparrowwallet.drongo.wallet.BlockTransaction; import javafx.scene.Node; import java.io.IOException; @@ -9,12 +10,18 @@ import java.io.IOException; public abstract class TransactionForm { private Transaction transaction; private PSBT psbt; + private BlockTransaction blockTransaction; public TransactionForm(PSBT psbt) { this.transaction = psbt.getTransaction(); this.psbt = psbt; } + public TransactionForm(BlockTransaction blockTransaction) { + this.transaction = blockTransaction.getTransaction(); + this.blockTransaction = blockTransaction; + } + public TransactionForm(Transaction transaction) { this.transaction = transaction; } @@ -27,5 +34,13 @@ public abstract class TransactionForm { return psbt; } + public BlockTransaction getBlockTransaction() { + return blockTransaction; + } + + public boolean isEditable() { + return blockTransaction == null; + } + public abstract Node getContents() throws IOException; } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java index 6d951547..9400e695 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java @@ -124,5 +124,6 @@ public class WalletForm { @Subscribe public void newBlock(NewBlockEvent event) { refreshHistory(); + wallet.setStoredBlockHeight(event.getHeight()); } } diff --git a/src/main/resources/com/sparrowwallet/sparrow/transaction/headers.fxml b/src/main/resources/com/sparrowwallet/sparrow/transaction/headers.fxml index 0688cdfe..a29a1803 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/transaction/headers.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/transaction/headers.fxml @@ -99,13 +99,13 @@ -
+
- + - - + +