Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend FeeRateService to support multiple API endpoints #4247

Merged
Merged
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,13 @@ configure(project(':pricenode')) {
compile("org.knowm.xchange:xchange-poloniex:$knowmXchangeVersion")
compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
testCompile "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
testRuntime("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
}

test {
useJUnitPlatform()
}

task stage {
Expand Down
9 changes: 9 additions & 0 deletions pricenode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,12 @@ curl -s https://raw.githubusercontent.com/bisq-network/bisq/master/pricenode/ins

- [README-HEROKU.md](README-HEROKU.md)
- [docker/README.md](docker/README.md)


## Bitcoin mining fee estimates

The pricenode exposes a service API to Bisq clients under `/getFees`.

This API returns a mining fee rate estimate, representing an average of several mining fee rate values retrieved from different `mempool.space` instances.

To configure which `mempool.space` instances are queried to calculate this average, see the relevant section in the file `application.properties`.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
*/
public abstract class FeeRateProvider extends PriceProvider<FeeRate> {

public static final long MIN_FEE_RATE = 10; // satoshi/byte
public static final long MAX_FEE_RATE = 1000;

public FeeRateProvider(Duration refreshInterval) {
super(refreshInterval);
}
Expand Down
45 changes: 39 additions & 6 deletions pricenode/src/main/java/bisq/price/mining/FeeRateService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,69 @@

import org.springframework.stereotype.Service;

import java.time.Instant;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
* High-level mining {@link FeeRate} operations.
*/
@Service
class FeeRateService {

private final Set<FeeRateProvider> providers;
private final List<FeeRateProvider> providers;

public FeeRateService(Set<FeeRateProvider> providers) {
/**
* Construct a {@link FeeRateService} with a list of all {@link FeeRateProvider}
* implementations discovered via classpath scanning.
*
* @param providers all {@link FeeRateProvider} implementations in ascending
* order of precedence
*/
public FeeRateService(List<FeeRateProvider> providers) {
this.providers = providers;
}

public Map<String, Object> getFees() {
Map<String, Long> metadata = new HashMap<>();
Map<String, Long> allFeeRates = new HashMap<>();

AtomicLong sumOfAllFeeRates = new AtomicLong();
AtomicInteger amountOfFeeRates = new AtomicInteger();

// Process each provider, retrieve and store their fee rate
providers.forEach(p -> {
FeeRate feeRate = p.get();
String currency = feeRate.getCurrency();
if ("BTC".equals(currency)) {
metadata.put("bitcoinFeesTs", feeRate.getTimestamp());
sumOfAllFeeRates.getAndAdd(feeRate.getPrice());
amountOfFeeRates.getAndAdd(1);
}
allFeeRates.put(currency.toLowerCase() + "TxFee", feeRate.getPrice());
});

return new HashMap<String, Object>() {{
// Calculate the average
long averageFeeRate = (amountOfFeeRates.intValue() > 0)
? sumOfAllFeeRates.longValue() / amountOfFeeRates.intValue()
: FeeRateProvider.MIN_FEE_RATE;

// Make sure the returned value is within the min-max range
averageFeeRate = Math.max(averageFeeRate, FeeRateProvider.MIN_FEE_RATE);
averageFeeRate = Math.min(averageFeeRate, FeeRateProvider.MAX_FEE_RATE);

// Prepare response: Add timestamp of now
// Since this is an average, the timestamp is associated with when the moment in
// time when the avg was computed
metadata.put("bitcoinFeesTs", Instant.now().getEpochSecond());

// Prepare response: Add the fee average
allFeeRates.put("btcTxFee", averageFeeRate);

// Build response
return new HashMap<>() {{
putAll(metadata);
put("dataMap", allFeeRates);
}};
Expand Down

This file was deleted.

Loading