ccxt 4.3.44 → 4.3.46

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.
Files changed (64) hide show
  1. package/README.md +130 -130
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/oxfun.js +9 -0
  5. package/dist/cjs/src/base/Exchange.js +1 -0
  6. package/dist/cjs/src/binance.js +2 -0
  7. package/dist/cjs/src/bingx.js +25 -17
  8. package/dist/cjs/src/bitmart.js +5 -0
  9. package/dist/cjs/src/bitstamp.js +18 -2
  10. package/dist/cjs/src/bitteam.js +5 -7
  11. package/dist/cjs/src/coinmetro.js +8 -17
  12. package/dist/cjs/src/hyperliquid.js +29 -21
  13. package/dist/cjs/src/idex.js +1 -0
  14. package/dist/cjs/src/kucoin.js +28 -1
  15. package/dist/cjs/src/luno.js +9 -1
  16. package/dist/cjs/src/mexc.js +8 -6
  17. package/dist/cjs/src/okx.js +1 -0
  18. package/dist/cjs/src/oxfun.js +2900 -0
  19. package/dist/cjs/src/pro/binanceus.js +0 -8
  20. package/dist/cjs/src/pro/oxfun.js +1034 -0
  21. package/dist/cjs/src/tokocrypto.js +8 -10
  22. package/dist/cjs/src/wavesexchange.js +122 -110
  23. package/dist/cjs/src/woofipro.js +1 -0
  24. package/dist/cjs/src/xt.js +1 -1
  25. package/js/ccxt.d.ts +8 -2
  26. package/js/ccxt.js +6 -2
  27. package/js/src/abstract/binance.d.ts +2 -0
  28. package/js/src/abstract/binancecoinm.d.ts +2 -0
  29. package/js/src/abstract/binanceus.d.ts +2 -0
  30. package/js/src/abstract/binanceusdm.d.ts +2 -0
  31. package/js/src/abstract/bitstamp.d.ts +16 -0
  32. package/js/src/abstract/kucoin.d.ts +14 -0
  33. package/js/src/abstract/kucoinfutures.d.ts +14 -0
  34. package/js/src/abstract/mexc.d.ts +2 -0
  35. package/js/src/abstract/oxfun.d.ts +37 -0
  36. package/js/src/abstract/oxfun.js +11 -0
  37. package/js/src/base/Exchange.d.ts +1 -0
  38. package/js/src/base/Exchange.js +1 -0
  39. package/js/src/binance.js +2 -0
  40. package/js/src/bingx.js +26 -18
  41. package/js/src/bitmart.js +5 -0
  42. package/js/src/bitstamp.js +18 -2
  43. package/js/src/bitteam.js +6 -8
  44. package/js/src/coinmetro.js +9 -18
  45. package/js/src/hyperliquid.d.ts +3 -3
  46. package/js/src/hyperliquid.js +29 -21
  47. package/js/src/idex.js +1 -0
  48. package/js/src/kucoin.js +28 -1
  49. package/js/src/luno.d.ts +1 -1
  50. package/js/src/luno.js +9 -1
  51. package/js/src/mexc.js +8 -6
  52. package/js/src/okx.js +1 -0
  53. package/js/src/oxfun.d.ts +129 -0
  54. package/js/src/oxfun.js +2901 -0
  55. package/js/src/pro/binanceus.js +0 -8
  56. package/js/src/pro/oxfun.d.ts +38 -0
  57. package/js/src/pro/oxfun.js +1035 -0
  58. package/js/src/static_dependencies/jsencrypt/lib/jsbn/jsbn.d.ts +1 -1
  59. package/js/src/tokocrypto.js +9 -11
  60. package/js/src/wavesexchange.d.ts +7 -7
  61. package/js/src/wavesexchange.js +123 -111
  62. package/js/src/woofipro.js +1 -0
  63. package/js/src/xt.js +1 -1
  64. package/package.json +1 -1
