add fee rate selection for premix

This commit is contained in:
Craig Raw
2021-10-22 11:01:58 +02:00
parent 813e0f3ab1
commit 1497b3d3bb
9 changed files with 90 additions and 8 deletions
@@ -11,6 +11,7 @@ public class SpendUtxoEvent {
private final Wallet wallet;
private final List<BlockTransactionHashIndex> utxos;
private final List<Payment> payments;
private final List<byte[]> opReturns;
private final Long fee;
private final boolean includeSpentMempoolOutputs;
private final Pool pool;
@@ -23,15 +24,17 @@ public class SpendUtxoEvent {
this.wallet = wallet;
this.utxos = utxos;
this.payments = payments;
this.opReturns = null;
this.fee = fee;
this.includeSpentMempoolOutputs = includeSpentMempoolOutputs;
this.pool = null;
}
public SpendUtxoEvent(Wallet wallet, List<BlockTransactionHashIndex> utxos, List<Payment> payments, Long fee, Pool pool) {
public SpendUtxoEvent(Wallet wallet, List<BlockTransactionHashIndex> utxos, List<Payment> payments, List<byte[]> opReturns, Long fee, Pool pool) {
this.wallet = wallet;
this.utxos = utxos;
this.payments = payments;
this.opReturns = opReturns;
this.fee = fee;
this.includeSpentMempoolOutputs = false;
this.pool = pool;
@@ -49,6 +52,10 @@ public class SpendUtxoEvent {
return payments;
}
public List<byte[]> getOpReturns() {
return opReturns;
}
public Long getFee() {
return fee;
}
@@ -162,6 +162,8 @@ public class SendController extends WalletFormController implements Initializabl
private final BooleanProperty includeSpentMempoolOutputsProperty = new SimpleBooleanProperty(false);
private final List<byte[]> opReturnsList = new ArrayList<>();
private final Set<WalletNode> excludedChangeNodes = new HashSet<>();
private final ChangeListener<String> feeListener = new ChangeListener<>() {
@@ -556,7 +558,7 @@ public class SendController extends WalletFormController implements Initializabl
boolean includeMempoolOutputs = Config.get().isIncludeMempoolOutputs();
boolean includeSpentMempoolOutputs = includeSpentMempoolOutputsProperty.get();
walletTransactionService = new WalletTransactionService(wallet, getUtxoSelectors(payments), getUtxoFilters(), payments, excludedChangeNodes, feeRate, getMinimumFeeRate(), userFee, currentBlockHeight, groupByAddress, includeMempoolOutputs, includeSpentMempoolOutputs);
walletTransactionService = new WalletTransactionService(wallet, getUtxoSelectors(payments), getUtxoFilters(), payments, opReturnsList, excludedChangeNodes, feeRate, getMinimumFeeRate(), userFee, currentBlockHeight, groupByAddress, includeMempoolOutputs, includeSpentMempoolOutputs);
walletTransactionService.setOnSucceeded(event -> {
if(!walletTransactionService.isIgnoreResult()) {
walletTransactionProperty.setValue(walletTransactionService.getValue());
@@ -616,6 +618,7 @@ public class SendController extends WalletFormController implements Initializabl
private final List<UtxoSelector> utxoSelectors;
private final List<UtxoFilter> utxoFilters;
private final List<Payment> payments;
private final List<byte[]> opReturns;
private final Set<WalletNode> excludedChangeNodes;
private final double feeRate;
private final double longTermFeeRate;
@@ -626,11 +629,12 @@ public class SendController extends WalletFormController implements Initializabl
private final boolean includeSpentMempoolOutputs;
private boolean ignoreResult;
public WalletTransactionService(Wallet wallet, List<UtxoSelector> utxoSelectors, List<UtxoFilter> utxoFilters, List<Payment> payments, Set<WalletNode> excludedChangeNodes, double feeRate, double longTermFeeRate, Long fee, Integer currentBlockHeight, boolean groupByAddress, boolean includeMempoolOutputs, boolean includeSpentMempoolOutputs) {
public WalletTransactionService(Wallet wallet, List<UtxoSelector> utxoSelectors, List<UtxoFilter> utxoFilters, List<Payment> payments, List<byte[]> opReturns, Set<WalletNode> excludedChangeNodes, double feeRate, double longTermFeeRate, Long fee, Integer currentBlockHeight, boolean groupByAddress, boolean includeMempoolOutputs, boolean includeSpentMempoolOutputs) {
this.wallet = wallet;
this.utxoSelectors = utxoSelectors;
this.utxoFilters = utxoFilters;
this.payments = payments;
this.opReturns = opReturns;
this.excludedChangeNodes = excludedChangeNodes;
this.feeRate = feeRate;
this.longTermFeeRate = longTermFeeRate;
@@ -645,7 +649,7 @@ public class SendController extends WalletFormController implements Initializabl
protected Task<WalletTransaction> createTask() {
return new Task<>() {
protected WalletTransaction call() throws InsufficientFundsException {
return wallet.createWalletTransaction(utxoSelectors, utxoFilters, payments, excludedChangeNodes, feeRate, longTermFeeRate, fee, currentBlockHeight, groupByAddress, includeMempoolOutputs, includeSpentMempoolOutputs);
return wallet.createWalletTransaction(utxoSelectors, utxoFilters, payments, opReturns, excludedChangeNodes, feeRate, longTermFeeRate, fee, currentBlockHeight, groupByAddress, includeMempoolOutputs, includeSpentMempoolOutputs);
}
};
}
@@ -1014,6 +1018,7 @@ public class SendController extends WalletFormController implements Initializabl
utxoSelectorProperty.setValue(null);
utxoFilterProperty.setValue(null);
includeSpentMempoolOutputsProperty.set(false);
opReturnsList.clear();
excludedChangeNodes.clear();
walletTransactionProperty.setValue(null);
createdWalletTransactionProperty.set(null);
@@ -1239,6 +1244,10 @@ public class SendController extends WalletFormController implements Initializabl
setPayments(List.of(payment));
}
if(event.getOpReturns() != null) {
opReturnsList.addAll(event.getOpReturns());
}
if(event.getFee() != null) {
setFeeValueSats(event.getFee());
userFeeSet.set(true);
@@ -320,10 +320,12 @@ public class UtxosController extends WalletFormController implements Initializab
payments.add(new Payment(premixAddress, "Premix #" + i, tx0Preview.getPremixValue(), false));
}
List<byte[]> opReturns = List.of(new byte[64]);
final List<BlockTransactionHashIndex> utxos = utxoEntries.stream().map(HashIndexEntry::getHashIndex).collect(Collectors.toList());
Platform.runLater(() -> {
EventManager.get().post(new SendActionEvent(getWalletForm().getWallet(), utxos));
Platform.runLater(() -> EventManager.get().post(new SpendUtxoEvent(getWalletForm().getWallet(), utxos, payments, tx0Preview.getTx0MinerFee(), tx0Preview.getPool())));
Platform.runLater(() -> EventManager.get().post(new SpendUtxoEvent(getWalletForm().getWallet(), utxos, payments, opReturns, tx0Preview.getTx0MinerFee(), tx0Preview.getPool())));
});
}
@@ -71,6 +71,7 @@ public class Whirlpool {
private final Tx0ParamService tx0ParamService;
private final ExpirablePoolSupplier poolSupplier;
private final Tx0Service tx0Service;
private Tx0FeeTarget tx0FeeTarget = Tx0FeeTarget.BLOCKS_4;
private HD_Wallet hdWallet;
private String walletId;
private String mixToWalletId;
@@ -140,7 +141,6 @@ public class Whirlpool {
}
private Tx0Config computeTx0Config() {
Tx0FeeTarget tx0FeeTarget = Tx0FeeTarget.BLOCKS_4;
Tx0FeeTarget mixFeeTarget = Tx0FeeTarget.BLOCKS_4;
return new Tx0Config(tx0ParamService, poolSupplier, tx0FeeTarget, mixFeeTarget, WhirlpoolAccount.BADBANK);
}
@@ -385,6 +385,14 @@ public class Whirlpool {
config.setScode(scode);
}
public Tx0FeeTarget getTx0FeeTarget() {
return tx0FeeTarget;
}
public void setTx0FeeTarget(Tx0FeeTarget tx0FeeTarget) {
this.tx0FeeTarget = tx0FeeTarget;
}
public String getWalletId() {
return walletId;
}
@@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.whirlpool;
import com.samourai.whirlpool.client.tx0.Tx0Preview;
import com.samourai.whirlpool.client.tx0.Tx0Previews;
import com.samourai.whirlpool.client.wallet.beans.Tx0FeeTarget;
import com.samourai.whirlpool.client.whirlpool.beans.Pool;
import com.sparrowwallet.drongo.BitcoinUnit;
import com.sparrowwallet.drongo.protocol.Transaction;
@@ -10,10 +11,12 @@ import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.control.CoinLabel;
import com.sparrowwallet.sparrow.control.CopyableLabel;
import com.sparrowwallet.sparrow.event.WalletMasterMixConfigChangedEvent;
import com.sparrowwallet.sparrow.io.Config;
import com.sparrowwallet.sparrow.wallet.Entry;
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
import com.sparrowwallet.sparrow.whirlpool.dataSource.SparrowMinerFeeSupplier;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
@@ -26,6 +29,8 @@ import javafx.util.StringConverter;
import java.util.*;
public class WhirlpoolController {
private static final List<Tx0FeeTarget> FEE_TARGETS = List.of(Tx0FeeTarget.MIN, Tx0FeeTarget.BLOCKS_4, Tx0FeeTarget.BLOCKS_2);
@FXML
private VBox whirlpoolBox;
@@ -44,6 +49,12 @@ public class WhirlpoolController {
@FXML
private TextField scode;
@FXML
private Slider premixPriority;
@FXML
private CopyableLabel premixFeeRate;
@FXML
private ComboBox<Pool> pool;
@@ -108,6 +119,30 @@ public class WhirlpoolController {
EventManager.get().post(new WalletMasterMixConfigChangedEvent(wallet));
});
premixPriority.setMin(0);
premixPriority.setMax(FEE_TARGETS.size() - 1);
premixPriority.setMajorTickUnit(1);
premixPriority.setMinorTickCount(0);
premixPriority.setLabelFormatter(new StringConverter<>() {
@Override
public String toString(Double object) {
return object.intValue() == 0 ? "Low" : (object.intValue() == 1 ? "Normal" : "High");
}
@Override
public Double fromString(String string) {
return null;
}
});
premixPriority.valueProperty().addListener((observable, oldValue, newValue) -> {
pool.setItems(FXCollections.emptyObservableList());
tx0Previews = null;
tx0PreviewProperty.set(null);
Tx0FeeTarget tx0FeeTarget = FEE_TARGETS.get(newValue.intValue());
premixFeeRate.setText(SparrowMinerFeeSupplier.getMinimumFeeForTarget(Integer.parseInt(tx0FeeTarget.getFeeTarget().getValue())) + " sats/vB");
});
premixPriority.setValue(1);
if(mixConfig.getScode() != null) {
step1.setVisible(false);
step3.setVisible(true);
@@ -280,6 +315,7 @@ public class WhirlpoolController {
} else {
tx0Previews = null;
whirlpool.setScode(mixConfig.getScode());
whirlpool.setTx0FeeTarget(FEE_TARGETS.get(premixPriority.valueProperty().intValue()));
Whirlpool.Tx0PreviewsService tx0PreviewsService = new Whirlpool.Tx0PreviewsService(whirlpool, wallet, utxoEntries);
tx0PreviewsService.setOnRunning(workerStateEvent -> {
@@ -32,7 +32,7 @@ public class SparrowMinerFeeSupplier implements MinerFeeSupplier {
return getMinimumFeeForTarget(Integer.parseInt(feeTarget.getValue()));
}
private Integer getMinimumFeeForTarget(int targetBlocks) {
public static Integer getMinimumFeeForTarget(int targetBlocks) {
List<Map.Entry<Integer, Double>> feeRates = new ArrayList<>(AppServices.getTargetBlockFeeRates().entrySet());
Collections.reverse(feeRates);
for(Map.Entry<Integer, Double> feeRate : feeRates) {
@@ -40,6 +40,7 @@ public class SparrowMinerFeeSupplier implements MinerFeeSupplier {
return feeRate.getValue().intValue();
}
}
return feeRates.get(0).getValue().intValue();
}