Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
# }

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7

- name: Download Ninja and CMake
id: cmake_and_ninja
Expand Down
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
- [Override exchange urls](#override-exchange-urls)
- [Connect to a proxy](#connect-to-a-proxy)
- [Reduce build time](#reduce-build-time)
- [Exchange Specific Notes](#exchange-specific-notes)
- [Hyperliquid](#hyperliquid)
- [Performance Tuning](#performance-tuning)
- [Known Issues and Workarounds](#known-issues-and-workarounds)

Expand All @@ -57,8 +59,8 @@
* Code closely follows Bloomberg's API: https://www.bloomberg.com/professional/support/api-library/.
* It is ultra fast thanks to very careful optimizations.
* Supported exchanges:
* Market Data: ascendex, [binance](https://accounts.maxweb.academy/register?ref=1116718520), [binance-usds-futures](https://accounts.maxweb.academy/register?ref=1116718520), [binance-coin-futures](https://accounts.maxweb.academy/register?ref=1116718520), bitfinex, bitget, bitget-futures, bitmart, bitmex, bitstamp, [bybit](https://www.bybit.com/invite?ref=XNYP2K), coinbase, [cryptocom](https://crypto.com/exch/tqj4b8x48w), deribit, erisx (Cboe Digital), [gateio](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), [gateio-perpetual-futures](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), gemini, [huobi](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-usdt-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-coin-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), kraken, kraken-futures, kucoin, kucoin-futures, mexc, mexc-futures, [okx](https://www.okx.com/join/47636709), whitebit.
* Execution Management: ascendex, [binance](https://accounts.maxweb.academy/register?ref=1116718520), [binance-usds-futures](https://accounts.maxweb.academy/register?ref=1116718520), [binance-coin-futures](https://accounts.maxweb.academy/register?ref=1116718520), bitfinex, bitget, bitget-futures, bitmart, bitmex, bitstamp, [bybit](https://www.bybit.com/invite?ref=XNYP2K), coinbase, [cryptocom](https://crypto.com/exch/tqj4b8x48w), deribit, erisx (Cboe Digital), [gateio](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), [gateio-perpetual-futures](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), gemini, [huobi](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-usdt-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-coin-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), kraken, kraken-futures, kucoin, kucoin-futures, mexc, [okx](https://www.okx.com/join/47636709).
* Market Data: ascendex, [binance](https://accounts.maxweb.academy/register?ref=1116718520), [binance-usds-futures](https://accounts.maxweb.academy/register?ref=1116718520), [binance-coin-futures](https://accounts.maxweb.academy/register?ref=1116718520), bitfinex, bitget, bitget-futures, bitmart, bitmex, bitstamp, [bybit](https://www.bybit.com/invite?ref=XNYP2K), coinbase, [cryptocom](https://crypto.com/exch/tqj4b8x48w), deribit, erisx (Cboe Digital), [gateio](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), [gateio-perpetual-futures](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), gemini, [huobi](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-usdt-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-coin-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [hyperliquid](https://app.hyperliquid.xyz/), kraken, kraken-futures, kucoin, kucoin-futures, mexc, mexc-futures, [okx](https://www.okx.com/join/47636709), whitebit.
* Execution Management: ascendex, [binance](https://accounts.maxweb.academy/register?ref=1116718520), [binance-usds-futures](https://accounts.maxweb.academy/register?ref=1116718520), [binance-coin-futures](https://accounts.maxweb.academy/register?ref=1116718520), bitfinex, bitget, bitget-futures, bitmart, bitmex, bitstamp, [bybit](https://www.bybit.com/invite?ref=XNYP2K), coinbase, [cryptocom](https://crypto.com/exch/tqj4b8x48w), deribit, erisx (Cboe Digital), [gateio](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), [gateio-perpetual-futures](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), gemini, [huobi](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-usdt-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [huobi-coin-swap](https://www.htx.com/invite/en-us/1f?invite_code=rmw7d223), [hyperliquid](https://app.hyperliquid.xyz/), kraken, kraken-futures, kucoin, kucoin-futures, mexc, [okx](https://www.okx.com/join/47636709).
* FIX: [binance](https://accounts.maxweb.academy/register?ref=1116718520), coinbase, gemini.
* Join us on Discord https://discord.gg/b5EKcp9s8T and Medium https://cryptochassis.medium.com.
* For any questions, email hello@cryptochassis.com.
Expand Down Expand Up @@ -1077,6 +1079,35 @@ Subscription subscription("bybit", "BTCUSDT", "MARKET_DEPTH", "", "", {}, "172.3
#### Reduce build time
The Pimpl (Pointer to Implementation) idiom in C++ can significantly reduce build time. This reduction is achieved by minimizing compilation dependencies and isolating implementation details. See [this example](example/reduce_build_time).

## Exchange Specific Notes
### Hyperliquid
* If you need execution management, secp256k1 and msgpack are needed. For example, a CMakeLists.txt for macOS will look like
```
if(APPLE)
find_path(SECP256K1_INCLUDE_DIR secp256k1.h PATHS /opt/homebrew/include)
find_path(
MSGPACK_INCLUDE_DIR
NAMES msgpack.hpp
PATHS /opt/homebrew/include)

find_library(SECP256K1_LIBRARY secp256k1 PATHS /opt/homebrew/lib)
find_library(MSGPACKC_LIBRARY msgpackc PATHS /opt/homebrew/lib)
endif()

add_compile_definitions(CCAPI_ENABLE_SERVICE_EXECUTION_MANAGEMENT)
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_HYPERLIQUID)
add_executable(${NAME} main.cpp)
add_dependencies(${NAME} boost rapidjson)

target_include_directories(${NAME} PRIVATE ${SECP256K1_INCLUDE_DIR}
${MSGPACK_INCLUDE_DIR})
target_link_libraries(${NAME} PRIVATE ${SECP256K1_LIBRARY} ${MSGPACKC_LIBRARY})
```
* For create order and cancel order, please provide hyperliquid's asset id as instrument (e.g. BTC = 0 on mainnet. See https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/asset-ids). For example,
```
Request request(Request::Operation::CREATE_ORDER, "hyperliquid", "0"); // Corresponds to https://app.hyperliquid.xyz/trade/BTC
```

## Performance Tuning
* Turn on compiler optimization flags (e.g. `cmake -DCMAKE_BUILD_TYPE=Release ...`).
* Enable link time optimization (e.g. in CMakeLists.txt `set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)` before a target is created). Note that link time optimization is only applicable to static linking.
Expand Down
7 changes: 4 additions & 3 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ if(NOT HFFIX_INCLUDE_DIR)
else()
add_library(hffix INTERFACE)
endif()
include_directories(
${CCAPI_PROJECT_DIR}/include ${BOOST_INCLUDE_DIR} ${RAPIDJSON_INCLUDE_DIR}
${HFFIX_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR})

include_directories(${CCAPI_PROJECT_DIR}/include)
include_directories(SYSTEM ${BOOST_INCLUDE_DIR} ${RAPIDJSON_INCLUDE_DIR}
${HFFIX_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR})

find_package(OpenSSL REQUIRED)
set(ADDITIONAL_LINK_LIBRARIES "")
Expand Down
31 changes: 31 additions & 0 deletions include/ccapi_cpp/ccapi_macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@
#define CCAPI_EXCHANGE_NAME_WHITEBIT "whitebit"
#endif

#ifndef CCAPI_EXCHANGE_NAME_HYPERLIQUID
#define CCAPI_EXCHANGE_NAME_HYPERLIQUID "hyperliquid"
#endif

#ifndef CCAPI_LAST_PRICE
#define CCAPI_LAST_PRICE "LAST_PRICE"
#endif
Expand Down Expand Up @@ -487,6 +491,9 @@
#define CCAPI_WEBSOCKET_MEXC_FUTURES_CHANNEL_DEPTH "depth"
#define CCAPI_WEBSOCKET_WHITEBIT_CHANNEL_MARKET_TRADES "trades"
#define CCAPI_WEBSOCKET_WHITEBIT_CHANNEL_MARKET_DEPTH "depth"
#define CCAPI_WEBSOCKET_HYPERLIQUID_CHANNEL_BBO "bbo"
#define CCAPI_WEBSOCKET_HYPERLIQUID_CHANNEL_L2_BOOK "l2Book"
#define CCAPI_WEBSOCKET_HYPERLIQUID_CHANNEL_TRADE "trades"
#ifndef CCAPI_CHANNEL_ID
#define CCAPI_CHANNEL_ID "channelId"
#endif
Expand Down Expand Up @@ -667,6 +674,14 @@
#define CCAPI_EM_POSITION_SIDE "POSITION_SIDE"
#endif

#ifndef CCAPI_EM_POSITION_SIDE_LONG
#define CCAPI_EM_POSITION_SIDE_LONG "POSITION_SIDE_LONG"
#endif

#ifndef CCAPI_EM_POSITION_SIDE_SHORT
#define CCAPI_EM_POSITION_SIDE_SHORT "POSITION_SIDE_SHORT"
#endif

#ifndef CCAPI_EM_POSITION_QUANTITY
#define CCAPI_EM_POSITION_QUANTITY "QUANTITY"
#endif
Expand Down Expand Up @@ -1057,6 +1072,10 @@
#define CCAPI_WHITEBIT_URL_REST_BASE "https://whitebit.com"
#endif

#ifndef CCAPI_HYPERLIQUID_URL_REST_BASE
#define CCAPI_HYPERLIQUID_URL_REST_BASE "https://api.hyperliquid.xyz"
#endif

// end: exchange REST urls

// start: exchange WS urls
Expand Down Expand Up @@ -1252,6 +1271,10 @@
#define CCAPI_WHITEBIT_URL_WS_BASE "wss://api.whitebit.com"
#endif

#ifndef CCAPI_HYPERLIQUID_URL_WS_BASE
#define CCAPI_HYPERLIQUID_URL_WS_BASE "wss://api.hyperliquid.xyz"
#endif

// end: exchange WS urls

// start: exchange FIX urls
Expand Down Expand Up @@ -1641,6 +1664,14 @@
#define CCAPI_MEXC_FUTURES_API_SECRET "MEXC_FUTURES_API_SECRET"
#endif

#ifndef CCAPI_HYPERLIQUID_WALLET_KEY
#define CCAPI_HYPERLIQUID_WALLET_KEY "HYPERLIQUID_WALLET_KEY"
#endif

#ifndef CCAPI_HYPERLIQUID_ACCOUNT_ADDRESS
#define CCAPI_HYPERLIQUID_ACCOUNT_ADDRESS "HYPERLIQUID_ACCOUNT_ADDRESS"
#endif

// end: exchange API credentials

#define CCAPI_HTTP_PORT_DEFAULT "80"
Expand Down
12 changes: 12 additions & 0 deletions include/ccapi_cpp/ccapi_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,18 @@ class Request {
}
nextClientOrderId += std::to_string(lastClientOrderIdUnixTimestampInSeconds);
nextClientOrderId += UtilString::leftPadTo(std::to_string(lastClientOrderIdSequenceNumber), CCAPI_EM_CLIENT_ORDER_ID_SEQUENCE_NUMBER_PAD_TO_LENGTH, '0');

if (this->exchange == CCAPI_EXCHANGE_NAME_HYPERLIQUID) {
int64_t value = std::stoll(nextClientOrderId);
std::stringstream ss;
ss << std::hex << std::nouppercase << value;
std::string hexStr = ss.str();
if (hexStr.length() < 32) {
hexStr = std::string(32 - hexStr.length(), '0') + hexStr;
}
nextClientOrderId = "0x" + hexStr;
}

return nextClientOrderId;
}
#ifndef CCAPI_EXPOSE_INTERNAL
Expand Down
16 changes: 16 additions & 0 deletions include/ccapi_cpp/ccapi_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@
#ifdef CCAPI_ENABLE_EXCHANGE_WHITEBIT
#include "ccapi_cpp/service/ccapi_market_data_service_whitebit.h"
#endif
#ifdef CCAPI_ENABLE_EXCHANGE_HYPERLIQUID
#include "ccapi_cpp/service/ccapi_market_data_service_hyperliquid.h"
#endif
#endif
// end: enable exchanges for market data

Expand Down Expand Up @@ -204,6 +207,9 @@
#ifdef CCAPI_ENABLE_EXCHANGE_WHITEBIT
#include "ccapi_cpp/service/ccapi_execution_management_service_whitebit.h"
#endif
#ifdef CCAPI_ENABLE_EXCHANGE_HYPERLIQUID
#include "ccapi_cpp/service/ccapi_execution_management_service_hyperliquid.h"
#endif
#endif
// end: enable exchanges for execution management

Expand Down Expand Up @@ -303,6 +309,7 @@ class Session {
this->serviceContextPtr->start();
}
this->onEventFunc = std::bind(&Session::onEvent, this, std::placeholders::_1, std::placeholders::_2);

#ifdef CCAPI_ENABLE_SERVICE_MARKET_DATA
#ifdef CCAPI_ENABLE_EXCHANGE_COINBASE
this->serviceByServiceNameExchangeMap[CCAPI_MARKET_DATA][CCAPI_EXCHANGE_NAME_COINBASE] =
Expand Down Expand Up @@ -432,7 +439,12 @@ class Session {
this->serviceByServiceNameExchangeMap[CCAPI_MARKET_DATA][CCAPI_EXCHANGE_NAME_WHITEBIT] =
std::make_shared<MarketDataServiceWhitebit>(this->onEventFunc, sessionOptions, sessionConfigs, this->serviceContextPtr);
#endif
#ifdef CCAPI_ENABLE_EXCHANGE_HYPERLIQUID
this->serviceByServiceNameExchangeMap[CCAPI_MARKET_DATA][CCAPI_EXCHANGE_NAME_HYPERLIQUID] =
std::make_shared<MarketDataServiceHyperliquid>(this->onEventFunc, sessionOptions, sessionConfigs, this->serviceContextPtr);
#endif
#endif

#ifdef CCAPI_ENABLE_SERVICE_EXECUTION_MANAGEMENT
#ifdef CCAPI_ENABLE_EXCHANGE_COINBASE
this->serviceByServiceNameExchangeMap[CCAPI_EXECUTION_MANAGEMENT][CCAPI_EXCHANGE_NAME_COINBASE] =
Expand Down Expand Up @@ -566,6 +578,10 @@ class Session {
// this->serviceByServiceNameExchangeMap[CCAPI_EXECUTION_MANAGEMENT][CCAPI_EXCHANGE_NAME_WHITEBIT] =
// std::make_shared<ExecutionManagementServiceWhitebit>(this->onEventFunc, sessionOptions, sessionConfigs, this->serviceContextPtr);
// #endif
#ifdef CCAPI_ENABLE_EXCHANGE_HYPERLIQUID
this->serviceByServiceNameExchangeMap[CCAPI_EXECUTION_MANAGEMENT][CCAPI_EXCHANGE_NAME_HYPERLIQUID] =
std::make_shared<ExecutionManagementServiceHyperliquid>(this->onEventFunc, sessionOptions, sessionConfigs, this->serviceContextPtr);
#endif
#endif

#ifdef CCAPI_ENABLE_SERVICE_FIX
Expand Down
14 changes: 14 additions & 0 deletions include/ccapi_cpp/ccapi_session_configs.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class SessionConfigs {

void setUrlWebsocketBase(const std::map<std::string, std::string>& urlWebsocketBase) { this->urlWebsocketBase = urlWebsocketBase; }

void setUrlWebsocketOrderEntryBase(const std::map<std::string, std::string>& urlWebsocketOrderEntryBase) {
this->urlWebsocketOrderEntryBase = urlWebsocketOrderEntryBase;
}

void setUrlRestBase(const std::map<std::string, std::string>& urlRestBase) { this->urlRestBase = urlRestBase; }

void setUrlFixBase(const std::map<std::string, std::string>& urlFixBase) { this->urlFixBase = urlFixBase; }
Expand Down Expand Up @@ -200,6 +204,10 @@ class SessionConfigs {
{CCAPI_TRADE, CCAPI_WEBSOCKET_WHITEBIT_CHANNEL_MARKET_TRADES},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_WHITEBIT_CHANNEL_MARKET_DEPTH},
};
std::map<std::string, std::string> fieldWebsocketChannelMapHyperliquid = {
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_HYPERLIQUID_CHANNEL_BBO},
{CCAPI_TRADE, CCAPI_WEBSOCKET_HYPERLIQUID_CHANNEL_TRADE},
};
for (auto const& fieldWebsocketChannel : fieldWebsocketChannelMapCoinbase) {
this->exchangeFieldMap[CCAPI_EXCHANGE_NAME_COINBASE].push_back(fieldWebsocketChannel.first);
}
Expand Down Expand Up @@ -296,6 +304,9 @@ class SessionConfigs {
for (auto const& fieldWebsocketChannel : fieldWebsocketChannelMapWhitebit) {
this->exchangeFieldMap[CCAPI_EXCHANGE_NAME_WHITEBIT].push_back(fieldWebsocketChannel.first);
}
for (auto const& fieldWebsocketChannel : fieldWebsocketChannelMapHyperliquid) {
this->exchangeFieldMap[CCAPI_EXCHANGE_NAME_HYPERLIQUID].push_back(fieldWebsocketChannel.first);
}
for (auto& x : this->exchangeFieldMap) {
x.second.push_back(CCAPI_GENERIC_PUBLIC_SUBSCRIPTION);
}
Expand Down Expand Up @@ -333,6 +344,7 @@ class SessionConfigs {
{CCAPI_EXCHANGE_NAME_MEXC, fieldWebsocketChannelMapMexc},
{CCAPI_EXCHANGE_NAME_MEXC_FUTURES, fieldWebsocketChannelMapMexcFutures},
{CCAPI_EXCHANGE_NAME_WHITEBIT, fieldWebsocketChannelMapWhitebit},
{CCAPI_EXCHANGE_NAME_HYPERLIQUID, fieldWebsocketChannelMapHyperliquid},
};
this->urlWebsocketBase = {
{CCAPI_EXCHANGE_NAME_COINBASE, CCAPI_COINBASE_URL_WS_BASE},
Expand Down Expand Up @@ -370,6 +382,7 @@ class SessionConfigs {
{CCAPI_EXCHANGE_NAME_MEXC, CCAPI_MEXC_URL_WS_BASE},
{CCAPI_EXCHANGE_NAME_MEXC_FUTURES, CCAPI_MEXC_FUTURES_URL_WS_BASE},
{CCAPI_EXCHANGE_NAME_WHITEBIT, CCAPI_WHITEBIT_URL_WS_BASE},
{CCAPI_EXCHANGE_NAME_HYPERLIQUID, CCAPI_HYPERLIQUID_URL_WS_BASE},
};
this->urlWebsocketOrderEntryBase = {
{CCAPI_EXCHANGE_NAME_OKX, CCAPI_OKX_URL_WS_BASE},
Expand Down Expand Up @@ -416,6 +429,7 @@ class SessionConfigs {
{CCAPI_EXCHANGE_NAME_MEXC, CCAPI_MEXC_URL_REST_BASE},
{CCAPI_EXCHANGE_NAME_MEXC_FUTURES, CCAPI_MEXC_FUTURES_URL_REST_BASE},
{CCAPI_EXCHANGE_NAME_WHITEBIT, CCAPI_WHITEBIT_URL_REST_BASE},
{CCAPI_EXCHANGE_NAME_HYPERLIQUID, CCAPI_HYPERLIQUID_URL_REST_BASE},
};
}

Expand Down
17 changes: 17 additions & 0 deletions include/ccapi_cpp/ccapi_util_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,23 @@ namespace ccapi {
*/
class UtilString {
public:
static std::string trimTrailingZeros(const std::string& input) {
std::string s = input;

auto pos = s.find('.');
if (pos == std::string::npos) return s;

while (!s.empty() && s.back() == '0') {
s.pop_back();
}

if (!s.empty() && s.back() == '.') {
s.pop_back();
}

return s;
}

static bool startsWith(const std::string& str, const std::string& prefix) {
return str.size() >= prefix.size() && std::memcmp(str.data(), prefix.data(), prefix.size()) == 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
message.setElementList(elementList);
message.setCorrelationIdList({requestCorrelationId});
}
this->requestCorrelationIdByWsRequestIdByConnectionIdMap.at(wsConnectionPtr->id).erase(wsRequestId);
}
messageList.emplace_back(std::move(message));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ class ExecutionManagementServiceBybit : public ExecutionManagementService {
message.setCorrelationIdList({requestCorrelationId});
messageList.emplace_back(std::move(message));
}
this->requestCorrelationIdByWsRequestIdByConnectionIdMap.at(wsConnectionPtr->id).erase(wsRequestId);
}
}
} else {
Expand Down
Loading
Loading