Skip to content

Commit fabe83e

Browse files
Merge pull request #525 from crypto-chassis/develop
Release
2 parents 5fbbc0b + 1559da7 commit fabe83e

10 files changed

Lines changed: 185 additions & 80 deletions

include/ccapi_cpp/ccapi_element.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,30 @@ class Element {
3939
}
4040
}
4141

42+
// Template insert: accept any string-like value
43+
template <typename S>
44+
void insert_or_assign(std::string_view name, S&& value) {
45+
// Construct std::string only if necessary
46+
if constexpr (std::is_same_v<std::decay_t<S>, std::string>) {
47+
// If value is std::string, move it in to avoid copy
48+
nameValueMap.insert_or_assign(name, std::forward<S>(value));
49+
} else {
50+
// Otherwise, construct std::string from value (string_view, const char*)
51+
nameValueMap.insert_or_assign(name, std::string(std::forward<S>(value)));
52+
}
53+
}
54+
55+
template <typename S>
56+
void insert_or_assign(int tag, S&& value) {
57+
if constexpr (std::is_same_v<std::decay_t<S>, std::string>) {
58+
// If already std::string, move to avoid copy
59+
tagValueMap.insert_or_assign(tag, std::forward<S>(value));
60+
} else {
61+
// Otherwise, construct std::string from value (string_view, literal, etc.)
62+
tagValueMap.insert_or_assign(tag, std::string(std::forward<S>(value)));
63+
}
64+
}
65+
4266
// void emplace(std::string& name, std::string& value) { this->nameValueMap.emplace(std::move(name), std::move(value)); }
4367

4468
// void emplace(int tag, std::string& value) { this->tagValueMap.emplace(std::move(tag), std::move(value)); }

include/ccapi_cpp/ccapi_http_connection.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,12 @@ class HttpConnection {
2828

2929
void clearBuffer() { this->buffer.consume(this->buffer.size()); }
3030

31-
void resetResponseParser() {
32-
this->resParserOpt.emplace();
33-
this->resParserOpt->body_limit(CCAPI_HTTP_RESPONSE_PARSER_BODY_LIMIT);
34-
}
35-
36-
void prepareReadNextResponse() {
37-
this->clearBuffer();
38-
this->resetResponseParser();
39-
}
40-
4131
std::string host;
4232
std::string port;
4333
std::shared_ptr<beast::ssl_stream<beast::tcp_stream>> streamPtr;
4434
TimePoint lastReceiveDataTp{std::chrono::seconds{0}};
4535

4636
boost::beast::flat_buffer buffer;
47-
std::optional<boost::beast::http::response_parser<boost::beast::http::string_body>> resParserOpt;
4837
};
4938

5039
} /* namespace ccapi */

include/ccapi_cpp/ccapi_http_retry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class HttpRetry {
1818
std::ostringstream oss;
1919
oss << promisePtr;
2020
std::string output =
21-
"HttpConnection [numRetry = " + ccapi::toString(numRetry) + ", numRedirect = " + ccapi::toString(numRedirect) + ", promisePtr = " + oss.str() + "]";
21+
"HttpRetry [numRetry = " + ccapi::toString(numRetry) + ", numRedirect = " + ccapi::toString(numRedirect) + ", promisePtr = " + oss.str() + "]";
2222
return output;
2323
}
2424

