ccxt 4.4.85 → 4.4.86
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 +6 -7
- package/dist/ccxt.browser.min.js +2 -2
- package/dist/cjs/ccxt.js +6 -9
- package/dist/cjs/src/abstract/bittrade.js +9 -0
- package/dist/cjs/src/ascendex.js +189 -155
- package/dist/cjs/src/bequant.js +1 -1
- package/dist/cjs/src/bitget.js +5 -4
- package/dist/cjs/src/bitmart.js +1 -1
- package/dist/cjs/src/bittrade.js +2049 -0
- package/dist/cjs/src/coinbase.js +2 -6
- package/dist/cjs/src/deribit.js +4 -5
- package/dist/cjs/src/hollaex.js +107 -49
- package/dist/cjs/src/htx.js +20 -44
- package/dist/cjs/src/hyperliquid.js +4 -4
- package/dist/cjs/src/mexc.js +2 -2
- package/dist/cjs/src/ndax.js +25 -24
- package/dist/cjs/src/okcoin.js +12 -31
- package/dist/cjs/src/okx.js +9 -0
- package/dist/cjs/src/onetrading.js +9 -6
- package/dist/cjs/src/oxfun.js +42 -114
- package/dist/cjs/src/paradex.js +5 -1
- package/dist/cjs/src/pro/binance.js +1 -0
- package/dist/cjs/src/pro/bittrade.js +605 -0
- package/dist/cjs/src/pro/luno.js +6 -5
- package/dist/cjs/src/pro/mexc.js +3 -0
- package/js/ccxt.d.ts +8 -11
- package/js/ccxt.js +6 -8
- package/js/src/abstract/myokx.d.ts +2 -0
- package/js/src/abstract/okx.d.ts +2 -0
- package/js/src/ascendex.d.ts +2 -0
- package/js/src/ascendex.js +189 -155
- package/js/src/bequant.js +1 -1
- package/js/src/bitget.js +5 -4
- package/js/src/bitmart.js +1 -1
- package/js/src/{huobijp.d.ts → bittrade.d.ts} +29 -29
- package/js/src/{huobijp.js → bittrade.js} +35 -35
- package/js/src/coinbase.js +2 -6
- package/js/src/deribit.js +4 -5
- package/js/src/hollaex.js +107 -49
- package/js/src/htx.js +20 -44
- package/js/src/hyperliquid.js +4 -4
- package/js/src/mexc.js +2 -2
- package/js/src/ndax.js +25 -24
- package/js/src/okcoin.js +12 -31
- package/js/src/okx.js +9 -0
- package/js/src/onetrading.js +9 -6
- package/js/src/oxfun.js +42 -114
- package/js/src/paradex.js +5 -1
- package/js/src/pro/binance.js +1 -0
- package/js/src/pro/{huobijp.d.ts → bittrade.d.ts} +6 -6
- package/js/src/pro/{huobijp.js → bittrade.js} +7 -7
- package/js/src/pro/luno.js +6 -5
- package/js/src/pro/mexc.js +3 -0
- package/package.json +1 -1
- package/js/src/abstract/kuna.d.ts +0 -185
- package/js/src/abstract/kuna.js +0 -11
- package/js/src/kuna.d.ts +0 -335
- package/js/src/kuna.js +0 -2006
- /package/js/src/abstract/{huobijp.d.ts → bittrade.d.ts} +0 -0
- /package/js/src/abstract/{huobijp.js → bittrade.js} +0 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var bittrade$1 = require('../bittrade.js');
|
|
4
|
+
var errors = require('../base/errors.js');
|
|
5
|
+
var Cache = require('../base/ws/Cache.js');
|
|
6
|
+
|
|
7
|
+
// ----------------------------------------------------------------------------
|
|
8
|
+
// ----------------------------------------------------------------------------
|
|
9
|
+
class bittrade extends bittrade$1 {
|
|
10
|
+
describe() {
|
|
11
|
+
return this.deepExtend(super.describe(), {
|
|
12
|
+
'has': {
|
|
13
|
+
'ws': true,
|
|
14
|
+
'watchOrderBook': true,
|
|
15
|
+
'watchTickers': false,
|
|
16
|
+
'watchTicker': true,
|
|
17
|
+
'watchTrades': true,
|
|
18
|
+
'watchTradesForSymbols': false,
|
|
19
|
+
'watchBalance': false,
|
|
20
|
+
'watchOHLCV': true,
|
|
21
|
+
},
|
|
22
|
+
'urls': {
|
|
23
|
+
'api': {
|
|
24
|
+
'ws': {
|
|
25
|
+
'api': {
|
|
26
|
+
'public': 'wss://{hostname}/ws',
|
|
27
|
+
'private': 'wss://{hostname}/ws/v2',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
'options': {
|
|
33
|
+
'tradesLimit': 1000,
|
|
34
|
+
'OHLCVLimit': 1000,
|
|
35
|
+
'api': 'api',
|
|
36
|
+
'ws': {
|
|
37
|
+
'gunzip': true,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
requestId() {
|
|
43
|
+
const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
|
|
44
|
+
this.options['requestId'] = requestId;
|
|
45
|
+
return requestId.toString();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* @method
|
|
49
|
+
* @name bittrade#watchTicker
|
|
50
|
+
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
51
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
52
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
53
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
54
|
+
*/
|
|
55
|
+
async watchTicker(symbol, params = {}) {
|
|
56
|
+
await this.loadMarkets();
|
|
57
|
+
const market = this.market(symbol);
|
|
58
|
+
symbol = market['symbol'];
|
|
59
|
+
// only supports a limit of 150 at this time
|
|
60
|
+
const messageHash = 'market.' + market['id'] + '.detail';
|
|
61
|
+
const api = this.safeString(this.options, 'api', 'api');
|
|
62
|
+
const hostname = { 'hostname': this.hostname };
|
|
63
|
+
const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
|
|
64
|
+
const requestId = this.requestId();
|
|
65
|
+
const request = {
|
|
66
|
+
'sub': messageHash,
|
|
67
|
+
'id': requestId,
|
|
68
|
+
};
|
|
69
|
+
const subscription = {
|
|
70
|
+
'id': requestId,
|
|
71
|
+
'messageHash': messageHash,
|
|
72
|
+
'symbol': symbol,
|
|
73
|
+
'params': params,
|
|
74
|
+
};
|
|
75
|
+
return await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
|
|
76
|
+
}
|
|
77
|
+
handleTicker(client, message) {
|
|
78
|
+
//
|
|
79
|
+
// {
|
|
80
|
+
// "ch": "market.btcusdt.detail",
|
|
81
|
+
// "ts": 1583494163784,
|
|
82
|
+
// "tick": {
|
|
83
|
+
// "id": 209988464418,
|
|
84
|
+
// "low": 8988,
|
|
85
|
+
// "high": 9155.41,
|
|
86
|
+
// "open": 9078.91,
|
|
87
|
+
// "close": 9136.46,
|
|
88
|
+
// "vol": 237813910.5928412,
|
|
89
|
+
// "amount": 26184.202558551195,
|
|
90
|
+
// "version": 209988464418,
|
|
91
|
+
// "count": 265673
|
|
92
|
+
// }
|
|
93
|
+
// }
|
|
94
|
+
//
|
|
95
|
+
const tick = this.safeValue(message, 'tick', {});
|
|
96
|
+
const ch = this.safeString(message, 'ch');
|
|
97
|
+
const parts = ch.split('.');
|
|
98
|
+
const marketId = this.safeString(parts, 1);
|
|
99
|
+
const market = this.safeMarket(marketId);
|
|
100
|
+
const ticker = this.parseTicker(tick, market);
|
|
101
|
+
const timestamp = this.safeValue(message, 'ts');
|
|
102
|
+
ticker['timestamp'] = timestamp;
|
|
103
|
+
ticker['datetime'] = this.iso8601(timestamp);
|
|
104
|
+
const symbol = ticker['symbol'];
|
|
105
|
+
this.tickers[symbol] = ticker;
|
|
106
|
+
client.resolve(ticker, ch);
|
|
107
|
+
return message;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* @method
|
|
111
|
+
* @name bittrade#watchTrades
|
|
112
|
+
* @description get the list of most recent trades for a particular symbol
|
|
113
|
+
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
114
|
+
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
115
|
+
* @param {int} [limit] the maximum amount of trades to fetch
|
|
116
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
117
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
118
|
+
*/
|
|
119
|
+
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
120
|
+
await this.loadMarkets();
|
|
121
|
+
const market = this.market(symbol);
|
|
122
|
+
symbol = market['symbol'];
|
|
123
|
+
// only supports a limit of 150 at this time
|
|
124
|
+
const messageHash = 'market.' + market['id'] + '.trade.detail';
|
|
125
|
+
const api = this.safeString(this.options, 'api', 'api');
|
|
126
|
+
const hostname = { 'hostname': this.hostname };
|
|
127
|
+
const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
|
|
128
|
+
const requestId = this.requestId();
|
|
129
|
+
const request = {
|
|
130
|
+
'sub': messageHash,
|
|
131
|
+
'id': requestId,
|
|
132
|
+
};
|
|
133
|
+
const subscription = {
|
|
134
|
+
'id': requestId,
|
|
135
|
+
'messageHash': messageHash,
|
|
136
|
+
'symbol': symbol,
|
|
137
|
+
'params': params,
|
|
138
|
+
};
|
|
139
|
+
const trades = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
|
|
140
|
+
if (this.newUpdates) {
|
|
141
|
+
limit = trades.getLimit(symbol, limit);
|
|
142
|
+
}
|
|
143
|
+
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
|
|
144
|
+
}
|
|
145
|
+
handleTrades(client, message) {
|
|
146
|
+
//
|
|
147
|
+
// {
|
|
148
|
+
// "ch": "market.btcusdt.trade.detail",
|
|
149
|
+
// "ts": 1583495834011,
|
|
150
|
+
// "tick": {
|
|
151
|
+
// "id": 105004645372,
|
|
152
|
+
// "ts": 1583495833751,
|
|
153
|
+
// "data": [
|
|
154
|
+
// {
|
|
155
|
+
// "id": 1.050046453727319e+22,
|
|
156
|
+
// "ts": 1583495833751,
|
|
157
|
+
// "tradeId": 102090727790,
|
|
158
|
+
// "amount": 0.003893,
|
|
159
|
+
// "price": 9150.01,
|
|
160
|
+
// "direction": "sell"
|
|
161
|
+
// }
|
|
162
|
+
// ]
|
|
163
|
+
// }
|
|
164
|
+
// }
|
|
165
|
+
//
|
|
166
|
+
const tick = this.safeValue(message, 'tick', {});
|
|
167
|
+
const data = this.safeValue(tick, 'data', {});
|
|
168
|
+
const ch = this.safeString(message, 'ch');
|
|
169
|
+
const parts = ch.split('.');
|
|
170
|
+
const marketId = this.safeString(parts, 1);
|
|
171
|
+
const market = this.safeMarket(marketId);
|
|
172
|
+
const symbol = market['symbol'];
|
|
173
|
+
let tradesCache = this.safeValue(this.trades, symbol);
|
|
174
|
+
if (tradesCache === undefined) {
|
|
175
|
+
const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
|
|
176
|
+
tradesCache = new Cache.ArrayCache(limit);
|
|
177
|
+
this.trades[symbol] = tradesCache;
|
|
178
|
+
}
|
|
179
|
+
for (let i = 0; i < data.length; i++) {
|
|
180
|
+
const trade = this.parseTrade(data[i], market);
|
|
181
|
+
tradesCache.append(trade);
|
|
182
|
+
}
|
|
183
|
+
client.resolve(tradesCache, ch);
|
|
184
|
+
return message;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* @method
|
|
188
|
+
* @name bittrade#watchOHLCV
|
|
189
|
+
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
190
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
191
|
+
* @param {string} timeframe the length of time each candle represents
|
|
192
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
193
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
194
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
195
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
196
|
+
*/
|
|
197
|
+
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
198
|
+
await this.loadMarkets();
|
|
199
|
+
const market = this.market(symbol);
|
|
200
|
+
symbol = market['symbol'];
|
|
201
|
+
const interval = this.safeString(this.timeframes, timeframe, timeframe);
|
|
202
|
+
const messageHash = 'market.' + market['id'] + '.kline.' + interval;
|
|
203
|
+
const api = this.safeString(this.options, 'api', 'api');
|
|
204
|
+
const hostname = { 'hostname': this.hostname };
|
|
205
|
+
const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
|
|
206
|
+
const requestId = this.requestId();
|
|
207
|
+
const request = {
|
|
208
|
+
'sub': messageHash,
|
|
209
|
+
'id': requestId,
|
|
210
|
+
};
|
|
211
|
+
const subscription = {
|
|
212
|
+
'id': requestId,
|
|
213
|
+
'messageHash': messageHash,
|
|
214
|
+
'symbol': symbol,
|
|
215
|
+
'timeframe': timeframe,
|
|
216
|
+
'params': params,
|
|
217
|
+
};
|
|
218
|
+
const ohlcv = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
|
|
219
|
+
if (this.newUpdates) {
|
|
220
|
+
limit = ohlcv.getLimit(symbol, limit);
|
|
221
|
+
}
|
|
222
|
+
return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
|
|
223
|
+
}
|
|
224
|
+
handleOHLCV(client, message) {
|
|
225
|
+
//
|
|
226
|
+
// {
|
|
227
|
+
// "ch": "market.btcusdt.kline.1min",
|
|
228
|
+
// "ts": 1583501786794,
|
|
229
|
+
// "tick": {
|
|
230
|
+
// "id": 1583501760,
|
|
231
|
+
// "open": 9094.5,
|
|
232
|
+
// "close": 9094.51,
|
|
233
|
+
// "low": 9094.5,
|
|
234
|
+
// "high": 9094.51,
|
|
235
|
+
// "amount": 0.44639786263800907,
|
|
236
|
+
// "vol": 4059.76919054,
|
|
237
|
+
// "count": 16
|
|
238
|
+
// }
|
|
239
|
+
// }
|
|
240
|
+
//
|
|
241
|
+
const ch = this.safeString(message, 'ch');
|
|
242
|
+
const parts = ch.split('.');
|
|
243
|
+
const marketId = this.safeString(parts, 1);
|
|
244
|
+
const market = this.safeMarket(marketId);
|
|
245
|
+
const symbol = market['symbol'];
|
|
246
|
+
const interval = this.safeString(parts, 3);
|
|
247
|
+
const timeframe = this.findTimeframe(interval);
|
|
248
|
+
this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
|
|
249
|
+
let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
|
|
250
|
+
if (stored === undefined) {
|
|
251
|
+
const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
|
|
252
|
+
stored = new Cache.ArrayCacheByTimestamp(limit);
|
|
253
|
+
this.ohlcvs[symbol][timeframe] = stored;
|
|
254
|
+
}
|
|
255
|
+
const tick = this.safeValue(message, 'tick');
|
|
256
|
+
const parsed = this.parseOHLCV(tick, market);
|
|
257
|
+
stored.append(parsed);
|
|
258
|
+
client.resolve(stored, ch);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* @method
|
|
262
|
+
* @name bittrade#watchOrderBook
|
|
263
|
+
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
264
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
265
|
+
* @param {int} [limit] the maximum amount of order book entries to return
|
|
266
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
267
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
268
|
+
*/
|
|
269
|
+
async watchOrderBook(symbol, limit = undefined, params = {}) {
|
|
270
|
+
if ((limit !== undefined) && (limit !== 150)) {
|
|
271
|
+
throw new errors.ExchangeError(this.id + ' watchOrderBook accepts limit = 150 only');
|
|
272
|
+
}
|
|
273
|
+
await this.loadMarkets();
|
|
274
|
+
const market = this.market(symbol);
|
|
275
|
+
symbol = market['symbol'];
|
|
276
|
+
// only supports a limit of 150 at this time
|
|
277
|
+
limit = (limit === undefined) ? 150 : limit;
|
|
278
|
+
const messageHash = 'market.' + market['id'] + '.mbp.' + limit.toString();
|
|
279
|
+
const api = this.safeString(this.options, 'api', 'api');
|
|
280
|
+
const hostname = { 'hostname': this.hostname };
|
|
281
|
+
const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
|
|
282
|
+
const requestId = this.requestId();
|
|
283
|
+
const request = {
|
|
284
|
+
'sub': messageHash,
|
|
285
|
+
'id': requestId,
|
|
286
|
+
};
|
|
287
|
+
const subscription = {
|
|
288
|
+
'id': requestId,
|
|
289
|
+
'messageHash': messageHash,
|
|
290
|
+
'symbol': symbol,
|
|
291
|
+
'limit': limit,
|
|
292
|
+
'params': params,
|
|
293
|
+
'method': this.handleOrderBookSubscription,
|
|
294
|
+
};
|
|
295
|
+
const orderbook = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscription);
|
|
296
|
+
return orderbook.limit();
|
|
297
|
+
}
|
|
298
|
+
handleOrderBookSnapshot(client, message, subscription) {
|
|
299
|
+
//
|
|
300
|
+
// {
|
|
301
|
+
// "id": 1583473663565,
|
|
302
|
+
// "rep": "market.btcusdt.mbp.150",
|
|
303
|
+
// "status": "ok",
|
|
304
|
+
// "data": {
|
|
305
|
+
// "seqNum": 104999417756,
|
|
306
|
+
// "bids": [
|
|
307
|
+
// [9058.27, 0],
|
|
308
|
+
// [9058.43, 0],
|
|
309
|
+
// [9058.99, 0],
|
|
310
|
+
// ],
|
|
311
|
+
// "asks": [
|
|
312
|
+
// [9084.27, 0.2],
|
|
313
|
+
// [9085.69, 0],
|
|
314
|
+
// [9085.81, 0],
|
|
315
|
+
// ]
|
|
316
|
+
// }
|
|
317
|
+
// }
|
|
318
|
+
//
|
|
319
|
+
const symbol = this.safeString(subscription, 'symbol');
|
|
320
|
+
const messageHash = this.safeString(subscription, 'messageHash');
|
|
321
|
+
const orderbook = this.orderbooks[symbol];
|
|
322
|
+
const data = this.safeValue(message, 'data');
|
|
323
|
+
const snapshot = this.parseOrderBook(data, symbol);
|
|
324
|
+
snapshot['nonce'] = this.safeInteger(data, 'seqNum');
|
|
325
|
+
orderbook.reset(snapshot);
|
|
326
|
+
// unroll the accumulated deltas
|
|
327
|
+
const messages = orderbook.cache;
|
|
328
|
+
for (let i = 0; i < messages.length; i++) {
|
|
329
|
+
this.handleOrderBookMessage(client, messages[i], orderbook);
|
|
330
|
+
}
|
|
331
|
+
this.orderbooks[symbol] = orderbook;
|
|
332
|
+
client.resolve(orderbook, messageHash);
|
|
333
|
+
}
|
|
334
|
+
async watchOrderBookSnapshot(client, message, subscription) {
|
|
335
|
+
const messageHash = this.safeString(subscription, 'messageHash');
|
|
336
|
+
try {
|
|
337
|
+
const symbol = this.safeString(subscription, 'symbol');
|
|
338
|
+
const limit = this.safeInteger(subscription, 'limit');
|
|
339
|
+
const params = this.safeValue(subscription, 'params');
|
|
340
|
+
const api = this.safeString(this.options, 'api', 'api');
|
|
341
|
+
const hostname = { 'hostname': this.hostname };
|
|
342
|
+
const url = this.implodeParams(this.urls['api']['ws'][api]['public'], hostname);
|
|
343
|
+
const requestId = this.requestId();
|
|
344
|
+
const request = {
|
|
345
|
+
'req': messageHash,
|
|
346
|
+
'id': requestId,
|
|
347
|
+
};
|
|
348
|
+
// this is a temporary subscription by a specific requestId
|
|
349
|
+
// it has a very short lifetime until the snapshot is received over ws
|
|
350
|
+
const snapshotSubscription = {
|
|
351
|
+
'id': requestId,
|
|
352
|
+
'messageHash': messageHash,
|
|
353
|
+
'symbol': symbol,
|
|
354
|
+
'limit': limit,
|
|
355
|
+
'params': params,
|
|
356
|
+
'method': this.handleOrderBookSnapshot,
|
|
357
|
+
};
|
|
358
|
+
const orderbook = await this.watch(url, requestId, request, requestId, snapshotSubscription);
|
|
359
|
+
return orderbook.limit();
|
|
360
|
+
}
|
|
361
|
+
catch (e) {
|
|
362
|
+
delete client.subscriptions[messageHash];
|
|
363
|
+
client.reject(e, messageHash);
|
|
364
|
+
}
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
handleDelta(bookside, delta) {
|
|
368
|
+
const price = this.safeFloat(delta, 0);
|
|
369
|
+
const amount = this.safeFloat(delta, 1);
|
|
370
|
+
bookside.store(price, amount);
|
|
371
|
+
}
|
|
372
|
+
handleDeltas(bookside, deltas) {
|
|
373
|
+
for (let i = 0; i < deltas.length; i++) {
|
|
374
|
+
this.handleDelta(bookside, deltas[i]);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
handleOrderBookMessage(client, message, orderbook) {
|
|
378
|
+
//
|
|
379
|
+
// {
|
|
380
|
+
// "ch": "market.btcusdt.mbp.150",
|
|
381
|
+
// "ts": 1583472025885,
|
|
382
|
+
// "tick": {
|
|
383
|
+
// "seqNum": 104998984994,
|
|
384
|
+
// "prevSeqNum": 104998984977,
|
|
385
|
+
// "bids": [
|
|
386
|
+
// [9058.27, 0],
|
|
387
|
+
// [9058.43, 0],
|
|
388
|
+
// [9058.99, 0],
|
|
389
|
+
// ],
|
|
390
|
+
// "asks": [
|
|
391
|
+
// [9084.27, 0.2],
|
|
392
|
+
// [9085.69, 0],
|
|
393
|
+
// [9085.81, 0],
|
|
394
|
+
// ]
|
|
395
|
+
// }
|
|
396
|
+
// }
|
|
397
|
+
//
|
|
398
|
+
const tick = this.safeValue(message, 'tick', {});
|
|
399
|
+
const seqNum = this.safeInteger(tick, 'seqNum');
|
|
400
|
+
const prevSeqNum = this.safeInteger(tick, 'prevSeqNum');
|
|
401
|
+
if ((prevSeqNum <= orderbook['nonce']) && (seqNum > orderbook['nonce'])) {
|
|
402
|
+
const asks = this.safeValue(tick, 'asks', []);
|
|
403
|
+
const bids = this.safeValue(tick, 'bids', []);
|
|
404
|
+
this.handleDeltas(orderbook['asks'], asks);
|
|
405
|
+
this.handleDeltas(orderbook['bids'], bids);
|
|
406
|
+
orderbook['nonce'] = seqNum;
|
|
407
|
+
const timestamp = this.safeInteger(message, 'ts');
|
|
408
|
+
orderbook['timestamp'] = timestamp;
|
|
409
|
+
orderbook['datetime'] = this.iso8601(timestamp);
|
|
410
|
+
}
|
|
411
|
+
return orderbook;
|
|
412
|
+
}
|
|
413
|
+
handleOrderBook(client, message) {
|
|
414
|
+
//
|
|
415
|
+
// deltas
|
|
416
|
+
//
|
|
417
|
+
// {
|
|
418
|
+
// "ch": "market.btcusdt.mbp.150",
|
|
419
|
+
// "ts": 1583472025885,
|
|
420
|
+
// "tick": {
|
|
421
|
+
// "seqNum": 104998984994,
|
|
422
|
+
// "prevSeqNum": 104998984977,
|
|
423
|
+
// "bids": [
|
|
424
|
+
// [9058.27, 0],
|
|
425
|
+
// [9058.43, 0],
|
|
426
|
+
// [9058.99, 0],
|
|
427
|
+
// ],
|
|
428
|
+
// "asks": [
|
|
429
|
+
// [9084.27, 0.2],
|
|
430
|
+
// [9085.69, 0],
|
|
431
|
+
// [9085.81, 0],
|
|
432
|
+
// ]
|
|
433
|
+
// }
|
|
434
|
+
// }
|
|
435
|
+
//
|
|
436
|
+
const messageHash = this.safeString(message, 'ch');
|
|
437
|
+
const ch = this.safeValue(message, 'ch');
|
|
438
|
+
const parts = ch.split('.');
|
|
439
|
+
const marketId = this.safeString(parts, 1);
|
|
440
|
+
const symbol = this.safeSymbol(marketId);
|
|
441
|
+
const orderbook = this.orderbooks[symbol];
|
|
442
|
+
if (orderbook['nonce'] === undefined) {
|
|
443
|
+
orderbook.cache.push(message);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
this.handleOrderBookMessage(client, message, orderbook);
|
|
447
|
+
client.resolve(orderbook, messageHash);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
handleOrderBookSubscription(client, message, subscription) {
|
|
451
|
+
const symbol = this.safeString(subscription, 'symbol');
|
|
452
|
+
const limit = this.safeInteger(subscription, 'limit');
|
|
453
|
+
if (symbol in this.orderbooks) {
|
|
454
|
+
delete this.orderbooks[symbol];
|
|
455
|
+
}
|
|
456
|
+
this.orderbooks[symbol] = this.orderBook({}, limit);
|
|
457
|
+
// watch the snapshot in a separate async call
|
|
458
|
+
this.spawn(this.watchOrderBookSnapshot, client, message, subscription);
|
|
459
|
+
}
|
|
460
|
+
handleSubscriptionStatus(client, message) {
|
|
461
|
+
//
|
|
462
|
+
// {
|
|
463
|
+
// "id": 1583414227,
|
|
464
|
+
// "status": "ok",
|
|
465
|
+
// "subbed": "market.btcusdt.mbp.150",
|
|
466
|
+
// "ts": 1583414229143
|
|
467
|
+
// }
|
|
468
|
+
//
|
|
469
|
+
const id = this.safeString(message, 'id');
|
|
470
|
+
const subscriptionsById = this.indexBy(client.subscriptions, 'id');
|
|
471
|
+
const subscription = this.safeValue(subscriptionsById, id);
|
|
472
|
+
if (subscription !== undefined) {
|
|
473
|
+
const method = this.safeValue(subscription, 'method');
|
|
474
|
+
if (method !== undefined) {
|
|
475
|
+
return method.call(this, client, message, subscription);
|
|
476
|
+
}
|
|
477
|
+
// clean up
|
|
478
|
+
if (id in client.subscriptions) {
|
|
479
|
+
delete client.subscriptions[id];
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return message;
|
|
483
|
+
}
|
|
484
|
+
handleSystemStatus(client, message) {
|
|
485
|
+
//
|
|
486
|
+
// todo: answer the question whether handleSystemStatus should be renamed
|
|
487
|
+
// and unified as handleStatus for any usage pattern that
|
|
488
|
+
// involves system status and maintenance updates
|
|
489
|
+
//
|
|
490
|
+
// {
|
|
491
|
+
// "id": "1578090234088", // connectId
|
|
492
|
+
// "type": "welcome",
|
|
493
|
+
// }
|
|
494
|
+
//
|
|
495
|
+
return message;
|
|
496
|
+
}
|
|
497
|
+
handleSubject(client, message) {
|
|
498
|
+
//
|
|
499
|
+
// {
|
|
500
|
+
// "ch": "market.btcusdt.mbp.150",
|
|
501
|
+
// "ts": 1583472025885,
|
|
502
|
+
// "tick": {
|
|
503
|
+
// "seqNum": 104998984994,
|
|
504
|
+
// "prevSeqNum": 104998984977,
|
|
505
|
+
// "bids": [
|
|
506
|
+
// [9058.27, 0],
|
|
507
|
+
// [9058.43, 0],
|
|
508
|
+
// [9058.99, 0],
|
|
509
|
+
// ],
|
|
510
|
+
// "asks": [
|
|
511
|
+
// [9084.27, 0.2],
|
|
512
|
+
// [9085.69, 0],
|
|
513
|
+
// [9085.81, 0],
|
|
514
|
+
// ]
|
|
515
|
+
// }
|
|
516
|
+
// }
|
|
517
|
+
//
|
|
518
|
+
const ch = this.safeValue(message, 'ch');
|
|
519
|
+
const parts = ch.split('.');
|
|
520
|
+
const type = this.safeString(parts, 0);
|
|
521
|
+
if (type === 'market') {
|
|
522
|
+
const methodName = this.safeString(parts, 2);
|
|
523
|
+
const methods = {
|
|
524
|
+
'mbp': this.handleOrderBook,
|
|
525
|
+
'detail': this.handleTicker,
|
|
526
|
+
'trade': this.handleTrades,
|
|
527
|
+
'kline': this.handleOHLCV,
|
|
528
|
+
// ...
|
|
529
|
+
};
|
|
530
|
+
const method = this.safeValue(methods, methodName);
|
|
531
|
+
if (method !== undefined) {
|
|
532
|
+
method.call(this, client, message);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
async pong(client, message) {
|
|
537
|
+
//
|
|
538
|
+
// { ping: 1583491673714 }
|
|
539
|
+
//
|
|
540
|
+
await client.send({ 'pong': this.safeInteger(message, 'ping') });
|
|
541
|
+
}
|
|
542
|
+
handlePing(client, message) {
|
|
543
|
+
this.spawn(this.pong, client, message);
|
|
544
|
+
}
|
|
545
|
+
handleErrorMessage(client, message) {
|
|
546
|
+
//
|
|
547
|
+
// {
|
|
548
|
+
// "ts": 1586323747018,
|
|
549
|
+
// "status": "error",
|
|
550
|
+
// 'err-code': "bad-request",
|
|
551
|
+
// 'err-msg': "invalid mbp.150.symbol linkusdt",
|
|
552
|
+
// "id": "2"
|
|
553
|
+
// }
|
|
554
|
+
//
|
|
555
|
+
const status = this.safeString(message, 'status');
|
|
556
|
+
if (status === 'error') {
|
|
557
|
+
const id = this.safeString(message, 'id');
|
|
558
|
+
const subscriptionsById = this.indexBy(client.subscriptions, 'id');
|
|
559
|
+
const subscription = this.safeValue(subscriptionsById, id);
|
|
560
|
+
if (subscription !== undefined) {
|
|
561
|
+
const errorCode = this.safeString(message, 'err-code');
|
|
562
|
+
try {
|
|
563
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, this.json(message));
|
|
564
|
+
}
|
|
565
|
+
catch (e) {
|
|
566
|
+
const messageHash = this.safeString(subscription, 'messageHash');
|
|
567
|
+
client.reject(e, messageHash);
|
|
568
|
+
client.reject(e, id);
|
|
569
|
+
if (id in client.subscriptions) {
|
|
570
|
+
delete client.subscriptions[id];
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
return message;
|
|
577
|
+
}
|
|
578
|
+
handleMessage(client, message) {
|
|
579
|
+
if (this.handleErrorMessage(client, message)) {
|
|
580
|
+
//
|
|
581
|
+
// {"id":1583414227,"status":"ok","subbed":"market.btcusdt.mbp.150","ts":1583414229143}
|
|
582
|
+
//
|
|
583
|
+
// ________________________
|
|
584
|
+
//
|
|
585
|
+
// sometimes bittrade responds with half of a JSON response like
|
|
586
|
+
//
|
|
587
|
+
// " {"ch":"market.ethbtc.m "
|
|
588
|
+
//
|
|
589
|
+
// this is passed to handleMessage as a string since it failed to be decoded as JSON
|
|
590
|
+
//
|
|
591
|
+
if (this.safeString(message, 'id') !== undefined) {
|
|
592
|
+
this.handleSubscriptionStatus(client, message);
|
|
593
|
+
}
|
|
594
|
+
else if (this.safeString(message, 'ch') !== undefined) {
|
|
595
|
+
// route by channel aka topic aka subject
|
|
596
|
+
this.handleSubject(client, message);
|
|
597
|
+
}
|
|
598
|
+
else if (this.safeString(message, 'ping') !== undefined) {
|
|
599
|
+
this.handlePing(client, message);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
module.exports = bittrade;
|
package/dist/cjs/src/pro/luno.js
CHANGED
|
@@ -195,17 +195,18 @@ class luno extends luno$1 {
|
|
|
195
195
|
if (!(symbol in this.orderbooks)) {
|
|
196
196
|
this.orderbooks[symbol] = this.indexedOrderBook({});
|
|
197
197
|
}
|
|
198
|
-
const orderbook = this.orderbooks[symbol];
|
|
199
198
|
const asks = this.safeValue(message, 'asks');
|
|
200
199
|
if (asks !== undefined) {
|
|
201
200
|
const snapshot = this.customParseOrderBook(message, symbol, timestamp, 'bids', 'asks', 'price', 'volume', 'id');
|
|
202
|
-
|
|
201
|
+
this.orderbooks[symbol] = this.indexedOrderBook(snapshot);
|
|
203
202
|
}
|
|
204
203
|
else {
|
|
205
|
-
this.
|
|
206
|
-
|
|
207
|
-
|
|
204
|
+
const ob = this.orderbooks[symbol];
|
|
205
|
+
this.handleDelta(ob, message);
|
|
206
|
+
ob['timestamp'] = timestamp;
|
|
207
|
+
ob['datetime'] = this.iso8601(timestamp);
|
|
208
208
|
}
|
|
209
|
+
const orderbook = this.orderbooks[symbol];
|
|
209
210
|
const nonce = this.safeInteger(message, 'sequence');
|
|
210
211
|
orderbook['nonce'] = nonce;
|
|
211
212
|
client.resolve(orderbook, messageHash);
|
package/dist/cjs/src/pro/mexc.js
CHANGED
|
@@ -794,6 +794,9 @@ class mexc extends mexc$1 {
|
|
|
794
794
|
const messageHash = 'orderbook:' + symbol;
|
|
795
795
|
const subscription = this.safeValue(client.subscriptions, messageHash);
|
|
796
796
|
const limit = this.safeInteger(subscription, 'limit');
|
|
797
|
+
if (!(symbol in this.orderbooks)) {
|
|
798
|
+
this.orderbooks[symbol] = this.orderBook();
|
|
799
|
+
}
|
|
797
800
|
const storedOrderBook = this.orderbooks[symbol];
|
|
798
801
|
const nonce = this.safeInteger(storedOrderBook, 'nonce');
|
|
799
802
|
if (nonce === undefined) {
|