respect configured bitcoin unit on transaction diagram and label
What changed, and why it matters
This commit is a straightforward user-interface improvement: it makes the transaction diagram and related labels display Bitcoin amounts in whatever unit the user has chosen (BTC or satoshis), instead of always showing satoshis. It also refreshes the diagram when the user changes the unit format. There is no security issue here.
No security action required. This is a normal UI/UX fix and can be reviewed through standard quality-assurance channels.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch renames getSatsValue() to getCoinValue() in TransactionDiagram and updates it to consult Config.get().getBitcoinUnit(). If the configured unit is BTC (or AUTO with a large enough amount), it formats the value as BTC; otherwise it formats as satoshis. Call sites in TransactionDiagram, TransactionDiagramLabel, HeadersController, and SendController are updated to use the new method and to refresh the diagram on UnitFormatChangedEvent. No cryptographic, network, or privilege logic is changed.
Changed components
com.sparrowwallet.sparrow.control.TransactionDiagramcom.sparrowwallet.sparrow.control.TransactionDiagramLabelcom.sparrowwallet.sparrow.transaction.HeadersControllercom.sparrowwallet.sparrow.wallet.SendControllerInspect captured patch +32 / −20
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java
index 59d2fd8..b832983 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java
@@ -1,5 +1,6 @@
package com.sparrowwallet.sparrow.control;
+import com.sparrowwallet.drongo.BitcoinUnit;
import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.OsType;
import com.sparrowwallet.drongo.address.Address;
@@ -474,7 +475,7 @@ public class TransactionDiagram extends GridPane {
inputValue = input.getValue();
Wallet nodeWallet = walletNode.getWallet();
StringJoiner joiner = new StringJoiner("\n");
- joiner.add("Spending " + getSatsValue(inputValue) + " sats from " + (isFinal() ? nodeWallet.getFullDisplayName() : (nodeWallet.isNested() ? nodeWallet.getDisplayName() : "")) + " " + walletNode);
+ joiner.add("Spending " + getCoinValue(inputValue) + " from " + (isFinal() ? nodeWallet.getFullDisplayName() : (nodeWallet.isNested() ? nodeWallet.getDisplayName() : "")) + " " + walletNode);
joiner.add(input.getHashAsString() + ":" + input.getIndex());
joiner.add(walletNode.getAddress().toString());
if(input.getLabel() != null) {
@@ -500,7 +501,7 @@ public class TransactionDiagram extends GridPane {
} else if(input instanceof AdditionalBlockTransactionHashIndex additionalReference) {
inputValue = input.getValue();
StringJoiner joiner = new StringJoiner("\n");
- joiner.add("Spending " + getSatsValue(inputValue) + " sats from" + (isExpanded() ? ":" : " (click to expand):"));
+ joiner.add("Spending " + getCoinValue(inputValue) + " from" + (isExpanded() ? ":" : " (click to expand):"));
for(BlockTransactionHashIndex additionalInput : additionalReference.getAdditionalInputs()) {
joiner.add(getInputDescription(additionalInput));
}
@@ -513,7 +514,7 @@ public class TransactionDiagram extends GridPane {
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get((int) input.getIndex());
Address fromAddress = txOutput.getScript().getToAddress();
inputValue = txOutput.getValue();
- tooltip.setText("Input of " + getSatsValue(inputValue) + " sats\n" + input.getHashAsString() + ":" + input.getIndex() + (fromAddress != null ? "\n" + fromAddress : ""));
+ tooltip.setText("Input of " + getCoinValue(inputValue) + "\n" + input.getHashAsString() + ":" + input.getIndex() + (fromAddress != null ? "\n" + fromAddress : ""));
ContextMenu contextMenu = new LabelContextMenu(fromAddress, inputValue);
label.setContextMenu(contextMenu);
@@ -572,13 +573,22 @@ public class TransactionDiagram extends GridPane {
return input.getLabel() != null && !input.getLabel().isEmpty() ? input.getLabel() : input.getHashAsString().substring(0, 8) + "..:" + input.getIndex();
}
- String getSatsValue(long amount) {
+ String getCoinValue(long amount) {
if(Config.get().isHideAmounts()) {
return CoinLabel.HIDDEN_AMOUNT_TEXT;
}
UnitFormat format = Config.get().getUnitFormat() == null ? UnitFormat.DOT : Config.get().getUnitFormat();
- return format.formatSatsValue(amount);
+ BitcoinUnit unit = Config.get().getBitcoinUnit();
+ if(unit == null || unit.equals(BitcoinUnit.AUTO)) {
+ unit = (amount >= BitcoinUnit.getAutoThreshold() ? BitcoinUnit.BTC : BitcoinUnit.SATOSHIS);
+ }
+
+ if(unit.equals(BitcoinUnit.BTC)) {
+ return format.formatBtcValue(amount) + " BTC";
+ }
+
+ return format.formatSatsValue(amount) + " sats";
}
private Pane getInputsLines(List<Map<BlockTransactionHashIndex, WalletNode>> displayedUtxoSets) {
@@ -740,7 +750,7 @@ public class TransactionDiagram extends GridPane {
Wallet toBip47Wallet = getBip47SendWallet(payment);
DnsPayment dnsPayment = DnsPaymentCache.getDnsPayment(payment);
Tooltip recipientTooltip = new Tooltip((toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ")
- + getSatsValue(payment.getAmount()) + " sats to "
+ + getCoinValue(payment.getAmount()) + " to "
+ (payment instanceof AdditionalPayment ? (isExpanded() ? "\n" : "(click to expand)\n") + payment : (toWallet == null ? (dnsPayment == null ? (payment.getLabel() == null ? (toNode != null ? toNode : (toBip47Wallet == null ? "external address" : toBip47Wallet.getDisplayName())) : payment.getLabel()) : dnsPayment.toString()) : toWallet.getFullDisplayName()) + "\n" + payment.getDisplayAddress())
+ (walletTx.isDuplicateAddress(payment) ? " (Duplicate)" : ""));
recipientTooltip.getStyleClass().add("recipient-label");
@@ -789,7 +799,7 @@ public class TransactionDiagram extends GridPane {
Label changeLabel = new Label(changeDesc, overGapLimit ? getChangeWarningGlyph() : getChangeGlyph());
changeLabel.getStyleClass().addAll("output-label", "change-label");
changeLabel.setSkin(new AddressLabelSkin(changeLabel));
- Tooltip changeTooltip = new Tooltip("Change of " + getSatsValue(changeEntry.getValue()) + " sats to " + changeNode + "\n" + walletTx.getChangeAddress(changeNode).toString() + (overGapLimit ? "\nAddress is beyond the gap limit!" : ""));
+ Tooltip changeTooltip = new Tooltip("Change of " + getCoinValue(changeEntry.getValue()) + " to " + changeNode + "\n" + walletTx.getChangeAddress(changeNode).toString() + (overGapLimit ? "\nAddress is beyond the gap limit!" : ""));
changeTooltip.getStyleClass().add("change-label");
changeTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
changeTooltip.setShowDuration(Duration.INDEFINITE);
@@ -849,7 +859,7 @@ public class TransactionDiagram extends GridPane {
Label feeLabel = highFee ? new Label("High Fee", getFeeWarningGlyph()) : new Label("Fee", getFeeGlyph());
feeLabel.getStyleClass().addAll("output-label", "fee-label");
String percentage = walletTx.getFeePercentage() < 0.0001d ? "<0.01" : String.format("%.2f", walletTx.getFeePercentage() * 100.0);
- Tooltip feeTooltip = new Tooltip(walletTx.getFee() < 0 ? "Unknown fee" : "Fee of " + getSatsValue(walletTx.getFee()) + " sats (" + percentage + "%)");
+ Tooltip feeTooltip = new Tooltip(walletTx.getFee() < 0 ? "Unknown fee" : "Fee of " + getCoinValue(walletTx.getFee()) + " (" + percentage + "%)");
feeTooltip.getStyleClass().add("fee-tooltip");
feeTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
feeTooltip.setShowDuration(Duration.INDEFINITE);
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagramLabel.java b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagramLabel.java
index 8c62a60..e3ff77b 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagramLabel.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagramLabel.java
@@ -147,10 +147,10 @@ public class TransactionDiagramLabel extends HBox {
Glyph glyph = GlyphUtils.getOutputGlyph(transactionDiagram.getWalletTransaction(), premixOutput);
String text;
if(premixOutputs.size() == 1) {
- text = "Premix transaction with 1 output of " + transactionDiagram.getSatsValue(premixOutput.getAmount()) + " sats";
+ text = "Premix transaction with 1 output of " + transactionDiagram.getCoinValue(premixOutput.getAmount());
} else {
- text = "Premix transaction with " + premixOutputs.size() + " outputs of " + transactionDiagram.getSatsValue(premixOutput.getAmount()) + " sats each ("
- + transactionDiagram.getSatsValue(total) + " sats)";
+ text = "Premix transaction with " + premixOutputs.size() + " outputs of " + transactionDiagram.getCoinValue(premixOutput.getAmount()) + " each ("
+ + transactionDiagram.getCoinValue(total) + ")";
}
return getOutputLabel(glyph, text);
@@ -158,7 +158,7 @@ public class TransactionDiagramLabel extends HBox {
private OutputLabel getBadbankOutputLabel(TransactionDiagram transactionDiagram, Payment payment) {
Glyph glyph = GlyphUtils.getOutputGlyph(transactionDiagram.getWalletTransaction(), payment);
- String text = "Badbank change of " + transactionDiagram.getSatsValue(payment.getAmount()) + " sats to " + payment.getAddress().toString();
+ String text = "Badbank change of " + transactionDiagram.getCoinValue(payment.getAmount()) + " to " + payment.getAddress().toString();
return getOutputLabel(glyph, text);
}
@@ -167,7 +167,7 @@ public class TransactionDiagramLabel extends HBox {
long total = premixOutputs.stream().mapToLong(Payment::getAmount).sum();
double feePercentage = (double)whirlpoolFee.getAmount() / (total - whirlpoolFee.getAmount());
Glyph glyph = GlyphUtils.getOutputGlyph(transactionDiagram.getWalletTransaction(), whirlpoolFee);
- String text = "Whirlpool fee of " + transactionDiagram.getSatsValue(whirlpoolFee.getAmount()) + " sats (" + String.format("%.2f", feePercentage * 100.0) + "% of total premix value)";
+ String text = "Whirlpool fee of " + transactionDiagram.getCoinValue(whirlpoolFee.getAmount()) + " (" + String.format("%.2f", feePercentage * 100.0) + "% of total premix value)";
return getOutputLabel(glyph, text);
}
@@ -180,8 +180,8 @@ public class TransactionDiagramLabel extends HBox {
Payment remixOutput = mixOutputs.get(0);
long total = mixOutputs.stream().mapToLong(Payment::getAmount).sum();
Glyph glyph = GlyphUtils.getPremixGlyph();
- String text = "Mix transaction with " + mixOutputs.size() + " outputs of " + transactionDiagram.getSatsValue(remixOutput.getAmount()) + " sats each ("
- + transactionDiagram.getSatsValue(total) + " sats)";
+ String text = "Mix transaction with " + mixOutputs.size() + " outputs of " + transactionDiagram.getCoinValue(remixOutput.getAmount()) + " each ("
+ + transactionDiagram.getCoinValue(total) + ")";
return getOutputLabel(glyph, text);
}
@@ -194,8 +194,8 @@ public class TransactionDiagramLabel extends HBox {
Payment remixOutput = remixOutputs.get(0);
long total = remixOutputs.stream().mapToLong(Payment::getAmount).sum();
Glyph glyph = GlyphUtils.getPremixGlyph();
- String text = "Remix transaction with " + remixOutputs.size() + " outputs of " + transactionDiagram.getSatsValue(remixOutput.getAmount()) + " sats each ("
- + transactionDiagram.getSatsValue(total) + " sats)";
+ String text = "Remix transaction with " + remixOutputs.size() + " outputs of " + transactionDiagram.getCoinValue(remixOutput.getAmount()) + " each ("
+ + transactionDiagram.getCoinValue(total) + ")";
return getOutputLabel(glyph, text);
}
@@ -206,7 +206,7 @@ public class TransactionDiagramLabel extends HBox {
WalletNode toNode = payment instanceof WalletNodePayment walletNodePayment ? walletNodePayment.getWalletNode() : null;
Glyph glyph = GlyphUtils.getOutputGlyph(transactionDiagram.getWalletTransaction(), payment);
- String text = (toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ") + transactionDiagram.getSatsValue(payment.getAmount()) + " sats to " + payment;
+ String text = (toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ") + transactionDiagram.getCoinValue(payment.getAmount()) + " to " + payment;
return getOutputLabel(glyph, text);
}
@@ -215,7 +215,7 @@ public class TransactionDiagramLabel extends HBox {
WalletTransaction walletTx = transactionDiagram.getWalletTransaction();
Glyph glyph = GlyphUtils.getChangeGlyph();
- String text = "Change of " + transactionDiagram.getSatsValue(changeEntry.getValue()) + " sats to " + walletTx.getChangeAddress(changeEntry.getKey()).toString();
+ String text = "Change of " + transactionDiagram.getCoinValue(changeEntry.getValue()) + " to " + walletTx.getChangeAddress(changeEntry.getKey()).toString();
return getOutputLabel(glyph, text);
}
@@ -228,7 +228,7 @@ public class TransactionDiagramLabel extends HBox {
Glyph glyph = GlyphUtils.getFeeGlyph();
String percentage = walletTx.getFeePercentage() < 0.0001d ? "<0.01" : String.format("%.2f", walletTx.getFeePercentage() * 100.0);
- String text = "Fee of " + transactionDiagram.getSatsValue(walletTx.getFee()) + " sats (" + percentage + "%)";
+ String text = "Fee of " + transactionDiagram.getCoinValue(walletTx.getFee()) + " (" + percentage + "%)";
return getOutputLabel(glyph, text);
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
index ce2bc47..87a1de4 100644
--- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java
@@ -1529,6 +1529,7 @@ public class HeadersController extends TransactionFormController implements Init
@Subscribe
public void unitFormatChanged(UnitFormatChangedEvent event) {
+ transactionDiagram.update(transactionDiagram.getWalletTransaction());
fee.refresh(event.getUnitFormat(), event.getBitcoinUnit());
}
diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java
index b81c0cb..286cee8 100644
--- a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java
@@ -1523,6 +1523,7 @@ public class SendController extends WalletFormController implements Initializabl
@Subscribe
public void unitFormatChanged(UnitFormatChangedEvent event) {
+ transactionDiagram.update(transactionDiagram.getWalletTransaction());
setEffectiveFeeRate(getWalletTransaction());
setFeeRate(getFeeRate());
if(fee.getTextFormatter() instanceof CoinTextFormatter coinTextFormatter && coinTextFormatter.getUnitFormat() != event.getUnitFormat()) {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.