Skip to content

Commit

Permalink
Currency is now optional for withdraw-fee CLI, renamed into withdraw-…
Browse files Browse the repository at this point in the history
…fees
  • Loading branch information
sjanel committed Dec 3, 2023
1 parent dfe9714 commit cdad878
Show file tree
Hide file tree
Showing 51 changed files with 343 additions and 200 deletions.
40 changes: 32 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Main features:
- Traded volume
- Last price
- Last trades
- Withdraw fees

**Private requests**

Expand Down Expand Up @@ -75,6 +76,9 @@ Main features:
- [Last price](#last-price)
- [Last trades](#last-trades)
- [Conversion path](#conversion-path)
- [Withdraw fees](#withdraw-fees)
- [Example 1: query all withdraw fees](#example-1-query-all-withdraw-fees)
- [Example 2: query ETH withdraw fees on Kraken and Kucoin](#example-2-query-eth-withdraw-fees-on-kraken-and-kucoin)
- [Private requests](#private-requests)
- [Selecting private keys on exchanges](#selecting-private-keys-on-exchanges)
- [Balance](#balance)
Expand Down Expand Up @@ -195,13 +199,14 @@ coincenter balance orderbook XRP-USDT,binance --cur EUR

Some commands' input can be deduced from previous commands' output, a bit like piping commands in Linux works.
Input commands accepting previous commands' output are:

- Withdraw
- Trade
- Sell

For example:

```
```bash
1st command 3rd command
/ \ / \
coincenter buy 1500XLM,binance withdraw kraken sell
Expand Down Expand Up @@ -255,13 +260,13 @@ It is the first thing that is checked in exchanges unit tests, hence if the heal

List all currencies for all supported exchanges

```
```bash
coincenter currencies
```

List all currencies for kucoin and upbit

```
```bash
coincenter currencies kucoin,upbit
```

Expand Down Expand Up @@ -318,7 +323,7 @@ In addition, for convenience, you can also specify a currency in which to conver

Example: Print ADA (Cardano) - USDT market order book with a depth of 20 on Kraken and Binance

```
```bash
coincenter orderbook ada-usdt,kraken,binance --depth 20
```

Expand All @@ -328,7 +333,7 @@ Fast query last 24h traded volume with `volume-day` option on one market on one,

Example: Print last 24h traded volume on market XLM-BTC for all exchanges supporting it

```
```bash
coincenter volume-day xlm-btc
```

Expand All @@ -338,7 +343,7 @@ Fast query last traded price with `price` option on one market on one, several o

Example: Print last price on market SOL-BTC for all exchanges supporting it

```
```bash
coincenter price sol-btc
```

Expand All @@ -349,7 +354,7 @@ You can specify the number of last trades to query (for exchanges supporting thi

Example: Print the last 15 trades on DOT-USDT on Binance and Huobi

```
```bash
coincenter last-trades dot-usdt,binance,huobi --n 15
```

Expand All @@ -363,12 +368,31 @@ Option `conversion` is used internally for [multi trade](#multi-trade) but is pr

Example: Print the fastest conversion path from Shiba Inu to Solana on all exchanges where such conversion is possible

```
```bash
coincenter conversion shib-sol
```

**Note**: when several conversion paths of same length are possible, it will favor the ones not involving fiat currencies.

### Withdraw fees

Some exchanges provide a withdraw fees endpoint. Some propose it without an API Key, other require an API Key. `coincenter` uses other sources of data (although less reliable) for exchanges which do not propose withdraw fees.

You can query all withdraw fees at once, for all exchanges or provided ones. You can also specify a currency to filter fees only for this currency.

#### Example 1: query all withdraw fees

```bash
coincenter withdraw-fees
```

#### Example 2: query ETH withdraw fees on Kraken and Kucoin

```bash
coincenter withdraw-fees eth,kraken,kucoin
```


## Private requests

These requests will require that you have your secret keys in `data/secret/secret.json` file, for each exchange used.
Expand Down
2 changes: 0 additions & 2 deletions src/api-objects/include/exchangepublicapitypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@
#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 WithdrawalFeesSet = MonetaryAmountByCurrencySet;
using LastTradesVector = vector<PublicTrade>;
} // namespace cct
10 changes: 6 additions & 4 deletions src/api-objects/include/tradeinfo.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#pragma once

#include "cct_string.hpp"
#include <cstdint>

#include "cct_type_traits.hpp"
#include "market.hpp"
#include "monetaryamount.hpp"
#include "orderid.hpp"
#include "tradedamounts.hpp"
#include "tradedefinitions.hpp"
#include "tradeoptions.hpp"

namespace cct::api {
Expand All @@ -28,7 +30,7 @@ struct TradeInfo {
};

struct OrderInfo {
bool operator==(const OrderInfo &) const = default;
bool operator==(const OrderInfo &) const noexcept = default;

TradedAmounts tradedAmounts;
bool isClosed = false;
Expand All @@ -41,7 +43,7 @@ struct PlaceOrderInfo {
TradedAmounts &tradedAmounts() { return orderInfo.tradedAmounts; }
const TradedAmounts &tradedAmounts() const { return orderInfo.tradedAmounts; }

bool operator==(const PlaceOrderInfo &) const = default;
bool operator==(const PlaceOrderInfo &) const noexcept = default;

using trivially_relocatable = is_trivially_relocatable<OrderId>::type;

Expand Down
8 changes: 3 additions & 5 deletions src/api/common/include/exchangeprivateapi.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#pragma once

#include <chrono>
#include <span>
#include <utility>

#include "apikey.hpp"
#include "balanceoptions.hpp"
#include "balanceportfolio.hpp"
#include "cachedresultvault.hpp"
#include "curlhandle.hpp"
#include "currencycode.hpp"
#include "currencyexchangeflatset.hpp"
#include "depositsconstraints.hpp"
Expand All @@ -19,7 +17,7 @@
#include "exchangepublicapitypes.hpp"
#include "market.hpp"
#include "monetaryamount.hpp"
#include "order.hpp"
#include "monetaryamountbycurrencyset.hpp"
#include "orderid.hpp"
#include "ordersconstraints.hpp"
#include "tradedamounts.hpp"
Expand Down Expand Up @@ -105,11 +103,11 @@ 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 WithdrawalFeesSet queryWithdrawalFees() { return _exchangePublic.queryWithdrawalFees(); }
virtual MonetaryAmountByCurrencySet 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.
virtual MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) {
virtual std::optional<MonetaryAmount> queryWithdrawalFee(CurrencyCode currencyCode) {
return _exchangePublic.queryWithdrawalFee(currencyCode);
}

Expand Down
10 changes: 7 additions & 3 deletions src/api/common/include/exchangepublicapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#include "market.hpp"
#include "marketorderbook.hpp"
#include "monetaryamount.hpp"
#include "monetaryamountbycurrencyset.hpp"
#include "priceoptions.hpp"
#include "tradedefinitions.hpp"

namespace cct {

Expand Down Expand Up @@ -70,10 +70,10 @@ 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 WithdrawalFeesSet queryWithdrawalFees() = 0;
virtual MonetaryAmountByCurrencySet queryWithdrawalFees() = 0;

/// Retrieve the withdrawal fee of a Currency only
virtual MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) = 0;
virtual std::optional<MonetaryAmount> queryWithdrawalFee(CurrencyCode currencyCode) = 0;

/// Return true if exchange supports official REST API has an endpoint to get withdrawal fees
/// For instance, Kraken does not offer such endpoint, we nee to query external sources which may provide inaccurate
Expand Down Expand Up @@ -162,6 +162,10 @@ class ExchangePublic : public ExchangeBase {

CommonAPI &commonAPI() { return _commonApi; }

/// Query withdrawal fee for given currency code.
/// If no data found, return a 0 MonetaryAmount on given currency.
MonetaryAmount queryWithdrawalFeeOrZero(CurrencyCode currencyCode);

protected:
friend class ExchangePrivate;

Expand Down
7 changes: 5 additions & 2 deletions src/api/common/include/exchangepublicapi_mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

#include <gmock/gmock.h>

#include <optional>

#include "commonapi.hpp"
#include "exchangepublicapi.hpp"
#include "exchangepublicapitypes.hpp"
#include "fiatconverter.hpp"
#include "monetaryamount.hpp"

namespace cct::api {
class MockExchangePublic : public ExchangePublic {
Expand All @@ -19,8 +22,8 @@ class MockExchangePublic : public ExchangePublic {
MOCK_METHOD(CurrencyExchange, convertStdCurrencyToCurrencyExchange, (CurrencyCode currencyCode), (override));
MOCK_METHOD(MarketSet, queryTradableMarkets, (), (override));
MOCK_METHOD(MarketPriceMap, queryAllPrices, (), (override));
MOCK_METHOD(WithdrawalFeesSet, queryWithdrawalFees, (), (override));
MOCK_METHOD(MonetaryAmount, queryWithdrawalFee, (CurrencyCode currencyCode), (override));
MOCK_METHOD(MonetaryAmountByCurrencySet, queryWithdrawalFees, (), (override));
MOCK_METHOD(std::optional<MonetaryAmount>, queryWithdrawalFee, (CurrencyCode currencyCode), (override));
MOCK_METHOD(bool, isWithdrawalFeesSourceReliable, (), (const override));
MOCK_METHOD(MarketOrderBookMap, queryAllApproximatedOrderBooks, (int depth), (override));
MOCK_METHOD(MarketOrderBook, queryOrderBook, (Market mk, int depth), (override));
Expand Down
12 changes: 12 additions & 0 deletions src/api/common/src/exchangepublicapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,4 +325,16 @@ Market ExchangePublic::determineMarketFromFilterCurrencies(MarketSet &markets, C
return ret;
}

MonetaryAmount ExchangePublic::queryWithdrawalFeeOrZero(CurrencyCode currencyCode) {
std::optional<MonetaryAmount> optWithdrawFee = queryWithdrawalFee(currencyCode);
MonetaryAmount withdrawFee;
if (optWithdrawFee) {
withdrawFee = *optWithdrawFee;
} else {
log::error("Unable to retrieve withdraw fee for {} on {}, consider 0", currencyCode, name());
withdrawFee = MonetaryAmount(0, currencyCode);
}
return withdrawFee;
}

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

#include <optional>
#include <type_traits>

#include "apikey.hpp"
#include "balanceoptions.hpp"
#include "balanceportfolio.hpp"
#include "cachedresult.hpp"
Expand All @@ -13,7 +13,6 @@
#include "depositsconstraints.hpp"
#include "exchangeprivateapi.hpp"
#include "exchangeprivateapitypes.hpp"
#include "exchangepublicapitypes.hpp"
#include "httprequesttype.hpp"
#include "monetaryamount.hpp"
#include "ordersconstraints.hpp"
Expand All @@ -30,6 +29,7 @@ class ExchangeInfo;
class FiatConverter;

namespace api {
class APIKey;
class BinancePublic;

class BinancePrivate : public ExchangePrivate {
Expand All @@ -54,9 +54,11 @@ class BinancePrivate : public ExchangePrivate {

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

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

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override { return _withdrawFeesCache.get(currencyCode); }
std::optional<MonetaryAmount> queryWithdrawalFee(CurrencyCode currencyCode) override {
return _withdrawFeesCache.get(currencyCode);
}

protected:
bool isSimulatedOrderSupported() const override { return true; }
Expand Down Expand Up @@ -111,14 +113,14 @@ class BinancePrivate : public ExchangePrivate {
Duration& queryDelay)
: BinanceContext(curlHandle, apiKey, exchangePublic, queryDelay) {}

WithdrawalFeesSet operator()();
MonetaryAmountByCurrencySet operator()();
};

struct WithdrawFeesFunc : public BinanceContext {
WithdrawFeesFunc(CurlHandle& curlHandle, const APIKey& apiKey, BinancePublic& exchangePublic, Duration& queryDelay)
: BinanceContext(curlHandle, apiKey, exchangePublic, queryDelay) {}

MonetaryAmount operator()(CurrencyCode currencyCode);
std::optional<MonetaryAmount> operator()(CurrencyCode currencyCode);
};

CurlHandle _curlHandle;
Expand Down
5 changes: 3 additions & 2 deletions src/api/exchanges/include/binancepublicapi.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <optional>
#include <string_view>
#include <unordered_map>

Expand Down Expand Up @@ -46,9 +47,9 @@ class BinancePublic : public ExchangePublic {

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

WithdrawalFeesSet queryWithdrawalFees() override;
MonetaryAmountByCurrencySet queryWithdrawalFees() override;

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;
std::optional<MonetaryAmount> queryWithdrawalFee(CurrencyCode currencyCode) override;

bool isWithdrawalFeesSourceReliable() const override { return true; }

Expand Down
2 changes: 1 addition & 1 deletion src/api/exchanges/include/bithumbprivateapi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace cct {
class CoincenterInfo;

namespace api {

class APIKey;
class BithumbPublic;

class BithumbPrivate : public ExchangePrivate {
Expand Down
7 changes: 4 additions & 3 deletions src/api/exchanges/include/bithumbpublicapi.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <optional>
#include <string_view>

#include "cachedresult.hpp"
Expand Down Expand Up @@ -34,9 +35,9 @@ class BithumbPublic : public ExchangePublic {

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

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

MonetaryAmount queryWithdrawalFee(CurrencyCode currencyCode) override;
std::optional<MonetaryAmount> queryWithdrawalFee(CurrencyCode currencyCode) override;

bool isWithdrawalFeesSourceReliable() const override { return true; }

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

WithdrawalFeesSet operator()();
MonetaryAmountByCurrencySet operator()();

CurlHandle _curlHandle;
};
Expand Down
Loading

0 comments on commit cdad878

Please sign in to comment.