Skip to content

Commit

Permalink
[Code refactoring] - Use ExchangeNameEnum instead of string_view in E…
Browse files Browse the repository at this point in the history
…xchangePublic
  • Loading branch information
sjanel committed Nov 16, 2024
1 parent 3d83e46 commit 89ce5ec
Show file tree
Hide file tree
Showing 40 changed files with 272 additions and 223 deletions.
8 changes: 5 additions & 3 deletions src/api-objects/include/apikeysprovider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,19 @@ class APIKeysProvider {

APIKeysProvider(std::string_view dataDir, const ExchangeSecretsInfo &exchangeSecretsInfo, settings::RunMode runMode);

KeyNames getKeyNames(std::string_view platform) const;
KeyNames getKeyNames(ExchangeNameEnum exchangeNameEnum) const;

bool contains(std::string_view platform) const { return _apiKeysMap.find(platform) != _apiKeysMap.end(); }
bool contains(ExchangeNameEnum exchangeNameEnum) const {
return _apiKeysMap.find(exchangeNameEnum) != _apiKeysMap.end();
}

const APIKey &get(const ExchangeName &exchangeName) const;

string str() const;

private:
using APIKeys = vector<APIKey>;
using APIKeysMap = std::map<string, APIKeys, std::less<>>;
using APIKeysMap = std::map<ExchangeNameEnum, APIKeys>;

static APIKeysMap ParseAPIKeys(std::string_view dataDir, const ExchangeSecretsInfo &exchangeSecretsInfo,
settings::RunMode runMode);
Expand Down
21 changes: 14 additions & 7 deletions src/api-objects/src/apikeysprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ APIKeysProvider::APIKeysProvider(std::string_view dataDir, const ExchangeSecrets
}
}

