Skip to content

Commit

Permalink
Use std::unique_ptr instead of forward_list to hold ExchangePrivate m…
Browse files Browse the repository at this point in the history
…emory
  • Loading branch information
sjanel committed Mar 20, 2024
1 parent a7136ad commit cf0a8a1
Show file tree
Hide file tree
Showing 11 changed files with 238 additions and 240 deletions.
50 changes: 28 additions & 22 deletions src/api/interface/include/exchange.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <memory>
#include <optional>
#include <string_view>
#include <type_traits>

#include "cct_exception.hpp"
#include "currencycode.hpp"
Expand Down Expand Up @@ -29,9 +31,10 @@ class Exchange {
Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic);

/// Build a Exchange with both private and public exchanges
Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic, ExchangePrivate &exchangePrivate);
Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic,
std::unique_ptr<ExchangePrivate> exchangePrivate);

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

ExchangeName createExchangeName() const {
Expand All @@ -41,63 +44,63 @@ class Exchange {
return ExchangeName(name());
}

ExchangePublic &apiPublic() { return _exchangePublic; }
const ExchangePublic &apiPublic() const { return _exchangePublic; }
ExchangePublic &apiPublic() { return *_pExchangePublic; }
const ExchangePublic &apiPublic() const { return *_pExchangePublic; }

ExchangePrivate &apiPrivate() {
if (hasPrivateAPI()) {
return *_pExchangePrivate;
return *_exchangePrivate;
}
throw exception("No private key associated to exchange {}", name());
}

const ExchangePrivate &apiPrivate() const {
if (hasPrivateAPI()) {
return *_pExchangePrivate;
return *_exchangePrivate;
}
throw exception("No private key associated to exchange {}", name());
}

const ExchangeConfig &exchangeConfig() const { return _exchangeConfig; }
const ExchangeConfig &exchangeConfig() const { return *_pExchangeConfig; }

bool hasPrivateAPI() const { return _pExchangePrivate != nullptr; }
bool hasPrivateAPI() const { return static_cast<bool>(_exchangePrivate); }

bool healthCheck() { return _exchangePublic.healthCheck(); }
bool healthCheck() { return apiPublic().healthCheck(); }

CurrencyExchangeFlatSet queryTradableCurrencies() {
return hasPrivateAPI() ? _pExchangePrivate->queryTradableCurrencies() : _exchangePublic.queryTradableCurrencies();
return hasPrivateAPI() ? _exchangePrivate->queryTradableCurrencies() : apiPublic().queryTradableCurrencies();
}

CurrencyExchange convertStdCurrencyToCurrencyExchange(CurrencyCode currencyCode) {
return _exchangePublic.convertStdCurrencyToCurrencyExchange(currencyCode);
return apiPublic().convertStdCurrencyToCurrencyExchange(currencyCode);
}

MarketSet queryTradableMarkets() { return _exchangePublic.queryTradableMarkets(); }
MarketSet queryTradableMarkets() { return apiPublic().queryTradableMarkets(); }

MarketPriceMap queryAllPrices() { return _exchangePublic.queryAllPrices(); }
MarketPriceMap queryAllPrices() { return apiPublic().queryAllPrices(); }

MonetaryAmountByCurrencySet queryWithdrawalFees() {
return hasPrivateAPI() ? _pExchangePrivate->queryWithdrawalFees() : _exchangePublic.queryWithdrawalFees();
return hasPrivateAPI() ? _exchangePrivate->queryWithdrawalFees() : apiPublic().queryWithdrawalFees();
}

std::optional<MonetaryAmount> queryWithdrawalFee(CurrencyCode currencyCode) {
return hasPrivateAPI() ? _pExchangePrivate->queryWithdrawalFee(currencyCode)
: _exchangePublic.queryWithdrawalFee(currencyCode);
return hasPrivateAPI() ? _exchangePrivate->queryWithdrawalFee(currencyCode)
: apiPublic().queryWithdrawalFee(currencyCode);
}

MarketOrderBookMap queryAllApproximatedOrderBooks(int depth = ExchangePublic::kDefaultDepth) {
return _exchangePublic.queryAllApproximatedOrderBooks(depth);
return apiPublic().queryAllApproximatedOrderBooks(depth);
}

MarketOrderBook queryOrderBook(Market mk, int depth = ExchangePublic::kDefaultDepth);

MonetaryAmount queryLast24hVolume(Market mk) { return _exchangePublic.queryLast24hVolume(mk); }
MonetaryAmount queryLast24hVolume(Market mk) { return apiPublic().queryLast24hVolume(mk); }

/// Retrieve an ordered vector of recent last trades
PublicTradeVector queryLastTrades(Market mk, int nbTrades = ExchangePublic::kNbLastTradesDefault);

/// Retrieve the last price of given market.
MonetaryAmount queryLastPrice(Market mk) { return _exchangePublic.queryLastPrice(mk); }
MonetaryAmount queryLastPrice(Market mk) { return apiPublic().queryLastPrice(mk); }

bool canWithdraw(CurrencyCode currencyCode, const CurrencyExchangeFlatSet &currencyExchangeSet) const;

Expand All @@ -109,10 +112,13 @@ class Exchange {

void updateCacheFile() const;

/// unique_ptr is always trivially relocatable whatever the underlying type.
using trivially_relocatable = std::true_type;

private:
ExchangePublic &_exchangePublic;
ExchangePrivate *_pExchangePrivate = nullptr;
const ExchangeConfig &_exchangeConfig;
ExchangePublic *_pExchangePublic;
std::unique_ptr<ExchangePrivate> _exchangePrivate;
const ExchangeConfig *_pExchangeConfig;
};

} // namespace cct
26 changes: 0 additions & 26 deletions src/api/interface/include/exchangepool.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#pragma once

