mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-11-05 11:56:37 +00:00
add duplicate address indicator
This commit is contained in:
parent
cd7fc06819
commit
07458d3dff
4 changed files with 90 additions and 2 deletions
|
|
@ -1,12 +1,14 @@
|
||||||
package com.sparrowwallet.sparrow.control;
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.address.Address;
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
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;
|
||||||
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
|
|
||||||
public class AddressCell extends TreeTableCell<Entry, Entry> {
|
public class AddressCell extends TreeTableCell<Entry, Entry> {
|
||||||
public AddressCell() {
|
public AddressCell() {
|
||||||
|
|
@ -32,10 +34,37 @@ public class AddressCell extends TreeTableCell<Entry, Entry> {
|
||||||
setText(address.toString());
|
setText(address.toString());
|
||||||
setContextMenu(new EntryCell.AddressContextMenu(address, utxoEntry.getOutputDescriptor()));
|
setContextMenu(new EntryCell.AddressContextMenu(address, utxoEntry.getOutputDescriptor()));
|
||||||
Tooltip tooltip = new Tooltip();
|
Tooltip tooltip = new Tooltip();
|
||||||
tooltip.setText(utxoEntry.getNode().getDerivationPath());
|
tooltip.setText(getTooltipText(utxoEntry));
|
||||||
setTooltip(tooltip);
|
setTooltip(tooltip);
|
||||||
|
|
||||||
|
if(utxoEntry.isDuplicateAddress()) {
|
||||||
|
setGraphic(getDuplicateGlyph());
|
||||||
|
} else {
|
||||||
|
setGraphic(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
utxoEntry.duplicateAddressProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
if(newValue) {
|
||||||
|
setGraphic(getDuplicateGlyph());
|
||||||
|
Tooltip tt = new Tooltip();
|
||||||
|
tt.setText(getTooltipText(utxoEntry));
|
||||||
|
setTooltip(tt);
|
||||||
|
} else {
|
||||||
|
setGraphic(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
setGraphic(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getTooltipText(UtxoEntry utxoEntry) {
|
||||||
|
return utxoEntry.getNode().getDerivationPath() + (utxoEntry.isDuplicateAddress() ? " (Duplicate address)" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Glyph getDuplicateGlyph() {
|
||||||
|
Glyph duplicateGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.EXCLAMATION_CIRCLE);
|
||||||
|
duplicateGlyph.getStyleClass().add("duplicate-warning");
|
||||||
|
duplicateGlyph.setFontSize(12);
|
||||||
|
return duplicateGlyph;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import com.sparrowwallet.drongo.address.Address;
|
||||||
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
import javafx.beans.property.BooleanPropertyBase;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
|
||||||
|
|
@ -41,4 +43,37 @@ public class UtxoEntry extends HashIndexEntry {
|
||||||
public String getOutputDescriptor() {
|
public String getOutputDescriptor() {
|
||||||
return getWallet().getOutputDescriptor(node);
|
return getWallet().getOutputDescriptor(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines whether this utxo shares it's address with another utxo in the wallet
|
||||||
|
*/
|
||||||
|
private BooleanProperty duplicateAddress;
|
||||||
|
|
||||||
|
public final void setDuplicateAddress(boolean value) {
|
||||||
|
if(duplicateAddress != null || value) {
|
||||||
|
duplicateAddressProperty().set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isDuplicateAddress() {
|
||||||
|
return duplicateAddress != null && duplicateAddress.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final BooleanProperty duplicateAddressProperty() {
|
||||||
|
if(duplicateAddress == null) {
|
||||||
|
duplicateAddress = new BooleanPropertyBase(false) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getBean() {
|
||||||
|
return UtxoEntry.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "duplicate";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return duplicateAddress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ public class WalletUtxosEntry extends Entry {
|
||||||
public WalletUtxosEntry(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()));
|
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;
|
this.wallet = wallet;
|
||||||
|
calculateDuplicates();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Wallet getWallet() {
|
public Wallet getWallet() {
|
||||||
|
|
@ -25,6 +26,23 @@ public class WalletUtxosEntry extends Entry {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void calculateDuplicates() {
|
||||||
|
Map<String, UtxoEntry> addressMap = new HashMap<>();
|
||||||
|
|
||||||
|
for(Entry entry : getChildren()) {
|
||||||
|
UtxoEntry utxoEntry = (UtxoEntry)entry;
|
||||||
|
String address = utxoEntry.getAddress().toString();
|
||||||
|
|
||||||
|
UtxoEntry duplicate = addressMap.get(address);
|
||||||
|
if(duplicate != null) {
|
||||||
|
duplicate.setDuplicateAddress(true);
|
||||||
|
utxoEntry.setDuplicateAddress(true);
|
||||||
|
} else {
|
||||||
|
addressMap.put(address, utxoEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void updateUtxos() {
|
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> 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> previous = new ArrayList<>(getChildren());
|
||||||
|
|
@ -36,6 +54,8 @@ public class WalletUtxosEntry extends Entry {
|
||||||
List<Entry> entriesRemoved = new ArrayList<>(previous);
|
List<Entry> entriesRemoved = new ArrayList<>(previous);
|
||||||
entriesRemoved.removeAll(current);
|
entriesRemoved.removeAll(current);
|
||||||
getChildren().removeAll(entriesRemoved);
|
getChildren().removeAll(entriesRemoved);
|
||||||
|
|
||||||
|
calculateDuplicates();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<BlockTransactionHashIndex, WalletNode> getWalletUtxos(Wallet wallet) {
|
private static Map<BlockTransactionHashIndex, WalletNode> getWalletUtxos(Wallet wallet) {
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,7 @@
|
||||||
.tree-table-row-cell:selected .entry-cell:hover .button .label .text {
|
.tree-table-row-cell:selected .entry-cell:hover .button .label .text {
|
||||||
-fx-fill: white;
|
-fx-fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.duplicate-warning {
|
||||||
|
-fx-text-fill: rgb(202, 18, 67);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue