@icgio/icg-exchanges 1.40.41 → 1.40.43

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 (45) hide show
  1. package/API_DOCS.md +6 -6
  2. package/lib/exchanges/ascendex.js +7 -3
  3. package/lib/exchanges/biconomy.js +65 -2
  4. package/lib/exchanges/binance.js +65 -3
  5. package/lib/exchanges/bingx.js +73 -2
  6. package/lib/exchanges/bitfinex.js +76 -0
  7. package/lib/exchanges/bitget.js +86 -3
  8. package/lib/exchanges/bithumb.js +3 -0
  9. package/lib/exchanges/bitkub.js +3 -0
  10. package/lib/exchanges/bitmart.js +3 -2
  11. package/lib/exchanges/bitmex.js +71 -1
  12. package/lib/exchanges/bitrue.js +59 -2
  13. package/lib/exchanges/bitstamp.js +71 -0
  14. package/lib/exchanges/blofin.js +76 -3
  15. package/lib/exchanges/btse.js +6 -2
  16. package/lib/exchanges/bybit.js +3 -2
  17. package/lib/exchanges/coinbase-fix.js +0 -1
  18. package/lib/exchanges/coinbase.js +113 -11
  19. package/lib/exchanges/coinstore.js +6 -2
  20. package/lib/exchanges/cryptocom.js +69 -2
  21. package/lib/exchanges/deepcoin.js +64 -0
  22. package/lib/exchanges/digifinex.js +62 -0
  23. package/lib/exchanges/exchange-base.js +167 -1
  24. package/lib/exchanges/exchange-fix.js +0 -2
  25. package/lib/exchanges/exchange-ws.js +2 -1
  26. package/lib/exchanges/fastex.js +3 -0
  27. package/lib/exchanges/gate.js +4 -2
  28. package/lib/exchanges/gemini.js +70 -0
  29. package/lib/exchanges/hashkey.js +70 -2
  30. package/lib/exchanges/hashkeyglobal.js +70 -2
  31. package/lib/exchanges/hitbtc.js +2 -1
  32. package/lib/exchanges/hkbitex.js +6 -2
  33. package/lib/exchanges/htx.js +78 -3
  34. package/lib/exchanges/indodax.js +3 -0
  35. package/lib/exchanges/kraken.js +63 -0
  36. package/lib/exchanges/kucoin.js +4 -3
  37. package/lib/exchanges/lbank.js +89 -53
  38. package/lib/exchanges/mexc.js +61 -2
  39. package/lib/exchanges/okx.js +4 -3
  40. package/lib/exchanges/phemex.js +4 -3
  41. package/lib/exchanges/swft.js +12 -9
  42. package/lib/exchanges/upbit.js +60 -2
  43. package/lib/exchanges/weex.js +3 -0
  44. package/lib/exchanges/xt.js +64 -2
  45. package/package.json +2 -2
@@ -7,6 +7,7 @@ const needle = require('needle')
7
7
 
8
8
  const ExchangeBase = require('./exchange-base.js')
9
9
  const ExchangeWs = require('./exchange-ws.js')
10
+ const { fetch_split_windows, sort_history_rows } = ExchangeBase.history_utils
10
11
 
11
12
  const { utils, rate_limiter: Limiter } = require('@icgio/icg-utils')
12
13
 
@@ -130,7 +131,7 @@ module.exports = class Mexc extends ExchangeBase {
130
131
  return false
131
132
  }
132
133
  }
