From 39e66cbc206e90f0a6ce9b02c3936c73eaff8f07 Mon Sep 17 00:00:00 2001 From: Stephane Janel Date: Sun, 5 Nov 2023 12:53:20 +0100 Subject: [PATCH] Clean up code around fiat converter --- src/api/common/include/fiatconverter.hpp | 1 - src/api/common/src/fiatconverter.cpp | 16 ++--- src/api/common/test/fiatconverter_test.cpp | 66 +++++++++---------- .../include/staticcommandlineoptioncheck.hpp | 20 +++--- src/objects/include/market.hpp | 2 +- src/objects/include/monetaryamount.hpp | 2 +- src/tech/include/cct_hash.hpp | 1 - src/tech/include/timedef.hpp | 20 +++--- 8 files changed, 60 insertions(+), 68 deletions(-) diff --git a/src/api/common/include/fiatconverter.hpp b/src/api/common/include/fiatconverter.hpp index 67b4a943..c66cbbe4 100644 --- a/src/api/common/include/fiatconverter.hpp +++ b/src/api/common/include/fiatconverter.hpp @@ -3,7 +3,6 @@ #include #include -#include "cachedresult.hpp" #include "cct_string.hpp" #include "curlhandle.hpp" #include "currencycode.hpp" diff --git a/src/api/common/src/fiatconverter.cpp b/src/api/common/src/fiatconverter.cpp index 0d43a74c..bcb70da6 100644 --- a/src/api/common/src/fiatconverter.cpp +++ b/src/api/common/src/fiatconverter.cpp @@ -27,7 +27,8 @@ string LoadCurrencyConverterAPIKey(std::string_view dataDir) { static constexpr std::string_view kThirdPartySecretFileName = "thirdparty_secret.json"; File thirdPartySecret(dataDir, File::Type::kSecret, kThirdPartySecretFileName, File::IfError::kNoThrow); json data = thirdPartySecret.readAllJson(); - if (data.empty() || data["freecurrencyconverter"].get() == kDefaultCommunityKey) { + auto freeConverterIt = data.find("freecurrencyconverter"); + if (freeConverterIt == data.end() || freeConverterIt->get() == kDefaultCommunityKey) { log::warn("Unable to find custom Free Currency Converter key in {}", kThirdPartySecretFileName); log::warn("If you want to use extensively coincenter, please create your own key by going to"); log::warn("https://free.currencyconverterapi.com/free-api-key and place it in"); @@ -36,7 +37,7 @@ string LoadCurrencyConverterAPIKey(std::string_view dataDir) { log::warn("Using default key provided as a demo to the community"); return string(kDefaultCommunityKey); } - return data["freecurrencyconverter"]; + return std::move(freeConverterIt->get_ref()); } constexpr std::string_view kRatesCacheFile = "ratescache.json"; @@ -45,7 +46,7 @@ File GetRatesCacheFile(std::string_view dataDir) { return {dataDir, File::Type::kCache, kRatesCacheFile, File::IfError::kNoThrow}; } -constexpr std::string_view kFiatConverterBaseUrl = "https://free.currconv.com/api"; +constexpr std::string_view kFiatConverterBaseUrl = "https://free.currconv.com"; } // namespace FiatConverter::FiatConverter(const CoincenterInfo& coincenterInfo, Duration ratesUpdateFrequency) @@ -79,17 +80,12 @@ void FiatConverter::updateCacheFile() const { std::optional FiatConverter::queryCurrencyRate(Market mk) { string qStr(mk.assetsPairStrUpper('_')); CurlOptions opts(HttpRequestType::kGet, {{"q", qStr}, {"apiKey", _apiKey}}); - - string method = "/v7/convert?"; - method.append(opts.getPostData().str()); - opts.getPostData().clear(); - - std::string_view dataStr = _curlHandle.query(method, opts); + std::string_view dataStr = _curlHandle.query("/api/v7/convert", opts); static constexpr bool kAllowExceptions = false; json data = json::parse(dataStr, nullptr, kAllowExceptions); //{"query":{"count":1},"results":{"EUR_KRW":{"id":"EUR_KRW","val":1329.475323,"to":"KRW","fr":"EUR"}}} if (data == json::value_t::discarded || !data.contains("results") || !data["results"].contains(qStr)) { - log::error("No JSON data received from fiat currency converter service"); + log::error("No JSON data received from fiat currency converter service for pair '{}'", mk); auto it = _pricesMap.find(mk); if (it != _pricesMap.end()) { // Update cache time anyway to avoid querying too much the service diff --git a/src/api/common/test/fiatconverter_test.cpp b/src/api/common/test/fiatconverter_test.cpp index 886d16ec..721caed6 100644 --- a/src/api/common/test/fiatconverter_test.cpp +++ b/src/api/common/test/fiatconverter_test.cpp @@ -9,6 +9,7 @@ #include "cct_json.hpp" #include "coincenterinfo.hpp" #include "curlhandle.hpp" +#include "curloptions.hpp" #include "permanentcurloptions.hpp" #include "runmodes.hpp" #include "timedef.hpp" @@ -17,7 +18,7 @@ namespace cct { namespace { void AreDoubleEqual(double lhs, double rhs) { - static constexpr double kEpsilon = 0.000001; + static constexpr double kEpsilon = 0.00000001; if (lhs < rhs) { EXPECT_LT(rhs - lhs, kEpsilon); } else { @@ -39,43 +40,40 @@ CurlHandle::CurlHandle([[maybe_unused]] const BestURLPicker &bestURLPicker, : _handle(nullptr), _bestUrlPicker(kSomeFakeURL) {} // NOLINTNEXTLINE(readability-convert-member-functions-to-static) -std::string_view CurlHandle::query(std::string_view endpoint, [[maybe_unused]] const CurlOptions &opts) { +std::string_view CurlHandle::query([[maybe_unused]] std::string_view endpoint, const CurlOptions &opts) { json jsonData; - if (endpoint.find("currencies") != std::string_view::npos) { - // Currencies - jsonData["results"] = {"EUR", "USD", "GBP", "KRW"}; - } else { - // Rates - std::string_view marketStr(endpoint.begin() + endpoint.find("q=") + 2, endpoint.begin() + endpoint.find("q=") + 9); - std::string_view fromCurrency = marketStr.substr(0, 3); - std::string_view targetCurrency = marketStr.substr(4); - double rate = 0; - if (fromCurrency == "EUR") { - if (targetCurrency == "KRW") { - rate = kKRW; - } else if (targetCurrency == "USD") { - rate = kUSD; - } else if (targetCurrency == "GBP") { - rate = kGBP; - } - } else if (fromCurrency == "KRW") { - if (targetCurrency == "EUR") { - rate = 1 / kKRW; - } else if (targetCurrency == "USD") { - rate = kUSD / kKRW; - } else if (targetCurrency == "GBP") { - rate = kGBP / kKRW; - } - } else if (fromCurrency == "GBP") { - if (targetCurrency == "USD") { - rate = kUSD / kGBP; - } - } - if (rate != 0) { - jsonData["results"][marketStr]["val"] = rate; + // Rates + std::string_view marketStr = opts.getPostData().get("q"); + std::string_view fromCurrency = marketStr.substr(0, 3); + std::string_view targetCurrency = marketStr.substr(4); + double rate = 0; + if (fromCurrency == "EUR") { + if (targetCurrency == "KRW") { + rate = kKRW; + } else if (targetCurrency == "USD") { + rate = kUSD; + } else if (targetCurrency == "GBP") { + rate = kGBP; + } + } else if (fromCurrency == "KRW") { + if (targetCurrency == "EUR") { + rate = 1 / kKRW; + } else if (targetCurrency == "USD") { + rate = kUSD / kKRW; + } else if (targetCurrency == "GBP") { + rate = kGBP / kKRW; + } + } else if (fromCurrency == "GBP") { + if (targetCurrency == "USD") { + rate = kUSD / kGBP; } } + + if (rate != 0) { + jsonData["results"][marketStr]["val"] = rate; + } + _queryData = jsonData.dump(); return _queryData; } diff --git a/src/engine/include/staticcommandlineoptioncheck.hpp b/src/engine/include/staticcommandlineoptioncheck.hpp index 370f268e..e294bc9f 100644 --- a/src/engine/include/staticcommandlineoptioncheck.hpp +++ b/src/engine/include/staticcommandlineoptioncheck.hpp @@ -2,8 +2,8 @@ #include #include +#include #include -#include #include "commandlineoption.hpp" @@ -12,7 +12,7 @@ namespace cct { /// Compile time checker of arguments. Currently, the following checks are made: /// - Uniqueness of short hand flags /// - Uniqueness of long names -template +template consteval bool StaticCommandLineOptionsDuplicatesCheck(std::array... ar) { auto all = ComputeAllCommandLineOptions(ar...); @@ -42,7 +42,7 @@ consteval bool StaticCommandLineOptionsDuplicatesCheck(std::array... ar) { /// Compile time checker of descriptions. Following checks are made: /// - Should not start nor end with a '\n' /// - Should not start no end with a space -template +template consteval bool StaticCommandLineOptionsDescriptionCheck(std::array... ar) { const auto all = ComputeAllCommandLineOptions(ar...); const auto isSpaceOrNewLine = [](char ch) { return ch == '\n' || ch == ' '; }; @@ -60,20 +60,20 @@ consteval bool StaticCommandLineOptionsDescriptionCheck(std::array... ar) return true; } -template +template consteval auto ComputeAllCommandLineOptions(std::array... ar) { - constexpr size_t kNbArrays = sizeof...(ar); + constexpr std::size_t kNbArrays = sizeof...(ar); const T* arr[kNbArrays] = {&ar[0]...}; - constexpr size_t lengths[kNbArrays] = {ar.size()...}; + constexpr std::size_t lengths[kNbArrays] = {ar.size()...}; - constexpr size_t kSumLen = std::accumulate(lengths, lengths + kNbArrays, 0); + constexpr std::size_t kSumLen = std::accumulate(lengths, lengths + kNbArrays, 0); std::array all; - size_t allIdx = 0; - for (size_t dataIdx = 0; dataIdx < kNbArrays; ++dataIdx) { - for (size_t lenIdx = 0; lenIdx < lengths[dataIdx]; ++lenIdx) { + std::size_t allIdx = 0; + for (std::size_t dataIdx = 0; dataIdx < kNbArrays; ++dataIdx) { + for (std::size_t lenIdx = 0; lenIdx < lengths[dataIdx]; ++lenIdx) { all[allIdx] = std::get<0>(arr[dataIdx][lenIdx]); ++allIdx; } diff --git a/src/objects/include/market.hpp b/src/objects/include/market.hpp index 03491edc..a0b0eada 100644 --- a/src/objects/include/market.hpp +++ b/src/objects/include/market.hpp @@ -87,7 +87,7 @@ struct fmt::formatter { namespace std { template <> struct hash { - size_t operator()(const cct::Market& mk) const { + auto operator()(const cct::Market& mk) const { return cct::HashCombine(hash()(mk.base()), hash()(mk.quote())); } }; diff --git a/src/objects/include/monetaryamount.hpp b/src/objects/include/monetaryamount.hpp index 3566acbc..2e188903 100644 --- a/src/objects/include/monetaryamount.hpp +++ b/src/objects/include/monetaryamount.hpp @@ -310,7 +310,7 @@ class MonetaryAmount { } [[nodiscard]] uint64_t code() const noexcept { - return HashCombine(static_cast(_amount), static_cast(_curWithDecimals.code())); + return HashCombine(static_cast(_amount), static_cast(_curWithDecimals.code())); } friend std::ostream &operator<<(std::ostream &os, const MonetaryAmount &ma); diff --git a/src/tech/include/cct_hash.hpp b/src/tech/include/cct_hash.hpp index dc6c44ae..41282680 100644 --- a/src/tech/include/cct_hash.hpp +++ b/src/tech/include/cct_hash.hpp @@ -4,7 +4,6 @@ #include #include #include -#include namespace cct { constexpr uint64_t HashValue64(uint64_t h1) { diff --git a/src/tech/include/timedef.hpp b/src/tech/include/timedef.hpp index cc7ad693..3e9c76b6 100644 --- a/src/tech/include/timedef.hpp +++ b/src/tech/include/timedef.hpp @@ -16,22 +16,22 @@ using TimeInMs = std::chrono::milliseconds; using TimeInUs = std::chrono::microseconds; template -T GetTimeDiff(TimePoint t1, TimePoint t2) { - return std::chrono::duration_cast(t2 - t1); +constexpr T GetTimeDiff(TimePoint tp1, TimePoint tp2) { + return std::chrono::duration_cast(tp2 - tp1); } template -T GetTimeFrom(TimePoint t) { - return GetTimeDiff(t, Clock::now()); +constexpr T GetTimeFrom(TimePoint tp) { + return GetTimeDiff(tp, Clock::now()); } -constexpr int64_t TimestampToS(TimePoint t) { - return std::chrono::duration_cast(t.time_since_epoch()).count(); +constexpr int64_t TimestampToS(TimePoint tp) { + return std::chrono::duration_cast(tp.time_since_epoch()).count(); } -constexpr int64_t TimestampToMs(TimePoint t) { - return std::chrono::duration_cast(t.time_since_epoch()).count(); +constexpr int64_t TimestampToMs(TimePoint tp) { + return std::chrono::duration_cast(tp.time_since_epoch()).count(); } -constexpr int64_t TimestampToUs(TimePoint t) { - return std::chrono::duration_cast(t.time_since_epoch()).count(); +constexpr int64_t TimestampToUs(TimePoint tp) { + return std::chrono::duration_cast(tp.time_since_epoch()).count(); } } // namespace cct