update to new xmr price server api

remove timestamp data structure
This commit is contained in:
woodser 2022-12-12 14:18:08 +00:00
parent 13b5d123bb
commit 9fda20f88b
7 changed files with 21 additions and 59 deletions

View file

@ -24,7 +24,6 @@ import bisq.asset.AssetRegistry;
import bisq.asset.Coin; import bisq.asset.Coin;
import bisq.asset.Token; import bisq.asset.Token;
import bisq.common.app.DevEnv;
import bisq.common.config.BaseCurrencyNetwork; import bisq.common.config.BaseCurrencyNetwork;
import bisq.common.config.Config; import bisq.common.config.Config;

View file

@ -104,7 +104,7 @@ public class ProvidersRepository {
if (useLocalhostForP2P) { if (useLocalhostForP2P) {
// If we run in localhost mode we don't have the tor node running, so we need a clearnet host // If we run in localhost mode we don't have the tor node running, so we need a clearnet host
// Use localhost for using a locally running provider // Use localhost for using a locally running provider
// providerAsString = Collections.singletonList("http://localhost:8080/"); // providers = Collections.singletonList("http://localhost:8078");
providers = Collections.singletonList("https://price.haveno.network/"); // Haveno providers = Collections.singletonList("https://price.haveno.network/"); // Haveno
} else { } else {
providers = DEFAULT_NODES; providers = DEFAULT_NODES;

View file

@ -338,8 +338,7 @@ public class PriceFeedService {
*/ */
public Map<String, MarketPrice> requestAllPrices() throws ExecutionException, InterruptedException, TimeoutException, CancellationException { public Map<String, MarketPrice> requestAllPrices() throws ExecutionException, InterruptedException, TimeoutException, CancellationException {
return new PriceRequest().requestAllPrices(priceProvider) return new PriceRequest().requestAllPrices(priceProvider)
.get(20, TimeUnit.SECONDS) .get(20, TimeUnit.SECONDS);
.second;
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -406,10 +405,10 @@ public class PriceFeedService {
} }
priceRequest = new PriceRequest(); priceRequest = new PriceRequest();
SettableFuture<Tuple2<Map<String, Long>, Map<String, MarketPrice>>> future = priceRequest.requestAllPrices(provider); SettableFuture<Map<String, MarketPrice>> future = priceRequest.requestAllPrices(provider);
Futures.addCallback(future, new FutureCallback<>() { Futures.addCallback(future, new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable Tuple2<Map<String, Long>, Map<String, MarketPrice>> result) { public void onSuccess(@Nullable Map<String, MarketPrice> result) {
UserThread.execute(() -> { UserThread.execute(() -> {
checkNotNull(result, "Result must not be null at requestAllPrices"); checkNotNull(result, "Result must not be null at requestAllPrices");
// Each currency rate has a different timestamp, depending on when // Each currency rate has a different timestamp, depending on when
@ -417,7 +416,7 @@ public class PriceFeedService {
// However, the request timestamp is when the pricenode was queried // However, the request timestamp is when the pricenode was queried
epochInMillisAtLastRequest = System.currentTimeMillis(); epochInMillisAtLastRequest = System.currentTimeMillis();
Map<String, MarketPrice> priceMap = result.second; Map<String, MarketPrice> priceMap = result;
cache.putAll(priceMap); cache.putAll(priceMap);

View file

@ -49,9 +49,9 @@ public class PriceProvider extends HttpClientProvider {
super(httpClient, baseUrl, false); super(httpClient, baseUrl, false);
} }
public synchronized Tuple2<Map<String, Long>, Map<String, MarketPrice>> getAll() throws IOException { public synchronized Map<String, MarketPrice> getAll() throws IOException {
if (shutDownRequested) { if (shutDownRequested) {
return new Tuple2<>(new HashMap<>(), new HashMap<>()); return new HashMap<>();
} }
Map<String, MarketPrice> marketPriceMap = new HashMap<>(); Map<String, MarketPrice> marketPriceMap = new HashMap<>();
@ -59,64 +59,28 @@ public class PriceProvider extends HttpClientProvider {
if (P2PService.getMyNodeAddress() != null) if (P2PService.getMyNodeAddress() != null)
hsVersion = P2PService.getMyNodeAddress().getHostName().length() > 22 ? ", HSv3" : ", HSv2"; hsVersion = P2PService.getMyNodeAddress().getHostName().length() > 22 ? ", HSv3" : ", HSv2";
String json = httpClient.get("getAllMarketPrices", "User-Agent", "bisq/" String json = httpClient.get("getAllMarketPrices", "User-Agent", "haveno/"
+ Version.VERSION + hsVersion); + Version.VERSION + hsVersion);
LinkedTreeMap<?, ?> map = new Gson().fromJson(json, LinkedTreeMap.class); LinkedTreeMap<?, ?> map = new Gson().fromJson(json, LinkedTreeMap.class);
Map<String, Long> tsMap = new HashMap<>();
transfer("btcAverageTs", map, tsMap);
transfer("poloniexTs", map, tsMap);
transfer("coinmarketcapTs", map, tsMap);
// get btc per xmr price to convert all prices to xmr
// TODO (woodser): currently using bisq price feed, switch?
List<?> list = (ArrayList<?>) map.get("data"); List<?> list = (ArrayList<?>) map.get("data");
double btcPerXmr = findBtcPerXmr(list); list.forEach(obj -> {
for (Object obj : list) {
try { try {
LinkedTreeMap<?, ?> treeMap = (LinkedTreeMap<?, ?>) obj; LinkedTreeMap<?, ?> treeMap = (LinkedTreeMap<?, ?>) obj;
String currencyCode = (String) treeMap.get("currencyCode"); String baseCurrencyCode = (String) treeMap.get("baseCurrencyCode");
String counterCurrencyCode = (String) treeMap.get("counterCurrencyCode");
String currencyCode = baseCurrencyCode.equals("XMR") ? counterCurrencyCode : baseCurrencyCode;
double price = (Double) treeMap.get("price"); double price = (Double) treeMap.get("price");
// json uses double for our timestampSec long value... // json uses double for our timestampSec long value...
long timestampSec = MathUtils.doubleToLong((Double) treeMap.get("timestampSec")); long timestampSec = MathUtils.doubleToLong((Double) treeMap.get("timestampSec"));
// convert price from btc to xmr
boolean isFiat = CurrencyUtil.isFiatCurrency(currencyCode);
if (isFiat) price = price * btcPerXmr;
else price = price / btcPerXmr;
// add currency price to map
marketPriceMap.put(currencyCode, new MarketPrice(currencyCode, price, timestampSec, true)); marketPriceMap.put(currencyCode, new MarketPrice(currencyCode, price, timestampSec, true));
} catch (Throwable t) { } catch (Throwable t) {
log.error(t.toString()); log.error(t.toString());
t.printStackTrace(); t.printStackTrace();
} }
}
// add btc to price map, remove xmr since base currency });
marketPriceMap.put("BTC", new MarketPrice("BTC", 1 / btcPerXmr, marketPriceMap.get("XMR").getTimestampSec(), true)); return marketPriceMap;
marketPriceMap.remove("XMR");
return new Tuple2<>(tsMap, marketPriceMap);
}
private void transfer(String key, LinkedTreeMap<?, ?> map, Map<String, Long> tsMap) {
if (map.containsKey(key)) tsMap.put(key, ((Double) map.get(key)).longValue());
else log.warn("No prices returned from provider " + key);
}
/**
* @return price of 1 XMR in BTC
*/
private static double findBtcPerXmr(List<?> list) {
for (Object obj : list) {
LinkedTreeMap<?, ?> treeMap = (LinkedTreeMap<?, ?>) obj;
String currencyCode = (String) treeMap.get("currencyCode");
if ("XMR".equalsIgnoreCase(currencyCode)) {
return (double) treeMap.get("price");
}
}
throw new IllegalStateException("BTC per XMR price not found");
} }
public String getBaseUrl() { public String getBaseUrl() {

View file

@ -45,17 +45,17 @@ public class PriceRequest {
public PriceRequest() { public PriceRequest() {
} }
public SettableFuture<Tuple2<Map<String, Long>, Map<String, MarketPrice>>> requestAllPrices(PriceProvider provider) { public SettableFuture<Map<String, MarketPrice>> requestAllPrices(PriceProvider provider) {
this.provider = provider; this.provider = provider;
String baseUrl = provider.getBaseUrl(); String baseUrl = provider.getBaseUrl();
SettableFuture<Tuple2<Map<String, Long>, Map<String, MarketPrice>>> resultFuture = SettableFuture.create(); SettableFuture<Map<String, MarketPrice>> resultFuture = SettableFuture.create();
ListenableFuture<Tuple2<Map<String, Long>, Map<String, MarketPrice>>> future = executorService.submit(() -> { ListenableFuture<Map<String, MarketPrice>> future = executorService.submit(() -> {
Thread.currentThread().setName("PriceRequest @ " + baseUrl); Thread.currentThread().setName("PriceRequest @ " + baseUrl);
return provider.getAll(); return provider.getAll();
}); });
Futures.addCallback(future, new FutureCallback<>() { Futures.addCallback(future, new FutureCallback<>() {
public void onSuccess(Tuple2<Map<String, Long>, Map<String, MarketPrice>> marketPriceTuple) { public void onSuccess(Map<String, MarketPrice> marketPriceTuple) {
log.trace("Received marketPriceTuple of {}\nfrom provider {}", marketPriceTuple, provider); log.trace("Received marketPriceTuple of {}\nfrom provider {}", marketPriceTuple, provider);
if (!shutDownRequested) { if (!shutDownRequested) {
resultFuture.set(marketPriceTuple); resultFuture.set(marketPriceTuple);

View file

@ -1082,7 +1082,7 @@ setting.about.def=Bisq ist keine Firma, sondern ein Gemeinschaftsprojekt, das of
setting.about.contribute=Mitwirken setting.about.contribute=Mitwirken
setting.about.providers=Datenanbieter setting.about.providers=Datenanbieter
setting.about.apisWithFee=Bisq verwendet die Bisq Preis Indizes für Fiat und Altcoin Preise und die Bisq Mempool Nodes für die Abschätzung der Mining-Gebühr. setting.about.apisWithFee=Bisq verwendet die Bisq Preis Indizes für Fiat und Altcoin Preise und die Bisq Mempool Nodes für die Abschätzung der Mining-Gebühr.
setting.about.apis=Bisq verwendet den Bisq Price Index für Fiat und Altcoin Preise. setting.about.apis=Bisq verwendet den Haveno Price Index für Fiat und Altcoin Preise.
setting.about.pricesProvided=Marktpreise zur Verfügung gestellt von setting.about.pricesProvided=Marktpreise zur Verfügung gestellt von
setting.about.feeEstimation.label=Geschätzte Mining-Gebühr bereitgestellt von setting.about.feeEstimation.label=Geschätzte Mining-Gebühr bereitgestellt von
setting.about.versionDetails=Versionsdetails setting.about.versionDetails=Versionsdetails

View file

@ -489,7 +489,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
private void updateMarketPriceLabel(Label label) { private void updateMarketPriceLabel(Label label) {
if (model.getIsPriceAvailable().get()) { if (model.getIsPriceAvailable().get()) {
if (model.getIsExternallyProvidedPrice().get()) { if (model.getIsExternallyProvidedPrice().get()) {
label.setText(Res.get("mainView.marketPriceWithProvider.label", "Bisq Price Index")); label.setText(Res.get("mainView.marketPriceWithProvider.label", "Haveno Price Index"));
label.setTooltip(new Tooltip(getPriceProviderTooltipString())); label.setTooltip(new Tooltip(getPriceProviderTooltipString()));
} else { } else {
label.setText(Res.get("mainView.marketPrice.bisqInternalPrice")); label.setText(Res.get("mainView.marketPrice.bisqInternalPrice"));
@ -509,7 +509,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
MarketPrice selectedMarketPrice = model.getPriceFeedService().getMarketPrice(selectedCurrencyCode); MarketPrice selectedMarketPrice = model.getPriceFeedService().getMarketPrice(selectedCurrencyCode);
return Res.get("mainView.marketPrice.tooltip", return Res.get("mainView.marketPrice.tooltip",
"Bisq Price Index for " + selectedCurrencyCode, "Haveno Price Index for " + selectedCurrencyCode,
"", "",
selectedMarketPrice != null ? DisplayUtils.formatTime(new Date(selectedMarketPrice.getTimestampSec())) : Res.get("shared.na"), selectedMarketPrice != null ? DisplayUtils.formatTime(new Date(selectedMarketPrice.getTimestampSec())) : Res.get("shared.na"),
model.getPriceFeedService().getProviderNodeAddress()); model.getPriceFeedService().getProviderNodeAddress());