mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-11-05 11:56:37 +00:00
Code cleanup & refactoring
This commit is contained in:
parent
550df1d91a
commit
435f126933
4 changed files with 255 additions and 118 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
package com.sparrowwallet.sparrow.joinstr;
|
package com.sparrowwallet.sparrow.joinstr;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.KeyPurpose;
|
|
||||||
import com.sparrowwallet.drongo.address.Address;
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
||||||
|
|
@ -13,45 +12,33 @@ import com.sparrowwallet.drongo.wallet.InsufficientFundsException;
|
||||||
import com.sparrowwallet.drongo.wallet.KnapsackUtxoSelector;
|
import com.sparrowwallet.drongo.wallet.KnapsackUtxoSelector;
|
||||||
import com.sparrowwallet.drongo.wallet.Payment;
|
import com.sparrowwallet.drongo.wallet.Payment;
|
||||||
import com.sparrowwallet.drongo.wallet.SpentTxoFilter;
|
import com.sparrowwallet.drongo.wallet.SpentTxoFilter;
|
||||||
import com.sparrowwallet.drongo.wallet.StonewallUtxoSelector;
|
|
||||||
import com.sparrowwallet.drongo.wallet.TxoFilter;
|
import com.sparrowwallet.drongo.wallet.TxoFilter;
|
||||||
import com.sparrowwallet.drongo.wallet.UtxoSelector;
|
import com.sparrowwallet.drongo.wallet.UtxoSelector;
|
||||||
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 com.sparrowwallet.drongo.wallet.WalletTransaction;
|
import com.sparrowwallet.drongo.wallet.WalletTransaction;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.control.QRScanDialog;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
import com.sparrowwallet.sparrow.io.WalletTransactions;
|
|
||||||
import com.sparrowwallet.sparrow.net.Tor;
|
import com.sparrowwallet.sparrow.net.Tor;
|
||||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
|
||||||
import com.sparrowwallet.sparrow.wallet.NodeEntry;
|
|
||||||
import com.sparrowwallet.sparrow.wallet.OptimizationStrategy;
|
|
||||||
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
|
||||||
import com.sparrowwallet.sparrow.wallet.WalletForm;
|
|
||||||
import com.sparrowwallet.sparrow.wallet.WalletUtxosEntry;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class JoinstrPool {
|
public class JoinstrPool {
|
||||||
|
|
||||||
private final String relay;
|
private final Integer port; // Nostr Port ?
|
||||||
private final Integer port;
|
|
||||||
private final String pubkey;
|
private final String pubkey;
|
||||||
private final long denomination; // Should be in sats, like transaction amounts
|
private final long denomination; // Should be in sats, like transaction amounts
|
||||||
private final WalletForm walletForm; // [FormController].getWalletForm()
|
|
||||||
|
|
||||||
public JoinstrPool(WalletForm walletForm,String relay, Integer port, String pubkey, long denomination) {
|
public JoinstrPool(Integer port, String pubkey, long denomination) {
|
||||||
|
|
||||||
this.walletForm = walletForm;
|
|
||||||
this.relay = relay;
|
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.pubkey = pubkey;
|
this.pubkey = pubkey;
|
||||||
this.denomination = denomination;
|
this.denomination = denomination;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRelay() {
|
private String getNostrRelay() {
|
||||||
return relay;
|
return Config.get().getNostrRelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getPort() {
|
public Integer getPort() {
|
||||||
|
|
@ -73,78 +60,13 @@ public class JoinstrPool {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address getNewSendAddress() {
|
public void publicNostrEvent() {
|
||||||
NodeEntry freshNodeEntry = walletForm.getFreshNodeEntry(KeyPurpose.SEND, null);
|
// TODO: Publish a nostr event with pool info
|
||||||
return freshNodeEntry.getAddress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createPSBT() throws InsufficientFundsException {
|
public void waitForPeers() {
|
||||||
|
// TODO: Wait for others to join
|
||||||
/* PSBT from byte[]
|
|
||||||
|
|
||||||
if(PSBT.isPSBT(bytes)) {
|
|
||||||
//Don't verify signatures here - provided PSBT may omit UTXO data that can be found when combining with an existing PSBT
|
|
||||||
PSBT psbt = new PSBT(bytes, false);
|
|
||||||
} else {
|
|
||||||
throw new ParseException("Not a valid PSBT or transaction", 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* PSBT from QR Code
|
|
||||||
|
|
||||||
QRScanDialog qrScanDialog = new QRScanDialog();
|
|
||||||
qrScanDialog.initOwner(rootStack.getScene().getWindow());
|
|
||||||
Optional<QRScanDialog.Result> optionalResult = qrScanDialog.showAndWait();
|
|
||||||
QRScanDialog.Result result = optionalResult.get();
|
|
||||||
result.psbt;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// PSBT from WalletTransaction
|
|
||||||
|
|
||||||
Address sendAddress = getNewSendAddress();
|
|
||||||
Wallet wallet = walletForm.getWallet();
|
|
||||||
double feeRate = 1.0;
|
|
||||||
double longTermFeeRate = 10.0;
|
|
||||||
long fee = 10L;
|
|
||||||
long dustThreshold = getRecipientDustThreshold(sendAddress);
|
|
||||||
long amount = wallet.getWalletTxos().keySet().stream().mapToLong(BlockTransactionHashIndex::getValue).sum();
|
|
||||||
long satsLeft = amount;
|
|
||||||
|
|
||||||
String paymentLabel = "coinjoin";
|
|
||||||
|
|
||||||
ArrayList<Payment> payments = new ArrayList<Payment>();
|
|
||||||
while(satsLeft > denomination + dustThreshold) {
|
|
||||||
Payment payment = new Payment(sendAddress, paymentLabel, denomination, false);
|
|
||||||
satsLeft -= denomination;
|
|
||||||
payment.setType(Payment.Type.COINJOIN);
|
|
||||||
payments.add(payment);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<UtxoSelector> selectors = new ArrayList<>();
|
|
||||||
long noInputsFee = wallet.getNoInputsFee(payments, feeRate);
|
|
||||||
long costOfChange = wallet.getCostOfChange(feeRate, longTermFeeRate);
|
|
||||||
selectors.addAll(List.of(new BnBUtxoSelector(noInputsFee, costOfChange), new KnapsackUtxoSelector(noInputsFee)));
|
|
||||||
|
|
||||||
SpentTxoFilter spentTxoFilter = new SpentTxoFilter(null);
|
|
||||||
List<TxoFilter> txoFilters = List.of(spentTxoFilter, new FrozenTxoFilter(), new CoinbaseTxoFilter(walletForm.getWallet()));
|
|
||||||
|
|
||||||
ArrayList<byte[]> opReturns = new ArrayList<>();
|
|
||||||
TreeSet<WalletNode> excludedChangeNodes = new TreeSet<>();
|
|
||||||
|
|
||||||
Integer currentBlockHeight = AppServices.getCurrentBlockHeight();
|
|
||||||
boolean groupByAddress = false;
|
|
||||||
boolean includeMempoolOutputs = false;
|
|
||||||
|
|
||||||
WalletTransaction walletTransaction = walletForm.getWallet().createWalletTransaction(selectors, txoFilters, payments, opReturns, excludedChangeNodes, feeRate, longTermFeeRate, fee, currentBlockHeight, groupByAddress, includeMempoolOutputs);
|
|
||||||
PSBT psbt = walletTransaction.createPSBT();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getRecipientDustThreshold(Address address) {
|
|
||||||
TransactionOutput txOutput = new TransactionOutput(new Transaction(), 1L, address.getOutputScript());
|
|
||||||
return address.getScriptType().getDustThreshold(txOutput, Transaction.DUST_RELAY_TX_FEE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,118 @@
|
||||||
package com.sparrowwallet.sparrow.joinstr;
|
package com.sparrowwallet.sparrow.joinstr;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.BitcoinUnit;
|
||||||
|
import com.sparrowwallet.drongo.KeyPurpose;
|
||||||
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
|
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
||||||
|
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||||
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||||
|
import com.sparrowwallet.drongo.wallet.BnBUtxoSelector;
|
||||||
|
import com.sparrowwallet.drongo.wallet.CoinbaseTxoFilter;
|
||||||
|
import com.sparrowwallet.drongo.wallet.FrozenTxoFilter;
|
||||||
|
import com.sparrowwallet.drongo.wallet.InsufficientFundsException;
|
||||||
|
import com.sparrowwallet.drongo.wallet.KnapsackUtxoSelector;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Payment;
|
||||||
|
import com.sparrowwallet.drongo.wallet.SpentTxoFilter;
|
||||||
|
import com.sparrowwallet.drongo.wallet.TxoFilter;
|
||||||
|
import com.sparrowwallet.drongo.wallet.UtxoSelector;
|
||||||
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
|
import com.sparrowwallet.drongo.wallet.WalletTransaction;
|
||||||
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.NodeEntry;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.ComboBox;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Alert.AlertType;
|
import javafx.scene.control.Alert.AlertType;
|
||||||
|
|
||||||
public class NewPoolController extends JoinstrFormController {
|
public class NewPoolController extends JoinstrFormController {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label addressLabel;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField labelField;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField amountField;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField denominationField;
|
private TextField denominationField;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField peersField;
|
private TextField peersField;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ComboBox<BlockTransactionHashIndex> utxosComboBox;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ComboBox<BitcoinUnit> denominationUnit;
|
||||||
|
|
||||||
|
private Address coinjoinAddress;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeView() {
|
public void initializeView() {
|
||||||
|
|
||||||
|
coinjoinAddress = getNewReceiveAddress();
|
||||||
|
addressLabel.setText(coinjoinAddress.getAddress());
|
||||||
|
|
||||||
|
ObservableList<BlockTransactionHashIndex> utxos = FXCollections.observableArrayList(getWalletForm().getWallet().getWalletTxos().keySet().stream().filter(ref -> !ref.isSpent()).collect(Collectors.toList()));
|
||||||
|
if(!utxos.isEmpty()) {
|
||||||
|
utxosComboBox.setItems(utxos);
|
||||||
|
}
|
||||||
|
utxosComboBox.setPromptText("Select an UTXO");
|
||||||
|
denominationUnit.setValue(BitcoinUnit.SATOSHIS);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void handleCreateButton() {
|
private void setUtxoAmount(ActionEvent event) {
|
||||||
|
switch(denominationUnit.getValue()) {
|
||||||
|
case BTC -> {
|
||||||
|
amountField.setText((utxosComboBox.getValue().getValue()) + " BTC");
|
||||||
|
}
|
||||||
|
case SATOSHIS -> {
|
||||||
|
amountField.setText((utxosComboBox.getValue().getValue()) + " sats");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void handleDenominationUnitChange(ActionEvent event) {
|
||||||
|
switch(denominationUnit.getValue()) {
|
||||||
|
case BTC -> {
|
||||||
|
if(!amountField.getText().isEmpty()) {
|
||||||
|
amountField.setText((Double.parseDouble(amountField.getText().split(" ")[0]) / 100000000) + " BTC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case SATOSHIS -> {
|
||||||
|
double amount = Double.parseDouble(amountField.getText().split(" ")[0]) * 100000000;
|
||||||
|
amountField.setText(String.valueOf(amount).split("\\.")[0] + " sats");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void handleCreateButton(ActionEvent event) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String denomination = denominationField.getText().trim();
|
String denomination = denominationField.getText().trim();
|
||||||
|
|
@ -31,6 +125,9 @@ public class NewPoolController extends JoinstrFormController {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
double denominationValue = Double.parseDouble(denomination);
|
double denominationValue = Double.parseDouble(denomination);
|
||||||
|
if(denominationUnit.getValue() == BitcoinUnit.SATOSHIS) {
|
||||||
|
Long.parseLong(denomination);
|
||||||
|
}
|
||||||
if (denominationValue <= 0) {
|
if (denominationValue <= 0) {
|
||||||
showError("Denomination must be greater than 0");
|
showError("Denomination must be greater than 0");
|
||||||
return;
|
return;
|
||||||
|
|
@ -51,11 +148,50 @@ public class NewPoolController extends JoinstrFormController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long denominationSats = Long.valueOf((long) (Double.parseDouble(denomination)*100000000.0D));
|
String amount = amountField.getText().trim();
|
||||||
|
if (amount.isEmpty()) {
|
||||||
|
showError("Please select an UTXO to create a pool.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
amount = amount.split(" ")[0]; // Removes BTC/sats
|
||||||
|
|
||||||
|
try {
|
||||||
|
double amountValue = Double.parseDouble(amount);
|
||||||
|
if(denominationUnit.getValue() == BitcoinUnit.SATOSHIS) {
|
||||||
|
Long.parseLong(amount);
|
||||||
|
}
|
||||||
|
if (amountValue != Double.parseDouble(denomination) && amountValue < Double.parseDouble(denomination) + getRecipientDustThreshold(coinjoinAddress)) {
|
||||||
|
showError("Amount is smaller than denomination with dust threshold");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
showError("Invalid amount format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long amountInSats;
|
||||||
|
long denominationInSats;
|
||||||
|
if(denominationUnit.getValue() == BitcoinUnit.SATOSHIS) {
|
||||||
|
denominationInSats = Long.parseLong(denomination);
|
||||||
|
amountInSats = Long.parseLong(amount);
|
||||||
|
} else {
|
||||||
|
denominationInSats = (long)Double.parseDouble(denomination) * 100000000;
|
||||||
|
amountInSats = (long)Double.parseDouble(amount) * 100000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
JoinstrPool pool = new JoinstrPool(9999, "pubkey", denominationInSats);
|
||||||
|
|
||||||
|
// TODO: Publish a nostr event with pool info and wait for peers
|
||||||
|
pool.publicNostrEvent();
|
||||||
|
pool.waitForPeers();
|
||||||
|
|
||||||
// TODO: Implement pool creation logic here
|
// TODO: Implement pool creation logic here
|
||||||
JoinstrPool pool = new JoinstrPool(getWalletForm(), Config.get().getNostrRelay(),9999, "pubkey", denominationSats);
|
PSBT myPoolPSBT = createPSBT(labelField.getText(), amountInSats, denominationInSats);
|
||||||
pool.createPSBT();
|
|
||||||
|
if(myPoolPSBT != null) {
|
||||||
|
/// TODO: Sign using sighash flag ALL | ACP
|
||||||
|
/// TODO: Combine all PSBTs
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Alert alert = new Alert(AlertType.INFORMATION);
|
Alert alert = new Alert(AlertType.INFORMATION);
|
||||||
|
|
@ -67,12 +203,54 @@ public class NewPoolController extends JoinstrFormController {
|
||||||
|
|
||||||
denominationField.clear();
|
denominationField.clear();
|
||||||
peersField.clear();
|
peersField.clear();
|
||||||
|
amountField.clear();
|
||||||
|
labelField.clear();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showError("An error occurred: " + e.getMessage());
|
showError("An error occurred: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PSBT createPSBT(String paymentLabel, long amount, long denomination) throws InsufficientFundsException {
|
||||||
|
|
||||||
|
// PSBT from WalletTransaction
|
||||||
|
double feeRate = 1.0;
|
||||||
|
double longTermFeeRate = 10.0;
|
||||||
|
long fee = 10L;
|
||||||
|
long dustThreshold = getRecipientDustThreshold(coinjoinAddress);
|
||||||
|
long satsLeft = amount;
|
||||||
|
|
||||||
|
ArrayList<Payment> payments = new ArrayList<Payment>();
|
||||||
|
while(satsLeft == denomination || satsLeft > denomination + dustThreshold) {
|
||||||
|
Payment payment = new Payment(coinjoinAddress, paymentLabel, denomination, false);
|
||||||
|
satsLeft -= denomination;
|
||||||
|
payment.setType(Payment.Type.COINJOIN);
|
||||||
|
payments.add(payment);
|
||||||
|
}
|
||||||
|
|
||||||
|
long noInputsFee = getWalletForm().getWallet().getNoInputsFee(payments, feeRate);
|
||||||
|
long costOfChange = getWalletForm().getWallet().getCostOfChange(feeRate, longTermFeeRate);
|
||||||
|
List<UtxoSelector> selectors = new ArrayList<>(List.of(new BnBUtxoSelector(noInputsFee, costOfChange), new KnapsackUtxoSelector(noInputsFee)));
|
||||||
|
|
||||||
|
SpentTxoFilter spentTxoFilter = new SpentTxoFilter(null);
|
||||||
|
List<TxoFilter> txoFilters = List.of(spentTxoFilter, new FrozenTxoFilter(), new CoinbaseTxoFilter(getWalletForm().getWallet()));
|
||||||
|
|
||||||
|
ArrayList<byte[]> opReturns = new ArrayList<>();
|
||||||
|
TreeSet<WalletNode> excludedChangeNodes = new TreeSet<>();
|
||||||
|
|
||||||
|
Integer currentBlockHeight = AppServices.getCurrentBlockHeight();
|
||||||
|
boolean groupByAddress = false;
|
||||||
|
boolean includeMempoolOutputs = false;
|
||||||
|
|
||||||
|
WalletTransaction walletTransaction = getWalletForm().getWallet().createWalletTransaction(selectors, txoFilters, payments, opReturns, excludedChangeNodes, feeRate, longTermFeeRate, fee, currentBlockHeight, groupByAddress, includeMempoolOutputs);
|
||||||
|
return walletTransaction.createPSBT();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getRecipientDustThreshold(Address address) {
|
||||||
|
TransactionOutput txOutput = new TransactionOutput(new Transaction(), 1L, address.getOutputScript());
|
||||||
|
return address.getScriptType().getDustThreshold(txOutput, Transaction.DUST_RELAY_TX_FEE);
|
||||||
|
}
|
||||||
|
|
||||||
private void showError(String message) {
|
private void showError(String message) {
|
||||||
Alert alert = new Alert(AlertType.ERROR);
|
Alert alert = new Alert(AlertType.ERROR);
|
||||||
alert.setTitle("Error");
|
alert.setTitle("Error");
|
||||||
|
|
@ -80,4 +258,10 @@ public class NewPoolController extends JoinstrFormController {
|
||||||
alert.setContentText(message);
|
alert.setContentText(message);
|
||||||
alert.showAndWait();
|
alert.showAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Address getNewReceiveAddress() {
|
||||||
|
NodeEntry freshNodeEntry = getWalletForm().getFreshNodeEntry(KeyPurpose.RECEIVE, null);
|
||||||
|
return freshNodeEntry.getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,21 @@ public class SettingsController extends JoinstrFormController {
|
||||||
@Override
|
@Override
|
||||||
public void changed(ObservableValue<? extends String> observable,
|
public void changed(ObservableValue<? extends String> observable,
|
||||||
String oldValue, String newValue) {
|
String oldValue, String newValue) {
|
||||||
if(nostrRelayTextField.getText().isEmpty()) {
|
setDefaultNostrRelayIfEmpty();
|
||||||
nostrRelayTextField.setText("wss://nostr.fmt.wiz.biz");
|
|
||||||
}
|
|
||||||
Config.get().setNostrRelay(nostrRelayTextField.getText());
|
Config.get().setNostrRelay(nostrRelayTextField.getText());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setDefaultNostrRelayIfEmpty();
|
||||||
|
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDefaultNostrRelayIfEmpty() {
|
||||||
|
if(nostrRelayTextField.getText().isEmpty()) {
|
||||||
|
nostrRelayTextField.setText("wss://nostr.fmt.wiz.biz");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,36 +3,62 @@
|
||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.collections.FXCollections?>
|
||||||
|
|
||||||
<BorderPane stylesheets="@joinstr.css, @../wallet/wallet.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.joinstr.NewPoolController">
|
<?import com.sparrowwallet.sparrow.control.FiatLabel?>
|
||||||
|
<?import com.sparrowwallet.drongo.BitcoinUnit?>
|
||||||
|
<?import org.controlsfx.glyphfont.Glyph?>
|
||||||
|
|
||||||
|
<?import tornadofx.control.Form?>
|
||||||
|
<?import tornadofx.control.Fieldset?>
|
||||||
|
<?import tornadofx.control.Field?>
|
||||||
|
|
||||||
|
<BorderPane stylesheets="@joinstr.css, @../wallet/wallet.css, @../general.css" styleClass="send-form" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.joinstr.NewPoolController">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets top="30" right="30" bottom="30" left="30"/>
|
<Insets top="30" right="30" bottom="30" left="30"/>
|
||||||
</padding>
|
</padding>
|
||||||
<center>
|
<center>
|
||||||
<VBox maxWidth="Infinity" fx:id="contentVBox" spacing="20">
|
<VBox maxWidth="Infinity" fx:id="contentVBox" spacing="20">
|
||||||
<VBox maxWidth="Infinity" HBox.hgrow="ALWAYS">
|
|
||||||
<Label styleClass="sub-title">Create a new pool</Label>
|
<Label styleClass="sub-title">Create a new pool</Label>
|
||||||
</VBox>
|
<Form maxWidth="Infinity" style="-fx-max-width: 600px;">
|
||||||
|
<Fieldset inputGrow="ALWAYS">
|
||||||
<GridPane hgap="10" vgap="15" maxWidth="600">
|
<Field text="Pay to:">
|
||||||
<padding>
|
<Label fx:id="addressLabel" />
|
||||||
<Insets top="20"/>
|
</Field>
|
||||||
</padding>
|
<Field text="Label:">
|
||||||
|
<TextField fx:id="labelField" promptText="Required" style="-fx-max-width: 250px;">
|
||||||
<Label text="Denomination (BTC):" GridPane.rowIndex="0" GridPane.columnIndex="0" style="-fx-text-fill: #aaaaaa;"/>
|
<tooltip>
|
||||||
<TextField fx:id="denominationField" GridPane.rowIndex="0" GridPane.columnIndex="1"
|
<Tooltip text="Required to label the transaction (privately in this wallet)"/>
|
||||||
style="-fx-background-color: #444444; -fx-text-fill: white; -fx-prompt-text-fill: #888888;"
|
</tooltip>
|
||||||
promptText="Enter denomination"/>
|
</TextField>
|
||||||
|
</Field>
|
||||||
<Label text="Number of Peers:" GridPane.rowIndex="1" GridPane.columnIndex="0" style="-fx-text-fill: #aaaaaa;"/>
|
<Field text="UTXO:">
|
||||||
<TextField fx:id="peersField" GridPane.rowIndex="1" GridPane.columnIndex="1"
|
<ComboBox fx:id="utxosComboBox" styleClass="amount-unit" style="-fx-max-width: 150px;" onAction="#setUtxoAmount" />
|
||||||
style="-fx-background-color: #444444; -fx-text-fill: white; -fx-prompt-text-fill: #888888;"
|
<TextField fx:id="amountField" disable="true" style="-fx-max-width: 100px;-fx-text-fill: white;" />
|
||||||
promptText="Enter number of peers"/>
|
</Field>
|
||||||
|
<Field text="Denomination:" style="-fx-text-fill: #aaaaaa;">
|
||||||
<Button fx:id="createButton" text="Create" GridPane.rowIndex="2" GridPane.columnIndex="1"
|
<TextField fx:id="denominationField" promptText="Required" style="-fx-max-width: 100px;-fx-background-color: #444444; -fx-text-fill: white; -fx-prompt-text-fill: #888888;">
|
||||||
onAction="#handleCreateButton"
|
<tooltip>
|
||||||
style="-fx-background-color: #2196F3; -fx-text-fill: white; -fx-cursor: hand;"/>
|
<Tooltip text="Required to create coinjoin pool"/>
|
||||||
</GridPane>
|
</tooltip>
|
||||||
|
</TextField>
|
||||||
|
<ComboBox fx:id="denominationUnit" styleClass="amount-unit" style="-fx-min-width: 60px;" onAction="#handleDenominationUnitChange">
|
||||||
|
<items>
|
||||||
|
<FXCollections fx:factory="observableArrayList">
|
||||||
|
<BitcoinUnit fx:constant="BTC" />
|
||||||
|
<BitcoinUnit fx:constant="SATOSHIS" />
|
||||||
|
</FXCollections>
|
||||||
|
</items>
|
||||||
|
</ComboBox>
|
||||||
|
</Field>
|
||||||
|
<Field text="Number of Peers:" style="-fx-text-fill: #aaaaaa;">
|
||||||
|
<TextField fx:id="peersField" promptText="Req." style="-fx-max-width: 50px;-fx-background-color: #444444; -fx-text-fill: white; -fx-prompt-text-fill: #888888;" />
|
||||||
|
</Field>
|
||||||
|
<Field>
|
||||||
|
<ToggleButton fx:id="createButton" text="Create" onAction="#handleCreateButton" style="-fx-background-color: #2196F3; -fx-text-fill: white; -fx-cursor: hand;" />
|
||||||
|
</Field>
|
||||||
|
</Fieldset>
|
||||||
|
</Form>
|
||||||
</VBox>
|
</VBox>
|
||||||
</center>
|
</center>
|
||||||
</BorderPane>
|
</BorderPane>
|
||||||
Loading…
Reference in a new issue