Skip to content

Commit

Permalink
Clean up code around fiat converter
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanel committed Nov 5, 2023
1 parent f6c421d commit a3605f4
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 68 deletions.
1 change: 0 additions & 1 deletion src/api/common/include/fiatconverter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <mutex>
#include <unordered_map>

#include "cachedresult.hpp"
#include "cct_string.hpp"
#include "curlhandle.hpp"
#include "currencycode.hpp"
Expand Down
16 changes: 6 additions & 10 deletions src/api/common/src/fiatconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string_view>() == kDefaultCommunityKey) {
auto freeConverterIt = data.find("freecurrencyconverter");
if (freeConverterIt == data.end() || freeConverterIt->get<std::string_view>() == 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");
Expand All @@ -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<string&>());
}

constexpr std::string_view kRatesCacheFile = "ratescache.json";
Expand All @@ -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)
Expand Down Expand Up @@ -79,17 +80,12 @@ void FiatConverter::updateCacheFile() const {
std::optional<double> 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
Expand Down
66 changes: 32 additions & 34 deletions src/api/common/test/fiatconverter_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {
Expand All @@ -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;
}
Expand Down
20 changes: 10 additions & 10 deletions src/engine/include/staticcommandlineoptioncheck.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include <algorithm>
#include <array>
#include <cstddef>
#include <numeric>
#include <string_view>

#include "commandlineoption.hpp"

Expand All @@ -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 <class T, size_t... N>
template <class T, std::size_t... N>
consteval bool StaticCommandLineOptionsDuplicatesCheck(std::array<T, N>... ar) {
auto all = ComputeAllCommandLineOptions(ar...);

Expand Down Expand Up @@ -42,7 +42,7 @@ consteval bool StaticCommandLineOptionsDuplicatesCheck(std::array<T, N>... 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 <class T, size_t... N>
template <class T, std::size_t... N>
consteval bool StaticCommandLineOptionsDescriptionCheck(std::array<T, N>... ar) {
const auto all = ComputeAllCommandLineOptions(ar...);
const auto isSpaceOrNewLine = [](char ch) { return ch == '\n' || ch == ' '; };
Expand All @@ -60,20 +60,20 @@ consteval bool StaticCommandLineOptionsDescriptionCheck(std::array<T, N>... ar)
return true;
}

template <class T, size_t... N>
template <class T, std::size_t... N>
consteval auto ComputeAllCommandLineOptions(std::array<T, N>... 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<CommandLineOption, kSumLen> 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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/objects/include/market.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ struct fmt::formatter<cct::Market> {
namespace std {
template <>
struct hash<cct::Market> {
size_t operator()(const cct::Market& mk) const {
auto operator()(const cct::Market& mk) const {
return cct::HashCombine(hash<cct::CurrencyCode>()(mk.base()), hash<cct::CurrencyCode>()(mk.quote()));
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/objects/include/monetaryamount.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ class MonetaryAmount {
}

[[nodiscard]] uint64_t code() const noexcept {
return HashCombine(static_cast<size_t>(_amount), static_cast<size_t>(_curWithDecimals.code()));
return HashCombine(static_cast<std::size_t>(_amount), static_cast<std::size_t>(_curWithDecimals.code()));
}

friend std::ostream &operator<<(std::ostream &os, const MonetaryAmount &ma);
Expand Down
1 change: 0 additions & 1 deletion src/tech/include/cct_hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <cstdint>
#include <functional>
#include <tuple>
#include <utility>

namespace cct {
constexpr uint64_t HashValue64(uint64_t h1) {
Expand Down
20 changes: 10 additions & 10 deletions src/tech/include/timedef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ using TimeInMs = std::chrono::milliseconds;
using TimeInUs = std::chrono::microseconds;

template <class T>
T GetTimeDiff(TimePoint t1, TimePoint t2) {
return std::chrono::duration_cast<T>(t2 - t1);
constexpr T GetTimeDiff(TimePoint tp1, TimePoint tp2) {
return std::chrono::duration_cast<T>(tp2 - tp1);
}

template <class T>
T GetTimeFrom(TimePoint t) {
return GetTimeDiff<T>(t, Clock::now());
constexpr T GetTimeFrom(TimePoint tp) {
return GetTimeDiff<T>(tp, Clock::now());
}

constexpr int64_t TimestampToS(TimePoint t) {
return std::chrono::duration_cast<TimeInS>(t.time_since_epoch()).count();
constexpr int64_t TimestampToS(TimePoint tp) {
return std::chrono::duration_cast<TimeInS>(tp.time_since_epoch()).count();
}
constexpr int64_t TimestampToMs(TimePoint t) {
return std::chrono::duration_cast<TimeInMs>(t.time_since_epoch()).count();
constexpr int64_t TimestampToMs(TimePoint tp) {
return std::chrono::duration_cast<TimeInMs>(tp.time_since_epoch()).count();
}
constexpr int64_t TimestampToUs(TimePoint t) {
return std::chrono::duration_cast<TimeInUs>(t.time_since_epoch()).count();
constexpr int64_t TimestampToUs(TimePoint tp) {
return std::chrono::duration_cast<TimeInUs>(tp.time_since_epoch()).count();
}
} // namespace cct

0 comments on commit a3605f4

Please sign in to comment.