From 189ac754672ab60b8cd83487585b218d7af43b22 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Sat, 22 Aug 2020 17:20:43 +0200 Subject: [PATCH] set null date on unconfirmed txes, dont let external utxos show as spendable --- drongo | 2 +- .../sparrow/control/BalanceChart.java | 3 +- .../sparrow/control/DateCell.java | 11 +++++-- .../sparrow/control/EntryCell.java | 33 ++++++++++++++++--- .../sparrow/net/ElectrumServer.java | 4 +-- .../sparrow/net/SimpleElectrumServerRpc.java | 4 +-- .../sparrow/wallet/HashIndexEntry.java | 6 +++- .../sparrow/wallet/ReceiveController.java | 2 +- .../sparrowwallet/sparrow/wallet/send.fxml | 2 +- 9 files changed, 49 insertions(+), 18 deletions(-) diff --git a/drongo b/drongo index 446eac34..e8bb733e 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 446eac3483229fc4c798e82f367ca9d8f797d16e +Subproject commit e8bb733ea8a6e476982e5ea78c288105d0bd8644 diff --git a/src/main/java/com/sparrowwallet/sparrow/control/BalanceChart.java b/src/main/java/com/sparrowwallet/sparrow/control/BalanceChart.java index c7172eb2..eb6f8020 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/BalanceChart.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/BalanceChart.java @@ -39,6 +39,7 @@ public class BalanceChart extends LineChart { List> balanceDataList = walletTransactionsEntry.getChildren().stream() .map(entry -> (TransactionEntry)entry) + .filter(txEntry -> txEntry.getBlockTransaction().getHeight() > 0) .map(txEntry -> new XYChart.Data<>((Number)txEntry.getBlockTransaction().getDate().getTime(), (Number)txEntry.getBalance(), txEntry)) .collect(Collectors.toList()); @@ -83,7 +84,7 @@ public class BalanceChart extends LineChart { XYChart.Data data = balanceSeries.getData().get(i); Node symbol = lookup(".chart-line-symbol.data" + i); if(symbol != null) { - if(data.getXValue().equals(transactionEntry.getBlockTransaction().getDate().getTime()) && data.getExtraValue() != null) { + if(transactionEntry.getBlockTransaction().getDate() != null && data.getXValue().equals(transactionEntry.getBlockTransaction().getDate().getTime()) && data.getExtraValue() != null) { symbol.getStyleClass().add("selected"); selectedEntry = transactionEntry; } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DateCell.java b/src/main/java/com/sparrowwallet/sparrow/control/DateCell.java index 7d3a0bf4..10776a32 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DateCell.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DateCell.java @@ -33,9 +33,14 @@ public class DateCell extends TreeTableCell { } 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())); + if(utxoEntry.getHashIndex().getHeight() <= 0) { + setText("Unconfirmed"); + } else { + String date = DATE_FORMAT.format(utxoEntry.getHashIndex().getDate()); + setText(date); + setContextMenu(new DateContextMenu(date, utxoEntry.getHashIndex())); + } + Tooltip tooltip = new Tooltip(); int height = utxoEntry.getHashIndex().getHeight(); tooltip.setText(height > 0 ? Integer.toString(height) : "Mempool"); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java b/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java index 8e9e4e20..c96e5b5c 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java @@ -43,9 +43,18 @@ class EntryCell extends TreeTableCell { } else { if(entry instanceof TransactionEntry) { TransactionEntry transactionEntry = (TransactionEntry)entry; - String date = DATE_FORMAT.format(transactionEntry.getBlockTransaction().getDate()); - setText(date); - setContextMenu(new TransactionContextMenu(date, transactionEntry.getBlockTransaction())); + if(transactionEntry.getBlockTransaction().getHeight() == -1) { + setText("Unconfirmed Parent"); + setContextMenu(new UnconfirmedTransactionContextMenu(transactionEntry.getBlockTransaction())); + } else if(transactionEntry.getBlockTransaction().getHeight() == 0) { + setText("Unconfirmed"); + setContextMenu(new UnconfirmedTransactionContextMenu(transactionEntry.getBlockTransaction())); + } else { + String date = DATE_FORMAT.format(transactionEntry.getBlockTransaction().getDate()); + setText(date); + setContextMenu(new TransactionContextMenu(date, transactionEntry.getBlockTransaction())); + } + Tooltip tooltip = new Tooltip(); tooltip.setText(transactionEntry.getBlockTransaction().getHash().toString()); setTooltip(tooltip); @@ -95,7 +104,7 @@ class EntryCell extends TreeTableCell { }); actionBox.getChildren().add(viewTransactionButton); - if(hashIndexEntry.getType().equals(HashIndexEntry.Type.OUTPUT) && !hashIndexEntry.isSpent()) { + if(hashIndexEntry.getType().equals(HashIndexEntry.Type.OUTPUT) && hashIndexEntry.isSpendable()) { Button spendUtxoButton = new Button(""); Glyph sendGlyph = new Glyph("FontAwesome", FontAwesome.Glyph.SEND); sendGlyph.setFontSize(12); @@ -105,7 +114,7 @@ class EntryCell extends TreeTableCell { .map(tp -> tp.getTreeItem().getValue()) .filter(e -> e instanceof HashIndexEntry) .map(e -> (HashIndexEntry)e) - .filter(e -> e.getType().equals(HashIndexEntry.Type.OUTPUT) && !hashIndexEntry.isSpent()) + .filter(e -> e.getType().equals(HashIndexEntry.Type.OUTPUT) && e.isSpendable()) .collect(Collectors.toList()); if(!utxoEntries.contains(hashIndexEntry)) { @@ -124,6 +133,20 @@ class EntryCell extends TreeTableCell { } } + private static class UnconfirmedTransactionContextMenu extends ContextMenu { + public UnconfirmedTransactionContextMenu(BlockTransaction blockTransaction) { + MenuItem copyTxid = new MenuItem("Copy Transaction ID"); + copyTxid.setOnAction(AE -> { + hide(); + ClipboardContent content = new ClipboardContent(); + content.putString(blockTransaction.getHashAsString()); + Clipboard.getSystemClipboard().setContent(content); + }); + + getItems().addAll(copyTxid); + } + } + private static class TransactionContextMenu extends ContextMenu { public TransactionContextMenu(String date, BlockTransaction blockTransaction) { MenuItem copyDate = new MenuItem("Copy Date"); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java index 94de6a27..1e551279 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java @@ -370,7 +370,7 @@ public class ElectrumServer { } BlockTransactionHash reference = optionalReference.get(); - Date blockDate; + Date blockDate = null; if(reference.getHeight() > 0) { BlockHeader blockHeader = blockHeaderMap.get(reference.getHeight()); if(blockHeader == null) { @@ -379,8 +379,6 @@ public class ElectrumServer { continue; } blockDate = blockHeader.getTimeAsDate(); - } else { - blockDate = new Date(); } BlockTransaction blockchainTransaction = new BlockTransaction(reference.getHash(), reference.getHeight(), blockDate, reference.getFee(), transaction); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java index 491be7bd..252b5614 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java @@ -210,12 +210,12 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { result.put(targetBlock, targetBlocksFeeRateBtcKb); } catch(IllegalStateException | IllegalArgumentException e) { log.warn("Failed to retrieve fee rate for target blocks: " + targetBlock + " (" + e.getMessage() + ")"); - result.put(targetBlock, 1d); + result.put(targetBlock, 0.0001d); } catch(JsonRpcException e) { throw new ElectrumServerRpcException("Failed to retrieve fee rate for target blocks: " + targetBlock, e); } } else { - result.put(targetBlock, 1d); + result.put(targetBlock, 0.0001d); } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java b/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java index 756c8b88..6f0a856b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java @@ -55,13 +55,17 @@ public class HashIndexEntry extends Entry implements Comparable return (type.equals(Type.INPUT) ? "Spent by input " : "Received from output ") + getHashIndex().getHash().toString().substring(0, 8) + "..:" + getHashIndex().getIndex() + - " on " + DateLabel.getShortDateFormat(getHashIndex().getDate()); + (getHashIndex().getHeight() <= 0 ? " (Unconfirmed)" : " on " + DateLabel.getShortDateFormat(getHashIndex().getDate())); } public boolean isSpent() { return getType().equals(HashIndexEntry.Type.INPUT) || getHashIndex().getSpentBy() != null; } + public boolean isSpendable() { + return !isSpent() && (hashIndex.getHeight() > 0 || wallet.allInputsFromWallet(hashIndex.getHash())); + } + @Override public Long getValue() { return hashIndex.getValue(); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java index 5d11f02f..5b87f38d 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java @@ -144,7 +144,7 @@ public class ReceiveController extends WalletFormController implements Initializ } else if(!currentOutputs.isEmpty()) { long count = currentOutputs.size(); BlockTransactionHashIndex lastUsedReference = currentOutputs.stream().skip(count - 1).findFirst().get(); - lastUsed.setText(DATE_FORMAT.format(lastUsedReference.getDate())); + lastUsed.setText(lastUsedReference.getHeight() <= 0 ? "Unconfirmed Transaction" : DATE_FORMAT.format(lastUsedReference.getDate())); lastUsed.setGraphic(getWarningGlyph()); } else { lastUsed.setText("Unknown"); diff --git a/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml b/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml index e09fc2f6..dc503e8c 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml @@ -106,7 +106,7 @@ - +