@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.
- package/API_DOCS.md +6 -6
- package/lib/exchanges/ascendex.js +7 -3
- package/lib/exchanges/biconomy.js +65 -2
- package/lib/exchanges/binance.js +65 -3
- package/lib/exchanges/bingx.js +73 -2
- package/lib/exchanges/bitfinex.js +76 -0
- package/lib/exchanges/bitget.js +86 -3
- package/lib/exchanges/bithumb.js +3 -0
- package/lib/exchanges/bitkub.js +3 -0
- package/lib/exchanges/bitmart.js +3 -2
- package/lib/exchanges/bitmex.js +71 -1
- package/lib/exchanges/bitrue.js +59 -2
- package/lib/exchanges/bitstamp.js +71 -0
- package/lib/exchanges/blofin.js +76 -3
- package/lib/exchanges/btse.js +6 -2
- package/lib/exchanges/bybit.js +3 -2
- package/lib/exchanges/coinbase-fix.js +0 -1
- package/lib/exchanges/coinbase.js +113 -11
- package/lib/exchanges/coinstore.js +6 -2
- package/lib/exchanges/cryptocom.js +69 -2
- package/lib/exchanges/deepcoin.js +64 -0
- package/lib/exchanges/digifinex.js +62 -0
- package/lib/exchanges/exchange-base.js +167 -1
- package/lib/exchanges/exchange-fix.js +0 -2
- package/lib/exchanges/exchange-ws.js +2 -1
- package/lib/exchanges/fastex.js +3 -0
- package/lib/exchanges/gate.js +4 -2
- package/lib/exchanges/gemini.js +70 -0
- package/lib/exchanges/hashkey.js +70 -2
- package/lib/exchanges/hashkeyglobal.js +70 -2
- package/lib/exchanges/hitbtc.js +2 -1
- package/lib/exchanges/hkbitex.js +6 -2
- package/lib/exchanges/htx.js +78 -3
- package/lib/exchanges/indodax.js +3 -0
- package/lib/exchanges/kraken.js +63 -0
- package/lib/exchanges/kucoin.js +4 -3
- package/lib/exchanges/lbank.js +89 -53
- package/lib/exchanges/mexc.js +61 -2
- package/lib/exchanges/okx.js +4 -3
- package/lib/exchanges/phemex.js +4 -3
- package/lib/exchanges/swft.js +12 -9
- package/lib/exchanges/upbit.js +60 -2
- package/lib/exchanges/weex.js +3 -0
- package/lib/exchanges/xt.js +64 -2
- package/package.json +2 -2
package/lib/exchanges/mexc.js
CHANGED
|
@@ -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
|
package/lib/exchanges/okx.js
CHANGED
|
@@ -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()
|
package/lib/exchanges/phemex.js
CHANGED
|
@@ -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()
|
package/lib/exchanges/swft.js
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
// }
|
package/lib/exchanges/upbit.js
CHANGED
|
@@ -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
|
-
|
|
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 = {
|
package/lib/exchanges/weex.js
CHANGED
|
@@ -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
|
package/lib/exchanges/xt.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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",
|