mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
add wallet utxo pane
This commit is contained in:
parent
183d0ded2f
commit
7444a87d89
19 changed files with 420 additions and 29 deletions
|
@ -0,0 +1,41 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.ContentDisplay;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.control.TreeTableCell;
|
||||||
|
|
||||||
|
public class AddressCell extends TreeTableCell<Entry, Entry> {
|
||||||
|
public AddressCell() {
|
||||||
|
super();
|
||||||
|
setAlignment(Pos.CENTER_LEFT);
|
||||||
|
setContentDisplay(ContentDisplay.RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Entry entry, boolean empty) {
|
||||||
|
super.updateItem(entry, empty);
|
||||||
|
|
||||||
|
EntryCell.applyRowStyles(this, entry);
|
||||||
|
getStyleClass().add("address-cell");
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
setText(null);
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
if(entry instanceof UtxoEntry) {
|
||||||
|
UtxoEntry utxoEntry = (UtxoEntry)entry;
|
||||||
|
Address address = utxoEntry.getAddress();
|
||||||
|
setText(address.toString());
|
||||||
|
setContextMenu(new EntryCell.AddressContextMenu(address, utxoEntry.getOutputDescriptor()));
|
||||||
|
Tooltip tooltip = new Tooltip();
|
||||||
|
tooltip.setText(utxoEntry.getNode().getDerivationPath());
|
||||||
|
setTooltip(tooltip);
|
||||||
|
}
|
||||||
|
setGraphic(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
import com.sparrowwallet.sparrow.wallet.HashIndexEntry;
|
import com.sparrowwallet.sparrow.wallet.HashIndexEntry;
|
||||||
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
||||||
import javafx.scene.control.ContentDisplay;
|
import javafx.scene.control.ContentDisplay;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.control.TreeTableCell;
|
import javafx.scene.control.TreeTableCell;
|
||||||
|
@ -51,6 +52,8 @@ class AmountCell extends TreeTableCell<Entry, Number> {
|
||||||
} else {
|
} else {
|
||||||
setGraphic(null);
|
setGraphic(null);
|
||||||
}
|
}
|
||||||
|
} else if(entry instanceof UtxoEntry) {
|
||||||
|
setGraphic(null);
|
||||||
} else if(entry instanceof HashIndexEntry) {
|
} else if(entry instanceof HashIndexEntry) {
|
||||||
Region node = new Region();
|
Region node = new Region();
|
||||||
node.setPrefWidth(10);
|
node.setPrefWidth(10);
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.input.Clipboard;
|
||||||
|
import javafx.scene.input.ClipboardContent;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
public class DateCell extends TreeTableCell<Entry, Entry> {
|
||||||
|
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
|
||||||
|
public DateCell() {
|
||||||
|
super();
|
||||||
|
setAlignment(Pos.CENTER_LEFT);
|
||||||
|
setContentDisplay(ContentDisplay.RIGHT);
|
||||||
|
getStyleClass().add("date-cell");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Entry entry, boolean empty) {
|
||||||
|
super.updateItem(entry, empty);
|
||||||
|
|
||||||
|
EntryCell.applyRowStyles(this, entry);
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
setText(null);
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
if(entry instanceof UtxoEntry) {
|
||||||
|
UtxoEntry utxoEntry = (UtxoEntry)entry;
|
||||||
|
String date = DATE_FORMAT.format(utxoEntry.getHashIndex().getDate());
|
||||||
|
setText(date);
|
||||||
|
setContextMenu(new DateContextMenu(date, utxoEntry.getHashIndex()));
|
||||||
|
Tooltip tooltip = new Tooltip();
|
||||||
|
tooltip.setText(Integer.toString(utxoEntry.getHashIndex().getHeight()));
|
||||||
|
setTooltip(tooltip);
|
||||||
|
}
|
||||||
|
setGraphic(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DateContextMenu extends ContextMenu {
|
||||||
|
public DateContextMenu(String date, BlockTransactionHashIndex reference) {
|
||||||
|
MenuItem copyDate = new MenuItem("Copy Date");
|
||||||
|
copyDate.setOnAction(AE -> {
|
||||||
|
hide();
|
||||||
|
ClipboardContent content = new ClipboardContent();
|
||||||
|
content.putString(date);
|
||||||
|
Clipboard.getSystemClipboard().setContent(content);
|
||||||
|
});
|
||||||
|
|
||||||
|
MenuItem copyHeight = new MenuItem("Copy Block Height");
|
||||||
|
copyHeight.setOnAction(AE -> {
|
||||||
|
hide();
|
||||||
|
ClipboardContent content = new ClipboardContent();
|
||||||
|
content.putString(Integer.toString(reference.getHeight()));
|
||||||
|
Clipboard.getSystemClipboard().setContent(content);
|
||||||
|
});
|
||||||
|
|
||||||
|
getItems().addAll(copyDate, copyHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,10 +8,7 @@ import com.sparrowwallet.sparrow.event.ReceiveActionEvent;
|
||||||
import com.sparrowwallet.sparrow.event.ReceiveToEvent;
|
import com.sparrowwallet.sparrow.event.ReceiveToEvent;
|
||||||
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
||||||
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
import com.sparrowwallet.sparrow.wallet.*;
|
||||||
import com.sparrowwallet.sparrow.wallet.HashIndexEntry;
|
|
||||||
import com.sparrowwallet.sparrow.wallet.NodeEntry;
|
|
||||||
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
@ -118,7 +115,7 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
});
|
});
|
||||||
|
|
||||||
MenuItem copyHeight = new MenuItem("Copy Block Height");
|
MenuItem copyHeight = new MenuItem("Copy Block Height");
|
||||||
copyTxid.setOnAction(AE -> {
|
copyHeight.setOnAction(AE -> {
|
||||||
hide();
|
hide();
|
||||||
ClipboardContent content = new ClipboardContent();
|
ClipboardContent content = new ClipboardContent();
|
||||||
content.putString(Integer.toString(blockTransaction.getHeight()));
|
content.putString(Integer.toString(blockTransaction.getHeight()));
|
||||||
|
@ -129,7 +126,7 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AddressContextMenu extends ContextMenu {
|
public static class AddressContextMenu extends ContextMenu {
|
||||||
public AddressContextMenu(Address address, String outputDescriptor) {
|
public AddressContextMenu(Address address, String outputDescriptor) {
|
||||||
MenuItem copyAddress = new MenuItem("Copy Address");
|
MenuItem copyAddress = new MenuItem("Copy Address");
|
||||||
copyAddress.setOnAction(AE -> {
|
copyAddress.setOnAction(AE -> {
|
||||||
|
@ -195,6 +192,8 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
}
|
}
|
||||||
} else if(entry instanceof NodeEntry) {
|
} else if(entry instanceof NodeEntry) {
|
||||||
cell.getStyleClass().add("node-row");
|
cell.getStyleClass().add("node-row");
|
||||||
|
} else if(entry instanceof UtxoEntry) {
|
||||||
|
cell.getStyleClass().add("utxo-row");
|
||||||
} else if(entry instanceof HashIndexEntry) {
|
} else if(entry instanceof HashIndexEntry) {
|
||||||
cell.getStyleClass().add("hashindex-row");
|
cell.getStyleClass().add("hashindex-row");
|
||||||
HashIndexEntry hashIndexEntry = (HashIndexEntry)entry;
|
HashIndexEntry hashIndexEntry = (HashIndexEntry)entry;
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class TransactionsTreeTable extends TreeTableView<Entry> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateHistory(List<WalletNode> updatedNodes) {
|
public void updateHistory(List<WalletNode> updatedNodes) {
|
||||||
//Recalculate from scratch and update according - any changes may affect the balance of other transactions
|
//Recalculate from scratch and update accordingly - any changes may affect the balance of other transactions
|
||||||
WalletTransactionsEntry rootEntry = (WalletTransactionsEntry)getRoot().getValue();
|
WalletTransactionsEntry rootEntry = (WalletTransactionsEntry)getRoot().getValue();
|
||||||
rootEntry.updateTransactions();
|
rootEntry.updateTransactions();
|
||||||
sort();
|
sort();
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.*;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TreeTableColumn;
|
||||||
|
import javafx.scene.control.TreeTableView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UtxosTreeTable extends TreeTableView<Entry> {
|
||||||
|
public void initialize(WalletUtxosEntry rootEntry) {
|
||||||
|
getStyleClass().add("utxos-treetable");
|
||||||
|
|
||||||
|
updateAll(rootEntry);
|
||||||
|
setShowRoot(false);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, Entry> dateCol = new TreeTableColumn<>("Date");
|
||||||
|
dateCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Entry> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue());
|
||||||
|
});
|
||||||
|
dateCol.setCellFactory(p -> new DateCell());
|
||||||
|
dateCol.setSortable(true);
|
||||||
|
getColumns().add(dateCol);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, Entry> outputCol = new TreeTableColumn<>("Output");
|
||||||
|
outputCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Entry> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue());
|
||||||
|
});
|
||||||
|
outputCol.setCellFactory(p -> new EntryCell());
|
||||||
|
outputCol.setSortable(true);
|
||||||
|
outputCol.setComparator((o1, o2) -> {
|
||||||
|
UtxoEntry entry1 = (UtxoEntry)o1;
|
||||||
|
UtxoEntry entry2 = (UtxoEntry)o2;
|
||||||
|
return entry1.getDescription().compareTo(entry2.getDescription());
|
||||||
|
});
|
||||||
|
getColumns().add(outputCol);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, Entry> addressCol = new TreeTableColumn<>("Address");
|
||||||
|
addressCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Entry> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue());
|
||||||
|
});
|
||||||
|
addressCol.setCellFactory(p -> new AddressCell());
|
||||||
|
addressCol.setSortable(true);
|
||||||
|
addressCol.setComparator((o1, o2) -> {
|
||||||
|
UtxoEntry entry1 = (UtxoEntry)o1;
|
||||||
|
UtxoEntry entry2 = (UtxoEntry)o2;
|
||||||
|
return entry1.getAddress().toString().compareTo(entry2.getAddress().toString());
|
||||||
|
});
|
||||||
|
getColumns().add(addressCol);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, String> labelCol = new TreeTableColumn<>("Label");
|
||||||
|
labelCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> {
|
||||||
|
return param.getValue().getValue().labelProperty();
|
||||||
|
});
|
||||||
|
labelCol.setCellFactory(p -> new LabelCell());
|
||||||
|
labelCol.setSortable(true);
|
||||||
|
getColumns().add(labelCol);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, Number> amountCol = new TreeTableColumn<>("Value");
|
||||||
|
amountCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Number> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getValue());
|
||||||
|
});
|
||||||
|
amountCol.setCellFactory(p -> new AmountCell());
|
||||||
|
amountCol.setSortable(true);
|
||||||
|
getColumns().add(amountCol);
|
||||||
|
setTreeColumn(amountCol);
|
||||||
|
|
||||||
|
setPlaceholder(new Label("No unspent outputs"));
|
||||||
|
setEditable(true);
|
||||||
|
setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
|
||||||
|
dateCol.setSortType(TreeTableColumn.SortType.DESCENDING);
|
||||||
|
getSortOrder().add(dateCol);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAll(WalletUtxosEntry rootEntry) {
|
||||||
|
RecursiveTreeItem<Entry> rootItem = new RecursiveTreeItem<>(rootEntry, Entry::getChildren);
|
||||||
|
setRoot(rootItem);
|
||||||
|
rootItem.setExpanded(true);
|
||||||
|
|
||||||
|
if(getColumns().size() > 0 && getSortOrder().isEmpty()) {
|
||||||
|
TreeTableColumn<Entry, ?> dateCol = getColumns().get(0);
|
||||||
|
getSortOrder().add(dateCol);
|
||||||
|
dateCol.setSortType(TreeTableColumn.SortType.DESCENDING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateHistory(List<WalletNode> updatedNodes) {
|
||||||
|
//Recalculate from scratch and update accordingly
|
||||||
|
WalletUtxosEntry rootEntry = (WalletUtxosEntry)getRoot().getValue();
|
||||||
|
rootEntry.updateUtxos();
|
||||||
|
sort();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ public class FontAwesome5 extends GlyphFont {
|
||||||
public static enum Glyph implements INamedCharacter {
|
public static enum Glyph implements INamedCharacter {
|
||||||
CHECK_CIRCLE('\uf058'),
|
CHECK_CIRCLE('\uf058'),
|
||||||
CIRCLE('\uf111'),
|
CIRCLE('\uf111'),
|
||||||
|
COINS('\uf51e'),
|
||||||
EXCLAMATION_CIRCLE('\uf06a'),
|
EXCLAMATION_CIRCLE('\uf06a'),
|
||||||
ELLIPSIS_H('\uf141'),
|
ELLIPSIS_H('\uf141'),
|
||||||
EYE('\uf06e'),
|
EYE('\uf06e'),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
package com.sparrowwallet.sparrow.wallet;
|
package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
public enum Function {
|
public enum Function {
|
||||||
TRANSACTIONS, SEND, RECEIVE, ADDRESSES, POLICIES, SETTINGS;
|
TRANSACTIONS, SEND, RECEIVE, ADDRESSES, UTXOS, SETTINGS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,14 +29,6 @@ public class TransactionHashIndexEntry extends HashIndexEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockTransaction getSpentByTransaction() {
|
|
||||||
if(getHashIndex().getSpentBy() != null) {
|
|
||||||
return getWallet().getTransactions().get(getHashIndex().getSpentBy().getHash());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSpent() {
|
public boolean isSpent() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
|
||||||
|
public class UtxoEntry extends HashIndexEntry {
|
||||||
|
private final WalletNode node;
|
||||||
|
|
||||||
|
public UtxoEntry(Wallet wallet, BlockTransactionHashIndex hashIndex, Type type, WalletNode node) {
|
||||||
|
super(wallet, hashIndex, type, node.getKeyPurpose());
|
||||||
|
this.node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObservableList<Entry> getChildren() {
|
||||||
|
return FXCollections.emptyObservableList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return getHashIndex().getHash().toString().substring(0, 8) + "...:" + getHashIndex().getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSpent() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getAddress() {
|
||||||
|
return getWallet().getAddress(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WalletNode getNode() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutputDescriptor() {
|
||||||
|
return getWallet().getOutputDescriptor(node);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
|
import com.sparrowwallet.sparrow.control.UtxosTreeTable;
|
||||||
|
import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent;
|
||||||
|
import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class UtxosController extends WalletFormController implements Initializable {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private UtxosTreeTable utxosTable;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
EventManager.get().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeView() {
|
||||||
|
utxosTable.initialize(getWalletForm().getWalletUtxosEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void walletNodesChanged(WalletNodesChangedEvent event) {
|
||||||
|
if(event.getWallet().equals(walletForm.getWallet())) {
|
||||||
|
utxosTable.updateAll(getWalletForm().getWalletUtxosEntry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void walletHistoryChanged(WalletHistoryChangedEvent event) {
|
||||||
|
if(event.getWallet().equals(walletForm.getWallet())) {
|
||||||
|
utxosTable.updateHistory(event.getHistoryChangedNodes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ public class WalletForm {
|
||||||
protected Wallet wallet;
|
protected Wallet wallet;
|
||||||
|
|
||||||
private WalletTransactionsEntry walletTransactionsEntry;
|
private WalletTransactionsEntry walletTransactionsEntry;
|
||||||
|
private WalletUtxosEntry walletUtxosEntry;
|
||||||
private final List<NodeEntry> accountEntries = new ArrayList<>();
|
private final List<NodeEntry> accountEntries = new ArrayList<>();
|
||||||
|
|
||||||
public WalletForm(Storage storage, Wallet currentWallet) {
|
public WalletForm(Storage storage, Wallet currentWallet) {
|
||||||
|
@ -136,6 +137,14 @@ public class WalletForm {
|
||||||
return walletTransactionsEntry;
|
return walletTransactionsEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WalletUtxosEntry getWalletUtxosEntry() {
|
||||||
|
if(walletUtxosEntry == null) {
|
||||||
|
walletUtxosEntry = new WalletUtxosEntry(wallet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return walletUtxosEntry;
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void walletLabelChanged(WalletEntryLabelChangedEvent event) {
|
public void walletLabelChanged(WalletEntryLabelChangedEvent event) {
|
||||||
if(event.getWallet().equals(wallet)) {
|
if(event.getWallet().equals(wallet)) {
|
||||||
|
@ -164,6 +173,7 @@ public class WalletForm {
|
||||||
if(event.getWalletFile().equals(storage.getWalletFile())) {
|
if(event.getWalletFile().equals(storage.getWalletFile())) {
|
||||||
wallet = event.getWallet();
|
wallet = event.getWallet();
|
||||||
walletTransactionsEntry = null;
|
walletTransactionsEntry = null;
|
||||||
|
walletUtxosEntry = null;
|
||||||
accountEntries.clear();
|
accountEntries.clear();
|
||||||
EventManager.get().post(new WalletNodesChangedEvent(wallet));
|
EventManager.get().post(new WalletNodesChangedEvent(wallet));
|
||||||
refreshHistory(AppController.getCurrentBlockHeight());
|
refreshHistory(AppController.getCurrentBlockHeight());
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.KeyPurpose;
|
||||||
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class WalletUtxosEntry extends Entry {
|
||||||
|
private final Wallet wallet;
|
||||||
|
|
||||||
|
public WalletUtxosEntry(Wallet wallet) {
|
||||||
|
super(wallet.getName(), getWalletUtxos(wallet).entrySet().stream().map(entry -> new UtxoEntry(wallet, entry.getKey(), HashIndexEntry.Type.OUTPUT, entry.getValue())).collect(Collectors.toList()));
|
||||||
|
this.wallet = wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wallet getWallet() {
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getValue() {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateUtxos() {
|
||||||
|
List<Entry> current = getWalletUtxos(wallet).entrySet().stream().map(entry -> new UtxoEntry(wallet, entry.getKey(), HashIndexEntry.Type.OUTPUT, entry.getValue())).collect(Collectors.toList());
|
||||||
|
List<Entry> previous = new ArrayList<>(getChildren());
|
||||||
|
|
||||||
|
List<Entry> entriesAdded = new ArrayList<>(current);
|
||||||
|
entriesAdded.removeAll(previous);
|
||||||
|
getChildren().addAll(entriesAdded);
|
||||||
|
|
||||||
|
List<Entry> entriesRemoved = new ArrayList<>(previous);
|
||||||
|
entriesRemoved.removeAll(current);
|
||||||
|
getChildren().removeAll(entriesRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<BlockTransactionHashIndex, WalletNode> getWalletUtxos(Wallet wallet) {
|
||||||
|
Map<BlockTransactionHashIndex, WalletNode> walletUtxos = new TreeMap<>();
|
||||||
|
|
||||||
|
getWalletUtxos(wallet, walletUtxos, wallet.getNode(KeyPurpose.RECEIVE));
|
||||||
|
getWalletUtxos(wallet, walletUtxos, wallet.getNode(KeyPurpose.CHANGE));
|
||||||
|
|
||||||
|
return walletUtxos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void getWalletUtxos(Wallet wallet, Map<BlockTransactionHashIndex, WalletNode> walletUtxos, WalletNode purposeNode) {
|
||||||
|
for(WalletNode addressNode : purposeNode.getChildren()) {
|
||||||
|
for(BlockTransactionHashIndex utxo : addressNode.getUnspentTransactionOutputs()) {
|
||||||
|
walletUtxos.put(utxo, addressNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,5 @@
|
||||||
|
.addresses-treetable-label {
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-font-size: 1.2em;
|
||||||
|
-fx-padding: 10 0 10 0;
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
|
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||||
<top>
|
<top>
|
||||||
<Label styleClass="address-treetable-label" text="Receiving Addresses:"/>
|
<Label styleClass="addresses-treetable-label" text="Receiving Addresses:"/>
|
||||||
</top>
|
</top>
|
||||||
<center>
|
<center>
|
||||||
<AddressTreeTable fx:id="receiveTable" />
|
<AddressTreeTable fx:id="receiveTable" />
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1">
|
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1">
|
||||||
<top>
|
<top>
|
||||||
<Label styleClass="address-treetable-label" text="Change Addresses:"/>
|
<Label styleClass="addresses-treetable-label" text="Change Addresses:"/>
|
||||||
</top>
|
</top>
|
||||||
<center>
|
<center>
|
||||||
<AddressTreeTable fx:id="changeTable" />
|
<AddressTreeTable fx:id="changeTable" />
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
.utxos-treetable-label {
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
-fx-font-size: 1.2em;
|
||||||
|
-fx-padding: 10 0 10 0;
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import java.lang.*?>
|
||||||
|
<?import java.util.*?>
|
||||||
|
<?import javafx.scene.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.chart.BarChart?>
|
||||||
|
<?import com.sparrowwallet.sparrow.control.UtxosTreeTable?>
|
||||||
|
<GridPane hgap="10.0" vgap="10.0" stylesheets="@utxos.css, @wallet.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.wallet.UtxosController">
|
||||||
|
<padding>
|
||||||
|
<Insets left="25.0" right="25.0" top="15.0" bottom="25.0" />
|
||||||
|
</padding>
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints percentWidth="100.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints percentHeight="50" />
|
||||||
|
<RowConstraints percentHeight="50" />
|
||||||
|
</rowConstraints>
|
||||||
|
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||||
|
<top>
|
||||||
|
<Label styleClass="utxos-treetable-label" text="Unspent Transaction Outputs:"/>
|
||||||
|
</top>
|
||||||
|
<center>
|
||||||
|
<UtxosTreeTable fx:id="utxosTable" />
|
||||||
|
</center>
|
||||||
|
</BorderPane>
|
||||||
|
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1">
|
||||||
|
<center>
|
||||||
|
<!-- <BarChart fx:id="changeTable" /> -->
|
||||||
|
</center>
|
||||||
|
</BorderPane>
|
||||||
|
</GridPane>
|
|
@ -29,13 +29,7 @@
|
||||||
-fx-background-color: -fx-background;
|
-fx-background-color: -fx-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
.address-treetable-label {
|
.address-cell, .utxo-row.entry-cell {
|
||||||
-fx-font-weight: bold;
|
|
||||||
-fx-font-size: 1.2em;
|
|
||||||
-fx-padding: 10 0 10 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.address-cell {
|
|
||||||
-fx-font-family: Courier;
|
-fx-font-family: Courier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,12 +46,12 @@
|
||||||
<Function fx:constant="ADDRESSES"/>
|
<Function fx:constant="ADDRESSES"/>
|
||||||
</userData>
|
</userData>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
<ToggleButton VBox.vgrow="ALWAYS" text="Policies" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity" toggleGroup="$walletMenu">
|
<ToggleButton VBox.vgrow="ALWAYS" text="UTXOs" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity" toggleGroup="$walletMenu">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="FontAwesome" icon="FILE_TEXT" fontSize="20" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="COINS" fontSize="20" />
|
||||||
</graphic>
|
</graphic>
|
||||||
<userData>
|
<userData>
|
||||||
<Function fx:constant="POLICIES"/>
|
<Function fx:constant="UTXOS"/>
|
||||||
</userData>
|
</userData>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
<ToggleButton VBox.vgrow="ALWAYS" text="Settings" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity" toggleGroup="$walletMenu">
|
<ToggleButton VBox.vgrow="ALWAYS" text="Settings" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity" toggleGroup="$walletMenu">
|
||||||
|
|
Loading…
Reference in a new issue