diff --git a/src/api-objects/include/apikey.hpp b/src/api-objects/include/apikey.hpp index a44e3606..1202d2ab 100644 --- a/src/api-objects/include/apikey.hpp +++ b/src/api-objects/include/apikey.hpp @@ -5,36 +5,28 @@ #include "accountowner.hpp" #include "cct_string.hpp" -#include "cct_type_traits.hpp" namespace cct::api { class APIKey { public: /// @brief Creates an API key without an associated name. - /// @param platform name of the platform exchange in lower case /// @param name name of the key as defined in the secret json file /// @param key the public api key /// @param privateKey the private api key /// @param passphrase passphrase used - APIKey(std::string_view platform, std::string_view name, string &&key, string &&privateKey, string &&passphrase) - : _platform(platform), - _name(name), - _key(std::move(key)), - _privateKey(std::move(privateKey)), - _passphrase(std::move(passphrase)) {} + APIKey(std::string_view name, string &&key, string &&privateKey, string &&passphrase) + : _name(name), _key(std::move(key)), _privateKey(std::move(privateKey)), _passphrase(std::move(passphrase)) {} /// @brief Creates an API key with an associated AccountOwner, needed for Bithumb withdrawals for instance. - /// @param platform name of the platform exchange in lower case /// @param name name of the key as defined in the secret json file /// @param key the public api key /// @param privateKey the private api key /// @param passphrase passphrase used /// @param accountOwner the person's name spelled in English that owns the account associated to the key - APIKey(std::string_view platform, std::string_view name, string &&key, string &&privateKey, string &&passphrase, + APIKey(std::string_view name, string &&key, string &&privateKey, string &&passphrase, const AccountOwner &accountOwner) - : _platform(platform), - _name(name), + : _name(name), _key(std::move(key)), _privateKey(std::move(privateKey)), _passphrase(std::move(passphrase)), @@ -52,18 +44,13 @@ class APIKey { _passphrase.assign(_passphrase.size(), '\0'); } - std::string_view platform() const { return _platform; } std::string_view name() const { return _name; } std::string_view key() const { return _key; } std::string_view privateKey() const { return _privateKey; } std::string_view passphrase() const { return _passphrase; } const AccountOwner &accountOwner() const { return _accountOwner; } - using trivially_relocatable = - std::bool_constant && is_trivially_relocatable_v>::type; - private: - string _platform; string _name; string _key; string _privateKey; diff --git a/src/api-objects/src/apikeysprovider.cpp b/src/api-objects/src/apikeysprovider.cpp index 5b097d06..75599ea0 100644 --- a/src/api-objects/src/apikeysprovider.cpp +++ b/src/api-objects/src/apikeysprovider.cpp @@ -52,20 +52,18 @@ APIKeysProvider::KeyNames APIKeysProvider::getKeyNames(ExchangeNameEnum exchange } const APIKey& APIKeysProvider::get(const ExchangeName& exchangeName) const { - std::string_view platformStr = exchangeName.name(); - ExchangeNameEnum exchangeNameEnum = static_cast( - std::ranges::find(kSupportedExchanges, platformStr) - std::begin(kSupportedExchanges)); + ExchangeNameEnum exchangeNameEnum = exchangeName.exchangeNameEnum(); const APIKeys& apiKeys = _apiKeysPerExchange[static_cast(exchangeNameEnum)]; if (!exchangeName.isKeyNameDefined()) { if (apiKeys.size() > 1) { - throw exception("Specify name for {} keys as you have several", platformStr); + throw exception("Specify name for {} keys as you have several", exchangeName.name()); } return apiKeys.front(); } auto keyNameIt = std::ranges::find_if( apiKeys, [exchangeName](const APIKey& apiKey) { return apiKey.name() == exchangeName.keyName(); }); if (keyNameIt == apiKeys.end()) { - throw exception("Unable to retrieve private key for {} named {:k}", platformStr, exchangeName); + throw exception("Unable to retrieve private key for {} named {:k}", exchangeName.name(), exchangeName); } return *keyNameIt; } @@ -92,11 +90,10 @@ APIKeysProvider::APIKeysPerExchange APIKeysProvider::ParseAPIKeys(std::string_vi bool atLeastOneKeyFound = false; for (auto& [exchangeNameEnum, apiKeys] : apiKeysPerExchangeMap) { - auto publicExchangeName = kSupportedExchanges[static_cast(exchangeNameEnum)]; if (std::ranges::any_of(exchangesWithoutSecrets, [exchangeNameEnum](const auto& exchangeName) { return exchangeName.exchangeNameEnum() == exchangeNameEnum; })) { - log::debug("Not loading {} private keys as requested", publicExchangeName); + log::debug("Not loading {} private keys as requested", EnumToString(exchangeNameEnum)); continue; } @@ -107,7 +104,7 @@ APIKeysProvider::APIKeysPerExchange APIKeysProvider::ParseAPIKeys(std::string_vi } apiKeysPerExchange[static_cast(exchangeNameEnum)].emplace_back( - publicExchangeName, keyName, std::move(apiKey.key), std::move(apiKey.priv), std::move(apiKey.passphrase), + keyName, std::move(apiKey.key), std::move(apiKey.priv), std::move(apiKey.passphrase), AccountOwner(apiKey.accountOwner.enName, apiKey.accountOwner.koName)); atLeastOneKeyFound = true; @@ -138,7 +135,7 @@ string APIKeysProvider::str() const { } foundKeysStr.push_back('}'); foundKeysStr.push_back('@'); - foundKeysStr.append(kSupportedExchanges[exchangePos]); + foundKeysStr.append(EnumToString(static_cast(exchangePos))); } return foundKeysStr; } diff --git a/src/api/common/include/exchangepublicapi.hpp b/src/api/common/include/exchangepublicapi.hpp index baffe686..5735559b 100644 --- a/src/api/common/include/exchangepublicapi.hpp +++ b/src/api/common/include/exchangepublicapi.hpp @@ -125,7 +125,7 @@ class ExchangePublic : public CacheFileUpdatorInterface { ExchangeNameEnum exchangeNameEnum() const { return _exchangeNameEnum; } /// Get the name of the exchange in lower case. - std::string_view name() const { return kSupportedExchanges[static_cast(_exchangeNameEnum)]; } + std::string_view name() const { return EnumToString(_exchangeNameEnum); } /// Retrieve the shortest array of markets that can convert 'fromCurrencyCode' to 'toCurrencyCode' (shortest in terms /// of number of conversions) of 'fromCurrencyCode' to 'toCurrencyCode'. diff --git a/src/api/common/src/commonapi.cpp b/src/api/common/src/commonapi.cpp index 6cae86a7..d1ef723c 100644 --- a/src/api/common/src/commonapi.cpp +++ b/src/api/common/src/commonapi.cpp @@ -78,7 +78,7 @@ MonetaryAmountByCurrencySet CommonAPI::tryQueryWithdrawalFees(ExchangeNameEnum e if (ret.empty()) { log::warn("Taking binance withdrawal fees for {} as crawler failed to retrieve data", - kSupportedExchanges[static_cast(exchangeNameEnum)]); + EnumToString(exchangeNameEnum)); ret = _binanceGlobalInfos.queryWithdrawalFees(); } return ret; @@ -95,7 +95,7 @@ std::optional CommonAPI::tryQueryWithdrawalFee(ExchangeNameEnum } } log::warn("Taking binance withdrawal fee for {} and currency {} as crawler failed to retrieve data", - kSupportedExchanges[static_cast(exchangeNameEnum)], currencyCode); + EnumToString(exchangeNameEnum), currencyCode); MonetaryAmount withdrawFee = _binanceGlobalInfos.queryWithdrawalFee(currencyCode); if (withdrawFee.isDefault()) { return {}; @@ -226,7 +226,7 @@ void CommonAPI::updateCacheFile() const { fiatsData.fiats.emplace_back(fiatCode.str()); } fiatsData.timeepoch = TimestampToSecondsSinceEpoch(fiatsPtrLastUpdatedTimePair.second); - fiatsCacheFile.write(WriteMiniJsonOrThrow(fiatsData)); + fiatsCacheFile.write(WriteJsonOrThrow(fiatsData)); } } diff --git a/src/api/common/src/fiatconverter.cpp b/src/api/common/src/fiatconverter.cpp index 544caa93..458e5d3e 100644 --- a/src/api/common/src/fiatconverter.cpp +++ b/src/api/common/src/fiatconverter.cpp @@ -62,7 +62,7 @@ FiatConverter::FiatConverter(const CoincenterInfo& coincenterInfo, Duration rate } void FiatConverter::updateCacheFile() const { - auto dataStr = WriteMiniJsonOrThrow(_pricesMap); + auto dataStr = WriteJsonOrThrow(_pricesMap); GetRatesCacheFile(_dataDir).write(dataStr); } diff --git a/src/api/common/src/withdrawalfees-crawler.cpp b/src/api/common/src/withdrawalfees-crawler.cpp index 37a66ea6..d162c74e 100644 --- a/src/api/common/src/withdrawalfees-crawler.cpp +++ b/src/api/common/src/withdrawalfees-crawler.cpp @@ -55,7 +55,7 @@ WithdrawalFeesCrawler::WithdrawalFeesCrawler(const CoincenterInfo& coincenterInf // we can reuse file data WithdrawalInfoMaps withdrawalInfoMaps; - std::string_view exchangeName = kSupportedExchanges[static_cast(exchangeNameEnum)]; + std::string_view exchangeName = EnumToString(exchangeNameEnum); for (const auto& [cur, val] : exchangeData.assets) { MonetaryAmount withdrawMin(val.min, cur); @@ -106,7 +106,7 @@ WithdrawalFeesCrawler::WithdrawalInfoMaps WithdrawalFeesCrawler::WithdrawalFeesF } if (withdrawFees1.empty() || withdrawMinMap1.empty()) { - log::error("Unable to parse {} withdrawal fees", kSupportedExchanges[static_cast(exchangeNameEnum)]); + log::error("Unable to parse {} withdrawal fees", EnumToString(exchangeNameEnum)); } return std::make_pair(std::move(withdrawFees1), std::move(withdrawMinMap1)); @@ -136,14 +136,14 @@ void WithdrawalFeesCrawler::updateCacheFile() const { } } } - auto dataStr = WriteMiniJsonOrThrow(withdrawInfoFile); + auto dataStr = WriteJsonOrThrow(withdrawInfoFile); GetWithdrawInfoFile(_coincenterInfo.dataDir()).write(dataStr); } WithdrawalFeesCrawler::WithdrawalInfoMaps WithdrawalFeesCrawler::WithdrawalFeesFunc::get1( ExchangeNameEnum exchangeNameEnum) { - std::string_view exchangeName = kSupportedExchanges[static_cast(exchangeNameEnum)]; + std::string_view exchangeName = EnumToString(exchangeNameEnum); string path(exchangeName); path.append(".json"); std::string_view dataStr = _curlHandle1.query(path, CurlOptions(HttpRequestType::kGet)); @@ -186,7 +186,7 @@ WithdrawalFeesCrawler::WithdrawalInfoMaps WithdrawalFeesCrawler::WithdrawalFeesF WithdrawalFeesCrawler::WithdrawalInfoMaps WithdrawalFeesCrawler::WithdrawalFeesFunc::get2( ExchangeNameEnum exchangeNameEnum) { - std::string_view exchangeName = kSupportedExchanges[static_cast(exchangeNameEnum)]; + std::string_view exchangeName = EnumToString(exchangeNameEnum); std::string_view withdrawalFeesCsv = _curlHandle2.query(exchangeName, CurlOptions(HttpRequestType::kGet)); static constexpr std::string_view kBeginTableTitle = "Deposit & Withdrawal fees"; diff --git a/src/api/common/test/exchangeprivateapi_test.cpp b/src/api/common/test/exchangeprivateapi_test.cpp index 9ab121d7..a3c715c4 100644 --- a/src/api/common/test/exchangeprivateapi_test.cpp +++ b/src/api/common/test/exchangeprivateapi_test.cpp @@ -94,7 +94,7 @@ class ExchangePrivateTest : public ::testing::Test { FiatConverter fiatConverter{coincenterInfo, Duration::max(), Reader(), Reader()}; MockExchangePublic exchangePublic{ExchangeNameEnum::binance, fiatConverter, commonAPI, coincenterInfo}; - APIKey key{"test", "testUser", "", "", ""}; + APIKey key{"testUser", "", "", ""}; MockExchangePrivate exchangePrivate{exchangePublic, coincenterInfo, key}; Market market{"ETH", "EUR"}; diff --git a/src/api/common/test/fiatconverter_test.cpp b/src/api/common/test/fiatconverter_test.cpp index f928ec6a..350becce 100644 --- a/src/api/common/test/fiatconverter_test.cpp +++ b/src/api/common/test/fiatconverter_test.cpp @@ -86,7 +86,7 @@ std::string_view CurlHandle::query([[maybe_unused]] std::string_view endpoint, c } } if (res.val != 0) { - _queryData = WriteMiniJsonOrThrow(response); + _queryData = WriteJsonOrThrow(response); } } else { @@ -96,7 +96,7 @@ std::string_view CurlHandle::query([[maybe_unused]] std::string_view endpoint, c response.rates["SUSHI"] = 36.78; response.rates["KRW"] = 1341.88; response.rates["NOK"] = 11.3375; - _queryData = WriteMiniJsonOrThrow(response); + _queryData = WriteJsonOrThrow(response); } return _queryData; diff --git a/src/api/exchanges/src/binanceprivateapi.cpp b/src/api/exchanges/src/binanceprivateapi.cpp index 9f33a4d9..5e3a4bab 100644 --- a/src/api/exchanges/src/binanceprivateapi.cpp +++ b/src/api/exchanges/src/binanceprivateapi.cpp @@ -232,7 +232,7 @@ T PrivateQuery(CurlHandle& curlHandle, const APIKey& apiKey, HttpRequestType req } if (throwIfError) { std::string_view errorMsg; - string jsonStr = WriteMiniJsonOrThrow(ret); + string jsonStr = WriteJsonOrThrow(ret); if constexpr (amc::is_detected::value) { if (ret.msg) { errorMsg = *ret.msg; diff --git a/src/api/exchanges/src/bithumbprivateapi.cpp b/src/api/exchanges/src/bithumbprivateapi.cpp index 52a9949f..72c74137 100644 --- a/src/api/exchanges/src/bithumbprivateapi.cpp +++ b/src/api/exchanges/src/bithumbprivateapi.cpp @@ -1095,7 +1095,7 @@ InitiatedWithdrawInfo BithumbPrivate::launchWithdraw(MonetaryAmount grossAmount, } void BithumbPrivate::updateCacheFile() const { - GetBithumbCurrencyInfoMapCache(_coincenterInfo.dataDir()).write(WriteMiniJsonOrThrow(_currencyOrderInfoMap)); + GetBithumbCurrencyInfoMapCache(_coincenterInfo.dataDir()).write(WriteJsonOrThrow(_currencyOrderInfoMap)); } } // namespace cct::api diff --git a/src/api/interface/include/exchangeretriever.hpp b/src/api/interface/include/exchangeretriever.hpp index ab34dc9c..650aff4c 100644 --- a/src/api/interface/include/exchangeretriever.hpp +++ b/src/api/interface/include/exchangeretriever.hpp @@ -90,7 +90,7 @@ class ExchangeRetriever { } if (ret.size() == oldSize) { if constexpr (std::is_same_v, ExchangeNameEnum>) { - throw exception("Unable to find {} in the exchange list", kSupportedExchanges[static_cast(name)]); + throw exception("Unable to find {} in the exchange list", EnumToString(name)); } else { throw exception("Unable to find {} in the exchange list", name); } diff --git a/src/api/interface/src/exchange.cpp b/src/api/interface/src/exchange.cpp index 4b8d5ca6..3d4edfb0 100644 --- a/src/api/interface/src/exchange.cpp +++ b/src/api/interface/src/exchange.cpp @@ -24,7 +24,7 @@ Exchange::Exchange(const schema::ExchangeConfig &exchangeConfig, ExchangePublic _exchangePrivate(std::move(exchangePrivate)), _pExchangeConfig(std::addressof(exchangeConfig)) {} -std::size_t Exchange::publicExchangePos() const { return PublicExchangePos(name()); } +std::size_t Exchange::publicExchangePos() const { return static_cast(exchangeNameEnum()); } bool Exchange::canWithdraw(CurrencyCode currencyCode, const CurrencyExchangeFlatSet ¤cyExchangeSet) const { if (_pExchangeConfig->asset.withdrawExclude.contains(currencyCode)) { diff --git a/src/api/interface/test/exchangeretriever_test.cpp b/src/api/interface/test/exchangeretriever_test.cpp index 4181becc..beb4fcf5 100644 --- a/src/api/interface/test/exchangeretriever_test.cpp +++ b/src/api/interface/test/exchangeretriever_test.cpp @@ -40,8 +40,8 @@ class ExchangeRetrieverTest : public ::testing::Test { api::MockExchangePublic exchangePublic1{ExchangeNameEnum::bithumb, fiatConverter, commonAPI, coincenterInfo}; api::MockExchangePublic exchangePublic2{ExchangeNameEnum::kraken, fiatConverter, commonAPI, coincenterInfo}; api::MockExchangePublic exchangePublic3{ExchangeNameEnum::kucoin, fiatConverter, commonAPI, coincenterInfo}; - api::APIKey key1{"test1", "user1", "", "", ""}; - api::APIKey key2{"test2", "user2", "", "", ""}; + api::APIKey key1{"user1", "", "", ""}; + api::APIKey key2{"user2", "", "", ""}; Exchange exchange1{coincenterInfo.exchangeConfig(exchangePublic1.exchangeNameEnum()), exchangePublic1, std::make_unique(exchangePublic1, coincenterInfo, key1)}; Exchange exchange2{coincenterInfo.exchangeConfig(exchangePublic2.exchangeNameEnum()), exchangePublic2, diff --git a/src/basic-objects/include/coincentercommandtype.hpp b/src/basic-objects/include/coincentercommandtype.hpp index f61798d3..b6518047 100644 --- a/src/basic-objects/include/coincentercommandtype.hpp +++ b/src/basic-objects/include/coincentercommandtype.hpp @@ -17,8 +17,6 @@ namespace cct { enum class CoincenterCommandType : int8_t { CCT_COINCENTER_COMMAND_TYPES }; -std::string_view CoincenterCommandTypeToString(CoincenterCommandType coincenterCommandType); - bool IsAnyTrade(CoincenterCommandType coincenterCommandType); } // namespace cct diff --git a/src/basic-objects/src/coincentercommandtype.cpp b/src/basic-objects/src/coincentercommandtype.cpp index 9bf9f861..9a654b64 100644 --- a/src/basic-objects/src/coincentercommandtype.cpp +++ b/src/basic-objects/src/coincentercommandtype.cpp @@ -3,15 +3,8 @@ #include #include -#include "cct_json.hpp" - namespace cct { -std::string_view CoincenterCommandTypeToString(CoincenterCommandType coincenterCommandType) { - return json::reflect::keys[static_cast>( - coincenterCommandType)]; -} - bool IsAnyTrade(CoincenterCommandType coincenterCommandType) { switch (coincenterCommandType) { case CoincenterCommandType::Trade: diff --git a/src/engine/include/exchangesorchestrator.hpp b/src/engine/include/exchangesorchestrator.hpp index b3a6256b..48c44f63 100644 --- a/src/engine/include/exchangesorchestrator.hpp +++ b/src/engine/include/exchangesorchestrator.hpp @@ -97,7 +97,7 @@ class ExchangesOrchestrator { MonetaryAmountPerExchange getLastPricePerExchange(Market mk, ExchangeNameSpan exchangeNames); MarketDataPerExchange getMarketDataPerExchange(std::span marketPerPublicExchange, - ExchangeNameSpan exchangeNames); + std::span exchangeNameEnums); MarketTimestampSetsPerExchange pullAvailableMarketsForReplay(TimeWindow timeWindow, ExchangeNameSpan exchangeNames); diff --git a/src/engine/include/queryresultprinter.hpp b/src/engine/include/queryresultprinter.hpp index 7870bfc4..ff66a1cb 100644 --- a/src/engine/include/queryresultprinter.hpp +++ b/src/engine/include/queryresultprinter.hpp @@ -121,9 +121,9 @@ class QueryResultPrinter { void printJson(const auto &jsonObj) const { if (_pOs != nullptr) { - *_pOs << WriteMiniJsonOrThrow(jsonObj) << '\n'; + *_pOs << WriteJsonOrThrow(jsonObj) << '\n'; } else { - _outputLogger->info(WriteMiniJsonOrThrow(jsonObj)); + _outputLogger->info(WriteJsonOrThrow(jsonObj)); } } @@ -131,7 +131,7 @@ class QueryResultPrinter { if (_loggingInfo.isCommandTypeTracked(commandType) && (!isSimulationMode || _loggingInfo.alsoLogActivityForSimulatedCommands())) { File activityFile = _loggingInfo.getActivityFile(); - activityFile.write(WriteMiniJsonOrThrow(jsonObj), Writer::Mode::Append); + activityFile.write(WriteJsonOrThrow(jsonObj), Writer::Mode::Append); } } diff --git a/src/engine/src/coincenter.cpp b/src/engine/src/coincenter.cpp index 806834aa..e5c8e1f1 100644 --- a/src/engine/src/coincenter.cpp +++ b/src/engine/src/coincenter.cpp @@ -73,18 +73,18 @@ MarketOrderBookConversionRates Coincenter::getMarketOrderBooks(Market mk, Exchan } MarketDataPerExchange Coincenter::queryMarketDataPerExchange(std::span marketPerPublicExchangePos) { - ExchangeNames exchangeNames; + ExchangeNameEnumVector exchangeNameEnums; int exchangePos{}; for (Market market : marketPerPublicExchangePos) { if (market.isDefined()) { - exchangeNames.emplace_back(kSupportedExchanges[exchangePos]); + exchangeNameEnums.emplace_back(static_cast(exchangePos)); } ++exchangePos; } const auto marketDataPerExchange = - _exchangesOrchestrator.getMarketDataPerExchange(marketPerPublicExchangePos, exchangeNames); + _exchangesOrchestrator.getMarketDataPerExchange(marketPerPublicExchangePos, exchangeNameEnums); // Transform data structures to export metrics input format MarketOrderBookConversionRates marketOrderBookConversionRates(marketDataPerExchange.size()); @@ -390,8 +390,7 @@ Coincenter::MarketTraderEngineVector Coincenter::createMarketTraderEngines( if (!isValidateOnly && (startBaseAmount == 0 || startQuoteAmount == 0)) { log::warn("Cannot convert to start base / quote amounts for {} ({} / {})", - kSupportedExchanges[static_cast(exchangesWithThisMarketData[exchangePos])], startBaseAmount, - startQuoteAmount); + EnumToString(exchangesWithThisMarketData[exchangePos]), startBaseAmount, startQuoteAmount); exchangesWithThisMarketData.erase(exchangesWithThisMarketData.begin() + exchangePos); convertedBaseAmountPerExchange.erase(convertedBaseAmountPerExchange.begin() + exchangePos); convertedQuoteAmountPerExchange.erase(convertedQuoteAmountPerExchange.begin() + exchangePos); diff --git a/src/engine/src/exchangesorchestrator.cpp b/src/engine/src/exchangesorchestrator.cpp index c1b44fb8..d78dc663 100644 --- a/src/engine/src/exchangesorchestrator.cpp +++ b/src/engine/src/exchangesorchestrator.cpp @@ -954,9 +954,9 @@ MonetaryAmountPerExchange ExchangesOrchestrator::getLastPricePerExchange(Market return lastPricePerExchange; } -MarketDataPerExchange ExchangesOrchestrator::getMarketDataPerExchange(std::span marketPerPublicExchange, - ExchangeNameSpan exchangeNames) { - UniquePublicSelectedExchanges selectedExchanges = _exchangeRetriever.selectOneAccount(exchangeNames); +MarketDataPerExchange ExchangesOrchestrator::getMarketDataPerExchange( + std::span marketPerPublicExchange, std::span exchangeNameEnums) { + UniquePublicSelectedExchanges selectedExchanges = _exchangeRetriever.selectOneAccount(exchangeNameEnums); std::array isMarketTradable; diff --git a/src/engine/src/metricsexporter.cpp b/src/engine/src/metricsexporter.cpp index 5fc9c83d..1cb28fcb 100644 --- a/src/engine/src/metricsexporter.cpp +++ b/src/engine/src/metricsexporter.cpp @@ -95,7 +95,7 @@ void MetricsExporter::exportOrderbookMetrics(const MarketOrderBookConversionRate for (const auto &[exchangeNameEnum, marketOrderBook, optConversionRate] : marketOrderBookConversionRates) { key.set("market", marketOrderBook.market().assetsPairStrLower('-')); - key.set("exchange", kSupportedExchanges[static_cast(exchangeNameEnum)]); + key.set("exchange", EnumToString(exchangeNameEnum)); key.set("side", "ask"); _pMetricsGateway->add(MetricType::kGauge, MetricOperation::kSet, key, marketOrderBook.lowestAskPrice().toDouble()); key.set("side", "bid"); @@ -105,7 +105,7 @@ void MetricsExporter::exportOrderbookMetrics(const MarketOrderBookConversionRate key.set(kMetricHelpKey, "Best bids and asks volumes"); for (const auto &[exchangeNameEnum, marketOrderBook, optConversionRate] : marketOrderBookConversionRates) { key.set("market", marketOrderBook.market().assetsPairStrLower('-')); - key.set("exchange", kSupportedExchanges[static_cast(exchangeNameEnum)]); + key.set("exchange", EnumToString(exchangeNameEnum)); key.set("side", "ask"); _pMetricsGateway->add(MetricType::kGauge, MetricOperation::kSet, key, marketOrderBook.amountAtAskPrice().toDouble()); diff --git a/src/engine/src/queryresultprinter.cpp b/src/engine/src/queryresultprinter.cpp index 2c126f49..01a01d63 100644 --- a/src/engine/src/queryresultprinter.cpp +++ b/src/engine/src/queryresultprinter.cpp @@ -1011,7 +1011,7 @@ void QueryResultPrinter::printTrades(const TradeResultPerExchange &tradeResultPe switch (_apiOutputType) { case ApiOutputType::table: { string tradedFromStr("Traded from amount ("); - auto tradeModeStr = WriteSingleObjectJsonNoQuotes(tradeOptions.tradeMode()); + string tradeModeStr(EnumToString(tradeOptions.tradeMode())); tradedFromStr.append(tradeModeStr); tradedFromStr.push_back(')'); string tradedToStr("Traded to amount ("); @@ -1026,8 +1026,7 @@ void QueryResultPrinter::printTrades(const TradeResultPerExchange &tradeResultPe const TradedAmounts &tradedAmounts = tradeResult.tradedAmounts(); table.emplace_back(exchangePtr->name(), exchangePtr->keyName(), tradeResult.from().str(), - tradedAmounts.from.str(), tradedAmounts.to.str(), - WriteSingleObjectJsonNoQuotes(tradeResult.state())); + tradedAmounts.from.str(), tradedAmounts.to.str(), EnumToString(tradeResult.state())); } printTable(table); break; @@ -1053,7 +1052,7 @@ void QueryResultPrinter::printClosedOrders(const ClosedOrdersPerExchange &closed for (const ClosedOrder &closedOrder : closedOrders) { table.emplace_back(exchangePtr->name(), exchangePtr->keyName(), closedOrder.id(), TimeToString(closedOrder.placedTime()), TimeToString(closedOrder.matchedTime()), - WriteSingleObjectJsonNoQuotes(closedOrder.side()), closedOrder.price().str(), + EnumToString(closedOrder.side()), closedOrder.price().str(), closedOrder.matchedVolume().str()); } } @@ -1080,7 +1079,7 @@ void QueryResultPrinter::printOpenedOrders(const OpenedOrdersPerExchange &opened for (const auto &[exchangePtr, openedOrders] : openedOrdersPerExchange) { for (const OpenedOrder &openedOrder : openedOrders) { table.emplace_back(exchangePtr->name(), exchangePtr->keyName(), openedOrder.id(), - TimeToString(openedOrder.placedTime()), WriteSingleObjectJsonNoQuotes(openedOrder.side()), + TimeToString(openedOrder.placedTime()), EnumToString(openedOrder.side()), openedOrder.price().str(), openedOrder.matchedVolume().str(), openedOrder.remainingVolume().str()); } @@ -1555,7 +1554,7 @@ void QueryResultPrinter::printMarketTradingResults(TimeWindow inputTimeWindow, c for (const ClosedOrder &closedOrder : marketTradingResults.matchedOrders()) { string orderStr = TimeToString(closedOrder.placedTime()); orderStr.append(" - "); - orderStr.append(WriteSingleObjectJsonNoQuotes(closedOrder.side())); + orderStr.append(EnumToString(closedOrder.side())); orderStr.append(" - "); orderStr.append(closedOrder.matchedVolume().str()); orderStr.append(" @ "); diff --git a/src/engine/test/exchangedata_test.hpp b/src/engine/test/exchangedata_test.hpp index b4389bed..7a567ee0 100644 --- a/src/engine/test/exchangedata_test.hpp +++ b/src/engine/test/exchangedata_test.hpp @@ -40,11 +40,11 @@ class ExchangesBaseTest : public ::testing::Test { api::MockExchangePublic exchangePublic1{ExchangeNameEnum::binance, fiatConverter, commonAPI, coincenterInfo}; api::MockExchangePublic exchangePublic2{ExchangeNameEnum::bithumb, fiatConverter, commonAPI, coincenterInfo}; api::MockExchangePublic exchangePublic3{ExchangeNameEnum::huobi, fiatConverter, commonAPI, coincenterInfo}; - api::APIKey key1{"test1", "testuser1", "", "", ""}; - api::APIKey key2{"test2", "testuser2", "", "", ""}; - api::APIKey key3{"test3", "testuser3", "", "", ""}; - api::APIKey key4{"test4", "testuser4", "", "", ""}; - api::APIKey key5{"test5", "testuser5", "", "", ""}; + api::APIKey key1{"testuser1", "", "", ""}; + api::APIKey key2{"testuser2", "", "", ""}; + api::APIKey key3{"testuser3", "", "", ""}; + api::APIKey key4{"testuser4", "", "", ""}; + api::APIKey key5{"testuser5", "", "", ""}; Exchange exchange1{coincenterInfo.exchangeConfig(exchangePublic1.exchangeNameEnum()), exchangePublic1, std::make_unique(exchangePublic1, coincenterInfo, key1)}; Exchange exchange2{coincenterInfo.exchangeConfig(exchangePublic2.exchangeNameEnum()), exchangePublic2, diff --git a/src/engine/test/exchangesorchestrator_public_test.cpp b/src/engine/test/exchangesorchestrator_public_test.cpp index f00c1ad0..bc92dd6f 100644 --- a/src/engine/test/exchangesorchestrator_public_test.cpp +++ b/src/engine/test/exchangesorchestrator_public_test.cpp @@ -33,8 +33,8 @@ TEST_F(ExchangeOrchestratorTest, HealthCheck) { EXPECT_CALL(exchangePublic1, healthCheck()).WillOnce(testing::Return(true)); EXPECT_CALL(exchangePublic2, healthCheck()).WillOnce(testing::Return(false)); - const ExchangeName kTestedExchanges12[] = {ExchangeName(kSupportedExchanges[0]), - ExchangeName(kSupportedExchanges[1])}; + const ExchangeName kTestedExchanges12[] = {ExchangeName(EnumToString(static_cast(0))), + ExchangeName(EnumToString(static_cast(1)))}; ExchangeHealthCheckStatus expectedHealthCheck = {{&exchange1, true}, {&exchange2, false}}; EXPECT_EQ(exchangesOrchestrator.healthCheck(kTestedExchanges12), expectedHealthCheck); @@ -47,8 +47,8 @@ TEST_F(ExchangeOrchestratorTest, TickerInformation) { const MarketOrderBookMap marketOrderbookMap2 = {{m1, marketOrderBook10}, {m3, marketOrderBook3}}; EXPECT_CALL(exchangePublic2, queryAllApproximatedOrderBooks(1)).WillOnce(testing::Return(marketOrderbookMap2)); - const ExchangeName kTestedExchanges12[] = {ExchangeName(kSupportedExchanges[0]), - ExchangeName(kSupportedExchanges[1])}; + const ExchangeName kTestedExchanges12[] = {ExchangeName(EnumToString(static_cast(0))), + ExchangeName(EnumToString(static_cast(1)))}; ExchangeTickerMaps expectedTickerMaps = {{&exchange1, marketOrderbookMap1}, {&exchange2, marketOrderbookMap2}}; EXPECT_EQ(exchangesOrchestrator.getTickerInformation(kTestedExchanges12), expectedTickerMaps); @@ -79,8 +79,9 @@ class ExchangeOrchestratorMarketOrderbookTest : public ExchangeOrchestratorTest }; TEST_F(ExchangeOrchestratorMarketOrderbookTest, AllSpecifiedExchanges) { - const ExchangeName kTestedExchanges123[] = { - ExchangeName(kSupportedExchanges[0]), ExchangeName(kSupportedExchanges[1]), ExchangeName(kSupportedExchanges[2])}; + const ExchangeName kTestedExchanges123[] = {ExchangeName(EnumToString(static_cast(0))), + ExchangeName(EnumToString(static_cast(1))), + ExchangeName(EnumToString(static_cast(2)))}; EXPECT_EQ(exchangesOrchestrator.getMarketOrderBooks(testedMarket, kTestedExchanges123, equiCurrencyCode, optDepth), marketOrderBookConversionRates); @@ -109,7 +110,7 @@ class ExchangeOrchestratorEmptyMarketOrderbookTest : public ExchangeOrchestrator }; TEST_F(ExchangeOrchestratorEmptyMarketOrderbookTest, MarketDoesNotExist) { - const ExchangeName kTestedExchanges2[] = {ExchangeName(kSupportedExchanges[1])}; + const ExchangeName kTestedExchanges2[] = {ExchangeName(EnumToString(static_cast(1)))}; EXPECT_EQ(exchangesOrchestrator.getMarketOrderBooks(testedMarket, kTestedExchanges2, equiCurrencyCode, optDepth), marketOrderBookConversionRates); } @@ -180,8 +181,8 @@ TEST_F(ExchangeOrchestratorTest, GetMarketsPerExchangeTwoCurrencies) { TEST_F(ExchangeOrchestratorTest, GetExchangesTradingCurrency) { CurrencyCode currencyCode{"XRP"}; - const ExchangeName kTestedExchanges13[] = {ExchangeName(kSupportedExchanges[0]), - ExchangeName(kSupportedExchanges[2])}; + const ExchangeName kTestedExchanges13[] = {ExchangeName(EnumToString(static_cast(0))), + ExchangeName(EnumToString(static_cast(2)))}; CurrencyExchangeFlatSet tradableCurrencies1{ CurrencyExchangeVector{CurrencyExchange("XRP", CurrencyExchange::Deposit::kUnavailable, diff --git a/src/http-request/include/request-retry.hpp b/src/http-request/include/request-retry.hpp index 971c440d..3b41cd71 100644 --- a/src/http-request/include/request-retry.hpp +++ b/src/http-request/include/request-retry.hpp @@ -49,8 +49,8 @@ class RequestRetry { do { if (nbRetries != 0) { if (log::get_level() <= log::level::warn) { - log::warn("Got query error: '{}' for {}, retry {}/{} after {}", WriteMiniJsonOrThrow(ret), endpoint, - nbRetries, _queryRetryPolicy.nbMaxRetries, DurationToString(sleepingTime)); + log::warn("Got query error: '{}' for {}, retry {}/{} after {}", WriteJsonOrThrow(ret), endpoint, nbRetries, + _queryRetryPolicy.nbMaxRetries, DurationToString(sleepingTime)); } std::this_thread::sleep_for(sleepingTime); diff --git a/src/objects/include/exchangename.hpp b/src/objects/include/exchangename.hpp index 623dc2cb..269f99e7 100644 --- a/src/objects/include/exchangename.hpp +++ b/src/objects/include/exchangename.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include @@ -12,15 +12,6 @@ namespace cct { -/// Returns the constant index (starting at 0) of given public exchange name in lower case. -/// If not found, kNbSupportedExchanges will be returned. -constexpr auto PublicExchangePos(std::string_view publicExchangeName) { - return std::ranges::find_if( - kSupportedExchanges, - [publicExchangeName](const auto exchangeStr) { return exchangeStr == publicExchangeName; }) - - std::begin(kSupportedExchanges); -} - class ExchangeName { public: static bool IsValid(std::string_view str); @@ -38,38 +29,33 @@ class ExchangeName { explicit ExchangeName(ExchangeNameEnum exchangeNameEnum, std::string_view keyName = {}); - std::string_view name() const { - const auto underscore = underscorePos(); - return {_nameWithKey.data(), underscore == string::npos ? _nameWithKey.size() : underscore}; - } + std::string_view name() const { return EnumToString(_exchangeNameEnum); } std::string_view keyName() const { - const auto underscore = underscorePos(); - return {_nameWithKey.begin() + (underscore == string::npos ? _nameWithKey.size() : underscore + 1U), + return {_nameWithKey.begin() + (_begKeyNamePos == kUndefinedKeyNamePos ? _nameWithKey.size() : _begKeyNamePos), _nameWithKey.end()}; } - auto publicExchangePos() const { return PublicExchangePos(name()); } + std::size_t publicExchangePos() const { return static_cast(_exchangeNameEnum); } - ExchangeNameEnum exchangeNameEnum() const { return static_cast(publicExchangePos()); } + ExchangeNameEnum exchangeNameEnum() const { return _exchangeNameEnum; } - bool isKeyNameDefined() const { return underscorePos() != string::npos; } + bool isKeyNameDefined() const { return _begKeyNamePos != kUndefinedKeyNamePos; } std::string_view str() const { return _nameWithKey; } bool operator==(const ExchangeName &) const noexcept = default; std::strong_ordering operator<=>(const ExchangeName &) const noexcept = default; - friend std::ostream &operator<<(std::ostream &os, const ExchangeName &rhs) { return os << rhs.str(); } + friend std::ostream &operator<<(std::ostream &os, const ExchangeName &en) { return os << en.str(); } using trivially_relocatable = is_trivially_relocatable::type; private: - static constexpr auto kMinExchangeNameLength = - std::ranges::min_element(kSupportedExchanges, [](auto lhs, auto rhs) { return lhs.size() < rhs.size(); })->size(); - - string::size_type underscorePos() const { return _nameWithKey.find('_', kMinExchangeNameLength); } + static constexpr uint8_t kUndefinedKeyNamePos = std::numeric_limits::max(); + ExchangeNameEnum _exchangeNameEnum; + uint8_t _begKeyNamePos; string _nameWithKey; }; diff --git a/src/objects/src/exchange-names.cpp b/src/objects/src/exchange-names.cpp index ab959277..d6530a27 100644 --- a/src/objects/src/exchange-names.cpp +++ b/src/objects/src/exchange-names.cpp @@ -17,14 +17,14 @@ string ConstructAccumulatedExchangeNames(ExchangeNameSpan exchangeNames) { return exchangesStr; } -string ConstructAccumulatedExchangeNames(ExchangeNameEnumSpan exchangeNames) { +string ConstructAccumulatedExchangeNames(ExchangeNameEnumSpan exchangeNameEnums) { // TODO: Use C++23 join_with feature - string exchangesStr(exchangeNames.empty() ? "all" : ""); - for (const auto &exchangeName : exchangeNames) { + string exchangesStr(exchangeNameEnums.empty() ? "all" : ""); + for (const auto exchangeNameEnum : exchangeNameEnums) { if (!exchangesStr.empty()) { exchangesStr.push_back(','); } - exchangesStr.append(kSupportedExchanges[static_cast(exchangeName)]); + exchangesStr.append(EnumToString(exchangeNameEnum)); } return exchangesStr; } diff --git a/src/objects/src/exchangename.cpp b/src/objects/src/exchangename.cpp index 90a61b48..d7d6c2c4 100644 --- a/src/objects/src/exchangename.cpp +++ b/src/objects/src/exchangename.cpp @@ -12,41 +12,63 @@ namespace cct { -bool ExchangeName::IsValid(std::string_view str) { +namespace { + +std::pair ExtractExchangeNameEnum(std::string_view str) { + static constexpr auto kMinExchangeNameLength = + std::ranges::min_element(kSupportedExchanges, [](auto lhs, auto rhs) { return lhs.size() < rhs.size(); })->size(); + + std::pair res{}; if (str.size() < kMinExchangeNameLength) { - return false; + return res; } const auto lowerStr = ToLower(str); const auto exchangePos = std::ranges::find_if(kSupportedExchanges, [&lowerStr](std::string_view ex) { return lowerStr.starts_with(ex); }) - std::begin(kSupportedExchanges); if (exchangePos == kNbSupportedExchanges) { - return false; + return res; } const auto publicExchangeName = kSupportedExchanges[exchangePos]; + res.first = static_cast(exchangePos); if (publicExchangeName.size() == lowerStr.size()) { - return true; + res.second = true; + return res; } if (lowerStr[publicExchangeName.size()] != '_') { - return false; + return res; } - std::string_view keyName(lowerStr.begin() + publicExchangeName.size() + 1U, lowerStr.end()); - return !keyName.empty(); + res.second = str.size() > publicExchangeName.size() + 1U; + return res; } +} // namespace + +bool ExchangeName::IsValid(std::string_view str) { return ExtractExchangeNameEnum(str).second; } ExchangeName::ExchangeName(std::string_view globalExchangeName) : _nameWithKey(globalExchangeName) { - if (!IsValid(globalExchangeName)) { + const auto [exchangeNameEnum, isValid] = ExtractExchangeNameEnum(globalExchangeName); + if (!isValid) { throw invalid_argument("Invalid exchange name '{}'", globalExchangeName); } - const auto sz = globalExchangeName.size(); - for (std::remove_const_t charPos = 0; charPos < sz && _nameWithKey[charPos] != '_'; ++charPos) { + _exchangeNameEnum = exchangeNameEnum; + const auto exchangeNameSize = EnumToString(exchangeNameEnum).size(); + if (_nameWithKey.size() > exchangeNameSize) { + _begKeyNamePos = exchangeNameSize + 1UL; + } else { + _begKeyNamePos = kUndefinedKeyNamePos; + } + + for (std::remove_const_t charPos = 0; charPos < exchangeNameSize; ++charPos) { _nameWithKey[charPos] = tolower(_nameWithKey[charPos]); } } ExchangeName::ExchangeName(ExchangeNameEnum exchangeNameEnum, std::string_view keyName) - : _nameWithKey(kSupportedExchanges[static_cast(exchangeNameEnum)]) { - if (!keyName.empty()) { + : _exchangeNameEnum(exchangeNameEnum), _nameWithKey(EnumToString(exchangeNameEnum)) { + if (keyName.empty()) { + _begKeyNamePos = kUndefinedKeyNamePos; + } else { + _begKeyNamePos = _nameWithKey.size() + 1UL; _nameWithKey.push_back('_'); _nameWithKey.append(keyName); } diff --git a/src/objects/src/marketorderbook.cpp b/src/objects/src/marketorderbook.cpp index 094fe0b4..e902e35f 100644 --- a/src/objects/src/marketorderbook.cpp +++ b/src/objects/src/marketorderbook.cpp @@ -734,7 +734,7 @@ SimpleTable MarketOrderBook::getTable(ExchangeNameEnum exchangeNameEnum, string h1("Sellers of "); string baseStr = _market.base().str(); h1.append(baseStr).append(" (asks)"); - std::string_view exchangeName = kSupportedExchanges[static_cast(exchangeNameEnum)]; + std::string_view exchangeName = EnumToString(exchangeNameEnum); string h2(exchangeName); h2.append(" ").append(baseStr).append(" price in "); _market.quote().appendStrTo(h2); diff --git a/src/schema/include/write-json.hpp b/src/schema/include/write-json.hpp index 8e06db88..928e548e 100644 --- a/src/schema/include/write-json.hpp +++ b/src/schema/include/write-json.hpp @@ -16,7 +16,7 @@ static constexpr auto kMinifiedJsonOptions = .minified = true, // NOLINT(readability-implicit-bool-conversion) .raw_string = true}; // NOLINT(readability-implicit-bool-conversion) -template +template string WriteJsonOrThrow(const auto &obj) { string buf; @@ -30,17 +30,6 @@ string WriteJsonOrThrow(const auto &obj) { return buf; } -string WriteMiniJsonOrThrow(const auto &obj) { return WriteJsonOrThrow(obj); } - -string WriteSingleObjectJsonNoQuotes(const auto &obj) { - auto buf = WriteMiniJsonOrThrow(obj); - if (!buf.empty() && buf.front() == '"') { - buf.pop_back(); - buf.erase(buf.begin()); - } - return buf; -} - string WritePrettyJsonOrThrow(const auto &obj) { return WriteJsonOrThrow(obj); } } // namespace cct \ No newline at end of file diff --git a/src/schema/test/general-config_test.cpp b/src/schema/test/general-config_test.cpp index 9e0926ac..6b7ee562 100644 --- a/src/schema/test/general-config_test.cpp +++ b/src/schema/test/general-config_test.cpp @@ -8,7 +8,7 @@ namespace cct { TEST(GeneralConfig, WriteMinified) { EXPECT_EQ( - WriteMiniJsonOrThrow(schema::GeneralConfig{}), + WriteJsonOrThrow(schema::GeneralConfig{}), R"({"apiOutputType":"table","fiatConversion":{"rate":"8h"},"log":{"activityTracking":{"commandTypes":["Trade","Buy","Sell","Withdraw","DustSweeper"],"dateFileNameFormat":"%Y-%m","withSimulatedCommands":false},"consoleLevel":"info","fileLevel":"debug","maxFileSize":"5Mi","maxNbFiles":20},"requests":{"concurrency":{"nbMaxParallelRequests":1}},"trading":{"automation":{"deserialization":{"loadChunkDuration":"1w"},"startingContext":{"startBaseAmountEquivalent":"1000 EUR","startQuoteAmountEquivalent":"1000 EUR"}}}})"); } diff --git a/src/tech/include/cct_json.hpp b/src/tech/include/cct_json.hpp index f2f62328..36c8a7ac 100644 --- a/src/tech/include/cct_json.hpp +++ b/src/tech/include/cct_json.hpp @@ -1,9 +1,12 @@ #pragma once #include // IWYU pragma: export +#include +#include -namespace cct::json { +namespace cct { +namespace json { using glz::error_ctx; using glz::format_error; using glz::meta; @@ -11,5 +14,15 @@ using glz::opts; using glz::read; using glz::reflect; using glz::write; +} // namespace json -} // namespace cct::json \ No newline at end of file +/** + * Get the string representation of an enum value, provided that enum values are contiguous and start at 0, and that + * they are specialized with glz::meta. + */ +constexpr std::string_view EnumToString(auto enumValue) { + using T = std::remove_cvref_t; + return json::reflect::keys[static_cast>(enumValue)]; +} + +} // namespace cct \ No newline at end of file diff --git a/src/tech/src/timestring.cpp b/src/tech/src/timestring.cpp index d0cdfc94..8dd6eb45 100644 --- a/src/tech/src/timestring.cpp +++ b/src/tech/src/timestring.cpp @@ -54,14 +54,17 @@ TimePoint StringToTime(std::string_view timeStr, const char* format) { if (ss.fail()) { throw exception("Failed to parse time string {}", timeStr); } - // Convert timestamp to epoch time assuming UTC +// Convert timestamp to epoch time assuming UTC +#ifdef _WIN32 + std::time_t timet = _mkgmtime(&utc); +#else std::time_t timet = timegm(&utc); +#endif return Clock::from_time_t(timet); } Nonce Nonce_TimeSinceEpochInMs(Duration delay) { - const auto nowTime = Clock::now(); - return IntegralToString(TimestampToMillisecondsSinceEpoch(nowTime + delay)); + return IntegralToString(TimestampToMillisecondsSinceEpoch(Clock::now() + delay)); } } // namespace cct