#include <forward_list>
#include <span>
#include <string_view>

#include "binancepublicapi.hpp"
#include "bithumbpublicapi.hpp"
Expand All @@ -21,13 +19,6 @@ class CoincenterInfo;
class FiatConverter;

namespace api {
class BinancePrivate;
class BithumbPrivate;
class HuobiPrivate;
class KrakenPrivate;
class KucoinPrivate;
class UpbitPrivate;

class CommonAPI;
class APIKeysProvider;
} // namespace api
Expand All @@ -37,13 +28,6 @@ class ExchangePool {
ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter& fiatConverter, api::CommonAPI& commonAPI,
const api::APIKeysProvider& apiKeyProvider);

ExchangePool(const ExchangePool&) = delete;
ExchangePool(ExchangePool&&) = delete;
ExchangePool& operator=(const ExchangePool&) = delete;
ExchangePool& operator=(ExchangePool&&) = delete;

~ExchangePool();

std::span<Exchange> exchanges() { return _exchanges; }
std::span<const Exchange> exchanges() const { return _exchanges; }

Expand All @@ -63,16 +47,6 @@ class ExchangePool {
api::KucoinPublic _kucoinPublic;
api::UpbitPublic _upbitPublic;

// Private exchanges (based on provided keys)
// Use std::forward_list to guarantee validity of the iterators and pointers, as we give them to Exchange object as
// pointers
std::forward_list<api::BinancePrivate> _binancePrivates;
std::forward_list<api::BithumbPrivate> _bithumbPrivates;
std::forward_list<api::HuobiPrivate> _huobiPrivates;
std::forward_list<api::KrakenPrivate> _krakenPrivates;
std::forward_list<api::KucoinPrivate> _kucoinPrivates;
std::forward_list<api::UpbitPrivate> _upbitPrivates;

ExchangeVector _exchanges;
};

Expand Down
28 changes: 13 additions & 15 deletions src/api/interface/src/exchange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@
#include "exchangeconfig.hpp"
#include "exchangeprivateapi.hpp"
#include "exchangepublicapi.hpp"
#include "marketorderbook.hpp"
#include "public-trade-vector.hpp"

namespace cct {

Exchange::Exchange(const ExchangeConfig &exchangeConfig, api::ExchangePublic &exchangePublic,
api::ExchangePrivate &exchangePrivate)
: _exchangePublic(exchangePublic),
_pExchangePrivate(std::addressof(exchangePrivate)),
_exchangeConfig(exchangeConfig) {}
Exchange::Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic)
: Exchange(exchangeConfig, exchangePublic, std::unique_ptr<ExchangePrivate>()) {}

Exchange::Exchange(const ExchangeConfig &exchangeConfig, api::ExchangePublic &exchangePublic)
: _exchangePublic(exchangePublic), _exchangeConfig(exchangeConfig) {}
Exchange::Exchange(const ExchangeConfig &exchangeConfig, ExchangePublic &exchangePublic,
std::unique_ptr<ExchangePrivate> exchangePrivate)
: _pExchangePublic(std::addressof(exchangePublic)),
_exchangePrivate(std::move(exchangePrivate)),
_pExchangeConfig(std::addressof(exchangeConfig)) {}