@@ -0,0 +1,1034 @@
1
+ 'use strict';
2
+
3
+ var oxfun$1 = require('../oxfun.js');
4
+ var errors = require('../base/errors.js');
5
+ var sha256 = require('../static_dependencies/noble-hashes/sha256.js');
6
+ var Cache = require('../base/ws/Cache.js');
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // ---------------------------------------------------------------------------
10
+ class oxfun extends oxfun$1 {
11
+ describe() {
12
+ return this.deepExtend(super.describe(), {
13
+ 'has': {
14
+ 'ws': true,
15
+ 'watchTrades': true,
16
+ 'watchTradesForSymbols': true,
17
+ 'watchOrderBook': true,
18
+ 'watchOrderBookForSymbols': true,
19
+ 'watchOHLCV': true,
20
+ 'watchOHLCVForSymbols': true,
21
+ 'watchOrders': true,
22
+ 'watchMyTrades': false,
23
+ 'watchTicker': true,
24
+ 'watchTickers': true,
25
+ 'watchBalance': true,
26
+ 'createOrderWs': true,
27
+ 'editOrderWs': true,
28
+ 'cancelOrderWs': true,
29
+ 'cancelOrdersWs': true,
30
+ },
31
+ 'urls': {
32
+ 'api': {
33
+ 'ws': 'wss://api.ox.fun/v2/websocket',
34
+ 'test': 'wss://stgapi.ox.fun/v2/websocket',
35
+ },
36
+ },
37
+ 'options': {
38
+ 'timeframes': {
39
+ '1m': '60s',
40
+ '3m': '180s',
41
+ '5m': '300s',
42
+ '15m': '900s',
43
+ '30m': '1800s',
44
+ '1h': '3600s',
45
+ '2h': '7200s',
46
+ '4h': '14400s',
47
+ '6h': '21600s',
48
+ '12h': '43200s',
49
+ '1d': '86400s',
50
+ },
51
+ 'watchOrderBook': {
52
+ 'channel': 'depth', // depth, depthL5, depthL10, depthL25
53
+ },
54
+ },
55
+ 'streaming': {
56
+ 'ping': this.ping,
57
+ 'keepAlive': 50000,
58
+ },
59
+ });
60
+ }
61
+ async subscribeMultiple(messageHashes, argsArray, params = {}) {
62
+ const url = this.urls['api']['ws'];
63
+ const request = {
64
+ 'op': 'subscribe',
65
+ 'args': argsArray,
66
+ };
67
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
68
+ }
69
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
70
+ /**
71
+ * @method
72
+ * @name oxfun#watchTrades
73
+ * @description watches information on multiple trades made in a market
74
+ * @see https://docs.ox.fun/?json#trade
75
+ * @param {string} symbol unified market symbol of the market trades were made in
76
+ * @param {int} [since] the earliest time in ms to fetch orders for
77
+ * @param {int} [limit] the maximum number of trade structures to retrieve
78
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
79
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
80
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
81
+ */
82
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
83
+ }
84
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
85
+ /**
86
+ * @method
87
+ * @name oxfun#watchTradesForSymbols
88
+ * @description get the list of most recent trades for a particular symbol
89
+ * @see https://docs.ox.fun/?json#trade
90
+ * @param {string} symbol unified symbol of the market to fetch trades for
91
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
92
+ * @param {int} [limit] the maximum amount of trades to fetch
93
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
94
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
95
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
96
+ */
97
+ await this.loadMarkets();
98
+ symbols = this.marketSymbols(symbols, undefined, false);
99
+ const args = [];
100
+ const messageHashes = [];
101
+ for (let i = 0; i < symbols.length; i++) {
102
+ const symbol = symbols[i];
103
+ const messageHash = 'trades' + ':' + symbol;
104
+ messageHashes.push(messageHash);
105
+ const marketId = this.marketId(symbol);
106
+ const arg = 'trade:' + marketId;
107
+ args.push(arg);
108
+ }
109
+ const trades = await this.subscribeMultiple(messageHashes, args, params);
110
+ if (this.newUpdates) {
111
+ const first = this.safeDict(trades, 0, {});
112
+ const tradeSymbol = this.safeString(first, 'symbol');
113
+ limit = trades.getLimit(tradeSymbol, limit);
114
+ }
115
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
116
+ }
117
+ handleTrades(client, message) {
118
+ //
119
+ // {
120
+ // table: 'trade',
121
+ // data: [
122
+ // {
123
+ // side: 'SELL',
124
+ // quantity: '0.074',
125
+ // matchType: 'TAKER',
126
+ // price: '3079.5',
127
+ // marketCode: 'ETH-USD-SWAP-LIN',
128
+ // tradeId: '400017157974517783',
129
+ // timestamp: '1716124156643'
130
+ // }
131
+ // ]
132
+ // }
133
+ //
134
+ const data = this.safeList(message, 'data', []);
135
+ for (let i = 0; i < data.length; i++) {
136
+ const trade = this.safeDict(data, i, {});
137
+ const parsedTrade = this.parseWsTrade(trade);
138
+ const symbol = this.safeString(parsedTrade, 'symbol');
139
+ const messageHash = 'trades:' + symbol;
140
+ if (!(symbol in this.trades)) {
141
+ const tradesLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
142
+ this.trades[symbol] = new Cache.ArrayCache(tradesLimit);
143
+ }
144
+ const stored = this.trades[symbol];
145
+ stored.append(parsedTrade);
146
+ client.resolve(stored, messageHash);
147
+ }
148
+ }
149
+ parseWsTrade(trade, market = undefined) {
150
+ //
151
+ // {
152
+ // side: 'SELL',
153
+ // quantity: '0.074',
154
+ // matchType: 'TAKER',
155
+ // price: '3079.5',
156
+ // marketCode: 'ETH-USD-SWAP-LIN',
157
+ // tradeId: '400017157974517783',
158
+ // timestamp: '1716124156643'
159
+ // }
160
+ //
161
+ const marketId = this.safeString(trade, 'marketCode');
162
+ market = this.safeMarket(marketId, market);
163
+ const timestamp = this.safeInteger(trade, 'timestamp');
164
+ return this.safeTrade({
165
+ 'info': trade,
166
+ 'timestamp': timestamp,
167
+ 'datetime': this.iso8601(timestamp),
168
+ 'symbol': market['symbol'],
169
+ 'id': this.safeString(trade, 'tradeId'),
170
+ 'order': undefined,
171
+ 'type': undefined,
172
+ 'takerOrMaker': this.safeStringLower(trade, 'matchType'),
173
+ 'side': this.safeStringLower(trade, 'side'),
174
+ 'price': this.safeNumber(trade, 'price'),
175
+ 'amount': this.safeNumber(trade, 'quantity'),
176
+ 'cost': undefined,
177
+ 'fee': undefined,
178
+ });
179
+ }
180
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
181
+ /**
182
+ * @method
183
+ * @name oxfun#watchOHLCV
184
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
185
+ * @see https://docs.ox.fun/?json#candles
186
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
187
+ * @param {string} timeframe the length of time each candle represents
188
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
189
+ * @param {int} [limit] the maximum amount of candles to fetch
190
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
191
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
192
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
193
+ */
194
+ await this.loadMarkets();
195
+ const market = this.market(symbol);
196
+ const timeframes = this.safeDict(this.options, 'timeframes', {});
197
+ const interval = this.safeString(timeframes, timeframe, timeframe);
198
+ const args = 'candles' + interval + ':' + market['id'];
199
+ const messageHash = 'ohlcv:' + symbol + ':' + timeframe;
200
+ const url = this.urls['api']['ws'];
201
+ const request = {
202
+ 'op': 'subscribe',
203
+ 'args': [args],
204
+ };
205
+ const ohlcvs = await this.watch(url, messageHash, this.extend(request, params), messageHash);
206
+ if (this.newUpdates) {
207
+ limit = ohlcvs.getLimit(symbol, limit);
208
+ }
209
+ return this.filterBySinceLimit(ohlcvs, since, limit, 0, true);
210
+ }
211
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
212
+ /**
213
+ * @method
214
+ * @name oxfun#watchOHLCVForSymbols
215
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
216
+ * @see https://docs.ox.fun/?json#candles
217
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
218
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
219
+ * @param {int} [limit] the maximum amount of candles to fetch
220
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
221
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
222
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
223
+ */
224
+ const symbolsLength = symbolsAndTimeframes.length;
225
+ if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
226
+ throw new errors.ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT:OX', '1m'], ['OX/USDT', '5m']]");
227
+ }
228
+ await this.loadMarkets();
229
+ const args = [];
230
+ const messageHashes = [];
231
+ const timeframes = this.safeDict(this.options, 'timeframes', {});
232
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
233
+ const symbolAndTimeframe = symbolsAndTimeframes[i];
234
+ const sym = symbolAndTimeframe[0];
235
+ const tf = symbolAndTimeframe[1];
236
+ const marketId = this.marketId(sym);
237
+ const interval = this.safeString(timeframes, tf, tf);
238
+ const arg = 'candles' + interval + ':' + marketId;
239
+ args.push(arg);
240
+ const messageHash = 'multi:ohlcv:' + sym + ':' + tf;
241
+ messageHashes.push(messageHash);
242
+ }
243
+ const [symbol, timeframe, candles] = await this.subscribeMultiple(messageHashes, args, params);
244
+ if (this.newUpdates) {
245
+ limit = candles.getLimit(symbol, limit);
246
+ }
247
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
248
+ return this.createOHLCVObject(symbol, timeframe, filtered);
249
+ }
250
+ handleOHLCV(client, message) {
251
+ //
252
+ // {
253
+ // "table": "candles60s",
254
+ // "data": [
255
+ // {
256
+ // "marketCode": "BTC-USD-SWAP-LIN",
257
+ // "candle": [
258
+ // "1594313762698", //timestamp
259
+ // "9633.1", //open
260
+ // "9693.9", //high
261
+ // "9238.1", //low
262
+ // "9630.2", //close
263
+ // "45247", //volume in OX
264
+ // "5.3" //volume in Contracts
265
+ // ]
266
+ // }
267
+ // ]
268
+ // }
269
+ //
270
+ const table = this.safeString(message, 'table');
271
+ const parts = table.split('candles');
272
+ const timeframeId = this.safeString(parts, 1, '');
273
+ const timeframe = this.findTimeframe(timeframeId);
274
+ const messageData = this.safeList(message, 'data', []);
275
+ const data = this.safeDict(messageData, 0, {});
276
+ const marketId = this.safeString(data, 'marketCode');
277
+ const market = this.safeMarket(marketId);
278
+ const symbol = this.safeSymbol(marketId, market);
279
+ if (!(symbol in this.ohlcvs)) {
280
+ this.ohlcvs[symbol] = {};
281
+ }
282
+ if (!(timeframe in this.ohlcvs[symbol])) {
283
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
284
+ this.ohlcvs[symbol][timeframe] = new Cache.ArrayCacheByTimestamp(limit);
285
+ }
286
+ const candle = this.safeList(data, 'candle', []);
287
+ const parsed = this.parseWsOHLCV(candle, market);
288
+ const stored = this.ohlcvs[symbol][timeframe];
289
+ stored.append(parsed);
290
+ const messageHash = 'ohlcv:' + symbol + ':' + timeframe;
291
+ client.resolve(stored, messageHash);
292
+ // for multiOHLCV we need special object, as opposed to other "multi"
293
+ // methods, because OHLCV response item does not contain symbol
294
+ // or timeframe, thus otherwise it would be unrecognizable
295
+ const messageHashForMulti = 'multi:' + messageHash;
296
+ client.resolve([symbol, timeframe, stored], messageHashForMulti);
297
+ }
298
+ parseWsOHLCV(ohlcv, market = undefined) {
299
+ //
300
+ // [
301
+ // "1594313762698", //timestamp
302
+ // "9633.1", //open
303
+ // "9693.9", //high
304
+ // "9238.1", //low
305
+ // "9630.2", //close
306
+ // "45247", //volume in OX
307
+ // "5.3" //volume in Contracts
308
+ // ]
309
+ //
310
+ return [
311
+ this.safeInteger(ohlcv, 0),
312
+ this.safeNumber(ohlcv, 1),
313
+ this.safeNumber(ohlcv, 2),
314
+ this.safeNumber(ohlcv, 3),
315
+ this.safeNumber(ohlcv, 4),
316
+ this.safeNumber(ohlcv, 6),
317
+ ];
318
+ }
319
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
320
+ /**
321
+ * @method
322
+ * @name oxfun#watchOrderBook
323
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
324
+ * @see https://docs.ox.fun/?json#fixed-size-order-book
325
+ * @see https://docs.ox.fun/?json#full-order-book
326
+ * @param {string} symbol unified symbol of the market to fetch the order book for
327
+ * @param {int} [limit] the maximum amount of order book entries to return
328
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
329
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
330
+ */
331
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
332
+ }
333
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
334
+ /**
335
+ * @method
336
+ * @name oxfun#watchOrderBookForSymbols
337
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
338
+ * @see https://docs.ox.fun/?json#fixed-size-order-book
339
+ * @see https://docs.ox.fun/?json#full-order-book
340
+ * @param {string[]} symbols unified array of symbols
341
+ * @param {int} [limit] the maximum amount of order book entries to return
342
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
343
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
344
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
345
+ */
346
+ await this.loadMarkets();
347
+ symbols = this.marketSymbols(symbols);
348
+ let channel = 'depth';
349
+ const options = this.safeDict(this.options, 'watchOrderBook', {});
350
+ const defaultChannel = this.safeString(options, 'channel');
351
+ if (defaultChannel !== undefined) {
352
+ channel = defaultChannel;
353
+ }
354
+ else if (limit !== undefined) {
355
+ if (limit <= 5) {
356
+ channel = 'depthL5';
357
+ }
358
+ else if (limit <= 10) {
359
+ channel = 'depthL10';
360
+ }
361
+ else if (limit <= 25) {
362
+ channel = 'depthL25';
363
+ }
364
+ }
365
+ const args = [];
366
+ const messageHashes = [];
367
+ for (let i = 0; i < symbols.length; i++) {
368
+ const symbol = symbols[i];
369
+ const messageHash = 'orderbook:' + symbol;
370
+ messageHashes.push(messageHash);
371
+ const marketId = this.marketId(symbol);
372
+ const arg = channel + ':' + marketId;
373
+ args.push(arg);
374
+ }
375
+ const orderbook = await this.subscribeMultiple(messageHashes, args, params);
376
+ return orderbook.limit();
377
+ }
378
+ handleOrderBook(client, message) {
379
+ //
380
+ // {
381
+ // "table": "depth",
382
+ // "data": {
383
+ // "seqNum": "100170478917895032",
384
+ // "asks": [
385
+ // [ 0.01, 100500 ],
386
+ // ...
387
+ // ],
388
+ // "bids": [
389
+ // [ 69.69696, 69 ],
390
+ // ...
391
+ // ],
392
+ // "checksum": 261021645,
393
+ // "marketCode": "OX-USDT",
394
+ // "timestamp": 1716204786184
395
+ // },
396
+ // "action": "partial"
397
+ // }
398
+ //
399
+ const data = this.safeDict(message, 'data', {});
400
+ const marketId = this.safeString(data, 'marketCode');
401
+ const symbol = this.safeSymbol(marketId);
402
+ const timestamp = this.safeInteger(data, 'timestamp');
403
+ const messageHash = 'orderbook:' + symbol;
404
+ if (!(symbol in this.orderbooks)) {
405
+ this.orderbooks[symbol] = this.orderBook({});
406
+ }
407
+ const orderbook = this.orderbooks[symbol];
408
+ const snapshot = this.parseOrderBook(data, symbol, timestamp, 'asks', 'bids');
409
+ orderbook.reset(snapshot);
410
+ orderbook['nonce'] = this.safeInteger(data, 'seqNum');
411
+ this.orderbooks[symbol] = orderbook;
412
+ client.resolve(orderbook, messageHash);
413
+ }
414
+ async watchTicker(symbol, params = {}) {
415
+ /**
416
+ * @method
417
+ * @name oxfun#watchTicker
418
+ * @see https://docs.ox.fun/?json#ticker
419
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
420
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
421
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
422
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
423
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
424
+ */
425
+ const ticker = await this.watchTickers([symbol], params);
426
+ return this.safeValue(ticker, symbol);
427
+ }
428
+ async watchTickers(symbols = undefined, params = {}) {
429
+ /**
430
+ * @method
431
+ * @name oxfun#watchTickers
432
+ * @see https://docs.ox.fun/?json#ticker
433
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
434
+ * @param {string[]} [symbols] unified symbol of the market to fetch the ticker for
435
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
436
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
437
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
438
+ */
439
+ await this.loadMarkets();
440
+ const allSymbols = (symbols === undefined);
441
+ let sym = symbols;
442
+ const args = [];
443
+ if (allSymbols) {
444
+ sym = this.symbols;
445
+ args.push('ticker:all');
446
+ }
447
+ const messageHashes = [];
448
+ for (let i = 0; i < sym.length; i++) {
449
+ const symbol = sym[i];
450
+ const messageHash = 'tickers' + ':' + symbol;
451
+ messageHashes.push(messageHash);
452
+ const marketId = this.marketId(symbol);
453
+ if (!allSymbols) {
454
+ args.push('ticker:' + marketId);
455
+ }
456
+ }
457
+ const newTicker = await this.subscribeMultiple(messageHashes, args, params);
458
+ if (this.newUpdates) {
459
+ const result = {};
460
+ result[newTicker['symbol']] = newTicker;
461
+ return result;
462
+ }
463
+ return this.filterByArray(this.tickers, 'symbol', symbols);
464
+ }
465
+ handleTicker(client, message) {
466
+ //
467
+ // {
468
+ // "table": "ticker",
469
+ // "data": [
470
+ // {
471
+ // "last": "3088.6",
472
+ // "open24h": "3087.2",
473
+ // "high24h": "3142.0",
474
+ // "low24h": "3053.9",
475
+ // "volume24h": "450512672.1800",
476
+ // "currencyVolume24h": "1458.579",
477
+ // "openInterest": "3786.801",
478
+ // "marketCode": "ETH-USD-SWAP-LIN",
479
+ // "timestamp": "1716212747050",
480
+ // "lastQty": "0.813",
481
+ // "markPrice": "3088.6",
482
+ // "lastMarkPrice": "3088.6",
483
+ // "indexPrice": "3086.5"
484
+ // },
485
+ // ...
486
+ // ]
487
+ // }
488
+ //
489
+ const data = this.safeList(message, 'data', []);
490
+ for (let i = 0; i < data.length; i++) {
491
+ const rawTicker = this.safeDict(data, i, {});
492
+ const ticker = this.parseTicker(rawTicker);
493
+ const symbol = ticker['symbol'];
494
+ const messageHash = 'tickers:' + symbol;
495
+ this.tickers[symbol] = ticker;
496
+ client.resolve(ticker, messageHash);
497
+ }
498
+ }
499
+ async watchBalance(params = {}) {
500
+ /**
501
+ * @method
502
+ * @name oxfun#watchBalance
503
+ * @see https://docs.ox.fun/?json#balance-channel
504
+ * @description watch balance and get the amount of funds available for trading or funds locked in orders
505
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
506
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
507
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
508
+ */
509
+ await this.loadMarkets();
510
+ this.authenticate();
511
+ const args = 'balance:all';
512
+ const messageHash = 'balance';
513
+ const url = this.urls['api']['ws'];
514
+ const request = {
515
+ 'op': 'subscribe',
516
+ 'args': [args],
517
+ };
518
+ return await this.watch(url, messageHash, this.extend(request, params), messageHash);
519
+ }
520
+ handleBalance(client, message) {
521
+ //
522
+ // {
523
+ // "table": "balance",
524
+ // "accountId": "106464",
525
+ // "timestamp": "1716549132780",
526
+ // "tradeType": "PORTFOLIO",
527
+ // "data": [
528
+ // {
529
+ // "instrumentId": "xOX",
530
+ // "total": "23.375591220",
531
+ // "available": "23.375591220",
532
+ // "reserved": "0",
533
+ // "quantityLastUpdated": "1716509744262",
534
+ // "locked": "0"
535
+ // },
536
+ // ...
537
+ // ]
538
+ // }
539
+ //
540
+ const balances = this.safeList(message, 'data');
541
+ const timestamp = this.safeInteger(message, 'timestamp');
542
+ this.balance['info'] = message;
543
+ this.balance['timestamp'] = timestamp;
544
+ this.balance['datetime'] = this.iso8601(timestamp);
545
+ for (let i = 0; i < balances.length; i++) {
546
+ const balance = this.safeDict(balances, i, {});
547
+ const currencyId = this.safeString(balance, 'instrumentId');
548
+ const code = this.safeCurrencyCode(currencyId);
549
+ if (!(code in this.balance)) {
550
+ this.balance[code] = this.account();
551
+ }
552
+ const account = this.balance[code];
553
+ account['total'] = this.safeString(balance, 'total');
554
+ account['used'] = this.safeString(balance, 'reserved');
555
+ account['free'] = this.safeString(balance, 'available');
556
+ this.balance[code] = account;
557
+ }
558
+ this.balance = this.safeBalance(this.balance);
559
+ client.resolve(this.balance, 'balance');
560
+ }
561
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
562
+ /**
563
+ * @method
564
+ * @name oxfun#watchPositions
565
+ * @see https://docs.ox.fun/?json#position-channel
566
+ * @description watch all open positions
567
+ * @param {string[]|undefined} symbols list of unified market symbols
568
+ * @param {object} params extra parameters specific to the exchange API endpoint
569
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
570
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
571
+ */
572
+ await this.loadMarkets();
573
+ await this.authenticate();
574
+ const allSymbols = (symbols === undefined);
575
+ let sym = symbols;
576
+ const args = [];
577
+ if (allSymbols) {
578
+ sym = this.symbols;
579
+ args.push('position:all');
580
+ }
581
+ const messageHashes = [];
582
+ for (let i = 0; i < sym.length; i++) {
583
+ const symbol = sym[i];
584
+ const messageHash = 'positions' + ':' + symbol;
585
+ messageHashes.push(messageHash);
586
+ const marketId = this.marketId(symbol);
587
+ if (!allSymbols) {
588
+ args.push('position:' + marketId);
589
+ }
590
+ }
591
+ const newPositions = await this.subscribeMultiple(messageHashes, args, params);
592
+ if (this.newUpdates) {
593
+ return newPositions;
594
+ }
595
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
596
+ }
597
+ handlePositions(client, message) {
598
+ //
599
+ // {
600
+ // "table": "position",
601
+ // "accountId": "106464",
602
+ // "timestamp": "1716550771582",
603
+ // "data": [
604
+ // {
605
+ // "instrumentId": "ETH-USD-SWAP-LIN",
606
+ // "quantity": "0.01",
607
+ // "lastUpdated": "1716550757299",
608
+ // "contractValCurrency": "ETH",
609
+ // "entryPrice": "3709.6",
610
+ // "positionPnl": "-5.000",
611
+ // "estLiquidationPrice": "743.4",
612
+ // "margin": "0",
613
+ // "leverage": "0"
614
+ // }
615
+ // ]
616
+ // }
617
+ //
618
+ if (this.positions === undefined) {
619
+ this.positions = new Cache.ArrayCacheBySymbolBySide();
620
+ }
621
+ const cache = this.positions;
622
+ const data = this.safeList(message, 'data', []);
623
+ for (let i = 0; i < data.length; i++) {
624
+ const rawPosition = this.safeDict(data, i, {});
625
+ const position = this.parseWsPosition(rawPosition);
626
+ const symbol = position['symbol'];
627
+ const messageHash = 'positions:' + symbol;
628
+ cache.append(position);
629
+ client.resolve(position, messageHash);
630
+ }
631
+ }
632
+ parseWsPosition(position, market = undefined) {
633
+ //
634
+ // {
635
+ // "instrumentId": "ETH-USD-SWAP-LIN",
636
+ // "quantity": "0.01",
637
+ // "lastUpdated": "1716550757299",
638
+ // "contractValCurrency": "ETH",
639
+ // "entryPrice": "3709.6",
640
+ // "positionPnl": "-5.000",
641
+ // "estLiquidationPrice": "743.4",
642
+ // "margin": "0", // Currently always reports 0
643
+ // "leverage": "0" // Currently always reports 0
644
+ // }
645
+ //
646
+ const marketId = this.safeString(position, 'instrumentId');
647
+ market = this.safeMarket(marketId, market);
648
+ return this.safePosition({
649
+ 'info': position,
650
+ 'id': undefined,
651
+ 'symbol': market['symbol'],
652
+ 'notional': undefined,
653
+ 'marginMode': 'cross',
654
+ 'liquidationPrice': this.safeNumber(position, 'estLiquidationPrice'),
655
+ 'entryPrice': this.safeNumber(position, 'entryPrice'),
656
+ 'unrealizedPnl': this.safeNumber(position, 'positionPnl'),
657
+ 'realizedPnl': undefined,
658
+ 'percentage': undefined,
659
+ 'contracts': this.safeNumber(position, 'quantity'),
660
+ 'contractSize': undefined,
661
+ 'markPrice': undefined,
662
+ 'lastPrice': undefined,
663
+ 'side': undefined,
664
+ 'hedged': undefined,
665
+ 'timestamp': undefined,
666
+ 'datetime': undefined,
667
+ 'lastUpdateTimestamp': this.safeInteger(position, 'lastUpdated'),
668
+ 'maintenanceMargin': undefined,
669
+ 'maintenanceMarginPercentage': undefined,
670
+ 'collateral': undefined,
671
+ 'initialMargin': undefined,
672
+ 'initialMarginPercentage': undefined,
673
+ 'leverage': undefined,
674
+ 'marginRatio': undefined,
675
+ 'stopLossPrice': undefined,
676
+ 'takeProfitPrice': undefined,
677
+ });
678
+ }
679
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
680
+ /**
681
+ * @method
682
+ * @name oxfun#watchOrders
683
+ * @description watches information on multiple orders made by the user
684
+ * @see https://docs.ox.fun/?json#order-channel
685
+ * @param {string} symbol unified market symbol of the market orders were made in
686
+ * @param {int} [since] the earliest time in ms to fetch orders for
687
+ * @param {int} [limit] the maximum number of order structures to retrieve
688
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
689
+ * @param {int|string} [params.tag] If given it will be echoed in the reply and the max size of tag is 32
690
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
691
+ */
692
+ await this.loadMarkets();
693
+ await this.authenticate();
694
+ let messageHash = 'orders';
695
+ let args = 'order:';
696
+ const market = this.safeMarket(symbol);
697
+ if (symbol === undefined) {
698
+ args += 'all';
699
+ }
700
+ else {
701
+ messageHash += ':' + symbol;
702
+ args += ':' + market['id'];
703
+ }
704
+ const request = {
705
+ 'op': 'subscribe',
706
+ 'args': [
707
+ args,
708
+ ],
709
+ };
710
+ const url = this.urls['api']['ws'];
711
+ const orders = await this.watch(url, messageHash, request, messageHash);
712
+ if (this.newUpdates) {
713
+ limit = orders.getLimit(symbol, limit);
714
+ }
715
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
716
+ }
717
+ handleOrders(client, message) {
718
+ //
719
+ // {
720
+ // "table": "order",
721
+ // "data": [
722
+ // {
723
+ // "accountId": "106464",
724
+ // "clientOrderId": "1716713676233",
725
+ // "orderId": "1000116921319",
726
+ // "price": "1000.0",
727
+ // "quantity": "0.01",
728
+ // "amount": "0.0",
729
+ // "side": "BUY",
730
+ // "status": "OPEN",
731
+ // "marketCode": "ETH-USD-SWAP-LIN",
732
+ // "timeInForce": "MAKER_ONLY",
733
+ // "timestamp": "1716713677834",
734
+ // "remainQuantity": "0.01",
735
+ // "limitPrice": "1000.0",
736
+ // "notice": "OrderOpened",
737
+ // "orderType": "LIMIT",
738
+ // "isTriggered": "false",
739
+ // "displayQuantity": "0.01"
740
+ // }
741
+ // ]
742
+ // }
743
+ //
744
+ const data = this.safeList(message, 'data', []);
745
+ let messageHash = 'orders';
746
+ if (this.orders === undefined) {
747
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
748
+ this.orders = new Cache.ArrayCacheBySymbolById(limit);
749
+ }
750
+ const orders = this.orders;
751
+ for (let i = 0; i < data.length; i++) {
752
+ const order = this.safeDict(data, i, {});
753
+ const parsedOrder = this.parseOrder(order);
754
+ orders.append(parsedOrder);
755
+ messageHash += ':' + parsedOrder['symbol'];
756
+ client.resolve(this.orders, messageHash);
757
+ }
758
+ }
759
+ async createOrderWs(symbol, type, side, amount, price = undefined, params = {}) {
760
+ /**
761
+ * @method
762
+ * @name oxfun#createOrderWs
763
+ * @see https://docs.ox.fun/?json#order-commands
764
+ * @description create a trade order
765
+ * @param {string} symbol unified symbol of the market to create an order in
766
+ * @param {string} type 'market', 'limit', 'STOP_LIMIT' or 'STOP_MARKET'
767
+ * @param {string} side 'buy' or 'sell'
768
+ * @param {float} amount how much of currency you want to trade in units of base currency
769
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
770
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
771
+ * @param {int} [params.clientOrderId] a unique id for the order
772
+ * @param {int} [params.timestamp] in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected.
773
+ * @param {int} [params.recvWindow] in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used.
774
+ * @param {float} [params.cost] the quote quantity that can be used as an alternative for the amount for market buy orders
775
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
776
+ * @param {float} [params.limitPrice] Limit price for the STOP_LIMIT order
777
+ * @param {bool} [params.postOnly] if true, the order will only be posted if it will be a maker order
778
+ * @param {string} [params.timeInForce] GTC (default), IOC, FOK, PO, MAKER_ONLY or MAKER_ONLY_REPRICE (reprices order to the best maker only price if the specified price were to lead to a taker trade)
779
+ * @param {string} [params.selfTradePreventionMode] NONE, EXPIRE_MAKER, EXPIRE_TAKER or EXPIRE_BOTH for more info check here {@link https://docs.ox.fun/?json#self-trade-prevention-modes}
780
+ * @param {string} [params.displayQuantity] for an iceberg order, pass both quantity and displayQuantity fields in the order request
781
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
782
+ */
783
+ await this.loadMarkets();
784
+ await this.authenticate();
785
+ const messageHash = this.nonce().toString();
786
+ const request = {
787
+ 'op': 'placeorder',
788
+ 'tag': messageHash,
789
+ };
790
+ params = this.omit(params, 'tag');
791
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
792
+ const timestamp = this.safeInteger(orderRequest, 'timestamp');
793
+ if (timestamp === undefined) {
794
+ orderRequest['timestamp'] = this.milliseconds();
795
+ }
796
+ request['data'] = orderRequest;
797
+ const url = this.urls['api']['ws'];
798
+ return await this.watch(url, messageHash, request, messageHash);
799
+ }
800
+ async editOrderWs(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
801
+ /**
802
+ * @method
803
+ * @name oxfun#editOrderWs
804
+ * @description edit a trade order
805
+ * @see https://docs.ox.fun/?json#modify-order
806
+ * @param {string} id order id
807
+ * @param {string} symbol unified symbol of the market to create an order in
808
+ * @param {string} type 'market' or 'limit'
809
+ * @param {string} side 'buy' or 'sell'
810
+ * @param {float} amount how much of the currency you want to trade in units of the base currency
811
+ * @param {float|undefined} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
812
+ * @param {int} [params.timestamp] in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected.
813
+ * @param {int} [params.recvWindow] in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used.
814
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
815
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
816
+ */
817
+ await this.loadMarkets();
818
+ await this.authenticate();
819
+ const messageHash = this.nonce().toString();
820
+ const request = {
821
+ 'op': 'modifyorder',
822
+ 'tag': messageHash,
823
+ };
824
+ params = this.omit(params, 'tag');
825
+ let orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
826
+ orderRequest = this.extend(orderRequest, { 'orderId': id });
827
+ const timestamp = this.safeInteger(orderRequest, 'timestamp');
828
+ if (timestamp === undefined) {
829
+ orderRequest['timestamp'] = this.milliseconds();
830
+ }
831
+ request['data'] = orderRequest;
832
+ const url = this.urls['api']['ws'];
833
+ return await this.watch(url, messageHash, request, messageHash);
834
+ }
835
+ handlePlaceOrders(client, message) {
836
+ //
837
+ // {
838
+ // "event": "placeorder",
839
+ // "submitted": true,
840
+ // "tag": "1716934577",
841
+ // "timestamp": "1716932973899",
842
+ // "data": {
843
+ // "marketCode": "ETH-USD-SWAP-LIN",
844
+ // "side": "BUY",
845
+ // "orderType": "LIMIT",
846
+ // "quantity": "0.010",
847
+ // "timeInForce": "GTC",
848
+ // "price": "400.0",
849
+ // "limitPrice": "400.0",
850
+ // "orderId": "1000117429736",
851
+ // "source": 13
852
+ // }
853
+ // }
854
+ //
855
+ //
856
+ // Failure response format
857
+ // {
858
+ // "event": "placeorder",
859
+ // "submitted": false,
860
+ // "message": "JSON data format is invalid",
861
+ // "code": "20009",
862
+ // "timestamp": "1716932877381"
863
+ // }
864
+ //
865
+ const messageHash = this.safeString(message, 'tag');
866
+ const submitted = this.safeBool(message, 'submitted');
867
+ // filter out partial errors
868
+ if (!submitted) {
869
+ const method = this.safeString(message, 'event');
870
+ const stringMsg = this.json(message);
871
+ const code = this.safeInteger(message, 'code');
872
+ this.handleErrors(code, undefined, client.url, method, undefined, stringMsg, message, undefined, undefined);
873
+ }
874
+ const data = this.safeValue(message, 'data', {});
875
+ const order = this.parseOrder(data);
876
+ client.resolve(order, messageHash);
877
+ }
878
+ async cancelOrderWs(id, symbol = undefined, params = {}) {
879
+ /**
880
+ * @method
881
+ * @name oxfun#cancelOrderWs
882
+ * @see https://docs.ox.fun/?json#cancel-order
883
+ * @description cancels an open order
884
+ * @param {string} id order id
885
+ * @param {string} symbol unified market symbol, default is undefined
886
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
887
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
888
+ */
889
+ if (symbol === undefined) {
890
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrderWs() requires a symbol argument');
891
+ }
892
+ await this.loadMarkets();
893
+ await this.authenticate();
894
+ const messageHash = this.nonce().toString();
895
+ const data = {
896
+ 'marketCode': this.marketId(symbol),
897
+ 'orderId': id,
898
+ };
899
+ const request = {
900
+ 'op': 'cancelorder',
901
+ 'tag': messageHash,
902
+ 'data': data,
903
+ };
904
+ const url = this.urls['api']['ws'];
905
+ return await this.watch(url, messageHash, request, messageHash);
906
+ }
907
+ async cancelOrdersWs(ids, symbol = undefined, params = {}) {
908
+ /**
909
+ * @method
910
+ * @name okx#cancelOrdersWs
911
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-mass-cancel-order
912
+ * @description cancel multiple orders
913
+ * @param {string[]} ids order ids
914
+ * @param {string} symbol unified market symbol, default is undefined
915
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
916
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
917
+ */
918
+ const idsLength = ids.length;
919
+ if (idsLength > 20) {
920
+ throw new errors.BadRequest(this.id + ' cancelOrdersWs() accepts up to 20 ids at a time');
921
+ }
922
+ if (symbol === undefined) {
923
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrdersWs() requires a symbol argument');
924
+ }
925
+ await this.loadMarkets();
926
+ await this.authenticate();
927
+ const messageHash = this.nonce().toString();
928
+ const marketId = this.marketId(symbol);
929
+ const dataArray = [];
930
+ for (let i = 0; i < idsLength; i++) {
931
+ const data = {
932
+ 'instId': marketId,
933
+ 'ordId': ids[i],
934
+ };
935
+ dataArray.push(data);
936
+ }
937
+ const request = {
938
+ 'op': 'cancelorders',
939
+ 'tag': messageHash,
940
+ 'dataArray': dataArray,
941
+ };
942
+ const url = this.urls['api']['ws'];
943
+ return await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
944
+ }
945
+ async authenticate(params = {}) {
946
+ const url = this.urls['api']['ws'];
947
+ const client = this.client(url);
948
+ const messageHash = 'authenticated';
949
+ const future = client.future(messageHash);
950
+ const authenticated = this.safeDict(client.subscriptions, messageHash);
951
+ if (authenticated === undefined) {
952
+ this.checkRequiredCredentials();
953
+ const timestamp = this.milliseconds();
954
+ const payload = timestamp.toString() + 'GET/auth/self/verify';
955
+ const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256.sha256, 'base64');
956
+ const request = {
957
+ 'op': 'login',
958
+ 'data': {
959
+ 'apiKey': this.apiKey,
960
+ 'timestamp': timestamp,
961
+ 'signature': signature,
962
+ },
963
+ };
964
+ const message = this.extend(request, params);
965
+ this.watch(url, messageHash, message, messageHash);
966
+ }
967
+ return await future;
968
+ }
969
+ handleAuthenticationMessage(client, message) {
970
+ const authenticated = this.safeBool(message, 'success', false);
971
+ const messageHash = 'authenticated';
972
+ if (authenticated) {
973
+ // we resolve the future here permanently so authentication only happens once
974
+ const future = this.safeDict(client.futures, messageHash);
975
+ future.resolve(true);
976
+ }
977
+ else {
978
+ const error = new errors.AuthenticationError(this.json(message));
979
+ client.reject(error, messageHash);
980
+ if (messageHash in client.subscriptions) {
981
+ delete client.subscriptions[messageHash];
982
+ }
983
+ }
984
+ }
985
+ ping(client) {
986
+ return 'ping';
987
+ }
988
+ handlePong(client, message) {
989
+ client.lastPong = this.milliseconds();
990
+ return message;
991
+ }
992
+ handleMessage(client, message) {
993
+ if (message === 'pong') {
994
+ this.handlePong(client, message);
995
+ return;
996
+ }
997
+ const table = this.safeString(message, 'table');
998
+ const data = this.safeList(message, 'data', []);
999
+ const event = this.safeString(message, 'event');
1000
+ if ((table !== undefined) && (data !== undefined)) {
1001
+ if (table === 'trade') {
1002
+ this.handleTrades(client, message);
1003
+ }
1004
+ if (table === 'ticker') {
1005
+ this.handleTicker(client, message);
1006
+ }
1007
+ if (table.indexOf('candles') > -1) {
1008
+ this.handleOHLCV(client, message);
1009
+ }
1010
+ if (table.indexOf('depth') > -1) {
1011
+ this.handleOrderBook(client, message);
1012
+ }
1013
+ if (table.indexOf('balance') > -1) {
1014
+ this.handleBalance(client, message);
1015
+ }
1016
+ if (table.indexOf('position') > -1) {
1017
+ this.handlePositions(client, message);
1018
+ }
1019
+ if (table.indexOf('order') > -1) {
1020
+ this.handleOrders(client, message);
1021
+ }
1022
+ }
1023
+ else {
1024
+ if (event === 'login') {
1025
+ this.handleAuthenticationMessage(client, message);
1026
+ }
1027
+ if ((event === 'placeorder') || (event === 'modifyorder') || (event === 'cancelorder')) {
1028
+ this.handlePlaceOrders(client, message);
1029
+ }
1030
+ }
1031
+ }
1032
+ }
1033
+
1034
+ module.exports = oxfun;