133
- this.ws.market.on_message((data) => {
134
+ this.ws.market.on_message((data, t_recv) => {
134
135
  if (is_json(data)) {
135
136
  try {
136
137
  const json = JSON.parse(data.toString())
@@ -151,6 +152,7 @@ module.exports = class Mexc extends ExchangeBase {
151
152
  try {
152
153
  const message = PushDataV3ApiWrapper.decode(data)
153
154
  const obj = PushDataV3ApiWrapper.toObject(message, { enums: String, longs: String })
155
+ const t_parsed = process.hrtime()
154
156
  const pair = post_process_pair(obj.symbol)
155
157
  const channel = obj.channel
156
158
  if (channel.startsWith('spot@public.limit.depth.v3.api.pb@')) {
@@ -158,7 +160,7 @@ module.exports = class Mexc extends ExchangeBase {
158
160
  this.ws.market.pair_status[pair] = 'opened'
159
161
  this.ws.market.asks_dict[pair] = asks.map((ask) => [parseFloat(ask.price), parseFloat(ask.quantity)])
160
162
  this.ws.market.bids_dict[pair] = bids.map((bid) => [parseFloat(bid.price), parseFloat(bid.quantity)])
161
- this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: parseInt(obj.sendTime) || undefined }
163
+ this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: parseInt(obj.sendTime) || undefined, t_recv, t_parsed }
162
164
  // Derive BBO from depth data
163
165
  if (options.bbo !== false && this.ws.market.asks_dict[pair].length > 0 && this.ws.market.bids_dict[pair].length > 0) {
164
166
  this.ws.market.tickers[pair] = {
@@ -515,6 +517,63 @@ module.exports = class Mexc extends ExchangeBase {
515
517
  }
516
518
  this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
517
519
  }
520
+ get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
521
+ const get_history_trades_base = (pair, start_time_in_ms, end_time_in_ms, cb) => {
522
+ let [api_key, secret_key] = this.api_secret_key
523
+ const options = get_options(api_key)
524
+ ;(async () => {
525
+ const rows = await fetch_split_windows({
526
+ start_ms: start_time_in_ms,
527
+ stop_ms: end_time_in_ms,
528
+ initial_window_ms: Math.max(end_time_in_ms - start_time_in_ms, 60 * 1000),
529
+ page_limit: 1000,
530
+ fetch_window: async (window_start_ms, window_stop_ms) =>
531
+ await new Promise((resolve, reject) => {
532
+ let params = {
533
+ symbol: pre_process_pair(pair),
534
+ startTime: window_start_ms,
535
+ endTime: window_stop_ms - 1,
536
+ limit: 1000,
537
+ timestamp: parseInt(Date.now()),
538
+ }
539
+ let signature = get_signature_mexc(secret_key, params)
540
+ let url = 'https://api.mexc.com/api/v3/myTrades?' + qs.stringify(params) + '&signature=' + signature
541
+ needle.get(url, options, (err, res, body) => {
542
+ if (body && Array.isArray(body)) {
543
+ resolve(
544
+ body.map((trade) => {
545
+ let result = {
546
+ order_id: trade.orderId != null ? trade.orderId.toString() : '',
547
+ pair,
548
+ type: trade.isBuyer ? 'buy' : 'sell',
549
+ price: parseFloat(trade.price),
550
+ amount: parseFloat(trade.qty),
551
+ total: parseFloat(trade.quoteQty),
552
+ close_time: new Date(parseInt(trade.time)),
553
+ fees: {
554
+ [post_process_cur(trade.commissionAsset)]: parseFloat(trade.commission),
555
+ },
556
+ role: trade.isMaker ? 'maker' : 'taker',
557
+ }
558
+ if (trade.id != null) result.trade_id = trade.id.toString()
559
+ return result
560
+ }),
561
+ )
562
+ } else if (body) {
563
+ reject({ error: error_codes.other, body })
564
+ } else {
565
+ reject({ error: error_codes.timeout })
566
+ }
567
+ })
568
+ }),
569
+ })
570
+ cb({ success: true, body: sort_history_rows(rows) })
571
+ })().catch((error) => {
572
+ cb({ success: false, error: error?.error || error_codes.other, body: error?.body })
573
+ })
574
+ }
575
+ this.private_limiter.process(get_history_trades_base, pair, start_time_in_ms, end_time_in_ms, cb)
576
+ }
518
577
  get_all_deposits(timeframe_in_ms, cb) {
519
578
  let get_all_deposits_base = (timeframe_in_ms, cb) => {
520
579
  let [api_key, secret_key] = this.api_secret_key
@@ -217,13 +217,14 @@ module.exports = class Okx extends ExchangeBase {
217
217
  this.ws.market.ping('ping')
218
218
  start_market_history_socket()
219
219
  })
220
- this.ws.market.on_message((data) => {
220
+ this.ws.market.on_message((data, t_recv) => {
221
221
  if (data.toString() === 'pong') {
222
222
  this.ws.market.last_pong = new Date()
223
223
  }
224
224
  if (data.toString() !== 'pong') {
225
225
  try {
226
226
  data = JSON.parse(data)
227
+ const t_parsed = process.hrtime()
227
228
  if (data && data.arg && data.arg.channel === 'books' && data.data && data.data[0]) {
228
229
  const action = data.action
229
230
  const pair = post_process_pair(data.arg.instId, true)
@@ -262,7 +263,7 @@ module.exports = class Okx extends ExchangeBase {
262
263
  } else {
263
264
  }
264
265
  }
265
- this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: parseInt(data.data[0].ts) }
266
+ this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: parseInt(data.data[0].ts), t_recv, t_parsed }
266
267
  } else if (data && data.data && data.arg && (data.arg.channel === 'trades' || data.arg.channel === 'trades-all')) {
267
268
  for (let datum of data.data) {
268
269
  let pair = post_process_pair(datum.instId)
@@ -299,7 +300,7 @@ module.exports = class Okx extends ExchangeBase {
299
300
  if (options.depth === false) {
300
301
  this.ws.market.asks_dict[pair] = [[askPrice, askSize]]
301
302
  this.ws.market.bids_dict[pair] = [[bidPrice, bidSize]]
302
- this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: parseInt(bbo.ts) }
303
+ this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: parseInt(bbo.ts), t_recv, t_parsed }
303
304
  this.ws.market.pair_status[pair] = 'opened'
304
305
  }
305
306
  this.ws.bbo_observable.notify()
@@ -773,8 +773,9 @@ module.exports = class Phemex extends ExchangeBase {
773
773
  }),
774
774
  )
775
775
  })
776
- this.ws.market.on_message((data) => {
776
+ this.ws.market.on_message((data, t_recv) => {
777
777
  data = JSON.parse(data)
778
+ const t_parsed = process.hrtime()
778
779
  if (data && data.book && data.type === 'snapshot') {
779
780
  let pair = post_process_pair(data.symbol)
780
781
  this.ws.market.pair_status[pair] = 'opened'
@@ -784,7 +785,7 @@ module.exports = class Phemex extends ExchangeBase {
784
785
  for (let bid of data.book.bids) {
785
786
  this.ws.market.bids_dict[pair].insert(bid[0], bid[1])
786
787
  }
787
- this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: data.timestamp ? Math.floor(data.timestamp / 1e6) : undefined }
788
+ this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: data.timestamp ? Math.floor(data.timestamp / 1e6) : undefined, t_recv, t_parsed }
788
789
  {
789
790
  const _asks = this.ws.market.asks_dict[pair].entries()
790
791
  const _bids = this.ws.market.bids_dict[pair].entries()
@@ -812,7 +813,7 @@ module.exports = class Phemex extends ExchangeBase {
812
813
  this.ws.market.bids_dict[pair].insert(parseFloat(bid[0]), parseFloat(bid[1]))
813
814
  }
814
815
  }
815
- this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: data.timestamp ? Math.floor(data.timestamp / 1e6) : undefined }
816
+ this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: data.timestamp ? Math.floor(data.timestamp / 1e6) : undefined, t_recv, t_parsed }
816
817
  {
817
818
  const _asks = this.ws.market.asks_dict[pair].entries()
818
819
  const _bids = this.ws.market.bids_dict[pair].entries()
@@ -81,7 +81,7 @@ module.exports = class Swft extends ExchangeBase {
81
81
  // }
82
82
  rate(pair, orderbook_depth, cb) {
83
83
  let [api_key, secret_key] = this.public_api_secret_key
84
- let timestamp = new Date().addHours(8).getTime().toString()
84
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
85
85
  let params = {
86
86
  channelId: api_key,
87
87
  depth: '1',
@@ -110,7 +110,7 @@ module.exports = class Swft extends ExchangeBase {
110
110
  }
111
111
  market_history(pair, timeframe_in_ms, cb) {
112
112
  let [api_key, secret_key] = this.public_api_secret_key
113
- let timestamp = new Date().addHours(8).getTime().toString()
113
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
114
114
  let params = {
115
115
  channelId: api_key,
116
116
  symbol: pre_process_pair(pair),
@@ -166,7 +166,7 @@ module.exports = class Swft extends ExchangeBase {
166
166
  return filled_data
167
167
  }
168
168
  let [api_key, secret_key] = this.public_api_secret_key
169
- let timestamp = new Date().addHours(8).getTime().toString()
169
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
170
170
  let params = {
171
171
  channelId: api_key,
172
172
  period: '60min',
@@ -206,7 +206,7 @@ module.exports = class Swft extends ExchangeBase {
206
206
  return
207
207
  }
208
208
  let [api_key, secret_key] = this.api_secret_key
209
- let timestamp = new Date().addHours(8).getTime().toString()
209
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
210
210
  let params = {
211
211
  amount,
212
212
  channelId: api_key,
@@ -241,7 +241,7 @@ module.exports = class Swft extends ExchangeBase {
241
241
  }
242
242
  balance(cb) {
243
243
  let [api_key, secret_key] = this.api_secret_key
244
- let timestamp = new Date().addHours(8).getTime().toString()
244
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
245
245
  let params = {
246
246
  channelId: api_key,
247
247
  timestamp,
@@ -272,7 +272,7 @@ module.exports = class Swft extends ExchangeBase {
272
272
  get_open_orders(pair, cb) {
273
273
  let get_open_orders_base = (pair, cb) => {
274
274
  let [api_key, secret_key] = this.api_secret_key
275
- let timestamp = new Date().addHours(8).getTime().toString()
275
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
276
276
  let params = {
277
277
  channelId: api_key,
278
278
  timestamp,
@@ -304,7 +304,7 @@ module.exports = class Swft extends ExchangeBase {
304
304
  }
305
305
  cancel_order(pair, id, cb) {
306
306
  let [api_key, secret_key] = this.api_secret_key
307
- let timestamp = new Date().addHours(8).getTime().toString()
307
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
308
308
  let params = {
309
309
  channelId: api_key,
310
310
  orderId: id,
@@ -329,7 +329,7 @@ module.exports = class Swft extends ExchangeBase {
329
329
  }
330
330
  query_order_base(pair, order_id, cb) {
331
331
  let [api_key, secret_key] = this.api_secret_key
332
- let timestamp = new Date().addHours(8).getTime().toString()
332
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
333
333
  let params = {
334
334
  channelId: api_key,
335
335
  orderId: order_id,
@@ -376,7 +376,7 @@ module.exports = class Swft extends ExchangeBase {
376
376
  get_trades(pair, timeframe_in_ms, cb) {
377
377
  let get_trades_base = (pair, timeframe_in_ms, cb) => {
378
378
  let [api_key, secret_key] = this.api_secret_key
379
- let timestamp = new Date().addHours(8).getTime().toString()
379
+ let timestamp = (Date.now() + 8 * 3_600_000).toString()
380
380
  let params = {
381
381
  channelId: api_key,
382
382
  timestamp,
@@ -416,6 +416,9 @@ module.exports = class Swft extends ExchangeBase {
416
416
  }
417
417
  this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
418
418
  }
419
+ get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
420
+ this._get_history_trades_via_timeframe(pair, start_time_in_ms, end_time_in_ms, cb)
421
+ }
419
422
  // get_all_deposits(timeframe_in_ms, cb) {
420
423
  //
421
424
  // }
@@ -97,7 +97,7 @@ module.exports = class Upbit extends ExchangeBase {
97
97
  let message = JSON.stringify([JSON.stringify(sub_channels).toString()])
98
98
  this.ws.market.send(message)
99
99
  })
100
- this.ws.market.on_message((data) => {
100
+ this.ws.market.on_message((data, t_recv) => {
101
101
  if (data.startsWith('a')) {
102
102
  data = _.trim(data, 'a')
103
103
  data = JSON.parse(JSON.parse(data)[0])
@@ -107,7 +107,8 @@ module.exports = class Upbit extends ExchangeBase {
107
107
  this.ws.market.pair_status[pair] = 'opened'
108
108
  this.ws.market.asks_dict[pair] = data.orderbookUnits.map((o) => [parseFloat(o.askPrice), parseFloat(o.askSize)])
109
109
  this.ws.market.bids_dict[pair] = data.orderbookUnits.map((o) => [parseFloat(o.bidPrice), parseFloat(o.bidSize)])
110
- this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: data.timestamp }
110
+ const t_parsed = process.hrtime()
111
+ this.ws.market.ts_dict[pair] = { received_ts: Date.now(), event_ts: data.timestamp, t_recv, t_parsed }
111
112
  const asks = this.ws.market.asks_dict[pair]
112
113
  const bids = this.ws.market.bids_dict[pair]
113
114
  if (asks && asks.length > 0 && bids && bids.length > 0) {
@@ -374,6 +375,63 @@ module.exports = class Upbit extends ExchangeBase {
374
375
  }
375
376
  this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
376
377
  }
378
+ get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
379
+ let [api_key, secret_key] = this.api_secret_key
380
+ let { filter_history_in_range, sort_history_rows, split_windows, sleep } = ExchangeBase.history_utils
381
+ let fetch_page = (params) =>
382
+ new Promise((resolve, reject) => {
383
+ let options = get_options(api_key, secret_key, params)
384
+ let url = 'https://api.upbit.com/v1/orders/closed?' + qs.stringify(params)
385
+ this.private_limiter.process(needle.get, url, options, (err, res, body) => {
386
+ if (body && Array.isArray(body)) {
387
+ resolve(body)
388
+ } else if (body) {
389
+ reject({ success: false, error: error_codes.other, body })
390
+ } else {
391
+ reject({ success: false, error: error_codes.timeout })
392
+ }
393
+ })
394
+ })
395
+ ;(async () => {
396
+ let trades = []
397
+ let windows = split_windows(start_time_in_ms, end_time_in_ms, 7 * 24 * 60 * 60 * 1000)
398
+ for (let [window_start_ms, window_stop_ms] of windows) {
399
+ let page = 1
400
+ while (true) {
401
+ let params = {
402
+ market: pre_process_pair(pair),
403
+ state: 'done',
404
+ page,
405
+ limit: 100,
406
+ order_by: 'asc',
407
+ start_time: window_start_ms,
408
+ end_time: window_stop_ms - 1,
409
+ }
410
+ let rows = await fetch_page(params)
411
+ trades.push(
412
+ ...rows.map((order) => {
413
+ let price = parseFloat(order.avg_price) > 0 ? parseFloat(order.avg_price) : parseFloat(order.price)
414
+ let amount = parseFloat(order.executed_volume)
415
+ return {
416
+ order_id: order.uuid,
417
+ pair,
418
+ type: order.side === 'bid' ? 'buy' : 'sell',
419
+ price,
420
+ amount,
421
+ total: Number.isFinite(parseFloat(order.executed_funds)) ? parseFloat(order.executed_funds) : price * amount,
422
+ close_time: new Date(order.done_at || order.created_at),
423
+ }
424
+ })
425
+ )
426
+ if (rows.length < 100) break
427
+ page++
428
+ await sleep(250)
429
+ }
430
+ }
431
+ trades = sort_history_rows(filter_history_in_range(trades, start_time_in_ms, end_time_in_ms))
432
+ cb({ success: true, body: trades })
433
+ })().catch((error) => cb(error))
434
+ }
377
435
  get_trades_id(pair, order_id, timeframe_in_ms, cb) {
378
436
  let get_trades_id_base = (pair, order_id, timeframe_in_ms, cb) => {
379
437
  let params = {
@@ -393,6 +393,9 @@ module.exports = class Weex extends ExchangeBase {
393
393
  }
394
394
  this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
395
395
  }
396
+ get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
397
+ this._get_history_trades_via_timeframe(pair, start_time_in_ms, end_time_in_ms, cb)
398
+ }
396
399
  get_all_deposits(timeframe_in_ms, cb) {
397
400
  let get_all_deposits_base = (cb) => {
398
401
  let [api_key, secret_key] = this.api_secret_key
@@ -7,6 +7,7 @@ const websocket = require('ws')
7
7
 
8
8
  const ExchangeBase = require('./exchange-base.js')
9
9
  const ExchangeWs = require('./exchange-ws.js')
10
+ const { fetch_split_windows, sort_query_params, sort_history_rows } = ExchangeBase.history_utils
10
11
 
11
12
  const { error_codes } = require('../error_codes.json')
12
13
  const { utils, rate_limiter: Limiter } = require('@icgio/icg-utils')
@@ -121,7 +122,7 @@ module.exports = class Xt extends ExchangeBase {
121
122
  })
122
123
  this.ws.market.ping('ping')
123
124
  })
124
- this.ws.market.on_message((data) => {
125
+ this.ws.market.on_message((data, t_recv) => {
125
126
  if (data.toString() === 'pong') {
126
127
  this.ws.market.last_pong = new Date()
127
128
  } else {
@@ -130,13 +131,14 @@ module.exports = class Xt extends ExchangeBase {
130
131
  } catch (err) {
131
132
  console.error('xt websocket', data.toString(), err)
132
133
  }
134
+ const t_parsed = process.hrtime()
133
135
  let book = data.data
134
136
  if (data && data.topic === 'depth' && book) {
135
137
  let pair = post_process_pair(data.data.s)
136
138
  this.ws.market.pair_status[pair] = 'opened'
137
139
  this.ws.market.asks_dict[pair] = data.data.a.map((ask) => [parseFloat(ask[0]), parseFloat(ask[1])])
138
140
  this.ws.market.bids_dict[pair] = data.data.b.map((bid) => [parseFloat(bid[0]), parseFloat(bid[1])])
139
- this.ws.market.ts_dict[pair] = { received_ts: Date.now() }
141
+ this.ws.market.ts_dict[pair] = { received_ts: Date.now(), t_recv, t_parsed }
140
142
  const asks = this.ws.market.asks_dict[pair]
141
143
  const bids = this.ws.market.bids_dict[pair]
142
144
  if (asks && asks.length > 0 && bids && bids.length > 0) {
@@ -516,6 +518,66 @@ module.exports = class Xt extends ExchangeBase {
516
518
  }
517
519
  this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
518
520
  }
521
+ get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
522
+ const get_history_trades_base = (pair, start_time_in_ms, end_time_in_ms, cb) => {
523
+ let [api_key, secret_key] = this.api_secret_key
524
+ ;(async () => {
525
+ const rows = await fetch_split_windows({
526
+ start_ms: start_time_in_ms,
527
+ stop_ms: end_time_in_ms,
528
+ initial_window_ms: 4 * 60 * 60 * 1000,
529
+ page_limit: 100,
530
+ fetch_window: async (window_start_ms, window_stop_ms) =>
531
+ await new Promise((resolve, reject) => {
532
+ const path = '/v4/trade'
533
+ const params = sort_query_params({
534
+ bizType: 'SPOT',
535
+ endTime: window_stop_ms - 1,
536
+ limit: 100,
537
+ startTime: window_start_ms,
538
+ symbol: pre_process_pair(pair),
539
+ })
540
+ const url = 'https://sapi.xt.com' + path + '?' + qs.stringify(params)
541
+ const timestamp = new Date().getTime()
542
+ const sign = get_signature_xt(api_key, secret_key, 'GET', path, params, '', timestamp)
543
+ const options = get_options(api_key, timestamp, sign)
544
+ needle.get(url, options, (err, res, body) => {
545
+ body = parse_body(body)
546
+ if (body && body.mc === 'SUCCESS' && body.result && Array.isArray(body.result.items)) {
547
+ resolve(
548
+ body.result.items.map((item) => {
549
+ let trade = {
550
+ order_id: item.orderId != null ? item.orderId.toString() : '',
551
+ pair,
552
+ type: String(item.orderSide || '').toLowerCase(),
553
+ price: parseFloat(item.price),
554
+ amount: parseFloat(item.quantity),
555
+ total: parseFloat(item.quoteQty),
556
+ close_time: new Date(item.time),
557
+ fees: {
558
+ [post_process_cur(item.feeCurrency)]: parseFloat(item.fee),
559
+ },
560
+ role: String(item.takerMaker || '').toLowerCase(),
561
+ }
562
+ if (item.tradeId != null) trade.trade_id = item.tradeId.toString()
563
+ return trade
564
+ }),
565
+ )
566
+ } else if (body) {
567
+ reject({ error: error_codes.other, body })
568
+ } else {
569
+ reject({ error: error_codes.timeout })
570
+ }
571
+ })
572
+ }),
573
+ })
574
+ cb({ success: true, body: sort_history_rows(rows) })
575
+ })().catch((error) => {
576
+ cb({ success: false, error: error?.error || error_codes.other, body: error?.body })
577
+ })
578
+ }
579
+ this.private_limiter.process(get_history_trades_base, pair, start_time_in_ms, end_time_in_ms, cb)
580
+ }
519
581
  get_deposits(cur, timeframe_in_ms, cb) {
520
582
  const chains = ['Tron', 'BNB Smart Chain', 'Ethereum']
521
583
  let get_deposits_base = (timeframe_in_ms, cb) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icgio/icg-exchanges",
3
- "version": "1.40.41",
3
+ "version": "1.40.43",
4
4
  "description": "icgio exchanges package",
5
5
  "main": "./exchanges.js",
6
6
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "homepage": "https://github.com/icgio/icg-exchanges#readme",
20
20
  "dependencies": {
21
- "@icgio/icg-utils": "^1.9.58",
21
+ "@icgio/icg-utils": "^1.9.60",
22
22
  "json-bigint": "^1.0.0",
23
23
  "jsonwebtoken": "^9.0.3",
24
24
  "lodash": "^4.17.20",