12 changed files with 215 additions and 59 deletions
@ -1,15 +0,0 @@ |
|||||
package com.sparrowwallet.sparrow.event; |
|
||||
|
|
||||
import com.sparrowwallet.sparrow.wallet.FeeRateSelection; |
|
||||
|
|
||||
public class FeeRateSelectionChangedEvent { |
|
||||
private final FeeRateSelection feeRateSelection; |
|
||||
|
|
||||
public FeeRateSelectionChangedEvent(FeeRateSelection feeRateSelection) { |
|
||||
this.feeRateSelection = feeRateSelection; |
|
||||
} |
|
||||
|
|
||||
public FeeRateSelection getFeeRateSelection() { |
|
||||
return feeRateSelection; |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,15 @@ |
|||||
|
package com.sparrowwallet.sparrow.event; |
||||
|
|
||||
|
import com.sparrowwallet.sparrow.wallet.FeeRatesSelection; |
||||
|
|
||||
|
public class FeeRatesSelectionChangedEvent { |
||||
|
private final FeeRatesSelection feeRatesSelection; |
||||
|
|
||||
|
public FeeRatesSelectionChangedEvent(FeeRatesSelection feeRatesSelection) { |
||||
|
this.feeRatesSelection = feeRatesSelection; |
||||
|
} |
||||
|
|
||||
|
public FeeRatesSelection getFeeRateSelection() { |
||||
|
return feeRatesSelection; |
||||
|
} |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package com.sparrowwallet.sparrow.event; |
||||
|
|
||||
|
import com.sparrowwallet.sparrow.net.FeeRatesSource; |
||||
|
|
||||
|
public class FeeRatesSourceChangedEvent { |
||||
|
private final FeeRatesSource feeRatesSource; |
||||
|
|
||||
|
public FeeRatesSourceChangedEvent(FeeRatesSource feeRatesSource) { |
||||
|
this.feeRatesSource = feeRatesSource; |
||||
|
} |
||||
|
|
||||
|
public FeeRatesSource getFeeRateSource() { |
||||
|
return feeRatesSource; |
||||
|
} |
||||
|
} |
@ -0,0 +1,102 @@ |
|||||
|
package com.sparrowwallet.sparrow.net; |
||||
|
|
||||
|
import com.google.common.net.HostAndPort; |
||||
|
import com.google.gson.Gson; |
||||
|
import com.sparrowwallet.sparrow.io.Config; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
|
||||
|
import java.io.InputStream; |
||||
|
import java.io.InputStreamReader; |
||||
|
import java.io.Reader; |
||||
|
import java.net.InetSocketAddress; |
||||
|
import java.net.Proxy; |
||||
|
import java.net.URL; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.util.Collections; |
||||
|
import java.util.LinkedHashMap; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
public enum FeeRatesSource { |
||||
|
ELECTRUM_SERVER("Electrum Server") { |
||||
|
@Override |
||||
|
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { |
||||
|
return Collections.emptyMap(); |
||||
|
} |
||||
|
}, |
||||
|
MEMPOOL_SPACE("mempool.space") { |
||||
|
@Override |
||||
|
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { |
||||
|
String url = "https://mempool.space/api/v1/fees/recommended"; |
||||
|
return getThreeTierFeeRates(defaultblockTargetFeeRates, url); |
||||
|
} |
||||
|
}, |
||||
|
BITCOINFEES_EARN_COM("bitcoinfees.earn.com") { |
||||
|
@Override |
||||
|
public Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates) { |
||||
|
String url = "https://bitcoinfees.earn.com/api/v1/fees/recommended"; |
||||
|
return getThreeTierFeeRates(defaultblockTargetFeeRates, url); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
private static final Logger log = LoggerFactory.getLogger(FeeRatesSource.class); |
||||
|
|
||||
|
private final String name; |
||||
|
|
||||
|
FeeRatesSource(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public abstract Map<Integer, Double> getBlockTargetFeeRates(Map<Integer, Double> defaultblockTargetFeeRates); |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
private static Map<Integer, Double> getThreeTierFeeRates(Map<Integer, Double> defaultblockTargetFeeRates, String url) { |
||||
|
Proxy proxy = getProxy(); |
||||
|
|
||||
|
Map<Integer, Double> blockTargetFeeRates = new LinkedHashMap<>(); |
||||
|
try(InputStream is = (proxy == null ? new URL(url).openStream() : new URL(url).openConnection(proxy).getInputStream()); Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { |
||||
|
Gson gson = new Gson(); |
||||
|
ThreeTierRates threeTierRates = gson.fromJson(reader, ThreeTierRates.class); |
||||
|
for(Integer blockTarget : defaultblockTargetFeeRates.keySet()) { |
||||
|
if(blockTarget < 3) { |
||||
|
blockTargetFeeRates.put(blockTarget, threeTierRates.fastestFee); |
||||
|
} else if(blockTarget < 6) { |
||||
|
blockTargetFeeRates.put(blockTarget, threeTierRates.halfHourFee); |
||||
|
} else if(blockTarget <= 10 || defaultblockTargetFeeRates.get(blockTarget) > threeTierRates.hourFee) { |
||||
|
blockTargetFeeRates.put(blockTarget, threeTierRates.hourFee); |
||||
|
} else { |
||||
|
blockTargetFeeRates.put(blockTarget, defaultblockTargetFeeRates.get(blockTarget)); |
||||
|
} |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
log.warn("Error retrieving recommended fee rates from " + url, e); |
||||
|
} |
||||
|
|
||||
|
return blockTargetFeeRates; |
||||
|
} |
||||
|
|
||||
|
private static Proxy getProxy() { |
||||
|
Config config = Config.get(); |
||||
|
if(config.isUseProxy()) { |
||||
|
HostAndPort proxy = HostAndPort.fromString(config.getProxyServer()); |
||||
|
InetSocketAddress proxyAddress = new InetSocketAddress(proxy.getHost(), proxy.getPortOrDefault(ProxyTcpOverTlsTransport.DEFAULT_PROXY_PORT)); |
||||
|
return new Proxy(Proxy.Type.SOCKS, proxyAddress); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
private static class ThreeTierRates { |
||||
|
Double fastestFee; |
||||
|
Double halfHourFee; |
||||
|
Double hourFee; |
||||
|
} |
||||
|
} |
@ -1,11 +1,11 @@ |
|||||
package com.sparrowwallet.sparrow.wallet; |
package com.sparrowwallet.sparrow.wallet; |
||||
|
|
||||
public enum FeeRateSelection { |
public enum FeeRatesSelection { |
||||
BLOCK_TARGET("Block Target"), MEMPOOL_SIZE("Mempool Size"); |
BLOCK_TARGET("Block Target"), MEMPOOL_SIZE("Mempool Size"); |
||||
|
|
||||
private final String name; |
private final String name; |
||||
|
|
||||
private FeeRateSelection(String name) { |
private FeeRatesSelection(String name) { |
||||
this.name = name; |
this.name = name; |
||||
} |
} |
||||
|
|
Loading…
Reference in new issue