ccxt-look 1.81.50
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/.cache/eslintcache +1 -0
- package/.dockerignore +6 -0
- package/.eslintignore +1 -0
- package/.gitattributes +5 -0
- package/.readthedocs.yaml +16 -0
- package/CONTRIBUTING.md +1049 -0
- package/LICENSE.txt +21 -0
- package/README.md +537 -0
- package/SECURITY.md +5 -0
- package/build/cleanup-old-tags.js +94 -0
- package/build/countries.js +256 -0
- package/build/export-exchanges.js +520 -0
- package/build/fs.js +51 -0
- package/build/transpile.js +1772 -0
- package/build/vss.js +78 -0
- package/ccxt.browser.js +7 -0
- package/ccxt.d.ts +692 -0
- package/ccxt.js +171 -0
- package/cleanup.sh +2 -0
- package/composer-install.sh +20 -0
- package/dist/ccxt.browser.js +208383 -0
- package/gource.sh +3 -0
- package/index.html +7 -0
- package/js/.eslintrc +87 -0
- package/js/aax.js +2686 -0
- package/js/ascendex.js +2584 -0
- package/js/base/.eslintrc.js +43 -0
- package/js/base/Exchange.js +2371 -0
- package/js/base/Precise.js +283 -0
- package/js/base/errorHierarchy.js +47 -0
- package/js/base/errors.js +55 -0
- package/js/base/functions/crypto.js +158 -0
- package/js/base/functions/encode.js +118 -0
- package/js/base/functions/generic.js +270 -0
- package/js/base/functions/misc.js +138 -0
- package/js/base/functions/number.js +329 -0
- package/js/base/functions/platform.js +38 -0
- package/js/base/functions/string.js +21 -0
- package/js/base/functions/throttle.js +79 -0
- package/js/base/functions/time.js +210 -0
- package/js/base/functions/type.js +66 -0
- package/js/base/functions.js +28 -0
- package/js/bequant.js +32 -0
- package/js/bibox.js +1407 -0
- package/js/bigone.js +1366 -0
- package/js/binance.js +5652 -0
- package/js/binancecoinm.js +46 -0
- package/js/binanceus.js +46 -0
- package/js/binanceusdm.js +49 -0
- package/js/bit2c.js +535 -0
- package/js/bitbank.js +842 -0
- package/js/bitbay.js +16 -0
- package/js/bitbns.js +1073 -0
- package/js/bitcoincom.js +15 -0
- package/js/bitfinex.js +1433 -0
- package/js/bitfinex2.js +2025 -0
- package/js/bitflyer.js +840 -0
- package/js/bitforex.js +614 -0
- package/js/bitget.js +2397 -0
- package/js/bithumb.js +980 -0
- package/js/bitmart.js +2516 -0
- package/js/bitmex.js +1809 -0
- package/js/bitopro.js +1443 -0
- package/js/bitpanda.js +1782 -0
- package/js/bitrue.js +1747 -0
- package/js/bitso.js +1062 -0
- package/js/bitstamp.js +1757 -0
- package/js/bitstamp1.js +343 -0
- package/js/bittrex.js +1876 -0
- package/js/bitvavo.js +1579 -0
- package/js/bkex.js +1233 -0
- package/js/bl3p.js +346 -0
- package/js/blockchaincom.js +969 -0
- package/js/btcalpha.js +680 -0
- package/js/btcbox.js +477 -0
- package/js/btcmarkets.js +1022 -0
- package/js/btctradeua.js +466 -0
- package/js/btcturk.js +734 -0
- package/js/buda.js +946 -0
- package/js/bw.js +1265 -0
- package/js/bybit.js +3372 -0
- package/js/bytetrade.js +1336 -0
- package/js/cdax.js +1646 -0
- package/js/cex.js +1410 -0
- package/js/coinbase.js +1342 -0
- package/js/coinbaseprime.js +31 -0
- package/js/coinbasepro.js +1466 -0
- package/js/coincheck.js +755 -0
- package/js/coinex.js +3400 -0
- package/js/coinfalcon.js +880 -0
- package/js/coinmate.js +794 -0
- package/js/coinone.js +816 -0
- package/js/coinspot.js +345 -0
- package/js/crex24.js +1636 -0
- package/js/cryptocom.js +1832 -0
- package/js/currencycom.js +1748 -0
- package/js/delta.js +1547 -0
- package/js/deribit.js +2148 -0
- package/js/digifinex.js +1585 -0
- package/js/eqonex.js +1660 -0
- package/js/exmo.js +1670 -0
- package/js/fairdesk.js +1231 -0
- package/js/flowbtc.js +35 -0
- package/js/fmfwio.js +34 -0
- package/js/ftx.js +2751 -0
- package/js/ftxus.js +38 -0
- package/js/gateio.js +4174 -0
- package/js/gemini.js +1397 -0
- package/js/hitbtc.js +1343 -0
- package/js/hitbtc3.js +2329 -0
- package/js/hollaex.js +1486 -0
- package/js/huobi.js +5706 -0
- package/js/huobijp.js +1710 -0
- package/js/huobipro.js +18 -0
- package/js/idex.js +1439 -0
- package/js/independentreserve.js +649 -0
- package/js/indodax.js +742 -0
- package/js/itbit.js +722 -0
- package/js/kraken.js +2179 -0
- package/js/kucoin.js +2571 -0
- package/js/kucoinfutures.js +1771 -0
- package/js/kuna.js +809 -0
- package/js/latoken.js +1445 -0
- package/js/lbank.js +760 -0
- package/js/liquid.js +1432 -0
- package/js/luno.js +873 -0
- package/js/lykke.js +1147 -0
- package/js/mercado.js +771 -0
- package/js/mexc.js +3151 -0
- package/js/ndax.js +2233 -0
- package/js/novadax.js +1318 -0
- package/js/oceanex.js +816 -0
- package/js/okcoin.js +3841 -0
- package/js/okex.js +16 -0
- package/js/okex5.js +16 -0
- package/js/okx.js +4795 -0
- package/js/paymium.js +498 -0
- package/js/phemex.js +2957 -0
- package/js/poloniex.js +1674 -0
- package/js/probit.js +1346 -0
- package/js/qtrade.js +1588 -0
- package/js/ripio.js +1061 -0
- package/js/static_dependencies/BN/bn.js +3526 -0
- package/js/static_dependencies/README.md +1 -0
- package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
- package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
- package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
- package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
- package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
- package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
- package/js/static_dependencies/node-fetch/index.js +1564 -0
- package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
- package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
- package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
- package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
- package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
- package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
- package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
- package/js/static_dependencies/node-rsa/formats/components.js +71 -0
- package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
- package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
- package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
- package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
- package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
- package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
- package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
- package/js/static_dependencies/node-rsa/utils.js +98 -0
- package/js/static_dependencies/qs/formats.js +18 -0
- package/js/static_dependencies/qs/index.js +11 -0
- package/js/static_dependencies/qs/parse.js +242 -0
- package/js/static_dependencies/qs/stringify.js +269 -0
- package/js/static_dependencies/qs/utils.js +230 -0
- package/js/stex.js +1925 -0
- package/js/test/.eslintrc.js +42 -0
- package/js/test/Exchange/test.balance.js +61 -0
- package/js/test/Exchange/test.borrowRate.js +32 -0
- package/js/test/Exchange/test.currency.js +52 -0
- package/js/test/Exchange/test.fetchBalance.js +23 -0
- package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
- package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
- package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
- package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
- package/js/test/Exchange/test.fetchCurrencies.js +35 -0
- package/js/test/Exchange/test.fetchDeposits.js +31 -0
- package/js/test/Exchange/test.fetchFundingFees.js +19 -0
- package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
- package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
- package/js/test/Exchange/test.fetchLedger.js +42 -0
- package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
- package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
- package/js/test/Exchange/test.fetchMarkets.js +33 -0
- package/js/test/Exchange/test.fetchMyTrades.js +42 -0
- package/js/test/Exchange/test.fetchOHLCV.js +46 -0
- package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
- package/js/test/Exchange/test.fetchOrderBook.js +25 -0
- package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
- package/js/test/Exchange/test.fetchOrders.js +41 -0
- package/js/test/Exchange/test.fetchPositions.js +47 -0
- package/js/test/Exchange/test.fetchStatus.js +35 -0
- package/js/test/Exchange/test.fetchTicker.js +38 -0
- package/js/test/Exchange/test.fetchTickers.js +49 -0
- package/js/test/Exchange/test.fetchTrades.js +39 -0
- package/js/test/Exchange/test.fetchTradingFee.js +18 -0
- package/js/test/Exchange/test.fetchTradingFees.js +22 -0
- package/js/test/Exchange/test.fetchTransactions.js +31 -0
- package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
- package/js/test/Exchange/test.ledgerItem.js +46 -0
- package/js/test/Exchange/test.leverageTier.js +33 -0
- package/js/test/Exchange/test.loadMarkets.js +35 -0
- package/js/test/Exchange/test.market.js +129 -0
- package/js/test/Exchange/test.ohlcv.js +33 -0
- package/js/test/Exchange/test.order.js +62 -0
- package/js/test/Exchange/test.orderbook.js +61 -0
- package/js/test/Exchange/test.position.js +21 -0
- package/js/test/Exchange/test.throttle.js +94 -0
- package/js/test/Exchange/test.ticker.js +95 -0
- package/js/test/Exchange/test.trade.js +68 -0
- package/js/test/Exchange/test.tradingFee.js +34 -0
- package/js/test/Exchange/test.transaction.js +35 -0
- package/js/test/base/.eslintrc +38 -0
- package/js/test/base/functions/test.crypto.js +110 -0
- package/js/test/base/functions/test.datetime.js +62 -0
- package/js/test/base/functions/test.generic.js +152 -0
- package/js/test/base/functions/test.number.js +362 -0
- package/js/test/base/functions/test.time.js +56 -0
- package/js/test/base/functions/test.type.js +53 -0
- package/js/test/base/test.base.js +193 -0
- package/js/test/errors/test.InsufficientFunds.js +86 -0
- package/js/test/errors/test.InvalidNonce.js +64 -0
- package/js/test/errors/test.InvalidOrder.js +35 -0
- package/js/test/errors/test.OrderNotFound.js +39 -0
- package/js/test/test.js +426 -0
- package/js/test/test.timeout_hang.js +12 -0
- package/js/therock.js +1431 -0
- package/js/tidebit.js +632 -0
- package/js/tidex.js +939 -0
- package/js/timex.js +1283 -0
- package/js/upbit.js +1622 -0
- package/js/vcc.js +1353 -0
- package/js/wavesexchange.js +2185 -0
- package/js/wazirx.js +732 -0
- package/js/whitebit.js +1352 -0
- package/js/woo.js +1577 -0
- package/js/xena.js +1948 -0
- package/js/yobit.js +1129 -0
- package/js/zaif.js +647 -0
- package/js/zb.js +4088 -0
- package/js/zipmex.js +40 -0
- package/js/zonda.js +1497 -0
- package/multilang.sh +159 -0
- package/package.json +591 -0
- package/postinstall.js +103 -0
package/js/bitfinex2.js
ADDED
@@ -0,0 +1,2025 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const bitfinex = require ('./bitfinex.js');
|
6
|
+
const { ExchangeError, InvalidAddress, ArgumentsRequired, InsufficientFunds, AuthenticationError, OrderNotFound, InvalidOrder, BadRequest, InvalidNonce, BadSymbol, OnMaintenance, NotSupported, PermissionDenied, ExchangeNotAvailable } = require ('./base/errors');
|
7
|
+
const Precise = require ('./base/Precise');
|
8
|
+
|
9
|
+
// ---------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = class bitfinex2 extends bitfinex {
|
12
|
+
describe () {
|
13
|
+
return this.deepExtend (super.describe (), {
|
14
|
+
'id': 'bitfinex2',
|
15
|
+
'name': 'Bitfinex',
|
16
|
+
'countries': [ 'VG' ],
|
17
|
+
'version': 'v2',
|
18
|
+
'certified': false,
|
19
|
+
'pro': false,
|
20
|
+
// new metainfo interface
|
21
|
+
'has': {
|
22
|
+
'CORS': undefined,
|
23
|
+
'spot': true,
|
24
|
+
'margin': undefined, // has but unimplemented
|
25
|
+
'swap': undefined, // has but unimplemented
|
26
|
+
'future': undefined,
|
27
|
+
'option': undefined,
|
28
|
+
'cancelAllOrders': true,
|
29
|
+
'cancelOrder': true,
|
30
|
+
'createDepositAddress': true,
|
31
|
+
'createLimitOrder': true,
|
32
|
+
'createMarketOrder': true,
|
33
|
+
'createOrder': true,
|
34
|
+
'createStopLimitOrder': true,
|
35
|
+
'createStopMarketOrder': true,
|
36
|
+
'createStopOrder': true,
|
37
|
+
'editOrder': undefined,
|
38
|
+
'fetchBalance': true,
|
39
|
+
'fetchClosedOrder': true,
|
40
|
+
'fetchClosedOrders': true,
|
41
|
+
'fetchCurrencies': true,
|
42
|
+
'fetchDepositAddress': true,
|
43
|
+
'fetchFundingFees': undefined,
|
44
|
+
'fetchIndexOHLCV': false,
|
45
|
+
'fetchLedger': true,
|
46
|
+
'fetchMarkOHLCV': false,
|
47
|
+
'fetchMyTrades': true,
|
48
|
+
'fetchOHLCV': true,
|
49
|
+
'fetchOpenOrder': true,
|
50
|
+
'fetchOpenOrders': true,
|
51
|
+
'fetchOrder': true,
|
52
|
+
'fetchOrderTrades': true,
|
53
|
+
'fetchStatus': true,
|
54
|
+
'fetchTickers': true,
|
55
|
+
'fetchTime': false,
|
56
|
+
'fetchTradingFee': false,
|
57
|
+
'fetchTradingFees': true,
|
58
|
+
'fetchTransactions': true,
|
59
|
+
'withdraw': true,
|
60
|
+
},
|
61
|
+
'timeframes': {
|
62
|
+
'1m': '1m',
|
63
|
+
'5m': '5m',
|
64
|
+
'15m': '15m',
|
65
|
+
'30m': '30m',
|
66
|
+
'1h': '1h',
|
67
|
+
'3h': '3h',
|
68
|
+
'4h': '4h',
|
69
|
+
'6h': '6h',
|
70
|
+
'12h': '12h',
|
71
|
+
'1d': '1D',
|
72
|
+
'1w': '7D',
|
73
|
+
'2w': '14D',
|
74
|
+
'1M': '1M',
|
75
|
+
},
|
76
|
+
// cheapest endpoint is 240 requests per minute => ~ 4 requests per second => ( 1000ms / 4 ) = 250ms between requests on average
|
77
|
+
'rateLimit': 250,
|
78
|
+
'urls': {
|
79
|
+
'logo': 'https://user-images.githubusercontent.com/1294454/27766244-e328a50c-5ed2-11e7-947b-041416579bb3.jpg',
|
80
|
+
'api': {
|
81
|
+
'v1': 'https://api.bitfinex.com',
|
82
|
+
'public': 'https://api-pub.bitfinex.com',
|
83
|
+
'private': 'https://api.bitfinex.com',
|
84
|
+
},
|
85
|
+
'www': 'https://www.bitfinex.com',
|
86
|
+
'doc': [
|
87
|
+
'https://docs.bitfinex.com/v2/docs/',
|
88
|
+
'https://github.com/bitfinexcom/bitfinex-api-node',
|
89
|
+
],
|
90
|
+
'fees': 'https://www.bitfinex.com/fees',
|
91
|
+
},
|
92
|
+
'api': {
|
93
|
+
'v1': {
|
94
|
+
'get': [
|
95
|
+
'symbols',
|
96
|
+
'symbols_details',
|
97
|
+
],
|
98
|
+
},
|
99
|
+
'public': {
|
100
|
+
'get': {
|
101
|
+
'conf/{config}': 2.66, // 90 requests a minute
|
102
|
+
'conf/pub:{action}:{object}': 2.66,
|
103
|
+
'conf/pub:{action}:{object}:{detail}': 2.66,
|
104
|
+
'conf/pub:map:{object}': 2.66,
|
105
|
+
'conf/pub:map:{object}:{detail}': 2.66,
|
106
|
+
'conf/pub:map:currency:{detail}': 2.66,
|
107
|
+
'conf/pub:map:currency:sym': 2.66, // maps symbols to their API symbols, BAB > BCH
|
108
|
+
'conf/pub:map:currency:label': 2.66, // verbose friendly names, BNT > Bancor
|
109
|
+
'conf/pub:map:currency:unit': 2.66, // maps symbols to unit of measure where applicable
|
110
|
+
'conf/pub:map:currency:undl': 2.66, // maps derivatives symbols to their underlying currency
|
111
|
+
'conf/pub:map:currency:pool': 2.66, // maps symbols to underlying network/protocol they operate on
|
112
|
+
'conf/pub:map:currency:explorer': 2.66, // maps symbols to their recognised block explorer URLs
|
113
|
+
'conf/pub:map:currency:tx:fee': 2.66, // maps currencies to their withdrawal fees https://github.com/ccxt/ccxt/issues/7745
|
114
|
+
'conf/pub:map:tx:method': 2.66,
|
115
|
+
'conf/pub:list:{object}': 2.66,
|
116
|
+
'conf/pub:list:{object}:{detail}': 2.66,
|
117
|
+
'conf/pub:list:currency': 2.66,
|
118
|
+
'conf/pub:list:pair:exchange': 2.66,
|
119
|
+
'conf/pub:list:pair:margin': 2.66,
|
120
|
+
'conf/pub:list:pair:futures': 2.66,
|
121
|
+
'conf/pub:list:competitions': 2.66,
|
122
|
+
'conf/pub:info:{object}': 2.66,
|
123
|
+
'conf/pub:info:{object}:{detail}': 2.66,
|
124
|
+
'conf/pub:info:pair': 2.66,
|
125
|
+
'conf/pub:info:tx:status': 2.66, // [ deposit, withdrawal ] statuses 1 = active, 0 = maintenance
|
126
|
+
'conf/pub:fees': 2.66,
|
127
|
+
'platform/status': 8, // 30 requests per minute = 0.5 requests per second => ( 1000ms / rateLimit ) / 0.5 = 8
|
128
|
+
'tickers': 2.66, // 90 requests a minute = 1.5 requests per second => ( 1000 / rateLimit ) / 1.5 = 2.666666666
|
129
|
+
'ticker/{symbol}': 2.66,
|
130
|
+
'tickers/hist': 2.66,
|
131
|
+
'trades/{symbol}/hist': 2.66,
|
132
|
+
'book/{symbol}/{precision}': 1, // 240 requests a minute
|
133
|
+
'book/{symbol}/P0': 1,
|
134
|
+
'book/{symbol}/P1': 1,
|
135
|
+
'book/{symbol}/P2': 1,
|
136
|
+
'book/{symbol}/P3': 1,
|
137
|
+
'book/{symbol}/R0': 1,
|
138
|
+
'stats1/{key}:{size}:{symbol}:{side}/{section}': 2.66,
|
139
|
+
'stats1/{key}:{size}:{symbol}:{side}/last': 2.66,
|
140
|
+
'stats1/{key}:{size}:{symbol}:{side}/hist': 2.66,
|
141
|
+
'stats1/{key}:{size}:{symbol}/{section}': 2.66,
|
142
|
+
'stats1/{key}:{size}:{symbol}/last': 2.66,
|
143
|
+
'stats1/{key}:{size}:{symbol}/hist': 2.66,
|
144
|
+
'stats1/{key}:{size}:{symbol}:long/last': 2.66,
|
145
|
+
'stats1/{key}:{size}:{symbol}:long/hist': 2.66,
|
146
|
+
'stats1/{key}:{size}:{symbol}:short/last': 2.66,
|
147
|
+
'stats1/{key}:{size}:{symbol}:short/hist': 2.66,
|
148
|
+
'candles/trade:{timeframe}:{symbol}:{period}/{section}': 2.66,
|
149
|
+
'candles/trade:{timeframe}:{symbol}/{section}': 2.66,
|
150
|
+
'candles/trade:{timeframe}:{symbol}/last': 2.66,
|
151
|
+
'candles/trade:{timeframe}:{symbol}/hist': 2.66,
|
152
|
+
'status/{type}': 2.66,
|
153
|
+
'status/deriv': 2.66,
|
154
|
+
'liquidations/hist': 80, // 3 requests a minute = 0.05 requests a second => ( 1000ms / rateLimit ) / 0.05 = 80
|
155
|
+
'rankings/{key}:{timeframe}:{symbol}/{section}': 2.66,
|
156
|
+
'rankings/{key}:{timeframe}:{symbol}/hist': 2.66,
|
157
|
+
'pulse/hist': 2.66,
|
158
|
+
'pulse/profile/{nickname}': 2.66,
|
159
|
+
'funding/stats/{symbol}/hist': 10, // ratelimit not in docs
|
160
|
+
},
|
161
|
+
'post': {
|
162
|
+
'calc/trade/avg': 2.66,
|
163
|
+
'calc/fx': 2.66,
|
164
|
+
},
|
165
|
+
},
|
166
|
+
'private': {
|
167
|
+
'post': {
|
168
|
+
// 'auth/r/orders/{symbol}/new', // outdated
|
169
|
+
// 'auth/r/stats/perf:{timeframe}/hist', // outdated
|
170
|
+
'auth/r/wallets': 2.66,
|
171
|
+
'auth/r/wallets/hist': 2.66,
|
172
|
+
'auth/r/orders': 2.66,
|
173
|
+
'auth/r/orders/{symbol}': 2.66,
|
174
|
+
'auth/w/order/submit': 2.66,
|
175
|
+
'auth/w/order/update': 2.66,
|
176
|
+
'auth/w/order/cancel': 2.66,
|
177
|
+
'auth/w/order/multi': 2.66,
|
178
|
+
'auth/w/order/cancel/multi': 2.66,
|
179
|
+
'auth/r/orders/{symbol}/hist': 2.66,
|
180
|
+
'auth/r/orders/hist': 2.66,
|
181
|
+
'auth/r/order/{symbol}:{id}/trades': 2.66,
|
182
|
+
'auth/r/trades/{symbol}/hist': 2.66,
|
183
|
+
'auth/r/trades/hist': 2.66,
|
184
|
+
'auth/r/ledgers/{currency}/hist': 2.66,
|
185
|
+
'auth/r/ledgers/hist': 2.66,
|
186
|
+
'auth/r/info/margin/{key}': 2.66,
|
187
|
+
'auth/r/info/margin/base': 2.66,
|
188
|
+
'auth/r/info/margin/sym_all': 2.66,
|
189
|
+
'auth/r/positions': 2.66,
|
190
|
+
'auth/w/position/claim': 2.66,
|
191
|
+
'auth/w/position/increase:': 2.66,
|
192
|
+
'auth/r/position/increase/info': 2.66,
|
193
|
+
'auth/r/positions/hist': 2.66,
|
194
|
+
'auth/r/positions/audit': 2.66,
|
195
|
+
'auth/r/positions/snap': 2.66,
|
196
|
+
'auth/w/deriv/collateral/set': 2.66,
|
197
|
+
'auth/w/deriv/collateral/limits': 2.66,
|
198
|
+
'auth/r/funding/offers': 2.66,
|
199
|
+
'auth/r/funding/offers/{symbol}': 2.66,
|
200
|
+
'auth/w/funding/offer/submit': 2.66,
|
201
|
+
'auth/w/funding/offer/cancel': 2.66,
|
202
|
+
'auth/w/funding/offer/cancel/all': 2.66,
|
203
|
+
'auth/w/funding/close': 2.66,
|
204
|
+
'auth/w/funding/auto': 2.66,
|
205
|
+
'auth/w/funding/keep': 2.66,
|
206
|
+
'auth/r/funding/offers/{symbol}/hist': 2.66,
|
207
|
+
'auth/r/funding/offers/hist': 2.66,
|
208
|
+
'auth/r/funding/loans': 2.66,
|
209
|
+
'auth/r/funding/loans/hist': 2.66,
|
210
|
+
'auth/r/funding/loans/{symbol}': 2.66,
|
211
|
+
'auth/r/funding/loans/{symbol}/hist': 2.66,
|
212
|
+
'auth/r/funding/credits': 2.66,
|
213
|
+
'auth/r/funding/credits/hist': 2.66,
|
214
|
+
'auth/r/funding/credits/{symbol}': 2.66,
|
215
|
+
'auth/r/funding/credits/{symbol}/hist': 2.66,
|
216
|
+
'auth/r/funding/trades/{symbol}/hist': 2.66,
|
217
|
+
'auth/r/funding/trades/hist': 2.66,
|
218
|
+
'auth/r/info/funding/{key}': 2.66,
|
219
|
+
'auth/r/info/user': 2.66,
|
220
|
+
'auth/r/summary': 2.66,
|
221
|
+
'auth/r/logins/hist': 2.66,
|
222
|
+
'auth/r/permissions': 2.66,
|
223
|
+
'auth/w/token': 2.66,
|
224
|
+
'auth/r/audit/hist': 2.66,
|
225
|
+
'auth/w/transfer': 2.66, // ratelimit not in docs...
|
226
|
+
'auth/w/deposit/address': 24, // 10 requests a minute = 0.166 requests per second => ( 1000ms / rateLimit ) / 0.166 = 24
|
227
|
+
'auth/w/deposit/invoice': 24, // ratelimit not in docs
|
228
|
+
'auth/w/withdraw': 24, // ratelimit not in docs
|
229
|
+
'auth/r/movements/{currency}/hist': 2.66,
|
230
|
+
'auth/r/movements/hist': 2.66,
|
231
|
+
'auth/r/alerts': 5.33, // 45 requests a minute = 0.75 requests per second => ( 1000ms / rateLimit ) / 0.75 => 5.33
|
232
|
+
'auth/w/alert/set': 2.66,
|
233
|
+
'auth/w/alert/price:{symbol}:{price}/del': 2.66,
|
234
|
+
'auth/w/alert/{type}:{symbol}:{price}/del': 2.66,
|
235
|
+
'auth/calc/order/avail': 2.66,
|
236
|
+
'auth/w/settings/set': 2.66,
|
237
|
+
'auth/r/settings': 2.66,
|
238
|
+
'auth/w/settings/del': 2.66,
|
239
|
+
'auth/r/pulse/hist': 2.66,
|
240
|
+
'auth/w/pulse/add': 16, // 15 requests a minute = 0.25 requests per second => ( 1000ms / rateLimit ) / 0.25 => 16
|
241
|
+
'auth/w/pulse/del': 2.66,
|
242
|
+
},
|
243
|
+
},
|
244
|
+
},
|
245
|
+
'fees': {
|
246
|
+
'trading': {
|
247
|
+
'feeSide': 'get',
|
248
|
+
'percentage': true,
|
249
|
+
'tierBased': true,
|
250
|
+
'maker': this.parseNumber ('0.001'),
|
251
|
+
'taker': this.parseNumber ('0.002'),
|
252
|
+
'tiers': {
|
253
|
+
'taker': [
|
254
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.002') ],
|
255
|
+
[ this.parseNumber ('500000'), this.parseNumber ('0.002') ],
|
256
|
+
[ this.parseNumber ('1000000'), this.parseNumber ('0.002') ],
|
257
|
+
[ this.parseNumber ('2500000'), this.parseNumber ('0.002') ],
|
258
|
+
[ this.parseNumber ('5000000'), this.parseNumber ('0.002') ],
|
259
|
+
[ this.parseNumber ('7500000'), this.parseNumber ('0.002') ],
|
260
|
+
[ this.parseNumber ('10000000'), this.parseNumber ('0.0018') ],
|
261
|
+
[ this.parseNumber ('15000000'), this.parseNumber ('0.0016') ],
|
262
|
+
[ this.parseNumber ('20000000'), this.parseNumber ('0.0014') ],
|
263
|
+
[ this.parseNumber ('25000000'), this.parseNumber ('0.0012') ],
|
264
|
+
[ this.parseNumber ('30000000'), this.parseNumber ('0.001') ],
|
265
|
+
],
|
266
|
+
'maker': [
|
267
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.001') ],
|
268
|
+
[ this.parseNumber ('500000'), this.parseNumber ('0.0008') ],
|
269
|
+
[ this.parseNumber ('1000000'), this.parseNumber ('0.0006') ],
|
270
|
+
[ this.parseNumber ('2500000'), this.parseNumber ('0.0004') ],
|
271
|
+
[ this.parseNumber ('5000000'), this.parseNumber ('0.0002') ],
|
272
|
+
[ this.parseNumber ('7500000'), this.parseNumber ('0') ],
|
273
|
+
[ this.parseNumber ('10000000'), this.parseNumber ('0') ],
|
274
|
+
[ this.parseNumber ('15000000'), this.parseNumber ('0') ],
|
275
|
+
[ this.parseNumber ('20000000'), this.parseNumber ('0') ],
|
276
|
+
[ this.parseNumber ('25000000'), this.parseNumber ('0') ],
|
277
|
+
[ this.parseNumber ('30000000'), this.parseNumber ('0') ],
|
278
|
+
],
|
279
|
+
},
|
280
|
+
},
|
281
|
+
'funding': {
|
282
|
+
'withdraw': {},
|
283
|
+
},
|
284
|
+
},
|
285
|
+
'options': {
|
286
|
+
'precision': 'R0', // P0, P1, P2, P3, P4, R0
|
287
|
+
// convert 'EXCHANGE MARKET' to lowercase 'market'
|
288
|
+
// convert 'EXCHANGE LIMIT' to lowercase 'limit'
|
289
|
+
// everything else remains uppercase
|
290
|
+
'exchangeTypes': {
|
291
|
+
// 'MARKET': undefined,
|
292
|
+
'EXCHANGE MARKET': 'market',
|
293
|
+
// 'LIMIT': undefined,
|
294
|
+
'EXCHANGE LIMIT': 'limit',
|
295
|
+
// 'STOP': undefined,
|
296
|
+
// 'EXCHANGE STOP': undefined,
|
297
|
+
// 'TRAILING STOP': undefined,
|
298
|
+
// 'EXCHANGE TRAILING STOP': undefined,
|
299
|
+
// 'FOK': undefined,
|
300
|
+
// 'EXCHANGE FOK': undefined,
|
301
|
+
// 'STOP LIMIT': undefined,
|
302
|
+
// 'EXCHANGE STOP LIMIT': undefined,
|
303
|
+
// 'IOC': undefined,
|
304
|
+
// 'EXCHANGE IOC': undefined,
|
305
|
+
},
|
306
|
+
// convert 'market' to 'EXCHANGE MARKET'
|
307
|
+
// convert 'limit' 'EXCHANGE LIMIT'
|
308
|
+
// everything else remains as is
|
309
|
+
'orderTypes': {
|
310
|
+
'market': 'EXCHANGE MARKET',
|
311
|
+
'limit': 'EXCHANGE LIMIT',
|
312
|
+
},
|
313
|
+
'fiat': {
|
314
|
+
'USD': 'USD',
|
315
|
+
'EUR': 'EUR',
|
316
|
+
'JPY': 'JPY',
|
317
|
+
'GBP': 'GBP',
|
318
|
+
'CHN': 'CHN',
|
319
|
+
},
|
320
|
+
// actually the correct names unlike the v1
|
321
|
+
// we don't want to extend this with accountsByType in v1
|
322
|
+
'v2AccountsByType': {
|
323
|
+
'spot': 'exchange',
|
324
|
+
'exchange': 'exchange',
|
325
|
+
'funding': 'funding',
|
326
|
+
'margin': 'margin',
|
327
|
+
'derivatives': 'margin',
|
328
|
+
'future': 'margin',
|
329
|
+
},
|
330
|
+
'swap': {
|
331
|
+
'fetchMarkets': {
|
332
|
+
'settlementCurrencies': [ 'BTC', 'USDT', 'EURT' ],
|
333
|
+
},
|
334
|
+
},
|
335
|
+
},
|
336
|
+
'exceptions': {
|
337
|
+
'exact': {
|
338
|
+
'10001': PermissionDenied, // api_key: permission invalid (#10001)
|
339
|
+
'10020': BadRequest,
|
340
|
+
'10100': AuthenticationError,
|
341
|
+
'10114': InvalidNonce,
|
342
|
+
'20060': OnMaintenance,
|
343
|
+
// {"code":503,"error":"temporarily_unavailable","error_description":"Sorry, the service is temporarily unavailable. See https://www.bitfinex.com/ for more info."}
|
344
|
+
'temporarily_unavailable': ExchangeNotAvailable,
|
345
|
+
},
|
346
|
+
'broad': {
|
347
|
+
'address': InvalidAddress,
|
348
|
+
'available balance is only': InsufficientFunds,
|
349
|
+
'not enough exchange balance': InsufficientFunds,
|
350
|
+
'Order not found': OrderNotFound,
|
351
|
+
'symbol: invalid': BadSymbol,
|
352
|
+
'Invalid order': InvalidOrder,
|
353
|
+
},
|
354
|
+
},
|
355
|
+
'commonCurrencies': {
|
356
|
+
'EUTFO': 'EURT',
|
357
|
+
'USTF0': 'USDT',
|
358
|
+
},
|
359
|
+
});
|
360
|
+
}
|
361
|
+
|
362
|
+
isFiat (code) {
|
363
|
+
return (code in this.options['fiat']);
|
364
|
+
}
|
365
|
+
|
366
|
+
getCurrencyId (code) {
|
367
|
+
return 'f' + code;
|
368
|
+
}
|
369
|
+
|
370
|
+
getCurrencyName (code) {
|
371
|
+
// temporary fix for transpiler recognition, even though this is in parent class
|
372
|
+
if (code in this.options['currencyNames']) {
|
373
|
+
return this.options['currencyNames'][code];
|
374
|
+
}
|
375
|
+
throw new NotSupported (this.id + ' ' + code + ' not supported for withdrawal');
|
376
|
+
}
|
377
|
+
|
378
|
+
async fetchStatus (params = {}) {
|
379
|
+
//
|
380
|
+
// [1] // operative
|
381
|
+
// [0] // maintenance
|
382
|
+
//
|
383
|
+
const response = await this.publicGetPlatformStatus (params);
|
384
|
+
const statusRaw = this.safeString (response, 0);
|
385
|
+
return {
|
386
|
+
'status': this.safeString ({ '0': 'maintenance', '1': 'ok' }, statusRaw, statusRaw),
|
387
|
+
'updated': this.milliseconds (),
|
388
|
+
'eta': undefined,
|
389
|
+
'url': undefined,
|
390
|
+
'info': response,
|
391
|
+
};
|
392
|
+
}
|
393
|
+
|
394
|
+
async fetchMarkets (params = {}) {
|
395
|
+
// todo drop v1 in favor of v2 configs ( temp-reference for v2update: https://pastebin.com/raw/S8CmqSHQ )
|
396
|
+
// pub:list:pair:exchange,pub:list:pair:margin,pub:list:pair:futures,pub:info:pair
|
397
|
+
const v2response = await this.publicGetConfPubListPairFutures (params);
|
398
|
+
const v1response = await this.v1GetSymbolsDetails (params);
|
399
|
+
const swapMarketIds = this.safeValue (v2response, 0, []);
|
400
|
+
const result = [];
|
401
|
+
for (let i = 0; i < v1response.length; i++) {
|
402
|
+
const market = v1response[i];
|
403
|
+
const id = this.safeStringUpper (market, 'pair');
|
404
|
+
let spot = true;
|
405
|
+
if (this.inArray (id, swapMarketIds)) {
|
406
|
+
spot = false;
|
407
|
+
}
|
408
|
+
const swap = !spot;
|
409
|
+
let baseId = undefined;
|
410
|
+
let quoteId = undefined;
|
411
|
+
if (id.indexOf (':') >= 0) {
|
412
|
+
const parts = id.split (':');
|
413
|
+
baseId = parts[0];
|
414
|
+
quoteId = parts[1];
|
415
|
+
} else {
|
416
|
+
baseId = id.slice (0, 3);
|
417
|
+
quoteId = id.slice (3, 6);
|
418
|
+
}
|
419
|
+
let base = this.safeCurrencyCode (baseId);
|
420
|
+
let quote = this.safeCurrencyCode (quoteId);
|
421
|
+
const splitBase = base.split ('F0');
|
422
|
+
const splitQuote = quote.split ('F0');
|
423
|
+
base = this.safeString (splitBase, 0);
|
424
|
+
quote = this.safeString (splitQuote, 0);
|
425
|
+
let symbol = base + '/' + quote;
|
426
|
+
baseId = this.getCurrencyId (baseId);
|
427
|
+
quoteId = this.getCurrencyId (quoteId);
|
428
|
+
let settleId = undefined;
|
429
|
+
let settle = undefined;
|
430
|
+
if (swap) {
|
431
|
+
settleId = quoteId;
|
432
|
+
settle = this.safeCurrencyCode (settleId);
|
433
|
+
symbol = symbol + ':' + settle;
|
434
|
+
}
|
435
|
+
const minOrderSizeString = this.safeString (market, 'minimum_order_size');
|
436
|
+
const maxOrderSizeString = this.safeString (market, 'maximum_order_size');
|
437
|
+
result.push ({
|
438
|
+
'id': 't' + id,
|
439
|
+
'symbol': symbol,
|
440
|
+
'base': base,
|
441
|
+
'quote': quote,
|
442
|
+
'settle': settle,
|
443
|
+
'baseId': baseId,
|
444
|
+
'quoteId': quoteId,
|
445
|
+
'settleId': settleId,
|
446
|
+
'type': spot ? 'spot' : 'swap',
|
447
|
+
'spot': spot,
|
448
|
+
'margin': this.safeValue (market, 'margin', false),
|
449
|
+
'swap': swap,
|
450
|
+
'future': false,
|
451
|
+
'option': false,
|
452
|
+
'active': true,
|
453
|
+
'contract': swap,
|
454
|
+
'linear': swap ? true : undefined,
|
455
|
+
'inverse': swap ? false : undefined,
|
456
|
+
'contractSize': swap ? this.parseNumber ('1') : undefined,
|
457
|
+
'expiry': undefined,
|
458
|
+
'expiryDatetime': undefined,
|
459
|
+
'strike': undefined,
|
460
|
+
'optionType': undefined,
|
461
|
+
'precision': {
|
462
|
+
'amount': parseInt ('8'), // https://github.com/ccxt/ccxt/issues/7310
|
463
|
+
'price': this.safeInteger (market, 'price_precision'),
|
464
|
+
},
|
465
|
+
'limits': {
|
466
|
+
'leverage': {
|
467
|
+
'min': undefined,
|
468
|
+
'max': undefined,
|
469
|
+
},
|
470
|
+
'amount': {
|
471
|
+
'min': this.parseNumber (minOrderSizeString),
|
472
|
+
'max': this.parseNumber (maxOrderSizeString),
|
473
|
+
},
|
474
|
+
'price': {
|
475
|
+
'min': this.parseNumber ('1e-8'),
|
476
|
+
'max': undefined,
|
477
|
+
},
|
478
|
+
'cost': {
|
479
|
+
'min': undefined,
|
480
|
+
'max': undefined,
|
481
|
+
},
|
482
|
+
},
|
483
|
+
'info': market,
|
484
|
+
});
|
485
|
+
}
|
486
|
+
return result;
|
487
|
+
}
|
488
|
+
|
489
|
+
async fetchCurrencies (params = {}) {
|
490
|
+
const labels = [
|
491
|
+
'pub:list:currency',
|
492
|
+
'pub:map:currency:sym', // maps symbols to their API symbols, BAB > BCH
|
493
|
+
'pub:map:currency:label', // verbose friendly names, BNT > Bancor
|
494
|
+
'pub:map:currency:unit', // maps symbols to unit of measure where applicable
|
495
|
+
'pub:map:currency:undl', // maps derivatives symbols to their underlying currency
|
496
|
+
'pub:map:currency:pool', // maps symbols to underlying network/protocol they operate on
|
497
|
+
'pub:map:currency:explorer', // maps symbols to their recognised block explorer URLs
|
498
|
+
'pub:map:currency:tx:fee', // maps currencies to their withdrawal fees https://github.com/ccxt/ccxt/issues/7745
|
499
|
+
];
|
500
|
+
const config = labels.join (',');
|
501
|
+
const request = {
|
502
|
+
'config': config,
|
503
|
+
};
|
504
|
+
const response = await this.publicGetConfConfig (this.extend (request, params));
|
505
|
+
//
|
506
|
+
// [
|
507
|
+
//
|
508
|
+
// a list of symbols
|
509
|
+
// ["AAA","ABS","ADA"],
|
510
|
+
//
|
511
|
+
// // sym
|
512
|
+
// // maps symbols to their API symbols, BAB > BCH
|
513
|
+
// [
|
514
|
+
// [ 'BAB', 'BCH' ],
|
515
|
+
// [ 'CNHT', 'CNHt' ],
|
516
|
+
// [ 'DSH', 'DASH' ],
|
517
|
+
// [ 'IOT', 'IOTA' ],
|
518
|
+
// [ 'LES', 'LEO-EOS' ],
|
519
|
+
// [ 'LET', 'LEO-ERC20' ],
|
520
|
+
// [ 'STJ', 'STORJ' ],
|
521
|
+
// [ 'TSD', 'TUSD' ],
|
522
|
+
// [ 'UDC', 'USDC' ],
|
523
|
+
// [ 'USK', 'USDK' ],
|
524
|
+
// [ 'UST', 'USDt' ],
|
525
|
+
// [ 'USTF0', 'USDt0' ],
|
526
|
+
// [ 'XCH', 'XCHF' ],
|
527
|
+
// [ 'YYW', 'YOYOW' ],
|
528
|
+
// // ...
|
529
|
+
// ],
|
530
|
+
// // label
|
531
|
+
// // verbose friendly names, BNT > Bancor
|
532
|
+
// [
|
533
|
+
// [ 'BAB', 'Bitcoin Cash' ],
|
534
|
+
// [ 'BCH', 'Bitcoin Cash' ],
|
535
|
+
// [ 'LEO', 'Unus Sed LEO' ],
|
536
|
+
// [ 'LES', 'Unus Sed LEO (EOS)' ],
|
537
|
+
// [ 'LET', 'Unus Sed LEO (ERC20)' ],
|
538
|
+
// // ...
|
539
|
+
// ],
|
540
|
+
// // unit
|
541
|
+
// // maps symbols to unit of measure where applicable
|
542
|
+
// [
|
543
|
+
// [ 'IOT', 'Mi|MegaIOTA' ],
|
544
|
+
// ],
|
545
|
+
// // undl
|
546
|
+
// // maps derivatives symbols to their underlying currency
|
547
|
+
// [
|
548
|
+
// [ 'USTF0', 'UST' ],
|
549
|
+
// [ 'BTCF0', 'BTC' ],
|
550
|
+
// [ 'ETHF0', 'ETH' ],
|
551
|
+
// ],
|
552
|
+
// // pool
|
553
|
+
// // maps symbols to underlying network/protocol they operate on
|
554
|
+
// [
|
555
|
+
// [ 'SAN', 'ETH' ], [ 'OMG', 'ETH' ], [ 'AVT', 'ETH' ], [ 'EDO', 'ETH' ],
|
556
|
+
// [ 'ESS', 'ETH' ], [ 'ATD', 'EOS' ], [ 'ADD', 'EOS' ], [ 'MTO', 'EOS' ],
|
557
|
+
// [ 'PNK', 'ETH' ], [ 'BAB', 'BCH' ], [ 'WLO', 'XLM' ], [ 'VLD', 'ETH' ],
|
558
|
+
// [ 'BTT', 'TRX' ], [ 'IMP', 'ETH' ], [ 'SCR', 'ETH' ], [ 'GNO', 'ETH' ],
|
559
|
+
// // ...
|
560
|
+
// ],
|
561
|
+
// // explorer
|
562
|
+
// // maps symbols to their recognised block explorer URLs
|
563
|
+
// [
|
564
|
+
// [
|
565
|
+
// 'AIO',
|
566
|
+
// [
|
567
|
+
// "https://mainnet.aion.network",
|
568
|
+
// "https://mainnet.aion.network/#/account/VAL",
|
569
|
+
// "https://mainnet.aion.network/#/transaction/VAL"
|
570
|
+
// ]
|
571
|
+
// ],
|
572
|
+
// // ...
|
573
|
+
// ],
|
574
|
+
// // fee
|
575
|
+
// // maps currencies to their withdrawal fees
|
576
|
+
// [
|
577
|
+
// ["AAA",[0,0]],
|
578
|
+
// ["ABS",[0,131.3]],
|
579
|
+
// ["ADA",[0,0.3]],
|
580
|
+
// ],
|
581
|
+
// ]
|
582
|
+
//
|
583
|
+
const indexed = {
|
584
|
+
'sym': this.indexBy (this.safeValue (response, 1, []), 0),
|
585
|
+
'label': this.indexBy (this.safeValue (response, 2, []), 0),
|
586
|
+
'unit': this.indexBy (this.safeValue (response, 3, []), 0),
|
587
|
+
'undl': this.indexBy (this.safeValue (response, 4, []), 0),
|
588
|
+
'pool': this.indexBy (this.safeValue (response, 5, []), 0),
|
589
|
+
'explorer': this.indexBy (this.safeValue (response, 6, []), 0),
|
590
|
+
'fees': this.indexBy (this.safeValue (response, 7, []), 0),
|
591
|
+
};
|
592
|
+
const ids = this.safeValue (response, 0, []);
|
593
|
+
const result = {};
|
594
|
+
for (let i = 0; i < ids.length; i++) {
|
595
|
+
const id = ids[i];
|
596
|
+
const code = this.safeCurrencyCode (id);
|
597
|
+
const label = this.safeValue (indexed['label'], id, []);
|
598
|
+
const name = this.safeString (label, 1);
|
599
|
+
const pool = this.safeValue (indexed['pool'], id, []);
|
600
|
+
const type = this.safeString (pool, 1);
|
601
|
+
const feeValues = this.safeValue (indexed['fees'], id, []);
|
602
|
+
const fees = this.safeValue (feeValues, 1, []);
|
603
|
+
const fee = this.safeNumber (fees, 1);
|
604
|
+
const undl = this.safeValue (indexed['undl'], id, []);
|
605
|
+
const precision = 8; // default precision, todo: fix "magic constants"
|
606
|
+
const fid = 'f' + id;
|
607
|
+
result[code] = {
|
608
|
+
'id': fid,
|
609
|
+
'uppercaseId': id,
|
610
|
+
'code': code,
|
611
|
+
'info': [ id, label, pool, feeValues, undl ],
|
612
|
+
'type': type,
|
613
|
+
'name': name,
|
614
|
+
'active': true,
|
615
|
+
'deposit': undefined,
|
616
|
+
'withdraw': undefined,
|
617
|
+
'fee': fee,
|
618
|
+
'precision': precision,
|
619
|
+
'limits': {
|
620
|
+
'amount': {
|
621
|
+
'min': 1 / Math.pow (10, precision),
|
622
|
+
'max': undefined,
|
623
|
+
},
|
624
|
+
'withdraw': {
|
625
|
+
'min': fee,
|
626
|
+
'max': undefined,
|
627
|
+
},
|
628
|
+
},
|
629
|
+
};
|
630
|
+
}
|
631
|
+
return result;
|
632
|
+
}
|
633
|
+
|
634
|
+
async fetchBalance (params = {}) {
|
635
|
+
// this api call does not return the 'used' amount - use the v1 version instead (which also returns zero balances)
|
636
|
+
// there is a difference between this and the v1 api, namely trading wallet is called margin in v2
|
637
|
+
await this.loadMarkets ();
|
638
|
+
const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {});
|
639
|
+
const requestedType = this.safeString (params, 'type', 'exchange');
|
640
|
+
const accountType = this.safeString (accountsByType, requestedType, requestedType);
|
641
|
+
if (accountType === undefined) {
|
642
|
+
const keys = Object.keys (accountsByType);
|
643
|
+
throw new ExchangeError (this.id + ' fetchBalance() type parameter must be one of ' + keys.join (', '));
|
644
|
+
}
|
645
|
+
const isDerivative = requestedType === 'derivatives';
|
646
|
+
const query = this.omit (params, 'type');
|
647
|
+
const response = await this.privatePostAuthRWallets (query);
|
648
|
+
const result = { 'info': response };
|
649
|
+
for (let i = 0; i < response.length; i++) {
|
650
|
+
const balance = response[i];
|
651
|
+
const type = this.safeString (balance, 0);
|
652
|
+
const currencyId = this.safeStringLower (balance, 1, '');
|
653
|
+
const start = currencyId.length - 2;
|
654
|
+
const isDerivativeCode = currencyId.slice (start) === 'f0';
|
655
|
+
// this will only filter the derivative codes if the requestedType is 'derivatives'
|
656
|
+
const derivativeCondition = (!isDerivative || isDerivativeCode);
|
657
|
+
if ((accountType === type) && derivativeCondition) {
|
658
|
+
const code = this.safeCurrencyCode (currencyId);
|
659
|
+
const account = this.account ();
|
660
|
+
account['total'] = this.safeString (balance, 2);
|
661
|
+
account['free'] = this.safeString (balance, 4);
|
662
|
+
result[code] = account;
|
663
|
+
}
|
664
|
+
}
|
665
|
+
return this.safeBalance (result);
|
666
|
+
}
|
667
|
+
|
668
|
+
async transfer (code, amount, fromAccount, toAccount, params = {}) {
|
669
|
+
// transferring between derivatives wallet and regular wallet is not documented in their API
|
670
|
+
// however we support it in CCXT (from just looking at web inspector)
|
671
|
+
await this.loadMarkets ();
|
672
|
+
const accountsByType = this.safeValue (this.options, 'v2AccountsByType', {});
|
673
|
+
const fromId = this.safeString (accountsByType, fromAccount);
|
674
|
+
if (fromId === undefined) {
|
675
|
+
const keys = Object.keys (accountsByType);
|
676
|
+
throw new ArgumentsRequired (this.id + ' transfer() fromAccount must be one of ' + keys.join (', '));
|
677
|
+
}
|
678
|
+
const toId = this.safeString (accountsByType, toAccount);
|
679
|
+
if (toId === undefined) {
|
680
|
+
const keys = Object.keys (accountsByType);
|
681
|
+
throw new ArgumentsRequired (this.id + ' transfer() toAccount must be one of ' + keys.join (', '));
|
682
|
+
}
|
683
|
+
const currency = this.currency (code);
|
684
|
+
const fromCurrencyId = this.convertDerivativesId (currency, fromAccount);
|
685
|
+
const toCurrencyId = this.convertDerivativesId (currency, toAccount);
|
686
|
+
const requestedAmount = this.currencyToPrecision (code, amount);
|
687
|
+
// this request is slightly different from v1 fromAccount -> from
|
688
|
+
const request = {
|
689
|
+
'amount': requestedAmount,
|
690
|
+
'currency': fromCurrencyId,
|
691
|
+
'currency_to': toCurrencyId,
|
692
|
+
'from': fromId,
|
693
|
+
'to': toId,
|
694
|
+
};
|
695
|
+
const response = await this.privatePostAuthWTransfer (this.extend (request, params));
|
696
|
+
// [1616451183763,"acc_tf",null,null,[1616451183763,"exchange","margin",null,"UST","UST",null,1],null,"SUCCESS","1.0 Tether USDt transfered from Exchange to Margin"]
|
697
|
+
const timestamp = this.safeInteger (response, 0);
|
698
|
+
// ["error",10001,"Momentary balance check. Please wait few seconds and try the transfer again."]
|
699
|
+
const error = this.safeString (response, 0);
|
700
|
+
if (error === 'error') {
|
701
|
+
const message = this.safeString (response, 2, '');
|
702
|
+
// same message as in v1
|
703
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message);
|
704
|
+
throw new ExchangeError (this.id + ' ' + message);
|
705
|
+
}
|
706
|
+
const info = this.safeValue (response, 4);
|
707
|
+
const fromResponse = this.safeString (info, 1);
|
708
|
+
const toResponse = this.safeString (info, 2);
|
709
|
+
const toCode = this.safeCurrencyCode (this.safeString (info, 5));
|
710
|
+
const success = this.safeString (response, 6);
|
711
|
+
const status = (success === 'SUCCESS') ? 'ok' : undefined;
|
712
|
+
return {
|
713
|
+
'info': response,
|
714
|
+
'timestamp': timestamp,
|
715
|
+
'datetime': this.iso8601 (timestamp),
|
716
|
+
'status': status,
|
717
|
+
'amount': requestedAmount,
|
718
|
+
'code': toCode,
|
719
|
+
'fromAccount': fromResponse,
|
720
|
+
'toAccount': toResponse,
|
721
|
+
};
|
722
|
+
}
|
723
|
+
|
724
|
+
convertDerivativesId (currency, type) {
|
725
|
+
// there is a difference between this and the v1 api, namely trading wallet is called margin in v2
|
726
|
+
// {
|
727
|
+
// id: 'fUSTF0',
|
728
|
+
// code: 'USTF0',
|
729
|
+
// info: [ 'USTF0', [], [], [], [ 'USTF0', 'UST' ] ],
|
730
|
+
const info = this.safeValue (currency, 'info');
|
731
|
+
const transferId = this.safeString (info, 0);
|
732
|
+
const underlying = this.safeValue (info, 4, []);
|
733
|
+
let currencyId = undefined;
|
734
|
+
if (type === 'derivatives') {
|
735
|
+
currencyId = this.safeString (underlying, 0, transferId);
|
736
|
+
const start = currencyId.length - 2;
|
737
|
+
const isDerivativeCode = currencyId.slice (start) === 'F0';
|
738
|
+
if (!isDerivativeCode) {
|
739
|
+
currencyId = currencyId + 'F0';
|
740
|
+
}
|
741
|
+
} else if (type !== 'margin') {
|
742
|
+
currencyId = this.safeString (underlying, 1, transferId);
|
743
|
+
} else {
|
744
|
+
currencyId = transferId;
|
745
|
+
}
|
746
|
+
return currencyId;
|
747
|
+
}
|
748
|
+
|
749
|
+
async fetchOrder (id, symbol = undefined, params = {}) {
|
750
|
+
throw new NotSupported (this.id + ' fetchOrder() is not supported yet');
|
751
|
+
}
|
752
|
+
|
753
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
754
|
+
await this.loadMarkets ();
|
755
|
+
const precision = this.safeValue (this.options, 'precision', 'R0');
|
756
|
+
const request = {
|
757
|
+
'symbol': this.marketId (symbol),
|
758
|
+
'precision': precision,
|
759
|
+
};
|
760
|
+
if (limit !== undefined) {
|
761
|
+
request['len'] = limit; // 25 or 100
|
762
|
+
}
|
763
|
+
const fullRequest = this.extend (request, params);
|
764
|
+
const orderbook = await this.publicGetBookSymbolPrecision (fullRequest);
|
765
|
+
const timestamp = this.milliseconds ();
|
766
|
+
const result = {
|
767
|
+
'symbol': symbol,
|
768
|
+
'bids': [],
|
769
|
+
'asks': [],
|
770
|
+
'timestamp': timestamp,
|
771
|
+
'datetime': this.iso8601 (timestamp),
|
772
|
+
'nonce': undefined,
|
773
|
+
};
|
774
|
+
const priceIndex = (fullRequest['precision'] === 'R0') ? 1 : 0;
|
775
|
+
for (let i = 0; i < orderbook.length; i++) {
|
776
|
+
const order = orderbook[i];
|
777
|
+
const price = this.safeNumber (order, priceIndex);
|
778
|
+
const signedAmount = this.safeNumber (order, 2);
|
779
|
+
const amount = Math.abs (signedAmount);
|
780
|
+
const side = (signedAmount > 0) ? 'bids' : 'asks';
|
781
|
+
result[side].push ([ price, amount ]);
|
782
|
+
}
|
783
|
+
result['bids'] = this.sortBy (result['bids'], 0, true);
|
784
|
+
result['asks'] = this.sortBy (result['asks'], 0);
|
785
|
+
return result;
|
786
|
+
}
|
787
|
+
|
788
|
+
parseTicker (ticker, market = undefined) {
|
789
|
+
//
|
790
|
+
// on trading pairs (ex. tBTCUSD)
|
791
|
+
//
|
792
|
+
// [
|
793
|
+
// SYMBOL,
|
794
|
+
// BID,
|
795
|
+
// BID_SIZE,
|
796
|
+
// ASK,
|
797
|
+
// ASK_SIZE,
|
798
|
+
// DAILY_CHANGE,
|
799
|
+
// DAILY_CHANGE_RELATIVE,
|
800
|
+
// LAST_PRICE,
|
801
|
+
// VOLUME,
|
802
|
+
// HIGH,
|
803
|
+
// LOW
|
804
|
+
// ]
|
805
|
+
//
|
806
|
+
// on funding currencies (ex. fUSD)
|
807
|
+
//
|
808
|
+
// [
|
809
|
+
// SYMBOL,
|
810
|
+
// FRR,
|
811
|
+
// BID,
|
812
|
+
// BID_PERIOD,
|
813
|
+
// BID_SIZE,
|
814
|
+
// ASK,
|
815
|
+
// ASK_PERIOD,
|
816
|
+
// ASK_SIZE,
|
817
|
+
// DAILY_CHANGE,
|
818
|
+
// DAILY_CHANGE_RELATIVE,
|
819
|
+
// LAST_PRICE,
|
820
|
+
// VOLUME,
|
821
|
+
// HIGH,
|
822
|
+
// LOW,
|
823
|
+
// _PLACEHOLDER,
|
824
|
+
// _PLACEHOLDER,
|
825
|
+
// FRR_AMOUNT_AVAILABLE
|
826
|
+
// ]
|
827
|
+
//
|
828
|
+
const timestamp = this.milliseconds ();
|
829
|
+
const symbol = this.safeSymbol (undefined, market);
|
830
|
+
const length = ticker.length;
|
831
|
+
const last = this.safeString (ticker, length - 4);
|
832
|
+
const percentage = this.safeString (ticker, length - 5);
|
833
|
+
return this.safeTicker ({
|
834
|
+
'symbol': symbol,
|
835
|
+
'timestamp': timestamp,
|
836
|
+
'datetime': this.iso8601 (timestamp),
|
837
|
+
'high': this.safeString (ticker, length - 2),
|
838
|
+
'low': this.safeString (ticker, length - 1),
|
839
|
+
'bid': this.safeString (ticker, length - 10),
|
840
|
+
'bidVolume': undefined,
|
841
|
+
'ask': this.safeString (ticker, length - 8),
|
842
|
+
'askVolume': undefined,
|
843
|
+
'vwap': undefined,
|
844
|
+
'open': undefined,
|
845
|
+
'close': last,
|
846
|
+
'last': last,
|
847
|
+
'previousClose': undefined,
|
848
|
+
'change': this.safeString (ticker, length - 6),
|
849
|
+
'percentage': Precise.stringMul (percentage, '100'),
|
850
|
+
'average': undefined,
|
851
|
+
'baseVolume': this.safeString (ticker, length - 3),
|
852
|
+
'quoteVolume': undefined,
|
853
|
+
'info': ticker,
|
854
|
+
}, market, false);
|
855
|
+
}
|
856
|
+
|
857
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
858
|
+
await this.loadMarkets ();
|
859
|
+
const request = {};
|
860
|
+
if (symbols !== undefined) {
|
861
|
+
const ids = this.marketIds (symbols);
|
862
|
+
request['symbols'] = ids.join (',');
|
863
|
+
} else {
|
864
|
+
request['symbols'] = 'ALL';
|
865
|
+
}
|
866
|
+
const tickers = await this.publicGetTickers (this.extend (request, params));
|
867
|
+
//
|
868
|
+
// [
|
869
|
+
// // on trading pairs (ex. tBTCUSD)
|
870
|
+
// [
|
871
|
+
// SYMBOL,
|
872
|
+
// BID,
|
873
|
+
// BID_SIZE,
|
874
|
+
// ASK,
|
875
|
+
// ASK_SIZE,
|
876
|
+
// DAILY_CHANGE,
|
877
|
+
// DAILY_CHANGE_RELATIVE,
|
878
|
+
// LAST_PRICE,
|
879
|
+
// VOLUME,
|
880
|
+
// HIGH,
|
881
|
+
// LOW
|
882
|
+
// ],
|
883
|
+
// // on funding currencies (ex. fUSD)
|
884
|
+
// [
|
885
|
+
// SYMBOL,
|
886
|
+
// FRR,
|
887
|
+
// BID,
|
888
|
+
// BID_PERIOD,
|
889
|
+
// BID_SIZE,
|
890
|
+
// ASK,
|
891
|
+
// ASK_PERIOD,
|
892
|
+
// ASK_SIZE,
|
893
|
+
// DAILY_CHANGE,
|
894
|
+
// DAILY_CHANGE_RELATIVE,
|
895
|
+
// LAST_PRICE,
|
896
|
+
// VOLUME,
|
897
|
+
// HIGH,
|
898
|
+
// LOW,
|
899
|
+
// _PLACEHOLDER,
|
900
|
+
// _PLACEHOLDER,
|
901
|
+
// FRR_AMOUNT_AVAILABLE
|
902
|
+
// ],
|
903
|
+
// ...
|
904
|
+
// ]
|
905
|
+
//
|
906
|
+
const result = {};
|
907
|
+
for (let i = 0; i < tickers.length; i++) {
|
908
|
+
const ticker = tickers[i];
|
909
|
+
const id = ticker[0];
|
910
|
+
if (id in this.markets_by_id) {
|
911
|
+
const market = this.markets_by_id[id];
|
912
|
+
const symbol = market['symbol'];
|
913
|
+
result[symbol] = this.parseTicker (ticker, market);
|
914
|
+
}
|
915
|
+
}
|
916
|
+
return this.filterByArray (result, 'symbol', symbols);
|
917
|
+
}
|
918
|
+
|
919
|
+
async fetchTicker (symbol, params = {}) {
|
920
|
+
await this.loadMarkets ();
|
921
|
+
const market = this.market (symbol);
|
922
|
+
const request = {
|
923
|
+
'symbol': market['id'],
|
924
|
+
};
|
925
|
+
const ticker = await this.publicGetTickerSymbol (this.extend (request, params));
|
926
|
+
return this.parseTicker (ticker, market);
|
927
|
+
}
|
928
|
+
|
929
|
+
parseSymbol (marketId) {
|
930
|
+
if (marketId === undefined) {
|
931
|
+
return marketId;
|
932
|
+
}
|
933
|
+
marketId = marketId.replace ('t', '');
|
934
|
+
let baseId = undefined;
|
935
|
+
let quoteId = undefined;
|
936
|
+
if (marketId.indexOf (':') >= 0) {
|
937
|
+
const parts = marketId.split (':');
|
938
|
+
baseId = parts[0];
|
939
|
+
quoteId = parts[1];
|
940
|
+
} else {
|
941
|
+
baseId = marketId.slice (0, 3);
|
942
|
+
quoteId = marketId.slice (3, 6);
|
943
|
+
}
|
944
|
+
const base = this.safeCurrencyCode (baseId);
|
945
|
+
const quote = this.safeCurrencyCode (quoteId);
|
946
|
+
return base + '/' + quote;
|
947
|
+
}
|
948
|
+
|
949
|
+
parseTrade (trade, market = undefined) {
|
950
|
+
//
|
951
|
+
// fetchTrades (public)
|
952
|
+
//
|
953
|
+
// [
|
954
|
+
// ID,
|
955
|
+
// MTS, // timestamp
|
956
|
+
// AMOUNT,
|
957
|
+
// PRICE
|
958
|
+
// ]
|
959
|
+
//
|
960
|
+
// fetchMyTrades (private)
|
961
|
+
//
|
962
|
+
// [
|
963
|
+
// ID,
|
964
|
+
// PAIR,
|
965
|
+
// MTS_CREATE,
|
966
|
+
// ORDER_ID,
|
967
|
+
// EXEC_AMOUNT,
|
968
|
+
// EXEC_PRICE,
|
969
|
+
// ORDER_TYPE,
|
970
|
+
// ORDER_PRICE,
|
971
|
+
// MAKER,
|
972
|
+
// FEE,
|
973
|
+
// FEE_CURRENCY,
|
974
|
+
// ...
|
975
|
+
// ]
|
976
|
+
//
|
977
|
+
const tradeLength = trade.length;
|
978
|
+
const isPrivate = (tradeLength > 5);
|
979
|
+
const id = this.safeString (trade, 0);
|
980
|
+
const amountIndex = isPrivate ? 4 : 2;
|
981
|
+
let side = undefined;
|
982
|
+
let amountString = this.safeString (trade, amountIndex);
|
983
|
+
const priceIndex = isPrivate ? 5 : 3;
|
984
|
+
const priceString = this.safeString (trade, priceIndex);
|
985
|
+
if (amountString[0] === '-') {
|
986
|
+
side = 'sell';
|
987
|
+
amountString = Precise.stringAbs (amountString);
|
988
|
+
} else {
|
989
|
+
side = 'buy';
|
990
|
+
}
|
991
|
+
let orderId = undefined;
|
992
|
+
let takerOrMaker = undefined;
|
993
|
+
let type = undefined;
|
994
|
+
let fee = undefined;
|
995
|
+
let symbol = undefined;
|
996
|
+
const timestampIndex = isPrivate ? 2 : 1;
|
997
|
+
const timestamp = this.safeInteger (trade, timestampIndex);
|
998
|
+
if (isPrivate) {
|
999
|
+
const marketId = trade[1];
|
1000
|
+
if (marketId in this.markets_by_id) {
|
1001
|
+
market = this.markets_by_id[marketId];
|
1002
|
+
symbol = market['symbol'];
|
1003
|
+
} else {
|
1004
|
+
symbol = this.parseSymbol (marketId);
|
1005
|
+
}
|
1006
|
+
orderId = this.safeString (trade, 3);
|
1007
|
+
const maker = this.safeInteger (trade, 8);
|
1008
|
+
takerOrMaker = (maker === 1) ? 'maker' : 'taker';
|
1009
|
+
let feeCostString = this.safeString (trade, 9);
|
1010
|
+
feeCostString = Precise.stringNeg (feeCostString);
|
1011
|
+
const feeCurrencyId = this.safeString (trade, 10);
|
1012
|
+
const feeCurrency = this.safeCurrencyCode (feeCurrencyId);
|
1013
|
+
fee = {
|
1014
|
+
'cost': feeCostString,
|
1015
|
+
'currency': feeCurrency,
|
1016
|
+
};
|
1017
|
+
const orderType = trade[6];
|
1018
|
+
type = this.safeString (this.options['exchangeTypes'], orderType);
|
1019
|
+
}
|
1020
|
+
if (symbol === undefined) {
|
1021
|
+
if (market !== undefined) {
|
1022
|
+
symbol = market['symbol'];
|
1023
|
+
}
|
1024
|
+
}
|
1025
|
+
return this.safeTrade ({
|
1026
|
+
'id': id,
|
1027
|
+
'timestamp': timestamp,
|
1028
|
+
'datetime': this.iso8601 (timestamp),
|
1029
|
+
'symbol': symbol,
|
1030
|
+
'order': orderId,
|
1031
|
+
'side': side,
|
1032
|
+
'type': type,
|
1033
|
+
'takerOrMaker': takerOrMaker,
|
1034
|
+
'price': priceString,
|
1035
|
+
'amount': amountString,
|
1036
|
+
'cost': undefined,
|
1037
|
+
'fee': fee,
|
1038
|
+
'info': trade,
|
1039
|
+
}, market);
|
1040
|
+
}
|
1041
|
+
|
1042
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
1043
|
+
await this.loadMarkets ();
|
1044
|
+
const market = this.market (symbol);
|
1045
|
+
let sort = '-1';
|
1046
|
+
const request = {
|
1047
|
+
'symbol': market['id'],
|
1048
|
+
};
|
1049
|
+
if (since !== undefined) {
|
1050
|
+
request['start'] = since;
|
1051
|
+
sort = '1';
|
1052
|
+
}
|
1053
|
+
if (limit !== undefined) {
|
1054
|
+
request['limit'] = limit; // default 120, max 5000
|
1055
|
+
}
|
1056
|
+
request['sort'] = sort;
|
1057
|
+
const response = await this.publicGetTradesSymbolHist (this.extend (request, params));
|
1058
|
+
//
|
1059
|
+
// [
|
1060
|
+
// [
|
1061
|
+
// ID,
|
1062
|
+
// MTS, // timestamp
|
1063
|
+
// AMOUNT,
|
1064
|
+
// PRICE
|
1065
|
+
// ]
|
1066
|
+
// ]
|
1067
|
+
//
|
1068
|
+
const trades = this.sortBy (response, 1);
|
1069
|
+
return this.parseTrades (trades, market, undefined, limit);
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = 100, params = {}) {
|
1073
|
+
await this.loadMarkets ();
|
1074
|
+
const market = this.market (symbol);
|
1075
|
+
if (limit === undefined) {
|
1076
|
+
limit = 100; // default 100, max 5000
|
1077
|
+
}
|
1078
|
+
if (since === undefined) {
|
1079
|
+
const duration = this.parseTimeframe (timeframe);
|
1080
|
+
since = this.milliseconds () - duration * limit * 1000;
|
1081
|
+
}
|
1082
|
+
const request = {
|
1083
|
+
'symbol': market['id'],
|
1084
|
+
'timeframe': this.timeframes[timeframe],
|
1085
|
+
'sort': 1,
|
1086
|
+
'start': since,
|
1087
|
+
'limit': limit,
|
1088
|
+
};
|
1089
|
+
const response = await this.publicGetCandlesTradeTimeframeSymbolHist (this.extend (request, params));
|
1090
|
+
//
|
1091
|
+
// [
|
1092
|
+
// [1591503840000,0.025069,0.025068,0.025069,0.025068,1.97828998],
|
1093
|
+
// [1591504500000,0.025065,0.025065,0.025065,0.025065,1.0164],
|
1094
|
+
// [1591504620000,0.025062,0.025062,0.025062,0.025062,0.5],
|
1095
|
+
// ]
|
1096
|
+
//
|
1097
|
+
return this.parseOHLCVs (response, market, timeframe, since, limit);
|
1098
|
+
}
|
1099
|
+
|
1100
|
+
parseOrderStatus (status) {
|
1101
|
+
if (status === undefined) {
|
1102
|
+
return status;
|
1103
|
+
}
|
1104
|
+
const parts = status.split (' ');
|
1105
|
+
const state = this.safeString (parts, 0);
|
1106
|
+
const statuses = {
|
1107
|
+
'ACTIVE': 'open',
|
1108
|
+
'PARTIALLY': 'open',
|
1109
|
+
'EXECUTED': 'closed',
|
1110
|
+
'CANCELED': 'canceled',
|
1111
|
+
'INSUFFICIENT': 'canceled',
|
1112
|
+
'POSTONLY': 'canceled',
|
1113
|
+
'RSN_DUST': 'rejected',
|
1114
|
+
'RSN_PAUSE': 'rejected',
|
1115
|
+
};
|
1116
|
+
return this.safeString (statuses, state, status);
|
1117
|
+
}
|
1118
|
+
|
1119
|
+
parseOrder (order, market = undefined) {
|
1120
|
+
const id = this.safeString (order, 0);
|
1121
|
+
let symbol = undefined;
|
1122
|
+
const marketId = this.safeString (order, 3);
|
1123
|
+
if (marketId in this.markets_by_id) {
|
1124
|
+
market = this.markets_by_id[marketId];
|
1125
|
+
} else {
|
1126
|
+
symbol = this.parseSymbol (marketId);
|
1127
|
+
}
|
1128
|
+
if ((symbol === undefined) && (market !== undefined)) {
|
1129
|
+
symbol = market['symbol'];
|
1130
|
+
}
|
1131
|
+
// https://github.com/ccxt/ccxt/issues/6686
|
1132
|
+
// const timestamp = this.safeTimestamp (order, 5);
|
1133
|
+
const timestamp = this.safeInteger (order, 5);
|
1134
|
+
const remaining = Precise.stringAbs (this.safeString (order, 6));
|
1135
|
+
const signedAmount = this.safeString (order, 7);
|
1136
|
+
const amount = Precise.stringAbs (signedAmount);
|
1137
|
+
const side = Precise.stringLt (signedAmount, '0') ? 'sell' : 'buy';
|
1138
|
+
const orderType = this.safeString (order, 8);
|
1139
|
+
const type = this.safeString (this.safeValue (this.options, 'exchangeTypes'), orderType);
|
1140
|
+
let status = undefined;
|
1141
|
+
const statusString = this.safeString (order, 13);
|
1142
|
+
if (statusString !== undefined) {
|
1143
|
+
const parts = statusString.split (' @ ');
|
1144
|
+
status = this.parseOrderStatus (this.safeString (parts, 0));
|
1145
|
+
}
|
1146
|
+
const price = this.safeString (order, 16);
|
1147
|
+
const average = this.safeString (order, 17);
|
1148
|
+
const clientOrderId = this.safeString (order, 2);
|
1149
|
+
return this.safeOrder ({
|
1150
|
+
'info': order,
|
1151
|
+
'id': id,
|
1152
|
+
'clientOrderId': clientOrderId,
|
1153
|
+
'timestamp': timestamp,
|
1154
|
+
'datetime': this.iso8601 (timestamp),
|
1155
|
+
'lastTradeTimestamp': undefined,
|
1156
|
+
'symbol': symbol,
|
1157
|
+
'type': type,
|
1158
|
+
'timeInForce': undefined,
|
1159
|
+
'postOnly': undefined,
|
1160
|
+
'side': side,
|
1161
|
+
'price': price,
|
1162
|
+
'stopPrice': undefined,
|
1163
|
+
'amount': amount,
|
1164
|
+
'cost': undefined,
|
1165
|
+
'average': average,
|
1166
|
+
'filled': undefined,
|
1167
|
+
'remaining': remaining,
|
1168
|
+
'status': status,
|
1169
|
+
'fee': undefined,
|
1170
|
+
'trades': undefined,
|
1171
|
+
}, market);
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
1175
|
+
await this.loadMarkets ();
|
1176
|
+
const market = this.market (symbol);
|
1177
|
+
const orderTypes = this.safeValue (this.options, 'orderTypes', {});
|
1178
|
+
const orderType = this.safeStringUpper (orderTypes, type, type);
|
1179
|
+
const postOnly = this.safeValue (params, 'postOnly', false);
|
1180
|
+
params = this.omit (params, [ 'postOnly' ]);
|
1181
|
+
amount = (side === 'sell') ? -amount : amount;
|
1182
|
+
const request = {
|
1183
|
+
// 'gid': 0123456789, // int32, optional group id for the order
|
1184
|
+
// 'cid': 0123456789, // int32 client order id
|
1185
|
+
'type': orderType,
|
1186
|
+
'symbol': market['id'],
|
1187
|
+
// 'price': this.numberToString (price),
|
1188
|
+
'amount': this.numberToString (amount),
|
1189
|
+
// 'flags': 0, // int32, https://docs.bitfinex.com/v2/docs/flag-values
|
1190
|
+
// 'lev': 10, // the value should be between 1 and 100 inclusive, optional, 10 by default
|
1191
|
+
// 'price_trailing': this.numberToString (priceTrailing),
|
1192
|
+
// 'price_aux_limit': this.numberToString (stopPrice),
|
1193
|
+
// 'price_oco_stop': this.numberToString (ocoStopPrice),
|
1194
|
+
// 'tif': '2020-01-01 10:45:23', // datetime for automatic order cancellation
|
1195
|
+
// 'meta': {
|
1196
|
+
// 'aff_code': 'AFF_CODE_HERE'
|
1197
|
+
// },
|
1198
|
+
};
|
1199
|
+
if (postOnly) {
|
1200
|
+
request['flags'] = 4096;
|
1201
|
+
}
|
1202
|
+
if ((orderType === 'LIMIT') || (orderType === 'EXCHANGE LIMIT')) {
|
1203
|
+
request['price'] = this.numberToString (price);
|
1204
|
+
} else if ((orderType === 'STOP') || (orderType === 'EXCHANGE STOP')) {
|
1205
|
+
const stopPrice = this.safeNumber (params, 'stopPrice', price);
|
1206
|
+
request['price'] = this.numberToString (stopPrice);
|
1207
|
+
} else if ((orderType === 'STOP LIMIT') || (orderType === 'EXCHANGE STOP LIMIT')) {
|
1208
|
+
const priceAuxLimit = this.safeNumber (params, 'price_aux_limit');
|
1209
|
+
let stopPrice = this.safeNumber (params, 'stopPrice');
|
1210
|
+
if (priceAuxLimit === undefined) {
|
1211
|
+
if (stopPrice === undefined) {
|
1212
|
+
throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter or a price_aux_limit parameter for a ' + orderType + ' order');
|
1213
|
+
} else {
|
1214
|
+
request['price_aux_limit'] = this.numberToString (price);
|
1215
|
+
}
|
1216
|
+
} else {
|
1217
|
+
request['price_aux_limit'] = this.numberToString (priceAuxLimit);
|
1218
|
+
if (stopPrice === undefined) {
|
1219
|
+
stopPrice = price;
|
1220
|
+
}
|
1221
|
+
}
|
1222
|
+
request['price'] = this.numberToString (stopPrice);
|
1223
|
+
} else if ((orderType === 'TRAILING STOP') || (orderType === 'EXCHANGE TRAILING STOP')) {
|
1224
|
+
const priceTrailing = this.safeNumber (params, 'price_trailing');
|
1225
|
+
request['price_trailing'] = this.numberToString (priceTrailing);
|
1226
|
+
const stopPrice = this.safeNumber (params, 'stopPrice', price);
|
1227
|
+
request['price'] = this.numberToString (stopPrice);
|
1228
|
+
} else if ((orderType === 'FOK') || (orderType === 'EXCHANGE FOK') || (orderType === 'IOC') || (orderType === 'EXCHANGE IOC')) {
|
1229
|
+
request['price'] = this.numberToString (price);
|
1230
|
+
}
|
1231
|
+
params = this.omit (params, [ 'stopPrice', 'price_aux_limit', 'price_trailing' ]);
|
1232
|
+
const clientOrderId = this.safeValue2 (params, 'cid', 'clientOrderId');
|
1233
|
+
if (clientOrderId !== undefined) {
|
1234
|
+
request['cid'] = clientOrderId;
|
1235
|
+
params = this.omit (params, [ 'cid', 'clientOrderId' ]);
|
1236
|
+
}
|
1237
|
+
const response = await this.privatePostAuthWOrderSubmit (this.extend (request, params));
|
1238
|
+
//
|
1239
|
+
// [
|
1240
|
+
// 1578784364.748, // Millisecond Time Stamp of the update
|
1241
|
+
// "on-req", // Purpose of notification ('on-req', 'oc-req', 'uca', 'fon-req', 'foc-req')
|
1242
|
+
// null, // Unique ID of the message
|
1243
|
+
// null, // Ignore
|
1244
|
+
// [
|
1245
|
+
// [
|
1246
|
+
// 37271830598, // Order ID
|
1247
|
+
// null, // Group ID
|
1248
|
+
// 1578784364748, // Client Order ID
|
1249
|
+
// "tBTCUST", // Pair
|
1250
|
+
// 1578784364748, // Millisecond timestamp of creation
|
1251
|
+
// 1578784364748, // Millisecond timestamp of update
|
1252
|
+
// -0.005, // Positive means buy, negative means sell
|
1253
|
+
// -0.005, // Original amount
|
1254
|
+
// "EXCHANGE LIMIT", // Order type (LIMIT, MARKET, STOP, TRAILING STOP, EXCHANGE MARKET, EXCHANGE LIMIT, EXCHANGE STOP, EXCHANGE TRAILING STOP, FOK, EXCHANGE FOK, IOC, EXCHANGE IOC)
|
1255
|
+
// null, // Previous order type
|
1256
|
+
// null, // Millisecond timestamp of Time-In-Force: automatic order cancellation
|
1257
|
+
// null, // Ignore
|
1258
|
+
// 0, // Flags (see https://docs.bitfinex.com/docs/flag-values)
|
1259
|
+
// "ACTIVE", // Order Status
|
1260
|
+
// null, // Ignore
|
1261
|
+
// null, // Ignore
|
1262
|
+
// 20000, // Price
|
1263
|
+
// 0, // Average price
|
1264
|
+
// 0, // The trailing price
|
1265
|
+
// 0, // Auxiliary Limit price (for STOP LIMIT)
|
1266
|
+
// null, // Ignore
|
1267
|
+
// null, // Ignore
|
1268
|
+
// null, // Ignore
|
1269
|
+
// 0, // 1 - hidden order
|
1270
|
+
// null, // If another order caused this order to be placed (OCO) this will be that other order's ID
|
1271
|
+
// null, // Ignore
|
1272
|
+
// null, // Ignore
|
1273
|
+
// null, // Ignore
|
1274
|
+
// "API>BFX", // Origin of action: BFX, ETHFX, API>BFX, API>ETHFX
|
1275
|
+
// null, // Ignore
|
1276
|
+
// null, // Ignore
|
1277
|
+
// null // Meta
|
1278
|
+
// ]
|
1279
|
+
// ],
|
1280
|
+
// null, // Error code
|
1281
|
+
// "SUCCESS", // Status (SUCCESS, ERROR, FAILURE, ...)
|
1282
|
+
// "Submitting 1 orders." // Text of the notification
|
1283
|
+
// ]
|
1284
|
+
//
|
1285
|
+
const status = this.safeString (response, 6);
|
1286
|
+
if (status !== 'SUCCESS') {
|
1287
|
+
const errorCode = response[5];
|
1288
|
+
const errorText = response[7];
|
1289
|
+
throw new ExchangeError (this.id + ' ' + response[6] + ': ' + errorText + ' (#' + errorCode + ')');
|
1290
|
+
}
|
1291
|
+
const orders = this.safeValue (response, 4, []);
|
1292
|
+
const order = this.safeValue (orders, 0);
|
1293
|
+
return this.parseOrder (order, market);
|
1294
|
+
}
|
1295
|
+
|
1296
|
+
async cancelAllOrders (symbol = undefined, params = {}) {
|
1297
|
+
const request = {
|
1298
|
+
'all': 1,
|
1299
|
+
};
|
1300
|
+
const response = await this.privatePostAuthWOrderCancelMulti (this.extend (request, params));
|
1301
|
+
const orders = this.safeValue (response, 4, []);
|
1302
|
+
return this.parseOrders (orders);
|
1303
|
+
}
|
1304
|
+
|
1305
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
1306
|
+
const cid = this.safeValue2 (params, 'cid', 'clientOrderId'); // client order id
|
1307
|
+
let request = undefined;
|
1308
|
+
if (cid !== undefined) {
|
1309
|
+
const cidDate = this.safeValue (params, 'cidDate'); // client order id date
|
1310
|
+
if (cidDate === undefined) {
|
1311
|
+
throw new InvalidOrder (this.id + " canceling an order by clientOrderId ('cid') requires both 'cid' and 'cid_date' ('YYYY-MM-DD')");
|
1312
|
+
}
|
1313
|
+
request = {
|
1314
|
+
'cid': cid,
|
1315
|
+
'cid_date': cidDate,
|
1316
|
+
};
|
1317
|
+
params = this.omit (params, [ 'cid', 'clientOrderId' ]);
|
1318
|
+
} else {
|
1319
|
+
request = {
|
1320
|
+
'id': parseInt (id),
|
1321
|
+
};
|
1322
|
+
}
|
1323
|
+
const response = await this.privatePostAuthWOrderCancel (this.extend (request, params));
|
1324
|
+
const order = this.safeValue (response, 4);
|
1325
|
+
return this.parseOrder (order);
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
async fetchOpenOrder (id, symbol = undefined, params = {}) {
|
1329
|
+
const request = {
|
1330
|
+
'id': [ parseInt (id) ],
|
1331
|
+
};
|
1332
|
+
const orders = await this.fetchOpenOrders (symbol, undefined, undefined, this.extend (request, params));
|
1333
|
+
const order = this.safeValue (orders, 0);
|
1334
|
+
if (order === undefined) {
|
1335
|
+
throw new OrderNotFound (this.id + ' order ' + id + ' not found');
|
1336
|
+
}
|
1337
|
+
return order;
|
1338
|
+
}
|
1339
|
+
|
1340
|
+
async fetchClosedOrder (id, symbol = undefined, params = {}) {
|
1341
|
+
const request = {
|
1342
|
+
'id': [ parseInt (id) ],
|
1343
|
+
};
|
1344
|
+
const orders = await this.fetchClosedOrders (symbol, undefined, undefined, this.extend (request, params));
|
1345
|
+
const order = this.safeValue (orders, 0);
|
1346
|
+
if (order === undefined) {
|
1347
|
+
throw new OrderNotFound (this.id + ' order ' + id + ' not found');
|
1348
|
+
}
|
1349
|
+
return order;
|
1350
|
+
}
|
1351
|
+
|
1352
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1353
|
+
await this.loadMarkets ();
|
1354
|
+
const request = {};
|
1355
|
+
let market = undefined;
|
1356
|
+
let response = undefined;
|
1357
|
+
if (symbol === undefined) {
|
1358
|
+
response = await this.privatePostAuthROrders (this.extend (request, params));
|
1359
|
+
} else {
|
1360
|
+
market = this.market (symbol);
|
1361
|
+
request['symbol'] = market['id'];
|
1362
|
+
response = await this.privatePostAuthROrdersSymbol (this.extend (request, params));
|
1363
|
+
}
|
1364
|
+
return this.parseOrders (response, market, since, limit);
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1368
|
+
// returns the most recent closed or canceled orders up to circa two weeks ago
|
1369
|
+
await this.loadMarkets ();
|
1370
|
+
const request = {};
|
1371
|
+
let market = undefined;
|
1372
|
+
let response = undefined;
|
1373
|
+
if (symbol === undefined) {
|
1374
|
+
response = await this.privatePostAuthROrdersHist (this.extend (request, params));
|
1375
|
+
} else {
|
1376
|
+
market = this.market (symbol);
|
1377
|
+
request['symbol'] = market['id'];
|
1378
|
+
response = await this.privatePostAuthROrdersSymbolHist (this.extend (request, params));
|
1379
|
+
}
|
1380
|
+
if (since !== undefined) {
|
1381
|
+
request['start'] = since;
|
1382
|
+
}
|
1383
|
+
if (limit !== undefined) {
|
1384
|
+
request['limit'] = limit; // default 25, max 2500
|
1385
|
+
}
|
1386
|
+
return this.parseOrders (response, market, since, limit);
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1390
|
+
if (symbol === undefined) {
|
1391
|
+
throw new ArgumentsRequired (this.id + ' fetchOrderTrades() requires a symbol argument');
|
1392
|
+
}
|
1393
|
+
await this.loadMarkets ();
|
1394
|
+
const market = this.market (symbol);
|
1395
|
+
const orderId = parseInt (id);
|
1396
|
+
const request = {
|
1397
|
+
'id': orderId,
|
1398
|
+
'symbol': market['id'],
|
1399
|
+
};
|
1400
|
+
// valid for trades upto 10 days old
|
1401
|
+
const response = await this.privatePostAuthROrderSymbolIdTrades (this.extend (request, params));
|
1402
|
+
return this.parseTrades (response, market, since, limit);
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1406
|
+
await this.loadMarkets ();
|
1407
|
+
let market = undefined;
|
1408
|
+
const request = {
|
1409
|
+
'end': this.milliseconds (),
|
1410
|
+
};
|
1411
|
+
if (since !== undefined) {
|
1412
|
+
request['start'] = since;
|
1413
|
+
}
|
1414
|
+
if (limit !== undefined) {
|
1415
|
+
request['limit'] = limit; // default 25, max 1000
|
1416
|
+
}
|
1417
|
+
let method = 'privatePostAuthRTradesHist';
|
1418
|
+
if (symbol !== undefined) {
|
1419
|
+
market = this.market (symbol);
|
1420
|
+
request['symbol'] = market['id'];
|
1421
|
+
method = 'privatePostAuthRTradesSymbolHist';
|
1422
|
+
}
|
1423
|
+
const response = await this[method] (this.extend (request, params));
|
1424
|
+
return this.parseTrades (response, market, since, limit);
|
1425
|
+
}
|
1426
|
+
|
1427
|
+
async createDepositAddress (code, params = {}) {
|
1428
|
+
await this.loadMarkets ();
|
1429
|
+
const request = {
|
1430
|
+
'op_renew': 1,
|
1431
|
+
};
|
1432
|
+
const response = await this.fetchDepositAddress (code, this.extend (request, params));
|
1433
|
+
return response;
|
1434
|
+
}
|
1435
|
+
|
1436
|
+
async fetchDepositAddress (code, params = {}) {
|
1437
|
+
await this.loadMarkets ();
|
1438
|
+
// todo rewrite for https://api-pub.bitfinex.com//v2/conf/pub:map:tx:method
|
1439
|
+
const name = this.getCurrencyName (code);
|
1440
|
+
const request = {
|
1441
|
+
'method': name,
|
1442
|
+
'wallet': 'exchange', // 'exchange', 'margin', 'funding' and also old labels 'exchange', 'trading', 'deposit', respectively
|
1443
|
+
'op_renew': 0, // a value of 1 will generate a new address
|
1444
|
+
};
|
1445
|
+
const response = await this.privatePostAuthWDepositAddress (this.extend (request, params));
|
1446
|
+
//
|
1447
|
+
// [
|
1448
|
+
// 1582269616687, // MTS Millisecond Time Stamp of the update
|
1449
|
+
// 'acc_dep', // TYPE Purpose of notification 'acc_dep' for account deposit
|
1450
|
+
// null, // MESSAGE_ID unique ID of the message
|
1451
|
+
// null, // not documented
|
1452
|
+
// [
|
1453
|
+
// null, // PLACEHOLDER
|
1454
|
+
// 'BITCOIN', // METHOD Method of deposit
|
1455
|
+
// 'BTC', // CURRENCY_CODE Currency code of new address
|
1456
|
+
// null, // PLACEHOLDER
|
1457
|
+
// '1BC9PZqpUmjyEB54uggn8TFKj49zSDYzqG', // ADDRESS
|
1458
|
+
// null, // POOL_ADDRESS
|
1459
|
+
// ],
|
1460
|
+
// null, // CODE null or integer work in progress
|
1461
|
+
// 'SUCCESS', // STATUS Status of the notification, SUCCESS, ERROR, FAILURE
|
1462
|
+
// 'success', // TEXT Text of the notification
|
1463
|
+
// ]
|
1464
|
+
//
|
1465
|
+
const result = this.safeValue (response, 4, []);
|
1466
|
+
const poolAddress = this.safeString (result, 5);
|
1467
|
+
const address = (poolAddress === undefined) ? this.safeString (result, 4) : poolAddress;
|
1468
|
+
const tag = (poolAddress === undefined) ? undefined : this.safeString (result, 4);
|
1469
|
+
this.checkAddress (address);
|
1470
|
+
return {
|
1471
|
+
'currency': code,
|
1472
|
+
'address': address,
|
1473
|
+
'tag': tag,
|
1474
|
+
'network': undefined,
|
1475
|
+
'info': response,
|
1476
|
+
};
|
1477
|
+
}
|
1478
|
+
|
1479
|
+
parseTransactionStatus (status) {
|
1480
|
+
const statuses = {
|
1481
|
+
'SUCCESS': 'ok',
|
1482
|
+
'ERROR': 'failed',
|
1483
|
+
'FAILURE': 'failed',
|
1484
|
+
'CANCELED': 'canceled',
|
1485
|
+
'COMPLETED': 'ok',
|
1486
|
+
};
|
1487
|
+
return this.safeString (statuses, status, status);
|
1488
|
+
}
|
1489
|
+
|
1490
|
+
parseTransaction (transaction, currency = undefined) {
|
1491
|
+
//
|
1492
|
+
// withdraw
|
1493
|
+
//
|
1494
|
+
// [
|
1495
|
+
// 1582271520931, // MTS Millisecond Time Stamp of the update
|
1496
|
+
// "acc_wd-req", // TYPE Purpose of notification 'acc_wd-req' account withdrawal request
|
1497
|
+
// null, // MESSAGE_ID unique ID of the message
|
1498
|
+
// null, // not documented
|
1499
|
+
// [
|
1500
|
+
// 0, // WITHDRAWAL_ID Unique Withdrawal ID
|
1501
|
+
// null, // PLACEHOLDER
|
1502
|
+
// "bitcoin", // METHOD Method of withdrawal
|
1503
|
+
// null, // PAYMENT_ID Payment ID if relevant
|
1504
|
+
// "exchange", // WALLET Sending wallet
|
1505
|
+
// 1, // AMOUNT Amount of Withdrawal less fee
|
1506
|
+
// null, // PLACEHOLDER
|
1507
|
+
// null, // PLACEHOLDER
|
1508
|
+
// 0.0004, // WITHDRAWAL_FEE Fee on withdrawal
|
1509
|
+
// ],
|
1510
|
+
// null, // CODE null or integer Work in progress
|
1511
|
+
// "SUCCESS", // STATUS Status of the notification, it may vary over time SUCCESS, ERROR, FAILURE
|
1512
|
+
// "Invalid bitcoin address (abcdef)", // TEXT Text of the notification
|
1513
|
+
// ]
|
1514
|
+
//
|
1515
|
+
// fetchTransactions
|
1516
|
+
//
|
1517
|
+
// [
|
1518
|
+
// 13293039, // ID
|
1519
|
+
// 'ETH', // CURRENCY
|
1520
|
+
// 'ETHEREUM', // CURRENCY_NAME
|
1521
|
+
// null,
|
1522
|
+
// null,
|
1523
|
+
// 1574175052000, // MTS_STARTED
|
1524
|
+
// 1574181326000, // MTS_UPDATED
|
1525
|
+
// null,
|
1526
|
+
// null,
|
1527
|
+
// 'CANCELED', // STATUS
|
1528
|
+
// null,
|
1529
|
+
// null,
|
1530
|
+
// -0.24, // AMOUNT, negative for withdrawals
|
1531
|
+
// -0.00135, // FEES
|
1532
|
+
// null,
|
1533
|
+
// null,
|
1534
|
+
// '0x38110e0Fc932CB2BE...........', // DESTINATION_ADDRESS
|
1535
|
+
// null,
|
1536
|
+
// null,
|
1537
|
+
// null,
|
1538
|
+
// '0x523ec8945500.....................................', // TRANSACTION_ID
|
1539
|
+
// "Purchase of 100 pizzas", // WITHDRAW_TRANSACTION_NOTE, might also be: null
|
1540
|
+
// ]
|
1541
|
+
//
|
1542
|
+
const transactionLength = transaction.length;
|
1543
|
+
let timestamp = undefined;
|
1544
|
+
let updated = undefined;
|
1545
|
+
let code = undefined;
|
1546
|
+
let amount = undefined;
|
1547
|
+
let id = undefined;
|
1548
|
+
let status = undefined;
|
1549
|
+
let tag = undefined;
|
1550
|
+
let type = undefined;
|
1551
|
+
let feeCost = undefined;
|
1552
|
+
let txid = undefined;
|
1553
|
+
let addressTo = undefined;
|
1554
|
+
if (transactionLength === 8) {
|
1555
|
+
const data = this.safeValue (transaction, 4, []);
|
1556
|
+
timestamp = this.safeInteger (transaction, 0);
|
1557
|
+
if (currency !== undefined) {
|
1558
|
+
code = currency['code'];
|
1559
|
+
}
|
1560
|
+
feeCost = this.safeNumber (data, 8);
|
1561
|
+
if (feeCost !== undefined) {
|
1562
|
+
feeCost = -feeCost;
|
1563
|
+
}
|
1564
|
+
amount = this.safeNumber (data, 5);
|
1565
|
+
id = this.safeValue (data, 0);
|
1566
|
+
status = 'ok';
|
1567
|
+
if (id === 0) {
|
1568
|
+
id = undefined;
|
1569
|
+
status = 'failed';
|
1570
|
+
}
|
1571
|
+
tag = this.safeString (data, 3);
|
1572
|
+
type = 'withdrawal';
|
1573
|
+
} else if (transactionLength === 22) {
|
1574
|
+
id = this.safeString (transaction, 0);
|
1575
|
+
const currencyId = this.safeString (transaction, 1);
|
1576
|
+
code = this.safeCurrencyCode (currencyId, currency);
|
1577
|
+
timestamp = this.safeInteger (transaction, 5);
|
1578
|
+
updated = this.safeInteger (transaction, 6);
|
1579
|
+
status = this.parseTransactionStatus (this.safeString (transaction, 9));
|
1580
|
+
amount = this.safeNumber (transaction, 12);
|
1581
|
+
if (amount !== undefined) {
|
1582
|
+
if (amount < 0) {
|
1583
|
+
type = 'withdrawal';
|
1584
|
+
} else {
|
1585
|
+
type = 'deposit';
|
1586
|
+
}
|
1587
|
+
}
|
1588
|
+
feeCost = this.safeNumber (transaction, 13);
|
1589
|
+
if (feeCost !== undefined) {
|
1590
|
+
feeCost = -feeCost;
|
1591
|
+
}
|
1592
|
+
addressTo = this.safeString (transaction, 16);
|
1593
|
+
txid = this.safeString (transaction, 20);
|
1594
|
+
}
|
1595
|
+
return {
|
1596
|
+
'info': transaction,
|
1597
|
+
'id': id,
|
1598
|
+
'txid': txid,
|
1599
|
+
'timestamp': timestamp,
|
1600
|
+
'datetime': this.iso8601 (timestamp),
|
1601
|
+
'network': undefined,
|
1602
|
+
'addressFrom': undefined,
|
1603
|
+
'address': addressTo, // this is actually the tag for XRP transfers (the address is missing)
|
1604
|
+
'addressTo': addressTo,
|
1605
|
+
'tagFrom': undefined,
|
1606
|
+
'tag': tag, // refix it properly for the tag from description
|
1607
|
+
'tagTo': tag,
|
1608
|
+
'type': type,
|
1609
|
+
'amount': amount,
|
1610
|
+
'currency': code,
|
1611
|
+
'status': status,
|
1612
|
+
'updated': updated,
|
1613
|
+
'fee': {
|
1614
|
+
'currency': code,
|
1615
|
+
'cost': feeCost,
|
1616
|
+
'rate': undefined,
|
1617
|
+
},
|
1618
|
+
};
|
1619
|
+
}
|
1620
|
+
|
1621
|
+
async fetchTradingFees (params = {}) {
|
1622
|
+
await this.loadMarkets ();
|
1623
|
+
const response = await this.privatePostAuthRSummary (params);
|
1624
|
+
//
|
1625
|
+
// Response Spec:
|
1626
|
+
// [
|
1627
|
+
// PLACEHOLDER,
|
1628
|
+
// PLACEHOLDER,
|
1629
|
+
// PLACEHOLDER,
|
1630
|
+
// PLACEHOLDER,
|
1631
|
+
// [
|
1632
|
+
// [
|
1633
|
+
// MAKER_FEE,
|
1634
|
+
// MAKER_FEE,
|
1635
|
+
// MAKER_FEE,
|
1636
|
+
// PLACEHOLDER,
|
1637
|
+
// PLACEHOLDER,
|
1638
|
+
// DERIV_REBATE
|
1639
|
+
// ],
|
1640
|
+
// [
|
1641
|
+
// TAKER_FEE_TO_CRYPTO,
|
1642
|
+
// TAKER_FEE_TO_STABLE,
|
1643
|
+
// TAKER_FEE_TO_FIAT,
|
1644
|
+
// PLACEHOLDER,
|
1645
|
+
// PLACEHOLDER,
|
1646
|
+
// DERIV_TAKER_FEE
|
1647
|
+
// ]
|
1648
|
+
// ],
|
1649
|
+
// PLACEHOLDER,
|
1650
|
+
// PLACEHOLDER,
|
1651
|
+
// PLACEHOLDER,
|
1652
|
+
// PLACEHOLDER,
|
1653
|
+
// {
|
1654
|
+
// LEO_LEV,
|
1655
|
+
// LEO_AMOUNT_AVG
|
1656
|
+
// }
|
1657
|
+
// ]
|
1658
|
+
//
|
1659
|
+
// Example response:
|
1660
|
+
//
|
1661
|
+
// [
|
1662
|
+
// null,
|
1663
|
+
// null,
|
1664
|
+
// null,
|
1665
|
+
// null,
|
1666
|
+
// [
|
1667
|
+
// [ 0.001, 0.001, 0.001, null, null, 0.0002 ],
|
1668
|
+
// [ 0.002, 0.002, 0.002, null, null, 0.00065 ]
|
1669
|
+
// ],
|
1670
|
+
// [
|
1671
|
+
// [
|
1672
|
+
// {
|
1673
|
+
// curr: 'Total (USD)',
|
1674
|
+
// vol: '0',
|
1675
|
+
// vol_safe: '0',
|
1676
|
+
// vol_maker: '0',
|
1677
|
+
// vol_BFX: '0',
|
1678
|
+
// vol_BFX_safe: '0',
|
1679
|
+
// vol_BFX_maker: '0'
|
1680
|
+
// }
|
1681
|
+
// ],
|
1682
|
+
// {},
|
1683
|
+
// 0
|
1684
|
+
// ],
|
1685
|
+
// [ null, {}, 0 ],
|
1686
|
+
// null,
|
1687
|
+
// null,
|
1688
|
+
// { leo_lev: '0', leo_amount_avg: '0' }
|
1689
|
+
// ]
|
1690
|
+
//
|
1691
|
+
const result = {};
|
1692
|
+
const fiat = this.safeValue (this.options, 'fiat', {});
|
1693
|
+
const feeData = this.safeValue (response, 4, []);
|
1694
|
+
const makerData = this.safeValue (feeData, 0, []);
|
1695
|
+
const takerData = this.safeValue (feeData, 1, []);
|
1696
|
+
const makerFee = this.safeNumber (makerData, 0);
|
1697
|
+
const makerFeeFiat = this.safeNumber (makerData, 2);
|
1698
|
+
const makerFeeDeriv = this.safeNumber (makerData, 5);
|
1699
|
+
const takerFee = this.safeNumber (takerData, 0);
|
1700
|
+
const takerFeeFiat = this.safeNumber (takerData, 2);
|
1701
|
+
const takerFeeDeriv = this.safeNumber (takerData, 5);
|
1702
|
+
for (let i = 0; i < this.symbols.length; i++) {
|
1703
|
+
const symbol = this.symbols[i];
|
1704
|
+
const market = this.market (symbol);
|
1705
|
+
const fee = {
|
1706
|
+
'info': response,
|
1707
|
+
'symbol': symbol,
|
1708
|
+
'percentage': true,
|
1709
|
+
'tierBased': true,
|
1710
|
+
};
|
1711
|
+
if (market['quote'] in fiat) {
|
1712
|
+
fee['maker'] = makerFeeFiat;
|
1713
|
+
fee['taker'] = takerFeeFiat;
|
1714
|
+
} else if (market['contract']) {
|
1715
|
+
fee['maker'] = makerFeeDeriv;
|
1716
|
+
fee['taker'] = takerFeeDeriv;
|
1717
|
+
} else { // TODO check if stable coin
|
1718
|
+
fee['maker'] = makerFee;
|
1719
|
+
fee['taker'] = takerFee;
|
1720
|
+
}
|
1721
|
+
result[symbol] = fee;
|
1722
|
+
}
|
1723
|
+
return result;
|
1724
|
+
}
|
1725
|
+
|
1726
|
+
async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1727
|
+
await this.loadMarkets ();
|
1728
|
+
let currency = undefined;
|
1729
|
+
const request = {};
|
1730
|
+
let method = 'privatePostAuthRMovementsHist';
|
1731
|
+
if (code !== undefined) {
|
1732
|
+
currency = this.currency (code);
|
1733
|
+
request['currency'] = currency['uppercaseId'];
|
1734
|
+
method = 'privatePostAuthRMovementsCurrencyHist';
|
1735
|
+
}
|
1736
|
+
if (since !== undefined) {
|
1737
|
+
request['start'] = since;
|
1738
|
+
}
|
1739
|
+
if (limit !== undefined) {
|
1740
|
+
request['limit'] = limit; // max 1000
|
1741
|
+
}
|
1742
|
+
const response = await this[method] (this.extend (request, params));
|
1743
|
+
//
|
1744
|
+
// [
|
1745
|
+
// [
|
1746
|
+
// 13293039, // ID
|
1747
|
+
// 'ETH', // CURRENCY
|
1748
|
+
// 'ETHEREUM', // CURRENCY_NAME
|
1749
|
+
// null,
|
1750
|
+
// null,
|
1751
|
+
// 1574175052000, // MTS_STARTED
|
1752
|
+
// 1574181326000, // MTS_UPDATED
|
1753
|
+
// null,
|
1754
|
+
// null,
|
1755
|
+
// 'CANCELED', // STATUS
|
1756
|
+
// null,
|
1757
|
+
// null,
|
1758
|
+
// -0.24, // AMOUNT, negative for withdrawals
|
1759
|
+
// -0.00135, // FEES
|
1760
|
+
// null,
|
1761
|
+
// null,
|
1762
|
+
// '0x38110e0Fc932CB2BE...........', // DESTINATION_ADDRESS
|
1763
|
+
// null,
|
1764
|
+
// null,
|
1765
|
+
// null,
|
1766
|
+
// '0x523ec8945500.....................................', // TRANSACTION_ID
|
1767
|
+
// "Purchase of 100 pizzas", // WITHDRAW_TRANSACTION_NOTE, might also be: null
|
1768
|
+
// ]
|
1769
|
+
// ]
|
1770
|
+
//
|
1771
|
+
return this.parseTransactions (response, currency, since, limit);
|
1772
|
+
}
|
1773
|
+
|
1774
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
1775
|
+
this.checkAddress (address);
|
1776
|
+
await this.loadMarkets ();
|
1777
|
+
const currency = this.currency (code);
|
1778
|
+
// todo rewrite for https://api-pub.bitfinex.com//v2/conf/pub:map:tx:method
|
1779
|
+
const name = this.getCurrencyName (code);
|
1780
|
+
const request = {
|
1781
|
+
'method': name,
|
1782
|
+
'wallet': 'exchange', // 'exchange', 'margin', 'funding' and also old labels 'exchange', 'trading', 'deposit', respectively
|
1783
|
+
'amount': this.numberToString (amount),
|
1784
|
+
'address': address,
|
1785
|
+
};
|
1786
|
+
if (tag !== undefined) {
|
1787
|
+
request['payment_id'] = tag;
|
1788
|
+
}
|
1789
|
+
const response = await this.privatePostAuthWWithdraw (this.extend (request, params));
|
1790
|
+
//
|
1791
|
+
// [
|
1792
|
+
// 1582271520931, // MTS Millisecond Time Stamp of the update
|
1793
|
+
// "acc_wd-req", // TYPE Purpose of notification 'acc_wd-req' account withdrawal request
|
1794
|
+
// null, // MESSAGE_ID unique ID of the message
|
1795
|
+
// null, // not documented
|
1796
|
+
// [
|
1797
|
+
// 0, // WITHDRAWAL_ID Unique Withdrawal ID
|
1798
|
+
// null, // PLACEHOLDER
|
1799
|
+
// "bitcoin", // METHOD Method of withdrawal
|
1800
|
+
// null, // PAYMENT_ID Payment ID if relevant
|
1801
|
+
// "exchange", // WALLET Sending wallet
|
1802
|
+
// 1, // AMOUNT Amount of Withdrawal less fee
|
1803
|
+
// null, // PLACEHOLDER
|
1804
|
+
// null, // PLACEHOLDER
|
1805
|
+
// 0.0004, // WITHDRAWAL_FEE Fee on withdrawal
|
1806
|
+
// ],
|
1807
|
+
// null, // CODE null or integer Work in progress
|
1808
|
+
// "SUCCESS", // STATUS Status of the notification, it may vary over time SUCCESS, ERROR, FAILURE
|
1809
|
+
// "Invalid bitcoin address (abcdef)", // TEXT Text of the notification
|
1810
|
+
// ]
|
1811
|
+
//
|
1812
|
+
const text = this.safeString (response, 7);
|
1813
|
+
if (text !== 'success') {
|
1814
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], text, text);
|
1815
|
+
}
|
1816
|
+
const transaction = this.parseTransaction (response, currency);
|
1817
|
+
return this.extend (transaction, {
|
1818
|
+
'address': address,
|
1819
|
+
});
|
1820
|
+
}
|
1821
|
+
|
1822
|
+
async fetchPositions (symbols = undefined, params = {}) {
|
1823
|
+
await this.loadMarkets ();
|
1824
|
+
const response = await this.privatePostAuthRPositions (params);
|
1825
|
+
//
|
1826
|
+
// [
|
1827
|
+
// [
|
1828
|
+
// "tBTCUSD", // SYMBOL
|
1829
|
+
// "ACTIVE", // STATUS
|
1830
|
+
// 0.0195, // AMOUNT
|
1831
|
+
// 8565.0267019, // BASE_PRICE
|
1832
|
+
// 0, // MARGIN_FUNDING
|
1833
|
+
// 0, // MARGIN_FUNDING_TYPE
|
1834
|
+
// -0.33455568705000516, // PL
|
1835
|
+
// -0.0003117550117425625, // PL_PERC
|
1836
|
+
// 7045.876419249083, // PRICE_LIQ
|
1837
|
+
// 3.0673001895895604, // LEVERAGE
|
1838
|
+
// null, // _PLACEHOLDER
|
1839
|
+
// 142355652, // POSITION_ID
|
1840
|
+
// 1574002216000, // MTS_CREATE
|
1841
|
+
// 1574002216000, // MTS_UPDATE
|
1842
|
+
// null, // _PLACEHOLDER
|
1843
|
+
// 0, // TYPE
|
1844
|
+
// null, // _PLACEHOLDER
|
1845
|
+
// 0, // COLLATERAL
|
1846
|
+
// 0, // COLLATERAL_MIN
|
1847
|
+
// // META
|
1848
|
+
// {
|
1849
|
+
// "reason":"TRADE",
|
1850
|
+
// "order_id":34271018124,
|
1851
|
+
// "liq_stage":null,
|
1852
|
+
// "trade_price":"8565.0267019",
|
1853
|
+
// "trade_amount":"0.0195",
|
1854
|
+
// "order_id_oppo":34277498022
|
1855
|
+
// }
|
1856
|
+
// ]
|
1857
|
+
// ]
|
1858
|
+
//
|
1859
|
+
// todo unify parsePosition/parsePositions
|
1860
|
+
return response;
|
1861
|
+
}
|
1862
|
+
|
1863
|
+
nonce () {
|
1864
|
+
return this.milliseconds ();
|
1865
|
+
}
|
1866
|
+
|
1867
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
1868
|
+
let request = '/' + this.implodeParams (path, params);
|
1869
|
+
const query = this.omit (params, this.extractParams (path));
|
1870
|
+
if (api === 'v1') {
|
1871
|
+
request = api + request;
|
1872
|
+
} else {
|
1873
|
+
request = this.version + request;
|
1874
|
+
}
|
1875
|
+
let url = this.urls['api'][api] + '/' + request;
|
1876
|
+
if (api === 'public') {
|
1877
|
+
if (Object.keys (query).length) {
|
1878
|
+
url += '?' + this.urlencode (query);
|
1879
|
+
}
|
1880
|
+
}
|
1881
|
+
if (api === 'private') {
|
1882
|
+
this.checkRequiredCredentials ();
|
1883
|
+
const nonce = this.nonce ().toString ();
|
1884
|
+
body = this.json (query);
|
1885
|
+
const auth = '/api/' + request + nonce + body;
|
1886
|
+
const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha384');
|
1887
|
+
headers = {
|
1888
|
+
'bfx-nonce': nonce,
|
1889
|
+
'bfx-apikey': this.apiKey,
|
1890
|
+
'bfx-signature': signature,
|
1891
|
+
'Content-Type': 'application/json',
|
1892
|
+
};
|
1893
|
+
}
|
1894
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
1895
|
+
}
|
1896
|
+
|
1897
|
+
handleErrors (statusCode, statusText, url, method, responseHeaders, responseBody, response, requestHeaders, requestBody) {
|
1898
|
+
if (response !== undefined) {
|
1899
|
+
if (!Array.isArray (response)) {
|
1900
|
+
const message = this.safeString2 (response, 'message', 'error');
|
1901
|
+
const feedback = this.id + ' ' + responseBody;
|
1902
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
|
1903
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
|
1904
|
+
throw new ExchangeError (this.id + ' ' + responseBody);
|
1905
|
+
}
|
1906
|
+
} else if (response === '') {
|
1907
|
+
throw new ExchangeError (this.id + ' returned empty response');
|
1908
|
+
}
|
1909
|
+
if (statusCode === 500) {
|
1910
|
+
// See https://docs.bitfinex.com/docs/abbreviations-glossary#section-errorinfo-codes
|
1911
|
+
const errorCode = this.numberToString (response[1]);
|
1912
|
+
const errorText = response[2];
|
1913
|
+
const feedback = this.id + ' ' + errorText;
|
1914
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
|
1915
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], errorText, feedback);
|
1916
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], errorText, feedback);
|
1917
|
+
throw new ExchangeError (this.id + ' ' + errorText + ' (#' + errorCode + ')');
|
1918
|
+
}
|
1919
|
+
return response;
|
1920
|
+
}
|
1921
|
+
|
1922
|
+
parseLedgerEntryType (type) {
|
1923
|
+
if (type === undefined) {
|
1924
|
+
return undefined;
|
1925
|
+
} else if (type.indexOf ('fee') >= 0 || type.indexOf ('charged') >= 0) {
|
1926
|
+
return 'fee';
|
1927
|
+
} else if (type.indexOf ('exchange') >= 0 || type.indexOf ('position') >= 0) {
|
1928
|
+
return 'trade';
|
1929
|
+
} else if (type.indexOf ('rebate') >= 0) {
|
1930
|
+
return 'rebate';
|
1931
|
+
} else if (type.indexOf ('deposit') >= 0 || type.indexOf ('withdrawal') >= 0) {
|
1932
|
+
return 'transaction';
|
1933
|
+
} else if (type.indexOf ('transfer') >= 0) {
|
1934
|
+
return 'transfer';
|
1935
|
+
} else if (type.indexOf ('payment') >= 0) {
|
1936
|
+
return 'payout';
|
1937
|
+
} else {
|
1938
|
+
return type;
|
1939
|
+
}
|
1940
|
+
}
|
1941
|
+
|
1942
|
+
parseLedgerEntry (item, currency = undefined) {
|
1943
|
+
//
|
1944
|
+
// [
|
1945
|
+
// [
|
1946
|
+
// 2531822314, // ID: Ledger identifier
|
1947
|
+
// "USD", // CURRENCY: The symbol of the currency (ex. "BTC")
|
1948
|
+
// null, // PLACEHOLDER
|
1949
|
+
// 1573521810000, // MTS: Timestamp in milliseconds
|
1950
|
+
// null, // PLACEHOLDER
|
1951
|
+
// 0.01644445, // AMOUNT: Amount of funds moved
|
1952
|
+
// 0, // BALANCE: New balance
|
1953
|
+
// null, // PLACEHOLDER
|
1954
|
+
// "Settlement @ 185.79 on wallet margin" // DESCRIPTION: Description of ledger transaction
|
1955
|
+
// ]
|
1956
|
+
// ]
|
1957
|
+
//
|
1958
|
+
let type = undefined;
|
1959
|
+
const id = this.safeString (item, 0);
|
1960
|
+
const currencyId = this.safeString (item, 1);
|
1961
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
1962
|
+
const timestamp = this.safeInteger (item, 3);
|
1963
|
+
const amount = this.safeNumber (item, 5);
|
1964
|
+
const after = this.safeNumber (item, 6);
|
1965
|
+
const description = this.safeString (item, 8);
|
1966
|
+
if (description !== undefined) {
|
1967
|
+
const parts = description.split (' @ ');
|
1968
|
+
const first = this.safeStringLower (parts, 0);
|
1969
|
+
type = this.parseLedgerEntryType (first);
|
1970
|
+
}
|
1971
|
+
return {
|
1972
|
+
'id': id,
|
1973
|
+
'direction': undefined,
|
1974
|
+
'account': undefined,
|
1975
|
+
'referenceId': id,
|
1976
|
+
'referenceAccount': undefined,
|
1977
|
+
'type': type,
|
1978
|
+
'currency': code,
|
1979
|
+
'amount': amount,
|
1980
|
+
'timestamp': timestamp,
|
1981
|
+
'datetime': this.iso8601 (timestamp),
|
1982
|
+
'before': undefined,
|
1983
|
+
'after': after,
|
1984
|
+
'status': undefined,
|
1985
|
+
'fee': undefined,
|
1986
|
+
'info': item,
|
1987
|
+
};
|
1988
|
+
}
|
1989
|
+
|
1990
|
+
async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1991
|
+
await this.loadMarkets ();
|
1992
|
+
await this.loadMarkets ();
|
1993
|
+
let currency = undefined;
|
1994
|
+
const request = {};
|
1995
|
+
let method = 'privatePostAuthRLedgersHist';
|
1996
|
+
if (code !== undefined) {
|
1997
|
+
currency = this.currency (code);
|
1998
|
+
request['currency'] = currency['uppercaseId'];
|
1999
|
+
method = 'privatePostAuthRLedgersCurrencyHist';
|
2000
|
+
}
|
2001
|
+
if (since !== undefined) {
|
2002
|
+
request['start'] = since;
|
2003
|
+
}
|
2004
|
+
if (limit !== undefined) {
|
2005
|
+
request['limit'] = limit; // max 2500
|
2006
|
+
}
|
2007
|
+
const response = await this[method] (this.extend (request, params));
|
2008
|
+
//
|
2009
|
+
// [
|
2010
|
+
// [
|
2011
|
+
// 2531822314, // ID: Ledger identifier
|
2012
|
+
// "USD", // CURRENCY: The symbol of the currency (ex. "BTC")
|
2013
|
+
// null, // PLACEHOLDER
|
2014
|
+
// 1573521810000, // MTS: Timestamp in milliseconds
|
2015
|
+
// null, // PLACEHOLDER
|
2016
|
+
// 0.01644445, // AMOUNT: Amount of funds moved
|
2017
|
+
// 0, // BALANCE: New balance
|
2018
|
+
// null, // PLACEHOLDER
|
2019
|
+
// "Settlement @ 185.79 on wallet margin" // DESCRIPTION: Description of ledger transaction
|
2020
|
+
// ]
|
2021
|
+
// ]
|
2022
|
+
//
|
2023
|
+
return this.parseLedger (response, currency, since, limit);
|
2024
|
+
}
|
2025
|
+
};
|