ccxt 4.3.89 → 4.3.91
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/README.md +3 -3
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/alpaca.js +2 -2
- package/dist/cjs/src/ascendex.js +95 -97
- package/dist/cjs/src/binance.js +1 -1
- package/dist/cjs/src/bingx.js +31 -17
- package/dist/cjs/src/bitfinex2.js +21 -22
- package/dist/cjs/src/bitget.js +2 -2
- package/dist/cjs/src/bitmart.js +6 -9
- package/dist/cjs/src/coinbaseinternational.js +2 -1
- package/dist/cjs/src/coinex.js +1 -17
- package/dist/cjs/src/hitbtc.js +2 -0
- package/dist/cjs/src/htx.js +49 -49
- package/dist/cjs/src/huobijp.js +0 -9
- package/dist/cjs/src/kucoin.js +59 -21
- package/dist/cjs/src/kucoinfutures.js +26 -2
- package/dist/cjs/src/latoken.js +1 -0
- package/dist/cjs/src/okx.js +1 -8
- package/dist/cjs/src/pro/binance.js +323 -0
- package/dist/cjs/src/pro/bingx.js +263 -91
- package/dist/cjs/src/pro/bithumb.js +5 -1
- package/dist/cjs/src/pro/bybit.js +1 -1
- package/dist/cjs/src/pro/coinex.js +994 -679
- package/dist/cjs/src/pro/lbank.js +2 -3
- package/dist/cjs/src/pro/okx.js +159 -3
- package/dist/cjs/src/whitebit.js +5 -3
- package/dist/cjs/src/woo.js +1 -1
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/abstract/kucoin.d.ts +1 -0
- package/js/src/abstract/kucoinfutures.d.ts +1 -0
- package/js/src/alpaca.js +2 -2
- package/js/src/ascendex.js +95 -97
- package/js/src/binance.js +1 -1
- package/js/src/bingx.js +31 -17
- package/js/src/bitfinex2.d.ts +0 -1
- package/js/src/bitfinex2.js +21 -22
- package/js/src/bitget.js +2 -2
- package/js/src/bitmart.d.ts +0 -1
- package/js/src/bitmart.js +6 -9
- package/js/src/coinbaseinternational.js +2 -1
- package/js/src/coinex.d.ts +0 -2
- package/js/src/coinex.js +1 -17
- package/js/src/hitbtc.js +2 -0
- package/js/src/htx.js +49 -49
- package/js/src/huobijp.d.ts +0 -1
- package/js/src/huobijp.js +0 -9
- package/js/src/kucoin.d.ts +3 -1
- package/js/src/kucoin.js +59 -21
- package/js/src/kucoinfutures.d.ts +1 -0
- package/js/src/kucoinfutures.js +26 -2
- package/js/src/latoken.js +1 -0
- package/js/src/okx.d.ts +0 -1
- package/js/src/okx.js +1 -8
- package/js/src/pro/binance.d.ts +9 -1
- package/js/src/pro/binance.js +327 -1
- package/js/src/pro/bingx.d.ts +2 -2
- package/js/src/pro/bingx.js +263 -91
- package/js/src/pro/bithumb.js +5 -1
- package/js/src/pro/bybit.js +1 -1
- package/js/src/pro/coinex.d.ts +12 -6
- package/js/src/pro/coinex.js +996 -681
- package/js/src/pro/lbank.js +2 -3
- package/js/src/pro/okx.d.ts +7 -0
- package/js/src/pro/okx.js +162 -4
- package/js/src/whitebit.js +5 -3
- package/js/src/woo.js +1 -1
- package/package.json +1 -1
package/js/src/pro/coinex.js
CHANGED
|
@@ -5,12 +5,10 @@
|
|
|
5
5
|
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
|
|
6
6
|
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
|
-
import { Precise } from '../base/Precise.js';
|
|
9
8
|
import coinexRest from '../coinex.js';
|
|
10
|
-
import { AuthenticationError, BadRequest,
|
|
11
|
-
import { ArrayCache,
|
|
9
|
+
import { AuthenticationError, BadRequest, RateLimitExceeded, NotSupported, RequestTimeout, ExchangeError, ExchangeNotAvailable } from '../base/errors.js';
|
|
10
|
+
import { ArrayCache, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
|
|
12
11
|
import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
|
|
13
|
-
import { md5 } from '../static_dependencies/noble-hashes/md5.js';
|
|
14
12
|
// ---------------------------------------------------------------------------
|
|
15
13
|
export default class coinex extends coinexRest {
|
|
16
14
|
describe() {
|
|
@@ -18,25 +16,30 @@ export default class coinex extends coinexRest {
|
|
|
18
16
|
'has': {
|
|
19
17
|
'ws': true,
|
|
20
18
|
'watchBalance': true,
|
|
19
|
+
'watchBidsAsks': true,
|
|
21
20
|
'watchTicker': true,
|
|
22
21
|
'watchTickers': true,
|
|
23
22
|
'watchTrades': true,
|
|
24
|
-
'
|
|
23
|
+
'watchTradesForSymbols': true,
|
|
24
|
+
'watchMyTrades': true,
|
|
25
25
|
'watchOrders': true,
|
|
26
26
|
'watchOrderBook': true,
|
|
27
|
-
'
|
|
28
|
-
'
|
|
27
|
+
'watchOrderBookForSymbols': true,
|
|
28
|
+
'watchOHLCV': false,
|
|
29
|
+
'fetchOHLCVWs': false,
|
|
29
30
|
},
|
|
30
31
|
'urls': {
|
|
31
32
|
'api': {
|
|
32
33
|
'ws': {
|
|
33
|
-
'spot': 'wss://socket.coinex.com/',
|
|
34
|
-
'swap': 'wss://
|
|
34
|
+
'spot': 'wss://socket.coinex.com/v2/spot/',
|
|
35
|
+
'swap': 'wss://socket.coinex.com/v2/futures/',
|
|
35
36
|
},
|
|
36
37
|
},
|
|
37
38
|
},
|
|
38
39
|
'options': {
|
|
39
|
-
'
|
|
40
|
+
'ws': {
|
|
41
|
+
'gunzip': true,
|
|
42
|
+
},
|
|
40
43
|
'timeframes': {
|
|
41
44
|
'1m': 60,
|
|
42
45
|
'3m': 180,
|
|
@@ -56,20 +59,31 @@ export default class coinex extends coinexRest {
|
|
|
56
59
|
'watchOrderBook': {
|
|
57
60
|
'limits': [5, 10, 20, 50],
|
|
58
61
|
'defaultLimit': 50,
|
|
59
|
-
'aggregations': ['10', '1', '0', '0.1', '0.01'],
|
|
62
|
+
'aggregations': ['1000', '100', '10', '1', '0', '0.1', '0.01', '0.001', '0.0001', '0.00001', '0.000001', '0.0000001', '0.00000001', '0.000000001', '0.0000000001', '0.00000000001'],
|
|
60
63
|
'defaultAggregation': '0',
|
|
61
64
|
},
|
|
62
65
|
},
|
|
63
66
|
'streaming': {},
|
|
64
67
|
'exceptions': {
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
'
|
|
70
|
-
'
|
|
71
|
-
'
|
|
68
|
+
'exact': {
|
|
69
|
+
'20001': BadRequest,
|
|
70
|
+
'20002': NotSupported,
|
|
71
|
+
'21001': AuthenticationError,
|
|
72
|
+
'21002': AuthenticationError,
|
|
73
|
+
'23001': RequestTimeout,
|
|
74
|
+
'23002': RateLimitExceeded,
|
|
75
|
+
'24001': ExchangeError,
|
|
76
|
+
'24002': ExchangeNotAvailable,
|
|
77
|
+
'30001': BadRequest,
|
|
78
|
+
'30002': NotSupported,
|
|
79
|
+
'31001': AuthenticationError,
|
|
80
|
+
'31002': AuthenticationError,
|
|
81
|
+
'33001': RequestTimeout,
|
|
82
|
+
'33002': RateLimitExceeded,
|
|
83
|
+
'34001': ExchangeError,
|
|
84
|
+
'34002': ExchangeNotAvailable, // Service unavailable temporarily
|
|
72
85
|
},
|
|
86
|
+
'broad': {},
|
|
73
87
|
},
|
|
74
88
|
});
|
|
75
89
|
}
|
|
@@ -84,61 +98,66 @@ export default class coinex extends coinexRest {
|
|
|
84
98
|
//
|
|
85
99
|
// {
|
|
86
100
|
// "method": "state.update",
|
|
87
|
-
// "
|
|
88
|
-
// "
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
+
// "data": {
|
|
102
|
+
// "state_list": [
|
|
103
|
+
// {
|
|
104
|
+
// "market": "LATUSDT",
|
|
105
|
+
// "last": "0.008157",
|
|
106
|
+
// "open": "0.008286",
|
|
107
|
+
// "close": "0.008157",
|
|
108
|
+
// "high": "0.008390",
|
|
109
|
+
// "low": "0.008106",
|
|
110
|
+
// "volume": "807714.49139758",
|
|
111
|
+
// "volume_sell": "286170.69645599",
|
|
112
|
+
// "volume_buy": "266161.23236408",
|
|
113
|
+
// "value": "6689.21644207",
|
|
114
|
+
// "period": 86400
|
|
115
|
+
// },
|
|
116
|
+
// ]
|
|
117
|
+
// },
|
|
118
|
+
// "id": null
|
|
101
119
|
// }
|
|
102
120
|
//
|
|
103
121
|
// swap
|
|
104
122
|
//
|
|
105
123
|
// {
|
|
106
124
|
// "method": "state.update",
|
|
107
|
-
// "
|
|
108
|
-
// "
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
//
|
|
125
|
+
// "data": {
|
|
126
|
+
// "state_list": [
|
|
127
|
+
// {
|
|
128
|
+
// "market": "ETHUSD_SIGNPRICE",
|
|
129
|
+
// "last": "1892.29",
|
|
130
|
+
// "open": "1884.62",
|
|
131
|
+
// "close": "1892.29",
|
|
132
|
+
// "high": "1894.09",
|
|
133
|
+
// "low": "1863.72",
|
|
134
|
+
// "volume": "0",
|
|
135
|
+
// "value": "0",
|
|
136
|
+
// "volume_sell": "0",
|
|
137
|
+
// "volume_buy": "0",
|
|
138
|
+
// "open_interest_size": "0",
|
|
139
|
+
// "insurance_fund_size": "0",
|
|
140
|
+
// "latest_funding_rate": "0",
|
|
141
|
+
// "next_funding_rate": "0",
|
|
142
|
+
// "latest_funding_time": 0,
|
|
143
|
+
// "next_funding_time": 0,
|
|
144
|
+
// "period": 86400
|
|
145
|
+
// },
|
|
146
|
+
// ]
|
|
147
|
+
// ],
|
|
148
|
+
// "id": null
|
|
129
149
|
// }
|
|
130
150
|
//
|
|
131
151
|
const defaultType = this.safeString(this.options, 'defaultType');
|
|
132
|
-
const
|
|
133
|
-
const rawTickers = this.
|
|
134
|
-
const keys = Object.keys(rawTickers);
|
|
152
|
+
const data = this.safeDict(message, 'data', {});
|
|
153
|
+
const rawTickers = this.safeList(data, 'state_list', []);
|
|
135
154
|
const newTickers = [];
|
|
136
|
-
for (let i = 0; i <
|
|
137
|
-
const
|
|
138
|
-
const
|
|
155
|
+
for (let i = 0; i < rawTickers.length; i++) {
|
|
156
|
+
const entry = rawTickers[i];
|
|
157
|
+
const marketId = this.safeString(entry, 'market');
|
|
139
158
|
const symbol = this.safeSymbol(marketId, undefined, undefined, defaultType);
|
|
140
159
|
const market = this.safeMarket(marketId, undefined, undefined, defaultType);
|
|
141
|
-
const parsedTicker = this.parseWSTicker(
|
|
160
|
+
const parsedTicker = this.parseWSTicker(entry, market);
|
|
142
161
|
this.tickers[symbol] = parsedTicker;
|
|
143
162
|
newTickers.push(parsedTicker);
|
|
144
163
|
}
|
|
@@ -162,52 +181,53 @@ export default class coinex extends coinexRest {
|
|
|
162
181
|
// spot
|
|
163
182
|
//
|
|
164
183
|
// {
|
|
165
|
-
// "
|
|
166
|
-
// "
|
|
167
|
-
// "
|
|
168
|
-
// "
|
|
169
|
-
// "
|
|
170
|
-
// "
|
|
171
|
-
// "
|
|
172
|
-
// "
|
|
173
|
-
// "
|
|
174
|
-
// "
|
|
184
|
+
// "market": "LATUSDT",
|
|
185
|
+
// "last": "0.008157",
|
|
186
|
+
// "open": "0.008286",
|
|
187
|
+
// "close": "0.008157",
|
|
188
|
+
// "high": "0.008390",
|
|
189
|
+
// "low": "0.008106",
|
|
190
|
+
// "volume": "807714.49139758",
|
|
191
|
+
// "volume_sell": "286170.69645599",
|
|
192
|
+
// "volume_buy": "266161.23236408",
|
|
193
|
+
// "value": "6689.21644207",
|
|
194
|
+
// "period": 86400
|
|
175
195
|
// }
|
|
176
196
|
//
|
|
177
197
|
// swap
|
|
178
198
|
//
|
|
179
199
|
// {
|
|
180
|
-
// "
|
|
181
|
-
// "
|
|
182
|
-
// "
|
|
183
|
-
// "
|
|
184
|
-
// "
|
|
185
|
-
// "
|
|
186
|
-
// "
|
|
187
|
-
// "
|
|
188
|
-
// "
|
|
189
|
-
// "
|
|
190
|
-
// "
|
|
191
|
-
// "
|
|
192
|
-
// "
|
|
193
|
-
// "
|
|
194
|
-
// "
|
|
195
|
-
// "
|
|
196
|
-
// "
|
|
197
|
-
// "buy_total": "25.7814"
|
|
200
|
+
// "market": "ETHUSD_SIGNPRICE",
|
|
201
|
+
// "last": "1892.29",
|
|
202
|
+
// "open": "1884.62",
|
|
203
|
+
// "close": "1892.29",
|
|
204
|
+
// "high": "1894.09",
|
|
205
|
+
// "low": "1863.72",
|
|
206
|
+
// "volume": "0",
|
|
207
|
+
// "value": "0",
|
|
208
|
+
// "volume_sell": "0",
|
|
209
|
+
// "volume_buy": "0",
|
|
210
|
+
// "open_interest_size": "0",
|
|
211
|
+
// "insurance_fund_size": "0",
|
|
212
|
+
// "latest_funding_rate": "0",
|
|
213
|
+
// "next_funding_rate": "0",
|
|
214
|
+
// "latest_funding_time": 0,
|
|
215
|
+
// "next_funding_time": 0,
|
|
216
|
+
// "period": 86400
|
|
198
217
|
// }
|
|
199
218
|
//
|
|
200
219
|
const defaultType = this.safeString(this.options, 'defaultType');
|
|
220
|
+
const marketId = this.safeString(ticker, 'market');
|
|
201
221
|
return this.safeTicker({
|
|
202
|
-
'symbol': this.safeSymbol(
|
|
222
|
+
'symbol': this.safeSymbol(marketId, market, undefined, defaultType),
|
|
203
223
|
'timestamp': undefined,
|
|
204
224
|
'datetime': undefined,
|
|
205
225
|
'high': this.safeString(ticker, 'high'),
|
|
206
226
|
'low': this.safeString(ticker, 'low'),
|
|
207
227
|
'bid': undefined,
|
|
208
|
-
'bidVolume': this.safeString(ticker, '
|
|
228
|
+
'bidVolume': this.safeString(ticker, 'volume_buy'),
|
|
209
229
|
'ask': undefined,
|
|
210
|
-
'askVolume': this.safeString(ticker, '
|
|
230
|
+
'askVolume': this.safeString(ticker, 'volume_sell'),
|
|
211
231
|
'vwap': undefined,
|
|
212
232
|
'open': this.safeString(ticker, 'open'),
|
|
213
233
|
'close': this.safeString(ticker, 'close'),
|
|
@@ -217,7 +237,7 @@ export default class coinex extends coinexRest {
|
|
|
217
237
|
'percentage': undefined,
|
|
218
238
|
'average': undefined,
|
|
219
239
|
'baseVolume': this.safeString(ticker, 'volume'),
|
|
220
|
-
'quoteVolume': this.safeString(ticker, '
|
|
240
|
+
'quoteVolume': this.safeString(ticker, 'value'),
|
|
221
241
|
'info': ticker,
|
|
222
242
|
}, market);
|
|
223
243
|
}
|
|
@@ -226,78 +246,290 @@ export default class coinex extends coinexRest {
|
|
|
226
246
|
* @method
|
|
227
247
|
* @name coinex#watchBalance
|
|
228
248
|
* @description watch balance and get the amount of funds available for trading or funds locked in orders
|
|
249
|
+
* @see https://docs.coinex.com/api/v2/assets/balance/ws/spot_balance
|
|
250
|
+
* @see https://docs.coinex.com/api/v2/assets/balance/ws/futures_balance
|
|
229
251
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
230
252
|
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
231
253
|
*/
|
|
232
254
|
await this.loadMarkets();
|
|
233
|
-
await this.authenticate(params);
|
|
234
|
-
const messageHash = 'balance';
|
|
235
255
|
let type = undefined;
|
|
236
|
-
[type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params);
|
|
256
|
+
[type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params, 'spot');
|
|
257
|
+
await this.authenticate(type);
|
|
237
258
|
const url = this.urls['api']['ws'][type];
|
|
238
|
-
|
|
259
|
+
let currencies = Object.keys(this.currencies_by_id);
|
|
260
|
+
if (currencies === undefined) {
|
|
261
|
+
currencies = [];
|
|
262
|
+
}
|
|
263
|
+
let messageHash = 'balances';
|
|
264
|
+
if (type === 'spot') {
|
|
265
|
+
messageHash += ':spot';
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
messageHash += ':swap';
|
|
269
|
+
}
|
|
239
270
|
const subscribe = {
|
|
240
|
-
'method': '
|
|
241
|
-
'params': currencies,
|
|
271
|
+
'method': 'balance.subscribe',
|
|
272
|
+
'params': { 'ccy_list': currencies },
|
|
242
273
|
'id': this.requestId(),
|
|
243
274
|
};
|
|
244
275
|
const request = this.deepExtend(subscribe, params);
|
|
245
276
|
return await this.watch(url, messageHash, request, messageHash);
|
|
246
277
|
}
|
|
247
278
|
handleBalance(client, message) {
|
|
279
|
+
//
|
|
280
|
+
// spot
|
|
248
281
|
//
|
|
249
282
|
// {
|
|
250
|
-
// "method": "
|
|
251
|
-
// "
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
// "
|
|
255
|
-
// "
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
283
|
+
// "method": "balance.update",
|
|
284
|
+
// "data": {
|
|
285
|
+
// "balance_list": [
|
|
286
|
+
// {
|
|
287
|
+
// "margin_market": "BTCUSDT",
|
|
288
|
+
// "ccy": "BTC",
|
|
289
|
+
// "available": "44.62207740",
|
|
290
|
+
// "frozen": "0.00000000",
|
|
291
|
+
// "updated_at": 1689152421692
|
|
292
|
+
// },
|
|
293
|
+
// ]
|
|
294
|
+
// },
|
|
259
295
|
// "id": null
|
|
260
296
|
// }
|
|
261
297
|
//
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
298
|
+
// swap
|
|
299
|
+
//
|
|
300
|
+
// {
|
|
301
|
+
// "method": "balance.update",
|
|
302
|
+
// "data": {
|
|
303
|
+
// "balance_list": [
|
|
304
|
+
// {
|
|
305
|
+
// "ccy": "USDT",
|
|
306
|
+
// "available": "97.92470982756335000001",
|
|
307
|
+
// "frozen": "0.00000000000000000000",
|
|
308
|
+
// "margin": "0.61442700000000000000",
|
|
309
|
+
// "transferrable": "97.92470982756335000001",
|
|
310
|
+
// "unrealized_pnl": "-0.00807000000000000000",
|
|
311
|
+
// "equity": "97.92470982756335000001"
|
|
312
|
+
// },
|
|
313
|
+
// ]
|
|
314
|
+
// },
|
|
315
|
+
// "id": null
|
|
316
|
+
// }
|
|
317
|
+
//
|
|
318
|
+
if (this.balance === undefined) {
|
|
319
|
+
this.balance = {};
|
|
320
|
+
}
|
|
321
|
+
const data = this.safeDict(message, 'data', {});
|
|
322
|
+
const balances = this.safeList(data, 'balance_list', []);
|
|
323
|
+
const firstEntry = balances[0];
|
|
324
|
+
const updated = this.safeInteger(firstEntry, 'updated_at');
|
|
325
|
+
const unrealizedPnl = this.safeString(firstEntry, 'unrealized_pnl');
|
|
326
|
+
const isSpot = (updated !== undefined);
|
|
327
|
+
const isSwap = (unrealizedPnl !== undefined);
|
|
328
|
+
let info = undefined;
|
|
329
|
+
let account = undefined;
|
|
330
|
+
let rawBalances = [];
|
|
331
|
+
if (isSpot) {
|
|
332
|
+
account = 'spot';
|
|
333
|
+
for (let i = 0; i < balances.length; i++) {
|
|
334
|
+
rawBalances = this.arrayConcat(rawBalances, balances);
|
|
335
|
+
}
|
|
336
|
+
info = rawBalances;
|
|
337
|
+
}
|
|
338
|
+
if (isSwap) {
|
|
339
|
+
account = 'swap';
|
|
340
|
+
for (let i = 0; i < balances.length; i++) {
|
|
341
|
+
rawBalances = this.arrayConcat(rawBalances, balances);
|
|
342
|
+
}
|
|
343
|
+
info = rawBalances;
|
|
344
|
+
}
|
|
345
|
+
for (let i = 0; i < rawBalances.length; i++) {
|
|
346
|
+
const entry = rawBalances[i];
|
|
347
|
+
this.parseWsBalance(entry, account);
|
|
348
|
+
}
|
|
349
|
+
let messageHash = undefined;
|
|
350
|
+
if (account !== undefined) {
|
|
351
|
+
if (this.safeValue(this.balance, account) === undefined) {
|
|
352
|
+
this.balance[account] = {};
|
|
353
|
+
}
|
|
354
|
+
this.balance[account]['info'] = info;
|
|
355
|
+
this.balance[account] = this.safeBalance(this.balance[account]);
|
|
356
|
+
messageHash = 'balances:' + account;
|
|
357
|
+
client.resolve(this.balance[account], messageHash);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
parseWsBalance(balance, accountType = undefined) {
|
|
361
|
+
//
|
|
362
|
+
// spot
|
|
363
|
+
//
|
|
364
|
+
// {
|
|
365
|
+
// "margin_market": "BTCUSDT",
|
|
366
|
+
// "ccy": "BTC",
|
|
367
|
+
// "available": "44.62207740",
|
|
368
|
+
// "frozen": "0.00000000",
|
|
369
|
+
// "updated_at": 1689152421692
|
|
370
|
+
// }
|
|
371
|
+
//
|
|
372
|
+
// swap
|
|
373
|
+
//
|
|
374
|
+
// {
|
|
375
|
+
// "ccy": "USDT",
|
|
376
|
+
// "available": "97.92470982756335000001",
|
|
377
|
+
// "frozen": "0.00000000000000000000",
|
|
378
|
+
// "margin": "0.61442700000000000000",
|
|
379
|
+
// "transferrable": "97.92470982756335000001",
|
|
380
|
+
// "unrealized_pnl": "-0.00807000000000000000",
|
|
381
|
+
// "equity": "97.92470982756335000001"
|
|
382
|
+
// }
|
|
383
|
+
//
|
|
384
|
+
const account = this.account();
|
|
385
|
+
const currencyId = this.safeString(balance, 'ccy');
|
|
386
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
387
|
+
account['free'] = this.safeString(balance, 'available');
|
|
388
|
+
account['used'] = this.safeString(balance, 'frozen');
|
|
389
|
+
if (accountType !== undefined) {
|
|
390
|
+
if (this.safeValue(this.balance, accountType) === undefined) {
|
|
391
|
+
this.balance[accountType] = {};
|
|
392
|
+
}
|
|
393
|
+
this.balance[accountType][code] = account;
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
274
396
|
this.balance[code] = account;
|
|
275
|
-
this.balance = this.safeBalance(this.balance);
|
|
276
397
|
}
|
|
277
|
-
|
|
278
|
-
|
|
398
|
+
}
|
|
399
|
+
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
400
|
+
/**
|
|
401
|
+
* @method
|
|
402
|
+
* @name coinex#watchMyTrades
|
|
403
|
+
* @description watches information on multiple trades made by the user
|
|
404
|
+
* @see https://docs.coinex.com/api/v2/spot/deal/ws/user-deals
|
|
405
|
+
* @see https://docs.coinex.com/api/v2/futures/deal/ws/user-deals
|
|
406
|
+
* @param {string} [symbol] unified symbol of the market the trades were made in
|
|
407
|
+
* @param {int} [since] the earliest time in ms to watch trades
|
|
408
|
+
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
409
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
410
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
411
|
+
*/
|
|
412
|
+
await this.loadMarkets();
|
|
413
|
+
let market = undefined;
|
|
414
|
+
if (symbol !== undefined) {
|
|
415
|
+
market = this.market(symbol);
|
|
416
|
+
symbol = market['symbol'];
|
|
417
|
+
}
|
|
418
|
+
let type = undefined;
|
|
419
|
+
[type, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params, 'spot');
|
|
420
|
+
await this.authenticate(type);
|
|
421
|
+
const url = this.urls['api']['ws'][type];
|
|
422
|
+
const subscribedSymbols = [];
|
|
423
|
+
let messageHash = 'myTrades';
|
|
424
|
+
if (market !== undefined) {
|
|
425
|
+
messageHash += ':' + symbol;
|
|
426
|
+
subscribedSymbols.push(market['id']);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
if (type === 'spot') {
|
|
430
|
+
messageHash += ':spot';
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
messageHash += ':swap';
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
const message = {
|
|
437
|
+
'method': 'user_deals.subscribe',
|
|
438
|
+
'params': { 'market_list': subscribedSymbols },
|
|
439
|
+
'id': this.requestId(),
|
|
440
|
+
};
|
|
441
|
+
const request = this.deepExtend(message, params);
|
|
442
|
+
const trades = await this.watch(url, messageHash, request, messageHash);
|
|
443
|
+
if (this.newUpdates) {
|
|
444
|
+
limit = trades.getLimit(symbol, limit);
|
|
445
|
+
}
|
|
446
|
+
return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
|
|
447
|
+
}
|
|
448
|
+
handleMyTrades(client, message) {
|
|
449
|
+
//
|
|
450
|
+
// {
|
|
451
|
+
// "method": "user_deals.update",
|
|
452
|
+
// "data": {
|
|
453
|
+
// "deal_id": 3514376759,
|
|
454
|
+
// "created_at": 1689152421692,
|
|
455
|
+
// "market": "BTCUSDT",
|
|
456
|
+
// "side": "buy",
|
|
457
|
+
// "order_id": 8678890,
|
|
458
|
+
// "margin_market": "BTCUSDT",
|
|
459
|
+
// "price": "30718.42",
|
|
460
|
+
// "amount": "0.00000325",
|
|
461
|
+
// "role": "taker",
|
|
462
|
+
// "fee": "0.0299",
|
|
463
|
+
// "fee_ccy": "USDT"
|
|
464
|
+
// },
|
|
465
|
+
// "id": null
|
|
466
|
+
// }
|
|
467
|
+
//
|
|
468
|
+
const data = this.safeDict(message, 'data', {});
|
|
469
|
+
const marketId = this.safeString(data, 'market');
|
|
470
|
+
const isSpot = client.url.indexOf('spot') > -1;
|
|
471
|
+
const defaultType = isSpot ? 'spot' : 'swap';
|
|
472
|
+
const market = this.safeMarket(marketId, undefined, undefined, defaultType);
|
|
473
|
+
const symbol = market['symbol'];
|
|
474
|
+
const messageHash = 'myTrades:' + symbol;
|
|
475
|
+
const messageWithType = 'myTrades:' + market['type'];
|
|
476
|
+
let stored = this.safeValue(this.trades, symbol);
|
|
477
|
+
if (stored === undefined) {
|
|
478
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
479
|
+
stored = new ArrayCache(limit);
|
|
480
|
+
this.trades[symbol] = stored;
|
|
481
|
+
}
|
|
482
|
+
const parsed = this.parseWsTrade(data, market);
|
|
483
|
+
stored.append(parsed);
|
|
484
|
+
this.trades[symbol] = stored;
|
|
485
|
+
client.resolve(this.trades[symbol], messageWithType);
|
|
486
|
+
client.resolve(this.trades[symbol], messageHash);
|
|
279
487
|
}
|
|
280
488
|
handleTrades(client, message) {
|
|
489
|
+
//
|
|
490
|
+
// spot
|
|
281
491
|
//
|
|
282
492
|
// {
|
|
283
493
|
// "method": "deals.update",
|
|
284
|
-
// "
|
|
285
|
-
// "
|
|
286
|
-
// [
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
//
|
|
293
|
-
//
|
|
494
|
+
// "data": {
|
|
495
|
+
// "market": "BTCUSDT",
|
|
496
|
+
// "deal_list": [
|
|
497
|
+
// {
|
|
498
|
+
// "deal_id": 3514376759,
|
|
499
|
+
// "created_at": 1689152421692,
|
|
500
|
+
// "side": "buy",
|
|
501
|
+
// "price": "30718.42",
|
|
502
|
+
// "amount": "0.00000325"
|
|
503
|
+
// },
|
|
504
|
+
// ]
|
|
505
|
+
// },
|
|
294
506
|
// "id": null
|
|
295
507
|
// }
|
|
296
508
|
//
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
509
|
+
// swap
|
|
510
|
+
//
|
|
511
|
+
// {
|
|
512
|
+
// "method": "deals.update",
|
|
513
|
+
// "data": {
|
|
514
|
+
// "market": "BTCUSDT",
|
|
515
|
+
// "deal_list": [
|
|
516
|
+
// {
|
|
517
|
+
// "deal_id": 3514376759,
|
|
518
|
+
// "created_at": 1689152421692,
|
|
519
|
+
// "side": "buy",
|
|
520
|
+
// "price": "30718.42",
|
|
521
|
+
// "amount": "0.00000325"
|
|
522
|
+
// },
|
|
523
|
+
// ]
|
|
524
|
+
// },
|
|
525
|
+
// "id": null
|
|
526
|
+
// }
|
|
527
|
+
//
|
|
528
|
+
const data = this.safeDict(message, 'data', {});
|
|
529
|
+
const trades = this.safeList(data, 'deal_list', []);
|
|
530
|
+
const marketId = this.safeString(data, 'market');
|
|
531
|
+
const isSpot = client.url.indexOf('spot') > -1;
|
|
532
|
+
const defaultType = isSpot ? 'spot' : 'swap';
|
|
301
533
|
const market = this.safeMarket(marketId, undefined, undefined, defaultType);
|
|
302
534
|
const symbol = market['symbol'];
|
|
303
535
|
const messageHash = 'trades:' + symbol;
|
|
@@ -316,133 +548,127 @@ export default class coinex extends coinexRest {
|
|
|
316
548
|
client.resolve(this.trades[symbol], messageHash);
|
|
317
549
|
}
|
|
318
550
|
parseWsTrade(trade, market = undefined) {
|
|
551
|
+
//
|
|
552
|
+
// spot watchTrades
|
|
319
553
|
//
|
|
320
554
|
// {
|
|
321
|
-
// "
|
|
322
|
-
// "
|
|
323
|
-
// "
|
|
324
|
-
// "
|
|
325
|
-
// "amount": "0.
|
|
555
|
+
// "deal_id": 3514376759,
|
|
556
|
+
// "created_at": 1689152421692,
|
|
557
|
+
// "side": "buy",
|
|
558
|
+
// "price": "30718.42",
|
|
559
|
+
// "amount": "0.00000325"
|
|
326
560
|
// }
|
|
327
561
|
//
|
|
328
|
-
|
|
329
|
-
|
|
562
|
+
// swap watchTrades
|
|
563
|
+
//
|
|
564
|
+
// {
|
|
565
|
+
// "deal_id": 3514376759,
|
|
566
|
+
// "created_at": 1689152421692,
|
|
567
|
+
// "side": "buy",
|
|
568
|
+
// "price": "30718.42",
|
|
569
|
+
// "amount": "0.00000325"
|
|
570
|
+
// }
|
|
571
|
+
//
|
|
572
|
+
// spot and swap watchMyTrades
|
|
573
|
+
//
|
|
574
|
+
// {
|
|
575
|
+
// "deal_id": 3514376759,
|
|
576
|
+
// "created_at": 1689152421692,
|
|
577
|
+
// "market": "BTCUSDT",
|
|
578
|
+
// "side": "buy",
|
|
579
|
+
// "order_id": 8678890,
|
|
580
|
+
// "margin_market": "BTCUSDT",
|
|
581
|
+
// "price": "30718.42",
|
|
582
|
+
// "amount": "0.00000325",
|
|
583
|
+
// "role": "taker",
|
|
584
|
+
// "fee": "0.0299",
|
|
585
|
+
// "fee_ccy": "USDT"
|
|
586
|
+
// }
|
|
587
|
+
//
|
|
588
|
+
const timestamp = this.safeInteger(trade, 'created_at');
|
|
589
|
+
const isSpot = ('margin_market' in trade);
|
|
590
|
+
const defaultType = isSpot ? 'spot' : 'swap';
|
|
591
|
+
const marketId = this.safeString(trade, 'market');
|
|
592
|
+
market = this.safeMarket(marketId, market, undefined, defaultType);
|
|
593
|
+
let fee = {};
|
|
594
|
+
const feeCost = this.omitZero(this.safeString(trade, 'fee'));
|
|
595
|
+
if (feeCost !== undefined) {
|
|
596
|
+
const feeCurrencyId = this.safeString(trade, 'fee_ccy', market['quote']);
|
|
597
|
+
fee = {
|
|
598
|
+
'currency': this.safeCurrencyCode(feeCurrencyId),
|
|
599
|
+
'cost': feeCost,
|
|
600
|
+
};
|
|
601
|
+
}
|
|
330
602
|
return this.safeTrade({
|
|
331
|
-
'id': this.safeString(trade, '
|
|
603
|
+
'id': this.safeString(trade, 'deal_id'),
|
|
332
604
|
'info': trade,
|
|
333
605
|
'timestamp': timestamp,
|
|
334
606
|
'datetime': this.iso8601(timestamp),
|
|
335
|
-
'symbol': this.safeSymbol(
|
|
336
|
-
'order':
|
|
607
|
+
'symbol': this.safeSymbol(marketId, market, undefined, defaultType),
|
|
608
|
+
'order': this.safeString(trade, 'order_id'),
|
|
337
609
|
'type': undefined,
|
|
338
|
-
'side': this.safeString(trade, '
|
|
339
|
-
'takerOrMaker':
|
|
610
|
+
'side': this.safeString(trade, 'side'),
|
|
611
|
+
'takerOrMaker': this.safeString(trade, 'role'),
|
|
340
612
|
'price': this.safeString(trade, 'price'),
|
|
341
613
|
'amount': this.safeString(trade, 'amount'),
|
|
342
614
|
'cost': undefined,
|
|
343
|
-
'fee':
|
|
615
|
+
'fee': fee,
|
|
344
616
|
}, market);
|
|
345
617
|
}
|
|
346
|
-
handleOHLCV(client, message) {
|
|
347
|
-
//
|
|
348
|
-
// spot
|
|
349
|
-
// {
|
|
350
|
-
// "error": null,
|
|
351
|
-
// "result": [
|
|
352
|
-
// [
|
|
353
|
-
// 1673846940,
|
|
354
|
-
// "21148.74",
|
|
355
|
-
// "21148.38",
|
|
356
|
-
// "21148.75",
|
|
357
|
-
// "21138.66",
|
|
358
|
-
// "1.57060173",
|
|
359
|
-
// "33214.9138778914"
|
|
360
|
-
// ],
|
|
361
|
-
// ]
|
|
362
|
-
// "id": 1,
|
|
363
|
-
// }
|
|
364
|
-
// swap
|
|
365
|
-
// {
|
|
366
|
-
// "method": "kline.update",
|
|
367
|
-
// "params": [
|
|
368
|
-
// [
|
|
369
|
-
// 1654019640, // timestamp
|
|
370
|
-
// "32061.99", // open
|
|
371
|
-
// "32061.28", // close
|
|
372
|
-
// "32061.99", // high
|
|
373
|
-
// "32061.28", // low
|
|
374
|
-
// "0.1285", // amount base
|
|
375
|
-
// "4119.943736" // amount quote
|
|
376
|
-
// ]
|
|
377
|
-
// ],
|
|
378
|
-
// "id": null
|
|
379
|
-
// }
|
|
380
|
-
//
|
|
381
|
-
const candles = this.safeValue2(message, 'params', 'result', []);
|
|
382
|
-
const messageHash = 'ohlcv';
|
|
383
|
-
const id = this.safeString(message, 'id');
|
|
384
|
-
const ohlcvs = this.parseOHLCVs(candles);
|
|
385
|
-
if (id !== undefined) {
|
|
386
|
-
// spot subscription response
|
|
387
|
-
client.resolve(ohlcvs, messageHash);
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
const keys = Object.keys(this.ohlcvs);
|
|
391
|
-
const keysLength = keys.length;
|
|
392
|
-
if (keysLength === 0) {
|
|
393
|
-
this.ohlcvs['unknown'] = {};
|
|
394
|
-
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
395
|
-
const stored = new ArrayCacheByTimestamp(limit);
|
|
396
|
-
this.ohlcvs['unknown']['unknown'] = stored;
|
|
397
|
-
}
|
|
398
|
-
const ohlcv = this.ohlcvs['unknown']['unknown'];
|
|
399
|
-
for (let i = 0; i < ohlcvs.length; i++) {
|
|
400
|
-
const candle = ohlcvs[i];
|
|
401
|
-
ohlcv.append(candle);
|
|
402
|
-
}
|
|
403
|
-
client.resolve(ohlcv, messageHash);
|
|
404
|
-
}
|
|
405
618
|
async watchTicker(symbol, params = {}) {
|
|
406
619
|
/**
|
|
407
620
|
* @method
|
|
408
621
|
* @name coinex#watchTicker
|
|
409
|
-
* @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket007_state_subscribe
|
|
410
622
|
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
623
|
+
* @see https://docs.coinex.com/api/v2/spot/market/ws/market
|
|
624
|
+
* @see https://docs.coinex.com/api/v2/futures/market/ws/market-state
|
|
411
625
|
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
412
626
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
413
627
|
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
414
628
|
*/
|
|
629
|
+
await this.loadMarkets();
|
|
630
|
+
const market = this.market(symbol);
|
|
415
631
|
const tickers = await this.watchTickers([symbol], params);
|
|
416
|
-
return
|
|
632
|
+
return tickers[market['symbol']];
|
|
417
633
|
}
|
|
418
634
|
async watchTickers(symbols = undefined, params = {}) {
|
|
419
635
|
/**
|
|
420
636
|
* @method
|
|
421
637
|
* @name coinex#watchTickers
|
|
422
|
-
* @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket007_state_subscribe
|
|
423
638
|
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
|
639
|
+
* @see https://docs.coinex.com/api/v2/spot/market/ws/market
|
|
640
|
+
* @see https://docs.coinex.com/api/v2/futures/market/ws/market-state
|
|
424
641
|
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
|
|
425
642
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
426
643
|
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
427
644
|
*/
|
|
428
645
|
await this.loadMarkets();
|
|
429
|
-
|
|
646
|
+
const marketIds = this.marketIds(symbols);
|
|
647
|
+
let market = undefined;
|
|
648
|
+
const messageHashes = [];
|
|
649
|
+
const symbolsDefined = (symbols !== undefined);
|
|
650
|
+
if (symbolsDefined) {
|
|
651
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
652
|
+
const symbol = symbols[i];
|
|
653
|
+
market = this.market(symbol);
|
|
654
|
+
messageHashes.push('tickers::' + market['symbol']);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
messageHashes.push('tickers');
|
|
659
|
+
}
|
|
430
660
|
let type = undefined;
|
|
431
|
-
[type, params] = this.handleMarketTypeAndParams('watchTickers',
|
|
661
|
+
[type, params] = this.handleMarketTypeAndParams('watchTickers', market, params);
|
|
432
662
|
const url = this.urls['api']['ws'][type];
|
|
433
|
-
|
|
434
|
-
if (symbols !== undefined) {
|
|
435
|
-
messageHash = 'tickers::' + symbols.join(',');
|
|
436
|
-
}
|
|
663
|
+
const subscriptionHashes = ['all@ticker'];
|
|
437
664
|
const subscribe = {
|
|
438
665
|
'method': 'state.subscribe',
|
|
666
|
+
'params': { 'market_list': marketIds },
|
|
439
667
|
'id': this.requestId(),
|
|
440
|
-
'params': [],
|
|
441
668
|
};
|
|
442
|
-
const
|
|
443
|
-
const newTickers = await this.watch(url, messageHash, request, messageHash);
|
|
669
|
+
const result = await this.watchMultiple(url, messageHashes, this.deepExtend(subscribe, params), subscriptionHashes);
|
|
444
670
|
if (this.newUpdates) {
|
|
445
|
-
return
|
|
671
|
+
return result;
|
|
446
672
|
}
|
|
447
673
|
return this.filterByArray(this.tickers, 'symbol', symbols);
|
|
448
674
|
}
|
|
@@ -450,179 +676,139 @@ export default class coinex extends coinexRest {
|
|
|
450
676
|
/**
|
|
451
677
|
* @method
|
|
452
678
|
* @name coinex#watchTrades
|
|
453
|
-
* @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket012_deal_subcribe
|
|
454
|
-
* @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures002_websocket019_deal_subcribe
|
|
455
679
|
* @description get the list of most recent trades for a particular symbol
|
|
680
|
+
* @see https://docs.coinex.com/api/v2/spot/market/ws/market-deals
|
|
681
|
+
* @see https://docs.coinex.com/api/v2/futures/market/ws/market-deals
|
|
456
682
|
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
457
683
|
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
458
684
|
* @param {int} [limit] the maximum amount of trades to fetch
|
|
459
685
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
460
686
|
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
461
687
|
*/
|
|
688
|
+
params['callerMethodName'] = 'watchTrades';
|
|
689
|
+
return await this.watchTradesForSymbols([symbol], since, limit, params);
|
|
690
|
+
}
|
|
691
|
+
async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
|
|
692
|
+
/**
|
|
693
|
+
* @method
|
|
694
|
+
* @name coinex#watchTradesForSymbols
|
|
695
|
+
* @description watch the most recent trades for a list of symbols
|
|
696
|
+
* @see https://docs.coinex.com/api/v2/spot/market/ws/market-deals
|
|
697
|
+
* @see https://docs.coinex.com/api/v2/futures/market/ws/market-deals
|
|
698
|
+
* @param {string[]} symbols unified symbols of the markets to fetch trades for
|
|
699
|
+
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
700
|
+
* @param {int} [limit] the maximum amount of trades to fetch
|
|
701
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
702
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
703
|
+
*/
|
|
462
704
|
await this.loadMarkets();
|
|
463
|
-
const
|
|
705
|
+
const subscribedSymbols = [];
|
|
706
|
+
const messageHashes = [];
|
|
707
|
+
let market = undefined;
|
|
708
|
+
let callerMethodName = undefined;
|
|
709
|
+
[callerMethodName, params] = this.handleParamString(params, 'callerMethodName', 'watchTradesForSymbols');
|
|
710
|
+
const symbolsDefined = (symbols !== undefined);
|
|
711
|
+
if (symbolsDefined) {
|
|
712
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
713
|
+
const symbol = symbols[i];
|
|
714
|
+
market = this.market(symbol);
|
|
715
|
+
subscribedSymbols.push(market['id']);
|
|
716
|
+
messageHashes.push('trades:' + market['symbol']);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
messageHashes.push('trades');
|
|
721
|
+
}
|
|
464
722
|
let type = undefined;
|
|
465
|
-
[type, params] = this.handleMarketTypeAndParams(
|
|
723
|
+
[type, params] = this.handleMarketTypeAndParams(callerMethodName, market, params);
|
|
466
724
|
const url = this.urls['api']['ws'][type];
|
|
467
|
-
const
|
|
468
|
-
const
|
|
469
|
-
const subscribedSymbols = this.safeValue(this.options, 'watchTradesSubscriptions', []);
|
|
470
|
-
subscribedSymbols.push(market['id']);
|
|
471
|
-
const message = {
|
|
725
|
+
const subscriptionHashes = ['trades'];
|
|
726
|
+
const subscribe = {
|
|
472
727
|
'method': 'deals.subscribe',
|
|
473
|
-
'params': subscribedSymbols,
|
|
728
|
+
'params': { 'market_list': subscribedSymbols },
|
|
474
729
|
'id': this.requestId(),
|
|
475
730
|
};
|
|
476
|
-
this.
|
|
477
|
-
|
|
478
|
-
|
|
731
|
+
const trades = await this.watchMultiple(url, messageHashes, this.deepExtend(subscribe, params), subscriptionHashes);
|
|
732
|
+
if (this.newUpdates) {
|
|
733
|
+
return trades;
|
|
734
|
+
}
|
|
479
735
|
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
480
736
|
}
|
|
481
|
-
async
|
|
737
|
+
async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
|
|
482
738
|
/**
|
|
483
739
|
* @method
|
|
484
|
-
* @name coinex#
|
|
485
|
-
* @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot004_websocket017_depth_subscribe_multi
|
|
486
|
-
* @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures002_websocket011_depth_subscribe_multi
|
|
740
|
+
* @name coinex#watchOrderBookForSymbols
|
|
487
741
|
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
488
|
-
* @
|
|
742
|
+
* @see https://docs.coinex.com/api/v2/spot/market/ws/market-depth
|
|
743
|
+
* @see https://docs.coinex.com/api/v2/futures/market/ws/market-depth
|
|
744
|
+
* @param {string[]} symbols unified array of symbols
|
|
489
745
|
* @param {int} [limit] the maximum amount of order book entries to return
|
|
490
746
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
491
747
|
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
492
748
|
*/
|
|
493
749
|
await this.loadMarkets();
|
|
494
|
-
const
|
|
495
|
-
|
|
750
|
+
const watchOrderBookSubscriptions = {};
|
|
751
|
+
const messageHashes = [];
|
|
752
|
+
let market = undefined;
|
|
496
753
|
let type = undefined;
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
const
|
|
501
|
-
const
|
|
502
|
-
const limits = this.safeValue(options, 'limits', []);
|
|
754
|
+
let callerMethodName = undefined;
|
|
755
|
+
[callerMethodName, params] = this.handleParamString(params, 'callerMethodName', 'watchOrderBookForSymbols');
|
|
756
|
+
[type, params] = this.handleMarketTypeAndParams(callerMethodName, undefined, params);
|
|
757
|
+
const options = this.safeDict(this.options, 'watchOrderBook', {});
|
|
758
|
+
const limits = this.safeList(options, 'limits', []);
|
|
503
759
|
if (limit === undefined) {
|
|
504
|
-
limit = this.
|
|
760
|
+
limit = this.safeInteger(options, 'defaultLimit', 50);
|
|
505
761
|
}
|
|
506
762
|
if (!this.inArray(limit, limits)) {
|
|
507
|
-
throw new NotSupported(this.id + '
|
|
763
|
+
throw new NotSupported(this.id + ' watchOrderBookForSymbols() limit must be one of ' + limits.join(', '));
|
|
508
764
|
}
|
|
509
765
|
const defaultAggregation = this.safeString(options, 'defaultAggregation', '0');
|
|
510
|
-
const aggregations = this.
|
|
766
|
+
const aggregations = this.safeList(options, 'aggregations', []);
|
|
511
767
|
const aggregation = this.safeString(params, 'aggregation', defaultAggregation);
|
|
512
768
|
if (!this.inArray(aggregation, aggregations)) {
|
|
513
|
-
throw new NotSupported(this.id + '
|
|
769
|
+
throw new NotSupported(this.id + ' watchOrderBookForSymbols() aggregation must be one of ' + aggregations.join(', '));
|
|
514
770
|
}
|
|
515
771
|
params = this.omit(params, 'aggregation');
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const subscriptionHash = this.hash(this.encode(this.json(watchOrderBookSubscriptions)), sha256);
|
|
525
|
-
const request = this.deepExtend(subscribe, params);
|
|
526
|
-
const orderbook = await this.watch(url, messageHash, request, subscriptionHash, request);
|
|
527
|
-
return orderbook.limit();
|
|
528
|
-
}
|
|
529
|
-
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
530
|
-
/**
|
|
531
|
-
* @method
|
|
532
|
-
* @name coinex#watchOHLCV
|
|
533
|
-
* @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures002_websocket023_kline_subscribe
|
|
534
|
-
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
535
|
-
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
536
|
-
* @param {string} timeframe the length of time each candle represents
|
|
537
|
-
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
538
|
-
* @param {int} [limit] the maximum amount of candles to fetch
|
|
539
|
-
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
540
|
-
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
541
|
-
*/
|
|
542
|
-
await this.loadMarkets();
|
|
543
|
-
const market = this.market(symbol);
|
|
544
|
-
symbol = market['symbol'];
|
|
545
|
-
let type = undefined;
|
|
546
|
-
[type, params] = this.handleMarketTypeAndParams('watchOHLCV', market, params);
|
|
547
|
-
if (type !== 'swap') {
|
|
548
|
-
throw new NotSupported(this.id + ' watchOHLCV() is only supported for swap markets. Try using fetchOHLCV () instead');
|
|
772
|
+
const symbolsDefined = (symbols !== undefined);
|
|
773
|
+
if (symbolsDefined) {
|
|
774
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
775
|
+
const symbol = symbols[i];
|
|
776
|
+
market = this.market(symbol);
|
|
777
|
+
messageHashes.push('orderbook:' + market['symbol']);
|
|
778
|
+
watchOrderBookSubscriptions[symbol] = [market['id'], limit, aggregation, true];
|
|
779
|
+
}
|
|
549
780
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
const watchOHLCVWarning = this.safeBool(this.options, 'watchOHLCVWarning', true);
|
|
553
|
-
const client = this.safeValue(this.clients, url, {});
|
|
554
|
-
const clientSub = this.safeValue(client, 'subscriptions', {});
|
|
555
|
-
const existingSubscription = this.safeValue(clientSub, messageHash);
|
|
556
|
-
const subSymbol = this.safeString(existingSubscription, 'symbol');
|
|
557
|
-
const subTimeframe = this.safeString(existingSubscription, 'timeframe');
|
|
558
|
-
// due to nature of coinex response can only watch one symbol at a time
|
|
559
|
-
if (watchOHLCVWarning && existingSubscription !== undefined && (subSymbol !== symbol || subTimeframe !== timeframe)) {
|
|
560
|
-
throw new ExchangeError(this.id + ' watchOHLCV() can only watch one symbol and timeframe at a time. To supress this warning set watchOHLCVWarning to false in options');
|
|
781
|
+
else {
|
|
782
|
+
messageHashes.push('orderbook');
|
|
561
783
|
}
|
|
562
|
-
const
|
|
784
|
+
const marketList = Object.values(watchOrderBookSubscriptions);
|
|
563
785
|
const subscribe = {
|
|
564
|
-
'method': '
|
|
786
|
+
'method': 'depth.subscribe',
|
|
787
|
+
'params': { 'market_list': marketList },
|
|
565
788
|
'id': this.requestId(),
|
|
566
|
-
'params': [
|
|
567
|
-
market['id'],
|
|
568
|
-
this.safeInteger(timeframes, timeframe),
|
|
569
|
-
],
|
|
570
789
|
};
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
};
|
|
575
|
-
const request = this.deepExtend(subscribe, params);
|
|
576
|
-
const ohlcvs = await this.watch(url, messageHash, request, messageHash, subscription);
|
|
790
|
+
const subscriptionHashes = this.hash(this.encode(this.json(watchOrderBookSubscriptions)), sha256);
|
|
791
|
+
const url = this.urls['api']['ws'][type];
|
|
792
|
+
const orderbooks = await this.watchMultiple(url, messageHashes, this.deepExtend(subscribe, params), subscriptionHashes);
|
|
577
793
|
if (this.newUpdates) {
|
|
578
|
-
|
|
794
|
+
return orderbooks;
|
|
579
795
|
}
|
|
580
|
-
return
|
|
796
|
+
return orderbooks.limit();
|
|
581
797
|
}
|
|
582
|
-
async
|
|
798
|
+
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
583
799
|
/**
|
|
584
800
|
* @method
|
|
585
|
-
* @name coinex#
|
|
586
|
-
* @
|
|
587
|
-
* @
|
|
588
|
-
* @
|
|
589
|
-
* @param {string}
|
|
590
|
-
* @param {int
|
|
591
|
-
* @param {
|
|
592
|
-
* @
|
|
593
|
-
* @param {int|undefined} params.end the end time for spot markets, this.seconds () is set as default
|
|
594
|
-
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
801
|
+
* @name coinex#watchOrderBook
|
|
802
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
803
|
+
* @see https://docs.coinex.com/api/v2/spot/market/ws/market-depth
|
|
804
|
+
* @see https://docs.coinex.com/api/v2/futures/market/ws/market-depth
|
|
805
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
806
|
+
* @param {int} [limit] the maximum amount of order book entries to return
|
|
807
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
808
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
595
809
|
*/
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
const [type, query] = this.handleMarketTypeAndParams('fetchOHLCV', market, params);
|
|
599
|
-
const url = this.urls['api']['ws'][type];
|
|
600
|
-
symbol = market['symbol'];
|
|
601
|
-
const messageHash = 'ohlcv';
|
|
602
|
-
const timeframes = this.safeValue(this.options, 'timeframes', {});
|
|
603
|
-
timeframe = this.safeString(timeframes, timeframe, timeframe);
|
|
604
|
-
if (since === undefined) {
|
|
605
|
-
since = 1640995200; // January 1, 2022
|
|
606
|
-
}
|
|
607
|
-
const id = this.requestId();
|
|
608
|
-
const subscribe = {
|
|
609
|
-
'method': 'kline.query',
|
|
610
|
-
'params': [
|
|
611
|
-
market['id'],
|
|
612
|
-
this.parseToInt(since / 1000),
|
|
613
|
-
this.safeInteger(params, 'end', this.seconds()),
|
|
614
|
-
this.parseToInt(timeframe),
|
|
615
|
-
],
|
|
616
|
-
'id': id,
|
|
617
|
-
};
|
|
618
|
-
const subscription = {
|
|
619
|
-
'id': id,
|
|
620
|
-
'future': messageHash,
|
|
621
|
-
};
|
|
622
|
-
const subscriptionHash = id;
|
|
623
|
-
const request = this.deepExtend(subscribe, query);
|
|
624
|
-
const ohlcvs = await this.watch(url, messageHash, request, subscriptionHash, subscription);
|
|
625
|
-
return this.filterBySinceLimit(ohlcvs, since, limit, 0);
|
|
810
|
+
params['callerMethodName'] = 'watchOrderBook';
|
|
811
|
+
return await this.watchOrderBookForSymbols([symbol], limit, params);
|
|
626
812
|
}
|
|
627
813
|
handleDelta(bookside, delta) {
|
|
628
814
|
const bidAsk = this.parseBidAsk(delta, 0, 1);
|
|
@@ -637,52 +823,54 @@ export default class coinex extends coinexRest {
|
|
|
637
823
|
//
|
|
638
824
|
// {
|
|
639
825
|
// "method": "depth.update",
|
|
640
|
-
// "
|
|
641
|
-
//
|
|
642
|
-
//
|
|
826
|
+
// "data": {
|
|
827
|
+
// "market": "BTCUSDT",
|
|
828
|
+
// "is_full": true,
|
|
829
|
+
// "depth": {
|
|
643
830
|
// "asks": [
|
|
644
|
-
// [
|
|
645
|
-
//
|
|
831
|
+
// [
|
|
832
|
+
// "30740.00",
|
|
833
|
+
// "0.31763545"
|
|
834
|
+
// ],
|
|
646
835
|
// ],
|
|
647
836
|
// "bids": [
|
|
648
|
-
// [
|
|
649
|
-
//
|
|
837
|
+
// [
|
|
838
|
+
// "30736.00",
|
|
839
|
+
// "0.04857373"
|
|
840
|
+
// ],
|
|
650
841
|
// ],
|
|
651
|
-
// "last": "
|
|
652
|
-
// "
|
|
653
|
-
// "checksum":
|
|
654
|
-
// }
|
|
655
|
-
//
|
|
656
|
-
// ],
|
|
842
|
+
// "last": "30746.28",
|
|
843
|
+
// "updated_at": 1689152421692,
|
|
844
|
+
// "checksum": 2578768879
|
|
845
|
+
// }
|
|
846
|
+
// },
|
|
657
847
|
// "id": null
|
|
658
848
|
// }
|
|
659
849
|
//
|
|
660
|
-
const
|
|
661
|
-
const
|
|
662
|
-
const
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
const marketId = this.safeString(params, 2);
|
|
666
|
-
const market = this.safeMarket(marketId, undefined, undefined, marketType);
|
|
850
|
+
const defaultType = this.safeString(this.options, 'defaultType');
|
|
851
|
+
const data = this.safeDict(message, 'data', {});
|
|
852
|
+
const depth = this.safeDict(data, 'depth', {});
|
|
853
|
+
const marketId = this.safeString(data, 'market');
|
|
854
|
+
const market = this.safeMarket(marketId, undefined, undefined, defaultType);
|
|
667
855
|
const symbol = market['symbol'];
|
|
668
856
|
const name = 'orderbook';
|
|
669
857
|
const messageHash = name + ':' + symbol;
|
|
670
|
-
const timestamp = this.safeInteger(
|
|
858
|
+
const timestamp = this.safeInteger(depth, 'updated_at');
|
|
671
859
|
const currentOrderBook = this.safeValue(this.orderbooks, symbol);
|
|
860
|
+
const fullOrderBook = this.safeBool(data, 'is_full', false);
|
|
672
861
|
if (fullOrderBook) {
|
|
673
|
-
const snapshot = this.parseOrderBook(
|
|
862
|
+
const snapshot = this.parseOrderBook(depth, symbol, timestamp);
|
|
674
863
|
if (currentOrderBook === undefined) {
|
|
675
|
-
|
|
676
|
-
this.orderbooks[symbol] = orderbook;
|
|
864
|
+
this.orderbooks[symbol] = this.orderBook(snapshot);
|
|
677
865
|
}
|
|
678
866
|
else {
|
|
679
|
-
orderbook = this.orderbooks[symbol];
|
|
867
|
+
const orderbook = this.orderbooks[symbol];
|
|
680
868
|
orderbook.reset(snapshot);
|
|
681
869
|
}
|
|
682
870
|
}
|
|
683
871
|
else {
|
|
684
|
-
const asks = this.
|
|
685
|
-
const bids = this.
|
|
872
|
+
const asks = this.safeList(depth, 'asks', []);
|
|
873
|
+
const bids = this.safeList(depth, 'bids', []);
|
|
686
874
|
this.handleDeltas(currentOrderBook['asks'], asks);
|
|
687
875
|
this.handleDeltas(currentOrderBook['bids'], bids);
|
|
688
876
|
currentOrderBook['nonce'] = timestamp;
|
|
@@ -694,26 +882,59 @@ export default class coinex extends coinexRest {
|
|
|
694
882
|
client.resolve(this.orderbooks[symbol], messageHash);
|
|
695
883
|
}
|
|
696
884
|
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
885
|
+
/**
|
|
886
|
+
* @method
|
|
887
|
+
* @name coinex#watchOrders
|
|
888
|
+
* @description watches information on multiple orders made by the user
|
|
889
|
+
* @see https://docs.coinex.com/api/v2/spot/order/ws/user-order
|
|
890
|
+
* @see https://docs.coinex.com/api/v2/futures/order/ws/user-order
|
|
891
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
892
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
893
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
894
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
895
|
+
* @param {bool} [params.trigger] if the orders to watch are trigger orders or not
|
|
896
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
897
|
+
*/
|
|
697
898
|
await this.loadMarkets();
|
|
698
|
-
|
|
899
|
+
const stop = this.safeBool2(params, 'trigger', 'stop');
|
|
900
|
+
params = this.omit(params, ['trigger', 'stop']);
|
|
699
901
|
let messageHash = 'orders';
|
|
700
902
|
let market = undefined;
|
|
701
|
-
|
|
702
|
-
const message = {
|
|
703
|
-
'method': 'order.subscribe',
|
|
704
|
-
'id': this.requestId(),
|
|
705
|
-
};
|
|
903
|
+
let marketList = undefined;
|
|
706
904
|
if (symbol !== undefined) {
|
|
707
905
|
market = this.market(symbol);
|
|
708
906
|
symbol = market['symbol'];
|
|
709
|
-
|
|
907
|
+
}
|
|
908
|
+
let type = undefined;
|
|
909
|
+
[type, params] = this.handleMarketTypeAndParams('watchOrders', market, params, 'spot');
|
|
910
|
+
await this.authenticate(type);
|
|
911
|
+
if (symbol !== undefined) {
|
|
912
|
+
marketList = [market['id']];
|
|
710
913
|
messageHash += ':' + symbol;
|
|
711
914
|
}
|
|
712
915
|
else {
|
|
713
|
-
|
|
916
|
+
marketList = [];
|
|
917
|
+
if (type === 'spot') {
|
|
918
|
+
messageHash += ':spot';
|
|
919
|
+
}
|
|
920
|
+
else {
|
|
921
|
+
messageHash += ':swap';
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
let method = undefined;
|
|
925
|
+
if (stop) {
|
|
926
|
+
method = 'stop.subscribe';
|
|
927
|
+
}
|
|
928
|
+
else {
|
|
929
|
+
method = 'order.subscribe';
|
|
714
930
|
}
|
|
931
|
+
const message = {
|
|
932
|
+
'method': method,
|
|
933
|
+
'params': { 'market_list': marketList },
|
|
934
|
+
'id': this.requestId(),
|
|
935
|
+
};
|
|
715
936
|
const url = this.urls['api']['ws'][type];
|
|
716
|
-
const request = this.deepExtend(message,
|
|
937
|
+
const request = this.deepExtend(message, params);
|
|
717
938
|
const orders = await this.watch(url, messageHash, request, messageHash, request);
|
|
718
939
|
if (this.newUpdates) {
|
|
719
940
|
limit = orders.getLimit(symbol, limit);
|
|
@@ -722,94 +943,126 @@ export default class coinex extends coinexRest {
|
|
|
722
943
|
}
|
|
723
944
|
handleOrders(client, message) {
|
|
724
945
|
//
|
|
725
|
-
//
|
|
946
|
+
// spot
|
|
726
947
|
//
|
|
727
|
-
//
|
|
728
|
-
//
|
|
729
|
-
//
|
|
730
|
-
//
|
|
731
|
-
//
|
|
732
|
-
//
|
|
733
|
-
//
|
|
734
|
-
//
|
|
735
|
-
//
|
|
736
|
-
//
|
|
737
|
-
//
|
|
738
|
-
//
|
|
739
|
-
//
|
|
740
|
-
//
|
|
741
|
-
//
|
|
742
|
-
//
|
|
743
|
-
//
|
|
744
|
-
//
|
|
745
|
-
//
|
|
746
|
-
//
|
|
747
|
-
//
|
|
748
|
-
//
|
|
749
|
-
//
|
|
750
|
-
//
|
|
751
|
-
//
|
|
752
|
-
//
|
|
753
|
-
//
|
|
754
|
-
//
|
|
755
|
-
// "last_deal_price": "0",
|
|
756
|
-
// "last_deal_time": 0,
|
|
757
|
-
// "last_deal_id": 0,
|
|
758
|
-
// "last_role": 0,
|
|
759
|
-
// "fee_asset": null,
|
|
760
|
-
// "stop_id": 0
|
|
761
|
-
// }
|
|
762
|
-
// ],
|
|
763
|
-
// "id": null
|
|
764
|
-
// }
|
|
948
|
+
// {
|
|
949
|
+
// "method": "order.update",
|
|
950
|
+
// "data": {
|
|
951
|
+
// "event": "put",
|
|
952
|
+
// "order": {
|
|
953
|
+
// "order_id": 12750,
|
|
954
|
+
// "market": "BTCUSDT",
|
|
955
|
+
// "margin_market": "BTCUSDT",
|
|
956
|
+
// "type": "limit",
|
|
957
|
+
// "side": "buy",
|
|
958
|
+
// "price": "5999.00",
|
|
959
|
+
// "amount": "1.50000000",
|
|
960
|
+
// "unfill_amount": "1.50000000",
|
|
961
|
+
// "fill_value": "1.50000000",
|
|
962
|
+
// "taker_fee_rate": "0.0001",
|
|
963
|
+
// "maker_fee_rate": "0.0001",
|
|
964
|
+
// "base_ccy_fee": "0.0001",
|
|
965
|
+
// "quote_ccy_fee": "0.0001",
|
|
966
|
+
// "discount_ccy_fee": "0.0001",
|
|
967
|
+
// "last_fill_amount": "0",
|
|
968
|
+
// "last_fill_price": "0",
|
|
969
|
+
// "client_id": "buy1_1234",
|
|
970
|
+
// "created_at": 1689152421692,
|
|
971
|
+
// "updated_at": 1689152421692,
|
|
972
|
+
// }
|
|
973
|
+
// },
|
|
974
|
+
// "id": null
|
|
975
|
+
// }
|
|
765
976
|
//
|
|
766
|
-
//
|
|
977
|
+
// spot stop
|
|
978
|
+
//
|
|
979
|
+
// {
|
|
980
|
+
// "method": "stop.update",
|
|
981
|
+
// "data": {
|
|
982
|
+
// "event": 1,
|
|
983
|
+
// "stop": {
|
|
984
|
+
// "stop_id": 102067022299,
|
|
985
|
+
// "market": "BTCUSDT",
|
|
986
|
+
// "margin_market": "BTCUSDT",
|
|
987
|
+
// "type": "limit",
|
|
988
|
+
// "side": "buy",
|
|
989
|
+
// "price": "20000.00",
|
|
990
|
+
// "amount": "0.10000000",
|
|
991
|
+
// "trigger_price": "20000.00",
|
|
992
|
+
// "trigger_direction": "lower",
|
|
993
|
+
// "taker_fee_rate": "0.0016",
|
|
994
|
+
// "maker_fee_rate": "0.0016",
|
|
995
|
+
// "status": "active_success",
|
|
996
|
+
// "client_id": "",
|
|
997
|
+
// "created_at": 1689152996689,
|
|
998
|
+
// "updated_at": 1689152996689,
|
|
999
|
+
// }
|
|
1000
|
+
// },
|
|
1001
|
+
// "id": null
|
|
1002
|
+
// }
|
|
1003
|
+
//
|
|
1004
|
+
// swap
|
|
1005
|
+
//
|
|
1006
|
+
// {
|
|
1007
|
+
// "method": "order.update",
|
|
1008
|
+
// "data": {
|
|
1009
|
+
// "event": "put",
|
|
1010
|
+
// "order": {
|
|
1011
|
+
// "order_id": 98388656341,
|
|
1012
|
+
// "stop_id": 0,
|
|
1013
|
+
// "market": "BTCUSDT",
|
|
1014
|
+
// "side": "buy",
|
|
1015
|
+
// "type": "limit",
|
|
1016
|
+
// "amount": "0.0010",
|
|
1017
|
+
// "price": "50000.00",
|
|
1018
|
+
// "unfilled_amount": "0.0010",
|
|
1019
|
+
// "filled_amount": "0",
|
|
1020
|
+
// "filled_value": "0",
|
|
1021
|
+
// "fee": "0",
|
|
1022
|
+
// "fee_ccy": "USDT",
|
|
1023
|
+
// "taker_fee_rate": "0.00046",
|
|
1024
|
+
// "maker_fee_rate": "0.00000000000000000000",
|
|
1025
|
+
// "client_id": "",
|
|
1026
|
+
// "last_filled_amount": "0.0010",
|
|
1027
|
+
// "last_filled_price": "30721.35",
|
|
1028
|
+
// "created_at": 1689145715129,
|
|
1029
|
+
// "updated_at": 1689145715129
|
|
1030
|
+
// }
|
|
1031
|
+
// },
|
|
1032
|
+
// "id": null
|
|
1033
|
+
// }
|
|
1034
|
+
//
|
|
1035
|
+
// swap stop
|
|
1036
|
+
//
|
|
1037
|
+
// {
|
|
1038
|
+
// "method": "stop.update",
|
|
1039
|
+
// "data": {
|
|
1040
|
+
// "event": "put",
|
|
1041
|
+
// "stop": {
|
|
1042
|
+
// "stop_id": 98389557871,
|
|
1043
|
+
// "market": "BTCUSDT",
|
|
1044
|
+
// "side": "sell",
|
|
1045
|
+
// "type": "limit",
|
|
1046
|
+
// "price": "20000.00",
|
|
1047
|
+
// "amount": "0.0100",
|
|
1048
|
+
// "trigger_price": "20000.00",
|
|
1049
|
+
// "trigger_direction": "higer",
|
|
1050
|
+
// "trigger_price_type": "index_price",
|
|
1051
|
+
// "taker_fee_rate": "0.00046",
|
|
1052
|
+
// "maker_fee_rate": "0.00026",
|
|
1053
|
+
// "client_id": "",
|
|
1054
|
+
// "created_at": 1689146382674,
|
|
1055
|
+
// "updated_at": 1689146382674
|
|
1056
|
+
// }
|
|
1057
|
+
// },
|
|
1058
|
+
// "id": null
|
|
1059
|
+
// }
|
|
767
1060
|
//
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
// "params": [
|
|
771
|
-
// 1,
|
|
772
|
-
// {
|
|
773
|
-
// "order_id": 23423462821,
|
|
774
|
-
// "position_id": 0,
|
|
775
|
-
// "stop_id": 0,
|
|
776
|
-
// "market": "BTCUSDT",
|
|
777
|
-
// "type": 1,
|
|
778
|
-
// "side": 2,
|
|
779
|
-
// "target": 0,
|
|
780
|
-
// "effect_type": 1,
|
|
781
|
-
// "user_id": 1849116,
|
|
782
|
-
// "create_time": 1653961509.25049,
|
|
783
|
-
// "update_time": 1653961509.25049,
|
|
784
|
-
// "source": "web",
|
|
785
|
-
// "price": "1.00",
|
|
786
|
-
// "amount": "1.0000",
|
|
787
|
-
// "taker_fee": "0.00050",
|
|
788
|
-
// "maker_fee": "0.00030",
|
|
789
|
-
// "left": "1.0000",
|
|
790
|
-
// "deal_stock": "0.00000000000000000000",
|
|
791
|
-
// "deal_fee": "0.00000000000000000000",
|
|
792
|
-
// "deal_profit": "0.00000000000000000000",
|
|
793
|
-
// "last_deal_amount": "0.00000000000000000000",
|
|
794
|
-
// "last_deal_price": "0.00000000000000000000",
|
|
795
|
-
// "last_deal_time": 0,
|
|
796
|
-
// "last_deal_id": 0,
|
|
797
|
-
// "last_deal_type": 0,
|
|
798
|
-
// "last_deal_role": 0,
|
|
799
|
-
// "client_id": '',
|
|
800
|
-
// "fee_asset": '',
|
|
801
|
-
// "fee_discount": "0.00000000000000000000",
|
|
802
|
-
// "deal_asset_fee": "0.00000000000000000000",
|
|
803
|
-
// "leverage": "3",
|
|
804
|
-
// "position_type": 2
|
|
805
|
-
// }
|
|
806
|
-
// ],
|
|
807
|
-
// "id": null
|
|
808
|
-
// }
|
|
809
|
-
//
|
|
810
|
-
const params = this.safeValue(message, 'params', []);
|
|
811
|
-
const order = this.safeValue(params, 1, {});
|
|
1061
|
+
const data = this.safeDict(message, 'data', {});
|
|
1062
|
+
const order = this.safeDict2(data, 'order', 'stop', {});
|
|
812
1063
|
const parsedOrder = this.parseWsOrder(order);
|
|
1064
|
+
const symbol = parsedOrder['symbol'];
|
|
1065
|
+
const market = this.market(symbol);
|
|
813
1066
|
if (this.orders === undefined) {
|
|
814
1067
|
const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
|
|
815
1068
|
this.orders = new ArrayCacheBySymbolById(limit);
|
|
@@ -817,138 +1070,110 @@ export default class coinex extends coinexRest {
|
|
|
817
1070
|
const orders = this.orders;
|
|
818
1071
|
orders.append(parsedOrder);
|
|
819
1072
|
let messageHash = 'orders';
|
|
820
|
-
|
|
821
|
-
|
|
1073
|
+
const messageWithType = messageHash + ':' + market['type'];
|
|
1074
|
+
client.resolve(this.orders, messageWithType);
|
|
1075
|
+
messageHash += ':' + symbol;
|
|
822
1076
|
client.resolve(this.orders, messageHash);
|
|
823
1077
|
}
|
|
824
1078
|
parseWsOrder(order, market = undefined) {
|
|
825
1079
|
//
|
|
826
|
-
//
|
|
1080
|
+
// spot
|
|
827
1081
|
//
|
|
828
|
-
//
|
|
829
|
-
//
|
|
830
|
-
//
|
|
831
|
-
//
|
|
832
|
-
//
|
|
833
|
-
//
|
|
834
|
-
//
|
|
835
|
-
//
|
|
836
|
-
//
|
|
837
|
-
//
|
|
838
|
-
//
|
|
839
|
-
//
|
|
840
|
-
//
|
|
841
|
-
//
|
|
842
|
-
//
|
|
843
|
-
//
|
|
844
|
-
//
|
|
845
|
-
//
|
|
846
|
-
//
|
|
847
|
-
//
|
|
848
|
-
//
|
|
849
|
-
// "asset_fee": "0",
|
|
850
|
-
// "fee_discount": "1",
|
|
851
|
-
// "last_deal_amount": "0",
|
|
852
|
-
// "last_deal_price": "0",
|
|
853
|
-
// "last_deal_time": 0,
|
|
854
|
-
// "last_deal_id": 0,
|
|
855
|
-
// "last_role": 0,
|
|
856
|
-
// "fee_asset": null,
|
|
857
|
-
// "stop_id": 0
|
|
858
|
-
// }
|
|
1082
|
+
// {
|
|
1083
|
+
// "order_id": 12750,
|
|
1084
|
+
// "market": "BTCUSDT",
|
|
1085
|
+
// "margin_market": "BTCUSDT",
|
|
1086
|
+
// "type": "limit",
|
|
1087
|
+
// "side": "buy",
|
|
1088
|
+
// "price": "5999.00",
|
|
1089
|
+
// "amount": "1.50000000",
|
|
1090
|
+
// "unfill_amount": "1.50000000",
|
|
1091
|
+
// "fill_value": "1.50000000",
|
|
1092
|
+
// "taker_fee_rate": "0.0001",
|
|
1093
|
+
// "maker_fee_rate": "0.0001",
|
|
1094
|
+
// "base_ccy_fee": "0.0001",
|
|
1095
|
+
// "quote_ccy_fee": "0.0001",
|
|
1096
|
+
// "discount_ccy_fee": "0.0001",
|
|
1097
|
+
// "last_fill_amount": "0",
|
|
1098
|
+
// "last_fill_price": "0",
|
|
1099
|
+
// "client_id": "buy1_1234",
|
|
1100
|
+
// "created_at": 1689152421692,
|
|
1101
|
+
// "updated_at": 1689152421692,
|
|
1102
|
+
// }
|
|
859
1103
|
//
|
|
860
|
-
//
|
|
1104
|
+
// spot stop
|
|
861
1105
|
//
|
|
862
|
-
//
|
|
863
|
-
//
|
|
864
|
-
//
|
|
865
|
-
//
|
|
866
|
-
//
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
//
|
|
870
|
-
//
|
|
871
|
-
//
|
|
872
|
-
//
|
|
873
|
-
//
|
|
874
|
-
//
|
|
875
|
-
//
|
|
876
|
-
//
|
|
877
|
-
//
|
|
878
|
-
//
|
|
879
|
-
//
|
|
880
|
-
//
|
|
881
|
-
//
|
|
882
|
-
//
|
|
883
|
-
//
|
|
884
|
-
//
|
|
885
|
-
//
|
|
886
|
-
//
|
|
887
|
-
//
|
|
888
|
-
//
|
|
889
|
-
//
|
|
890
|
-
//
|
|
891
|
-
//
|
|
892
|
-
//
|
|
893
|
-
//
|
|
894
|
-
//
|
|
895
|
-
//
|
|
896
|
-
//
|
|
897
|
-
//
|
|
898
|
-
//
|
|
899
|
-
//
|
|
900
|
-
//
|
|
901
|
-
//
|
|
902
|
-
//
|
|
903
|
-
//
|
|
904
|
-
//
|
|
905
|
-
//
|
|
906
|
-
//
|
|
907
|
-
//
|
|
908
|
-
//
|
|
909
|
-
//
|
|
910
|
-
//
|
|
911
|
-
//
|
|
912
|
-
//
|
|
913
|
-
//
|
|
914
|
-
//
|
|
915
|
-
//
|
|
916
|
-
//
|
|
917
|
-
//
|
|
918
|
-
//
|
|
919
|
-
//
|
|
920
|
-
//
|
|
921
|
-
//
|
|
922
|
-
|
|
1106
|
+
// {
|
|
1107
|
+
// "stop_id": 102067022299,
|
|
1108
|
+
// "market": "BTCUSDT",
|
|
1109
|
+
// "margin_market": "BTCUSDT",
|
|
1110
|
+
// "type": "limit",
|
|
1111
|
+
// "side": "buy",
|
|
1112
|
+
// "price": "20000.00",
|
|
1113
|
+
// "amount": "0.10000000",
|
|
1114
|
+
// "trigger_price": "20000.00",
|
|
1115
|
+
// "trigger_direction": "lower",
|
|
1116
|
+
// "taker_fee_rate": "0.0016",
|
|
1117
|
+
// "maker_fee_rate": "0.0016",
|
|
1118
|
+
// "status": "active_success",
|
|
1119
|
+
// "client_id": "",
|
|
1120
|
+
// "created_at": 1689152996689,
|
|
1121
|
+
// "updated_at": 1689152996689,
|
|
1122
|
+
// }
|
|
1123
|
+
//
|
|
1124
|
+
// swap
|
|
1125
|
+
//
|
|
1126
|
+
// {
|
|
1127
|
+
// "order_id": 98388656341,
|
|
1128
|
+
// "stop_id": 0,
|
|
1129
|
+
// "market": "BTCUSDT",
|
|
1130
|
+
// "side": "buy",
|
|
1131
|
+
// "type": "limit",
|
|
1132
|
+
// "amount": "0.0010",
|
|
1133
|
+
// "price": "50000.00",
|
|
1134
|
+
// "unfilled_amount": "0.0010",
|
|
1135
|
+
// "filled_amount": "0",
|
|
1136
|
+
// "filled_value": "0",
|
|
1137
|
+
// "fee": "0",
|
|
1138
|
+
// "fee_ccy": "USDT",
|
|
1139
|
+
// "taker_fee_rate": "0.00046",
|
|
1140
|
+
// "maker_fee_rate": "0.00000000000000000000",
|
|
1141
|
+
// "client_id": "",
|
|
1142
|
+
// "last_filled_amount": "0.0010",
|
|
1143
|
+
// "last_filled_price": "30721.35",
|
|
1144
|
+
// "created_at": 1689145715129,
|
|
1145
|
+
// "updated_at": 1689145715129
|
|
1146
|
+
// }
|
|
1147
|
+
//
|
|
1148
|
+
// swap stop
|
|
1149
|
+
//
|
|
1150
|
+
// {
|
|
1151
|
+
// "stop_id": 98389557871,
|
|
1152
|
+
// "market": "BTCUSDT",
|
|
1153
|
+
// "side": "sell",
|
|
1154
|
+
// "type": "limit",
|
|
1155
|
+
// "price": "20000.00",
|
|
1156
|
+
// "amount": "0.0100",
|
|
1157
|
+
// "trigger_price": "20000.00",
|
|
1158
|
+
// "trigger_direction": "higer",
|
|
1159
|
+
// "trigger_price_type": "index_price",
|
|
1160
|
+
// "taker_fee_rate": "0.00046",
|
|
1161
|
+
// "maker_fee_rate": "0.00026",
|
|
1162
|
+
// "client_id": "",
|
|
1163
|
+
// "created_at": 1689146382674,
|
|
1164
|
+
// "updated_at": 1689146382674
|
|
1165
|
+
// }
|
|
1166
|
+
//
|
|
1167
|
+
const timestamp = this.safeInteger(order, 'created_at');
|
|
923
1168
|
const marketId = this.safeString(order, 'market');
|
|
924
|
-
const typeCode = this.safeString(order, 'type');
|
|
925
|
-
const type = this.safeString({
|
|
926
|
-
'1': 'limit',
|
|
927
|
-
'2': 'market',
|
|
928
|
-
}, typeCode);
|
|
929
|
-
const sideCode = this.safeString(order, 'side');
|
|
930
|
-
const side = this.safeString({
|
|
931
|
-
'1': 'sell',
|
|
932
|
-
'2': 'buy',
|
|
933
|
-
}, sideCode);
|
|
934
|
-
const remaining = this.safeString(order, 'left');
|
|
935
|
-
const amount = this.safeString(order, 'amount');
|
|
936
1169
|
const status = this.safeString(order, 'status');
|
|
937
|
-
const
|
|
1170
|
+
const isSpot = ('margin_market' in order);
|
|
1171
|
+
const defaultType = isSpot ? 'spot' : 'swap';
|
|
938
1172
|
market = this.safeMarket(marketId, market, undefined, defaultType);
|
|
939
|
-
let cost = this.safeString(order, 'deal_money');
|
|
940
|
-
let filled = this.safeString(order, 'deal_stock');
|
|
941
|
-
let average = undefined;
|
|
942
|
-
if (market['swap']) {
|
|
943
|
-
const leverage = this.safeString(order, 'leverage');
|
|
944
|
-
cost = Precise.stringDiv(filled, leverage);
|
|
945
|
-
average = Precise.stringDiv(filled, amount);
|
|
946
|
-
filled = undefined;
|
|
947
|
-
}
|
|
948
1173
|
let fee = undefined;
|
|
949
|
-
const feeCost = this.omitZero(this.
|
|
1174
|
+
const feeCost = this.omitZero(this.safeString2(order, 'fee', 'quote_ccy_fee'));
|
|
950
1175
|
if (feeCost !== undefined) {
|
|
951
|
-
const feeCurrencyId = this.safeString(order, '
|
|
1176
|
+
const feeCurrencyId = this.safeString(order, 'fee_ccy', market['quote']);
|
|
952
1177
|
fee = {
|
|
953
1178
|
'currency': this.safeCurrencyCode(feeCurrencyId),
|
|
954
1179
|
'cost': feeCost,
|
|
@@ -956,24 +1181,24 @@ export default class coinex extends coinexRest {
|
|
|
956
1181
|
}
|
|
957
1182
|
return this.safeOrder({
|
|
958
1183
|
'info': order,
|
|
959
|
-
'id': this.safeString2(order, 'order_id', '
|
|
1184
|
+
'id': this.safeString2(order, 'order_id', 'stop_id'),
|
|
960
1185
|
'clientOrderId': this.safeString(order, 'client_id'),
|
|
961
1186
|
'datetime': this.iso8601(timestamp),
|
|
962
1187
|
'timestamp': timestamp,
|
|
963
|
-
'lastTradeTimestamp': this.
|
|
1188
|
+
'lastTradeTimestamp': this.safeInteger(order, 'updated_at'),
|
|
964
1189
|
'symbol': market['symbol'],
|
|
965
|
-
'type': type,
|
|
1190
|
+
'type': this.safeString(order, 'type'),
|
|
966
1191
|
'timeInForce': undefined,
|
|
967
1192
|
'postOnly': undefined,
|
|
968
|
-
'side': side,
|
|
1193
|
+
'side': this.safeString(order, 'side'),
|
|
969
1194
|
'price': this.safeString(order, 'price'),
|
|
970
|
-
'stopPrice': this.safeString(order, '
|
|
971
|
-
'triggerPrice': this.safeString(order, '
|
|
972
|
-
'amount': amount,
|
|
973
|
-
'filled':
|
|
974
|
-
'remaining':
|
|
975
|
-
'cost':
|
|
976
|
-
'average':
|
|
1195
|
+
'stopPrice': this.safeString(order, 'trigger_price'),
|
|
1196
|
+
'triggerPrice': this.safeString(order, 'trigger_price'),
|
|
1197
|
+
'amount': this.safeString(order, 'amount'),
|
|
1198
|
+
'filled': this.safeString2(order, 'filled_amount', 'fill_value'),
|
|
1199
|
+
'remaining': this.safeString2(order, 'unfilled_amount', 'unfill_amount'),
|
|
1200
|
+
'cost': undefined,
|
|
1201
|
+
'average': undefined,
|
|
977
1202
|
'status': this.parseWsOrderStatus(status),
|
|
978
1203
|
'fee': fee,
|
|
979
1204
|
'trades': undefined,
|
|
@@ -981,25 +1206,116 @@ export default class coinex extends coinexRest {
|
|
|
981
1206
|
}
|
|
982
1207
|
parseWsOrderStatus(status) {
|
|
983
1208
|
const statuses = {
|
|
984
|
-
'
|
|
985
|
-
'
|
|
1209
|
+
'active_success': 'open',
|
|
1210
|
+
'active_fail': 'canceled',
|
|
1211
|
+
'cancel': 'canceled',
|
|
986
1212
|
};
|
|
987
1213
|
return this.safeString(statuses, status, status);
|
|
988
1214
|
}
|
|
1215
|
+
async watchBidsAsks(symbols = undefined, params = {}) {
|
|
1216
|
+
/**
|
|
1217
|
+
* @method
|
|
1218
|
+
* @name coinex#watchBidsAsks
|
|
1219
|
+
* @description watches best bid & ask for symbols
|
|
1220
|
+
* @see https://docs.coinex.com/api/v2/spot/market/ws/market-bbo
|
|
1221
|
+
* @see https://docs.coinex.com/api/v2/futures/market/ws/market-bbo
|
|
1222
|
+
* @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
|
|
1223
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1224
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
1225
|
+
*/
|
|
1226
|
+
await this.loadMarkets();
|
|
1227
|
+
const marketIds = this.marketIds(symbols);
|
|
1228
|
+
const messageHashes = [];
|
|
1229
|
+
let market = undefined;
|
|
1230
|
+
const symbolsDefined = (symbols !== undefined);
|
|
1231
|
+
if (symbolsDefined) {
|
|
1232
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
1233
|
+
const symbol = symbols[i];
|
|
1234
|
+
market = this.market(symbol);
|
|
1235
|
+
messageHashes.push('bidsasks:' + market['symbol']);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
messageHashes.push('bidsasks');
|
|
1240
|
+
}
|
|
1241
|
+
let type = undefined;
|
|
1242
|
+
[type, params] = this.handleMarketTypeAndParams('watchBidsAsks', market, params);
|
|
1243
|
+
const url = this.urls['api']['ws'][type];
|
|
1244
|
+
const subscriptionHashes = ['all@bidsasks'];
|
|
1245
|
+
const subscribe = {
|
|
1246
|
+
'method': 'bbo.subscribe',
|
|
1247
|
+
'params': { 'market_list': marketIds },
|
|
1248
|
+
'id': this.requestId(),
|
|
1249
|
+
};
|
|
1250
|
+
const result = await this.watchMultiple(url, messageHashes, this.deepExtend(subscribe, params), subscriptionHashes);
|
|
1251
|
+
if (this.newUpdates) {
|
|
1252
|
+
return result;
|
|
1253
|
+
}
|
|
1254
|
+
return this.filterByArray(this.bidsasks, 'symbol', symbols);
|
|
1255
|
+
}
|
|
1256
|
+
handleBidAsk(client, message) {
|
|
1257
|
+
//
|
|
1258
|
+
// {
|
|
1259
|
+
// "method": "bbo.update",
|
|
1260
|
+
// "data": {
|
|
1261
|
+
// "market": "BTCUSDT",
|
|
1262
|
+
// "updated_at": 1656660154,
|
|
1263
|
+
// "best_bid_price": "20000",
|
|
1264
|
+
// "best_bid_size": "0.1",
|
|
1265
|
+
// "best_ask_price": "20001",
|
|
1266
|
+
// "best_ask_size": "0.15"
|
|
1267
|
+
// },
|
|
1268
|
+
// "id": null
|
|
1269
|
+
// }
|
|
1270
|
+
//
|
|
1271
|
+
const data = this.safeDict(message, 'data', {});
|
|
1272
|
+
const parsedTicker = this.parseWsBidAsk(data);
|
|
1273
|
+
const symbol = parsedTicker['symbol'];
|
|
1274
|
+
this.bidsasks[symbol] = parsedTicker;
|
|
1275
|
+
const messageHash = 'bidsasks:' + symbol;
|
|
1276
|
+
client.resolve(parsedTicker, messageHash);
|
|
1277
|
+
}
|
|
1278
|
+
parseWsBidAsk(ticker, market = undefined) {
|
|
1279
|
+
//
|
|
1280
|
+
// {
|
|
1281
|
+
// "market": "BTCUSDT",
|
|
1282
|
+
// "updated_at": 1656660154,
|
|
1283
|
+
// "best_bid_price": "20000",
|
|
1284
|
+
// "best_bid_size": "0.1",
|
|
1285
|
+
// "best_ask_price": "20001",
|
|
1286
|
+
// "best_ask_size": "0.15"
|
|
1287
|
+
// }
|
|
1288
|
+
//
|
|
1289
|
+
const defaultType = this.safeString(this.options, 'defaultType');
|
|
1290
|
+
const marketId = this.safeString(ticker, 'market');
|
|
1291
|
+
market = this.safeMarket(marketId, market, undefined, defaultType);
|
|
1292
|
+
const timestamp = this.safeTimestamp(ticker, 'updated_at');
|
|
1293
|
+
return this.safeTicker({
|
|
1294
|
+
'symbol': this.safeSymbol(marketId, market, undefined, defaultType),
|
|
1295
|
+
'timestamp': timestamp,
|
|
1296
|
+
'datetime': this.iso8601(timestamp),
|
|
1297
|
+
'ask': this.safeNumber(ticker, 'best_ask_price'),
|
|
1298
|
+
'askVolume': this.safeNumber(ticker, 'best_ask_size'),
|
|
1299
|
+
'bid': this.safeNumber(ticker, 'best_bid_price'),
|
|
1300
|
+
'bidVolume': this.safeNumber(ticker, 'best_bid_size'),
|
|
1301
|
+
'info': ticker,
|
|
1302
|
+
}, market);
|
|
1303
|
+
}
|
|
989
1304
|
handleMessage(client, message) {
|
|
990
|
-
const
|
|
1305
|
+
const method = this.safeString(message, 'method');
|
|
1306
|
+
const error = this.safeString(message, 'message');
|
|
991
1307
|
if (error !== undefined) {
|
|
992
|
-
|
|
1308
|
+
this.handleErrors(undefined, undefined, client.url, method, undefined, this.json(error), message, undefined, undefined);
|
|
993
1309
|
}
|
|
994
|
-
const method = this.safeString(message, 'method');
|
|
995
1310
|
const handlers = {
|
|
996
1311
|
'state.update': this.handleTicker,
|
|
997
|
-
'
|
|
1312
|
+
'balance.update': this.handleBalance,
|
|
998
1313
|
'deals.update': this.handleTrades,
|
|
1314
|
+
'user_deals.update': this.handleMyTrades,
|
|
999
1315
|
'depth.update': this.handleOrderBook,
|
|
1000
1316
|
'order.update': this.handleOrders,
|
|
1001
|
-
'
|
|
1002
|
-
'
|
|
1317
|
+
'stop.update': this.handleOrders,
|
|
1318
|
+
'bbo.update': this.handleBidAsk,
|
|
1003
1319
|
};
|
|
1004
1320
|
const handler = this.safeValue(handlers, method);
|
|
1005
1321
|
if (handler !== undefined) {
|
|
@@ -1008,35 +1324,65 @@ export default class coinex extends coinexRest {
|
|
|
1008
1324
|
}
|
|
1009
1325
|
this.handleSubscriptionStatus(client, message);
|
|
1010
1326
|
}
|
|
1327
|
+
handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
|
1328
|
+
if (response === undefined) {
|
|
1329
|
+
return undefined;
|
|
1330
|
+
}
|
|
1331
|
+
//
|
|
1332
|
+
// { "id": 1, "code": 20001, "message": "invalid argument" }
|
|
1333
|
+
// { "id": 2, "code": 21001, "message": "require auth" }
|
|
1334
|
+
// { "id": 1, "code": 21002, "message": "Signature Incorrect" }
|
|
1335
|
+
//
|
|
1336
|
+
const message = this.safeStringLower(response, 'message');
|
|
1337
|
+
const isErrorMessage = (message !== undefined) && (message !== 'ok');
|
|
1338
|
+
const errorCode = this.safeString(response, 'code');
|
|
1339
|
+
const isErrorCode = (errorCode !== undefined) && (errorCode !== '0');
|
|
1340
|
+
if (isErrorCode || isErrorMessage) {
|
|
1341
|
+
const feedback = this.id + ' ' + body;
|
|
1342
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
|
|
1343
|
+
this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
|
|
1344
|
+
throw new ExchangeError(feedback);
|
|
1345
|
+
}
|
|
1346
|
+
return undefined;
|
|
1347
|
+
}
|
|
1011
1348
|
handleAuthenticationMessage(client, message) {
|
|
1349
|
+
//
|
|
1350
|
+
// success
|
|
1012
1351
|
//
|
|
1013
1352
|
// {
|
|
1014
|
-
// "
|
|
1015
|
-
// "
|
|
1016
|
-
//
|
|
1017
|
-
//
|
|
1018
|
-
//
|
|
1353
|
+
// "id": 1,
|
|
1354
|
+
// "code": 0,
|
|
1355
|
+
// "message": "OK"
|
|
1356
|
+
// }
|
|
1357
|
+
//
|
|
1358
|
+
// fail
|
|
1359
|
+
//
|
|
1360
|
+
// {
|
|
1361
|
+
// "id": 1,
|
|
1362
|
+
// "code": 21002,
|
|
1363
|
+
// "message": ""
|
|
1019
1364
|
// }
|
|
1020
1365
|
//
|
|
1021
|
-
const
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1366
|
+
const status = this.safeStringLower(message, 'message');
|
|
1367
|
+
const errorCode = this.safeString(message, 'code');
|
|
1368
|
+
const messageHash = 'authenticated';
|
|
1369
|
+
if ((status === 'ok') || (errorCode === '0')) {
|
|
1370
|
+
const future = this.safeValue(client.futures, messageHash);
|
|
1371
|
+
future.resolve(true);
|
|
1372
|
+
}
|
|
1373
|
+
else {
|
|
1374
|
+
const error = new AuthenticationError(this.json(message));
|
|
1375
|
+
client.reject(error, messageHash);
|
|
1376
|
+
if (messageHash in client.subscriptions) {
|
|
1377
|
+
delete client.subscriptions[messageHash];
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1030
1380
|
}
|
|
1031
1381
|
handleSubscriptionStatus(client, message) {
|
|
1032
1382
|
const id = this.safeInteger(message, 'id');
|
|
1033
1383
|
const subscription = this.safeValue(client.subscriptions, id);
|
|
1034
1384
|
if (subscription !== undefined) {
|
|
1035
1385
|
const futureIndex = this.safeString(subscription, 'future');
|
|
1036
|
-
if (futureIndex === 'ohlcv') {
|
|
1037
|
-
this.handleOHLCV(client, message);
|
|
1038
|
-
return;
|
|
1039
|
-
}
|
|
1040
1386
|
const future = this.safeValue(client.futures, futureIndex);
|
|
1041
1387
|
if (future !== undefined) {
|
|
1042
1388
|
future.resolve(true);
|
|
@@ -1044,65 +1390,34 @@ export default class coinex extends coinexRest {
|
|
|
1044
1390
|
delete client.subscriptions[id];
|
|
1045
1391
|
}
|
|
1046
1392
|
}
|
|
1047
|
-
async authenticate(
|
|
1048
|
-
let type = undefined;
|
|
1049
|
-
[type, params] = this.handleMarketTypeAndParams('authenticate', undefined, params);
|
|
1393
|
+
async authenticate(type) {
|
|
1050
1394
|
const url = this.urls['api']['ws'][type];
|
|
1051
1395
|
const client = this.client(url);
|
|
1052
1396
|
const time = this.milliseconds();
|
|
1053
|
-
const
|
|
1054
|
-
const
|
|
1055
|
-
const swapMessageHash = 'authenticated:swap';
|
|
1056
|
-
const messageHash = isSpot ? spotMessageHash : swapMessageHash;
|
|
1397
|
+
const timestamp = time.toString();
|
|
1398
|
+
const messageHash = 'authenticated';
|
|
1057
1399
|
const future = client.future(messageHash);
|
|
1058
1400
|
const authenticated = this.safeValue(client.subscriptions, messageHash);
|
|
1059
|
-
if (
|
|
1060
|
-
if (authenticated !== undefined) {
|
|
1061
|
-
return await future;
|
|
1062
|
-
}
|
|
1063
|
-
const requestId = this.requestId();
|
|
1064
|
-
const subscribe = {
|
|
1065
|
-
'id': requestId,
|
|
1066
|
-
'future': spotMessageHash,
|
|
1067
|
-
};
|
|
1068
|
-
const signData = 'access_id=' + this.apiKey + '&tonce=' + this.numberToString(time) + '&secret_key=' + this.secret;
|
|
1069
|
-
const hash = this.hash(this.encode(signData), md5);
|
|
1070
|
-
const request = {
|
|
1071
|
-
'method': 'server.sign',
|
|
1072
|
-
'params': [
|
|
1073
|
-
this.apiKey,
|
|
1074
|
-
hash.toUpperCase(),
|
|
1075
|
-
time,
|
|
1076
|
-
],
|
|
1077
|
-
'id': requestId,
|
|
1078
|
-
};
|
|
1079
|
-
this.watch(url, messageHash, request, requestId, subscribe);
|
|
1080
|
-
client.subscriptions[messageHash] = true;
|
|
1081
|
-
return await future;
|
|
1082
|
-
}
|
|
1083
|
-
else {
|
|
1084
|
-
if (authenticated !== undefined) {
|
|
1085
|
-
return await future;
|
|
1086
|
-
}
|
|
1087
|
-
const requestId = this.requestId();
|
|
1088
|
-
const subscribe = {
|
|
1089
|
-
'id': requestId,
|
|
1090
|
-
'future': swapMessageHash,
|
|
1091
|
-
};
|
|
1092
|
-
const signData = 'access_id=' + this.apiKey + '×tamp=' + this.numberToString(time) + '&secret_key=' + this.secret;
|
|
1093
|
-
const hash = this.hash(this.encode(signData), sha256, 'hex');
|
|
1094
|
-
const request = {
|
|
1095
|
-
'method': 'server.sign',
|
|
1096
|
-
'params': [
|
|
1097
|
-
this.apiKey,
|
|
1098
|
-
hash.toLowerCase(),
|
|
1099
|
-
time,
|
|
1100
|
-
],
|
|
1101
|
-
'id': requestId,
|
|
1102
|
-
};
|
|
1103
|
-
this.watch(url, messageHash, request, requestId, subscribe);
|
|
1104
|
-
client.subscriptions[messageHash] = true;
|
|
1401
|
+
if (authenticated !== undefined) {
|
|
1105
1402
|
return await future;
|
|
1106
1403
|
}
|
|
1404
|
+
const requestId = this.requestId();
|
|
1405
|
+
const subscribe = {
|
|
1406
|
+
'id': requestId,
|
|
1407
|
+
'future': messageHash,
|
|
1408
|
+
};
|
|
1409
|
+
const hmac = this.hmac(this.encode(timestamp), this.encode(this.secret), sha256, 'hex');
|
|
1410
|
+
const request = {
|
|
1411
|
+
'id': requestId,
|
|
1412
|
+
'method': 'server.sign',
|
|
1413
|
+
'params': {
|
|
1414
|
+
'access_id': this.apiKey,
|
|
1415
|
+
'signed_str': hmac.toLowerCase(),
|
|
1416
|
+
'timestamp': time,
|
|
1417
|
+
},
|
|
1418
|
+
};
|
|
1419
|
+
this.watch(url, messageHash, request, requestId, subscribe);
|
|
1420
|
+
client.subscriptions[messageHash] = true;
|
|
1421
|
+
return await future;
|
|
1107
1422
|
}
|
|
1108
1423
|
}
|