ccxt 4.1.30 → 4.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +186 -0
- package/README.md +3 -3
- package/dist/ccxt.browser.js +428 -174
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/ascendex.js +89 -12
- package/dist/cjs/src/base/Exchange.js +6 -0
- package/dist/cjs/src/bitget.js +43 -27
- package/dist/cjs/src/bitvavo.js +43 -7
- package/dist/cjs/src/bybit.js +0 -3
- package/dist/cjs/src/coinex.js +2 -1
- package/dist/cjs/src/gemini.js +1 -2
- package/dist/cjs/src/hitbtc.js +32 -22
- package/dist/cjs/src/huobi.js +18 -12
- package/dist/cjs/src/krakenfutures.js +1 -0
- package/dist/cjs/src/mexc.js +2 -6
- package/dist/cjs/src/okx.js +1 -0
- package/dist/cjs/src/phemex.js +8 -6
- package/dist/cjs/src/pro/bittrex.js +68 -2
- package/dist/cjs/src/pro/huobi.js +76 -32
- package/dist/cjs/src/woo.js +27 -31
- package/js/ccxt.d.ts +3 -3
- package/js/ccxt.js +1 -1
- package/js/src/ascendex.d.ts +11 -1
- package/js/src/ascendex.js +89 -12
- package/js/src/base/Exchange.d.ts +5 -3
- package/js/src/base/Exchange.js +6 -0
- package/js/src/base/types.d.ts +9 -0
- package/js/src/binance.d.ts +1 -1
- package/js/src/bitget.d.ts +3 -3
- package/js/src/bitget.js +43 -27
- package/js/src/bitvavo.d.ts +13 -13
- package/js/src/bitvavo.js +43 -7
- package/js/src/bybit.js +0 -3
- package/js/src/coinex.d.ts +2 -2
- package/js/src/coinex.js +2 -1
- package/js/src/gate.d.ts +3 -3
- package/js/src/gemini.js +1 -2
- package/js/src/hitbtc.js +33 -23
- package/js/src/huobi.d.ts +1 -1
- package/js/src/huobi.js +18 -12
- package/js/src/krakenfutures.js +1 -0
- package/js/src/kucoinfutures.d.ts +2 -2
- package/js/src/mexc.d.ts +2 -2
- package/js/src/mexc.js +2 -6
- package/js/src/okx.d.ts +2 -2
- package/js/src/okx.js +1 -0
- package/js/src/phemex.d.ts +2 -2
- package/js/src/phemex.js +8 -6
- package/js/src/poloniexfutures.d.ts +2 -2
- package/js/src/pro/bittrex.d.ts +1 -0
- package/js/src/pro/bittrex.js +69 -3
- package/js/src/pro/huobi.js +76 -32
- package/js/src/woo.d.ts +1 -1
- package/js/src/woo.js +27 -31
- package/package.json +2 -2
package/dist/cjs/src/hitbtc.js
CHANGED
|
@@ -33,6 +33,7 @@ class hitbtc extends hitbtc$1 {
|
|
|
33
33
|
'cancelOrder': true,
|
|
34
34
|
'createDepositAddress': true,
|
|
35
35
|
'createOrder': true,
|
|
36
|
+
'createPostOnlyOrder': true,
|
|
36
37
|
'createReduceOnlyOrder': true,
|
|
37
38
|
'createStopLimitOrder': true,
|
|
38
39
|
'createStopMarketOrder': true,
|
|
@@ -2047,14 +2048,24 @@ class hitbtc extends hitbtc$1 {
|
|
|
2047
2048
|
* @param {float} amount how much of currency you want to trade in units of base currency
|
|
2048
2049
|
* @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
2049
2050
|
* @param {object} [params] extra parameters specific to the hitbtc api endpoint
|
|
2050
|
-
* @param {string} [params.marginMode] 'cross' or 'isolated' only 'isolated' is supported
|
|
2051
|
+
* @param {string} [params.marginMode] 'cross' or 'isolated' only 'isolated' is supported for spot-margin, swap supports both
|
|
2051
2052
|
* @param {bool} [params.margin] true for creating a margin order
|
|
2052
2053
|
* @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
|
|
2054
|
+
* @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
|
|
2055
|
+
* @param {string} [params.timeInForce] "GTC", "IOC", "FOK", "Day", "GTD"
|
|
2053
2056
|
* @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
|
|
2054
2057
|
*/
|
|
2055
2058
|
await this.loadMarkets();
|
|
2056
2059
|
const market = this.market(symbol);
|
|
2057
2060
|
const isLimit = (type === 'limit');
|
|
2061
|
+
const reduceOnly = this.safeValue(params, 'reduceOnly');
|
|
2062
|
+
const timeInForce = this.safeString(params, 'timeInForce');
|
|
2063
|
+
const triggerPrice = this.safeNumberN(params, ['triggerPrice', 'stopPrice', 'stop_price']);
|
|
2064
|
+
let marketType = undefined;
|
|
2065
|
+
[marketType, params] = this.handleMarketTypeAndParams('createOrder', market, params);
|
|
2066
|
+
let marginMode = undefined;
|
|
2067
|
+
[marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
|
|
2068
|
+
const isPostOnly = this.isPostOnly(type === 'market', undefined, params);
|
|
2058
2069
|
const request = {
|
|
2059
2070
|
'type': type,
|
|
2060
2071
|
'side': side,
|
|
@@ -2072,7 +2083,6 @@ class hitbtc extends hitbtc$1 {
|
|
|
2072
2083
|
// 'take_rate': 0.001, // Optional
|
|
2073
2084
|
// 'make_rate': 0.001, // Optional
|
|
2074
2085
|
};
|
|
2075
|
-
const reduceOnly = this.safeValue(params, 'reduceOnly');
|
|
2076
2086
|
if (reduceOnly !== undefined) {
|
|
2077
2087
|
if ((market['type'] !== 'swap') && (market['type'] !== 'margin')) {
|
|
2078
2088
|
throw new errors.InvalidOrder(this.id + ' createOrder() does not support reduce_only for ' + market['type'] + ' orders, reduce_only orders are supported for swap and margin markets only');
|
|
@@ -2081,8 +2091,12 @@ class hitbtc extends hitbtc$1 {
|
|
|
2081
2091
|
if (reduceOnly === true) {
|
|
2082
2092
|
request['reduce_only'] = reduceOnly;
|
|
2083
2093
|
}
|
|
2084
|
-
|
|
2085
|
-
|
|
2094
|
+
if (isPostOnly) {
|
|
2095
|
+
request['post_only'] = true;
|
|
2096
|
+
}
|
|
2097
|
+
if (timeInForce !== undefined) {
|
|
2098
|
+
request['time_in_force'] = timeInForce;
|
|
2099
|
+
}
|
|
2086
2100
|
if (isLimit || (type === 'stopLimit') || (type === 'takeProfitLimit')) {
|
|
2087
2101
|
if (price === undefined) {
|
|
2088
2102
|
throw new errors.ExchangeError(this.id + ' createOrder() requires a price argument for limit orders');
|
|
@@ -2107,19 +2121,20 @@ class hitbtc extends hitbtc$1 {
|
|
|
2107
2121
|
else if ((type === 'stopLimit') || (type === 'stopMarket') || (type === 'takeProfitLimit') || (type === 'takeProfitMarket')) {
|
|
2108
2122
|
throw new errors.ExchangeError(this.id + ' createOrder() requires a stopPrice parameter for stop-loss and take-profit orders');
|
|
2109
2123
|
}
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
if (marginMode !== undefined) {
|
|
2119
|
-
|
|
2124
|
+
params = this.omit(params, ['triggerPrice', 'timeInForce', 'stopPrice', 'stop_price', 'reduceOnly', 'postOnly']);
|
|
2125
|
+
if ((marketType === 'swap') && (marginMode !== undefined)) {
|
|
2126
|
+
request['margin_mode'] = marginMode;
|
|
2127
|
+
}
|
|
2128
|
+
let response = undefined;
|
|
2129
|
+
if (marketType === 'swap') {
|
|
2130
|
+
response = await this.privatePostFuturesOrder(this.extend(request, params));
|
|
2131
|
+
}
|
|
2132
|
+
else if ((marketType === 'margin') || (marginMode !== undefined)) {
|
|
2133
|
+
response = await this.privatePostMarginOrder(this.extend(request, params));
|
|
2134
|
+
}
|
|
2135
|
+
else {
|
|
2136
|
+
response = await this.privatePostSpotOrder(this.extend(request, params));
|
|
2120
2137
|
}
|
|
2121
|
-
params = this.omit(params, ['triggerPrice', 'timeInForce', 'time_in_force', 'stopPrice', 'stop_price', 'reduceOnly']);
|
|
2122
|
-
const response = await this[method](this.extend(request, query));
|
|
2123
2138
|
return this.parseOrder(response, market);
|
|
2124
2139
|
}
|
|
2125
2140
|
parseOrderStatus(status) {
|
|
@@ -3042,12 +3057,7 @@ class hitbtc extends hitbtc$1 {
|
|
|
3042
3057
|
const isMargin = this.safeValue(params, 'margin', false);
|
|
3043
3058
|
let marginMode = undefined;
|
|
3044
3059
|
[marginMode, params] = super.handleMarginModeAndParams(methodName, params, defaultValue);
|
|
3045
|
-
if (marginMode
|
|
3046
|
-
if (marginMode !== 'isolated') {
|
|
3047
|
-
throw new errors.NotSupported(this.id + ' only isolated margin is supported');
|
|
3048
|
-
}
|
|
3049
|
-
}
|
|
3050
|
-
else {
|
|
3060
|
+
if (marginMode === undefined) {
|
|
3051
3061
|
if ((defaultType === 'margin') || (isMargin === true)) {
|
|
3052
3062
|
marginMode = 'isolated';
|
|
3053
3063
|
}
|
package/dist/cjs/src/huobi.js
CHANGED
|
@@ -872,6 +872,7 @@ class huobi extends huobi$1 {
|
|
|
872
872
|
'1220': errors.AccountNotEnabled,
|
|
873
873
|
'1303': errors.BadRequest,
|
|
874
874
|
'1461': errors.InvalidOrder,
|
|
875
|
+
'4007': errors.BadRequest,
|
|
875
876
|
'bad-request': errors.BadRequest,
|
|
876
877
|
'validation-format-error': errors.BadRequest,
|
|
877
878
|
'validation-constraints-required': errors.BadRequest,
|
|
@@ -3014,6 +3015,13 @@ class huobi extends huobi$1 {
|
|
|
3014
3015
|
/**
|
|
3015
3016
|
* @method
|
|
3016
3017
|
* @name huobi#fetchBalance
|
|
3018
|
+
* @see https://huobiapi.github.io/docs/spot/v1/en/#get-account-balance-of-a-specific-account
|
|
3019
|
+
* @see https://www.htx.com/en-us/opend/newApiPages/?id=7ec4b429-7773-11ed-9966-0242ac110003
|
|
3020
|
+
* @see https://www.htx.com/en-us/opend/newApiPages/?id=10000074-77b7-11ed-9966-0242ac110003
|
|
3021
|
+
* @see https://huobiapi.github.io/docs/dm/v1/en/#query-asset-valuation
|
|
3022
|
+
* @see https://huobiapi.github.io/docs/coin_margined_swap/v1/en/#query-user-s-account-information
|
|
3023
|
+
* @see https://huobiapi.github.io/docs/usdt_swap/v1/en/#isolated-query-user-s-account-information
|
|
3024
|
+
* @see https://huobiapi.github.io/docs/usdt_swap/v1/en/#cross-query-user-39-s-account-information
|
|
3017
3025
|
* @description query for balance and get the amount of funds available for trading or funds locked in orders
|
|
3018
3026
|
* @param {object} [params] extra parameters specific to the huobi api endpoint
|
|
3019
3027
|
* @param {bool} [params.unified] provide this parameter if you have a recent account with unified cross+isolated margin account
|
|
@@ -3026,10 +3034,8 @@ class huobi extends huobi$1 {
|
|
|
3026
3034
|
const isUnifiedAccount = this.safeValue2(params, 'isUnifiedAccount', 'unified', false);
|
|
3027
3035
|
params = this.omit(params, ['isUnifiedAccount', 'unified']);
|
|
3028
3036
|
const request = {};
|
|
3029
|
-
let method = undefined;
|
|
3030
3037
|
const spot = (type === 'spot');
|
|
3031
3038
|
const future = (type === 'future');
|
|
3032
|
-
const swap = (type === 'swap');
|
|
3033
3039
|
const defaultSubType = this.safeString2(this.options, 'defaultSubType', 'subType', 'linear');
|
|
3034
3040
|
let subType = this.safeString2(options, 'defaultSubType', 'subType', defaultSubType);
|
|
3035
3041
|
subType = this.safeString2(params, 'defaultSubType', 'subType', subType);
|
|
@@ -3041,42 +3047,42 @@ class huobi extends huobi$1 {
|
|
|
3041
3047
|
const isolated = (marginMode === 'isolated');
|
|
3042
3048
|
const cross = (marginMode === 'cross');
|
|
3043
3049
|
const margin = (type === 'margin') || (spot && (cross || isolated));
|
|
3050
|
+
let response = undefined;
|
|
3044
3051
|
if (spot || margin) {
|
|
3045
3052
|
if (margin) {
|
|
3046
3053
|
if (isolated) {
|
|
3047
|
-
|
|
3054
|
+
response = await this.spotPrivateGetV1MarginAccountsBalance(this.extend(request, params));
|
|
3048
3055
|
}
|
|
3049
3056
|
else {
|
|
3050
|
-
|
|
3057
|
+
response = await this.spotPrivateGetV1CrossMarginAccountsBalance(this.extend(request, params));
|
|
3051
3058
|
}
|
|
3052
3059
|
}
|
|
3053
3060
|
else {
|
|
3054
3061
|
await this.loadAccounts();
|
|
3055
3062
|
const accountId = await this.fetchAccountIdByType(type, undefined, undefined, params);
|
|
3056
3063
|
request['account-id'] = accountId;
|
|
3057
|
-
|
|
3064
|
+
response = await this.spotPrivateGetV1AccountAccountsAccountIdBalance(this.extend(request, params));
|
|
3058
3065
|
}
|
|
3059
3066
|
}
|
|
3060
3067
|
else if (isUnifiedAccount) {
|
|
3061
|
-
|
|
3068
|
+
response = await this.contractPrivateGetLinearSwapApiV3UnifiedAccountInfo(this.extend(request, params));
|
|
3062
3069
|
}
|
|
3063
3070
|
else if (linear) {
|
|
3064
3071
|
if (isolated) {
|
|
3065
|
-
|
|
3072
|
+
response = await this.contractPrivatePostLinearSwapApiV1SwapAccountInfo(this.extend(request, params));
|
|
3066
3073
|
}
|
|
3067
3074
|
else {
|
|
3068
|
-
|
|
3075
|
+
response = await this.contractPrivatePostLinearSwapApiV1SwapCrossAccountInfo(this.extend(request, params));
|
|
3069
3076
|
}
|
|
3070
3077
|
}
|
|
3071
3078
|
else if (inverse) {
|
|
3072
3079
|
if (future) {
|
|
3073
|
-
|
|
3080
|
+
response = await this.contractPrivatePostApiV1ContractAccountInfo(this.extend(request, params));
|
|
3074
3081
|
}
|
|
3075
|
-
else
|
|
3076
|
-
|
|
3082
|
+
else {
|
|
3083
|
+
response = await this.contractPrivatePostSwapApiV1SwapAccountInfo(this.extend(request, params));
|
|
3077
3084
|
}
|
|
3078
3085
|
}
|
|
3079
|
-
const response = await this[method](this.extend(request, params));
|
|
3080
3086
|
//
|
|
3081
3087
|
// spot
|
|
3082
3088
|
//
|
|
@@ -2343,6 +2343,7 @@ class krakenfutures extends krakenfutures$1 {
|
|
|
2343
2343
|
}
|
|
2344
2344
|
const url = this.urls['api'][api] + query;
|
|
2345
2345
|
if (api === 'private' || access === 'private') {
|
|
2346
|
+
this.checkRequiredCredentials();
|
|
2346
2347
|
let auth = postData + '/api/';
|
|
2347
2348
|
if (api !== 'private') {
|
|
2348
2349
|
auth += api + '/';
|
package/dist/cjs/src/mexc.js
CHANGED
|
@@ -27,8 +27,8 @@ class mexc extends mexc$1 {
|
|
|
27
27
|
'spot': true,
|
|
28
28
|
'margin': true,
|
|
29
29
|
'swap': true,
|
|
30
|
-
'future':
|
|
31
|
-
'option':
|
|
30
|
+
'future': false,
|
|
31
|
+
'option': false,
|
|
32
32
|
'addMargin': true,
|
|
33
33
|
'borrowMargin': true,
|
|
34
34
|
'cancelAllOrders': true,
|
|
@@ -396,10 +396,6 @@ class mexc extends mexc$1 {
|
|
|
396
396
|
'fetchMarkets': {
|
|
397
397
|
'types': {
|
|
398
398
|
'spot': true,
|
|
399
|
-
'future': {
|
|
400
|
-
'linear': false,
|
|
401
|
-
'inverse': false,
|
|
402
|
-
},
|
|
403
399
|
'swap': {
|
|
404
400
|
'linear': true,
|
|
405
401
|
'inverse': false,
|
package/dist/cjs/src/okx.js
CHANGED
package/dist/cjs/src/phemex.js
CHANGED
|
@@ -3633,17 +3633,19 @@ class phemex extends phemex$1 {
|
|
|
3633
3633
|
// 'limit': 20, // Page size default 20, max 200
|
|
3634
3634
|
// 'offset': 0, // Page start default 0
|
|
3635
3635
|
};
|
|
3636
|
-
if (limit > 200) {
|
|
3637
|
-
throw new errors.BadRequest(this.id + ' fetchFundingHistory() limit argument cannot exceed 200');
|
|
3638
|
-
}
|
|
3639
3636
|
if (limit !== undefined) {
|
|
3637
|
+
if (limit > 200) {
|
|
3638
|
+
throw new errors.BadRequest(this.id + ' fetchFundingHistory() limit argument cannot exceed 200');
|
|
3639
|
+
}
|
|
3640
3640
|
request['limit'] = limit;
|
|
3641
3641
|
}
|
|
3642
|
-
let
|
|
3642
|
+
let response = undefined;
|
|
3643
3643
|
if (market['settle'] === 'USDT') {
|
|
3644
|
-
|
|
3644
|
+
response = await this.privateGetApiDataGFuturesFundingFees(this.extend(request, params));
|
|
3645
|
+
}
|
|
3646
|
+
else {
|
|
3647
|
+
response = await this.privateGetApiDataFuturesFundingFees(this.extend(request, params));
|
|
3645
3648
|
}
|
|
3646
|
-
const response = await this[method](this.extend(request, params));
|
|
3647
3649
|
//
|
|
3648
3650
|
// {
|
|
3649
3651
|
// "code": 0,
|
|
@@ -46,6 +46,12 @@ class bittrex extends bittrex$1 {
|
|
|
46
46
|
'maxRetries': 3,
|
|
47
47
|
},
|
|
48
48
|
},
|
|
49
|
+
'exceptions': {
|
|
50
|
+
'exact': {
|
|
51
|
+
'INVALID_APIKEY': errors.AuthenticationError,
|
|
52
|
+
'UNAUTHORIZED_USER': errors.AuthenticationError,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
49
55
|
});
|
|
50
56
|
}
|
|
51
57
|
getSignalRUrl(negotiation) {
|
|
@@ -96,6 +102,7 @@ class bittrex extends bittrex$1 {
|
|
|
96
102
|
return await this.watch(url, messageHash, request, messageHash, subscription);
|
|
97
103
|
}
|
|
98
104
|
async authenticate(params = {}) {
|
|
105
|
+
this.checkRequiredCredentials();
|
|
99
106
|
await this.loadMarkets();
|
|
100
107
|
const request = await this.negotiate();
|
|
101
108
|
return await this.sendRequestToAuthenticate(request, false, params);
|
|
@@ -116,7 +123,7 @@ class bittrex extends bittrex$1 {
|
|
|
116
123
|
'negotiation': negotiation,
|
|
117
124
|
'method': this.handleAuthenticate,
|
|
118
125
|
};
|
|
119
|
-
this.
|
|
126
|
+
this.watch(url, messageHash, request, requestId, subscription);
|
|
120
127
|
}
|
|
121
128
|
return await future;
|
|
122
129
|
}
|
|
@@ -523,7 +530,9 @@ class bittrex extends bittrex$1 {
|
|
|
523
530
|
* @returns {object[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure
|
|
524
531
|
*/
|
|
525
532
|
await this.loadMarkets();
|
|
526
|
-
symbol
|
|
533
|
+
if (symbol !== undefined) {
|
|
534
|
+
symbol = this.symbol(symbol);
|
|
535
|
+
}
|
|
527
536
|
const authentication = await this.authenticate();
|
|
528
537
|
const trades = await this.subscribeToMyTrades(authentication, params);
|
|
529
538
|
if (this.newUpdates) {
|
|
@@ -788,6 +797,60 @@ class bittrex extends bittrex$1 {
|
|
|
788
797
|
}
|
|
789
798
|
return message;
|
|
790
799
|
}
|
|
800
|
+
handleErrorMessage(client, message) {
|
|
801
|
+
//
|
|
802
|
+
// {
|
|
803
|
+
// R: [{ Success: false, ErrorCode: 'UNAUTHORIZED_USER' }, ... ],
|
|
804
|
+
// I: '1698601759267'
|
|
805
|
+
// }
|
|
806
|
+
// {
|
|
807
|
+
// R: { Success: false, ErrorCode: 'INVALID_APIKEY' },
|
|
808
|
+
// I: '1698601759266'
|
|
809
|
+
// }
|
|
810
|
+
//
|
|
811
|
+
const R = this.safeValue(message, 'R');
|
|
812
|
+
if (R === undefined) {
|
|
813
|
+
// Return there is no error
|
|
814
|
+
return false;
|
|
815
|
+
}
|
|
816
|
+
const I = this.safeString(message, 'I');
|
|
817
|
+
let errorCode = undefined;
|
|
818
|
+
if (Array.isArray(R)) {
|
|
819
|
+
for (let i = 0; i < R.length; i++) {
|
|
820
|
+
const response = this.safeValue(R, i);
|
|
821
|
+
const success = this.safeValue(response, 'Success', true);
|
|
822
|
+
if (!success) {
|
|
823
|
+
errorCode = this.safeString(response, 'ErrorCode');
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
const success = this.safeValue(R, 'Success', true);
|
|
830
|
+
if (!success) {
|
|
831
|
+
errorCode = this.safeString(R, 'ErrorCode');
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (errorCode === undefined) {
|
|
835
|
+
// Return there is no error
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
const feedback = this.id + ' ' + errorCode;
|
|
839
|
+
try {
|
|
840
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
|
|
841
|
+
if (message !== undefined) {
|
|
842
|
+
this.throwBroadlyMatchedException(this.exceptions['broad'], errorCode, feedback);
|
|
843
|
+
}
|
|
844
|
+
throw new errors.ExchangeError(feedback);
|
|
845
|
+
}
|
|
846
|
+
catch (e) {
|
|
847
|
+
if (e instanceof errors.AuthenticationError) {
|
|
848
|
+
client.reject(e, 'authenticate');
|
|
849
|
+
}
|
|
850
|
+
client.reject(e, I);
|
|
851
|
+
}
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
791
854
|
handleMessage(client, message) {
|
|
792
855
|
//
|
|
793
856
|
// subscription confirmation
|
|
@@ -834,6 +897,9 @@ class bittrex extends bittrex$1 {
|
|
|
834
897
|
// M: [ { H: 'C3', M: 'authenticationExpiring', A: [] } ]
|
|
835
898
|
// }
|
|
836
899
|
//
|
|
900
|
+
if (this.handleErrorMessage(client, message)) {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
837
903
|
const methods = {
|
|
838
904
|
'authenticationExpiring': this.handleAuthenticationExpiring,
|
|
839
905
|
'order': this.handleOrder,
|
|
@@ -102,7 +102,8 @@ class huobi extends huobi$1 {
|
|
|
102
102
|
'2021': errors.BadRequest,
|
|
103
103
|
'2001': errors.BadSymbol,
|
|
104
104
|
'2011': errors.BadSymbol,
|
|
105
|
-
'2040': errors.BadRequest,
|
|
105
|
+
'2040': errors.BadRequest,
|
|
106
|
+
'4007': errors.BadRequest, // { op: 'sub', cid: '1', topic: 'accounts_unify.USDT', 'err-code': 4007, 'err-msg': 'Non - single account user is not available, please check through the cross and isolated account asset interface', ts: 1698419318540 }
|
|
106
107
|
},
|
|
107
108
|
},
|
|
108
109
|
},
|
|
@@ -1191,12 +1192,12 @@ class huobi extends huobi$1 {
|
|
|
1191
1192
|
* @param {object} [params] extra parameters specific to the huobi api endpoint
|
|
1192
1193
|
* @returns {object} a [balance structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#balance-structure}
|
|
1193
1194
|
*/
|
|
1194
|
-
let type =
|
|
1195
|
-
type = this.
|
|
1196
|
-
let subType =
|
|
1197
|
-
subType = this.
|
|
1198
|
-
|
|
1199
|
-
params = this.omit(params, '
|
|
1195
|
+
let type = undefined;
|
|
1196
|
+
[type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params);
|
|
1197
|
+
let subType = undefined;
|
|
1198
|
+
[subType, params] = this.handleSubTypeAndParams('watchBalance', undefined, params, 'linear');
|
|
1199
|
+
const isUnifiedAccount = this.safeValue2(params, 'isUnifiedAccount', 'unified', false);
|
|
1200
|
+
params = this.omit(params, ['isUnifiedAccount', 'unified']);
|
|
1200
1201
|
await this.loadMarkets();
|
|
1201
1202
|
let messageHash = undefined;
|
|
1202
1203
|
let channel = undefined;
|
|
@@ -1217,29 +1218,37 @@ class huobi extends huobi$1 {
|
|
|
1217
1218
|
let prefix = 'accounts';
|
|
1218
1219
|
messageHash = prefix;
|
|
1219
1220
|
if (subType === 'linear') {
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
if (symbol !== undefined) {
|
|
1226
|
-
messageHash += '.' + market['id'];
|
|
1227
|
-
channel = messageHash;
|
|
1228
|
-
}
|
|
1229
|
-
else {
|
|
1230
|
-
// subscribe to all
|
|
1231
|
-
channel = prefix + '.' + '*';
|
|
1232
|
-
}
|
|
1221
|
+
if (isUnifiedAccount) {
|
|
1222
|
+
// usdt contracts account
|
|
1223
|
+
prefix = 'accounts_unify';
|
|
1224
|
+
messageHash = prefix;
|
|
1225
|
+
channel = prefix + '.' + 'usdt';
|
|
1233
1226
|
}
|
|
1234
1227
|
else {
|
|
1235
|
-
//
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1228
|
+
// usdt contracts account
|
|
1229
|
+
prefix = (marginMode === 'cross') ? prefix + '_cross' : prefix;
|
|
1230
|
+
messageHash = prefix;
|
|
1231
|
+
if (marginMode === 'isolated') {
|
|
1232
|
+
// isolated margin only allows filtering by symbol3
|
|
1233
|
+
if (symbol !== undefined) {
|
|
1234
|
+
messageHash += '.' + market['id'];
|
|
1235
|
+
channel = messageHash;
|
|
1236
|
+
}
|
|
1237
|
+
else {
|
|
1238
|
+
// subscribe to all
|
|
1239
|
+
channel = prefix + '.' + '*';
|
|
1240
|
+
}
|
|
1239
1241
|
}
|
|
1240
1242
|
else {
|
|
1241
|
-
//
|
|
1242
|
-
|
|
1243
|
+
// cross margin
|
|
1244
|
+
if (currencyCode !== undefined) {
|
|
1245
|
+
channel = prefix + '.' + currencyCode['id'];
|
|
1246
|
+
messageHash = channel;
|
|
1247
|
+
}
|
|
1248
|
+
else {
|
|
1249
|
+
// subscribe to all
|
|
1250
|
+
channel = prefix + '.' + '*';
|
|
1251
|
+
}
|
|
1243
1252
|
}
|
|
1244
1253
|
}
|
|
1245
1254
|
}
|
|
@@ -1417,7 +1426,9 @@ class huobi extends huobi$1 {
|
|
|
1417
1426
|
return;
|
|
1418
1427
|
}
|
|
1419
1428
|
const first = this.safeValue(data, 0, {});
|
|
1420
|
-
|
|
1429
|
+
const topic = this.safeString(message, 'topic');
|
|
1430
|
+
const splitTopic = topic.split('.');
|
|
1431
|
+
let messageHash = this.safeString(splitTopic, 0);
|
|
1421
1432
|
let subscription = this.safeValue2(client.subscriptions, messageHash, messageHash + '.*');
|
|
1422
1433
|
if (subscription === undefined) {
|
|
1423
1434
|
// if subscription not found means that we subscribed to a specific currency/symbol
|
|
@@ -1425,13 +1436,37 @@ class huobi extends huobi$1 {
|
|
|
1425
1436
|
// Example: topic = 'accounts'
|
|
1426
1437
|
// client.subscription hash = 'accounts.usdt'
|
|
1427
1438
|
// we do 'accounts' + '.' + data[0]]['margin_asset'] to get it
|
|
1428
|
-
const
|
|
1429
|
-
messageHash += '.' +
|
|
1439
|
+
const currencyId = this.safeString2(first, 'margin_asset', 'symbol');
|
|
1440
|
+
messageHash += '.' + currencyId.toLowerCase();
|
|
1430
1441
|
subscription = this.safeValue(client.subscriptions, messageHash);
|
|
1431
1442
|
}
|
|
1432
1443
|
const type = this.safeString(subscription, 'type');
|
|
1433
1444
|
const subType = this.safeString(subscription, 'subType');
|
|
1434
|
-
if (
|
|
1445
|
+
if (topic === 'accounts_unify') {
|
|
1446
|
+
// {
|
|
1447
|
+
// margin_asset: 'USDT',
|
|
1448
|
+
// margin_static: 10,
|
|
1449
|
+
// cross_margin_static: 10,
|
|
1450
|
+
// margin_balance: 10,
|
|
1451
|
+
// cross_profit_unreal: 0,
|
|
1452
|
+
// margin_frozen: 0,
|
|
1453
|
+
// withdraw_available: 10,
|
|
1454
|
+
// cross_risk_rate: null,
|
|
1455
|
+
// cross_swap: [],
|
|
1456
|
+
// cross_future: [],
|
|
1457
|
+
// isolated_swap: []
|
|
1458
|
+
// }
|
|
1459
|
+
const marginAsset = this.safeString(first, 'margin_asset');
|
|
1460
|
+
const code = this.safeCurrencyCode(marginAsset);
|
|
1461
|
+
const marginFrozen = this.safeString(first, 'margin_frozen');
|
|
1462
|
+
const unifiedAccount = this.account();
|
|
1463
|
+
unifiedAccount['free'] = this.safeString(first, 'withdraw_available');
|
|
1464
|
+
unifiedAccount['used'] = marginFrozen;
|
|
1465
|
+
this.balance[code] = unifiedAccount;
|
|
1466
|
+
this.balance = this.safeBalance(this.balance);
|
|
1467
|
+
client.resolve(this.balance, 'accounts_unify');
|
|
1468
|
+
}
|
|
1469
|
+
else if (subType === 'linear') {
|
|
1435
1470
|
const margin = this.safeString(subscription, 'margin');
|
|
1436
1471
|
if (margin === 'cross') {
|
|
1437
1472
|
const fieldName = (type === 'future') ? 'futures_contract_detail' : 'contract_detail';
|
|
@@ -1729,6 +1764,15 @@ class huobi extends huobi$1 {
|
|
|
1729
1764
|
// id: '2'
|
|
1730
1765
|
// }
|
|
1731
1766
|
//
|
|
1767
|
+
// {
|
|
1768
|
+
// op: 'sub',
|
|
1769
|
+
// cid: '1',
|
|
1770
|
+
// topic: 'accounts_unify.USDT',
|
|
1771
|
+
// 'err-code': 4007,
|
|
1772
|
+
// 'err-msg': 'Non - single account user is not available, please check through the cross and isolated account asset interface',
|
|
1773
|
+
// ts: 1698419490189
|
|
1774
|
+
// }
|
|
1775
|
+
//
|
|
1732
1776
|
const status = this.safeString(message, 'status');
|
|
1733
1777
|
if (status === 'error') {
|
|
1734
1778
|
const id = this.safeString(message, 'id');
|
|
@@ -1750,8 +1794,8 @@ class huobi extends huobi$1 {
|
|
|
1750
1794
|
}
|
|
1751
1795
|
return false;
|
|
1752
1796
|
}
|
|
1753
|
-
const code = this.
|
|
1754
|
-
if (code !== undefined && code !== 200) {
|
|
1797
|
+
const code = this.safeInteger2(message, 'code', 'err-code');
|
|
1798
|
+
if (code !== undefined && ((code !== 200) && (code !== 0))) {
|
|
1755
1799
|
const feedback = this.id + ' ' + this.json(message);
|
|
1756
1800
|
try {
|
|
1757
1801
|
this.throwExactlyMatchedException(this.exceptions['ws']['exact'], code, feedback);
|
package/dist/cjs/src/woo.js
CHANGED
|
@@ -947,29 +947,27 @@ class woo extends woo$1 {
|
|
|
947
947
|
if (stopPrice !== undefined) {
|
|
948
948
|
request['triggerPrice'] = this.priceToPrecision(symbol, stopPrice);
|
|
949
949
|
}
|
|
950
|
+
params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'stopPrice', 'triggerPrice', 'takeProfitPrice', 'stopLossPrice']);
|
|
950
951
|
const isStop = (stopPrice !== undefined) || (this.safeValue(params, 'childOrders') !== undefined);
|
|
951
|
-
let
|
|
952
|
+
let response = undefined;
|
|
952
953
|
if (isByClientOrder) {
|
|
954
|
+
request['client_order_id'] = clientOrderIdExchangeSpecific;
|
|
953
955
|
if (isStop) {
|
|
954
|
-
|
|
955
|
-
request['oid'] = id;
|
|
956
|
+
response = await this.v3PrivatePutAlgoOrderClientClientOrderId(this.extend(request, params));
|
|
956
957
|
}
|
|
957
958
|
else {
|
|
958
|
-
|
|
959
|
-
request['client_order_id'] = clientOrderIdExchangeSpecific;
|
|
959
|
+
response = await this.v3PrivatePutOrderClientClientOrderId(this.extend(request, params));
|
|
960
960
|
}
|
|
961
961
|
}
|
|
962
962
|
else {
|
|
963
|
+
request['oid'] = id;
|
|
963
964
|
if (isStop) {
|
|
964
|
-
|
|
965
|
+
response = await this.v3PrivatePutAlgoOrderOid(this.extend(request, params));
|
|
965
966
|
}
|
|
966
967
|
else {
|
|
967
|
-
|
|
968
|
+
response = await this.v3PrivatePutOrderOid(this.extend(request, params));
|
|
968
969
|
}
|
|
969
|
-
request['oid'] = id;
|
|
970
970
|
}
|
|
971
|
-
params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'stopPrice', 'triggerPrice', 'takeProfitPrice', 'stopLossPrice']);
|
|
972
|
-
const response = await this[method](this.extend(request, params));
|
|
973
971
|
//
|
|
974
972
|
// {
|
|
975
973
|
// "code": 0,
|
|
@@ -1005,32 +1003,31 @@ class woo extends woo$1 {
|
|
|
1005
1003
|
this.checkRequiredSymbol('cancelOrder', symbol);
|
|
1006
1004
|
}
|
|
1007
1005
|
await this.loadMarkets();
|
|
1006
|
+
let market = undefined;
|
|
1007
|
+
if (symbol !== undefined) {
|
|
1008
|
+
market = this.market(symbol);
|
|
1009
|
+
}
|
|
1008
1010
|
const request = {};
|
|
1009
1011
|
const clientOrderIdUnified = this.safeString2(params, 'clOrdID', 'clientOrderId');
|
|
1010
1012
|
const clientOrderIdExchangeSpecific = this.safeString(params, 'client_order_id', clientOrderIdUnified);
|
|
1011
1013
|
const isByClientOrder = clientOrderIdExchangeSpecific !== undefined;
|
|
1012
|
-
let
|
|
1014
|
+
let response = undefined;
|
|
1013
1015
|
if (stop) {
|
|
1014
|
-
method = 'v3PrivateDeleteAlgoOrderOrderId';
|
|
1015
1016
|
request['order_id'] = id;
|
|
1016
|
-
|
|
1017
|
-
else if (isByClientOrder) {
|
|
1018
|
-
method = 'v1PrivateDeleteClientOrder';
|
|
1019
|
-
request['client_order_id'] = clientOrderIdExchangeSpecific;
|
|
1020
|
-
params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
|
|
1017
|
+
response = await this.v3PrivateDeleteAlgoOrderOrderId(this.extend(request, params));
|
|
1021
1018
|
}
|
|
1022
1019
|
else {
|
|
1023
|
-
method = 'v1PrivateDeleteOrder';
|
|
1024
|
-
request['order_id'] = id;
|
|
1025
|
-
}
|
|
1026
|
-
let market = undefined;
|
|
1027
|
-
if (symbol !== undefined) {
|
|
1028
|
-
market = this.market(symbol);
|
|
1029
|
-
}
|
|
1030
|
-
if (!stop) {
|
|
1031
1020
|
request['symbol'] = market['id'];
|
|
1021
|
+
if (isByClientOrder) {
|
|
1022
|
+
request['client_order_id'] = clientOrderIdExchangeSpecific;
|
|
1023
|
+
params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
|
|
1024
|
+
response = await this.v1PrivateDeleteClientOrder(this.extend(request, params));
|
|
1025
|
+
}
|
|
1026
|
+
else {
|
|
1027
|
+
request['order_id'] = id;
|
|
1028
|
+
response = await this.v1PrivateDeleteOrder(this.extend(request, params));
|
|
1029
|
+
}
|
|
1032
1030
|
}
|
|
1033
|
-
const response = await this[method](this.extend(request, params));
|
|
1034
1031
|
//
|
|
1035
1032
|
// { success: true, status: 'CANCEL_SENT' }
|
|
1036
1033
|
//
|
|
@@ -1094,20 +1091,19 @@ class woo extends woo$1 {
|
|
|
1094
1091
|
params = this.omit(params, 'stop');
|
|
1095
1092
|
const request = {};
|
|
1096
1093
|
const clientOrderId = this.safeString2(params, 'clOrdID', 'clientOrderId');
|
|
1097
|
-
let
|
|
1094
|
+
let response = undefined;
|
|
1098
1095
|
if (stop) {
|
|
1099
|
-
method = 'v3PrivateGetAlgoOrderOid';
|
|
1100
1096
|
request['oid'] = id;
|
|
1097
|
+
response = await this.v3PrivateGetAlgoOrderOid(this.extend(request, params));
|
|
1101
1098
|
}
|
|
1102
1099
|
else if (clientOrderId) {
|
|
1103
|
-
method = 'v1PrivateGetClientOrderClientOrderId';
|
|
1104
1100
|
request['client_order_id'] = clientOrderId;
|
|
1101
|
+
response = await this.v1PrivateGetClientOrderClientOrderId(this.extend(request, params));
|
|
1105
1102
|
}
|
|
1106
1103
|
else {
|
|
1107
|
-
method = 'v1PrivateGetOrderOid';
|
|
1108
1104
|
request['oid'] = id;
|
|
1105
|
+
response = await this.v1PrivateGetOrderOid(this.extend(request, params));
|
|
1109
1106
|
}
|
|
1110
|
-
const response = await this[method](this.extend(request, params));
|
|
1111
1107
|
//
|
|
1112
1108
|
// {
|
|
1113
1109
|
// success: true,
|