include/ccapi_cpp/ccapi_request.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace ccapi {
2828
class Request {
2929
public:
3030
enum class Operation {
31+
UNKNOWN = 0,
3132
CUSTOM = CCAPI_REQUEST_OPERATION_TYPE_CUSTOM,
3233
GENERIC_PUBLIC_REQUEST = CCAPI_REQUEST_OPERATION_TYPE_GENERIC_PUBLIC_REQUEST,
3334
GENERIC_PRIVATE_REQUEST = CCAPI_REQUEST_OPERATION_TYPE_GENERIC_PRIVATE_REQUEST,
@@ -60,6 +61,9 @@ class Request {
6061
case Operation::CUSTOM:
6162
output = "CUSTOM";
6263
break;
64+
case Operation::UNKNOWN:
65+
output = "UNKNOWN";
66+
break;
6367
case Operation::GENERIC_PUBLIC_REQUEST:
6468
output = "GENERIC_PUBLIC_REQUEST";
6569
break;
@@ -130,15 +134,15 @@ class Request {
130134
output = "GET_ACCOUNT_POSITIONS";
131135
break;
132136
default:
133-
CCAPI_LOGGER_FATAL(CCAPI_UNSUPPORTED_VALUE);
137+
CCAPI_LOGGER_FATAL(std::string(CCAPI_UNSUPPORTED_VALUE) + " " + std::to_string(static_cast<int>(operation)));
134138
}
135139
return output;
136140
}
137141

138142
Request() {}
139143

140-
Request(Operation operation, const std::string& exchange, const std::string& instrument = "", const std::string& correlationId = "",
141-
const std::map<std::string, std::string>& credential = {})
144+
explicit Request(Operation operation, const std::string& exchange = "", const std::string& instrument = "", const std::string& correlationId = "",
145+
const std::map<std::string, std::string>& credential = {})
142146
: operation(operation), exchange(exchange), instrument(instrument), correlationId(correlationId), credential(credential) {
143147
if (operation == Operation::CUSTOM) {
144148
this->serviceName = CCAPI_UNKNOWN;
@@ -228,6 +232,10 @@ class Request {
228232

229233
const std::string& getPort() const { return port; }
230234

235+
void setExchange(const std::string& exchange) { this->exchange = exchange; }
236+
237+
void setInstrument(const std::string& instrument) { this->instrument = instrument; }
238+
231239
void setIndex(int index) { this->index = index; }
232240

233241
void setCredential(const std::map<std::string, std::string>& credential) { this->credential = credential; }
@@ -263,7 +271,7 @@ class Request {
263271

264272
private:
265273
#endif
266-
Operation operation;
274+
Operation operation{Operation::UNKNOWN};
267275
std::string exchange;
268276
std::string marginType;
269277
std::string instrument;

include/ccapi_cpp/ccapi_session.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ class Session {
286286

287287
virtual ~Session() {
288288
CCAPI_LOGGER_FUNCTION_ENTER;
289+
this->delayTimerByIdMap.clear();
290+
this->serviceByServiceNameExchangeMap.clear();
289291
if (this->useInternalServiceContextPtr) {
290292
delete this->serviceContextPtr;
291293
}
@@ -597,6 +599,9 @@ class Session {
597599

598600
virtual void stop() {
599601
boost::asio::post(*this->serviceContextPtr->ioContextPtr, [this]() {
602+
for (const auto& [_, delayTimer] : this->delayTimerByIdMap) {
603+
delayTimer->cancel();
604+
}
600605
for (const auto& x : this->serviceByServiceNameExchangeMap) {
601606
for (const auto& y : x.second) {
602607
y.second->stop();
@@ -655,7 +660,7 @@ class Session {
655660
auto subscriptionList = x.second;
656661
if (this->serviceByServiceNameExchangeMap.find(serviceName) == this->serviceByServiceNameExchangeMap.end()) {
657662
this->onError(Event::Type::SUBSCRIPTION_STATUS, Message::Type::SUBSCRIPTION_FAILURE,
658-
"please enable service: " + serviceName + ", and the exchanges that you want");
663+
"please enable service: " + serviceName + ", and the exchanges that you want for subscriptionList " + toString(subscriptionList));
659664
return;
660665
}
661666
if (serviceName == CCAPI_MARKET_DATA) {
@@ -722,7 +727,8 @@ class Session {
722727
auto serviceName = subscription.getServiceName();
723728
CCAPI_LOGGER_DEBUG("serviceName = " + serviceName);
724729
if (this->serviceByServiceNameExchangeMap.find(serviceName) == this->serviceByServiceNameExchangeMap.end()) {
725-
this->onError(Event::Type::FIX_STATUS, Message::Type::FIX_FAILURE, "please enable service: " + serviceName + ", and the exchanges that you want");
730+
this->onError(Event::Type::FIX_STATUS, Message::Type::FIX_FAILURE,
731+
"please enable service: " + serviceName + ", and the exchanges that you want for subscription " + toString(subscription));
726732
return;
727733
}
728734
auto exchange = subscription.getExchange();
@@ -776,7 +782,8 @@ class Session {
776782
auto serviceName = request.getServiceName();
777783
CCAPI_LOGGER_DEBUG("serviceName = " + serviceName);
778784
if (this->serviceByServiceNameExchangeMap.find(serviceName) == this->serviceByServiceNameExchangeMap.end()) {
779-
this->onError(Event::Type::FIX_STATUS, Message::Type::FIX_FAILURE, "please enable service: " + serviceName + ", and the exchanges that you want");
785+
this->onError(Event::Type::FIX_STATUS, Message::Type::FIX_FAILURE,
786+
"please enable service: " + serviceName + ", and the exchanges that you want for request " + toString(request));
780787
return;
781788
}
782789
std::map<std::string, std::shared_ptr<Service>>& serviceByExchangeMap = this->serviceByServiceNameExchangeMap.at(serviceName);
@@ -802,7 +809,9 @@ class Session {
802809
const auto& serviceName = request.getServiceName();
803810
CCAPI_LOGGER_DEBUG("serviceName = " + serviceName);
804811
if (this->serviceByServiceNameExchangeMap.find(serviceName) == this->serviceByServiceNameExchangeMap.end()) {
805-
this->onError(Event::Type::REQUEST_STATUS, Message::Type::REQUEST_FAILURE, "please enable service: " + serviceName + ", and the exchanges that you want");
812+
this->onError(Event::Type::REQUEST_STATUS, Message::Type::REQUEST_FAILURE,
813+
"please enable service: " + serviceName + ", and the exchanges that you want for websocketOrderEntrySubscriptionCorrelationId " +
814+
toString(websocketOrderEntrySubscriptionCorrelationId) + ", request = " + toString(request));
806815
return;
807816
}
808817
const std::map<std::string, std::shared_ptr<Service>>& serviceByExchangeMap = this->serviceByServiceNameExchangeMap.at(serviceName);
@@ -841,7 +850,7 @@ class Session {
841850
CCAPI_LOGGER_DEBUG("serviceName = " + serviceName);
842851
if (this->serviceByServiceNameExchangeMap.find(serviceName) == this->serviceByServiceNameExchangeMap.end()) {
843852
this->onError(Event::Type::REQUEST_STATUS, Message::Type::REQUEST_FAILURE,
844-
"please enable service: " + serviceName + ", and the exchanges that you want", eventQueuePtr);
853+
"please enable service: " + serviceName + ", and the exchanges that you want for request " + toString(request), eventQueuePtr);
845854
return;
846855
}
847856
std::map<std::string, std::shared_ptr<Service>>& serviceByExchangeMap = this->serviceByServiceNameExchangeMap.at(serviceName);
@@ -902,8 +911,7 @@ class Session {
902911
virtual void setTimer(const std::string& id, long delayMilliseconds, std::function<void(const boost::system::error_code&)> errorHandler,
903912
std::function<void()> successHandler) {
904913
boost::asio::post(*this->serviceContextPtr->ioContextPtr, [this, id, delayMilliseconds, errorHandler, successHandler]() {
905-
std::shared_ptr<boost::asio::steady_timer> timerPtr(
906-
new boost::asio::steady_timer(*this->serviceContextPtr->ioContextPtr, boost::asio::chrono::milliseconds(delayMilliseconds)));
914+
auto timerPtr = std::make_shared<boost::asio::steady_timer>(*this->serviceContextPtr->ioContextPtr, boost::asio::chrono::milliseconds(delayMilliseconds));
907915
timerPtr->async_wait([this, id, errorHandler, successHandler](const boost::system::error_code& ec) {
908916
if (this->eventHandler) {
909917
if (!this->eventDispatcher) {

include/ccapi_cpp/ccapi_subscription.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class Subscription {
159159
output = "UNSUBSCRIBED";
160160
break;
161161
default:
162-
CCAPI_LOGGER_FATAL(CCAPI_UNSUPPORTED_VALUE);
162+
CCAPI_LOGGER_FATAL(std::string(CCAPI_UNSUPPORTED_VALUE) + " " + std::to_string(static_cast<int>(status)));
163163
}
164164
return output;
165165
}

include/ccapi_cpp/ccapi_util_private.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,18 +1142,21 @@ class Decimal {
11421142
return *this;
11431143
}
11441144

1145-
#ifndef CCAPI_EXPOSE_INTERNAL
1146-
1147-
private:
1148-
#endif
11491145
Decimal negate() const {
11501146
Decimal o;
1147+
o.sign = !this->sign;
11511148
o.before = this->before;
11521149
o.frac = this->frac;
1153-
o.sign = !this->sign;
11541150
return o;
11551151
}
11561152

1153+
Decimal abs() const {
1154+
if (!this->sign) { // if the input is negative
1155+
return -*this; // negate it
1156+
}
1157+
return *this; // already positive
1158+
}
1159+
11571160
Decimal add(const Decimal& x) const {
11581161
/* ---------------- Same-sign fast path ---------------- */
11591162
if (this->sign && x.sign) {
@@ -1337,7 +1340,10 @@ class Decimal {
13371340

13381341
return result;
13391342
}
1343+
#ifndef CCAPI_EXPOSE_INTERNAL
13401344

1345+
private:
1346+
#endif
13411347
// false means negative sign needed
13421348
bool sign{true};
13431349
// {-}bbbb.aaaa
@@ -1381,6 +1387,10 @@ inline std::string ConvertDecimalToString(const Decimal& input, bool normalize =
13811387
return input.toString();
13821388
}
13831389

1390+
inline Decimal ConvertDecimalToAbs(const Decimal& input) { return input.abs(); }
1391+
1392+
inline double ConvertDecimalToDouble(const Decimal& input) { return input.toDouble(); }
1393+
13841394
inline std::string size_tToString(const size_t& t) {
13851395
std::stringstream ss;
13861396
ss << t;

include/ccapi_cpp/service/ccapi_execution_management_service_binance_base.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,14 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
529529
element.insert(CCAPI_EM_ORDER_SIDE, std::string_view(data["S"].GetString()) == "BUY" ? CCAPI_EM_ORDER_SIDE_BUY : CCAPI_EM_ORDER_SIDE_SELL);
530530
element.insert(CCAPI_IS_MAKER, data["m"].GetBool() ? "1" : "0");
531531
element.insert(CCAPI_EM_ORDER_ID, data["i"].GetString());
532-
element.insert(CCAPI_EM_CLIENT_ORDER_ID, data["c"].GetString());
532+
{
533+
auto it = data.FindMember("C");
534+
if (it != data.MemberEnd() && !it->value.IsNull() && it->value.GetStringLength()) {
535+
element.insert(CCAPI_EM_CLIENT_ORDER_ID, std::string(it->value.GetString()));
536+
} else {
537+
element.insert(CCAPI_EM_CLIENT_ORDER_ID, data["c"].GetString());
538+
}
539+
}
533540
element.insert(CCAPI_EM_ORDER_INSTRUMENT, instrument);
534541
{
535542
auto it = data.FindMember("n");
@@ -555,7 +562,7 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
555562
message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_ORDER_UPDATE);
556563
const std::map<std::string_view, std::pair<std::string_view, JsonDataType>>& extractionFieldNameMap = {
557564
{CCAPI_EM_ORDER_ID, std::make_pair("i", JsonDataType::INTEGER)},
558-
{CCAPI_EM_CLIENT_ORDER_ID, std::make_pair("c", JsonDataType::STRING)},
565+
{CCAPI_EM_CLIENT_ORDER_ID, std::make_pair("C", JsonDataType::STRING)},
559566
{CCAPI_EM_ORDER_SIDE, std::make_pair("S", JsonDataType::STRING)},
560567
{CCAPI_EM_ORDER_LIMIT_PRICE, std::make_pair("p", JsonDataType::STRING)},
561568
{CCAPI_EM_ORDER_QUANTITY, std::make_pair("q", JsonDataType::STRING)},
@@ -566,10 +573,10 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
566573
};
567574
Element info;
568575
this->extractOrderInfo(info, data, extractionFieldNameMap);
569-
{
570-
auto it = data.FindMember("C");
576+
if (info.getValue(CCAPI_EM_CLIENT_ORDER_ID).empty()) {
577+
auto it = data.FindMember("c");
571578
if (it != data.MemberEnd() && !it->value.IsNull() && it->value.GetStringLength()) {
572-
info.insert(CCAPI_EM_ORIGINAL_CLIENT_ORDER_ID, std::string(it->value.GetString()));
579+
info.insert_or_assign(CCAPI_EM_CLIENT_ORDER_ID, std::string(it->value.GetString()));
573580
}
574581
}
575582
{
@@ -723,7 +730,7 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
723730
{CCAPI_EM_ORDER_STATUS, std::make_pair("status", JsonDataType::STRING)},
724731
{CCAPI_EM_ORDER_INSTRUMENT, std::make_pair("symbol", JsonDataType::STRING)},
725732
{CCAPI_LAST_UPDATED_TIME_SECONDS, std::make_pair(this->isDerivatives ? "updateTime" : "transactTime", JsonDataType::STRING)},
726-
{CCAPI_EM_CLIENT_ORDER_ID, std::make_pair("clientOrderId", JsonDataType::STRING)},
733+
{CCAPI_EM_CLIENT_ORDER_ID, std::make_pair("origClientOrderId", JsonDataType::STRING)},
727734
};
728735

729736
Element element;

0 commit comments

Comments
 (0)