mirror of
https://github.com/boldsuck/haveno.git
synced 2025-01-08 17:19:29 +00:00
update price node from upstream, fix XMR price, default port 8078
Co-authored-by: Christoph Atteneder <christoph.atteneder@gmail.com> Co-authored-by: wiz <j@wiz.biz> Co-authored-by: jmacxx <47253594+jmacxx@users.noreply.github.com> Co-authored-by: Stephan Oeste <emzy@emzy.de> Co-authored-by: Chris Beams <chris@beams.io>
This commit is contained in:
parent
45a61ae835
commit
e864210f4b
58 changed files with 343 additions and 442 deletions
66
build.gradle
66
build.gradle
|
@ -491,51 +491,57 @@ configure(project(':monitor')) {
|
||||||
configure(project(':pricenode')) {
|
configure(project(':pricenode')) {
|
||||||
apply plugin: "org.springframework.boot"
|
apply plugin: "org.springframework.boot"
|
||||||
|
|
||||||
|
apply plugin: 'io.spring.dependency-management'
|
||||||
|
|
||||||
|
mainClassName = 'bisq.price.Main'
|
||||||
|
|
||||||
version = file("src/main/resources/version.txt").text.trim()
|
version = file("src/main/resources/version.txt").text.trim()
|
||||||
|
|
||||||
jar.manifest.attributes(
|
jar.manifest.attributes(
|
||||||
"Implementation-Title": project.name,
|
"Implementation-Title": project.name,
|
||||||
"Implementation-Version": version)
|
"Implementation-Version": version)
|
||||||
|
|
||||||
|
ext['log4j2.version'] = '2.17.0'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(":core")
|
implementation project(":common")
|
||||||
|
implementation project(":core")
|
||||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||||
|
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||||
implementation "com.google.code.gson:gson:$gsonVersion"
|
implementation "com.google.code.gson:gson:$gsonVersion"
|
||||||
|
implementation "com.google.guava:guava:$guavaVersion"
|
||||||
implementation "commons-codec:commons-codec:$codecVersion"
|
implementation "commons-codec:commons-codec:$codecVersion"
|
||||||
implementation "org.apache.httpcomponents:httpcore:$httpcoreVersion"
|
implementation "org.apache.httpcomponents:httpcore:$httpcoreVersion"
|
||||||
implementation("org.apache.httpcomponents:httpclient:$httpclientVersion") {
|
implementation("org.apache.httpcomponents:httpclient:$httpclientVersion") {
|
||||||
exclude(module: 'commons-codec')
|
exclude(module: 'commons-codec')
|
||||||
}
|
}
|
||||||
compile("org.knowm.xchange:xchange-bitbay:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-binance:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-btcmarkets:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-bitbay:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-binance:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-bitfinex:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-bitfinex:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-bitflyer:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-bitflyer:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-bitstamp:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-bitstamp:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-btcmarkets:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-cexio:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-cexio:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-coinmate:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-coinmarketcap:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-coinmarketcap:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-coinmate:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-coinone:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-coinone:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-exmo:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-exmo:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-hitbtc:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-hitbtc:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-huobi:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-huobi:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-independentreserve:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-independentreserve:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-kraken:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-kraken:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-luno:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-luno:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-mercadobitcoin:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-mercadobitcoin:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-paribu:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-paribu:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-poloniex:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-poloniex:$knowmXchangeVersion")
|
||||||
compile("org.knowm.xchange:xchange-quoine:$knowmXchangeVersion")
|
implementation("org.knowm.xchange:xchange-quoine:$knowmXchangeVersion")
|
||||||
compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
|
implementation("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")
|
|
||||||
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
||||||
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||||
|
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||||
|
testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
|
||||||
|
testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
|
||||||
|
testImplementation "org.mockito:mockito-core:$mockitoVersion"
|
||||||
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|
|
@ -110,9 +110,11 @@ public class Config {
|
||||||
public static final String API_PORT = "apiPort";
|
public static final String API_PORT = "apiPort";
|
||||||
public static final String PREVENT_PERIODIC_SHUTDOWN_AT_SEED_NODE = "preventPeriodicShutdownAtSeedNode";
|
public static final String PREVENT_PERIODIC_SHUTDOWN_AT_SEED_NODE = "preventPeriodicShutdownAtSeedNode";
|
||||||
public static final String REPUBLISH_MAILBOX_ENTRIES = "republishMailboxEntries";
|
public static final String REPUBLISH_MAILBOX_ENTRIES = "republishMailboxEntries";
|
||||||
|
public static final String LEGACY_FEE_DATAMAP = "dataMap";
|
||||||
public static final String BTC_TX_FEE = "btcTxFee";
|
public static final String BTC_TX_FEE = "btcTxFee";
|
||||||
public static final String BTC_MIN_TX_FEE = "btcMinTxFee";
|
public static final String BTC_MIN_TX_FEE = "btcMinTxFee";
|
||||||
public static final String BTC_FEES_TS = "bitcoinFeesTs";
|
public static final String BTC_FEES_TS = "bitcoinFeesTs";
|
||||||
|
public static final String BTC_FEE_INFO = "bitcoinFeeInfo";
|
||||||
public static final String BYPASS_MEMPOOL_VALIDATION = "bypassMempoolValidation";
|
public static final String BYPASS_MEMPOOL_VALIDATION = "bypassMempoolValidation";
|
||||||
public static final String PASSWORD_REQUIRED = "passwordRequired";
|
public static final String PASSWORD_REQUIRED = "passwordRequired";
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ To manually test endpoints, run each of the following:
|
||||||
curl http://localhost:8080/getAllMarketPrices
|
curl http://localhost:8080/getAllMarketPrices
|
||||||
curl http://localhost:8080/getFees
|
curl http://localhost:8080/getFees
|
||||||
curl http://localhost:8080/getParams
|
curl http://localhost:8080/getParams
|
||||||
curl http://localhost:8080/getVersion
|
|
||||||
curl http://localhost:8080/info
|
curl http://localhost:8080/info
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Bisq Price Node
|
Description=Haveno Price Node
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
SyslogIdentifier=bisq-pricenode
|
SyslogIdentifier=Haveno-pricenode
|
||||||
EnvironmentFile=/etc/default/bisq-pricenode.env
|
EnvironmentFile=/etc/default/Haveno-pricenode.env
|
||||||
ExecStart=/bisq/bisq/bisq-pricenode 2
|
ExecStart=/Haveno/Haveno/Haveno-pricenode 2
|
||||||
ExecStop=/bin/kill -TERM ${MAINPID}
|
ExecStop=/bin/kill -TERM ${MAINPID}
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
||||||
User=bisq
|
User=Haveno
|
||||||
Group=bisq
|
Group=Haveno
|
||||||
|
|
||||||
PrivateTmp=true
|
PrivateTmp=true
|
||||||
ProtectSystem=full
|
ProtectSystem=full
|
||||||
|
|
|
@ -16,7 +16,7 @@ HAVENO_USER=haveno
|
||||||
HAVENO_GROUP=haveno
|
HAVENO_GROUP=haveno
|
||||||
HAVENO_HOME=/haveno
|
HAVENO_HOME=/haveno
|
||||||
|
|
||||||
HAVENO_REPO_URL=https://github.com/haveno-dex/haveno
|
HAVENO_REPO_URL=https://github.com/haveno-network/haveno
|
||||||
HAVENO_REPO_NAME=haveno
|
HAVENO_REPO_NAME=haveno
|
||||||
HAVENO_REPO_TAG=master
|
HAVENO_REPO_TAG=master
|
||||||
HAVENO_LATEST_RELEASE=master
|
HAVENO_LATEST_RELEASE=master
|
||||||
|
|
|
@ -78,13 +78,14 @@ public abstract class PriceProvider<T> implements SmartLifecycle, Supplier<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refresh() {
|
private void refresh() {
|
||||||
long ts = System.currentTimeMillis();
|
try {
|
||||||
|
long ts = System.currentTimeMillis();
|
||||||
cachedResult = doGet();
|
cachedResult = doGet();
|
||||||
|
log.info("refresh took {} ms.", (System.currentTimeMillis() - ts));
|
||||||
log.info("refresh took {} ms.", (System.currentTimeMillis() - ts));
|
onRefresh();
|
||||||
|
} catch (Exception e) {
|
||||||
onRefresh();
|
log.warn("Error refreshing price provider {}", getClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract T doGet();
|
protected abstract T doGet();
|
||||||
|
|
|
@ -26,7 +26,8 @@ import java.time.Duration;
|
||||||
*/
|
*/
|
||||||
public abstract class FeeRateProvider extends PriceProvider<FeeRate> {
|
public abstract class FeeRateProvider extends PriceProvider<FeeRate> {
|
||||||
|
|
||||||
public static final long MIN_FEE_RATE = 10; // satoshi/vbyte
|
public static final long MIN_FEE_RATE_FOR_WITHDRAWAL = 2; // satoshi/vbyte
|
||||||
|
public static final long MIN_FEE_RATE_FOR_TRADING = 10; // satoshi/vbyte
|
||||||
public static final long MAX_FEE_RATE = 1000;
|
public static final long MAX_FEE_RATE = 1000;
|
||||||
|
|
||||||
public FeeRateProvider(Duration refreshInterval) {
|
public FeeRateProvider(Duration refreshInterval) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory;
|
||||||
* High-level mining {@link FeeRate} operations.
|
* High-level mining {@link FeeRate} operations.
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
class FeeRateService {
|
public class FeeRateService {
|
||||||
|
|
||||||
private final List<FeeRateProvider> providers;
|
private final List<FeeRateProvider> providers;
|
||||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
@ -78,15 +78,15 @@ class FeeRateService {
|
||||||
// Calculate the average
|
// Calculate the average
|
||||||
long averageFeeRate = (amountOfFeeRates.intValue() > 0)
|
long averageFeeRate = (amountOfFeeRates.intValue() > 0)
|
||||||
? sumOfAllFeeRates.longValue() / amountOfFeeRates.intValue()
|
? sumOfAllFeeRates.longValue() / amountOfFeeRates.intValue()
|
||||||
: FeeRateProvider.MIN_FEE_RATE;
|
: FeeRateProvider.MIN_FEE_RATE_FOR_TRADING;
|
||||||
long averageMinFeeRate = (amountOfFeeRates.intValue() > 0)
|
long averageMinFeeRate = (amountOfFeeRates.intValue() > 0)
|
||||||
? sumOfAllMinFeeRates.longValue() / amountOfFeeRates.intValue()
|
? sumOfAllMinFeeRates.longValue() / amountOfFeeRates.intValue()
|
||||||
: FeeRateProvider.MIN_FEE_RATE;
|
: FeeRateProvider.MIN_FEE_RATE_FOR_WITHDRAWAL;
|
||||||
|
|
||||||
// Make sure the returned value is within the min-max range
|
// Make sure the returned value is within the min-max range
|
||||||
averageFeeRate = Math.max(averageFeeRate, FeeRateProvider.MIN_FEE_RATE);
|
averageFeeRate = Math.max(averageFeeRate, FeeRateProvider.MIN_FEE_RATE_FOR_TRADING);
|
||||||
averageFeeRate = Math.min(averageFeeRate, FeeRateProvider.MAX_FEE_RATE);
|
averageFeeRate = Math.min(averageFeeRate, FeeRateProvider.MAX_FEE_RATE);
|
||||||
averageMinFeeRate = Math.max(averageMinFeeRate, FeeRateProvider.MIN_FEE_RATE);
|
averageMinFeeRate = Math.max(averageMinFeeRate, FeeRateProvider.MIN_FEE_RATE_FOR_WITHDRAWAL);
|
||||||
averageMinFeeRate = Math.min(averageMinFeeRate, FeeRateProvider.MAX_FEE_RATE);
|
averageMinFeeRate = Math.min(averageMinFeeRate, FeeRateProvider.MAX_FEE_RATE);
|
||||||
|
|
||||||
// Prepare response: Add timestamp of now
|
// Prepare response: Add timestamp of now
|
||||||
|
@ -101,7 +101,7 @@ class FeeRateService {
|
||||||
// Build response
|
// Build response
|
||||||
return new HashMap<>() {{
|
return new HashMap<>() {{
|
||||||
putAll(metadata);
|
putAll(metadata);
|
||||||
put("dataMap", allFeeRates);
|
put(Config.LEGACY_FEE_DATAMAP, allFeeRates);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,24 +85,24 @@ abstract class MempoolFeeRateProvider extends FeeRateProvider {
|
||||||
log.error("Error retrieving bitcoin mining fee estimation: " + e.getMessage());
|
log.error("Error retrieving bitcoin mining fee estimation: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FeeRate("BTC", MIN_FEE_RATE, MIN_FEE_RATE, Instant.now().getEpochSecond());
|
return new FeeRate("BTC", MIN_FEE_RATE_FOR_TRADING, MIN_FEE_RATE_FOR_WITHDRAWAL, Instant.now().getEpochSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
private FeeRate getEstimatedFeeRate() {
|
private FeeRate getEstimatedFeeRate() {
|
||||||
Set<Map.Entry<String, Long>> feeRatePredictions = getFeeRatePredictions();
|
Set<Map.Entry<String, Long>> feeRatePredictions = getFeeRatePredictions();
|
||||||
long estimatedFeeRate = feeRatePredictions.stream()
|
long estimatedFeeRate = feeRatePredictions.stream()
|
||||||
.filter(p -> p.getKey().equalsIgnoreCase("fastestFee"))
|
.filter(p -> p.getKey().equalsIgnoreCase("halfHourFee"))
|
||||||
.map(Map.Entry::getValue)
|
.map(Map.Entry::getValue)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.map(r -> Math.max(r, MIN_FEE_RATE))
|
.map(r -> Math.max(r, MIN_FEE_RATE_FOR_TRADING))
|
||||||
.map(r -> Math.min(r, MAX_FEE_RATE))
|
.map(r -> Math.min(r, MAX_FEE_RATE))
|
||||||
.orElse(MIN_FEE_RATE);
|
.orElse(MIN_FEE_RATE_FOR_TRADING);
|
||||||
long minimumFee = feeRatePredictions.stream()
|
long minimumFee = feeRatePredictions.stream()
|
||||||
.filter(p -> p.getKey().equalsIgnoreCase("minimumFee"))
|
.filter(p -> p.getKey().equalsIgnoreCase("minimumFee"))
|
||||||
.map(Map.Entry::getValue)
|
.map(Map.Entry::getValue)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.map(r -> Math.multiplyExact(r, 2)) // multiply the minimumFee by 2 (per wiz)
|
.map(r -> Math.multiplyExact(r, 2)) // multiply the minimumFee by 2 (per wiz)
|
||||||
.orElse(MIN_FEE_RATE);
|
.orElse(MIN_FEE_RATE_FOR_WITHDRAWAL);
|
||||||
log.info("Retrieved estimated mining fee of {} sat/vB and minimumFee of {} sat/vB from {}", estimatedFeeRate, minimumFee, getMempoolApiHostname());
|
log.info("Retrieved estimated mining fee of {} sat/vB and minimumFee of {} sat/vB from {}", estimatedFeeRate, minimumFee, getMempoolApiHostname());
|
||||||
return new FeeRate("BTC", estimatedFeeRate, minimumFee, Instant.now().getEpochSecond());
|
return new FeeRate("BTC", estimatedFeeRate, minimumFee, Instant.now().getEpochSecond());
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
package bisq.price.spot;
|
package bisq.price.spot;
|
||||||
|
|
||||||
import bisq.price.PriceController;
|
import bisq.price.PriceController;
|
||||||
|
import bisq.price.mining.FeeRateService;
|
||||||
|
|
||||||
|
import bisq.common.config.Config;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
@ -28,13 +31,28 @@ import java.util.Map;
|
||||||
class ExchangeRateController extends PriceController {
|
class ExchangeRateController extends PriceController {
|
||||||
|
|
||||||
private final ExchangeRateService exchangeRateService;
|
private final ExchangeRateService exchangeRateService;
|
||||||
|
private final FeeRateService feeRateService;
|
||||||
|
|
||||||
public ExchangeRateController(ExchangeRateService exchangeRateService) {
|
public ExchangeRateController(ExchangeRateService exchangeRateService, FeeRateService feeRateService) {
|
||||||
this.exchangeRateService = exchangeRateService;
|
this.exchangeRateService = exchangeRateService;
|
||||||
|
this.feeRateService = feeRateService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(path = "/getAllMarketPrices")
|
@GetMapping(path = "/getAllMarketPrices")
|
||||||
public Map<String, Object> getAllMarketPrices() {
|
public Map<String, Object> getAllMarketPrices() {
|
||||||
return exchangeRateService.getAllMarketPrices();
|
Map<String, Object> retVal = exchangeRateService.getAllMarketPrices();
|
||||||
|
|
||||||
|
// add the fee info to results
|
||||||
|
feeRateService.getFees().forEach((key, value) -> {
|
||||||
|
retVal.put(translateFieldName(key), value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String translateFieldName(String name) {
|
||||||
|
if (name.equals(Config.LEGACY_FEE_DATAMAP))
|
||||||
|
name = Config.BTC_FEE_INFO; // name changed for clarity
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,14 @@ import org.knowm.xchange.service.marketdata.MarketDataService;
|
||||||
import org.knowm.xchange.service.marketdata.params.CurrencyPairsParam;
|
import org.knowm.xchange.service.marketdata.params.CurrencyPairsParam;
|
||||||
import org.knowm.xchange.service.marketdata.params.Params;
|
import org.knowm.xchange.service.marketdata.params.Params;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -59,21 +62,56 @@ import java.util.stream.Stream;
|
||||||
*/
|
*/
|
||||||
public abstract class ExchangeRateProvider extends PriceProvider<Set<ExchangeRate>> {
|
public abstract class ExchangeRateProvider extends PriceProvider<Set<ExchangeRate>> {
|
||||||
|
|
||||||
public static final Set<String> SUPPORTED_CRYPTO_CURRENCIES = CurrencyUtil.getAllSortedCryptoCurrencies().stream()
|
private static Set<String> SUPPORTED_CRYPTO_CURRENCIES = new HashSet<>();
|
||||||
.map(TradeCurrency::getCode)
|
private static Set<String> SUPPORTED_FIAT_CURRENCIES = new HashSet<>();
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
public static final Set<String> SUPPORTED_FIAT_CURRENCIES = CurrencyUtil.getAllSortedFiatCurrencies().stream()
|
|
||||||
.map(TradeCurrency::getCode)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String prefix;
|
private final String prefix;
|
||||||
|
private final Environment env;
|
||||||
|
|
||||||
public ExchangeRateProvider(String name, String prefix, Duration refreshInterval) {
|
public ExchangeRateProvider(Environment env, String name, String prefix, Duration refreshInterval) {
|
||||||
super(refreshInterval);
|
super(refreshInterval);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
|
this.env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getSupportedFiatCurrencies() {
|
||||||
|
if (SUPPORTED_FIAT_CURRENCIES.isEmpty()) { // one-time initialization
|
||||||
|
List<String> excludedFiatCurrencies =
|
||||||
|
Arrays.asList(env.getProperty("bisq.price.fiatcurrency.excluded", "")
|
||||||
|
.toUpperCase().trim().split("\\s*,\\s*"));
|
||||||
|
String validatedExclusionList = excludedFiatCurrencies.stream()
|
||||||
|
.filter(ccy -> !ccy.isEmpty())
|
||||||
|
.filter(CurrencyUtil::isFiatCurrency)
|
||||||
|
.collect(Collectors.toList()).toString();
|
||||||
|
SUPPORTED_FIAT_CURRENCIES = CurrencyUtil.getAllSortedFiatCurrencies().stream()
|
||||||
|
.map(TradeCurrency::getCode)
|
||||||
|
.filter(ccy -> !validatedExclusionList.contains(ccy.toUpperCase()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
log.info("fiat currencies excluded: {}", validatedExclusionList);
|
||||||
|
log.info("fiat currencies supported: {}", SUPPORTED_FIAT_CURRENCIES.size());
|
||||||
|
}
|
||||||
|
return SUPPORTED_FIAT_CURRENCIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getSupportedCryptoCurrencies() {
|
||||||
|
if (SUPPORTED_CRYPTO_CURRENCIES.isEmpty()) { // one-time initialization
|
||||||
|
List<String> excludedCryptoCurrencies =
|
||||||
|
Arrays.asList(env.getProperty("bisq.price.cryptocurrency.excluded", "")
|
||||||
|
.toUpperCase().trim().split("\\s*,\\s*"));
|
||||||
|
String validatedExclusionList = excludedCryptoCurrencies.stream()
|
||||||
|
.filter(ccy -> !ccy.isEmpty())
|
||||||
|
.filter(CurrencyUtil::isCryptoCurrency)
|
||||||
|
.collect(Collectors.toList()).toString();
|
||||||
|
SUPPORTED_CRYPTO_CURRENCIES = CurrencyUtil.getAllSortedCryptoCurrencies().stream()
|
||||||
|
.map(TradeCurrency::getCode)
|
||||||
|
.filter(ccy -> !validatedExclusionList.contains(ccy.toUpperCase()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
SUPPORTED_CRYPTO_CURRENCIES.add("XMR"); // XMR is skipped because it's a base currency
|
||||||
|
log.info("crypto currencies excluded: {}", validatedExclusionList);
|
||||||
|
log.info("crypto currencies supported: {}", SUPPORTED_CRYPTO_CURRENCIES.size());
|
||||||
|
}
|
||||||
|
return SUPPORTED_CRYPTO_CURRENCIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@ -87,7 +125,7 @@ public abstract class ExchangeRateProvider extends PriceProvider<Set<ExchangeRat
|
||||||
@Override
|
@Override
|
||||||
protected void onRefresh() {
|
protected void onRefresh() {
|
||||||
get().stream()
|
get().stream()
|
||||||
.filter(e -> "USD".equals(e.getCurrency()) || "LTC".equals(e.getCurrency()))
|
.filter(e -> "USD".equals(e.getCurrency()) || "XMR".equals(e.getCurrency()) || "ETH".equals(e.getCurrency()) || "BCH".equals(e.getCurrency()))
|
||||||
.forEach(e -> log.info("BTC/{}: {}", e.getCurrency(), e.getPrice()));
|
.forEach(e -> log.info("BTC/{}: {}", e.getCurrency(), e.getPrice()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,13 +157,13 @@ public abstract class ExchangeRateProvider extends PriceProvider<Set<ExchangeRat
|
||||||
// Find the desired fiat pairs (pair format is BTC-FIAT)
|
// Find the desired fiat pairs (pair format is BTC-FIAT)
|
||||||
List<CurrencyPair> desiredFiatPairs = allCurrencyPairsOnExchange.stream()
|
List<CurrencyPair> desiredFiatPairs = allCurrencyPairsOnExchange.stream()
|
||||||
.filter(cp -> cp.base.equals(Currency.BTC))
|
.filter(cp -> cp.base.equals(Currency.BTC))
|
||||||
.filter(cp -> SUPPORTED_FIAT_CURRENCIES.contains(cp.counter.getCurrencyCode()))
|
.filter(cp -> getSupportedFiatCurrencies().contains(cp.counter.getCurrencyCode()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// Find the desired altcoin pairs (pair format is ALT-BTC)
|
// Find the desired altcoin pairs (pair format is ALT-BTC)
|
||||||
List<CurrencyPair> desiredCryptoPairs = allCurrencyPairsOnExchange.stream()
|
List<CurrencyPair> desiredCryptoPairs = allCurrencyPairsOnExchange.stream()
|
||||||
.filter(cp -> cp.counter.equals(Currency.BTC))
|
.filter(cp -> cp.counter.equals(Currency.BTC))
|
||||||
.filter(cp -> SUPPORTED_CRYPTO_CURRENCIES.contains(cp.base.getCurrencyCode()))
|
.filter(cp -> getSupportedCryptoCurrencies().contains(cp.base.getCurrencyCode()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// Retrieve in bulk all tickers offered by the exchange
|
// Retrieve in bulk all tickers offered by the exchange
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.btcmarkets.BTCMarketsExchange;
|
import org.knowm.xchange.btcmarkets.BTCMarketsExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class BTCMarkets extends ExchangeRateProvider {
|
class BTCMarkets extends ExchangeRateProvider {
|
||||||
|
|
||||||
public BTCMarkets() {
|
public BTCMarkets(Environment env) {
|
||||||
super("BTCMARKETS", "btcmarkets", Duration.ofMinutes(1));
|
super(env, "BTCMARKETS", "btcmarkets", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.binance.BinanceExchange;
|
import org.knowm.xchange.binance.BinanceExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Binance extends ExchangeRateProvider {
|
class Binance extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Binance() {
|
public Binance(Environment env) {
|
||||||
super("BINANCE", "binance", Duration.ofMinutes(1));
|
super(env, "BINANCE", "binance", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.bitbay.BitbayExchange;
|
import org.knowm.xchange.bitbay.BitbayExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Bitbay extends ExchangeRateProvider {
|
class Bitbay extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Bitbay() {
|
public Bitbay(Environment env) {
|
||||||
super("BITBAY", "bitbay", Duration.ofMinutes(1));
|
super(env, "BITBAY", "bitbay", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@ package bisq.price.spot.providers;
|
||||||
import bisq.price.spot.ExchangeRate;
|
import bisq.price.spot.ExchangeRate;
|
||||||
import bisq.price.spot.ExchangeRateProvider;
|
import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -34,12 +35,12 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class BitcoinAverage extends ExchangeRateProvider {
|
class BitcoinAverage extends ExchangeRateProvider {
|
||||||
|
|
||||||
public BitcoinAverage() {
|
public BitcoinAverage(Environment env) {
|
||||||
// Simulate a deactivated BitcoinAverage provider
|
// Simulate a deactivated BitcoinAverage provider
|
||||||
// We still need the class to exist and be registered as a provider though,
|
// We still need the class to exist and be registered as a provider though,
|
||||||
// because the returned data structure must contain the "btcAverageTs" key
|
// because the returned data structure must contain the "btcAverageTs" key
|
||||||
// for backward compatibility with Bisq clients which hardcode that key
|
// for backward compatibility with Bisq clients which hardcode that key
|
||||||
super("BA", "btcAverage", Duration.ofMinutes(100));
|
super(env, "BA", "btcAverage", Duration.ofMinutes(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.bitfinex.BitfinexExchange;
|
import org.knowm.xchange.bitfinex.BitfinexExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Bitfinex extends ExchangeRateProvider {
|
class Bitfinex extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Bitfinex() {
|
public Bitfinex(Environment env) {
|
||||||
super("BITFINEX", "bitfinex", Duration.ofMinutes(1));
|
super(env, "BITFINEX", "bitfinex", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.bitflyer.BitflyerExchange;
|
import org.knowm.xchange.bitflyer.BitflyerExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Bitflyer extends ExchangeRateProvider {
|
class Bitflyer extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Bitflyer() {
|
public Bitflyer(Environment env) {
|
||||||
super("BITFLYER", "bitflyer", Duration.ofMinutes(1));
|
super(env, "BITFLYER", "bitflyer", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Haveno.
|
|
||||||
*
|
|
||||||
* Haveno is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Haveno is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package bisq.price.spot.providers;
|
|
||||||
|
|
||||||
import bisq.price.spot.ExchangeRate;
|
|
||||||
import bisq.price.spot.ExchangeRateProvider;
|
|
||||||
import bisq.price.util.bitpay.BitpayMarketData;
|
|
||||||
import bisq.price.util.bitpay.BitpayTicker;
|
|
||||||
|
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
|
||||||
import org.springframework.http.RequestEntity;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
class Bitpay extends ExchangeRateProvider {
|
|
||||||
|
|
||||||
private final RestTemplate restTemplate = new RestTemplate();
|
|
||||||
|
|
||||||
public Bitpay() {
|
|
||||||
super("BITPAY", "bitpay", Duration.ofMinutes(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ExchangeRate> doGet() {
|
|
||||||
|
|
||||||
Set<ExchangeRate> result = new HashSet<ExchangeRate>();
|
|
||||||
|
|
||||||
Predicate<BitpayTicker> isDesiredFiatPair = t -> SUPPORTED_FIAT_CURRENCIES.contains(t.getCode());
|
|
||||||
Predicate<BitpayTicker> isDesiredCryptoPair = t -> SUPPORTED_CRYPTO_CURRENCIES.contains(t.getCode());
|
|
||||||
|
|
||||||
getTickers()
|
|
||||||
.filter(isDesiredFiatPair.or(isDesiredCryptoPair))
|
|
||||||
.forEach(ticker -> {
|
|
||||||
boolean useInverseRate = false;
|
|
||||||
if (SUPPORTED_CRYPTO_CURRENCIES.contains(ticker.getCode())) {
|
|
||||||
// Use inverse rate for alts, because the API returns the
|
|
||||||
// conversion rate in the opposite direction than what we need
|
|
||||||
// API returns the BTC/Alt rate, we need the Alt/BTC rate
|
|
||||||
useInverseRate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BigDecimal rate = ticker.getRate();
|
|
||||||
// Find the inverse rate, while using enough decimals to reflect very
|
|
||||||
// small exchange rates
|
|
||||||
BigDecimal inverseRate = (rate.compareTo(BigDecimal.ZERO) > 0) ?
|
|
||||||
BigDecimal.ONE.divide(rate, 8, RoundingMode.HALF_UP) :
|
|
||||||
BigDecimal.ZERO;
|
|
||||||
|
|
||||||
result.add(new ExchangeRate(
|
|
||||||
ticker.getCode(),
|
|
||||||
(useInverseRate ? inverseRate : rate),
|
|
||||||
new Date(),
|
|
||||||
this.getName()
|
|
||||||
));
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream<BitpayTicker> getTickers() {
|
|
||||||
BitpayMarketData marketData = restTemplate.exchange(
|
|
||||||
RequestEntity
|
|
||||||
.get(UriComponentsBuilder
|
|
||||||
.fromUriString("https://bitpay.com/rates").build()
|
|
||||||
.toUri())
|
|
||||||
.build(),
|
|
||||||
new ParameterizedTypeReference<BitpayMarketData>() {
|
|
||||||
}
|
|
||||||
).getBody();
|
|
||||||
|
|
||||||
return Arrays.stream(marketData.getData());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.bitstamp.BitstampExchange;
|
import org.knowm.xchange.bitstamp.BitstampExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Bitstamp extends ExchangeRateProvider {
|
class Bitstamp extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Bitstamp() {
|
public Bitstamp(Environment env) {
|
||||||
super("BITSTAMP", "bitstamp", Duration.ofMinutes(1));
|
super(env, "BITSTAMP", "bitstamp", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
import bisq.price.util.coingecko.CoinGeckoMarketData;
|
import bisq.price.util.coingecko.CoinGeckoMarketData;
|
||||||
|
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.http.RequestEntity;
|
import org.springframework.http.RequestEntity;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
@ -44,8 +45,8 @@ class CoinGecko extends ExchangeRateProvider {
|
||||||
|
|
||||||
private final RestTemplate restTemplate = new RestTemplate();
|
private final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
|
||||||
public CoinGecko() {
|
public CoinGecko(Environment env) {
|
||||||
super("COINGECKO", "coingecko", Duration.ofMinutes(1));
|
super(env, "COINGECKO", "coingecko", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,8 +57,8 @@ class CoinGecko extends ExchangeRateProvider {
|
||||||
|
|
||||||
Set<ExchangeRate> result = new HashSet<ExchangeRate>();
|
Set<ExchangeRate> result = new HashSet<ExchangeRate>();
|
||||||
|
|
||||||
Predicate<Map.Entry> isDesiredFiatPair = t -> SUPPORTED_FIAT_CURRENCIES.contains(t.getKey());
|
Predicate<Map.Entry> isDesiredFiatPair = t -> getSupportedFiatCurrencies().contains(t.getKey());
|
||||||
Predicate<Map.Entry> isDesiredCryptoPair = t -> SUPPORTED_CRYPTO_CURRENCIES.contains(t.getKey());
|
Predicate<Map.Entry> isDesiredCryptoPair = t -> getSupportedCryptoCurrencies().contains(t.getKey());
|
||||||
|
|
||||||
getMarketData().getRates().entrySet().stream()
|
getMarketData().getRates().entrySet().stream()
|
||||||
.filter(isDesiredFiatPair.or(isDesiredCryptoPair))
|
.filter(isDesiredFiatPair.or(isDesiredCryptoPair))
|
||||||
|
@ -65,7 +66,7 @@ class CoinGecko extends ExchangeRateProvider {
|
||||||
.forEach((key, ticker) -> {
|
.forEach((key, ticker) -> {
|
||||||
|
|
||||||
boolean useInverseRate = false;
|
boolean useInverseRate = false;
|
||||||
if (SUPPORTED_CRYPTO_CURRENCIES.contains(key)) {
|
if (getSupportedCryptoCurrencies().contains(key)) {
|
||||||
// Use inverse rate for alts, because the API returns the
|
// Use inverse rate for alts, because the API returns the
|
||||||
// conversion rate in the opposite direction than what we need
|
// conversion rate in the opposite direction than what we need
|
||||||
// API returns the BTC/Alt rate, we need the Alt/BTC rate
|
// API returns the BTC/Alt rate, we need the Alt/BTC rate
|
||||||
|
|
|
@ -20,6 +20,7 @@ package bisq.price.spot.providers;
|
||||||
import bisq.price.spot.ExchangeRate;
|
import bisq.price.spot.ExchangeRate;
|
||||||
import bisq.price.spot.ExchangeRateProvider;
|
import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -33,8 +34,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class CoinMarketCap extends ExchangeRateProvider {
|
class CoinMarketCap extends ExchangeRateProvider {
|
||||||
|
|
||||||
public CoinMarketCap() {
|
public CoinMarketCap(Environment env) {
|
||||||
super("CMC", "coinmarketcap", Duration.ofMinutes(5)); // large data structure, so don't request it too often
|
super(env, "CMC", "coinmarketcap", Duration.ofMinutes(5)); // large data structure, so don't request it too often
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.coinone.CoinoneExchange;
|
import org.knowm.xchange.coinone.CoinoneExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Coinone extends ExchangeRateProvider {
|
class Coinone extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Coinone() {
|
public Coinone(Environment env) {
|
||||||
super("COINONE", "coinone", Duration.ofMinutes(1));
|
super(env, "COINONE", "coinone", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
import bisq.price.util.coinpaprika.CoinpaprikaMarketData;
|
import bisq.price.util.coinpaprika.CoinpaprikaMarketData;
|
||||||
|
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.http.RequestEntity;
|
import org.springframework.http.RequestEntity;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
@ -55,8 +56,8 @@ class Coinpaprika extends ExchangeRateProvider {
|
||||||
"INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK")
|
"INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK")
|
||||||
.replace(" ", ""); // Strip any spaces
|
.replace(" ", ""); // Strip any spaces
|
||||||
|
|
||||||
public Coinpaprika() {
|
public Coinpaprika(Environment env) {
|
||||||
super("COINPAPRIKA", "coinpaprika", Duration.ofMinutes(1));
|
super(env, "COINPAPRIKA", "coinpaprika", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -67,7 +68,7 @@ class Coinpaprika extends ExchangeRateProvider {
|
||||||
|
|
||||||
Set<ExchangeRate> result = new HashSet<ExchangeRate>();
|
Set<ExchangeRate> result = new HashSet<ExchangeRate>();
|
||||||
|
|
||||||
Predicate<Map.Entry> isDesiredFiatPair = t -> SUPPORTED_FIAT_CURRENCIES.contains(t.getKey());
|
Predicate<Map.Entry> isDesiredFiatPair = t -> getSupportedFiatCurrencies().contains(t.getKey());
|
||||||
|
|
||||||
getMarketData().getQuotes().entrySet().stream()
|
getMarketData().getQuotes().entrySet().stream()
|
||||||
.filter(isDesiredFiatPair)
|
.filter(isDesiredFiatPair)
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Haveno.
|
|
||||||
*
|
|
||||||
* Haveno is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Haveno is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package bisq.price.spot.providers;
|
|
||||||
|
|
||||||
import bisq.price.spot.ExchangeRate;
|
|
||||||
import bisq.price.spot.ExchangeRateProvider;
|
|
||||||
|
|
||||||
import org.knowm.xchange.exmo.ExmoExchange;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
class Exmo extends ExchangeRateProvider {
|
|
||||||
|
|
||||||
public Exmo() {
|
|
||||||
// API rate limit = 10 calls / second from the same IP ( see https://exmo.com/en/api )
|
|
||||||
super("EXMO", "exmo", Duration.ofMinutes(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ExchangeRate> doGet() {
|
|
||||||
// Supported fiat: EUR, PLN, RUB, UAH (Ukrainian hryvnia), USD
|
|
||||||
// Supported alts: DASH, DOGE, ETC, ETH, LTC, XMR, ZEC
|
|
||||||
return doGet(ExmoExchange.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.huobi.HuobiExchange;
|
import org.knowm.xchange.huobi.HuobiExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Huobi extends ExchangeRateProvider {
|
class Huobi extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Huobi() {
|
public Huobi(Environment env) {
|
||||||
super("HUOBI", "huobi", Duration.ofMinutes(1));
|
super(env, "HUOBI", "huobi", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.independentreserve.IndependentReserveExchange;
|
import org.knowm.xchange.independentreserve.IndependentReserveExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class IndependentReserve extends ExchangeRateProvider {
|
class IndependentReserve extends ExchangeRateProvider {
|
||||||
|
|
||||||
public IndependentReserve() {
|
public IndependentReserve(Environment env) {
|
||||||
super("IndependentReserve", "independentreserve", Duration.ofMinutes(1));
|
super(env, "IndependentReserve", "independentreserve", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.kraken.KrakenExchange;
|
import org.knowm.xchange.kraken.KrakenExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Kraken extends ExchangeRateProvider {
|
class Kraken extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Kraken() {
|
public Kraken(Environment env) {
|
||||||
super("KRAKEN", "kraken", Duration.ofMinutes(1));
|
super(env, "KRAKEN", "kraken", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.luno.LunoExchange;
|
import org.knowm.xchange.luno.LunoExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Luno extends ExchangeRateProvider {
|
class Luno extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Luno() {
|
public Luno(Environment env) {
|
||||||
super("LUNO", "luno", Duration.ofMinutes(1));
|
super(env, "LUNO", "luno", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.mercadobitcoin.MercadoBitcoinExchange;
|
import org.knowm.xchange.mercadobitcoin.MercadoBitcoinExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class MercadoBitcoin extends ExchangeRateProvider {
|
class MercadoBitcoin extends ExchangeRateProvider {
|
||||||
|
|
||||||
public MercadoBitcoin() {
|
public MercadoBitcoin(Environment env) {
|
||||||
super("MercadoBitcoin", "mercadobitcoin", Duration.ofMinutes(1));
|
super(env, "MercadoBitcoin", "mercadobitcoin", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.paribu.ParibuExchange;
|
import org.knowm.xchange.paribu.ParibuExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Paribu extends ExchangeRateProvider {
|
class Paribu extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Paribu() {
|
public Paribu(Environment env) {
|
||||||
super("PARIBU", "paribu", Duration.ofMinutes(1));
|
super(env, "PARIBU", "paribu", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.poloniex.PoloniexExchange;
|
import org.knowm.xchange.poloniex.PoloniexExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Poloniex extends ExchangeRateProvider {
|
class Poloniex extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Poloniex() {
|
public Poloniex(Environment env) {
|
||||||
super("POLO", "poloniex", Duration.ofMinutes(1));
|
super(env, "POLO", "poloniex", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,6 +22,7 @@ import bisq.price.spot.ExchangeRateProvider;
|
||||||
|
|
||||||
import org.knowm.xchange.quoine.QuoineExchange;
|
import org.knowm.xchange.quoine.QuoineExchange;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -31,8 +32,8 @@ import java.util.Set;
|
||||||
@Component
|
@Component
|
||||||
class Quoine extends ExchangeRateProvider {
|
class Quoine extends ExchangeRateProvider {
|
||||||
|
|
||||||
public Quoine() {
|
public Quoine(Environment env) {
|
||||||
super("QUOINE", "quoine", Duration.ofMinutes(1));
|
super(env, "QUOINE", "quoine", Duration.ofMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Haveno.
|
|
||||||
*
|
|
||||||
* Haveno is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Haveno is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package bisq.price.util;
|
|
||||||
|
|
||||||
import bisq.price.PriceController;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.actuate.info.Info;
|
|
||||||
import org.springframework.boot.actuate.info.InfoContributor;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
class VersionController extends PriceController implements InfoContributor {
|
|
||||||
|
|
||||||
private final String version;
|
|
||||||
|
|
||||||
public VersionController(@Value("classpath:version.txt") Resource versionTxt) throws IOException {
|
|
||||||
this.version = FileCopyUtils.copyToString(
|
|
||||||
new InputStreamReader(
|
|
||||||
versionTxt.getInputStream()
|
|
||||||
)
|
|
||||||
).trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(path = "/getVersion")
|
|
||||||
public String getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void contribute(Info.Builder builder) {
|
|
||||||
builder.withDetail("version", version);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
server.port=8078
|
||||||
spring.jackson.serialization.indent_output=true
|
spring.jackson.serialization.indent_output=true
|
||||||
|
|
||||||
# To enable another fee estimation endpoint, simply uncomment one of the following lines
|
# To enable another fee estimation endpoint, simply uncomment one of the following lines
|
||||||
|
@ -7,3 +8,5 @@ bisq.price.mining.providers.mempoolHostname.2=mempool.emzy.de
|
||||||
bisq.price.mining.providers.mempoolHostname.3=mempool.ninja
|
bisq.price.mining.providers.mempoolHostname.3=mempool.ninja
|
||||||
bisq.price.mining.providers.mempoolHostname.4=mempool.bisq.services
|
bisq.price.mining.providers.mempoolHostname.4=mempool.bisq.services
|
||||||
# bisq.price.mining.providers.mempoolHostname.5=someHostOrIP
|
# bisq.price.mining.providers.mempoolHostname.5=someHostOrIP
|
||||||
|
bisq.price.fiatcurrency.excluded=LBP,ARS
|
||||||
|
bisq.price.cryptocurrency.excluded=
|
||||||
|
|
|
@ -30,7 +30,7 @@ public abstract class AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
assertTrue(retrievedExchangeRates.size() > 0);
|
assertTrue(retrievedExchangeRates.size() > 0);
|
||||||
checkProviderCurrencyPairs(retrievedExchangeRates);
|
checkProviderCurrencyPairs(exchangeProvider, retrievedExchangeRates);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,24 +40,24 @@ public abstract class AbstractExchangeRateProviderTest {
|
||||||
*
|
*
|
||||||
* @param retrievedExchangeRates Exchange rates retrieved from the provider
|
* @param retrievedExchangeRates Exchange rates retrieved from the provider
|
||||||
*/
|
*/
|
||||||
private void checkProviderCurrencyPairs(Set<ExchangeRate> retrievedExchangeRates) {
|
private void checkProviderCurrencyPairs(ExchangeRateProvider exchangeProvider, Set<ExchangeRate> retrievedExchangeRates) {
|
||||||
Set<String> retrievedRatesCurrencies = retrievedExchangeRates.stream()
|
Set<String> retrievedRatesCurrencies = retrievedExchangeRates.stream()
|
||||||
.map(ExchangeRate::getCurrency)
|
.map(ExchangeRate::getCurrency)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
Set<String> supportedFiatCurrenciesRetrieved = ExchangeRateProvider.SUPPORTED_FIAT_CURRENCIES.stream()
|
Set<String> supportedFiatCurrenciesRetrieved = exchangeProvider.getSupportedFiatCurrencies().stream()
|
||||||
.filter(f -> retrievedRatesCurrencies.contains(f))
|
.filter(f -> retrievedRatesCurrencies.contains(f))
|
||||||
.collect(Collectors.toCollection(TreeSet::new));
|
.collect(Collectors.toCollection(TreeSet::new));
|
||||||
log.info("Retrieved rates for supported fiat currencies: " + supportedFiatCurrenciesRetrieved);
|
log.info("Retrieved rates for supported fiat currencies: " + supportedFiatCurrenciesRetrieved);
|
||||||
|
|
||||||
Set<String> supportedCryptoCurrenciesRetrieved = ExchangeRateProvider.SUPPORTED_CRYPTO_CURRENCIES.stream()
|
Set<String> supportedCryptoCurrenciesRetrieved = exchangeProvider.getSupportedCryptoCurrencies().stream()
|
||||||
.filter(c -> retrievedRatesCurrencies.contains(c))
|
.filter(c -> retrievedRatesCurrencies.contains(c))
|
||||||
.collect(Collectors.toCollection(TreeSet::new));
|
.collect(Collectors.toCollection(TreeSet::new));
|
||||||
log.info("Retrieved rates for supported altcoins: " + supportedCryptoCurrenciesRetrieved);
|
log.info("Retrieved rates for supported altcoins: " + supportedCryptoCurrenciesRetrieved);
|
||||||
|
|
||||||
Set<String> supportedCurrencies = Sets.union(
|
Set<String> supportedCurrencies = Sets.union(
|
||||||
ExchangeRateProvider.SUPPORTED_CRYPTO_CURRENCIES,
|
exchangeProvider.getSupportedCryptoCurrencies(),
|
||||||
ExchangeRateProvider.SUPPORTED_FIAT_CURRENCIES);
|
exchangeProvider.getSupportedFiatCurrencies());
|
||||||
|
|
||||||
Set unsupportedCurrencies = Sets.difference(retrievedRatesCurrencies, supportedCurrencies);
|
Set unsupportedCurrencies = Sets.difference(retrievedRatesCurrencies, supportedCurrencies);
|
||||||
assertTrue("Retrieved exchange rates contain unsupported currencies: " + unsupportedCurrencies,
|
assertTrue("Retrieved exchange rates contain unsupported currencies: " + unsupportedCurrencies,
|
||||||
|
|
|
@ -47,13 +47,13 @@ public class FeeRateServiceTest {
|
||||||
|
|
||||||
// Even with no working providers, we expect the service to return pre-configured
|
// Even with no working providers, we expect the service to return pre-configured
|
||||||
// minimum fee rate
|
// minimum fee rate
|
||||||
doSanityChecksForRetrievedData(retrievedData, FeeRateProvider.MIN_FEE_RATE);
|
doSanityChecksForRetrievedData(retrievedData, FeeRateProvider.MIN_FEE_RATE_FOR_TRADING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFees_singleProvider_feeBelowMin() {
|
public void getFees_singleProvider_feeBelowMin() {
|
||||||
// One working provider, which returns a fee lower than the minimum
|
// One working provider, which returns a fee lower than the minimum
|
||||||
long providerFee = FeeRateProvider.MIN_FEE_RATE - 3;
|
long providerFee = FeeRateProvider.MIN_FEE_RATE_FOR_TRADING - 3;
|
||||||
FeeRateService service = new FeeRateService(
|
FeeRateService service = new FeeRateService(
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
buildDummyReachableMempoolFeeRateProvider(providerFee)));
|
buildDummyReachableMempoolFeeRateProvider(providerFee)));
|
||||||
|
@ -62,7 +62,7 @@ public class FeeRateServiceTest {
|
||||||
|
|
||||||
// When the provider returns a value below the expected min, the service should
|
// When the provider returns a value below the expected min, the service should
|
||||||
// return the min
|
// return the min
|
||||||
doSanityChecksForRetrievedData(retrievedData, FeeRateProvider.MIN_FEE_RATE);
|
doSanityChecksForRetrievedData(retrievedData, FeeRateProvider.MIN_FEE_RATE_FOR_TRADING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -84,14 +84,14 @@ public class FeeRateServiceTest {
|
||||||
public void getFees_multipleProviders() {
|
public void getFees_multipleProviders() {
|
||||||
// 3 providers, returning 1xMIN, 2xMIN, 3xMIN
|
// 3 providers, returning 1xMIN, 2xMIN, 3xMIN
|
||||||
FeeRateService service = new FeeRateService(asList(
|
FeeRateService service = new FeeRateService(asList(
|
||||||
buildDummyReachableMempoolFeeRateProvider(FeeRateProvider.MIN_FEE_RATE * 1),
|
buildDummyReachableMempoolFeeRateProvider(FeeRateProvider.MIN_FEE_RATE_FOR_TRADING * 1),
|
||||||
buildDummyReachableMempoolFeeRateProvider(FeeRateProvider.MIN_FEE_RATE * 2),
|
buildDummyReachableMempoolFeeRateProvider(FeeRateProvider.MIN_FEE_RATE_FOR_TRADING * 2),
|
||||||
buildDummyReachableMempoolFeeRateProvider(FeeRateProvider.MIN_FEE_RATE * 3)));
|
buildDummyReachableMempoolFeeRateProvider(FeeRateProvider.MIN_FEE_RATE_FOR_TRADING * 3)));
|
||||||
|
|
||||||
Map<String, Object> retrievedData = service.getFees();
|
Map<String, Object> retrievedData = service.getFees();
|
||||||
|
|
||||||
// The service should then return the average, which is 2xMIN
|
// The service should then return the average, which is 2xMIN
|
||||||
doSanityChecksForRetrievedData(retrievedData, FeeRateProvider.MIN_FEE_RATE * 2);
|
doSanityChecksForRetrievedData(retrievedData, FeeRateProvider.MIN_FEE_RATE_FOR_TRADING * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,7 +103,7 @@ public class FeeRateServiceTest {
|
||||||
// providers), we always expect a non-zero timestamp
|
// providers), we always expect a non-zero timestamp
|
||||||
assertNotEquals(0L, retrievedData.get(Config.BTC_FEES_TS));
|
assertNotEquals(0L, retrievedData.get(Config.BTC_FEES_TS));
|
||||||
|
|
||||||
Map<String, String> retrievedDataMap = (Map<String, String>) retrievedData.get("dataMap");
|
Map<String, String> retrievedDataMap = (Map<String, String>) retrievedData.get(Config.LEGACY_FEE_DATAMAP);
|
||||||
assertEquals(2, retrievedDataMap.size());
|
assertEquals(2, retrievedDataMap.size());
|
||||||
assertEquals(expectedFeeRate, retrievedDataMap.get(Config.BTC_TX_FEE));
|
assertEquals(expectedFeeRate, retrievedDataMap.get(Config.BTC_TX_FEE));
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class MempoolFeeRateProviderTest {
|
||||||
FeeRate retrievedFeeRate = feeRateProvider.doGet();
|
FeeRate retrievedFeeRate = feeRateProvider.doGet();
|
||||||
|
|
||||||
// Check that the FeeRateProvider returns a fee within the defined parameters
|
// Check that the FeeRateProvider returns a fee within the defined parameters
|
||||||
assertTrue(retrievedFeeRate.getPrice() >= FeeRateProvider.MIN_FEE_RATE);
|
assertTrue(retrievedFeeRate.getPrice() >= FeeRateProvider.MIN_FEE_RATE_FOR_TRADING);
|
||||||
assertTrue(retrievedFeeRate.getPrice() <= FeeRateProvider.MAX_FEE_RATE);
|
assertTrue(retrievedFeeRate.getPrice() <= FeeRateProvider.MAX_FEE_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class MempoolFeeRateProviderTest {
|
||||||
MempoolFeeRateProvider dummyProvider = new MempoolFeeRateProvider.First(env) {
|
MempoolFeeRateProvider dummyProvider = new MempoolFeeRateProvider.First(env) {
|
||||||
@Override
|
@Override
|
||||||
protected FeeRate doGet() {
|
protected FeeRate doGet() {
|
||||||
return new FeeRate("BTC", feeRate, MIN_FEE_RATE, Instant.now().getEpochSecond());
|
return new FeeRate("BTC", feeRate, MIN_FEE_RATE_FOR_WITHDRAWAL, Instant.now().getEpochSecond());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
|
|
||||||
package bisq.price.spot;
|
package bisq.price.spot;
|
||||||
|
|
||||||
|
import bisq.core.locale.CurrencyUtil;
|
||||||
|
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
|
@ -46,10 +51,9 @@ import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static java.lang.Thread.sleep;
|
import static java.lang.Thread.sleep;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
public class ExchangeRateServiceTest {
|
public class ExchangeRateServiceTest {
|
||||||
|
|
||||||
|
@ -156,6 +160,72 @@ public class ExchangeRateServiceTest {
|
||||||
assertNotEquals(0L, retrievedData.get(dummyProvider2.getPrefix() + "Ts"));
|
assertNotEquals(0L, retrievedData.get(dummyProvider2.getPrefix() + "Ts"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the scenario when currencies are excluded from the PriceNode feed via configuration settings
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void getAllMarketPrices_withMultipleProviders_excludedCurrencyCodes() {
|
||||||
|
String excludedCcyString = "LBP,USD,EUR";
|
||||||
|
Environment mockedEnvironment = mock(Environment.class);
|
||||||
|
when(mockedEnvironment.getProperty(eq("bisq.price.fiatcurrency.excluded"), anyString())).thenReturn(excludedCcyString);
|
||||||
|
|
||||||
|
class MockedExchangeRateProvider extends ExchangeRateProvider {
|
||||||
|
MockedExchangeRateProvider() {
|
||||||
|
super(mockedEnvironment, "ExchangeName", "EXCH", Duration.ofDays(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRunning() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ExchangeRate> doGet() {
|
||||||
|
HashSet<ExchangeRate> exchangeRates = new HashSet<>();
|
||||||
|
// Simulate rates for all the supported ccys
|
||||||
|
for (String rateCurrencyCode : getSupportedFiatCurrencies()) {
|
||||||
|
exchangeRates.add(new ExchangeRate(
|
||||||
|
rateCurrencyCode,
|
||||||
|
RandomUtils.nextDouble(1, 1000), // random price
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
getName())); // ExchangeRateProvider name
|
||||||
|
}
|
||||||
|
return exchangeRates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger exchangeRateProviderLogger;
|
||||||
|
String LIST_APPENDER_NAME2 = "testListAppender2";
|
||||||
|
exchangeRateProviderLogger = (Logger) LoggerFactory.getLogger(MockedExchangeRateProvider.class);
|
||||||
|
ListAppender<ILoggingEvent> listAppender2 = new ListAppender<>();
|
||||||
|
listAppender2.setName(LIST_APPENDER_NAME2);
|
||||||
|
listAppender2.start();
|
||||||
|
exchangeRateProviderLogger.addAppender(listAppender2);
|
||||||
|
|
||||||
|
// we request rates for all currencies, and check that:
|
||||||
|
// (a) the provider supplies more currency rates than the number of currencies we are trying to exclude (sanity test),
|
||||||
|
// (b) the number of missing currency rates equals the number of currencies we told PriceNode to exclude,
|
||||||
|
// (c) none of the rates supplied are for an excluded currency.
|
||||||
|
|
||||||
|
Set<String> excludedFiatCurrencies = new HashSet<>(asList(excludedCcyString.split(",")));
|
||||||
|
MockedExchangeRateProvider mockedExchangeRateProvider = new MockedExchangeRateProvider();
|
||||||
|
Set<ExchangeRate> exchangeRates = mockedExchangeRateProvider.doGet();
|
||||||
|
assertTrue(exchangeRates.size() > excludedFiatCurrencies.size());
|
||||||
|
int numSortedFiatCurrencies = CurrencyUtil.getAllSortedFiatCurrencies().size();
|
||||||
|
int numCurrenciesFromProvider = mockedExchangeRateProvider.getSupportedFiatCurrencies().size();
|
||||||
|
int missingCurrencyCount = numSortedFiatCurrencies - numCurrenciesFromProvider;
|
||||||
|
assertEquals(missingCurrencyCount, excludedFiatCurrencies.size());
|
||||||
|
for (ExchangeRate exchangeRate : exchangeRates) {
|
||||||
|
assertFalse(excludedCcyString.contains(exchangeRate.getCurrency()));
|
||||||
|
}
|
||||||
|
List<ILoggingEvent> logsList = ((ListAppender) exchangeRateProviderLogger.getAppender(LIST_APPENDER_NAME2)).list;
|
||||||
|
assertEquals(3, logsList.size());
|
||||||
|
assertEquals(Level.INFO, logsList.get(1).getLevel());
|
||||||
|
assertTrue(logsList.get(0).getFormattedMessage().endsWith("will refresh every PT24H"));
|
||||||
|
assertTrue(logsList.get(1).getFormattedMessage().endsWith("fiat currencies excluded: [LBP, USD, EUR]"));
|
||||||
|
assertTrue(logsList.get(2).getFormattedMessage().endsWith("fiat currencies supported: " + numCurrenciesFromProvider));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs generic sanity checks on the response format and contents.
|
* Performs generic sanity checks on the response format and contents.
|
||||||
*
|
*
|
||||||
|
@ -259,6 +329,7 @@ public class ExchangeRateServiceTest {
|
||||||
*/
|
*/
|
||||||
private ExchangeRateProvider buildDummyExchangeRateProvider(int numberOfRatesAvailable) {
|
private ExchangeRateProvider buildDummyExchangeRateProvider(int numberOfRatesAvailable) {
|
||||||
ExchangeRateProvider dummyProvider = new ExchangeRateProvider(
|
ExchangeRateProvider dummyProvider = new ExchangeRateProvider(
|
||||||
|
new StandardEnvironment(),
|
||||||
"ExchangeName-" + getRandomAlphaNumericString(5),
|
"ExchangeName-" + getRandomAlphaNumericString(5),
|
||||||
"EXCH-" + getRandomAlphaNumericString(3),
|
"EXCH-" + getRandomAlphaNumericString(3),
|
||||||
Duration.ofDays(1)) {
|
Duration.ofDays(1)) {
|
||||||
|
@ -298,6 +369,7 @@ public class ExchangeRateServiceTest {
|
||||||
|
|
||||||
private ExchangeRateProvider buildDummyExchangeRateProvider(Set<String> rateCurrencyCodes) {
|
private ExchangeRateProvider buildDummyExchangeRateProvider(Set<String> rateCurrencyCodes) {
|
||||||
ExchangeRateProvider dummyProvider = new ExchangeRateProvider(
|
ExchangeRateProvider dummyProvider = new ExchangeRateProvider(
|
||||||
|
new StandardEnvironment(),
|
||||||
"ExchangeName-" + getRandomAlphaNumericString(5),
|
"ExchangeName-" + getRandomAlphaNumericString(5),
|
||||||
"EXCH-" + getRandomAlphaNumericString(3),
|
"EXCH-" + getRandomAlphaNumericString(3),
|
||||||
Duration.ofDays(1)) {
|
Duration.ofDays(1)) {
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class BTCMarketsTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new BTCMarkets());
|
doGet_successfulCall(new BTCMarkets(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class BinanceTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Binance());
|
doGet_successfulCall(new Binance(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class BitbayTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Bitbay());
|
doGet_successfulCall(new Bitbay(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class BitfinexTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Bitfinex());
|
doGet_successfulCall(new Bitfinex(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class BitflyerTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Bitflyer());
|
doGet_successfulCall(new Bitflyer(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Haveno.
|
|
||||||
*
|
|
||||||
* Haveno is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Haveno is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package bisq.price.spot.providers;
|
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class BitpayTest extends AbstractExchangeRateProviderTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void doGet_successfulCall() {
|
|
||||||
doGet_successfulCall(new Bitpay());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class BitstampTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Bitstamp());
|
doGet_successfulCall(new Bitstamp(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class CoinGeckoTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new CoinGecko());
|
doGet_successfulCall(new CoinGecko(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class CoinoneTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Coinone());
|
doGet_successfulCall(new Coinone(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class CoinpaprikaTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Coinpaprika());
|
doGet_successfulCall(new Coinpaprika(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Haveno.
|
|
||||||
*
|
|
||||||
* Haveno is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Haveno is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package bisq.price.spot.providers;
|
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class ExmoTest extends AbstractExchangeRateProviderTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void doGet_successfulCall() {
|
|
||||||
doGet_successfulCall(new Exmo());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class HuobiTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Huobi());
|
doGet_successfulCall(new Huobi(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class IndependentReserveTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new IndependentReserve());
|
doGet_successfulCall(new IndependentReserve(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class KrakenTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Kraken());
|
doGet_successfulCall(new Kraken(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class LunoTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Luno());
|
doGet_successfulCall(new Luno(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class MercadoBitcoinTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new MercadoBitcoin());
|
doGet_successfulCall(new MercadoBitcoin(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class ParibuTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Paribu());
|
doGet_successfulCall(new Paribu(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class PoloniexTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Poloniex());
|
doGet_successfulCall(new Poloniex(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ package bisq.price.spot.providers;
|
||||||
|
|
||||||
import bisq.price.AbstractExchangeRateProviderTest;
|
import bisq.price.AbstractExchangeRateProviderTest;
|
||||||
|
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -28,7 +30,7 @@ public class QuoineTest extends AbstractExchangeRateProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doGet_successfulCall() {
|
public void doGet_successfulCall() {
|
||||||
doGet_successfulCall(new Quoine());
|
doGet_successfulCall(new Quoine(new StandardEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package bisq.price.util;
|
|
||||||
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
public class VersionControllerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getVersion() throws IOException {
|
|
||||||
VersionController controller = new VersionController(
|
|
||||||
new FileSystemResource("src/main/resources/version.txt"));
|
|
||||||
|
|
||||||
String version = controller.getVersion();
|
|
||||||
assertTrue(version.length() > 0);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue