Transaltions for Send tab

This commit is contained in:
Anurag Lint 2024-10-12 10:41:49 +02:00
parent 87f2fbcbb3
commit bcffa0a681
7 changed files with 191 additions and 59 deletions

View file

@ -14,6 +14,7 @@ import com.sparrowwallet.sparrow.event.ExcludeUtxoEvent;
import com.sparrowwallet.sparrow.event.ReplaceChangeAddressEvent; import com.sparrowwallet.sparrow.event.ReplaceChangeAddressEvent;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
import com.sparrowwallet.sparrow.glyphfont.GlyphUtils; import com.sparrowwallet.sparrow.glyphfont.GlyphUtils;
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
import com.sparrowwallet.sparrow.io.Config; import com.sparrowwallet.sparrow.io.Config;
import com.sparrowwallet.sparrow.wallet.OptimizationStrategy; import com.sparrowwallet.sparrow.wallet.OptimizationStrategy;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
@ -806,7 +807,7 @@ public class TransactionDiagram extends GridPane {
txPane.setAlignment(Pos.CENTER); txPane.setAlignment(Pos.CENTER);
txPane.getChildren().add(createSpacer()); txPane.getChildren().add(createSpacer());
String txDesc = "Transaction"; String txDesc = LanguagesManager.getMessage("diagram.transaction");
Label txLabel = new Label(txDesc); Label txLabel = new Label(txDesc);
boolean isFinalized = walletTx.getTransaction().hasScriptSigs() || walletTx.getTransaction().hasWitnesses(); boolean isFinalized = walletTx.getTransaction().hasScriptSigs() || walletTx.getTransaction().hasWitnesses();
Tooltip tooltip = new Tooltip(walletTx.getTransaction().getLength() + " bytes\n" Tooltip tooltip = new Tooltip(walletTx.getTransaction().getLength() + " bytes\n"

View file

@ -20,6 +20,7 @@ import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.control.*;
import com.sparrowwallet.sparrow.event.*; import com.sparrowwallet.sparrow.event.*;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
import com.sparrowwallet.sparrow.i18n.LanguagesManager;
import com.sparrowwallet.sparrow.io.Config; import com.sparrowwallet.sparrow.io.Config;
import com.sparrowwallet.sparrow.io.Storage; import com.sparrowwallet.sparrow.io.Storage;
import com.sparrowwallet.sparrow.net.*; import com.sparrowwallet.sparrow.net.*;
@ -356,7 +357,7 @@ public class SendController extends WalletFormController implements Initializabl
}); });
utxoLabelSelectionProperty.addListener((observable, oldValue, newValue) -> { utxoLabelSelectionProperty.addListener((observable, oldValue, newValue) -> {
clearButton.setText("Clear" + newValue); clearButton.setText(LanguagesManager.getMessage("wallet.send.clear") + newValue);
}); });
utxoSelectorProperty.addListener((observable, oldValue, utxoSelector) -> { utxoSelectorProperty.addListener((observable, oldValue, utxoSelector) -> {
@ -475,7 +476,7 @@ public class SendController extends WalletFormController implements Initializabl
Tab tab = new Tab(" " + (highestTabNo.isPresent() ? highestTabNo.getAsInt() + 1 : 1) + " "); Tab tab = new Tab(" " + (highestTabNo.isPresent() ? highestTabNo.getAsInt() + 1 : 1) + " ");
try { try {
FXMLLoader paymentLoader = new FXMLLoader(AppServices.class.getResource("wallet/payment.fxml")); FXMLLoader paymentLoader = new FXMLLoader(AppServices.class.getResource("wallet/payment.fxml"), LanguagesManager.getResourceBundle());
tab.setContent(paymentLoader.load()); tab.setContent(paymentLoader.load());
PaymentController controller = paymentLoader.getController(); PaymentController controller = paymentLoader.getController();
controller.setSendController(this); controller.setSendController(this);
@ -896,8 +897,8 @@ public class SendController extends WalletFormController implements Initializabl
if(targetBlocksFeeRates.get(Integer.MAX_VALUE) != null) { if(targetBlocksFeeRates.get(Integer.MAX_VALUE) != null) {
Double minFeeRate = targetBlocksFeeRates.get(Integer.MAX_VALUE); Double minFeeRate = targetBlocksFeeRates.get(Integer.MAX_VALUE);
if(minFeeRate > 1.0 && feeRateAmt < minFeeRate) { if(minFeeRate > 1.0 && feeRateAmt < minFeeRate) {
feeRatePriority.setText("Below Minimum"); feeRatePriority.setText(LanguagesManager.getMessage("wallet.send.fee.rate.below-minimum"));
feeRatePriority.setTooltip(new Tooltip("Transactions at this fee rate are currently being purged from the default sized mempool")); feeRatePriority.setTooltip(new Tooltip(LanguagesManager.getMessage("wallet.send.fee.rate.below-minimum.tooltip")));
feeRatePriorityGlyph.setStyle("-fx-text-fill: #a0a1a7cc"); feeRatePriorityGlyph.setStyle("-fx-text-fill: #a0a1a7cc");
feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.EXCLAMATION_CIRCLE); feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.EXCLAMATION_CIRCLE);
return; return;
@ -905,8 +906,8 @@ public class SendController extends WalletFormController implements Initializabl
Double lowestBlocksRate = targetBlocksFeeRates.get(TARGET_BLOCKS_RANGE.get(TARGET_BLOCKS_RANGE.size() - 1)); Double lowestBlocksRate = targetBlocksFeeRates.get(TARGET_BLOCKS_RANGE.get(TARGET_BLOCKS_RANGE.size() - 1));
if(lowestBlocksRate >= minFeeRate && feeRateAmt < (minFeeRate + ((lowestBlocksRate - minFeeRate) / 2)) && !isPayjoinTx()) { if(lowestBlocksRate >= minFeeRate && feeRateAmt < (minFeeRate + ((lowestBlocksRate - minFeeRate) / 2)) && !isPayjoinTx()) {
feeRatePriority.setText("Try Then Replace"); feeRatePriority.setText(LanguagesManager.getMessage("wallet.send.fee.rate.replace"));
feeRatePriority.setTooltip(new Tooltip("Send a transaction, verify it appears in the destination wallet, then RBF to get it confirmed or sent to another address")); feeRatePriority.setTooltip(new Tooltip(LanguagesManager.getMessage("wallet.send.fee.rate.replace.tooltip")));
feeRatePriorityGlyph.setStyle("-fx-text-fill: #7eb7c9cc"); feeRatePriorityGlyph.setStyle("-fx-text-fill: #7eb7c9cc");
feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.PLUS_CIRCLE); feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.PLUS_CIRCLE);
return; return;
@ -918,24 +919,24 @@ public class SendController extends WalletFormController implements Initializabl
Double maxFeeRate = FEE_RATES_RANGE.get(FEE_RATES_RANGE.size() - 1).doubleValue(); Double maxFeeRate = FEE_RATES_RANGE.get(FEE_RATES_RANGE.size() - 1).doubleValue();
Double highestBlocksRate = targetBlocksFeeRates.get(TARGET_BLOCKS_RANGE.get(0)); Double highestBlocksRate = targetBlocksFeeRates.get(TARGET_BLOCKS_RANGE.get(0));
if(highestBlocksRate < maxFeeRate && feeRateAmt > (highestBlocksRate + ((maxFeeRate - highestBlocksRate) / 10))) { if(highestBlocksRate < maxFeeRate && feeRateAmt > (highestBlocksRate + ((maxFeeRate - highestBlocksRate) / 10))) {
feeRatePriority.setText("Overpaid"); feeRatePriority.setText(LanguagesManager.getMessage("wallet.send.fee.rate.overpaid"));
feeRatePriority.setTooltip(new Tooltip("Transaction fees at this rate are likely higher than necessary")); feeRatePriority.setTooltip(new Tooltip(LanguagesManager.getMessage("wallet.send.fee.rate.overpaid.tooltip")));
feeRatePriorityGlyph.setStyle("-fx-text-fill: #c8416499"); feeRatePriorityGlyph.setStyle("-fx-text-fill: #c8416499");
feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.EXCLAMATION_CIRCLE); feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.EXCLAMATION_CIRCLE);
} else { } else {
feeRatePriority.setText("High Priority"); feeRatePriority.setText(LanguagesManager.getMessage("wallet.send.fee.rate.high-priority"));
feeRatePriority.setTooltip(new Tooltip("Typically confirms within minutes")); feeRatePriority.setTooltip(new Tooltip(LanguagesManager.getMessage("wallet.send.fee.rate.high-priority.tooltip")));
feeRatePriorityGlyph.setStyle("-fx-text-fill: #c8416499"); feeRatePriorityGlyph.setStyle("-fx-text-fill: #c8416499");
feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.CIRCLE); feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.CIRCLE);
} }
} else if(targetBlocks < FeeRatesSource.BLOCKS_IN_HOUR) { } else if(targetBlocks < FeeRatesSource.BLOCKS_IN_HOUR) {
feeRatePriority.setText("Medium Priority"); feeRatePriority.setText(LanguagesManager.getMessage("wallet.send.fee.rate.medium-priority"));
feeRatePriority.setTooltip(new Tooltip("Typically confirms within an hour or two")); feeRatePriority.setTooltip(new Tooltip(LanguagesManager.getMessage("wallet.send.fee.rate.medium-priority.tooltip")));
feeRatePriorityGlyph.setStyle("-fx-text-fill: #fba71b99"); feeRatePriorityGlyph.setStyle("-fx-text-fill: #fba71b99");
feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.CIRCLE); feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.CIRCLE);
} else { } else {
feeRatePriority.setText("Low Priority"); feeRatePriority.setText(LanguagesManager.getMessage("wallet.send.fee.rate.low-priority"));
feeRatePriority.setTooltip(new Tooltip("Typically confirms in a day or longer")); feeRatePriority.setTooltip(new Tooltip(LanguagesManager.getMessage("wallet.send.fee.rate.low-priority.tooltip")));
feeRatePriorityGlyph.setStyle("-fx-text-fill: #41a9c999"); feeRatePriorityGlyph.setStyle("-fx-text-fill: #41a9c999");
feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.CIRCLE); feeRatePriorityGlyph.setIcon(FontAwesome5.Glyph.CIRCLE);
} }
@ -963,11 +964,11 @@ public class SendController extends WalletFormController implements Initializabl
private void updateMaxClearButtons(UtxoSelector utxoSelector, TxoFilter txoFilter) { private void updateMaxClearButtons(UtxoSelector utxoSelector, TxoFilter txoFilter) {
if(utxoSelector instanceof PresetUtxoSelector presetUtxoSelector) { if(utxoSelector instanceof PresetUtxoSelector presetUtxoSelector) {
int num = presetUtxoSelector.getPresetUtxos().size(); int num = presetUtxoSelector.getPresetUtxos().size();
String selection = " (" + num + " UTXO" + (num != 1 ? "s" : "") + " selected)"; String selection = " (" + num + " UTXO" + (num != 1 ? "s" : "") + " " + LanguagesManager.getMessage("common.selected") + ")";
utxoLabelSelectionProperty.set(selection); utxoLabelSelectionProperty.set(selection);
} else if(txoFilter instanceof ExcludeTxoFilter excludeTxoFilter) { } else if(txoFilter instanceof ExcludeTxoFilter excludeTxoFilter) {
int num = excludeTxoFilter.getExcludedTxos().size(); int num = excludeTxoFilter.getExcludedTxos().size();
String exclusion = " (" + num + " UTXO" + (num != 1 ? "s" : "") + " excluded)"; String exclusion = " (" + num + " UTXO" + (num != 1 ? "s" : "") + " " + LanguagesManager.getMessage("common.excluded") + ")";
utxoLabelSelectionProperty.set(exclusion); utxoLabelSelectionProperty.set(exclusion);
} else { } else {
utxoLabelSelectionProperty.set(""); utxoLabelSelectionProperty.set("");
@ -1579,38 +1580,38 @@ public class SendController extends WalletFormController implements Initializabl
if(optimizationStrategy == OptimizationStrategy.PRIVACY) { if(optimizationStrategy == OptimizationStrategy.PRIVACY) {
if(fakeMixPresent) { if(fakeMixPresent) {
addLabel("Appears as a two person coinjoin", getPlusGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.coinjoin"), getPlusGlyph());
} else { } else {
if(mixedAddressTypes) { if(mixedAddressTypes) {
addLabel("Cannot fake coinjoin due to mixed address types", getInfoGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.coinjoin.mixes-address-types"), getInfoGlyph());
} else if(userPayments.size() > 1) { } else if(userPayments.size() > 1) {
addLabel("Cannot fake coinjoin due to multiple payments", getInfoGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.coinjoin.multiple-payments"), getInfoGlyph());
} else if(payjoinPresent) { } else if(payjoinPresent) {
addLabel("Cannot fake coinjoin due to payjoin", getInfoGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.coinjoin.payjoin"), getInfoGlyph());
} else { } else {
if(utxoSelectorProperty().get() != null) { if(utxoSelectorProperty().get() != null) {
addLabel("Cannot fake coinjoin due to coin control", getInfoGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.coinjoin.coincontrol"), getInfoGlyph());
} else { } else {
addLabel("Cannot fake coinjoin due to insufficient funds", getInfoGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.coinjoin.insufficient-funds"), getInfoGlyph());
} }
} }
} }
} }
if(mixedAddressTypes) { if(mixedAddressTypes) {
addLabel("Address types different to the wallet indicate external payments", getMinusGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.mixes-address-types"), getMinusGlyph());
} }
if(roundPaymentAmounts && !fakeMixPresent) { if(roundPaymentAmounts && !fakeMixPresent) {
addLabel("Rounded payment amounts indicate external payments", getMinusGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.external-payments"), getMinusGlyph());
} }
if(addressReuse) { if(addressReuse) {
addLabel("Address reuse detected", getMinusGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.reuse"), getMinusGlyph());
} }
if(!fakeMixPresent && !mixedAddressTypes && !roundPaymentAmounts) { if(!fakeMixPresent && !mixedAddressTypes && !roundPaymentAmounts) {
addLabel("Appears as a possible self transfer", getPlusGlyph()); addLabel(LanguagesManager.getMessage("wallet.send.optimize.self-transfer"), getPlusGlyph());
} }
analysisLabels.sort(Comparator.comparingInt(o -> (Integer)o.getGraphic().getUserData())); analysisLabels.sort(Comparator.comparingInt(o -> (Integer)o.getGraphic().getUserData()));

View file

@ -30,24 +30,24 @@
</rowConstraints> </rowConstraints>
<Form GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2"> <Form GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2">
<Fieldset inputGrow="ALWAYS"> <Fieldset inputGrow="ALWAYS">
<Field text="Pay to:"> <Field text="%wallet.send.pay-to">
<StackPane> <StackPane>
<ComboBox fx:id="openWallets" /> <ComboBox fx:id="openWallets" />
<ComboBoxTextField fx:id="address" styleClass="address-text-field" comboProperty="$openWallets"> <ComboBoxTextField fx:id="address" styleClass="address-text-field" comboProperty="$openWallets">
<tooltip> <tooltip>
<Tooltip text="Address, payment code or bitcoin: URI"/> <Tooltip text="%wallet.send.pay-to.tooltip"/>
</tooltip> </tooltip>
</ComboBoxTextField> </ComboBoxTextField>
</StackPane> </StackPane>
</Field> </Field>
<Field text="Label:"> <Field text="%wallet.send.label">
<TextField fx:id="label" promptText="Required"> <TextField fx:id="label" promptText="%wallet.send.label.required">
<tooltip> <tooltip>
<Tooltip text="Required to label the transaction (privately in this wallet)"/> <Tooltip text="%wallet.send.label.tooltip"/>
</tooltip> </tooltip>
</TextField> </TextField>
</Field> </Field>
<Field text="Amount:"> <Field text="%wallet.send.amount">
<TextField fx:id="amount" styleClass="amount-field" /> <TextField fx:id="amount" styleClass="amount-field" />
<ComboBox fx:id="amountUnit" styleClass="amount-unit"> <ComboBox fx:id="amountUnit" styleClass="amount-unit">
<items> <items>
@ -60,17 +60,17 @@
<Label style="-fx-pref-width: 15" /> <Label style="-fx-pref-width: 15" />
<FiatLabel fx:id="fiatAmount" /> <FiatLabel fx:id="fiatAmount" />
<Group managed="false" translateY="38"> <Group managed="false" translateY="38">
<Label fx:id="amountStatus" text="Insufficient funds"> <Label fx:id="amountStatus" text="%wallet.send.amount.insuficient">
<tooltip> <tooltip>
<Tooltip text="Insufficient confirmed transaction value" /> <Tooltip text="%wallet.send.amount.insuficient.tootip" />
</tooltip> </tooltip>
<graphic> <graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="EXCLAMATION_CIRCLE" styleClass="failure" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="EXCLAMATION_CIRCLE" styleClass="failure" />
</graphic> </graphic>
</Label> </Label>
<Label fx:id="dustStatus" text="Amount too low"> <Label fx:id="dustStatus" text="%wallet.send.amount.dust">
<tooltip> <tooltip>
<Tooltip text="Amount below the Bitcoin network dust threshold for this address type" /> <Tooltip text="%wallet.send.amount.dust.tooltip" />
</tooltip> </tooltip>
<graphic> <graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="EXCLAMATION_CIRCLE" styleClass="failure" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="EXCLAMATION_CIRCLE" styleClass="failure" />
@ -91,7 +91,7 @@
</graphic> </graphic>
</Button> </Button>
<Region HBox.hgrow="ALWAYS" /> <Region HBox.hgrow="ALWAYS" />
<Button fx:id="addPaymentButton" text="Add" onAction="#addPayment" prefHeight="30"> <Button fx:id="addPaymentButton" text="%wallet.send.pay-to.add-address" onAction="#addPayment" prefHeight="30">
<graphic> <graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="PLUS" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="PLUS" />
</graphic> </graphic>

View file

@ -45,7 +45,7 @@
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="3"> <BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="3">
<top> <top>
<Form styleClass="title-form"> <Form styleClass="title-form">
<Fieldset inputGrow="ALWAYS" text="Send"/> <Fieldset inputGrow="ALWAYS" text="%wallet.send"/>
</Form> </Form>
</top> </top>
<center> <center>
@ -53,7 +53,7 @@
</center> </center>
</BorderPane> </BorderPane>
<Form styleClass="title-form" GridPane.columnIndex="0" GridPane.rowIndex="1"> <Form styleClass="title-form" GridPane.columnIndex="0" GridPane.rowIndex="1">
<Fieldset inputGrow="ALWAYS" text="Fee"/> <Fieldset inputGrow="ALWAYS" text="%wallet.send.fee"/>
</Form> </Form>
<HBox GridPane.columnIndex="1" GridPane.rowIndex="1" GridPane.columnSpan="2" GridPane.halignment="RIGHT" alignment="CENTER_RIGHT"> <HBox GridPane.columnIndex="1" GridPane.rowIndex="1" GridPane.columnSpan="2" GridPane.halignment="RIGHT" alignment="CENTER_RIGHT">
<padding> <padding>
@ -64,17 +64,17 @@
<ToggleGroup fx:id="feeSelectionToggleGroup" /> <ToggleGroup fx:id="feeSelectionToggleGroup" />
</toggleGroup> </toggleGroup>
<buttons> <buttons>
<ToggleButton fx:id="targetBlocksToggle" text="Target Blocks" toggleGroup="$feeSelectionToggleGroup"> <ToggleButton fx:id="targetBlocksToggle" text="%wallet.send.fee.target-block" toggleGroup="$feeSelectionToggleGroup">
<tooltip> <tooltip>
<Tooltip text="Determine fee via estimated number of blocks"/> <Tooltip text="%wallet.send.fee.target-block.tooltip"/>
</tooltip> </tooltip>
<userData> <userData>
<FeeRatesSelection fx:constant="BLOCK_TARGET"/> <FeeRatesSelection fx:constant="BLOCK_TARGET"/>
</userData> </userData>
</ToggleButton> </ToggleButton>
<ToggleButton fx:id="mempoolSizeToggle" text="Mempool Size" toggleGroup="$feeSelectionToggleGroup"> <ToggleButton fx:id="mempoolSizeToggle" text="%wallet.send.fee.mempool-size" toggleGroup="$feeSelectionToggleGroup">
<tooltip> <tooltip>
<Tooltip text="Determine fee via current mempool size"/> <Tooltip text="%wallet.send.fee.mempool-size.tooltip"/>
</tooltip> </tooltip>
<userData> <userData>
<FeeRatesSelection fx:constant="MEMPOOL_SIZE"/> <FeeRatesSelection fx:constant="MEMPOOL_SIZE"/>
@ -85,13 +85,13 @@
</HBox> </HBox>
<Form GridPane.columnIndex="0" GridPane.rowIndex="2"> <Form GridPane.columnIndex="0" GridPane.rowIndex="2">
<Fieldset inputGrow="SOMETIMES"> <Fieldset inputGrow="SOMETIMES">
<Field fx:id="targetBlocksField" text="Blocks:"> <Field fx:id="targetBlocksField" text="%wallet.send.fee.blocks">
<Slider fx:id="targetBlocks" snapToTicks="true" showTickLabels="true" showTickMarks="true" /> <Slider fx:id="targetBlocks" snapToTicks="true" showTickLabels="true" showTickMarks="true" />
</Field> </Field>
<Field fx:id="feeRangeField" text="Range:"> <Field fx:id="feeRangeField" text="%wallet.send.fee.range">
<FeeRangeSlider fx:id="feeRange" /> <FeeRangeSlider fx:id="feeRange" />
</Field> </Field>
<Field fx:id="feeRateField" text="Rate:"> <Field fx:id="feeRateField" text="%wallet.send.fee.rate">
<CopyableLabel fx:id="feeRate" /> <CopyableLabel fx:id="feeRate" />
<Label fx:id="cpfpFeeRate" text="CPFP"> <Label fx:id="cpfpFeeRate" text="CPFP">
<graphic> <graphic>
@ -108,7 +108,7 @@
</graphic> </graphic>
</Label> </Label>
</Field> </Field>
<Field text="Fee:"> <Field text="%wallet.send.fee.fee">
<TextField fx:id="fee" styleClass="amount-field"/> <TextField fx:id="fee" styleClass="amount-field"/>
<ComboBox fx:id="feeAmountUnit" styleClass="amount-unit"> <ComboBox fx:id="feeAmountUnit" styleClass="amount-unit">
<items> <items>
@ -153,23 +153,23 @@
<Insets left="25.0" right="25.0" bottom="25.0" /> <Insets left="25.0" right="25.0" bottom="25.0" />
</padding> </padding>
<HBox AnchorPane.leftAnchor="5" alignment="CENTER_LEFT"> <HBox AnchorPane.leftAnchor="5" alignment="CENTER_LEFT">
<Label text="Optimize:" styleClass="buttonRowLabel" /> <Label text="%wallet.send.optimize" styleClass="buttonRowLabel" />
<SegmentedButton> <SegmentedButton>
<toggleGroup> <toggleGroup>
<ToggleGroup fx:id="optimizationToggleGroup" /> <ToggleGroup fx:id="optimizationToggleGroup" />
</toggleGroup> </toggleGroup>
<buttons> <buttons>
<ToggleButton fx:id="efficiencyToggle" text="Efficiency" toggleGroup="$optimizationToggleGroup"> <ToggleButton fx:id="efficiencyToggle" text="%wallet.send.optimize.efficiency" toggleGroup="$optimizationToggleGroup">
<tooltip> <tooltip>
<Tooltip text="Smallest transaction size for lowest fees"/> <Tooltip text="%wallet.send.optimize.efficiency.tootip"/>
</tooltip> </tooltip>
<userData> <userData>
<OptimizationStrategy fx:constant="EFFICIENCY"/> <OptimizationStrategy fx:constant="EFFICIENCY"/>
</userData> </userData>
</ToggleButton> </ToggleButton>
<ToggleButton fx:id="privacyToggle" text="Privacy" toggleGroup="$optimizationToggleGroup"> <ToggleButton fx:id="privacyToggle" text="%wallet.send.optimize.privacy" toggleGroup="$optimizationToggleGroup">
<tooltip> <tooltip>
<Tooltip text="Higher entropy transactions that reduce probabilities in blockchain analysis"/> <Tooltip text="%wallet.send.optimize.privacy.tooltip"/>
</tooltip> </tooltip>
<userData> <userData>
<OptimizationStrategy fx:constant="PRIVACY"/> <OptimizationStrategy fx:constant="PRIVACY"/>
@ -177,22 +177,22 @@
</ToggleButton> </ToggleButton>
</buttons> </buttons>
</SegmentedButton> </SegmentedButton>
<HelpLabel fx:id="optimizationHelp" helpText="Determines whether to optimize the transaction for low fees or greater privacy" /> <HelpLabel fx:id="optimizationHelp" helpText="%wallet.send.optimize.help" />
<Label fx:id="privacyAnalysis" graphicTextGap="5" text="Analysis..." styleClass="help-label"> <Label fx:id="privacyAnalysis" graphicTextGap="5" text="%wallet.send.optimize.analysis" styleClass="help-label">
<graphic> <graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="11" icon="INFO_CIRCLE" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="11" icon="INFO_CIRCLE" />
</graphic> </graphic>
</Label> </Label>
</HBox> </HBox>
<HBox AnchorPane.rightAnchor="10"> <HBox AnchorPane.rightAnchor="10">
<Button fx:id="clearButton" text="Clear" cancelButton="true" onAction="#clear" /> <Button fx:id="clearButton" text="%wallet.send.clear" cancelButton="true" onAction="#clear" />
<Region HBox.hgrow="ALWAYS" style="-fx-min-width: 20px" /> <Region HBox.hgrow="ALWAYS" style="-fx-min-width: 20px" />
<Button fx:id="notificationButton" text="Broadcast Notification" contentDisplay="RIGHT" graphicTextGap="5" onAction="#broadcastNotification"> <Button fx:id="notificationButton" text="%wallet.send.broadcast-notification" contentDisplay="RIGHT" graphicTextGap="5" onAction="#broadcastNotification">
<graphic> <graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="SATELLITE_DISH" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="SATELLITE_DISH" />
</graphic> </graphic>
</Button> </Button>
<Button fx:id="createButton" text="Create Transaction" defaultButton="true" disable="true" contentDisplay="RIGHT" graphicTextGap="5" onAction="#createTransaction"> <Button fx:id="createButton" text="%wallet.send.create-transaction" defaultButton="true" disable="true" contentDisplay="RIGHT" graphicTextGap="5" onAction="#createTransaction">
<graphic> <graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="ANGLE_DOUBLE_RIGHT" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="12" icon="ANGLE_DOUBLE_RIGHT" />
</graphic> </graphic>

View file

@ -22,7 +22,7 @@
<Function fx:constant="TRANSACTIONS"/> <Function fx:constant="TRANSACTIONS"/>
</userData> </userData>
</ToggleButton> </ToggleButton>
<ToggleButton VBox.vgrow="ALWAYS" text="Send" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity" toggleGroup="$walletMenu"> <ToggleButton VBox.vgrow="ALWAYS" text="%wallet.send" contentDisplay="TOP" styleClass="list-item" maxHeight="Infinity" toggleGroup="$walletMenu">
<graphic> <graphic>
<Glyph fontFamily="FontAwesome" icon="SEND" fontSize="20" /> <Glyph fontFamily="FontAwesome" icon="SEND" fontSize="20" />
</graphic> </graphic>

View file

@ -1,3 +1,7 @@
#common
common.selected=selected
common.excluded=excluded
#welcome #welcome
welcome.title=Welcome to Sparrow welcome.title=Welcome to Sparrow
welcome.step1.introduction=Introduction welcome.step1.introduction=Introduction
@ -28,6 +32,9 @@ welcome.configure-server=Configure Server
welcome.done=Done welcome.done=Done
welcome.configure-later=Later or Offline Mode welcome.configure-later=Later or Offline Mode
#Wallet common
wallet.deposit=Deposit
# wallet transactions # wallet transactions
wallet.transactions=Transactions wallet.transactions=Transactions
wallet.transactions.balance=Balance: wallet.transactions.balance=Balance:
@ -51,6 +58,64 @@ wallet.transactions.table.loading=Loading transactions...
wallet.transactions.table.loading.error=Error loading transactions: wallet.transactions.table.loading.error=Error loading transactions:
wallet.transactions.table.no-transactions=No transactions wallet.transactions.table.no-transactions=No transactions
# wallet send
wallet.send=Send
wallet.send.pay-to=Pay to:
wallet.send.pay-to.tooltip=Address, payment code or bitcoin: URI
wallet.send.pay-to.add-address=Add
wallet.send.label=Label:
wallet.send.label.tooltip=Required to label the transaction (privately in this wallet)
wallet.send.label.required=Required
wallet.send.amount=Amount:
wallet.send.amount.insuficient=Insufficient funds
wallet.send.amount.insuficient.tootip=Insufficient confirmed transaction value
wallet.send.amount.dust=Amount too low
wallet.send.amount.dust.tooltip=Amount below the Bitcoin network dust threshold for this address type
wallet.send.fee=Fee
wallet.send.fee.target-block=Target Blocks
wallet.send.fee.target-block.tooltip=Determine fee via estimated number of blocks
wallet.send.fee.mempool-size=Mempool Size
wallet.send.fee.mempool-size.tooltip=Determine fee via current mempool size
wallet.send.fee.blocks=Blocks:
wallet.send.fee.range=Range:
wallet.send.fee.rate=Rate:
wallet.send.fee.rate.below-minimum=Below Minimum
wallet.send.fee.rate.below-minimum.tooltip=Transactions at this fee rate are currently being purged from the default sized mempool
wallet.send.fee.rate.replace=Try Then Replace
wallet.send.fee.rate.replace.tooltip=Send a transaction, verify it appears in the destination wallet, then RBF to get it confirmed or sent to another address
wallet.send.fee.rate.overpaid=Overpaid
wallet.send.fee.rate.overpaid.tooltip=Transaction fees at this rate are likely higher than necessary
wallet.send.fee.rate.high-priority=High Priority
wallet.send.fee.rate.high-priority.tooltip=Typically confirms within minutes
wallet.send.fee.rate.medium-priority=Medium Priority
wallet.send.fee.rate.medium-priority.tooltip=Typically confirms within an hour or two
wallet.send.fee.rate.low-priority=Low Priority
wallet.send.fee.rate.low-priority.tooltip=Typically confirms in a day or longer
wallet.send.fee.fee=Fee:
wallet.send.optimize=Optimize:
wallet.send.optimize.efficiency=Efficiency
wallet.send.optimize.efficiency.tootip=Smallest transaction size for lowest fees
wallet.send.optimize.privacy=Privacy
wallet.send.optimize.privacy.tooltip=Higher entropy transactions that reduce probabilities in blockchain analysis
wallet.send.optimize.help=Determines whether to optimize the transaction for low fees or greater privacy
wallet.send.optimize.analysis=Analysis...
wallet.send.optimize.coinjoin=Appears as a two person coinjoin
wallet.send.optimize.coinjoin.mixes-address-types=Cannot fake coinjoin due to mixed address types
wallet.send.optimize.coinjoin.multiple-payments=Cannot fake coinjoin due to multiple payments
wallet.send.optimize.coinjoin.payjoin=Cannot fake coinjoin due to payjoin
wallet.send.optimize.coinjoin.coincontrol=Cannot fake coinjoin due to coin control
wallet.send.optimize.coinjoin.insufficient-funds=Cannot fake coinjoin due to insufficient funds
wallet.send.optimize.mixes-address-types=Address types different to the wallet indicate external payments
wallet.send.optimize.external-payments=Rounded payment amounts indicate external payments
wallet.send.optimize.reuse=Address reuse detected
wallet.send.optimize.self-transfer=Appears as a possible self transfer
wallet.send.clear=Clear
wallet.send.broadcast-notification=Broadcast Notification
wallet.send.create-transaction=Create Transaction
# Transaction diagram
diagram.transaction=Transaction
# settings # settings
language=Language language=Language
language.en=English language.en=English

View file

@ -1,3 +1,7 @@
#common
common.selected=seleccionados
common.excluded=excluídos
#welcome #welcome
welcome.title=Bienvenido a Sparrow welcome.title=Bienvenido a Sparrow
welcome.step1.introduction=Introducción welcome.step1.introduction=Introducción
@ -28,6 +32,9 @@ welcome.configure-server=Configurar Servidor
welcome.done=Hecho welcome.done=Hecho
welcome.configure-later=Después o Modo Sin Conexción welcome.configure-later=Después o Modo Sin Conexción
#Wallet common
wallet.deposit=Depósito
# wallet transactions # wallet transactions
wallet.transactions=Transacciones wallet.transactions=Transacciones
wallet.transactions.balance=Saldo: wallet.transactions.balance=Saldo:
@ -51,6 +58,64 @@ wallet.transactions.table.loading=Cargando transacciones...
wallet.transactions.table.loading.error=Error cargando transacciones: wallet.transactions.table.loading.error=Error cargando transacciones:
wallet.transactions.table.no-transactions=Sin transacciones wallet.transactions.table.no-transactions=Sin transacciones
# wallet send
wallet.send=Enviar
wallet.send.pay-to=Pagar a:
wallet.send.pay-to.tooltip=Dirección, código de pago o bitcoin: URI
wallet.send.pay-to.add-address=Añadir
wallet.send.label=Etiqueta:
wallet.send.label.tooltip=Obligatorio etiquetar la transacción (privado para esta wallet)
wallet.send.label.required=Obligatorio
wallet.send.amount=Cantidad:
wallet.send.amount.insuficient=Fondos insuficientes
wallet.send.amount.insuficient.tootip=Valor de transacción confirmado insuficiente
wallet.send.amount.dust=Cantidad demasiado baja
wallet.send.amount.dust.tooltip=Cantidad por debajo del umbral de polvo de la red Bitcoin para este tipo de dirección
wallet.send.fee=Comisión
wallet.send.fee.target-block=Bloques objetivo
wallet.send.fee.target-block.tooltip=Determina la comisión en función del número estimado de bloques
wallet.send.fee.mempool-size=Tamaño Mempool
wallet.send.fee.mempool-size.tooltip=Determina la comisión en función del tamaño actual de la mempool
wallet.send.fee.blocks=Bloques:
wallet.send.fee.range=Rango:
wallet.send.fee.rate=Ratio:
wallet.send.fee.rate.below-minimum=Por debajo del mínimo
wallet.send.fee.rate.below-minimum.tooltip=Las transacciones con esta tasa de comisión están siendo eliminadas del mempool con tamaño predeterminado
wallet.send.fee.rate.replace=Probar y luego Reemplazar
wallet.send.fee.rate.replace.tooltip=Envía una transacción, verifica que aparezca en la billetera de destino, luego usa RBF para que se confirme o se envíe a otra dirección
wallet.send.fee.rate.overpaid=Sobrepago
wallet.send.fee.rate.overpaid.tooltip=Las comisiones de transacción a esta tasa probablemente son más altas de lo necesario
wallet.send.fee.rate.high-priority=Alta Prioridad
wallet.send.fee.rate.high-priority.tooltip=Normalmente se confirma en minutos
wallet.send.fee.rate.medium-priority=Prioridad Media
wallet.send.fee.rate.medium-priority.tooltip=Normalmente se confirma en una o dos horas
wallet.send.fee.rate.low-priority=Baja Prioridad
wallet.send.fee.rate.low-priority.tooltip=Normalmente se confirma en un día o más
wallet.send.fee.fee=Comisión:
wallet.send.optimize=Optimizar:
wallet.send.optimize.efficiency=Eficiencia
wallet.send.optimize.efficiency.tootip=Tamaño de transacción más pequeño para tarifas más bajas
wallet.send.optimize.privacy=Privacidad
wallet.send.optimize.privacy.tooltip=Transacciones de mayor entropía que reducen las probabilidades en el análisis de la cadena de bloques
wallet.send.optimize.help=Determina si se debe optimizar la transacción para obtener tarifas bajas o mayor privacidad
wallet.send.optimize.analysis=Análisis...
wallet.send.optimize.coinjoin=Aparece como un coinjoin de dos personas
wallet.send.optimize.coinjoin.mixes-address-types=No se puede simular coinjoin debido a tipos de direcciones mixtas
wallet.send.optimize.coinjoin.multiple-payments=No se puede simular coinjoin debido a pagos múltiples
wallet.send.optimize.coinjoin.payjoin=No se puede simular coinjoin debido a payjoin
wallet.send.optimize.coinjoin.coincontrol=No se puede simular coinjoin debido al control de monedas
wallet.send.optimize.coinjoin.insufficient-funds=No se puede simular coinjoin debido a fondos insuficientes
wallet.send.optimize.mixes-address-types=Los tipos de direcciones diferentes a las de la billetera indican pagos externos
wallet.send.optimize.external-payments=Las cantidades redondeadas de pagos indican pagos externos
wallet.send.optimize.reuse=Se ha detectado reutilización de direcciones
wallet.send.optimize.self-transfer=Aparece como una posible auto-transferencia
wallet.send.clear=Limpiar
wallet.send.broadcast-notification=Retransmitir Notificación
wallet.send.create-transaction=Crear Transacción
# Transaction diagram
diagram.transaction=Transacción
# settings # settings
language=Idioma language=Idioma
language.en=Inglés language.en=Inglés