From 0f366517e177fb491bb844e880bfdd5175b67adf Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Sat, 16 Sep 2023 14:08:41 +0200 Subject: [PATCH 1/2] CryptoYa: Create ExchangeRate per exchange CryptoYa queries 20 exchanges and returns their data. It makes more sense to pass the data from each exchange separately to the ExchangeRateService. The ExchangeRateService aggregates all exchange rates later. --- .../bisq/price/spot/providers/CryptoYa.java | 50 ++++++---- .../util/cryptoya/CryptoYaMarketData.java | 92 ------------------- .../price/util/cryptoya/CryptoYaTicker.java | 29 +++++- 3 files changed, 57 insertions(+), 114 deletions(-) delete mode 100644 src/main/java/bisq/price/util/cryptoya/CryptoYaMarketData.java diff --git a/src/main/java/bisq/price/spot/providers/CryptoYa.java b/src/main/java/bisq/price/spot/providers/CryptoYa.java index 43d1b3c..a031356 100644 --- a/src/main/java/bisq/price/spot/providers/CryptoYa.java +++ b/src/main/java/bisq/price/spot/providers/CryptoYa.java @@ -19,17 +19,19 @@ import bisq.price.spot.ExchangeRate; import bisq.price.spot.ExchangeRateProvider; -import bisq.price.util.cryptoya.CryptoYaMarketData; +import bisq.price.util.cryptoya.CryptoYaTicker; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.env.Environment; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; import java.time.Duration; +import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.OptionalDouble; -import java.util.Set; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; /** * CryptoYa is used only for Argentina Peso (ARS). @@ -39,44 +41,52 @@ * This ExchangeRateProvider provides a real market rate (black or "blue") for ARS/BTC */ @Component -class CryptoYa extends ExchangeRateProvider implements BlueRateProvider { +public class CryptoYa extends ExchangeRateProvider implements BlueRateProvider { + public static final String PROVIDER_NAME = "CRYPTOYA"; private static final String CRYPTO_YA_BTC_ARS_API_URL = "https://criptoya.com/api/btc/ars/0.1"; private final WebClient webClient = WebClient.create(); public CryptoYa(Environment env) { - super(env, "CRYPTOYA", "cryptoya", Duration.ofMinutes(1)); + super(env, PROVIDER_NAME, "cryptoya", Duration.ofMinutes(1)); } /** - * * @return average price buy/sell price averaging different providers suported by cryptoya api * which uses the free market (or blue, or unofficial) ARS price for BTC */ @Override public Set doGet() { - CryptoYaMarketData cryptoYaMarketData = fetchArsBlueMarketData(); - OptionalDouble arsBlueRate = cryptoYaMarketData.averagedArsBlueRateFromLast24Hours(); + Map cryptoYaMarketData = fetchArsBlueMarketData(); - if (arsBlueRate.isPresent()) { - ExchangeRate exchangeRate = new ExchangeRate( - "ARS", - arsBlueRate.getAsDouble(), - System.currentTimeMillis(), - this.getName()); - return Set.of(exchangeRate); - } + Instant yesterdayInstant = Instant.now() + .minus(1, ChronoUnit.DAYS); - return Collections.emptySet(); + return cryptoYaMarketData.entrySet() + .stream() + .map(cryptoYaEntryToExchangeRate(yesterdayInstant)) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toUnmodifiableSet()); } - private CryptoYaMarketData fetchArsBlueMarketData() { + private Map fetchArsBlueMarketData() { return webClient.get() .uri(CRYPTO_YA_BTC_ARS_API_URL) .accept(MediaType.APPLICATION_JSON) .retrieve() - .bodyToMono(CryptoYaMarketData.class) + .bodyToMono(new ParameterizedTypeReference>() { + }) .block(Duration.of(30, ChronoUnit.SECONDS)); } + + private Function, Optional> cryptoYaEntryToExchangeRate( + Instant newerThanInstant) { + return entry -> { + String exchangeName = entry.getKey(); + CryptoYaTicker ticker = entry.getValue(); + return ticker.toExchangeRate(exchangeName, newerThanInstant); + }; + } } diff --git a/src/main/java/bisq/price/util/cryptoya/CryptoYaMarketData.java b/src/main/java/bisq/price/util/cryptoya/CryptoYaMarketData.java deleted file mode 100644 index 72dd529..0000000 --- a/src/main/java/bisq/price/util/cryptoya/CryptoYaMarketData.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq 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. - * - * Bisq 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 Bisq. If not, see . - */ - -package bisq.price.util.cryptoya; - - -import lombok.Getter; -import lombok.Setter; - -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Objects; -import java.util.OptionalDouble; -import java.util.stream.Stream; - -@Getter -@Setter -public class CryptoYaMarketData { - - private CryptoYaTicker argenbtc; - private CryptoYaTicker buenbit; - private CryptoYaTicker ripio; - private CryptoYaTicker ripioexchange; - private CryptoYaTicker satoshitango; - private CryptoYaTicker cryptomkt; - private CryptoYaTicker decrypto; - private CryptoYaTicker latamex; - private CryptoYaTicker bitso; - private CryptoYaTicker letsbit; - private CryptoYaTicker fiwind; - private CryptoYaTicker lemoncash; - private CryptoYaTicker bitmonedero; - private CryptoYaTicker belo; - private CryptoYaTicker tiendacrypto; - private CryptoYaTicker saldo; - private CryptoYaTicker kriptonmarket; - private CryptoYaTicker calypso; - private CryptoYaTicker bybit; - private CryptoYaTicker binance; - - public OptionalDouble averagedArsBlueRateFromLast24Hours() { - long yesterdayTimestamp = Instant.now() - .minus(1, ChronoUnit.DAYS) - .getEpochSecond(); - - return allTickersAsStream() - .filter(Objects::nonNull) - .filter(rate -> rate.getTime() > yesterdayTimestamp) - .mapToDouble(CryptoYaTicker::getAsk) - .filter(ask -> ask > 0) - .average(); - } - - private Stream allTickersAsStream() { - return Stream.of( - argenbtc, - buenbit, - ripio, - ripioexchange, - satoshitango, - cryptomkt, - decrypto, - latamex, - bitso, - letsbit, - fiwind, - lemoncash, - bitmonedero, - belo, - tiendacrypto, - saldo, - kriptonmarket, - calypso, - bybit, - binance - ); - } -} diff --git a/src/main/java/bisq/price/util/cryptoya/CryptoYaTicker.java b/src/main/java/bisq/price/util/cryptoya/CryptoYaTicker.java index 9a1657d..0e7ea1c 100644 --- a/src/main/java/bisq/price/util/cryptoya/CryptoYaTicker.java +++ b/src/main/java/bisq/price/util/cryptoya/CryptoYaTicker.java @@ -17,21 +17,46 @@ package bisq.price.util.cryptoya; +import bisq.price.spot.ExchangeRate; +import bisq.price.spot.providers.CryptoYa; import lombok.Getter; import lombok.Setter; +import java.time.Instant; +import java.util.Optional; + @Getter @Setter public class CryptoYaTicker { private double ask; - private double totalAsk; private double bid; - private double totalBid; private long time; + public Optional toExchangeRate(String exchangeName, Instant newerThan) { + if (isTooOld(newerThan) || isAskZeroOrNegative()) { + return Optional.empty(); + } + + return Optional.of( + new ExchangeRate( + "ARS", + ask, + System.currentTimeMillis(), + CryptoYa.PROVIDER_NAME + ": " + exchangeName + ) + ); + } + + private boolean isTooOld(Instant newerThan) { + return time <= newerThan.getEpochSecond(); + } + + private boolean isAskZeroOrNegative() { + return ask <= 0; + } } From 8068ce784f8e8409998aed3459eb148c856017d7 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Sun, 17 Sep 2023 15:52:18 +0200 Subject: [PATCH 2/2] ExchangeRateService: Filter by provider names with startsWith --- src/main/java/bisq/price/spot/ExchangeRateService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/bisq/price/spot/ExchangeRateService.java b/src/main/java/bisq/price/spot/ExchangeRateService.java index a7c0c93..ca9b2b8 100644 --- a/src/main/java/bisq/price/spot/ExchangeRateService.java +++ b/src/main/java/bisq/price/spot/ExchangeRateService.java @@ -237,7 +237,7 @@ private Map getMetadata(ExchangeRateProvider provider) { private long getTimestamp(ExchangeRateProvider provider, Set exchangeRates) { return exchangeRates.stream() - .filter(e -> provider.getName().equals(e.getProvider())) + .filter(e -> e.getProvider().startsWith(provider.getName())) .findFirst() .orElseThrow(() -> new IllegalStateException("No exchange rate data found for " + provider.getName())) .getTimestamp();