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(); 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; + } }