bool Exchange::canWithdraw(CurrencyCode currencyCode, const CurrencyExchangeFlatSet &currencyExchangeSet) const {
if (_exchangeConfig.excludedCurrenciesWithdrawal().contains(currencyCode)) {
if (_pExchangeConfig->excludedCurrenciesWithdrawal().contains(currencyCode)) {
return false;
}
auto lb = currencyExchangeSet.find(currencyCode);
Expand All @@ -43,17 +41,17 @@ bool Exchange::canDeposit(CurrencyCode currencyCode, const CurrencyExchangeFlatS
return lb->canDeposit();
}

MarketOrderBook Exchange::queryOrderBook(Market mk, int depth) { return _exchangePublic.queryOrderBook(mk, depth); }
MarketOrderBook Exchange::queryOrderBook(Market mk, int depth) { return apiPublic().queryOrderBook(mk, depth); }

/// Retrieve an ordered vector of recent last trades
PublicTradeVector Exchange::queryLastTrades(Market mk, int nbTrades) {
return _exchangePublic.queryLastTrades(mk, nbTrades);
return apiPublic().queryLastTrades(mk, nbTrades);
}

void Exchange::updateCacheFile() const {
_exchangePublic.updateCacheFile();
if (_pExchangePrivate != nullptr) {
_pExchangePrivate->updateCacheFile();
apiPublic().updateCacheFile();
if (_exchangePrivate) {
_exchangePrivate->updateCacheFile();
}
}
} // namespace cct
20 changes: 10 additions & 10 deletions src/api/interface/src/exchangepool.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "exchangepool.hpp"

#include <memory>
#include <string_view>

#include "apikey.hpp"
#include "apikeysprovider.hpp"
#include "binanceprivateapi.hpp"
#include "bithumbprivateapi.hpp"
#include "bithumbpublicapi.hpp"
#include "cct_const.hpp"
#include "cct_exception.hpp"
#include "cct_log.hpp"
Expand Down Expand Up @@ -53,21 +55,21 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
const ExchangeConfig& exchangeConfig = _coincenterInfo.exchangeConfig(exchangePublic->name());
if (canUsePrivateExchange) {
for (std::string_view keyName : _apiKeyProvider.getKeyNames(exchangeStr)) {
api::ExchangePrivate* exchangePrivate;
std::unique_ptr<api::ExchangePrivate> exchangePrivate;
ExchangeName exchangeName(exchangeStr, keyName);
const api::APIKey& apiKey = _apiKeyProvider.get(exchangeName);
if (exchangePublic == &_binancePublic) {
exchangePrivate = &_binancePrivates.emplace_front(_coincenterInfo, _binancePublic, apiKey);
exchangePrivate = std::make_unique<api::BinancePrivate>(_coincenterInfo, _binancePublic, apiKey);
} else if (exchangePublic == &_bithumbPublic) {
exchangePrivate = &_bithumbPrivates.emplace_front(_coincenterInfo, _bithumbPublic, apiKey);
exchangePrivate = std::make_unique<api::BithumbPrivate>(_coincenterInfo, _bithumbPublic, apiKey);
} else if (exchangePublic == &_huobiPublic) {
exchangePrivate = &_huobiPrivates.emplace_front(_coincenterInfo, _huobiPublic, apiKey);
exchangePrivate = std::make_unique<api::HuobiPrivate>(_coincenterInfo, _huobiPublic, apiKey);
} else if (exchangePublic == &_krakenPublic) {
exchangePrivate = &_krakenPrivates.emplace_front(_coincenterInfo, _krakenPublic, apiKey);
exchangePrivate = std::make_unique<api::KrakenPrivate>(_coincenterInfo, _krakenPublic, apiKey);
} else if (exchangePublic == &_kucoinPublic) {
exchangePrivate = &_kucoinPrivates.emplace_front(_coincenterInfo, _kucoinPublic, apiKey);
exchangePrivate = std::make_unique<api::KucoinPrivate>(_coincenterInfo, _kucoinPublic, apiKey);
} else if (exchangePublic == &_upbitPublic) {
exchangePrivate = &_upbitPrivates.emplace_front(_coincenterInfo, _upbitPublic, apiKey);
exchangePrivate = std::make_unique<api::UpbitPrivate>(_coincenterInfo, _upbitPublic, apiKey);
} else {
throw exception("Unsupported platform {}", exchangeStr);
}
Expand All @@ -81,7 +83,7 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
}
}

_exchanges.emplace_back(exchangeConfig, *exchangePublic, *exchangePrivate);
_exchanges.emplace_back(exchangeConfig, *exchangePublic, std::move(exchangePrivate));
}
} else {
_exchanges.emplace_back(exchangeConfig, *exchangePublic);
Expand All @@ -90,6 +92,4 @@ ExchangePool::ExchangePool(const CoincenterInfo& coincenterInfo, FiatConverter&
_exchanges.shrink_to_fit();
}

ExchangePool::~ExchangePool() = default;

} // namespace cct
Loading

0 comments on commit cf0a8a1

Please sign in to comment.