@icgio/icg-exchanges 1.40.42 → 1.40.44
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 +3 -0
- package/lib/exchanges/biconomy.js +62 -0
- package/lib/exchanges/binance.js +61 -0
- package/lib/exchanges/bingx.js +70 -0
- package/lib/exchanges/bitfinex.js +76 -0
- package/lib/exchanges/bitget.js +82 -0
- package/lib/exchanges/bithumb.js +3 -0
- package/lib/exchanges/bitkub.js +3 -0
- package/lib/exchanges/bitmex.js +69 -0
- package/lib/exchanges/bitrue.js +56 -0
- package/lib/exchanges/bitstamp.js +71 -0
- package/lib/exchanges/blofin.js +72 -0
- package/lib/exchanges/btse.js +3 -0
- package/lib/exchanges/coinbase.js +102 -0
- package/lib/exchanges/coinstore.js +3 -0
- package/lib/exchanges/cryptocom.js +66 -0
- 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/fastex.js +3 -0
- package/lib/exchanges/gemini.js +70 -0
- package/lib/exchanges/hashkey.js +67 -0
- package/lib/exchanges/hashkeyglobal.js +67 -0
- package/lib/exchanges/hkbitex.js +3 -0
- package/lib/exchanges/htx.js +74 -0
- package/lib/exchanges/indodax.js +3 -0
- package/lib/exchanges/kraken.js +63 -0
- package/lib/exchanges/lbank.js +86 -51
- package/lib/exchanges/mexc.js +58 -0
- package/lib/exchanges/swft.js +3 -0
- package/lib/exchanges/upbit.js +57 -0
- package/lib/exchanges/weex.js +3 -0
- package/lib/exchanges/xt.js +61 -0
- package/package.json +1 -1
|
@@ -370,6 +370,77 @@ module.exports = class Bitstamp extends ExchangeBase {
|
|
|
370
370
|
}
|
|
371
371
|
this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
|
|
372
372
|
}
|
|
373
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
374
|
+
let [api_key, secret_key] = this.api_secret_key
|
|
375
|
+
let { filter_history_in_range, sort_history_rows, sleep } = ExchangeBase.history_utils
|
|
376
|
+
let [base_cur, quote_cur] = utils.parse_pair(pair)
|
|
377
|
+
let base_key = base_cur.toLowerCase()
|
|
378
|
+
let quote_key = quote_cur.toLowerCase()
|
|
379
|
+
let price_key = base_key + '_' + quote_key
|
|
380
|
+
let parse_trade_time = (datetime) => {
|
|
381
|
+
let iso = datetime.replace(' ', 'T').replace(/(\.\d{3})\d+$/, '$1')
|
|
382
|
+
return new Date(iso + 'Z')
|
|
383
|
+
}
|
|
384
|
+
let fetch_page = (offset) =>
|
|
385
|
+
new Promise((resolve, reject) => {
|
|
386
|
+
let url = 'https://www.bitstamp.net/api/v2/user_transactions/' + pre_process_pair(pair) + '/'
|
|
387
|
+
let params = {
|
|
388
|
+
key: api_key,
|
|
389
|
+
nonce: Date.now(),
|
|
390
|
+
signature: get_signature_bitstamp(api_key, secret_key, this.account_id),
|
|
391
|
+
limit: 1000,
|
|
392
|
+
offset,
|
|
393
|
+
sort: 'desc',
|
|
394
|
+
}
|
|
395
|
+
needle.post(url, params, (err, res, body) => {
|
|
396
|
+
if (Array.isArray(body)) {
|
|
397
|
+
resolve(body)
|
|
398
|
+
} else if (body) {
|
|
399
|
+
reject({ success: false, error: error_codes.other, body })
|
|
400
|
+
} else {
|
|
401
|
+
reject({ success: false, error: error_codes.timeout })
|
|
402
|
+
}
|
|
403
|
+
})
|
|
404
|
+
})
|
|
405
|
+
;(async () => {
|
|
406
|
+
let trades = []
|
|
407
|
+
let offset = 0
|
|
408
|
+
while (offset <= 200000) {
|
|
409
|
+
let rows = await fetch_page(offset)
|
|
410
|
+
if (rows.length === 0) break
|
|
411
|
+
trades.push(
|
|
412
|
+
...rows
|
|
413
|
+
.filter((trade) => String(trade.type) === '2')
|
|
414
|
+
.map((trade) => {
|
|
415
|
+
let close_time = parse_trade_time(trade.datetime)
|
|
416
|
+
let price = parseFloat(trade[price_key])
|
|
417
|
+
let amount = Math.abs(parseFloat(trade[base_key]))
|
|
418
|
+
let total = Math.abs(parseFloat(trade[quote_key]))
|
|
419
|
+
return {
|
|
420
|
+
order_id: trade.order_id != null ? trade.order_id.toString() : '',
|
|
421
|
+
trade_id: (trade.id || trade.tid || '').toString(),
|
|
422
|
+
pair,
|
|
423
|
+
type: parseFloat(trade[base_key]) < 0 ? 'sell' : 'buy',
|
|
424
|
+
price,
|
|
425
|
+
amount,
|
|
426
|
+
total: Number.isFinite(total) ? total : price * amount,
|
|
427
|
+
close_time,
|
|
428
|
+
}
|
|
429
|
+
})
|
|
430
|
+
)
|
|
431
|
+
let oldest_seen_ms = Math.min(
|
|
432
|
+
...rows
|
|
433
|
+
.map((trade) => parse_trade_time(trade.datetime).getTime())
|
|
434
|
+
.filter((time) => Number.isFinite(time))
|
|
435
|
+
)
|
|
436
|
+
if (rows.length < 1000 || (Number.isFinite(oldest_seen_ms) && oldest_seen_ms < start_time_in_ms)) break
|
|
437
|
+
offset += rows.length
|
|
438
|
+
await sleep(250)
|
|
439
|
+
}
|
|
440
|
+
trades = sort_history_rows(filter_history_in_range(trades, start_time_in_ms, end_time_in_ms))
|
|
441
|
+
cb({ success: true, body: trades })
|
|
442
|
+
})().catch((error) => cb(error))
|
|
443
|
+
}
|
|
373
444
|
static get_min_amount(cb) {
|
|
374
445
|
let min_quote_cur_amount = {}
|
|
375
446
|
needle.get('https://www.bitstamp.net/api/v2/trading-pairs-info/', (err, res, body) => {
|
package/lib/exchanges/blofin.js
CHANGED
|
@@ -583,6 +583,78 @@ module.exports = class Blofin extends ExchangeBase {
|
|
|
583
583
|
}
|
|
584
584
|
this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
|
|
585
585
|
}
|
|
586
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
587
|
+
let [api_key, secret_key] = this.api_secret_key
|
|
588
|
+
let { fetch_split_windows, filter_history_in_range, sort_history_rows } = ExchangeBase.history_utils
|
|
589
|
+
let [base_cur, quote_cur] = utils.parse_pair(pair)
|
|
590
|
+
let path = '/api/v1/spot/trade/fills-history'
|
|
591
|
+
let fetch_window = (window_start_ms, window_stop_ms) =>
|
|
592
|
+
new Promise((resolve, reject) => {
|
|
593
|
+
let params = {
|
|
594
|
+
instType: 'SPOT',
|
|
595
|
+
instId: pre_process_pair(pair),
|
|
596
|
+
begin: window_start_ms.toString(),
|
|
597
|
+
end: (window_stop_ms - 1).toString(),
|
|
598
|
+
limit: '100',
|
|
599
|
+
}
|
|
600
|
+
let query = qs.stringify(params)
|
|
601
|
+
let request_path = path + '?' + query
|
|
602
|
+
let timestamp = Date.now()
|
|
603
|
+
let nonce = generate_nonce()
|
|
604
|
+
let signature = get_signature_blofin(secret_key, 'GET', timestamp, request_path, nonce)
|
|
605
|
+
let options = get_options(api_key, signature, timestamp, nonce, this.passphrase)
|
|
606
|
+
let url = 'https://openapi.blofin.com' + request_path
|
|
607
|
+
needle.get(url, options, (err, res, body) => {
|
|
608
|
+
if (body && _.includes(['0', 0, 200], body.code) && Array.isArray(body.data)) {
|
|
609
|
+
resolve(
|
|
610
|
+
body.data.map((trade) => {
|
|
611
|
+
let price = parseFloat(trade.fillPrice || trade.trade_price)
|
|
612
|
+
let amount = parseFloat(trade.fillSize || trade.trade_quantity)
|
|
613
|
+
let total = price * amount
|
|
614
|
+
let fee = Math.abs(parseFloat(trade.fee || trade.trade_fee))
|
|
615
|
+
let fee_currency = trade.feeCurrency || trade.fee_currency
|
|
616
|
+
if (fee_currency === 'base_currency') fee_currency = base_cur
|
|
617
|
+
if (fee_currency === 'quote_currency') fee_currency = quote_cur
|
|
618
|
+
let mapped_trade = {
|
|
619
|
+
order_id: (trade.orderId || trade.order_id || '').toString(),
|
|
620
|
+
trade_id: (trade.tradeId || trade.trade_id || '').toString(),
|
|
621
|
+
pair,
|
|
622
|
+
type: (trade.side || trade.order_side || '').toLowerCase(),
|
|
623
|
+
price,
|
|
624
|
+
amount,
|
|
625
|
+
total,
|
|
626
|
+
close_time: new Date(parseInt(trade.ts || trade.create_time)),
|
|
627
|
+
}
|
|
628
|
+
if (Number.isFinite(fee) && fee_currency) {
|
|
629
|
+
mapped_trade.fees = {
|
|
630
|
+
[post_process_cur(fee_currency)]: fee,
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
return mapped_trade
|
|
634
|
+
})
|
|
635
|
+
)
|
|
636
|
+
} else if (body && body.toString().startsWith('<html>')) {
|
|
637
|
+
reject({ success: false, error: error_codes.service_unavailable, body })
|
|
638
|
+
} else if (body) {
|
|
639
|
+
reject({ success: false, error: error_codes.other, body })
|
|
640
|
+
} else {
|
|
641
|
+
reject({ success: false, error: error_codes.timeout })
|
|
642
|
+
}
|
|
643
|
+
})
|
|
644
|
+
})
|
|
645
|
+
;(async () => {
|
|
646
|
+
let trades = await fetch_split_windows({
|
|
647
|
+
start_ms: start_time_in_ms,
|
|
648
|
+
stop_ms: end_time_in_ms,
|
|
649
|
+
initial_window_ms: 30 * 24 * 60 * 60 * 1000,
|
|
650
|
+
page_limit: 100,
|
|
651
|
+
fetch_window,
|
|
652
|
+
delay_ms: 250,
|
|
653
|
+
})
|
|
654
|
+
trades = sort_history_rows(filter_history_in_range(trades, start_time_in_ms, end_time_in_ms))
|
|
655
|
+
cb({ success: true, body: trades })
|
|
656
|
+
})().catch((error) => cb(error))
|
|
657
|
+
}
|
|
586
658
|
get_all_deposits(timeframe_in_ms, cb) {
|
|
587
659
|
let get_all_deposits_base = (timeframe_in_ms, cb) => {
|
|
588
660
|
let [api_key, secret_key] = this.api_secret_key
|
package/lib/exchanges/btse.js
CHANGED
|
@@ -488,6 +488,9 @@ module.exports = class Btse extends ExchangeBase {
|
|
|
488
488
|
}
|
|
489
489
|
this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
|
|
490
490
|
}
|
|
491
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
492
|
+
this._get_history_trades_via_timeframe(pair, start_time_in_ms, end_time_in_ms, cb)
|
|
493
|
+
}
|
|
491
494
|
get_all_deposits(timeframe_in_ms, cb) {
|
|
492
495
|
let get_all_deposits_base = (timeframe_in_ms, cb) => {
|
|
493
496
|
let [api_key, secret_key] = this.api_secret_key
|
|
@@ -7,6 +7,7 @@ const needle = require('needle')
|
|
|
7
7
|
|
|
8
8
|
const ExchangeWs = require('./exchange-ws.js')
|
|
9
9
|
const ExchangeBase = require('./exchange-base.js')
|
|
10
|
+
const { filter_history_in_range, history_time_ms, sleep, sort_history_rows } = ExchangeBase.history_utils
|
|
10
11
|
|
|
11
12
|
const { sorted_book } = require('@icgio/icg-utils')
|
|
12
13
|
|
|
@@ -1572,6 +1573,107 @@ module.exports = class Coinbase extends ExchangeBase {
|
|
|
1572
1573
|
cb({ success: true, body: [] })
|
|
1573
1574
|
}
|
|
1574
1575
|
}
|
|
1576
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
1577
|
+
const get_history_trades_base = async (pair, start_time_in_ms, end_time_in_ms, cb) => {
|
|
1578
|
+
try {
|
|
1579
|
+
const results = []
|
|
1580
|
+
if (this.advanced) {
|
|
1581
|
+
let cursor = null
|
|
1582
|
+
while (true) {
|
|
1583
|
+
let path = '/api/v3/brokerage/orders/historical/fills'
|
|
1584
|
+
let params = { product_id: pre_process_pair(pair) }
|
|
1585
|
+
if (cursor) params.cursor = cursor
|
|
1586
|
+
let options = this._get_auth('GET', path, params)
|
|
1587
|
+
let url = this._base_url() + path + '?' + qs.stringify(params)
|
|
1588
|
+
const response = await new Promise((resolve, reject) => {
|
|
1589
|
+
needle.get(url, options, (err, res, body) => {
|
|
1590
|
+
if (body && Array.isArray(body.fills)) {
|
|
1591
|
+
resolve(body)
|
|
1592
|
+
} else if (body) {
|
|
1593
|
+
reject({ error: error_codes.other, body })
|
|
1594
|
+
} else {
|
|
1595
|
+
reject({ error: error_codes.timeout })
|
|
1596
|
+
}
|
|
1597
|
+
})
|
|
1598
|
+
})
|
|
1599
|
+
if (response.fills.length === 0) break
|
|
1600
|
+
let oldest_ms = Infinity
|
|
1601
|
+
for (const fill of response.fills) {
|
|
1602
|
+
const close_time_ms = history_time_ms(fill.trade_time)
|
|
1603
|
+
if (close_time_ms < oldest_ms) oldest_ms = close_time_ms
|
|
1604
|
+
if (close_time_ms < start_time_in_ms || close_time_ms >= end_time_in_ms) continue
|
|
1605
|
+
let quote_cur = (fill.product_id || '').split('-')[1] || ''
|
|
1606
|
+
let trade = {
|
|
1607
|
+
order_id: fill.order_id != null ? fill.order_id.toString() : '',
|
|
1608
|
+
pair,
|
|
1609
|
+
type: String(fill.side || '').toLowerCase(),
|
|
1610
|
+
price: parseFloat(fill.price),
|
|
1611
|
+
amount: parseFloat(fill.size),
|
|
1612
|
+
total: parseFloat(fill.price) * parseFloat(fill.size),
|
|
1613
|
+
close_time: new Date(close_time_ms),
|
|
1614
|
+
fees: quote_cur && fill.commission != null ? { [post_process_cur(quote_cur)]: parseFloat(fill.commission) } : {},
|
|
1615
|
+
role: fill.liquidity_indicator === 'MAKER' ? 'maker' : 'taker',
|
|
1616
|
+
}
|
|
1617
|
+
if (fill.trade_id != null) trade.trade_id = fill.trade_id.toString()
|
|
1618
|
+
else if (fill.entry_id != null) trade.trade_id = fill.entry_id.toString()
|
|
1619
|
+
results.push(trade)
|
|
1620
|
+
}
|
|
1621
|
+
if (!response.has_next || !response.cursor || oldest_ms < start_time_in_ms) break
|
|
1622
|
+
cursor = response.cursor
|
|
1623
|
+
await sleep(50)
|
|
1624
|
+
}
|
|
1625
|
+
} else {
|
|
1626
|
+
let after = null
|
|
1627
|
+
while (true) {
|
|
1628
|
+
let path = '/fills'
|
|
1629
|
+
let params = { product_id: pre_process_pair(pair) }
|
|
1630
|
+
if (after) params.after = after
|
|
1631
|
+
let options = this._get_auth('GET', path, params)
|
|
1632
|
+
let url = this._base_url() + path + '?' + qs.stringify(params)
|
|
1633
|
+
const response = await new Promise((resolve, reject) => {
|
|
1634
|
+
needle.get(url, options, (err, res, body) => {
|
|
1635
|
+
if (body && Array.isArray(body)) {
|
|
1636
|
+
resolve({ res, body })
|
|
1637
|
+
} else if (body) {
|
|
1638
|
+
reject({ error: error_codes.other, body })
|
|
1639
|
+
} else {
|
|
1640
|
+
reject({ error: error_codes.timeout })
|
|
1641
|
+
}
|
|
1642
|
+
})
|
|
1643
|
+
})
|
|
1644
|
+
if (response.body.length === 0) break
|
|
1645
|
+
let oldest_ms = Infinity
|
|
1646
|
+
for (const fill of response.body) {
|
|
1647
|
+
const close_time_ms = history_time_ms(fill.created_at)
|
|
1648
|
+
if (close_time_ms < oldest_ms) oldest_ms = close_time_ms
|
|
1649
|
+
if (close_time_ms < start_time_in_ms || close_time_ms >= end_time_in_ms) continue
|
|
1650
|
+
let trade = {
|
|
1651
|
+
order_id: fill.order_id != null ? fill.order_id.toString() : '',
|
|
1652
|
+
pair,
|
|
1653
|
+
type: String(fill.side || '').toLowerCase(),
|
|
1654
|
+
price: parseFloat(fill.price),
|
|
1655
|
+
amount: parseFloat(fill.size),
|
|
1656
|
+
total: parseFloat(fill.price) * parseFloat(fill.size),
|
|
1657
|
+
close_time: new Date(close_time_ms),
|
|
1658
|
+
fees: fill.funding_currency && fill.fee != null ? { [post_process_cur(fill.funding_currency)]: parseFloat(fill.fee) } : {},
|
|
1659
|
+
role: fill.liquidity === 'M' ? 'maker' : 'taker',
|
|
1660
|
+
}
|
|
1661
|
+
if (fill.trade_id != null) trade.trade_id = fill.trade_id.toString()
|
|
1662
|
+
results.push(trade)
|
|
1663
|
+
}
|
|
1664
|
+
const next_after = response.res?.headers?.['cb-after']
|
|
1665
|
+
if (!next_after || oldest_ms < start_time_in_ms) break
|
|
1666
|
+
after = next_after
|
|
1667
|
+
await sleep(50)
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
cb({ success: true, body: sort_history_rows(filter_history_in_range(results, start_time_in_ms, end_time_in_ms)) })
|
|
1671
|
+
} catch (error) {
|
|
1672
|
+
cb({ success: false, error: error?.error || error_codes.other, body: error?.body })
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
this.private_limiter.process(get_history_trades_base, pair, start_time_in_ms, end_time_in_ms, cb)
|
|
1676
|
+
}
|
|
1575
1677
|
_convert(from_cur, to_cur, amount, cb) {
|
|
1576
1678
|
if (this.advanced) {
|
|
1577
1679
|
cb({ success: false, error: error_codes.other, body: { message: 'Convert not supported on Advanced API' } })
|
|
@@ -476,6 +476,9 @@ module.exports = class Coinstore extends ExchangeBase {
|
|
|
476
476
|
}
|
|
477
477
|
this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
|
|
478
478
|
}
|
|
479
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
480
|
+
this._get_history_trades_via_timeframe(pair, start_time_in_ms, end_time_in_ms, cb)
|
|
481
|
+
}
|
|
479
482
|
static get_precision(cb) {
|
|
480
483
|
const price_precision = {}
|
|
481
484
|
const amount_precision = {}
|
|
@@ -493,6 +493,72 @@ module.exports = class Cryptocom extends ExchangeBase {
|
|
|
493
493
|
}
|
|
494
494
|
})
|
|
495
495
|
}
|
|
496
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
497
|
+
let [api_key, secret_key] = this.api_secret_key
|
|
498
|
+
let { fetch_split_windows, filter_history_in_range, sort_history_rows } = ExchangeBase.history_utils
|
|
499
|
+
let fetch_window = (window_start_ms, window_stop_ms) =>
|
|
500
|
+
new Promise((resolve, reject) => {
|
|
501
|
+
let req = {
|
|
502
|
+
id: 11,
|
|
503
|
+
method: 'private/get-trades',
|
|
504
|
+
params: {
|
|
505
|
+
instrument_name: pre_process_pair(pair),
|
|
506
|
+
start_time: window_start_ms,
|
|
507
|
+
end_time: window_stop_ms - 1,
|
|
508
|
+
limit: 100,
|
|
509
|
+
},
|
|
510
|
+
api_key: api_key,
|
|
511
|
+
nonce: Date.now(),
|
|
512
|
+
}
|
|
513
|
+
req.sig = get_signature_crypto(req, secret_key)
|
|
514
|
+
needle.post('https://api.crypto.com/v2/private/get-trades', req, options, (err, res, body) => {
|
|
515
|
+
body = parse_body(body)
|
|
516
|
+
let rows = body?.result?.data || body?.result?.trade_list
|
|
517
|
+
if (body && body.code === 0 && Array.isArray(rows)) {
|
|
518
|
+
resolve(
|
|
519
|
+
rows.map((trade) => {
|
|
520
|
+
let price = parseFloat(trade.traded_price)
|
|
521
|
+
let amount = parseFloat(trade.traded_quantity)
|
|
522
|
+
let fee = Math.abs(parseFloat(trade.fees || trade.fee))
|
|
523
|
+
let mapped_trade = {
|
|
524
|
+
order_id: (trade.order_id || '').toString(),
|
|
525
|
+
trade_id: (trade.trade_id || trade.trade_match_id || '').toString(),
|
|
526
|
+
pair,
|
|
527
|
+
type: (trade.side || '').toLowerCase(),
|
|
528
|
+
price,
|
|
529
|
+
amount,
|
|
530
|
+
total: price * amount,
|
|
531
|
+
close_time: new Date(parseInt(trade.create_time)),
|
|
532
|
+
}
|
|
533
|
+
if (trade.taker_side) mapped_trade.role = trade.taker_side.toLowerCase()
|
|
534
|
+
if (Number.isFinite(fee) && trade.fee_instrument_name) {
|
|
535
|
+
mapped_trade.fees = {
|
|
536
|
+
[post_process_cur(trade.fee_instrument_name)]: fee,
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return mapped_trade
|
|
540
|
+
})
|
|
541
|
+
)
|
|
542
|
+
} else if (body) {
|
|
543
|
+
reject({ success: false, error: error_codes.other, body })
|
|
544
|
+
} else {
|
|
545
|
+
reject({ success: false, error: error_codes.timeout })
|
|
546
|
+
}
|
|
547
|
+
})
|
|
548
|
+
})
|
|
549
|
+
;(async () => {
|
|
550
|
+
let trades = await fetch_split_windows({
|
|
551
|
+
start_ms: start_time_in_ms,
|
|
552
|
+
stop_ms: end_time_in_ms,
|
|
553
|
+
initial_window_ms: 7 * 24 * 60 * 60 * 1000,
|
|
554
|
+
page_limit: 100,
|
|
555
|
+
fetch_window,
|
|
556
|
+
delay_ms: 250,
|
|
557
|
+
})
|
|
558
|
+
trades = sort_history_rows(filter_history_in_range(trades, start_time_in_ms, end_time_in_ms))
|
|
559
|
+
cb({ success: true, body: trades })
|
|
560
|
+
})().catch((error) => cb(error))
|
|
561
|
+
}
|
|
496
562
|
get_all_deposits(timeframe_in_ms, cb) {
|
|
497
563
|
let [api_key, secret_key] = this.api_secret_key
|
|
498
564
|
let req = {
|
|
@@ -467,6 +467,70 @@ module.exports = class Deepcoin extends ExchangeBase {
|
|
|
467
467
|
}
|
|
468
468
|
this.private_limiter.process(get_all_trades_base, timeframe_in_ms, cb, 2)
|
|
469
469
|
}
|
|
470
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
471
|
+
let [api_key, secret_key] = this.api_secret_key
|
|
472
|
+
let { fetch_split_windows, filter_history_in_range, sort_history_rows } = ExchangeBase.history_utils
|
|
473
|
+
let path = '/deepcoin/trade/fills'
|
|
474
|
+
let fetch_window = (window_start_ms, window_stop_ms) =>
|
|
475
|
+
new Promise((resolve, reject) => {
|
|
476
|
+
let params = {
|
|
477
|
+
instType: 'SPOT',
|
|
478
|
+
instId: pre_process_pair(pair),
|
|
479
|
+
begin: window_start_ms,
|
|
480
|
+
end: window_stop_ms - 1,
|
|
481
|
+
limit: 100,
|
|
482
|
+
}
|
|
483
|
+
let query = qs.stringify(params)
|
|
484
|
+
let options = get_options(api_key, secret_key, this.passphrase, 'GET', path + '?' + query, '')
|
|
485
|
+
needle.get(base_url + path + '?' + query, options, (err, res, body) => {
|
|
486
|
+
body = parse_body(body)
|
|
487
|
+
if (body && body.code === '0' && Array.isArray(body.data)) {
|
|
488
|
+
resolve(
|
|
489
|
+
body.data.map((trade) => {
|
|
490
|
+
let price = parseFloat(trade.fillPx)
|
|
491
|
+
let amount = parseFloat(trade.fillSz)
|
|
492
|
+
let mapped_trade = {
|
|
493
|
+
order_id: (trade.ordId || '').toString(),
|
|
494
|
+
trade_id: (trade.tradeId || trade.billId || '').toString(),
|
|
495
|
+
pair: post_process_pair(trade.instId),
|
|
496
|
+
type: trade.side,
|
|
497
|
+
price,
|
|
498
|
+
amount,
|
|
499
|
+
total: price * amount,
|
|
500
|
+
close_time: new Date(parseInt(trade.ts)),
|
|
501
|
+
}
|
|
502
|
+
if (trade.execType === 'M') mapped_trade.role = 'maker'
|
|
503
|
+
if (trade.execType === 'T') mapped_trade.role = 'taker'
|
|
504
|
+
if (trade.feeCcy && Number.isFinite(parseFloat(trade.fee))) {
|
|
505
|
+
mapped_trade.fees = {
|
|
506
|
+
[post_process_cur(trade.feeCcy)]: Math.abs(parseFloat(trade.fee)),
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return mapped_trade
|
|
510
|
+
})
|
|
511
|
+
)
|
|
512
|
+
} else if (body && (body.code === '50026' || body.code === '50001')) {
|
|
513
|
+
reject({ success: false, error: error_codes.service_unavailable, body })
|
|
514
|
+
} else if (body) {
|
|
515
|
+
reject({ success: false, error: error_codes.other, body })
|
|
516
|
+
} else {
|
|
517
|
+
reject({ success: false, error: error_codes.timeout })
|
|
518
|
+
}
|
|
519
|
+
})
|
|
520
|
+
})
|
|
521
|
+
;(async () => {
|
|
522
|
+
let trades = await fetch_split_windows({
|
|
523
|
+
start_ms: start_time_in_ms,
|
|
524
|
+
stop_ms: end_time_in_ms,
|
|
525
|
+
initial_window_ms: 30 * 24 * 60 * 60 * 1000,
|
|
526
|
+
page_limit: 100,
|
|
527
|
+
fetch_window,
|
|
528
|
+
delay_ms: 250,
|
|
529
|
+
})
|
|
530
|
+
trades = sort_history_rows(filter_history_in_range(trades, start_time_in_ms, end_time_in_ms))
|
|
531
|
+
cb({ success: true, body: trades })
|
|
532
|
+
})().catch((error) => cb(error))
|
|
533
|
+
}
|
|
470
534
|
static get_min_amount(cb) {
|
|
471
535
|
let min_quote_cur_amount = {}
|
|
472
536
|
needle.get('https://api.deepcoin.com/deepcoin/market/instruments?instType=SPOT', (err, res, body) => {
|
|
@@ -381,6 +381,68 @@ module.exports = class Digifinex extends ExchangeBase {
|
|
|
381
381
|
}
|
|
382
382
|
this.private_limiter.process(get_trades_base, pair, timeframe_in_ms, cb)
|
|
383
383
|
}
|
|
384
|
+
get_history_trades(pair, start_time_in_ms, end_time_in_ms, cb) {
|
|
385
|
+
let [api_key, secret_key] = this.api_secret_key
|
|
386
|
+
let { fetch_split_windows, filter_history_in_range, sort_history_rows } = ExchangeBase.history_utils
|
|
387
|
+
let fetch_window = (window_start_ms, window_stop_ms) =>
|
|
388
|
+
new Promise((resolve, reject) => {
|
|
389
|
+
let params = {
|
|
390
|
+
symbol: pre_process_pair(pair),
|
|
391
|
+
limit: 500,
|
|
392
|
+
start_time: Math.floor(window_start_ms / 1000),
|
|
393
|
+
end_time: Math.floor((window_stop_ms - 1) / 1000),
|
|
394
|
+
}
|
|
395
|
+
let signature = get_signature_digifinex(secret_key, params)
|
|
396
|
+
let options = get_options(api_key, signature)
|
|
397
|
+
let url = 'https://openapi.digifinex.com/v3/spot/mytrades?' + qs.stringify(params)
|
|
398
|
+
needle.get(url, options, (err, res, body) => {
|
|
399
|
+
if (body && body.code === 0 && Array.isArray(body.list)) {
|
|
400
|
+
resolve(
|
|
401
|
+
body.list.map((trade) => {
|
|
402
|
+
let price = parseFloat(trade.price)
|
|
403
|
+
let amount = parseFloat(trade.amount)
|
|
404
|
+
let is_maker = trade.is_maker === true || trade.is_maker === 1 || trade.is_maker === '1' || trade.is_maker === 'true'
|
|
405
|
+
let mapped_trade = {
|
|
406
|
+
order_id: (trade.order_id || '').toString(),
|
|
407
|
+
trade_id: (trade.id || trade.tid || '').toString(),
|
|
408
|
+
pair,
|
|
409
|
+
type: (trade.side || '').split('_')[0],
|
|
410
|
+
price,
|
|
411
|
+
amount,
|
|
412
|
+
total: price * amount,
|
|
413
|
+
close_time: new Date(parseInt(trade.timestamp) * 1000),
|
|
414
|
+
role: is_maker ? 'maker' : 'taker',
|
|
415
|
+
}
|
|
416
|
+
if (trade.fee_currency && Number.isFinite(parseFloat(trade.fee))) {
|
|
417
|
+
mapped_trade.fees = {
|
|
418
|
+
[post_process_cur(trade.fee_currency)]: Math.abs(parseFloat(trade.fee)),
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return mapped_trade
|
|
422
|
+
})
|
|
423
|
+
)
|
|
424
|
+
} else if (body && body.toString().startsWith('<html>')) {
|
|
425
|
+
reject({ success: false, error: error_codes.service_unavailable, body })
|
|
426
|
+
} else if (body) {
|
|
427
|
+
reject({ success: false, error: error_codes.other, body })
|
|
428
|
+
} else {
|
|
429
|
+
reject({ success: false, error: error_codes.timeout })
|
|
430
|
+
}
|
|
431
|
+
})
|
|
432
|
+
})
|
|
433
|
+
;(async () => {
|
|
434
|
+
let trades = await fetch_split_windows({
|
|
435
|
+
start_ms: start_time_in_ms,
|
|
436
|
+
stop_ms: end_time_in_ms,
|
|
437
|
+
initial_window_ms: 30 * 24 * 60 * 60 * 1000,
|
|
438
|
+
page_limit: 500,
|
|
439
|
+
fetch_window,
|
|
440
|
+
delay_ms: 250,
|
|
441
|
+
})
|
|
442
|
+
trades = sort_history_rows(filter_history_in_range(trades, start_time_in_ms, end_time_in_ms))
|
|
443
|
+
cb({ success: true, body: trades })
|
|
444
|
+
})().catch((error) => cb(error))
|
|
445
|
+
}
|
|
384
446
|
get_all_deposits(timeframe_in_ms, cb) {
|
|
385
447
|
let get_all_deposits_base = (timeframe_in_ms, cb) => {
|
|
386
448
|
let [api_key, secret_key] = this.api_secret_key
|