ccxt 4.3.57 → 4.3.59
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 +4 -4
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +4 -2
- package/dist/cjs/src/alpaca.js +5 -1
- package/dist/cjs/src/base/Exchange.js +4 -4
- package/dist/cjs/src/base/errors.js +22 -22
- package/dist/cjs/src/bigone.js +21 -1
- package/dist/cjs/src/bingx.js +131 -26
- package/dist/cjs/src/bitmart.js +1 -0
- package/dist/cjs/src/btcbox.js +149 -7
- package/dist/cjs/src/bybit.js +2 -2
- package/dist/cjs/src/coinmate.js +28 -35
- package/dist/cjs/src/coinone.js +1 -1
- package/dist/cjs/src/deribit.js +15 -1
- package/dist/cjs/src/digifinex.js +32 -7
- package/dist/cjs/src/gate.js +24 -18
- package/dist/cjs/src/htx.js +10 -8
- package/dist/cjs/src/hyperliquid.js +107 -1
- package/dist/cjs/src/kucoin.js +3 -0
- package/dist/cjs/src/latoken.js +5 -1
- package/dist/cjs/src/mexc.js +11 -11
- package/dist/cjs/src/okx.js +3 -0
- package/dist/cjs/src/pro/binance.js +11 -13
- package/dist/cjs/src/pro/bingx.js +11 -8
- package/dist/cjs/src/pro/okx.js +3 -3
- package/dist/cjs/src/pro/xt.js +1108 -0
- package/dist/cjs/src/upbit.js +148 -49
- package/dist/cjs/src/woo.js +1 -1
- package/dist/cjs/src/xt.js +72 -7
- package/js/ccxt.d.ts +6 -3
- package/js/ccxt.js +5 -3
- package/js/src/abstract/bitmart.d.ts +1 -0
- package/js/src/abstract/btcbox.d.ts +1 -0
- package/js/src/abstract/kucoin.d.ts +1 -0
- package/js/src/abstract/kucoinfutures.d.ts +1 -0
- package/js/src/abstract/upbit.d.ts +3 -0
- package/js/src/abstract/xt.d.ts +1 -0
- package/js/src/alpaca.d.ts +1 -1
- package/js/src/alpaca.js +5 -1
- package/js/src/base/Exchange.d.ts +3 -3
- package/js/src/base/Exchange.js +5 -5
- package/js/src/base/errorHierarchy.d.ts +5 -5
- package/js/src/base/errorHierarchy.js +5 -5
- package/js/src/base/errors.d.ts +15 -15
- package/js/src/base/errors.js +22 -22
- package/js/src/bigone.d.ts +1 -1
- package/js/src/bigone.js +21 -1
- package/js/src/bingx.js +131 -26
- package/js/src/bitmart.js +1 -0
- package/js/src/btcbox.d.ts +4 -1
- package/js/src/btcbox.js +149 -7
- package/js/src/bybit.js +2 -2
- package/js/src/coinmate.js +28 -35
- package/js/src/coinone.js +1 -1
- package/js/src/deribit.d.ts +1 -1
- package/js/src/deribit.js +15 -1
- package/js/src/digifinex.d.ts +3 -2
- package/js/src/digifinex.js +32 -7
- package/js/src/gate.js +24 -18
- package/js/src/htx.js +10 -8
- package/js/src/hyperliquid.d.ts +3 -1
- package/js/src/hyperliquid.js +107 -1
- package/js/src/kucoin.js +3 -0
- package/js/src/latoken.d.ts +1 -1
- package/js/src/latoken.js +5 -1
- package/js/src/mexc.js +11 -11
- package/js/src/okx.js +3 -0
- package/js/src/pro/binance.js +11 -13
- package/js/src/pro/bingx.js +11 -8
- package/js/src/pro/bitmart.d.ts +3 -3
- package/js/src/pro/bitopro.d.ts +2 -2
- package/js/src/pro/coincheck.d.ts +2 -2
- package/js/src/pro/coinone.d.ts +2 -2
- package/js/src/pro/hyperliquid.d.ts +2 -2
- package/js/src/pro/okx.js +3 -3
- package/js/src/pro/xt.d.ts +31 -0
- package/js/src/pro/xt.js +1109 -0
- package/js/src/upbit.d.ts +0 -1
- package/js/src/upbit.js +148 -49
- package/js/src/woo.js +2 -2
- package/js/src/xt.js +72 -7
- package/package.json +1 -1
|
@@ -0,0 +1,1108 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var xt$1 = require('../xt.js');
|
|
4
|
+
var Cache = require('../base/ws/Cache.js');
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
class xt extends xt$1 {
|
|
9
|
+
describe() {
|
|
10
|
+
return this.deepExtend(super.describe(), {
|
|
11
|
+
'has': {
|
|
12
|
+
'ws': true,
|
|
13
|
+
'watchOHLCV': true,
|
|
14
|
+
'watchOrderBook': true,
|
|
15
|
+
'watchTicker': true,
|
|
16
|
+
'watchTickers': true,
|
|
17
|
+
'watchTrades': true,
|
|
18
|
+
'watchBalance': true,
|
|
19
|
+
'watchOrders': true,
|
|
20
|
+
'watchMyTrades': true,
|
|
21
|
+
'watchPositions': undefined, // TODO https://doc.xt.com/#futures_user_websocket_v2position
|
|
22
|
+
},
|
|
23
|
+
'urls': {
|
|
24
|
+
'api': {
|
|
25
|
+
'ws': {
|
|
26
|
+
'spot': 'wss://stream.xt.com',
|
|
27
|
+
'contract': 'wss://fstream.xt.com/ws',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
'options': {
|
|
32
|
+
'tradesLimit': 1000,
|
|
33
|
+
'ordersLimit': 1000,
|
|
34
|
+
'OHLCVLimit': 1000,
|
|
35
|
+
'watchTicker': {
|
|
36
|
+
'method': 'ticker', // agg_ticker (contract only)
|
|
37
|
+
},
|
|
38
|
+
'watchTickers': {
|
|
39
|
+
'method': 'tickers', // agg_tickers (contract only)
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
'streaming': {
|
|
43
|
+
'keepAlive': 20000,
|
|
44
|
+
'ping': this.ping,
|
|
45
|
+
},
|
|
46
|
+
'token': undefined,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async getListenKey(isContract) {
|
|
50
|
+
/**
|
|
51
|
+
* @ignore
|
|
52
|
+
* @method
|
|
53
|
+
* @description required for private endpoints
|
|
54
|
+
* @param {string} isContract true for contract trades
|
|
55
|
+
* @see https://doc.xt.com/#websocket_privategetToken
|
|
56
|
+
* @see https://doc.xt.com/#futures_user_websocket_v2base
|
|
57
|
+
* @returns {string} listen key / access token
|
|
58
|
+
*/
|
|
59
|
+
this.checkRequiredCredentials();
|
|
60
|
+
const tradeType = isContract ? 'contract' : 'spot';
|
|
61
|
+
let url = this.urls['api']['ws'][tradeType];
|
|
62
|
+
if (!isContract) {
|
|
63
|
+
url = url + '/private';
|
|
64
|
+
}
|
|
65
|
+
const client = this.client(url);
|
|
66
|
+
const token = this.safeDict(client.subscriptions, 'token');
|
|
67
|
+
if (token === undefined) {
|
|
68
|
+
if (isContract) {
|
|
69
|
+
const response = await this.privateLinearGetFutureUserV1UserListenKey();
|
|
70
|
+
//
|
|
71
|
+
// {
|
|
72
|
+
// returnCode: '0',
|
|
73
|
+
// msgInfo: 'success',
|
|
74
|
+
// error: null,
|
|
75
|
+
// result: '3BC1D71D6CF96DA3458FC35B05B633351684511731128'
|
|
76
|
+
// }
|
|
77
|
+
//
|
|
78
|
+
client.subscriptions['token'] = this.safeString(response, 'result');
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const response = await this.privateSpotPostWsToken();
|
|
82
|
+
//
|
|
83
|
+
// {
|
|
84
|
+
// "rc": 0,
|
|
85
|
+
// "mc": "SUCCESS",
|
|
86
|
+
// "ma": [],
|
|
87
|
+
// "result": {
|
|
88
|
+
// "token": "eyJhbqGciOiJSUzI1NiJ9.eyJhY2NvdW50SWQiOiIyMTQ2Mjg1MzIyNTU5Iiwic3ViIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsInNjb3BlIjoiYXV0aCIsImlzcyI6Inh0LmNvbSIsImxhc3RBdXRoVGltZSI6MTY2MzgxMzY5MDk1NSwic2lnblR5cGUiOiJBSyIsInVzZXJOYW1lIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsImV4cCI6MTY2NjQwNTY5MCwiZGV2aWNlIjoidW5rbm93biIsInVzZXJJZCI6MjE0NjI4NTMyMjU1OX0.h3zJlJBQrK2x1HvUxsKivnn6PlSrSDXXXJ7WqHAYSrN2CG5XPTKc4zKnTVoYFbg6fTS0u1fT8wH7wXqcLWXX71vm0YuP8PCvdPAkUIq4-HyzltbPr5uDYd0UByx0FPQtq1exvsQGe7evXQuDXx3SEJXxEqUbq_DNlXPTq_JyScI",
|
|
89
|
+
// "refreshToken": "eyJhbGciOiqJSUzI1NiJ9.eyJhY2NvdW50SWQiOiIyMTQ2Mjg1MzIyNTU5Iiwic3ViIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsInNjb3BlIjoicmVmcmVzaCIsImlzcyI6Inh0LmNvbSIsImxhc3RBdXRoVGltZSI6MTY2MzgxMzY5MDk1NSwic2lnblR5cGUiOiJBSyIsInVzZXJOYW1lIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsImV4cCI6MTY2NjQwNTY5MCwiZGV2aWNlIjoidW5rbm93biIsInVzZXJJZCI6MjE0NjI4NTMyMjU1OX0.Fs3YVm5YrEOzzYOSQYETSmt9iwxUHBovh2u73liv1hLUec683WGfktA_s28gMk4NCpZKFeQWFii623FvdfNoteXR0v1yZ2519uNvNndtuZICDdv3BQ4wzW1wIHZa1skxFfqvsDnGdXpjqu9UFSbtHwxprxeYfnxChNk4ssei430"
|
|
90
|
+
// }
|
|
91
|
+
// }
|
|
92
|
+
//
|
|
93
|
+
const result = this.safeDict(response, 'result');
|
|
94
|
+
client.subscriptions['token'] = this.safeString(result, 'accessToken');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return client.subscriptions['token'];
|
|
98
|
+
}
|
|
99
|
+
getCacheIndex(orderbook, cache) {
|
|
100
|
+
// return the first index of the cache that can be applied to the orderbook or -1 if not possible
|
|
101
|
+
const nonce = this.safeInteger(orderbook, 'nonce');
|
|
102
|
+
const firstDelta = this.safeValue(cache, 0);
|
|
103
|
+
const firstDeltaNonce = this.safeInteger2(firstDelta, 'i', 'u');
|
|
104
|
+
if (nonce < firstDeltaNonce - 1) {
|
|
105
|
+
return -1;
|
|
106
|
+
}
|
|
107
|
+
for (let i = 0; i < cache.length; i++) {
|
|
108
|
+
const delta = cache[i];
|
|
109
|
+
const deltaNonce = this.safeInteger2(delta, 'i', 'u');
|
|
110
|
+
if (deltaNonce >= nonce) {
|
|
111
|
+
return i;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return cache.length;
|
|
115
|
+
}
|
|
116
|
+
handleDelta(orderbook, delta) {
|
|
117
|
+
orderbook['nonce'] = this.safeInteger2(delta, 'i', 'u');
|
|
118
|
+
const obAsks = this.safeList(delta, 'a', []);
|
|
119
|
+
const obBids = this.safeList(delta, 'b', []);
|
|
120
|
+
const bids = orderbook['bids'];
|
|
121
|
+
const asks = orderbook['asks'];
|
|
122
|
+
for (let i = 0; i < obBids.length; i++) {
|
|
123
|
+
const bid = obBids[i];
|
|
124
|
+
const price = this.safeNumber(bid, 0);
|
|
125
|
+
const quantity = this.safeNumber(bid, 1);
|
|
126
|
+
bids.store(price, quantity);
|
|
127
|
+
}
|
|
128
|
+
for (let i = 0; i < obAsks.length; i++) {
|
|
129
|
+
const ask = obAsks[i];
|
|
130
|
+
const price = this.safeNumber(ask, 0);
|
|
131
|
+
const quantity = this.safeNumber(ask, 1);
|
|
132
|
+
asks.store(price, quantity);
|
|
133
|
+
}
|
|
134
|
+
// this.handleBidAsks (storedBids, bids);
|
|
135
|
+
// this.handleBidAsks (storedAsks, asks);
|
|
136
|
+
}
|
|
137
|
+
async subscribe(name, access, methodName, market = undefined, symbols = undefined, params = {}) {
|
|
138
|
+
/**
|
|
139
|
+
* @ignore
|
|
140
|
+
* @method
|
|
141
|
+
* @description Connects to a websocket channel
|
|
142
|
+
* @see https://doc.xt.com/#websocket_privaterequestFormat
|
|
143
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2base
|
|
144
|
+
* @param {string} name name of the channel
|
|
145
|
+
* @param {string} access public or private
|
|
146
|
+
* @param {string} methodName the name of the CCXT class method
|
|
147
|
+
* @param {object} [market] CCXT market
|
|
148
|
+
* @param {string[]} [symbols] unified market symbols
|
|
149
|
+
* @param {object} params extra parameters specific to the xt api
|
|
150
|
+
* @returns {object} data from the websocket stream
|
|
151
|
+
*/
|
|
152
|
+
const privateAccess = access === 'private';
|
|
153
|
+
let type = undefined;
|
|
154
|
+
[type, params] = this.handleMarketTypeAndParams(methodName, market, params);
|
|
155
|
+
const isContract = (type !== 'spot');
|
|
156
|
+
const subscribe = {
|
|
157
|
+
'method': isContract ? 'SUBSCRIBE' : 'subscribe',
|
|
158
|
+
'id': this.numberToString(this.milliseconds()) + name, // call back ID
|
|
159
|
+
};
|
|
160
|
+
if (privateAccess) {
|
|
161
|
+
if (!isContract) {
|
|
162
|
+
subscribe['params'] = [name];
|
|
163
|
+
subscribe['listenKey'] = await this.getListenKey(isContract);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
const listenKey = await this.getListenKey(isContract);
|
|
167
|
+
const param = name + '@' + listenKey;
|
|
168
|
+
subscribe['params'] = [param];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
subscribe['params'] = [name];
|
|
173
|
+
}
|
|
174
|
+
const tradeType = isContract ? 'contract' : 'spot';
|
|
175
|
+
let messageHash = name + '::' + tradeType;
|
|
176
|
+
if (symbols !== undefined) {
|
|
177
|
+
messageHash = messageHash + '::' + symbols.join(',');
|
|
178
|
+
}
|
|
179
|
+
const request = this.extend(subscribe, params);
|
|
180
|
+
let tail = access;
|
|
181
|
+
if (isContract) {
|
|
182
|
+
tail = privateAccess ? 'user' : 'market';
|
|
183
|
+
}
|
|
184
|
+
const url = this.urls['api']['ws'][tradeType] + '/' + tail;
|
|
185
|
+
return await this.watch(url, messageHash, request, messageHash);
|
|
186
|
+
}
|
|
187
|
+
async watchTicker(symbol, params = {}) {
|
|
188
|
+
/**
|
|
189
|
+
* @method
|
|
190
|
+
* @name xt#watchTicker
|
|
191
|
+
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
192
|
+
* @see https://doc.xt.com/#websocket_publictickerRealTime
|
|
193
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2tickerRealTime
|
|
194
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2aggTickerRealTime
|
|
195
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
196
|
+
* @param {object} params extra parameters specific to the xt api endpoint
|
|
197
|
+
* @param {string} [params.method] 'agg_ticker' (contract only) or 'ticker', default = 'ticker' - the endpoint that will be streamed
|
|
198
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
|
|
199
|
+
*/
|
|
200
|
+
await this.loadMarkets();
|
|
201
|
+
const market = this.market(symbol);
|
|
202
|
+
const options = this.safeDict(this.options, 'watchTicker');
|
|
203
|
+
const defaultMethod = this.safeString(options, 'method', 'ticker');
|
|
204
|
+
const method = this.safeString(params, 'method', defaultMethod);
|
|
205
|
+
const name = method + '@' + market['id'];
|
|
206
|
+
return await this.subscribe(name, 'public', 'watchTicker', market, undefined, params);
|
|
207
|
+
}
|
|
208
|
+
async watchTickers(symbols = undefined, params = {}) {
|
|
209
|
+
/**
|
|
210
|
+
* @method
|
|
211
|
+
* @name xt#watchTicker
|
|
212
|
+
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
213
|
+
* @see https://doc.xt.com/#websocket_publicallTicker
|
|
214
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2allTicker
|
|
215
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2allAggTicker
|
|
216
|
+
* @param {string} [symbols] unified market symbols
|
|
217
|
+
* @param {object} params extra parameters specific to the xt api endpoint
|
|
218
|
+
* @param {string} [params.method] 'agg_tickers' (contract only) or 'tickers', default = 'tickers' - the endpoint that will be streamed
|
|
219
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
|
|
220
|
+
*/
|
|
221
|
+
await this.loadMarkets();
|
|
222
|
+
const options = this.safeDict(this.options, 'watchTickers');
|
|
223
|
+
const defaultMethod = this.safeString(options, 'method', 'tickers');
|
|
224
|
+
const name = this.safeString(params, 'method', defaultMethod);
|
|
225
|
+
let market = undefined;
|
|
226
|
+
if (symbols !== undefined) {
|
|
227
|
+
market = this.market(symbols[0]);
|
|
228
|
+
}
|
|
229
|
+
const tickers = await this.subscribe(name, 'public', 'watchTickers', market, symbols, params);
|
|
230
|
+
if (this.newUpdates) {
|
|
231
|
+
return tickers;
|
|
232
|
+
}
|
|
233
|
+
return this.filterByArray(this.tickers, 'symbol', symbols);
|
|
234
|
+
}
|
|
235
|
+
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
236
|
+
/**
|
|
237
|
+
* @method
|
|
238
|
+
* @name hitbtc#watchOHLCV
|
|
239
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
240
|
+
* @see https://doc.xt.com/#websocket_publicsymbolKline
|
|
241
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2symbolKline
|
|
242
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
243
|
+
* @param {string} timeframe 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, or 1M
|
|
244
|
+
* @param {int} [since] not used by xt watchOHLCV
|
|
245
|
+
* @param {int} [limit] not used by xt watchOHLCV
|
|
246
|
+
* @param {object} params extra parameters specific to the xt api endpoint
|
|
247
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
248
|
+
*/
|
|
249
|
+
await this.loadMarkets();
|
|
250
|
+
const market = this.market(symbol);
|
|
251
|
+
const name = 'kline@' + market['id'] + ',' + timeframe;
|
|
252
|
+
return await this.subscribe(name, 'public', 'watchOHLCV', market, undefined, params);
|
|
253
|
+
}
|
|
254
|
+
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
255
|
+
/**
|
|
256
|
+
* @method
|
|
257
|
+
* @name xt#watchTrades
|
|
258
|
+
* @description get the list of most recent trades for a particular symbol
|
|
259
|
+
* @see https://doc.xt.com/#websocket_publicdealRecord
|
|
260
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2dealRecord
|
|
261
|
+
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
262
|
+
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
263
|
+
* @param {int} [limit] the maximum amount of trades to fetch
|
|
264
|
+
* @param {object} params extra parameters specific to the xt api endpoint
|
|
265
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
|
|
266
|
+
*/
|
|
267
|
+
await this.loadMarkets();
|
|
268
|
+
const market = this.market(symbol);
|
|
269
|
+
const name = 'trade@' + market['id'];
|
|
270
|
+
const trades = await this.subscribe(name, 'public', 'watchTrades', market, undefined, params);
|
|
271
|
+
if (this.newUpdates) {
|
|
272
|
+
limit = trades.getLimit(symbol, limit);
|
|
273
|
+
}
|
|
274
|
+
return this.filterBySinceLimit(trades, since, limit, 'timestamp');
|
|
275
|
+
}
|
|
276
|
+
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
277
|
+
/**
|
|
278
|
+
* @method
|
|
279
|
+
* @name xt#watchOrderBook
|
|
280
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
281
|
+
* @see https://doc.xt.com/#websocket_publiclimitDepth
|
|
282
|
+
* @see https://doc.xt.com/#websocket_publicincreDepth
|
|
283
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2limitDepth
|
|
284
|
+
* @see https://doc.xt.com/#futures_market_websocket_v2increDepth
|
|
285
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
286
|
+
* @param {int} [limit] not used by xt watchOrderBook
|
|
287
|
+
* @param {object} params extra parameters specific to the xt api endpoint
|
|
288
|
+
* @param {int} [params.levels] 5, 10, 20, or 50
|
|
289
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols
|
|
290
|
+
*/
|
|
291
|
+
await this.loadMarkets();
|
|
292
|
+
const market = this.market(symbol);
|
|
293
|
+
const levels = this.safeString(params, 'levels');
|
|
294
|
+
params = this.omit(params, 'levels');
|
|
295
|
+
let name = 'depth_update@' + market['id'];
|
|
296
|
+
if (levels !== undefined) {
|
|
297
|
+
name = 'depth@' + market['id'] + ',' + levels;
|
|
298
|
+
}
|
|
299
|
+
const orderbook = await this.subscribe(name, 'public', 'watchOrderBook', market, undefined, params);
|
|
300
|
+
return orderbook.limit();
|
|
301
|
+
}
|
|
302
|
+
async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
303
|
+
/**
|
|
304
|
+
* @method
|
|
305
|
+
* @name xt#watchOrders
|
|
306
|
+
* @description watches information on multiple orders made by the user
|
|
307
|
+
* @see https://doc.xt.com/#websocket_privateorderChange
|
|
308
|
+
* @see https://doc.xt.com/#futures_user_websocket_v2order
|
|
309
|
+
* @param {string} [symbol] unified market symbol
|
|
310
|
+
* @param {int} [since] not used by xt watchOrders
|
|
311
|
+
* @param {int} [limit] the maximum number of orders to return
|
|
312
|
+
* @param {object} params extra parameters specific to the xt api endpoint
|
|
313
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
|
|
314
|
+
*/
|
|
315
|
+
await this.loadMarkets();
|
|
316
|
+
const name = 'order';
|
|
317
|
+
let market = undefined;
|
|
318
|
+
if (symbol !== undefined) {
|
|
319
|
+
market = this.market(symbol);
|
|
320
|
+
}
|
|
321
|
+
const orders = await this.subscribe(name, 'private', 'watchOrders', market, undefined, params);
|
|
322
|
+
if (this.newUpdates) {
|
|
323
|
+
limit = orders.getLimit(symbol, limit);
|
|
324
|
+
}
|
|
325
|
+
return this.filterBySinceLimit(orders, since, limit, 'timestamp');
|
|
326
|
+
}
|
|
327
|
+
async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
328
|
+
/**
|
|
329
|
+
* @method
|
|
330
|
+
* @name xt#watchMyTrades
|
|
331
|
+
* @description watches information on multiple trades made by the user
|
|
332
|
+
* @see https://doc.xt.com/#websocket_privateorderDeal
|
|
333
|
+
* @see https://doc.xt.com/#futures_user_websocket_v2trade
|
|
334
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
335
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
336
|
+
* @param {int} [limit] the maximum number of orde structures to retrieve
|
|
337
|
+
* @param {object} params extra parameters specific to the kucoin api endpoint
|
|
338
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
339
|
+
*/
|
|
340
|
+
await this.loadMarkets();
|
|
341
|
+
const name = 'trade';
|
|
342
|
+
let market = undefined;
|
|
343
|
+
if (symbol !== undefined) {
|
|
344
|
+
market = this.market(symbol);
|
|
345
|
+
}
|
|
346
|
+
const trades = await this.subscribe(name, 'private', 'watchMyTrades', market, undefined, params);
|
|
347
|
+
if (this.newUpdates) {
|
|
348
|
+
limit = trades.getLimit(symbol, limit);
|
|
349
|
+
}
|
|
350
|
+
return this.filterBySinceLimit(trades, since, limit, 'timestamp');
|
|
351
|
+
}
|
|
352
|
+
async watchBalance(params = {}) {
|
|
353
|
+
/**
|
|
354
|
+
* @method
|
|
355
|
+
* @name xt#watchOrders
|
|
356
|
+
* @description watches information on multiple orders made by the user
|
|
357
|
+
* @see https://doc.xt.com/#websocket_privatebalanceChange
|
|
358
|
+
* @see https://doc.xt.com/#futures_user_websocket_v2balance
|
|
359
|
+
* @param {object} params extra parameters specific to the xt api endpoint
|
|
360
|
+
* @returns {object[]} a list of [balance structures]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
361
|
+
*/
|
|
362
|
+
await this.loadMarkets();
|
|
363
|
+
const name = 'balance';
|
|
364
|
+
return await this.subscribe(name, 'private', 'watchBalance', undefined, undefined, params);
|
|
365
|
+
}
|
|
366
|
+
handleTicker(client, message) {
|
|
367
|
+
//
|
|
368
|
+
// spot
|
|
369
|
+
//
|
|
370
|
+
// {
|
|
371
|
+
// topic: 'ticker',
|
|
372
|
+
// event: 'ticker@btc_usdt',
|
|
373
|
+
// data: {
|
|
374
|
+
// s: 'btc_usdt', // symbol
|
|
375
|
+
// t: 1683501935877, // time(Last transaction time)
|
|
376
|
+
// cv: '-82.67', // priceChangeValue(24 hour price change)
|
|
377
|
+
// cr: '-0.0028', // priceChangeRate 24-hour price change (percentage)
|
|
378
|
+
// o: '28823.87', // open price
|
|
379
|
+
// c: '28741.20', // close price
|
|
380
|
+
// h: '29137.64', // highest price
|
|
381
|
+
// l: '28660.93', // lowest price
|
|
382
|
+
// q: '6372.601573', // quantity
|
|
383
|
+
// v: '184086075.2772391' // volume
|
|
384
|
+
// }
|
|
385
|
+
// }
|
|
386
|
+
//
|
|
387
|
+
// contract
|
|
388
|
+
//
|
|
389
|
+
// {
|
|
390
|
+
// "topic": "ticker",
|
|
391
|
+
// "event": "ticker@btc_usdt",
|
|
392
|
+
// "data": {
|
|
393
|
+
// "s": "btc_index", // trading pair
|
|
394
|
+
// "o": "49000", // opening price
|
|
395
|
+
// "c": "50000", // closing price
|
|
396
|
+
// "h": "0.1", // highest price
|
|
397
|
+
// "l": "0.1", // lowest price
|
|
398
|
+
// "a": "0.1", // volume
|
|
399
|
+
// "v": "0.1", // turnover
|
|
400
|
+
// "ch": "0.21", // quote change
|
|
401
|
+
// "t": 123124124 // timestamp
|
|
402
|
+
// }
|
|
403
|
+
// }
|
|
404
|
+
//
|
|
405
|
+
// agg_ticker (contract)
|
|
406
|
+
//
|
|
407
|
+
// {
|
|
408
|
+
// "topic": "agg_ticker",
|
|
409
|
+
// "event": "agg_ticker@btc_usdt",
|
|
410
|
+
// "data": {
|
|
411
|
+
// "s": "btc_index", // trading pair
|
|
412
|
+
// "o": "49000", // opening price
|
|
413
|
+
// "c": "50000", // closing price
|
|
414
|
+
// "h": "0.1", // highest price
|
|
415
|
+
// "l": "0.1", // lowest price
|
|
416
|
+
// "a": "0.1", // volume
|
|
417
|
+
// "v": "0.1", // turnover
|
|
418
|
+
// "ch": "0.21", // quote change
|
|
419
|
+
// "i": "0.21" , // index price
|
|
420
|
+
// "m": "0.21", // mark price
|
|
421
|
+
// "bp": "0.21", // bid price
|
|
422
|
+
// "ap": "0.21" , // ask price
|
|
423
|
+
// "t": 123124124 // timestamp
|
|
424
|
+
// }
|
|
425
|
+
// }
|
|
426
|
+
//
|
|
427
|
+
const data = this.safeDict(message, 'data');
|
|
428
|
+
const marketId = this.safeString(data, 's');
|
|
429
|
+
if (marketId !== undefined) {
|
|
430
|
+
const cv = this.safeString(data, 'cv');
|
|
431
|
+
const isSpot = cv !== undefined;
|
|
432
|
+
const ticker = this.parseTicker(data);
|
|
433
|
+
const symbol = ticker['symbol'];
|
|
434
|
+
this.tickers[symbol] = ticker;
|
|
435
|
+
const event = this.safeString(message, 'event');
|
|
436
|
+
const messageHashTail = isSpot ? 'spot' : 'contract';
|
|
437
|
+
const messageHash = event + '::' + messageHashTail;
|
|
438
|
+
client.resolve(ticker, messageHash);
|
|
439
|
+
}
|
|
440
|
+
return message;
|
|
441
|
+
}
|
|
442
|
+
handleTickers(client, message) {
|
|
443
|
+
//
|
|
444
|
+
// spot
|
|
445
|
+
//
|
|
446
|
+
// {
|
|
447
|
+
// topic: 'tickers',
|
|
448
|
+
// event: 'tickers',
|
|
449
|
+
// data: [
|
|
450
|
+
// {
|
|
451
|
+
// s: 'elon_usdt',
|
|
452
|
+
// t: 1683502958381,
|
|
453
|
+
// cv: '-0.0000000125',
|
|
454
|
+
// cr: '-0.0495',
|
|
455
|
+
// o: '0.0000002522',
|
|
456
|
+
// c: '0.0000002397',
|
|
457
|
+
// h: '0.0000002690',
|
|
458
|
+
// l: '0.0000002371',
|
|
459
|
+
// q: '3803783034.0000000000',
|
|
460
|
+
// v: '955.3260820022'
|
|
461
|
+
// },
|
|
462
|
+
// ...
|
|
463
|
+
// ]
|
|
464
|
+
// }
|
|
465
|
+
//
|
|
466
|
+
// contract
|
|
467
|
+
//
|
|
468
|
+
// {
|
|
469
|
+
// "topic": "tickers",
|
|
470
|
+
// "event": "tickers",
|
|
471
|
+
// "data": [
|
|
472
|
+
// {
|
|
473
|
+
// "s": "btc_index", // trading pair
|
|
474
|
+
// "o": "49000", // opening price
|
|
475
|
+
// "c": "50000", // closing price
|
|
476
|
+
// "h": "0.1", // highest price
|
|
477
|
+
// "l": "0.1", // lowest price
|
|
478
|
+
// "a": "0.1", // volume
|
|
479
|
+
// "v": "0.1", // turnover
|
|
480
|
+
// "ch": "0.21", // quote change
|
|
481
|
+
// "t": 123124124 // timestamp
|
|
482
|
+
// }
|
|
483
|
+
// ]
|
|
484
|
+
// }
|
|
485
|
+
//
|
|
486
|
+
// agg_ticker (contract)
|
|
487
|
+
//
|
|
488
|
+
// {
|
|
489
|
+
// "topic": "agg_tickers",
|
|
490
|
+
// "event": "agg_tickers",
|
|
491
|
+
// "data": [
|
|
492
|
+
// {
|
|
493
|
+
// "s": "btc_index", // trading pair
|
|
494
|
+
// "o": "49000", // opening price
|
|
495
|
+
// "c": "50000", // closing price
|
|
496
|
+
// "h": "0.1", // highest price
|
|
497
|
+
// "l": "0.1", // lowest price
|
|
498
|
+
// "a": "0.1", // volume
|
|
499
|
+
// "v": "0.1", // turnover
|
|
500
|
+
// "ch": "0.21", // quote change
|
|
501
|
+
// "i": "0.21" , // index price
|
|
502
|
+
// "m": "0.21", // mark price
|
|
503
|
+
// "bp": "0.21", // bid price
|
|
504
|
+
// "ap": "0.21" , // ask price
|
|
505
|
+
// "t": 123124124 // timestamp
|
|
506
|
+
// }
|
|
507
|
+
// ]
|
|
508
|
+
// }
|
|
509
|
+
//
|
|
510
|
+
const data = this.safeList(message, 'data', []);
|
|
511
|
+
const firstTicker = this.safeDict(data, 0);
|
|
512
|
+
const spotTest = this.safeString2(firstTicker, 'cv', 'aq');
|
|
513
|
+
const tradeType = (spotTest !== undefined) ? 'spot' : 'contract';
|
|
514
|
+
const newTickers = [];
|
|
515
|
+
for (let i = 0; i < data.length; i++) {
|
|
516
|
+
const tickerData = data[i];
|
|
517
|
+
const ticker = this.parseTicker(tickerData);
|
|
518
|
+
const symbol = ticker['symbol'];
|
|
519
|
+
this.tickers[symbol] = ticker;
|
|
520
|
+
newTickers.push(ticker);
|
|
521
|
+
}
|
|
522
|
+
const messageHashStart = this.safeString(message, 'topic') + '::' + tradeType;
|
|
523
|
+
const messageHashes = this.findMessageHashes(client, messageHashStart + '::');
|
|
524
|
+
for (let i = 0; i < messageHashes.length; i++) {
|
|
525
|
+
const messageHash = messageHashes[i];
|
|
526
|
+
const parts = messageHash.split('::');
|
|
527
|
+
const symbolsString = parts[2];
|
|
528
|
+
const symbols = symbolsString.split(',');
|
|
529
|
+
const tickers = this.filterByArray(newTickers, 'symbol', symbols);
|
|
530
|
+
const tickersSymbols = Object.keys(tickers);
|
|
531
|
+
const numTickers = tickersSymbols.length;
|
|
532
|
+
if (numTickers > 0) {
|
|
533
|
+
client.resolve(tickers, messageHash);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
client.resolve(this.tickers, messageHashStart);
|
|
537
|
+
return message;
|
|
538
|
+
}
|
|
539
|
+
handleOHLCV(client, message) {
|
|
540
|
+
//
|
|
541
|
+
// spot
|
|
542
|
+
//
|
|
543
|
+
// {
|
|
544
|
+
// "topic": "kline",
|
|
545
|
+
// "event": "kline@btc_usdt,5m",
|
|
546
|
+
// "data": {
|
|
547
|
+
// "s": "btc_usdt", // symbol
|
|
548
|
+
// "t": 1656043200000, // time
|
|
549
|
+
// "i": "5m", // interval
|
|
550
|
+
// "o": "44000", // open price
|
|
551
|
+
// "c": "50000", // close price
|
|
552
|
+
// "h": "52000", // highest price
|
|
553
|
+
// "l": "36000", // lowest price
|
|
554
|
+
// "q": "34.2", // qty(quantity)
|
|
555
|
+
// "v": "230000" // volume
|
|
556
|
+
// }
|
|
557
|
+
// }
|
|
558
|
+
//
|
|
559
|
+
// contract
|
|
560
|
+
//
|
|
561
|
+
// {
|
|
562
|
+
// "topic": "kline",
|
|
563
|
+
// "event": "kline@btc_usdt,5m",
|
|
564
|
+
// "data": {
|
|
565
|
+
// "s": "btc_index", // trading pair
|
|
566
|
+
// "o": "49000", // opening price
|
|
567
|
+
// "c": "50000", // closing price
|
|
568
|
+
// "h": "0.1", // highest price
|
|
569
|
+
// "l": "0.1", // lowest price
|
|
570
|
+
// "a": "0.1", // volume
|
|
571
|
+
// "v": "0.1", // turnover
|
|
572
|
+
// "ch": "0.21", // quote change
|
|
573
|
+
// "t": 123124124 // timestamp
|
|
574
|
+
// }
|
|
575
|
+
// }
|
|
576
|
+
//
|
|
577
|
+
const data = this.safeDict(message, 'data', {});
|
|
578
|
+
const marketId = this.safeString(data, 's');
|
|
579
|
+
if (marketId !== undefined) {
|
|
580
|
+
const timeframe = this.safeString(data, 'i');
|
|
581
|
+
const tradeType = ('q' in data) ? 'spot' : 'contract';
|
|
582
|
+
const market = this.safeMarket(marketId, undefined, undefined, tradeType);
|
|
583
|
+
const symbol = market['symbol'];
|
|
584
|
+
const parsed = this.parseOHLCV(data, market);
|
|
585
|
+
this.ohlcvs[symbol] = this.safeDict(this.ohlcvs, symbol, {});
|
|
586
|
+
let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
|
|
587
|
+
if (stored === undefined) {
|
|
588
|
+
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
589
|
+
stored = new Cache.ArrayCacheByTimestamp(limit);
|
|
590
|
+
this.ohlcvs[symbol][timeframe] = stored;
|
|
591
|
+
}
|
|
592
|
+
stored.append(parsed);
|
|
593
|
+
const event = this.safeString(message, 'event');
|
|
594
|
+
const messageHash = event + '::' + tradeType;
|
|
595
|
+
client.resolve(stored, messageHash);
|
|
596
|
+
}
|
|
597
|
+
return message;
|
|
598
|
+
}
|
|
599
|
+
handleTrade(client, message) {
|
|
600
|
+
//
|
|
601
|
+
// spot
|
|
602
|
+
//
|
|
603
|
+
// {
|
|
604
|
+
// topic: 'trade',
|
|
605
|
+
// event: 'trade@btc_usdt',
|
|
606
|
+
// data: {
|
|
607
|
+
// s: 'btc_usdt',
|
|
608
|
+
// i: '228825383103928709',
|
|
609
|
+
// t: 1684258222702,
|
|
610
|
+
// p: '27003.65',
|
|
611
|
+
// q: '0.000796',
|
|
612
|
+
// b: true
|
|
613
|
+
// }
|
|
614
|
+
// }
|
|
615
|
+
//
|
|
616
|
+
// contract
|
|
617
|
+
//
|
|
618
|
+
// {
|
|
619
|
+
// "topic": "trade",
|
|
620
|
+
// "event": "trade@btc_usdt",
|
|
621
|
+
// "data": {
|
|
622
|
+
// "s": "btc_index", // trading pair
|
|
623
|
+
// "p": "50000", // price
|
|
624
|
+
// "a": "0.1" // Quantity
|
|
625
|
+
// "m": "BID" // Deal side BID:Buy ASK:Sell
|
|
626
|
+
// "t": 123124124 // timestamp
|
|
627
|
+
// }
|
|
628
|
+
// }
|
|
629
|
+
//
|
|
630
|
+
const data = this.safeDict(message, 'data');
|
|
631
|
+
const marketId = this.safeStringLower(data, 's');
|
|
632
|
+
if (marketId !== undefined) {
|
|
633
|
+
const trade = this.parseTrade(data);
|
|
634
|
+
const i = this.safeString(data, 'i');
|
|
635
|
+
const tradeType = (i !== undefined) ? 'spot' : 'contract';
|
|
636
|
+
const market = this.safeMarket(marketId, undefined, undefined, tradeType);
|
|
637
|
+
const symbol = market['symbol'];
|
|
638
|
+
const event = this.safeString(message, 'event');
|
|
639
|
+
let tradesArray = this.safeValue(this.trades, symbol);
|
|
640
|
+
if (tradesArray === undefined) {
|
|
641
|
+
const tradesLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
642
|
+
tradesArray = new Cache.ArrayCache(tradesLimit);
|
|
643
|
+
this.trades[symbol] = tradesArray;
|
|
644
|
+
}
|
|
645
|
+
tradesArray.append(trade);
|
|
646
|
+
const messageHash = event + '::' + tradeType;
|
|
647
|
+
client.resolve(tradesArray, messageHash);
|
|
648
|
+
}
|
|
649
|
+
return message;
|
|
650
|
+
}
|
|
651
|
+
handleOrderBook(client, message) {
|
|
652
|
+
//
|
|
653
|
+
// spot
|
|
654
|
+
//
|
|
655
|
+
// {
|
|
656
|
+
// "topic": "depth",
|
|
657
|
+
// "event": "depth@btc_usdt,20",
|
|
658
|
+
// "data": {
|
|
659
|
+
// "s": "btc_usdt", // symbol
|
|
660
|
+
// "fi": 1681433733351, // firstUpdateId = previous lastUpdateId + 1
|
|
661
|
+
// "i": 1681433733371, // updateId
|
|
662
|
+
// "a": [ // asks(sell order)
|
|
663
|
+
// [ // [0]price, [1]quantity
|
|
664
|
+
// "34000", // price
|
|
665
|
+
// "1.2" // quantity
|
|
666
|
+
// ],
|
|
667
|
+
// [
|
|
668
|
+
// "34001",
|
|
669
|
+
// "2.3"
|
|
670
|
+
// ]
|
|
671
|
+
// ],
|
|
672
|
+
// "b": [ // bids(buy order)
|
|
673
|
+
// [
|
|
674
|
+
// "32000",
|
|
675
|
+
// "0.2"
|
|
676
|
+
// ],
|
|
677
|
+
// [
|
|
678
|
+
// "31000",
|
|
679
|
+
// "0.5"
|
|
680
|
+
// ]
|
|
681
|
+
// ]
|
|
682
|
+
// }
|
|
683
|
+
// }
|
|
684
|
+
//
|
|
685
|
+
// contract
|
|
686
|
+
//
|
|
687
|
+
// {
|
|
688
|
+
// "topic": "depth",
|
|
689
|
+
// "event": "depth@btc_usdt,20",
|
|
690
|
+
// "data": {
|
|
691
|
+
// s: "btc_usdt",
|
|
692
|
+
// pu: "548111455664",
|
|
693
|
+
// fu: "548111455665",
|
|
694
|
+
// u: "548111455667",
|
|
695
|
+
// a: [
|
|
696
|
+
// [
|
|
697
|
+
// "26841.5",
|
|
698
|
+
// "50210",
|
|
699
|
+
// ],
|
|
700
|
+
// ],
|
|
701
|
+
// b: [
|
|
702
|
+
// [
|
|
703
|
+
// "26841",
|
|
704
|
+
// "67075",
|
|
705
|
+
// ],
|
|
706
|
+
// ],
|
|
707
|
+
// t: 1684530667083,
|
|
708
|
+
// }
|
|
709
|
+
// }
|
|
710
|
+
//
|
|
711
|
+
const data = this.safeDict(message, 'data');
|
|
712
|
+
const marketId = this.safeString(data, 's');
|
|
713
|
+
if (marketId !== undefined) {
|
|
714
|
+
let event = this.safeString(message, 'event');
|
|
715
|
+
const splitEvent = event.split(',');
|
|
716
|
+
event = this.safeString(splitEvent, 0);
|
|
717
|
+
const tradeType = ('fu' in data) ? 'contract' : 'spot';
|
|
718
|
+
const market = this.safeMarket(marketId, undefined, undefined, tradeType);
|
|
719
|
+
const symbol = market['symbol'];
|
|
720
|
+
const obAsks = this.safeList(data, 'a');
|
|
721
|
+
const obBids = this.safeList(data, 'b');
|
|
722
|
+
const messageHash = event + '::' + tradeType;
|
|
723
|
+
if (!(symbol in this.orderbooks)) {
|
|
724
|
+
const subscription = this.safeDict(client.subscriptions, messageHash, {});
|
|
725
|
+
const limit = this.safeInteger(subscription, 'limit');
|
|
726
|
+
this.orderbooks[symbol] = this.orderBook({}, limit);
|
|
727
|
+
}
|
|
728
|
+
const orderbook = this.orderbooks[symbol];
|
|
729
|
+
const nonce = this.safeInteger(orderbook, 'nonce');
|
|
730
|
+
if (nonce === undefined) {
|
|
731
|
+
const cacheLength = orderbook.cache.length;
|
|
732
|
+
const snapshotDelay = this.handleOption('watchOrderBook', 'snapshotDelay', 25);
|
|
733
|
+
if (cacheLength === snapshotDelay) {
|
|
734
|
+
this.spawn(this.loadOrderBook, client, messageHash, symbol);
|
|
735
|
+
}
|
|
736
|
+
orderbook.cache.push(data);
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (obAsks !== undefined) {
|
|
740
|
+
const asks = orderbook['asks'];
|
|
741
|
+
for (let i = 0; i < obAsks.length; i++) {
|
|
742
|
+
const ask = obAsks[i];
|
|
743
|
+
const price = this.safeNumber(ask, 0);
|
|
744
|
+
const quantity = this.safeNumber(ask, 1);
|
|
745
|
+
asks.store(price, quantity);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
if (obBids !== undefined) {
|
|
749
|
+
const bids = orderbook['bids'];
|
|
750
|
+
for (let i = 0; i < obBids.length; i++) {
|
|
751
|
+
const bid = obBids[i];
|
|
752
|
+
const price = this.safeNumber(bid, 0);
|
|
753
|
+
const quantity = this.safeNumber(bid, 1);
|
|
754
|
+
bids.store(price, quantity);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
const timestamp = this.safeInteger(data, 't');
|
|
758
|
+
orderbook['nonce'] = this.safeInteger2(data, 'i', 'u');
|
|
759
|
+
orderbook['timestamp'] = timestamp;
|
|
760
|
+
orderbook['datetime'] = this.iso8601(timestamp);
|
|
761
|
+
orderbook['symbol'] = symbol;
|
|
762
|
+
client.resolve(orderbook, messageHash);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
parseWsOrderTrade(trade, market = undefined) {
|
|
766
|
+
//
|
|
767
|
+
// {
|
|
768
|
+
// "s": "btc_usdt", // symbol
|
|
769
|
+
// "t": 1656043204763, // time happened time
|
|
770
|
+
// "i": "6216559590087220004", // orderId,
|
|
771
|
+
// "ci": "test123", // clientOrderId
|
|
772
|
+
// "st": "PARTIALLY_FILLED", // state
|
|
773
|
+
// "sd": "BUY", // side BUY/SELL
|
|
774
|
+
// "eq": "2", // executedQty executed quantity
|
|
775
|
+
// "ap": "30000", // avg price
|
|
776
|
+
// "f": "0.002" // fee
|
|
777
|
+
// }
|
|
778
|
+
//
|
|
779
|
+
// contract
|
|
780
|
+
//
|
|
781
|
+
// {
|
|
782
|
+
// "symbol": "btc_usdt", // Trading pair
|
|
783
|
+
// "orderId": "1234", // Order Id
|
|
784
|
+
// "origQty": "34244", // Original Quantity
|
|
785
|
+
// "avgPrice": "123", // Quantity
|
|
786
|
+
// "price": "1111", // Average price
|
|
787
|
+
// "executedQty": "34244", // Volume (Cont)
|
|
788
|
+
// "orderSide": "BUY", // BUY, SELL
|
|
789
|
+
// "positionSide": "LONG", // LONG, SHORT
|
|
790
|
+
// "marginFrozen": "123", // Occupied margin
|
|
791
|
+
// "sourceType": "default", // DEFAULT:normal order,ENTRUST:plan commission,PROFIR:Take Profit and Stop Loss
|
|
792
|
+
// "sourceId" : "1231231", // Triggering conditions ID
|
|
793
|
+
// "state": "", // state:NEW:New order (unfilled);PARTIALLY_FILLED:Partial deal;PARTIALLY_CANCELED:Partial revocation;FILLED:Filled;CANCELED:Cancled;REJECTED:Order failed;EXPIRED:Expired
|
|
794
|
+
// "createTime": 1731231231, // CreateTime
|
|
795
|
+
// "clientOrderId": "204788317630342726"
|
|
796
|
+
// }
|
|
797
|
+
//
|
|
798
|
+
const marketId = this.safeString(trade, 's');
|
|
799
|
+
const tradeType = ('symbol' in trade) ? 'contract' : 'spot';
|
|
800
|
+
market = this.safeMarket(marketId, market, undefined, tradeType);
|
|
801
|
+
const timestamp = this.safeString(trade, 't');
|
|
802
|
+
return this.safeTrade({
|
|
803
|
+
'info': trade,
|
|
804
|
+
'id': undefined,
|
|
805
|
+
'timestamp': timestamp,
|
|
806
|
+
'datetime': this.iso8601(timestamp),
|
|
807
|
+
'symbol': market['symbol'],
|
|
808
|
+
'order': this.safeString(trade, 'i', 'orderId'),
|
|
809
|
+
'type': this.parseOrderStatus(this.safeString(trade, 'st', 'state')),
|
|
810
|
+
'side': this.safeStringLower(trade, 'sd', 'orderSide'),
|
|
811
|
+
'takerOrMaker': undefined,
|
|
812
|
+
'price': this.safeNumber(trade, 'price'),
|
|
813
|
+
'amount': this.safeString(trade, 'origQty'),
|
|
814
|
+
'cost': undefined,
|
|
815
|
+
'fee': {
|
|
816
|
+
'currency': undefined,
|
|
817
|
+
'cost': this.safeNumber(trade, 'f'),
|
|
818
|
+
'rate': undefined,
|
|
819
|
+
},
|
|
820
|
+
}, market);
|
|
821
|
+
}
|
|
822
|
+
parseWsOrder(order, market = undefined) {
|
|
823
|
+
//
|
|
824
|
+
// spot
|
|
825
|
+
//
|
|
826
|
+
// {
|
|
827
|
+
// "s": "btc_usdt", // symbol
|
|
828
|
+
// "bc": "btc", // base currency
|
|
829
|
+
// "qc": "usdt", // quotation currency
|
|
830
|
+
// "t": 1656043204763, // happened time
|
|
831
|
+
// "ct": 1656043204663, // create time
|
|
832
|
+
// "i": "6216559590087220004", // order id,
|
|
833
|
+
// "ci": "test123", // client order id
|
|
834
|
+
// "st": "PARTIALLY_FILLED", // state NEW/PARTIALLY_FILLED/FILLED/CANCELED/REJECTED/EXPIRED
|
|
835
|
+
// "sd": "BUY", // side BUY/SELL
|
|
836
|
+
// "tp": "LIMIT", // type LIMIT/MARKET
|
|
837
|
+
// "oq": "4" // original quantity
|
|
838
|
+
// "oqq": 48000, // original quotation quantity
|
|
839
|
+
// "eq": "2", // executed quantity
|
|
840
|
+
// "lq": "2", // remaining quantity
|
|
841
|
+
// "p": "4000", // price
|
|
842
|
+
// "ap": "30000", // avg price
|
|
843
|
+
// "f":"0.002" // fee
|
|
844
|
+
// }
|
|
845
|
+
//
|
|
846
|
+
// contract
|
|
847
|
+
//
|
|
848
|
+
// {
|
|
849
|
+
// "symbol": "btc_usdt", // Trading pair
|
|
850
|
+
// "orderId": "1234", // Order Id
|
|
851
|
+
// "origQty": "34244", // Original Quantity
|
|
852
|
+
// "avgPrice": "123", // Quantity
|
|
853
|
+
// "price": "1111", // Average price
|
|
854
|
+
// "executedQty": "34244", // Volume (Cont)
|
|
855
|
+
// "orderSide": "BUY", // BUY, SELL
|
|
856
|
+
// "positionSide": "LONG", // LONG, SHORT
|
|
857
|
+
// "marginFrozen": "123", // Occupied margin
|
|
858
|
+
// "sourceType": "default", // DEFAULT:normal order,ENTRUST:plan commission,PROFIR:Take Profit and Stop Loss
|
|
859
|
+
// "sourceId" : "1231231", // Triggering conditions ID
|
|
860
|
+
// "state": "", // state:NEW:New order (unfilled);PARTIALLY_FILLED:Partial deal;PARTIALLY_CANCELED:Partial revocation;FILLED:Filled;CANCELED:Cancled;REJECTED:Order failed;EXPIRED:Expired
|
|
861
|
+
// "createTime": 1731231231, // CreateTime
|
|
862
|
+
// "clientOrderId": "204788317630342726"
|
|
863
|
+
// }
|
|
864
|
+
//
|
|
865
|
+
const marketId = this.safeString2(order, 's', 'symbol');
|
|
866
|
+
const tradeType = ('symbol' in order) ? 'contract' : 'spot';
|
|
867
|
+
market = this.safeMarket(marketId, market, undefined, tradeType);
|
|
868
|
+
const timestamp = this.safeInteger2(order, 'ct', 'createTime');
|
|
869
|
+
return this.safeOrder({
|
|
870
|
+
'info': order,
|
|
871
|
+
'id': this.safeString2(order, 'i', 'orderId'),
|
|
872
|
+
'clientOrderId': this.safeString2(order, 'ci', 'clientOrderId'),
|
|
873
|
+
'timestamp': timestamp,
|
|
874
|
+
'datetime': this.iso8601(timestamp),
|
|
875
|
+
'lastTradeTimestamp': undefined,
|
|
876
|
+
'symbol': market['symbol'],
|
|
877
|
+
'type': market['type'],
|
|
878
|
+
'timeInForce': undefined,
|
|
879
|
+
'postOnly': undefined,
|
|
880
|
+
'side': this.safeStringLower2(order, 'sd', 'orderSide'),
|
|
881
|
+
'price': this.safeNumber2(order, 'p', 'price'),
|
|
882
|
+
'stopPrice': undefined,
|
|
883
|
+
'stopLoss': undefined,
|
|
884
|
+
'takeProfit': undefined,
|
|
885
|
+
'amount': this.safeString2(order, 'oq', 'origQty'),
|
|
886
|
+
'filled': this.safeString2(order, 'eq', 'executedQty'),
|
|
887
|
+
'remaining': this.safeString(order, 'lq'),
|
|
888
|
+
'cost': undefined,
|
|
889
|
+
'average': this.safeString2(order, 'ap', 'avgPrice'),
|
|
890
|
+
'status': this.parseOrderStatus(this.safeString(order, 'st', 'state')),
|
|
891
|
+
'fee': {
|
|
892
|
+
'currency': undefined,
|
|
893
|
+
'cost': this.safeNumber(order, 'f'),
|
|
894
|
+
},
|
|
895
|
+
'trades': undefined,
|
|
896
|
+
}, market);
|
|
897
|
+
}
|
|
898
|
+
handleOrder(client, message) {
|
|
899
|
+
//
|
|
900
|
+
// spot
|
|
901
|
+
//
|
|
902
|
+
// {
|
|
903
|
+
// "topic": "order",
|
|
904
|
+
// "event": "order",
|
|
905
|
+
// "data": {
|
|
906
|
+
// "s": "btc_usdt", // symbol
|
|
907
|
+
// "t": 1656043204763, // time happened time
|
|
908
|
+
// "i": "6216559590087220004", // orderId,
|
|
909
|
+
// "ci": "test123", // clientOrderId
|
|
910
|
+
// "st": "PARTIALLY_FILLED", // state
|
|
911
|
+
// "sd": "BUY", // side BUY/SELL
|
|
912
|
+
// "eq": "2", // executedQty executed quantity
|
|
913
|
+
// "ap": "30000", // avg price
|
|
914
|
+
// "f": "0.002" // fee
|
|
915
|
+
// }
|
|
916
|
+
// }
|
|
917
|
+
//
|
|
918
|
+
// contract
|
|
919
|
+
//
|
|
920
|
+
// {
|
|
921
|
+
// "topic": "order",
|
|
922
|
+
// "event": "order@123456",
|
|
923
|
+
// "data": {
|
|
924
|
+
// "symbol": "btc_usdt", // Trading pair
|
|
925
|
+
// "orderId": "1234", // Order Id
|
|
926
|
+
// "origQty": "34244", // Original Quantity
|
|
927
|
+
// "avgPrice": "123", // Quantity
|
|
928
|
+
// "price": "1111", // Average price
|
|
929
|
+
// "executedQty": "34244", // Volume (Cont)
|
|
930
|
+
// "orderSide": "BUY", // BUY, SELL
|
|
931
|
+
// "positionSide": "LONG", // LONG, SHORT
|
|
932
|
+
// "marginFrozen": "123", // Occupied margin
|
|
933
|
+
// "sourceType": "default", // DEFAULT:normal order,ENTRUST:plan commission,PROFIR:Take Profit and Stop Loss
|
|
934
|
+
// "sourceId" : "1231231", // Triggering conditions ID
|
|
935
|
+
// "state": "", // state:NEW:New order (unfilled);PARTIALLY_FILLED:Partial deal;PARTIALLY_CANCELED:Partial revocation;FILLED:Filled;CANCELED:Cancled;REJECTED:Order failed;EXPIRED:Expired
|
|
936
|
+
// "createTime": 1731231231, // CreateTime
|
|
937
|
+
// "clientOrderId": "204788317630342726"
|
|
938
|
+
// }
|
|
939
|
+
// }
|
|
940
|
+
//
|
|
941
|
+
let orders = this.orders;
|
|
942
|
+
if (orders === undefined) {
|
|
943
|
+
const limit = this.safeInteger(this.options, 'ordersLimit');
|
|
944
|
+
orders = new Cache.ArrayCacheBySymbolById(limit);
|
|
945
|
+
this.orders = orders;
|
|
946
|
+
}
|
|
947
|
+
const order = this.safeDict(message, 'data', {});
|
|
948
|
+
const marketId = this.safeString2(order, 's', 'symbol');
|
|
949
|
+
if (marketId !== undefined) {
|
|
950
|
+
const tradeType = ('symbol' in order) ? 'contract' : 'spot';
|
|
951
|
+
const market = this.safeMarket(marketId, undefined, undefined, tradeType);
|
|
952
|
+
const parsed = this.parseWsOrder(order, market);
|
|
953
|
+
orders.append(parsed);
|
|
954
|
+
client.resolve(orders, 'order::' + tradeType);
|
|
955
|
+
}
|
|
956
|
+
return message;
|
|
957
|
+
}
|
|
958
|
+
handleBalance(client, message) {
|
|
959
|
+
//
|
|
960
|
+
// spot
|
|
961
|
+
//
|
|
962
|
+
// {
|
|
963
|
+
// topic: 'balance',
|
|
964
|
+
// event: 'balance',
|
|
965
|
+
// data: {
|
|
966
|
+
// a: 3513677381884,
|
|
967
|
+
// t: 1684250056775,
|
|
968
|
+
// c: 'usdt',
|
|
969
|
+
// b: '7.71000000',
|
|
970
|
+
// f: '0.00000000',
|
|
971
|
+
// z: 'SPOT'
|
|
972
|
+
// }
|
|
973
|
+
// }
|
|
974
|
+
//
|
|
975
|
+
// contract
|
|
976
|
+
//
|
|
977
|
+
// {
|
|
978
|
+
// "topic": "balance",
|
|
979
|
+
// "event": "balance@123456",
|
|
980
|
+
// "data": {
|
|
981
|
+
// "coin": "usdt",
|
|
982
|
+
// "underlyingType": 1, // 1:Coin-M,2:USDT-M
|
|
983
|
+
// "walletBalance": "123", // Balance
|
|
984
|
+
// "openOrderMarginFrozen": "123", // Frozen order
|
|
985
|
+
// "isolatedMargin": "213", // Isolated Margin
|
|
986
|
+
// "crossedMargin": "0" // Crossed Margin
|
|
987
|
+
// "availableBalance": '2.256114450000000000',
|
|
988
|
+
// "coupon": '0',
|
|
989
|
+
// "bonus": '0'
|
|
990
|
+
// }
|
|
991
|
+
// }
|
|
992
|
+
//
|
|
993
|
+
const data = this.safeDict(message, 'data', {});
|
|
994
|
+
const currencyId = this.safeString2(data, 'c', 'coin');
|
|
995
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
996
|
+
const account = this.account();
|
|
997
|
+
account['free'] = this.safeString(data, 'availableBalance');
|
|
998
|
+
account['used'] = this.safeString(data, 'f');
|
|
999
|
+
account['total'] = this.safeString2(data, 'b', 'walletBalance');
|
|
1000
|
+
this.balance[code] = account;
|
|
1001
|
+
this.balance = this.safeBalance(this.balance);
|
|
1002
|
+
const tradeType = ('coin' in data) ? 'contract' : 'spot';
|
|
1003
|
+
client.resolve(this.balance, 'balance::' + tradeType);
|
|
1004
|
+
}
|
|
1005
|
+
handleMyTrades(client, message) {
|
|
1006
|
+
//
|
|
1007
|
+
// spot
|
|
1008
|
+
//
|
|
1009
|
+
// {
|
|
1010
|
+
// "topic": "trade",
|
|
1011
|
+
// "event": "trade",
|
|
1012
|
+
// "data": {
|
|
1013
|
+
// "s": "btc_usdt", // symbol
|
|
1014
|
+
// "t": 1656043204763, // time
|
|
1015
|
+
// "i": "6316559590087251233", // tradeId
|
|
1016
|
+
// "oi": "6216559590087220004", // orderId
|
|
1017
|
+
// "p": "30000", // trade price
|
|
1018
|
+
// "q": "3", // qty quantity
|
|
1019
|
+
// "v": "90000" // volume trade amount
|
|
1020
|
+
// }
|
|
1021
|
+
// }
|
|
1022
|
+
//
|
|
1023
|
+
// contract
|
|
1024
|
+
//
|
|
1025
|
+
// {
|
|
1026
|
+
// "topic": "trade",
|
|
1027
|
+
// "event": "trade@123456",
|
|
1028
|
+
// "data": {
|
|
1029
|
+
// "symbol": 'btc_usdt',
|
|
1030
|
+
// "orderSide": 'SELL',
|
|
1031
|
+
// "positionSide": 'LONG',
|
|
1032
|
+
// "orderId": '231485367663419328',
|
|
1033
|
+
// "price": '27152.7',
|
|
1034
|
+
// "quantity": '33',
|
|
1035
|
+
// "marginUnfrozen": '2.85318000',
|
|
1036
|
+
// "timestamp": 1684892412565
|
|
1037
|
+
// }
|
|
1038
|
+
// }
|
|
1039
|
+
//
|
|
1040
|
+
const data = this.safeDict(message, 'data', {});
|
|
1041
|
+
let stored = this.myTrades;
|
|
1042
|
+
if (stored === undefined) {
|
|
1043
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
1044
|
+
stored = new Cache.ArrayCacheBySymbolById(limit);
|
|
1045
|
+
this.myTrades = stored;
|
|
1046
|
+
}
|
|
1047
|
+
const parsedTrade = this.parseTrade(data);
|
|
1048
|
+
const market = this.market(parsedTrade['symbol']);
|
|
1049
|
+
stored.append(parsedTrade);
|
|
1050
|
+
const tradeType = market['contract'] ? 'contract' : 'spot';
|
|
1051
|
+
client.resolve(stored, 'trade::' + tradeType);
|
|
1052
|
+
}
|
|
1053
|
+
handleMessage(client, message) {
|
|
1054
|
+
const event = this.safeString(message, 'event');
|
|
1055
|
+
if (event === 'pong') {
|
|
1056
|
+
client.onPong();
|
|
1057
|
+
}
|
|
1058
|
+
else if (event !== undefined) {
|
|
1059
|
+
const topic = this.safeString(message, 'topic');
|
|
1060
|
+
const methods = {
|
|
1061
|
+
'kline': this.handleOHLCV,
|
|
1062
|
+
'depth': this.handleOrderBook,
|
|
1063
|
+
'depth_update': this.handleOrderBook,
|
|
1064
|
+
'ticker': this.handleTicker,
|
|
1065
|
+
'agg_ticker': this.handleTicker,
|
|
1066
|
+
'tickers': this.handleTickers,
|
|
1067
|
+
'agg_tickers': this.handleTickers,
|
|
1068
|
+
'balance': this.handleBalance,
|
|
1069
|
+
'order': this.handleOrder,
|
|
1070
|
+
};
|
|
1071
|
+
let method = this.safeValue(methods, topic);
|
|
1072
|
+
if (topic === 'trade') {
|
|
1073
|
+
const data = this.safeDict(message, 'data');
|
|
1074
|
+
if (('oi' in data) || ('orderId' in data)) {
|
|
1075
|
+
method = this.handleMyTrades;
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
method = this.handleTrade;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
if (method !== undefined) {
|
|
1082
|
+
method.call(this, client, message);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
ping(client) {
|
|
1087
|
+
client.lastPong = this.milliseconds();
|
|
1088
|
+
return 'ping';
|
|
1089
|
+
}
|
|
1090
|
+
handleErrorMessage(client, message) {
|
|
1091
|
+
//
|
|
1092
|
+
// {
|
|
1093
|
+
// "id": "123",
|
|
1094
|
+
// "code": 401,
|
|
1095
|
+
// "msg": "token expire"
|
|
1096
|
+
// }
|
|
1097
|
+
//
|
|
1098
|
+
const msg = this.safeString(message, 'msg');
|
|
1099
|
+
if ((msg === 'invalid_listen_key') || (msg === 'token expire')) {
|
|
1100
|
+
client.subscriptions['token'] = undefined;
|
|
1101
|
+
this.getListenKey(true);
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
client.reject(message);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
module.exports = xt;
|