Skip to content

Commit

Permalink
Use FlatSet instead of unordered_map for withdrawal fees
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanel committed Nov 28, 2023
1 parent afc1f21 commit 65a864f
Show file tree
Hide file tree
Showing 23 changed files with 160 additions and 81 deletions.
3 changes: 2 additions & 1 deletion src/api-objects/include/exchangepublicapitypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
#include "market.hpp"
#include "marketorderbook.hpp"
#include "monetaryamount.hpp"
#include "monetaryamountbycurrencyset.hpp"
#include "publictrade.hpp"

namespace cct {
using MarketSet = FlatSet<Market>;
using MarketOrderBookMap = std::unordered_map<Market, MarketOrderBook>;
using MarketPriceMap = std::unordered_map<Market, MonetaryAmount>;
using MarketsPath = SmallVector<Market, 3>;
using WithdrawalFeeMap = std::unordered_map<CurrencyCode, MonetaryAmount>;
using WithdrawalFeesSet = MonetaryAmountByCurrencySet;
using LastTradesVector = vector<PublicTrade>;
} // namespace cct
2 changes: 1 addition & 1 deletion src/api/common/include/exchangeprivateapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class ExchangePrivate : public ExchangeBase {

/// Retrieve the fixed withdrawal fees per currency.
/// Some exchanges provide this service in the public REST API but not all, hence this private API flavor.
virtual WithdrawalFeeMap queryWithdrawalFees() { return _exchangePublic.queryWithdrawalFees(); }
virtual WithdrawalFeesSet queryWithdrawalFees() { return _exchangePublic.queryWithdrawalFees(); }

/// Retrieve the withdrawal fee of a Currency only
/// Some exchanges provide this service in the public REST API but not all, hence this private API flavor.
Expand Down
2 changes: 1 addition & 1 deletion src/api/common/include/exchangepublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class ExchangePublic : public ExchangeBase {
/// Retrieve the fixed withdrawal fees per currency.
/// Depending on the exchange, this could be retrieved dynamically,
/// or, if not possible, should be retrieved from a static source updated regularly.
virtual WithdrawalFeeMap queryWithdrawalFees() = 0;
virtual WithdrawalFeesSet queryWithdrawalFees() = 0;

/// Retrieve the withdrawal fee of a Currency only
virtual MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/api/common/include/exchangepublicapi_mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class MockExchangePublic : public ExchangePublic {
MOCK_METHOD(CurrencyExchange, convertStdCurrencyToCurrencyExchange, (CurrencyCode currencyCode), (override));
MOCK_METHOD(MarketSet, queryTradableMarkets, (), (override));
MOCK_METHOD(MarketPriceMap, queryAllPrices, (), (override));
MOCK_METHOD(WithdrawalFeeMap, queryWithdrawalFees, (), (override));
MOCK_METHOD(WithdrawalFeesSet, queryWithdrawalFees, (), (override));
MOCK_METHOD(MonetaryAmount, queryWithdrawalFee, (CurrencyCode currencyCode), (override));
MOCK_METHOD(bool, isWithdrawalFeesSourceReliable, (), (const override));
MOCK_METHOD(MarketOrderBookMap, queryAllApproximatedOrderBooks, (int depth), (override));
Expand Down
4 changes: 2 additions & 2 deletions src/api/exchanges/include/binanceprivateapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class BinancePrivate : public ExchangePrivate {

WithdrawsSet queryRecentWithdraws(const WithdrawsConstraints& withdrawsConstraints = WithdrawsConstraints()) override;

WithdrawalFeeMap queryWithdrawalFees() override { return _allWithdrawFeesCache.get(); }
WithdrawalFeesSet queryWithdrawalFees() override { return _allWithdrawFeesCache.get(); }

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override { return _withdrawFeesCache.get(currencyCode); }

Expand Down Expand Up @@ -111,7 +111,7 @@ class BinancePrivate : public ExchangePrivate {
Duration& queryDelay)
: BinanceContext(curlHandle, apiKey, exchangePublic, queryDelay) {}

WithdrawalFeeMap operator()();
WithdrawalFeesSet operator()();
};

struct WithdrawFeesFunc : public BinanceContext {
Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/include/binancepublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class BinancePublic : public ExchangePublic {

MarketPriceMap queryAllPrices() override { return MarketPriceMapFromMarketOrderBookMap(_allOrderBooksCache.get(1)); }

WithdrawalFeeMap queryWithdrawalFees() override;
WithdrawalFeesSet queryWithdrawalFees() override;

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;

Expand Down
4 changes: 2 additions & 2 deletions src/api/exchanges/include/bithumbpublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class BithumbPublic : public ExchangePublic {

MarketPriceMap queryAllPrices() override { return MarketPriceMapFromMarketOrderBookMap(_allOrderBooksCache.get()); }

WithdrawalFeeMap queryWithdrawalFees() override { return _withdrawalFeesCache.get(); }
WithdrawalFeesSet queryWithdrawalFees() override { return _withdrawalFeesCache.get(); }

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;

Expand Down Expand Up @@ -74,7 +74,7 @@ class BithumbPublic : public ExchangePublic {
settings::RunMode runMode)
: _curlHandle(kFeeUrl, pMetricGateway, permanentCurlOptions, runMode) {}

WithdrawalFeeMap operator()();
WithdrawalFeesSet operator()();

CurlHandle _curlHandle;
};
Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/include/huobipublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class HuobiPublic : public ExchangePublic {

MarketPriceMap queryAllPrices() override { return MarketPriceMapFromMarketOrderBookMap(_allOrderBooksCache.get(1)); }

WithdrawalFeeMap queryWithdrawalFees() override;
WithdrawalFeesSet queryWithdrawalFees() override;

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;

Expand Down
4 changes: 2 additions & 2 deletions src/api/exchanges/include/krakenpublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class KrakenPublic : public ExchangePublic {

MarketPriceMap queryAllPrices() override { return MarketPriceMapFromMarketOrderBookMap(_allOrderBooksCache.get(1)); }

WithdrawalFeeMap queryWithdrawalFees() override { return _withdrawalFeesCache.get().first; }
WithdrawalFeesSet queryWithdrawalFees() override { return _withdrawalFeesCache.get().first; }

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;

Expand Down Expand Up @@ -76,7 +76,7 @@ class KrakenPublic : public ExchangePublic {
class WithdrawalFeesFunc {
public:
using WithdrawalMinMap = std::unordered_map<CurrencyCode, MonetaryAmount>;
using WithdrawalInfoMaps = std::pair<WithdrawalFeeMap, WithdrawalMinMap>;
using WithdrawalInfoMaps = std::pair<WithdrawalFeesSet, WithdrawalMinMap>;

WithdrawalFeesFunc(const CoincenterInfo& coincenterInfo, Duration minDurationBetweenQueries);

Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/include/kucoinpublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class KucoinPublic : public ExchangePublic {

MarketPriceMap queryAllPrices() override { return MarketPriceMapFromMarketOrderBookMap(_allOrderBooksCache.get(1)); }

WithdrawalFeeMap queryWithdrawalFees() override;
WithdrawalFeesSet queryWithdrawalFees() override;

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;

Expand Down
4 changes: 2 additions & 2 deletions src/api/exchanges/include/upbitpublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class UpbitPublic : public ExchangePublic {

MarketPriceMap queryAllPrices() override { return MarketPriceMapFromMarketOrderBookMap(_allOrderBooksCache.get(1)); }

WithdrawalFeeMap queryWithdrawalFees() override { return _withdrawalFeesCache.get(); }
WithdrawalFeesSet queryWithdrawalFees() override { return _withdrawalFeesCache.get(); }

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;

Expand Down Expand Up @@ -79,7 +79,7 @@ class UpbitPublic : public ExchangePublic {
};

struct WithdrawalFeesFunc {
WithdrawalFeeMap operator()();
WithdrawalFeesSet operator()();

const string& _name;
std::string_view _dataDir;
Expand Down
9 changes: 5 additions & 4 deletions src/api/exchanges/src/binanceprivateapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "cct_json.hpp"
#include "cct_smallvector.hpp"
#include "cct_string.hpp"
#include "cct_vector.hpp"
#include "coincenterinfo.hpp"
#include "curlhandle.hpp"
#include "curloptions.hpp"
Expand Down Expand Up @@ -541,16 +542,16 @@ WithdrawsSet BinancePrivate::queryRecentWithdraws(const WithdrawsConstraints& wi
return withdrawsSet;
}

WithdrawalFeeMap BinancePrivate::AllWithdrawFeesFunc::operator()() {
WithdrawalFeesSet BinancePrivate::AllWithdrawFeesFunc::operator()() {
json result = PrivateQuery(_curlHandle, _apiKey, HttpRequestType::kGet, "/sapi/v1/asset/assetDetail", _queryDelay);
WithdrawalFeeMap ret;
vector<MonetaryAmount> fees;
for (const auto& [curCodeStr, withdrawFeeDetails] : result.items()) {
if (withdrawFeeDetails["withdrawStatus"].get<bool>()) {
CurrencyCode cur(curCodeStr);
ret.insert_or_assign(cur, MonetaryAmount(withdrawFeeDetails["withdrawFee"].get<std::string_view>(), cur));
fees.emplace_back(withdrawFeeDetails["withdrawFee"].get<std::string_view>(), cur);
}
}
return ret;
return WithdrawalFeesSet(std::move(fees));
}

MonetaryAmount BinancePrivate::WithdrawFeesFunc::operator()(CurrencyCode currencyCode) {
Expand Down
12 changes: 6 additions & 6 deletions src/api/exchanges/src/binancepublicapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ MonetaryAmount ComputeWithdrawalFeesFromNetworkList(CurrencyCode cur, const json
}
} // namespace

WithdrawalFeeMap BinancePublic::queryWithdrawalFees() {
WithdrawalFeeMap ret;
WithdrawalFeesSet BinancePublic::queryWithdrawalFees() {
vector<MonetaryAmount> fees;
for (const json& coinJson : _globalInfosCache.get()) {
std::string_view coinStr = coinJson["coin"].get<std::string_view>();
if (coinStr.size() > CurrencyCode::kMaxLen) {
Expand All @@ -249,12 +249,12 @@ WithdrawalFeeMap BinancePublic::queryWithdrawalFees() {
CurrencyCode cur(coinStr);
MonetaryAmount withdrawFee = ComputeWithdrawalFeesFromNetworkList(cur, coinJson["networkList"]);
log::trace("Retrieved {} withdrawal fee {}", _name, withdrawFee);
ret.insert_or_assign(cur, withdrawFee);
fees.push_back(std::move(withdrawFee));
}

log::info("Retrieved {} withdrawal fees for {} coins", _name, ret.size());
assert(!ret.empty());
return ret;
log::info("Retrieved {} withdrawal fees for {} coins", _name, fees.size());
assert(!fees.empty());
return WithdrawalFeesSet(std::move(fees));
}

MonetaryAmount BinancePublic::queryWithdrawalFee(CurrencyCode currencyCode) {
Expand Down
18 changes: 9 additions & 9 deletions src/api/exchanges/src/bithumbpublicapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ MonetaryAmount BithumbPublic::queryWithdrawalFee(CurrencyCode currencyCode) {
if (it == map.end()) {
throw exception("Unable to find {} in withdrawal fees", currencyCode);
}
return it->second;
return *it;
}

MonetaryAmount BithumbPublic::queryLastPrice(Market mk) {
Expand All @@ -147,8 +147,8 @@ MonetaryAmount BithumbPublic::queryLastPrice(Market mk) {
return *avgPrice;
}

WithdrawalFeeMap BithumbPublic::WithdrawalFeesFunc::operator()() {
WithdrawalFeeMap ret;
WithdrawalFeesSet BithumbPublic::WithdrawalFeesFunc::operator()() {
vector<MonetaryAmount> fees;
// This is not a published API and only a "standard" html page. We will capture the text information in it.
// Warning, it's not in json format so we will need manual parsing.
std::string_view dataStr = _curlHandle.query("/customer_support/info_fee", CurlOptions(HttpRequestType::kGet));
Expand All @@ -170,7 +170,7 @@ WithdrawalFeeMap BithumbPublic::WithdrawalFeesFunc::operator()() {
std::size_t nextCoinSep = dataStr.find(kCoinSep, endP);
if (nextRightOutFee > nextCoinSep) {
// This means no withdraw fee data, probably 0 ?
ret.insert_or_assign(coinAcro, MonetaryAmount(0, coinAcro));
fees.emplace_back(0, coinAcro);
continue;
}
charPos = dataStr.find(kFeeSep, endP);
Expand All @@ -181,15 +181,15 @@ WithdrawalFeeMap BithumbPublic::WithdrawalFeesFunc::operator()() {
endP = dataStr.find('<', charPos);
std::string_view withdrawFee(dataStr.begin() + charPos, dataStr.begin() + endP);
MonetaryAmount ma(withdrawFee, coinAcro);
log::debug("Updated Bithumb withdrawal fees {}", ma);
ret.insert_or_assign(std::move(coinAcro), std::move(ma));
log::debug("Updated Bithumb withdrawal fee {}", ma);
fees.push_back(std::move(ma));
}
if (ret.empty()) {
if (fees.empty()) {
log::error("Unable to parse Bithumb withdrawal fees, syntax might have changed");
} else {
log::info("Updated Bithumb withdrawal fees for {} coins", ret.size());
log::info("Updated Bithumb withdrawal fees for {} coins", fees.size());
}
return ret;
return WithdrawalFeesSet(std::move(fees));
}

CurrencyExchangeFlatSet BithumbPublic::TradableCurrenciesFunc::operator()() {
Expand Down
14 changes: 7 additions & 7 deletions src/api/exchanges/src/huobipublicapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ std::pair<MarketSet, HuobiPublic::MarketsFunc::MarketInfoMap> HuobiPublic::Marke
return {std::move(markets), std::move(marketInfoMap)};
}

WithdrawalFeeMap HuobiPublic::queryWithdrawalFees() {
WithdrawalFeeMap ret;
WithdrawalFeesSet HuobiPublic::queryWithdrawalFees() {
vector<MonetaryAmount> fees;
for (const json& curDetail : _tradableCurrenciesCache.get()) {
std::string_view curStr = curDetail["currency"].get<std::string_view>();
CurrencyCode cur(_coincenterInfo.standardizeCurrencyCode(curStr));
Expand All @@ -264,13 +264,13 @@ WithdrawalFeeMap HuobiPublic::queryWithdrawalFees() {
std::string_view withdrawFeeStr = chainDetail["transactFeeWithdraw"].get<std::string_view>();
MonetaryAmount withdrawFee(withdrawFeeStr, cur);
log::trace("Retrieved {} withdrawal fee {}", _name, withdrawFee);
ret.insert_or_assign(cur, withdrawFee);
fees.push_back(withdrawFee);
} else if (withdrawFeeTypeStr == "rate") {
log::debug("Unsupported rate withdraw fee for {}", _name);
ret.insert_or_assign(cur, MonetaryAmount(0, cur));
fees.emplace_back(0, cur);
} else if (withdrawFeeTypeStr == "circulated") {
log::debug("Unsupported circulated withdraw fee for {}", _name);
ret.insert_or_assign(cur, MonetaryAmount(0, cur));
fees.emplace_back(0, cur);
}
}

Expand All @@ -282,8 +282,8 @@ WithdrawalFeeMap HuobiPublic::queryWithdrawalFees() {
}
}

log::info("Retrieved {} withdrawal fees for {} coins", _name, ret.size());
return ret;
log::info("Retrieved {} withdrawal fees for {} coins", _name, fees.size());
return WithdrawalFeesSet(std::move(fees));
}

MonetaryAmount HuobiPublic::queryWithdrawalFee(CurrencyCode currencyCode) {
Expand Down
34 changes: 18 additions & 16 deletions src/api/exchanges/src/krakenpublicapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ KrakenPublic::KrakenPublic(const CoincenterInfo& config, FiatConverter& fiatConv
log::trace("Updated {} withdrawal fee {} from cache", _name, withdrawFee);
log::trace("Updated {} min withdraw {} from cache", _name, withdrawMin);

withdrawalInfoMaps.first.insert_or_assign(cur, withdrawFee);
withdrawalInfoMaps.first.insert(withdrawFee);
withdrawalInfoMaps.second.insert_or_assign(cur, withdrawMin);
}

Expand Down Expand Up @@ -169,13 +169,14 @@ bool KrakenPublic::healthCheck() {
}

MonetaryAmount KrakenPublic::queryWithdrawalFee(CurrencyCode currencyCode) {
const WithdrawalFeeMap& withdrawalFeeMaps = _withdrawalFeesCache.get().first;
auto foundIt = withdrawalFeeMaps.find(currencyCode);
if (foundIt == withdrawalFeeMaps.end()) {
const WithdrawalFeesSet& withdrawalFees = _withdrawalFeesCache.get().first;
MonetaryAmount emptyAmount(0, currencyCode);
auto foundIt = withdrawalFees.find(emptyAmount);
if (foundIt == withdrawalFees.end()) {
log::warn("Unable to find {} withdrawal fee for {}, consider 0 instead", name(), currencyCode);
return MonetaryAmount(0, currencyCode);
return emptyAmount;
}
return foundIt->second;
return *foundIt;
}

namespace {
Expand Down Expand Up @@ -245,7 +246,7 @@ KrakenPublic::WithdrawalFeesFunc::WithdrawalInfoMaps KrakenPublic::WithdrawalFee
}

log::trace("Updated Kraken withdrawal fee {} from first source", withdrawalFee);
ret.first.insert_or_assign(withdrawalFee.currencyCode(), withdrawalFee);
ret.first.insert(withdrawalFee);

// Locate min withdrawal
searchPos = withdrawalFeesCsv.find(kBeginMinWithdrawalHtmlTag, searchPos) + kBeginMinWithdrawalHtmlTag.size();
Expand Down Expand Up @@ -321,7 +322,7 @@ KrakenPublic::WithdrawalFeesFunc::WithdrawalInfoMaps KrakenPublic::WithdrawalFee
MonetaryAmount withdrawalFee = parseNextFee(searchPos);

log::trace("Updated Kraken withdrawal fee {} from source 2, simulate min withdrawal amount", withdrawalFee);
ret.first.insert_or_assign(withdrawalFee.currencyCode(), withdrawalFee);
ret.first.insert(withdrawalFee);

ret.second.insert_or_assign(withdrawalFee.currencyCode(), 3 * withdrawalFee);
}
Expand All @@ -337,16 +338,16 @@ KrakenPublic::WithdrawalFeesFunc::WithdrawalInfoMaps KrakenPublic::WithdrawalFee
}

KrakenPublic::WithdrawalFeesFunc::WithdrawalInfoMaps KrakenPublic::WithdrawalFeesFunc::operator()() {
auto [withdrawFeeMap1, withdrawMinMap1] = updateFromSource1();
auto [withdrawFeeMap2, withdrawMinMap2] = updateFromSource2();
auto [withdrawFees1, withdrawMinMap1] = updateFromSource1();
auto [withdrawFees2, withdrawMinMap2] = updateFromSource2();

withdrawFeeMap1.merge(std::move(withdrawFeeMap2));
withdrawFees1.insert(withdrawFees2.begin(), withdrawFees2.end());
withdrawMinMap1.merge(std::move(withdrawMinMap2));

if (withdrawFeeMap1.empty() || withdrawMinMap1.empty()) {
if (withdrawFees1.empty() || withdrawMinMap1.empty()) {
throw exception("Unable to parse Kraken withdrawal fees");
}
return std::make_pair(std::move(withdrawFeeMap1), std::move(withdrawMinMap1));
return std::make_pair(std::move(withdrawFees1), std::move(withdrawMinMap1));
}

CurrencyExchangeFlatSet KrakenPublic::TradableCurrenciesFunc::operator()() {
Expand Down Expand Up @@ -555,9 +556,10 @@ void KrakenPublic::updateCacheFile() const {

json data;
data["timeepoch"] = TimestampToS(latestUpdate);
for (const auto& [curCode, withdrawFee] : withdrawalInfoMaps.first) {
string curCodeStr = curCode.str();
data["assets"][curCodeStr]["min"] = withdrawalInfoMaps.second.find(curCode)->second.amountStr();
for (const auto withdrawFee : withdrawalInfoMaps.first) {
string curCodeStr = withdrawFee.currencyCode().str();
data["assets"][curCodeStr]["min"] =
withdrawalInfoMaps.second.find(withdrawFee.currencyCode())->second.amountStr();
data["assets"][curCodeStr]["fee"] = withdrawFee.amountStr();
}
GetKrakenWithdrawInfoFile(_coincenterInfo.dataDir()).write(data);
Expand Down
16 changes: 9 additions & 7 deletions src/api/exchanges/src/kucoinpublicapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,18 @@ std::pair<MarketSet, KucoinPublic::MarketsFunc::MarketInfoMap> KucoinPublic::Mar
return {std::move(markets), std::move(marketInfoMap)};
}

WithdrawalFeeMap KucoinPublic::queryWithdrawalFees() {
WithdrawalFeeMap ret;
for (const TradableCurrenciesFunc::CurrencyInfo& curDetail : _tradableCurrenciesCache.get()) {
ret.insert_or_assign(curDetail.currencyExchange.standardCode(), curDetail.withdrawalMinFee);
WithdrawalFeesSet KucoinPublic::queryWithdrawalFees() {
vector<MonetaryAmount> fees;
const auto& tradableCurrencies = _tradableCurrenciesCache.get();
fees.reserve(tradableCurrencies.size());
for (const TradableCurrenciesFunc::CurrencyInfo& curDetail : tradableCurrencies) {
fees.push_back(curDetail.withdrawalMinFee);
log::trace("Retrieved {} withdrawal fee {}", _name, curDetail.withdrawalMinFee);
}

log::info("Retrieved {} withdrawal fees for {} coins", _name, ret.size());
assert(!ret.empty());
return ret;
log::info("Retrieved {} withdrawal fees for {} coins", _name, fees.size());
assert(!fees.empty());
return WithdrawalFeesSet(std::move(fees));
}

MonetaryAmount KucoinPublic::queryWithdrawalFee(CurrencyCode currencyCode) {
Expand Down
Loading

0 comments on commit 65a864f

Please sign in to comment.