mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 21:36:45 +00:00
retrieve min fee rate, adjust block target rates and dont create txes with insufficient fee rate
This commit is contained in:
parent
e878c4ea78
commit
e48e40da0d
8 changed files with 58 additions and 6 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit 2650dafa66623c1205582c555369a5118a343ccf
|
Subproject commit 79eb8b002d01be5195bb7fc7eba6bb34bf3366e3
|
|
@ -137,6 +137,8 @@ public class AppController implements Initializable {
|
||||||
|
|
||||||
private static Map<Integer, Double> targetBlockFeeRates;
|
private static Map<Integer, Double> targetBlockFeeRates;
|
||||||
|
|
||||||
|
private static Double minimumRelayFeeRate;
|
||||||
|
|
||||||
private static CurrencyRate fiatCurrencyExchangeRate;
|
private static CurrencyRate fiatCurrencyExchangeRate;
|
||||||
|
|
||||||
private static List<Device> devices;
|
private static List<Device> devices;
|
||||||
|
@ -643,6 +645,10 @@ public class AppController implements Initializable {
|
||||||
return targetBlockFeeRates;
|
return targetBlockFeeRates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Double getMinimumRelayFeeRate() {
|
||||||
|
return minimumRelayFeeRate;
|
||||||
|
}
|
||||||
|
|
||||||
public static CurrencyRate getFiatCurrencyExchangeRate() {
|
public static CurrencyRate getFiatCurrencyExchangeRate() {
|
||||||
return fiatCurrencyExchangeRate;
|
return fiatCurrencyExchangeRate;
|
||||||
}
|
}
|
||||||
|
@ -1305,6 +1311,7 @@ public class AppController implements Initializable {
|
||||||
public void newConnection(ConnectionEvent event) {
|
public void newConnection(ConnectionEvent event) {
|
||||||
currentBlockHeight = event.getBlockHeight();
|
currentBlockHeight = event.getBlockHeight();
|
||||||
targetBlockFeeRates = event.getTargetBlockFeeRates();
|
targetBlockFeeRates = event.getTargetBlockFeeRates();
|
||||||
|
minimumRelayFeeRate = event.getMinimumRelayFeeRate();
|
||||||
String banner = event.getServerBanner();
|
String banner = event.getServerBanner();
|
||||||
String status = "Connected to " + Config.get().getElectrumServer() + " at height " + event.getBlockHeight();
|
String status = "Connected to " + Config.get().getElectrumServer() + " at height " + event.getBlockHeight();
|
||||||
EventManager.get().post(new StatusEvent(status));
|
EventManager.get().post(new StatusEvent(status));
|
||||||
|
|
|
@ -10,13 +10,15 @@ public class ConnectionEvent extends FeeRatesUpdatedEvent {
|
||||||
private final String serverBanner;
|
private final String serverBanner;
|
||||||
private final int blockHeight;
|
private final int blockHeight;
|
||||||
private final BlockHeader blockHeader;
|
private final BlockHeader blockHeader;
|
||||||
|
private final Double minimumRelayFeeRate;
|
||||||
|
|
||||||
public ConnectionEvent(List<String> serverVersion, String serverBanner, int blockHeight, BlockHeader blockHeader, Map<Integer, Double> targetBlockFeeRates) {
|
public ConnectionEvent(List<String> serverVersion, String serverBanner, int blockHeight, BlockHeader blockHeader, Map<Integer, Double> targetBlockFeeRates, Double minimumRelayFeeRate) {
|
||||||
super(targetBlockFeeRates);
|
super(targetBlockFeeRates);
|
||||||
this.serverVersion = serverVersion;
|
this.serverVersion = serverVersion;
|
||||||
this.serverBanner = serverBanner;
|
this.serverBanner = serverBanner;
|
||||||
this.blockHeight = blockHeight;
|
this.blockHeight = blockHeight;
|
||||||
this.blockHeader = blockHeader;
|
this.blockHeader = blockHeader;
|
||||||
|
this.minimumRelayFeeRate = minimumRelayFeeRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getServerVersion() {
|
public List<String> getServerVersion() {
|
||||||
|
@ -34,4 +36,8 @@ public class ConnectionEvent extends FeeRatesUpdatedEvent {
|
||||||
public BlockHeader getBlockHeader() {
|
public BlockHeader getBlockHeader() {
|
||||||
return blockHeader;
|
return blockHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Double getMinimumRelayFeeRate() {
|
||||||
|
return minimumRelayFeeRate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,16 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getMinimumRelayFee(Transport transport) {
|
||||||
|
try {
|
||||||
|
JsonRpcClient client = new JsonRpcClient(transport);
|
||||||
|
return client.createRequest().returnAs(Double.class).method("blockchain.relayfee").id(1).execute();
|
||||||
|
} catch(JsonRpcException e) {
|
||||||
|
throw new ElectrumServerRpcException("Error getting minimum relay fee", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String broadcastTransaction(Transport transport, String txHex) {
|
public String broadcastTransaction(Transport transport, String txHex) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -528,7 +528,7 @@ public class ElectrumServer {
|
||||||
|
|
||||||
Map<Integer, Double> targetBlocksFeeRatesSats = new TreeMap<>();
|
Map<Integer, Double> targetBlocksFeeRatesSats = new TreeMap<>();
|
||||||
for(Integer target : targetBlocksFeeRatesBtcKb.keySet()) {
|
for(Integer target : targetBlocksFeeRatesBtcKb.keySet()) {
|
||||||
targetBlocksFeeRatesSats.put(target, targetBlocksFeeRatesBtcKb.get(target) * Transaction.SATOSHIS_PER_BITCOIN / 1024);
|
targetBlocksFeeRatesSats.put(target, targetBlocksFeeRatesBtcKb.get(target) * Transaction.SATOSHIS_PER_BITCOIN / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return targetBlocksFeeRatesSats;
|
return targetBlocksFeeRatesSats;
|
||||||
|
@ -537,6 +537,16 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Double getMinimumRelayFee() throws ServerException {
|
||||||
|
Double minFeeRateBtcKb = electrumServerRpc.getMinimumRelayFee(getTransport());
|
||||||
|
if(minFeeRateBtcKb != null) {
|
||||||
|
long minFeeRateSatsKb = (long)(minFeeRateBtcKb * Transaction.SATOSHIS_PER_BITCOIN);
|
||||||
|
return minFeeRateSatsKb / 1000d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Transaction.DEFAULT_MIN_RELAY_FEE;
|
||||||
|
}
|
||||||
|
|
||||||
public Sha256Hash broadcastTransaction(Transaction transaction) throws ServerException {
|
public Sha256Hash broadcastTransaction(Transaction transaction) throws ServerException {
|
||||||
byte[] rawtxBytes = transaction.bitcoinSerialize();
|
byte[] rawtxBytes = transaction.bitcoinSerialize();
|
||||||
String rawtxHex = Utils.bytesToHex(rawtxBytes);
|
String rawtxHex = Utils.bytesToHex(rawtxBytes);
|
||||||
|
@ -667,7 +677,12 @@ public class ElectrumServer {
|
||||||
Map<Integer, Double> blockTargetFeeRates = electrumServer.getFeeEstimates(SendController.TARGET_BLOCKS_RANGE);
|
Map<Integer, Double> blockTargetFeeRates = electrumServer.getFeeEstimates(SendController.TARGET_BLOCKS_RANGE);
|
||||||
feeRatesRetrievedAt = System.currentTimeMillis();
|
feeRatesRetrievedAt = System.currentTimeMillis();
|
||||||
|
|
||||||
return new ConnectionEvent(serverVersion, banner, tip.height, tip.getBlockHeader(), blockTargetFeeRates);
|
Double minimumRelayFeeRate = electrumServer.getMinimumRelayFee();
|
||||||
|
for(Integer blockTarget : blockTargetFeeRates.keySet()) {
|
||||||
|
blockTargetFeeRates.computeIfPresent(blockTarget, (blocks, feeRate) -> feeRate < minimumRelayFeeRate ? minimumRelayFeeRate : feeRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ConnectionEvent(serverVersion, banner, tip.height, tip.getBlockHeader(), blockTargetFeeRates, minimumRelayFeeRate);
|
||||||
} else {
|
} else {
|
||||||
if(reader.isAlive()) {
|
if(reader.isAlive()) {
|
||||||
electrumServer.ping();
|
electrumServer.ping();
|
||||||
|
|
|
@ -29,5 +29,7 @@ public interface ElectrumServerRpc {
|
||||||
|
|
||||||
Map<Integer, Double> getFeeEstimates(Transport transport, List<Integer> targetBlocks);
|
Map<Integer, Double> getFeeEstimates(Transport transport, List<Integer> targetBlocks);
|
||||||
|
|
||||||
|
Double getMinimumRelayFee(Transport transport);
|
||||||
|
|
||||||
String broadcastTransaction(Transport transport, String txHex);
|
String broadcastTransaction(Transport transport, String txHex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,16 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getMinimumRelayFee(Transport transport) {
|
||||||
|
try {
|
||||||
|
JsonRpcClient client = new JsonRpcClient(transport);
|
||||||
|
return client.createRequest().returnAs(Double.class).method("blockchain.relayfee").id(1).execute();
|
||||||
|
} catch(JsonRpcException e) {
|
||||||
|
throw new ElectrumServerRpcException("Error getting minimum relay fee", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String broadcastTransaction(Transport transport, String txHex) {
|
public String broadcastTransaction(Transport transport, String txHex) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -306,7 +306,9 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
));
|
));
|
||||||
validationSupport.registerValidator(fee, Validator.combine(
|
validationSupport.registerValidator(fee, Validator.combine(
|
||||||
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Insufficient Inputs", userFeeSet.get() && insufficientInputsProperty.get()),
|
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Insufficient Inputs", userFeeSet.get() && insufficientInputsProperty.get()),
|
||||||
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Insufficient Fee", getFeeValueSats() != null && getFeeValueSats() == 0)
|
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Insufficient Fee", getFeeValueSats() != null && getFeeValueSats() == 0),
|
||||||
|
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Insufficient Fee Rate", walletTransactionProperty.get() != null &&
|
||||||
|
(double)walletTransactionProperty.get().getFee() / walletTransactionProperty.get().getTransaction().getVirtualSize() < AppController.getMinimumRelayFeeRate())
|
||||||
));
|
));
|
||||||
|
|
||||||
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
|
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
|
||||||
|
@ -445,7 +447,7 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
LinkedHashMap::new));
|
LinkedHashMap::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
return retrievedFeeRates;
|
return retrievedFeeRates;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Double getFeeRate() {
|
private Double getFeeRate() {
|
||||||
|
|
Loading…
Reference in a new issue