APIKeysProvider::KeyNames APIKeysProvider::getKeyNames(std::string_view platform) const {
APIKeysProvider::KeyNames APIKeysProvider::getKeyNames(ExchangeNameEnum exchangeNameEnum) const {
KeyNames keyNames;
auto foundIt = _apiKeysMap.find(platform);
auto foundIt = _apiKeysMap.find(exchangeNameEnum);
if (foundIt != _apiKeysMap.end()) {
const APIKeys& apiKeys = foundIt->second;
std::ranges::transform(apiKeys, std::back_inserter(keyNames), [](const APIKey& apiKey) { return apiKey.name(); });
Expand All @@ -52,7 +52,10 @@ APIKeysProvider::KeyNames APIKeysProvider::getKeyNames(std::string_view platform

const APIKey& APIKeysProvider::get(const ExchangeName& exchangeName) const {
std::string_view platformStr = exchangeName.name();
auto foundIt = _apiKeysMap.find(platformStr);
ExchangeNameEnum exchangeNameEnum = static_cast<ExchangeNameEnum>(
std::find(std::begin(kSupportedExchanges), std::end(kSupportedExchanges), platformStr) -
std::begin(kSupportedExchanges));
auto foundIt = _apiKeysMap.find(exchangeNameEnum);
if (foundIt == _apiKeysMap.end()) {
throw exception("Unable to retrieve private key for {}", platformStr);
}
Expand Down Expand Up @@ -89,6 +92,10 @@ APIKeysProvider::APIKeysMap APIKeysProvider::ParseAPIKeys(std::string_view dataD
log::info("Not loading {} private keys as requested", publicExchangeName);
continue;
}
ExchangeNameEnum exchangeNameEnum = static_cast<ExchangeNameEnum>(
std::find(std::begin(kSupportedExchanges), std::end(kSupportedExchanges), publicExchangeName) -
std::begin(kSupportedExchanges));

for (auto& [name, keySecretObj] : keyObj.items()) {
auto keyIt = keySecretObj.find("key");
auto privateIt = keySecretObj.find("private");
Expand All @@ -115,9 +122,9 @@ APIKeysProvider::APIKeysMap APIKeysProvider::ParseAPIKeys(std::string_view dataD
}
}

map[publicExchangeName].emplace_back(publicExchangeName, name, std::move(keyIt->get_ref<string&>()),
std::move(privateIt->get_ref<string&>()), std::move(passphrase),
AccountOwner(ownerEnName, ownerKoName));
map[exchangeNameEnum].emplace_back(publicExchangeName, name, std::move(keyIt->get_ref<string&>()),
std::move(privateIt->get_ref<string&>()), std::move(passphrase),
AccountOwner(ownerEnName, ownerKoName));
}
}
if (map.empty()) {
Expand Down Expand Up @@ -149,7 +156,7 @@ string APIKeysProvider::str() const {
foundKeysStr.push_back('}');
}
foundKeysStr.push_back('@');
foundKeysStr.append(platform);
foundKeysStr.append(kSupportedExchanges[static_cast<int>(platform)]);
}
return foundKeysStr;
}
Expand Down
4 changes: 2 additions & 2 deletions src/api/common/include/exchangeprivateapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ class ExchangePrivate : public CacheFileUpdatorInterface {
TradedAmountsVectorWithFinalAmount queryDustSweeper(CurrencyCode currencyCode);

/// Builds an ExchangeName wrapping the exchange and the key name
ExchangeName exchangeName() const { return {_exchangePublic.name(), _apiKey.name()}; }
ExchangeName exchangeName() const { return ExchangeName(_exchangePublic.exchangeNameEnum(), _apiKey.name()); }

const ExchangeConfig &exchangeConfig() const { return _exchangePublic.exchangeConfig(); }
const auto &exchangeConfig() const { return _exchangePublic.exchangeConfig(); }

protected:
ExchangePrivate(const CoincenterInfo &coincenterInfo, ExchangePublic &exchangePublic, const APIKey &apiKey);
Expand Down
2 changes: 1 addition & 1 deletion src/api/common/src/exchangeprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ PlaceOrderInfo ExchangePrivate::computeSimulatedMatchedPlacedOrderInfo(MonetaryA
const bool isSell = tradeInfo.tradeContext.side == TradeSide::kSell;

MonetaryAmount toAmount = isSell ? volume.convertTo(price) : volume;
ExchangeConfig::FeeType feeType = isTakerStrategy ? ExchangeConfig::FeeType::kTaker : ExchangeConfig::FeeType::kMaker;
auto feeType = isTakerStrategy ? ExchangeConfig::FeeType::kTaker : ExchangeConfig::FeeType::kMaker;
toAmount = _coincenterInfo.exchangeConfig(_exchangePublic.name()).applyFee(toAmount, feeType);
PlaceOrderInfo placeOrderInfo(OrderInfo(TradedAmounts(isSell ? volume : volume.toNeutral() * price, toAmount)),
OrderId("SimulatedOrderId"));
Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/src/binanceprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ Wallet BinancePrivate::DepositWalletFunc::operator()(CurrencyCode currencyCode)
const CoincenterInfo& coincenterInfo = _exchangePublic.coincenterInfo();
bool doCheckWallet = coincenterInfo.exchangeConfig(_exchangePublic.name()).validateDepositAddressesInFile();
WalletCheck walletCheck(coincenterInfo.dataDir(), doCheckWallet);
Wallet wallet(ExchangeName(_exchangePublic.name(), _apiKey.name()), currencyCode,
Wallet wallet(ExchangeName(_exchangePublic.exchangeNameEnum(), _apiKey.name()), currencyCode,
std::move(result["address"].get_ref<string&>()), tag, walletCheck, _apiKey.accountOwner());
log::info("Retrieved {} (URL: '{}')", wallet, result["url"].get<std::string_view>());
return wallet;
Expand Down
9 changes: 4 additions & 5 deletions src/api/exchanges/src/bithumbprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@ Wallet BithumbPrivate::DepositWalletFunc::operator()(CurrencyCode currencyCode)
const CoincenterInfo& coincenterInfo = _exchangePublic.coincenterInfo();
bool doCheckWallet = coincenterInfo.exchangeConfig(_exchangePublic.name()).validateDepositAddressesInFile();
WalletCheck walletCheck(coincenterInfo.dataDir(), doCheckWallet);
Wallet wallet(ExchangeName(_exchangePublic.name(), _apiKey.name()), currencyCode, string(address), tag, walletCheck,
_apiKey.accountOwner());
Wallet wallet(ExchangeName(_exchangePublic.exchangeNameEnum(), _apiKey.name()), currencyCode, string(address), tag,
walletCheck, _apiKey.accountOwner());
log::info("Retrieved {}", wallet);
return wallet;
}
Expand Down Expand Up @@ -867,9 +867,8 @@ PlaceOrderInfo BithumbPrivate::placeOrder(MonetaryAmount /*from*/, MonetaryAmoun

// Volume is gross amount if from amount is in quote currency, we should remove the fees
if (fromCurrencyCode == mk.quote()) {
ExchangeConfig::FeeType feeType =
isTakerStrategy ? ExchangeConfig::FeeType::kTaker : ExchangeConfig::FeeType::kMaker;
const ExchangeConfig& exchangeConfig = _coincenterInfo.exchangeConfig(_exchangePublic.name());
const auto feeType = isTakerStrategy ? ExchangeConfig::FeeType::kTaker : ExchangeConfig::FeeType::kMaker;
const auto& exchangeConfig = _coincenterInfo.exchangeConfig(_exchangePublic.name());
volume = exchangeConfig.applyFee(volume, feeType);
}

Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/src/huobiprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ Wallet HuobiPrivate::DepositWalletFunc::operator()(CurrencyCode currencyCode) {

string address;
std::string_view tag;
ExchangeName exchangeName(_huobiPublic.name(), _apiKey.name());
ExchangeName exchangeName(_huobiPublic.exchangeNameEnum(), _apiKey.name());
const CoincenterInfo& coincenterInfo = _huobiPublic.coincenterInfo();
bool doCheckWallet = coincenterInfo.exchangeConfig(_huobiPublic.name()).validateDepositAddressesInFile();
WalletCheck walletCheck(coincenterInfo.dataDir(), doCheckWallet);
Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/src/krakenprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ BalancePortfolio KrakenPrivate::queryAccountBalance(const BalanceOptions& balanc
Wallet KrakenPrivate::DepositWalletFunc::operator()(CurrencyCode currencyCode) {
CurrencyExchange krakenCurrency = _exchangePublic.convertStdCurrencyToCurrencyExchange(currencyCode);
auto [res, err] = PrivateQuery(_curlHandle, _apiKey, "/private/DepositMethods", {{"asset", krakenCurrency.altStr()}});
ExchangeName eName(_exchangePublic.name(), _apiKey.name());
ExchangeName eName(_exchangePublic.exchangeNameEnum(), _apiKey.name());
if (res.empty()) {
throw exception("No deposit method found on {} for {}", eName, currencyCode);
}
Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/src/kucoinprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ BalancePortfolio KucoinPrivate::queryAccountBalance(const BalanceOptions& balanc
Wallet KucoinPrivate::DepositWalletFunc::operator()(CurrencyCode currencyCode) {
json::container result = PrivateQuery(_curlHandle, _apiKey, HttpRequestType::kGet, "/api/v2/deposit-addresses",
{{"currency", currencyCode.str()}})["data"];
ExchangeName exchangeName(_kucoinPublic.name(), _apiKey.name());
ExchangeName exchangeName(_kucoinPublic.exchangeNameEnum(), _apiKey.name());
if (result.empty()) {
log::info("No deposit address for {} in {}, creating one", currencyCode, exchangeName);
result = PrivateQuery(_curlHandle, _apiKey, HttpRequestType::kPost, "/api/v1/deposit-addresses",
Expand Down
7 changes: 3 additions & 4 deletions src/api/exchanges/src/upbitprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ Wallet UpbitPrivate::DepositWalletFunc::operator()(CurrencyCode currencyCode) {
const CoincenterInfo& coincenterInfo = _exchangePublic.coincenterInfo();
bool doCheckWallet = coincenterInfo.exchangeConfig(_exchangePublic.name()).validateDepositAddressesInFile();
WalletCheck walletCheck(coincenterInfo.dataDir(), doCheckWallet);
Wallet wallet(ExchangeName(_exchangePublic.name(), _apiKey.name()), currencyCode,
Wallet wallet(ExchangeName(_exchangePublic.exchangeNameEnum(), _apiKey.name()), currencyCode,
std::move(addressIt->get_ref<string&>()), tag, walletCheck, _apiKey.accountOwner());
log::info("Retrieved {}", wallet);
return wallet;
Expand Down Expand Up @@ -554,9 +554,8 @@ void UpbitPrivate::applyFee(Market mk, CurrencyCode fromCurrencyCode, bool isTak
MonetaryAmount& volume) {
if (fromCurrencyCode == mk.quote()) {
// For 'buy', from amount is fee excluded
ExchangeConfig::FeeType feeType =
isTakerStrategy ? ExchangeConfig::FeeType::kTaker : ExchangeConfig::FeeType::kMaker;
const ExchangeConfig& exchangeConfig = _coincenterInfo.exchangeConfig(_exchangePublic.name());
const auto feeType = isTakerStrategy ? ExchangeConfig::FeeType::kTaker : ExchangeConfig::FeeType::kMaker;
const auto& exchangeConfig = _coincenterInfo.exchangeConfig(_exchangePublic.name());
if (isTakerStrategy) {
from = exchangeConfig.applyFee(from, feeType);
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/api/exchanges/test/bithumb_place_order_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class BithumbPrivateAPIPlaceOrderTest : public ::testing::Test {
CommonAPI commonAPI{coincenterInfo, Duration::max()};
BithumbPublic exchangePublic{coincenterInfo, fiatConverter, commonAPI};
APIKeysProvider apiKeysProvider{coincenterInfo.dataDir(), coincenterInfo.getRunMode()};
ExchangeName exchangeName{exchangePublic.name(), apiKeysProvider.getKeyNames(exchangePublic.name()).front()};
ExchangeName exchangeName{exchangePublic.exchangeNameEnum(),
apiKeysProvider.getKeyNames(exchangePublic.exchangeNameEnum()).front()};
const APIKey& testKey = apiKeysProvider.get(exchangeName);
BithumbPrivate exchangePrivate{coincenterInfo, exchangePublic, testKey};

Expand Down
8 changes: 4 additions & 4 deletions src/api/exchanges/test/exchangecommonapi_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,13 @@ class TestAPI {

private:
void createPrivateExchangeIfKeyPresent() {
std::string_view publicExchangeName = exchangePublic.name();
if (!apiKeysProvider.contains(publicExchangeName)) {
log::warn("Skip {} private API test as cannot find associated private key", publicExchangeName);
auto exchangeNameEnum = exchangePublic.exchangeNameEnum();
if (!apiKeysProvider.contains(exchangeNameEnum)) {
log::warn("Skip {} private API test as cannot find associated private key", exchangePublic.name());
return;
}

ExchangeName exchangeName(publicExchangeName, apiKeysProvider.getKeyNames(publicExchangeName).front());
ExchangeName exchangeName(exchangeNameEnum, apiKeysProvider.getKeyNames(exchangeNameEnum).front());
const APIKey &firstAPIKey = apiKeysProvider.get(exchangeName);

exchangePrivateOpt.emplace(coincenterInfo, exchangePublic, firstAPIKey);
Expand Down
6 changes: 2 additions & 4 deletions src/api/interface/include/exchange.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,13 @@ class Exchange : public CacheFileUpdatorInterface {
std::unique_ptr<ExchangePrivate> exchangePrivate);

std::string_view name() const { return apiPublic().name(); }
ExchangeNameEnum exchangeNameEnum() const { return apiPublic().exchangeNameEnum(); }
std::string_view keyName() const { return apiPrivate().keyName(); }

std::size_t publicExchangePos() const;

ExchangeName createExchangeName() const {
if (hasPrivateAPI()) {
return {name(), keyName()};
}
return ExchangeName(name());
return ExchangeName(exchangeNameEnum(), hasPrivateAPI() ? keyName() : std::string_view());
}

ExchangePublic &apiPublic() { return *_pExchangePublic; }
Expand Down
13 changes: 10 additions & 3 deletions src/api/interface/include/exchangeretriever.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ class ExchangeRetriever {
ret.push_back(std::addressof(*foundIt));
}
if (ret.size() == oldSize) {
throw exception("Unable to find {} in the exchange list", name);
if constexpr (std::is_same_v<std::remove_cvref_t<decltype(name)>, ExchangeNameEnum>) {
throw exception("Unable to find {} in the exchange list", kSupportedExchanges[static_cast<int>(name)]);
} else {
throw exception("Unable to find {} in the exchange list", name);
}
}
}
break;
Expand All @@ -103,13 +107,16 @@ class ExchangeRetriever {

template <class NameType>
struct Matcher {
static_assert(std::is_same_v<NameType, ExchangeName> || std::is_same_v<NameType, std::string_view>);
static_assert(std::is_same_v<NameType, ExchangeName> || std::is_same_v<NameType, std::string_view> ||
std::is_same_v<NameType, ExchangeNameEnum>);

bool operator()(const Exchange &e, const NameType &n) const {
if constexpr (std::is_same_v<NameType, std::string_view>) {
return e.name() == n;
} else {
} else if constexpr (std::is_same_v<NameType, ExchangeName>) {
return e.matches(n);
} else if constexpr (std::is_same_v<NameType, ExchangeNameEnum>) {
return e.exchangeNameEnum() == n;
}
}
};
Expand Down
27 changes: 14 additions & 13 deletions src/api/interface/src/exchangepool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,31 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
_krakenPublic(_coincenterInfo, _fiatConverter, _commonAPI),
_kucoinPublic(_coincenterInfo, _fiatConverter, _commonAPI),
_upbitPublic(_coincenterInfo, _fiatConverter, _commonAPI) {
for (std::string_view exchangeStr : kSupportedExchanges) {
for (int exchangePos = 0; exchangePos < kNbSupportedExchanges; ++exchangePos) {
ExchangeNameEnum exchangeNameEnum = static_cast<ExchangeNameEnum>(exchangePos);
api::ExchangePublic* exchangePublic;
if (exchangeStr == "binance") {
if (exchangeNameEnum == ExchangeNameEnum::binance) {
exchangePublic = &_binancePublic;
} else if (exchangeStr == "bithumb") {
} else if (exchangeNameEnum == ExchangeNameEnum::bithumb) {
exchangePublic = &_bithumbPublic;
} else if (exchangeStr == "huobi") {
} else if (exchangeNameEnum == ExchangeNameEnum::huobi) {
exchangePublic = &_huobiPublic;
} else if (exchangeStr == "kraken") {
} else if (exchangeNameEnum == ExchangeNameEnum::kraken) {
exchangePublic = &_krakenPublic;
} else if (exchangeStr == "kucoin") {
} else if (exchangeNameEnum == ExchangeNameEnum::kucoin) {
exchangePublic = &_kucoinPublic;
} else if (exchangeStr == "upbit") {
} else if (exchangeNameEnum == ExchangeNameEnum::upbit) {
exchangePublic = &_upbitPublic;
} else {
throw exception("Should not happen, unsupported platform {}", exchangeStr);
throw exception("Should not happen, unsupported exchange pos {}", exchangePos);
}

const bool canUsePrivateExchange = _apiKeyProvider.contains(exchangeStr);
const ExchangeConfig& exchangeConfig = _coincenterInfo.exchangeConfig(exchangePublic->name());
const bool canUsePrivateExchange = _apiKeyProvider.contains(exchangeNameEnum);
const auto& exchangeConfig = _coincenterInfo.exchangeConfig(kSupportedExchanges[exchangePos]);
if (canUsePrivateExchange) {
for (std::string_view keyName : _apiKeyProvider.getKeyNames(exchangeStr)) {
for (std::string_view keyName : _apiKeyProvider.getKeyNames(exchangeNameEnum)) {
std::unique_ptr<api::ExchangePrivate> exchangePrivate;
ExchangeName exchangeName(exchangeStr, keyName);
ExchangeName exchangeName(exchangeNameEnum, keyName);
const api::APIKey& apiKey = _apiKeyProvider.get(exchangeName);
if (exchangePublic == &_binancePublic) {
exchangePrivate = std::make_unique<api::BinancePrivate>(_coincenterInfo, _binancePublic, apiKey);
Expand All @@ -72,7 +73,7 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
} else if (exchangePublic == &_upbitPublic) {
exchangePrivate = std::make_unique<api::UpbitPrivate>(_coincenterInfo, _upbitPublic, apiKey);
} else {
throw exception("Unsupported platform {}", exchangeStr);
throw exception("Should not happen");
}

if (exchangeConfig.shouldValidateApiKey()) {
Expand Down
8 changes: 6 additions & 2 deletions src/basic-objects/include/cct_const.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

namespace cct {

enum class ExchangeNameEnum : int8_t { binance, bithumb, huobi, kraken, kucoin, upbit };
#define CCT_EXCHANGE_NAMES binance, bithumb, huobi, kraken, kucoin, upbit

enum class ExchangeNameEnum : int8_t { CCT_EXCHANGE_NAMES };

static constexpr std::string_view kDefaultDataDir = CCT_DATA_DIR;

Expand All @@ -35,9 +37,11 @@ template <>
struct glz::meta<cct::ExchangeNameEnum> {
using enum cct::ExchangeNameEnum;

static constexpr auto value = enumerate(binance, bithumb, huobi, kraken, kucoin, upbit);
static constexpr auto value = enumerate(CCT_EXCHANGE_NAMES);
};

#undef CCT_EXCHANGE_NAMES

namespace cct {

/// Ordered list of supported exchange names.
Expand Down
Loading

0 comments on commit 89ce5ec

Please sign in to comment.