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/bitmart.js
ADDED
@@ -0,0 +1,2516 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { AuthenticationError, ExchangeNotAvailable, AccountSuspended, PermissionDenied, RateLimitExceeded, InvalidNonce, InvalidAddress, ArgumentsRequired, ExchangeError, InvalidOrder, InsufficientFunds, BadRequest, OrderNotFound, BadSymbol, NotSupported } = require ('./base/errors');
|
7
|
+
const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number');
|
8
|
+
const Precise = require ('./base/Precise');
|
9
|
+
|
10
|
+
// ---------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module.exports = class bitmart extends Exchange {
|
13
|
+
describe () {
|
14
|
+
return this.deepExtend (super.describe (), {
|
15
|
+
'id': 'bitmart',
|
16
|
+
'name': 'BitMart',
|
17
|
+
'countries': [ 'US', 'CN', 'HK', 'KR' ],
|
18
|
+
'rateLimit': 250, // a bit slower than 50 times per second ~40 times per second
|
19
|
+
'version': 'v1',
|
20
|
+
'certified': true,
|
21
|
+
'pro': true,
|
22
|
+
'has': {
|
23
|
+
'CORS': undefined,
|
24
|
+
'spot': true,
|
25
|
+
'margin': undefined, // has but unimplemented
|
26
|
+
'swap': undefined, // has but unimplemented
|
27
|
+
'future': undefined, // has but unimplemented
|
28
|
+
'option': undefined,
|
29
|
+
'cancelAllOrders': true,
|
30
|
+
'cancelOrder': true,
|
31
|
+
'cancelOrders': true,
|
32
|
+
'createOrder': true,
|
33
|
+
'fetchBalance': true,
|
34
|
+
'fetchCanceledOrders': true,
|
35
|
+
'fetchClosedOrders': true,
|
36
|
+
'fetchCurrencies': true,
|
37
|
+
'fetchDeposit': true,
|
38
|
+
'fetchDepositAddress': true,
|
39
|
+
'fetchDepositAddresses': false,
|
40
|
+
'fetchDepositAddressesByNetwork': false,
|
41
|
+
'fetchDeposits': true,
|
42
|
+
'fetchFundingFee': true,
|
43
|
+
'fetchFundingFees': false,
|
44
|
+
'fetchFundingHistory': undefined,
|
45
|
+
'fetchMarkets': true,
|
46
|
+
'fetchMyTrades': true,
|
47
|
+
'fetchOHLCV': true,
|
48
|
+
'fetchOpenOrders': true,
|
49
|
+
'fetchOrder': true,
|
50
|
+
'fetchOrderBook': true,
|
51
|
+
'fetchOrders': true,
|
52
|
+
'fetchOrderTrades': true,
|
53
|
+
'fetchStatus': true,
|
54
|
+
'fetchTicker': true,
|
55
|
+
'fetchTickers': true,
|
56
|
+
'fetchTime': true,
|
57
|
+
'fetchTrades': true,
|
58
|
+
'fetchTradingFee': false,
|
59
|
+
'fetchTradingFees': false,
|
60
|
+
'fetchTransfer': false,
|
61
|
+
'fetchTransfers': false,
|
62
|
+
'fetchWithdrawAddressesByNetwork': false,
|
63
|
+
'fetchWithdrawal': true,
|
64
|
+
'fetchWithdrawals': true,
|
65
|
+
'reduceMargin': false,
|
66
|
+
'setLeverage': false,
|
67
|
+
'setMarginMode': false,
|
68
|
+
'transfer': false,
|
69
|
+
'withdraw': true,
|
70
|
+
},
|
71
|
+
'hostname': 'bitmart.com', // bitmart.info, bitmart.news for Hong Kong users
|
72
|
+
'urls': {
|
73
|
+
'logo': 'https://user-images.githubusercontent.com/1294454/129991357-8f47464b-d0f4-41d6-8a82-34122f0d1398.jpg',
|
74
|
+
'api': {
|
75
|
+
'rest': 'https://api-cloud.{hostname}', // bitmart.info for Hong Kong users
|
76
|
+
},
|
77
|
+
'www': 'https://www.bitmart.com/',
|
78
|
+
'doc': 'https://developer-pro.bitmart.com/',
|
79
|
+
'referral': {
|
80
|
+
'url': 'http://www.bitmart.com/?r=rQCFLh',
|
81
|
+
'discount': 0.3,
|
82
|
+
},
|
83
|
+
'fees': 'https://www.bitmart.com/fee/en',
|
84
|
+
},
|
85
|
+
'requiredCredentials': {
|
86
|
+
'apiKey': true,
|
87
|
+
'secret': true,
|
88
|
+
'uid': true,
|
89
|
+
},
|
90
|
+
'api': {
|
91
|
+
'public': {
|
92
|
+
'system': {
|
93
|
+
'get': {
|
94
|
+
'time': 5, // https://api-cloud.bitmart.com/system/time
|
95
|
+
'service': 5, // https://api-cloud.bitmart.com/system/service
|
96
|
+
},
|
97
|
+
},
|
98
|
+
'account': {
|
99
|
+
'get': {
|
100
|
+
'currencies': 10, // https://api-cloud.bitmart.com/account/v1/currencies
|
101
|
+
},
|
102
|
+
},
|
103
|
+
'spot': {
|
104
|
+
'get': {
|
105
|
+
'currencies': 1,
|
106
|
+
'symbols': 1,
|
107
|
+
'symbols/details': 1,
|
108
|
+
'ticker': 1, // ?symbol=BTC_USDT
|
109
|
+
'steps': 1, // ?symbol=BMX_ETH
|
110
|
+
'symbols/kline': 1, // ?symbol=BMX_ETH&step=15&from=1525760116&to=1525769116
|
111
|
+
'symbols/book': 1, // ?symbol=BMX_ETH&precision=6
|
112
|
+
'symbols/trades': 1, // ?symbol=BMX_ETH
|
113
|
+
},
|
114
|
+
},
|
115
|
+
'contract': {
|
116
|
+
'get': {
|
117
|
+
'tickers': 0.5,
|
118
|
+
},
|
119
|
+
},
|
120
|
+
},
|
121
|
+
'private': {
|
122
|
+
'account': {
|
123
|
+
'get': {
|
124
|
+
'wallet': 0.5, // ?account_type=1
|
125
|
+
'deposit/address': 1, // ?currency=USDT-TRC20
|
126
|
+
'withdraw/charge': 1, // ?currency=BTC
|
127
|
+
'deposit-withdraw/history': 1, // ?limit=10&offset=1&operationType=withdraw
|
128
|
+
'deposit-withdraw/detail': 1, // ?id=1679952
|
129
|
+
},
|
130
|
+
'post': {
|
131
|
+
'withdraw/apply': 1,
|
132
|
+
},
|
133
|
+
},
|
134
|
+
'spot': {
|
135
|
+
'get': {
|
136
|
+
'wallet': 0.5,
|
137
|
+
'order_detail': 0.1,
|
138
|
+
'orders': 0.5,
|
139
|
+
'trades': 0.5,
|
140
|
+
},
|
141
|
+
'post': {
|
142
|
+
'submit_order': 0.1, // https://api-cloud.bitmart.com/spot/v1/submit_order
|
143
|
+
'cancel_order': 0.1, // https://api-cloud.bitmart.com/spot/v2/cancel_order
|
144
|
+
'cancel_orders': 0.1,
|
145
|
+
},
|
146
|
+
},
|
147
|
+
},
|
148
|
+
},
|
149
|
+
'timeframes': {
|
150
|
+
'1m': 1,
|
151
|
+
'3m': 3,
|
152
|
+
'5m': 5,
|
153
|
+
'15m': 15,
|
154
|
+
'30m': 30,
|
155
|
+
'45m': 45,
|
156
|
+
'1h': 60,
|
157
|
+
'2h': 120,
|
158
|
+
'3h': 180,
|
159
|
+
'4h': 240,
|
160
|
+
'1d': 1440,
|
161
|
+
'1w': 10080,
|
162
|
+
'1M': 43200,
|
163
|
+
},
|
164
|
+
'fees': {
|
165
|
+
'trading': {
|
166
|
+
'tierBased': true,
|
167
|
+
'percentage': true,
|
168
|
+
'taker': this.parseNumber ('0.0025'),
|
169
|
+
'maker': this.parseNumber ('0.0025'),
|
170
|
+
'tiers': {
|
171
|
+
'taker': [
|
172
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.0020') ],
|
173
|
+
[ this.parseNumber ('10'), this.parseNumber ('0.18') ],
|
174
|
+
[ this.parseNumber ('50'), this.parseNumber ('0.0016') ],
|
175
|
+
[ this.parseNumber ('250'), this.parseNumber ('0.0014') ],
|
176
|
+
[ this.parseNumber ('1000'), this.parseNumber ('0.0012') ],
|
177
|
+
[ this.parseNumber ('5000'), this.parseNumber ('0.0010') ],
|
178
|
+
[ this.parseNumber ('25000'), this.parseNumber ('0.0008') ],
|
179
|
+
[ this.parseNumber ('50000'), this.parseNumber ('0.0006') ],
|
180
|
+
],
|
181
|
+
'maker': [
|
182
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.001') ],
|
183
|
+
[ this.parseNumber ('10'), this.parseNumber ('0.0009') ],
|
184
|
+
[ this.parseNumber ('50'), this.parseNumber ('0.0008') ],
|
185
|
+
[ this.parseNumber ('250'), this.parseNumber ('0.0007') ],
|
186
|
+
[ this.parseNumber ('1000'), this.parseNumber ('0.0006') ],
|
187
|
+
[ this.parseNumber ('5000'), this.parseNumber ('0.0005') ],
|
188
|
+
[ this.parseNumber ('25000'), this.parseNumber ('0.0004') ],
|
189
|
+
[ this.parseNumber ('50000'), this.parseNumber ('0.0003') ],
|
190
|
+
],
|
191
|
+
},
|
192
|
+
},
|
193
|
+
},
|
194
|
+
'precisionMode': TICK_SIZE,
|
195
|
+
'exceptions': {
|
196
|
+
'exact': {
|
197
|
+
// general errors
|
198
|
+
'30000': ExchangeError, // 404, Not found
|
199
|
+
'30001': AuthenticationError, // 401, Header X-BM-KEY is empty
|
200
|
+
'30002': AuthenticationError, // 401, Header X-BM-KEY not found
|
201
|
+
'30003': AccountSuspended, // 401, Header X-BM-KEY has frozen
|
202
|
+
'30004': AuthenticationError, // 401, Header X-BM-SIGN is empty
|
203
|
+
'30005': AuthenticationError, // 401, Header X-BM-SIGN is wrong
|
204
|
+
'30006': AuthenticationError, // 401, Header X-BM-TIMESTAMP is empty
|
205
|
+
'30007': AuthenticationError, // 401, Header X-BM-TIMESTAMP range. Within a minute
|
206
|
+
'30008': AuthenticationError, // 401, Header X-BM-TIMESTAMP invalid format
|
207
|
+
'30010': PermissionDenied, // 403, IP is forbidden. We recommend enabling IP whitelist for API trading. After that reauth your account
|
208
|
+
'30011': AuthenticationError, // 403, Header X-BM-KEY over expire time
|
209
|
+
'30012': AuthenticationError, // 403, Header X-BM-KEY is forbidden to request it
|
210
|
+
'30013': RateLimitExceeded, // 429, Request too many requests
|
211
|
+
'30014': ExchangeNotAvailable, // 503, Service unavailable
|
212
|
+
// funding account errors
|
213
|
+
'60000': BadRequest, // 400, Invalid request (maybe the body is empty, or the int parameter passes string data)
|
214
|
+
'60001': BadRequest, // 400, Asset account type does not exist
|
215
|
+
'60002': BadRequest, // 400, currency does not exist
|
216
|
+
'60003': ExchangeError, // 400, Currency has been closed recharge channel, if there is any problem, please consult customer service
|
217
|
+
'60004': ExchangeError, // 400, Currency has been closed withdraw channel, if there is any problem, please consult customer service
|
218
|
+
'60005': ExchangeError, // 400, Minimum amount is %s
|
219
|
+
'60006': ExchangeError, // 400, Maximum withdraw precision is %d
|
220
|
+
'60007': InvalidAddress, // 400, Only withdrawals from added addresses are allowed
|
221
|
+
'60008': InsufficientFunds, // 400, Balance not enough
|
222
|
+
'60009': ExchangeError, // 400, Beyond the limit
|
223
|
+
'60010': ExchangeError, // 400, Withdraw id or deposit id not found
|
224
|
+
'60011': InvalidAddress, // 400, Address is not valid
|
225
|
+
'60012': ExchangeError, // 400, This action is not supported in this currency(If IOTA, HLX recharge and withdraw calls are prohibited)
|
226
|
+
'60020': PermissionDenied, // 403, Your account is not allowed to recharge
|
227
|
+
'60021': PermissionDenied, // 403, Your account is not allowed to withdraw
|
228
|
+
'60022': PermissionDenied, // 403, No withdrawals for 24 hours
|
229
|
+
'60030': BadRequest, // 405, Method Not Allowed
|
230
|
+
'60031': BadRequest, // 415, Unsupported Media Type
|
231
|
+
'60050': ExchangeError, // 500, User account not found
|
232
|
+
'60051': ExchangeError, // 500, Internal Server Error
|
233
|
+
// spot errors
|
234
|
+
'50000': BadRequest, // 400, Bad Request
|
235
|
+
'50001': BadSymbol, // 400, Symbol not found
|
236
|
+
'50002': BadRequest, // 400, From Or To format error
|
237
|
+
'50003': BadRequest, // 400, Step format error
|
238
|
+
'50004': BadRequest, // 400, Kline size over 500
|
239
|
+
'50005': OrderNotFound, // 400, Order Id not found
|
240
|
+
'50006': InvalidOrder, // 400, Minimum size is %s
|
241
|
+
'50007': InvalidOrder, // 400, Maximum size is %s
|
242
|
+
'50008': InvalidOrder, // 400, Minimum price is %s
|
243
|
+
'50009': InvalidOrder, // 400, Minimum count*price is %s
|
244
|
+
'50010': InvalidOrder, // 400, RequestParam size is required
|
245
|
+
'50011': InvalidOrder, // 400, RequestParam price is required
|
246
|
+
'50012': InvalidOrder, // 400, RequestParam notional is required
|
247
|
+
'50013': InvalidOrder, // 400, Maximum limit*offset is %d
|
248
|
+
'50014': BadRequest, // 400, RequestParam limit is required
|
249
|
+
'50015': BadRequest, // 400, Minimum limit is 1
|
250
|
+
'50016': BadRequest, // 400, Maximum limit is %d
|
251
|
+
'50017': BadRequest, // 400, RequestParam offset is required
|
252
|
+
'50018': BadRequest, // 400, Minimum offset is 1
|
253
|
+
'50019': BadRequest, // 400, Maximum price is %s
|
254
|
+
// '50019': ExchangeError, // 400, Invalid status. validate status is [1=Failed, 2=Success, 3=Frozen Failed, 4=Frozen Success, 5=Partially Filled, 6=Fully Fulled, 7=Canceling, 8=Canceled
|
255
|
+
'50020': InsufficientFunds, // 400, Balance not enough
|
256
|
+
'50021': BadRequest, // 400, Invalid %s
|
257
|
+
'50022': ExchangeNotAvailable, // 400, Service unavailable
|
258
|
+
'50023': BadSymbol, // 400, This Symbol can't place order by api
|
259
|
+
'50029': InvalidOrder, // {"message":"param not match : size * price >=1000","code":50029,"trace":"f931f030-b692-401b-a0c5-65edbeadc598","data":{}}
|
260
|
+
'50030': InvalidOrder, // {"message":"Order is already canceled","code":50030,"trace":"8d6f64ee-ad26-45a4-9efd-1080f9fca1fa","data":{}}
|
261
|
+
// below Error codes used interchangeably for both failed postOnly and IOC orders depending on market price and order side
|
262
|
+
'50035': InvalidOrder, // {"message":"The price is low and there is no matching depth","code":50035,"trace":"677f01c7-8b88-4346-b097-b4226c75c90e","data":{}}
|
263
|
+
'50034': InvalidOrder, // {"message":"The price is high and there is no matching depth","code":50034,"trace":"ebfae59a-ba69-4735-86b2-0ed7b9ca14ea","data":{}}
|
264
|
+
'53000': AccountSuspended, // 403, Your account is frozen due to security policies. Please contact customer service
|
265
|
+
'53001': AccountSuspended, // {"message":"Your kyc country is restricted. Please contact customer service.","code":53001,"trace":"8b445940-c123-4de9-86d7-73c5be2e7a24","data":{}}
|
266
|
+
'57001': BadRequest, // 405, Method Not Allowed
|
267
|
+
'58001': BadRequest, // 415, Unsupported Media Type
|
268
|
+
'59001': ExchangeError, // 500, User account not found
|
269
|
+
'59002': ExchangeError, // 500, Internal Server Error
|
270
|
+
// contract errors
|
271
|
+
'40001': ExchangeError, // 400, Cloud account not found
|
272
|
+
'40002': ExchangeError, // 400, out_trade_no not found
|
273
|
+
'40003': ExchangeError, // 400, out_trade_no already existed
|
274
|
+
'40004': ExchangeError, // 400, Cloud account count limit
|
275
|
+
'40005': ExchangeError, // 400, Transfer vol precision error
|
276
|
+
'40006': PermissionDenied, // 400, Invalid ip error
|
277
|
+
'40007': BadRequest, // 400, Parse parameter error
|
278
|
+
'40008': InvalidNonce, // 400, Check nonce error
|
279
|
+
'40009': BadRequest, // 400, Check ver error
|
280
|
+
'40010': BadRequest, // 400, Not found func error
|
281
|
+
'40011': BadRequest, // 400, Invalid request
|
282
|
+
'40012': ExchangeError, // 500, System error
|
283
|
+
'40013': ExchangeError, // 400, Access too often" CLIENT_TIME_INVALID, "Please check your system time.
|
284
|
+
'40014': BadSymbol, // 400, This contract is offline
|
285
|
+
'40015': BadSymbol, // 400, This contract's exchange has been paused
|
286
|
+
'40016': InvalidOrder, // 400, This order would trigger user position liquidate
|
287
|
+
'40017': InvalidOrder, // 400, It is not possible to open and close simultaneously in the same position
|
288
|
+
'40018': InvalidOrder, // 400, Your position is closed
|
289
|
+
'40019': ExchangeError, // 400, Your position is in liquidation delegating
|
290
|
+
'40020': InvalidOrder, // 400, Your position volume is not enough
|
291
|
+
'40021': ExchangeError, // 400, The position is not exsit
|
292
|
+
'40022': ExchangeError, // 400, The position is not isolated
|
293
|
+
'40023': ExchangeError, // 400, The position would liquidate when sub margin
|
294
|
+
'40024': ExchangeError, // 400, The position would be warnning of liquidation when sub margin
|
295
|
+
'40025': ExchangeError, // 400, The position’s margin shouldn’t be lower than the base limit
|
296
|
+
'40026': ExchangeError, // 400, You cross margin position is in liquidation delegating
|
297
|
+
'40027': InsufficientFunds, // 400, You contract account available balance not enough
|
298
|
+
'40028': PermissionDenied, // 400, Your plan order's count is more than system maximum limit.
|
299
|
+
'40029': InvalidOrder, // 400, The order's leverage is too large.
|
300
|
+
'40030': InvalidOrder, // 400, The order's leverage is too small.
|
301
|
+
'40031': InvalidOrder, // 400, The deviation between current price and trigger price is too large.
|
302
|
+
'40032': InvalidOrder, // 400, The plan order's life cycle is too long.
|
303
|
+
'40033': InvalidOrder, // 400, The plan order's life cycle is too short.
|
304
|
+
'40034': BadSymbol, // 400, This contract is not found
|
305
|
+
'53002': PermissionDenied, // 403, Your account has not yet completed the kyc advanced certification, please complete first
|
306
|
+
},
|
307
|
+
'broad': {},
|
308
|
+
},
|
309
|
+
'commonCurrencies': {
|
310
|
+
'$GM': 'GOLDMINER',
|
311
|
+
'$HERO': 'Step Hero',
|
312
|
+
'$PAC': 'PAC',
|
313
|
+
'AUR': 'Aurum',
|
314
|
+
'BP': 'BEYOND',
|
315
|
+
'COT': 'Community Coin',
|
316
|
+
'CPC': 'CPCoin',
|
317
|
+
'DMS': 'DimSum', // conflict with Dragon Mainland Shards
|
318
|
+
'FOX': 'Fox Finance',
|
319
|
+
'GDT': 'Gorilla Diamond',
|
320
|
+
'GLD': 'Goldario',
|
321
|
+
'MIM': 'MIM Swarm',
|
322
|
+
'MVP': 'MVP Coin',
|
323
|
+
'ONE': 'Menlo One',
|
324
|
+
'PLA': 'Plair',
|
325
|
+
'TCT': 'TacoCat Token',
|
326
|
+
'TRU': 'Truebit', // conflict with TrueFi
|
327
|
+
'ULT': 'Ultiledger',
|
328
|
+
},
|
329
|
+
'options': {
|
330
|
+
'networks': {
|
331
|
+
'TRX': 'TRC20',
|
332
|
+
'ETH': 'ERC20',
|
333
|
+
},
|
334
|
+
'defaultNetworks': {
|
335
|
+
'USDT': 'ERC20',
|
336
|
+
},
|
337
|
+
'defaultType': 'spot', // 'spot', 'swap'
|
338
|
+
'fetchBalance': {
|
339
|
+
'type': 'spot', // 'spot', 'swap', 'contract', 'account'
|
340
|
+
},
|
341
|
+
'createMarketBuyOrderRequiresPrice': true,
|
342
|
+
},
|
343
|
+
});
|
344
|
+
}
|
345
|
+
|
346
|
+
async fetchTime (params = {}) {
|
347
|
+
const response = await this.publicSystemGetTime (params);
|
348
|
+
//
|
349
|
+
// {
|
350
|
+
// "message":"OK",
|
351
|
+
// "code":1000,
|
352
|
+
// "trace":"c4e5e5b7-fe9f-4191-89f7-53f6c5bf9030",
|
353
|
+
// "data":{
|
354
|
+
// "server_time":1599843709578
|
355
|
+
// }
|
356
|
+
// }
|
357
|
+
//
|
358
|
+
const data = this.safeValue (response, 'data', {});
|
359
|
+
return this.safeInteger (data, 'server_time');
|
360
|
+
}
|
361
|
+
|
362
|
+
async fetchStatus (params = {}) {
|
363
|
+
const options = this.safeValue (this.options, 'fetchBalance', {});
|
364
|
+
const defaultType = this.safeString (this.options, 'defaultType');
|
365
|
+
let type = this.safeString (options, 'type', defaultType);
|
366
|
+
type = this.safeString (params, 'type', type);
|
367
|
+
params = this.omit (params, 'type');
|
368
|
+
const response = await this.publicSystemGetService (params);
|
369
|
+
//
|
370
|
+
// {
|
371
|
+
// "message": "OK",
|
372
|
+
// "code": 1000,
|
373
|
+
// "trace": "1d3f28b0-763e-4f78-90c4-5e3ad19dc595",
|
374
|
+
// "data": {
|
375
|
+
// "service": [
|
376
|
+
// {
|
377
|
+
// "title": "Spot API Stop",
|
378
|
+
// "service_type": "spot",
|
379
|
+
// "status": 2,
|
380
|
+
// "start_time": 1648639069125,
|
381
|
+
// "end_time": 1648639069125
|
382
|
+
// },
|
383
|
+
// {
|
384
|
+
// "title": "Contract API Stop",
|
385
|
+
// "service_type": "contract",
|
386
|
+
// "status": 2,
|
387
|
+
// "start_time": 1648639069125,
|
388
|
+
// "end_time": 1648639069125
|
389
|
+
// }
|
390
|
+
// ]
|
391
|
+
// }
|
392
|
+
// }
|
393
|
+
//
|
394
|
+
const data = this.safeValue (response, 'data', {});
|
395
|
+
const services = this.safeValue (data, 'service', []);
|
396
|
+
const servicesByType = this.indexBy (services, 'service_type');
|
397
|
+
if ((type === 'swap') || (type === 'future')) {
|
398
|
+
type = 'contract';
|
399
|
+
}
|
400
|
+
const service = this.safeValue (servicesByType, type);
|
401
|
+
let status = undefined;
|
402
|
+
let eta = undefined;
|
403
|
+
if (service !== undefined) {
|
404
|
+
const statusCode = this.safeInteger (service, 'status');
|
405
|
+
if (statusCode === 2) {
|
406
|
+
status = 'ok';
|
407
|
+
} else {
|
408
|
+
status = 'maintenance';
|
409
|
+
eta = this.safeInteger (service, 'end_time');
|
410
|
+
}
|
411
|
+
}
|
412
|
+
return {
|
413
|
+
'status': status,
|
414
|
+
'updated': this.milliseconds (),
|
415
|
+
'eta': eta,
|
416
|
+
'url': undefined,
|
417
|
+
'info': response,
|
418
|
+
};
|
419
|
+
}
|
420
|
+
|
421
|
+
async fetchSpotMarkets (params = {}) {
|
422
|
+
const response = await this.publicSpotGetSymbolsDetails (params);
|
423
|
+
//
|
424
|
+
// {
|
425
|
+
// "message":"OK",
|
426
|
+
// "code":1000,
|
427
|
+
// "trace":"a67c9146-086d-4d3f-9897-5636a9bb26e1",
|
428
|
+
// "data":{
|
429
|
+
// "symbols":[
|
430
|
+
// {
|
431
|
+
// "symbol":"PRQ_BTC",
|
432
|
+
// "symbol_id":1232,
|
433
|
+
// "base_currency":"PRQ",
|
434
|
+
// "quote_currency":"BTC",
|
435
|
+
// "quote_increment":"1.0000000000",
|
436
|
+
// "base_min_size":"1.0000000000",
|
437
|
+
// "base_max_size":"10000000.0000000000",
|
438
|
+
// "price_min_precision":8,
|
439
|
+
// "price_max_precision":10,
|
440
|
+
// "expiration":"NA",
|
441
|
+
// "min_buy_amount":"0.0001000000",
|
442
|
+
// "min_sell_amount":"0.0001000000"
|
443
|
+
// },
|
444
|
+
// ]
|
445
|
+
// }
|
446
|
+
// }
|
447
|
+
//
|
448
|
+
const data = this.safeValue (response, 'data', {});
|
449
|
+
const symbols = this.safeValue (data, 'symbols', []);
|
450
|
+
const result = [];
|
451
|
+
for (let i = 0; i < symbols.length; i++) {
|
452
|
+
const market = symbols[i];
|
453
|
+
const id = this.safeString (market, 'symbol');
|
454
|
+
const numericId = this.safeInteger (market, 'symbol_id');
|
455
|
+
const baseId = this.safeString (market, 'base_currency');
|
456
|
+
const quoteId = this.safeString (market, 'quote_currency');
|
457
|
+
const base = this.safeCurrencyCode (baseId);
|
458
|
+
const quote = this.safeCurrencyCode (quoteId);
|
459
|
+
const symbol = base + '/' + quote;
|
460
|
+
//
|
461
|
+
// https://github.com/bitmartexchange/bitmart-official-api-docs/blob/master/rest/public/symbols_details.md#response-details
|
462
|
+
// from the above API doc:
|
463
|
+
// quote_increment Minimum order price as well as the price increment
|
464
|
+
// price_min_precision Minimum price precision (digit) used to query price and kline
|
465
|
+
// price_max_precision Maximum price precision (digit) used to query price and kline
|
466
|
+
//
|
467
|
+
// the docs are wrong: https://github.com/ccxt/ccxt/issues/5612
|
468
|
+
//
|
469
|
+
const minBuyCost = this.safeString (market, 'min_buy_amount');
|
470
|
+
const minSellCost = this.safeString (market, 'min_sell_amount');
|
471
|
+
const minCost = Precise.stringMax (minBuyCost, minSellCost);
|
472
|
+
const pricePrecision = this.parsePrecision (this.safeString (market, 'price_max_precision'));
|
473
|
+
result.push ({
|
474
|
+
'id': id,
|
475
|
+
'numericId': numericId,
|
476
|
+
'symbol': symbol,
|
477
|
+
'base': base,
|
478
|
+
'quote': quote,
|
479
|
+
'settle': undefined,
|
480
|
+
'baseId': baseId,
|
481
|
+
'quoteId': quoteId,
|
482
|
+
'settleId': undefined,
|
483
|
+
'type': 'spot',
|
484
|
+
'spot': true,
|
485
|
+
'margin': false,
|
486
|
+
'swap': false,
|
487
|
+
'future': false,
|
488
|
+
'option': false,
|
489
|
+
'active': true,
|
490
|
+
'contract': false,
|
491
|
+
'linear': undefined,
|
492
|
+
'inverse': undefined,
|
493
|
+
'contractSize': undefined,
|
494
|
+
'expiry': undefined,
|
495
|
+
'expiryDatetime': undefined,
|
496
|
+
'strike': undefined,
|
497
|
+
'optionType': undefined,
|
498
|
+
'precision': {
|
499
|
+
'amount': this.safeNumber (market, 'base_min_size'),
|
500
|
+
'price': this.parseNumber (pricePrecision),
|
501
|
+
},
|
502
|
+
'limits': {
|
503
|
+
'leverage': {
|
504
|
+
'min': undefined,
|
505
|
+
'max': undefined,
|
506
|
+
},
|
507
|
+
'amount': {
|
508
|
+
'min': this.safeNumber (market, 'base_min_size'),
|
509
|
+
'max': this.safeNumber (market, 'base_max_size'),
|
510
|
+
},
|
511
|
+
'price': {
|
512
|
+
'min': undefined,
|
513
|
+
'max': undefined,
|
514
|
+
},
|
515
|
+
'cost': {
|
516
|
+
'min': this.parseNumber (minCost),
|
517
|
+
'max': undefined,
|
518
|
+
},
|
519
|
+
},
|
520
|
+
'info': market,
|
521
|
+
});
|
522
|
+
}
|
523
|
+
return result;
|
524
|
+
}
|
525
|
+
|
526
|
+
async fetchContractMarkets (params = {}) {
|
527
|
+
const response = await this.publicContractGetTickers (params);
|
528
|
+
//
|
529
|
+
// {
|
530
|
+
// "message": "OK",
|
531
|
+
// "code": 1000,
|
532
|
+
// "trace": "045d13a8-4bc7-4974-9748-97d0ea183ef0",
|
533
|
+
// "data": {
|
534
|
+
// "tickers": [
|
535
|
+
// {
|
536
|
+
// "contract_symbol": "RAYUSDT",
|
537
|
+
// "last_price": "3.893",
|
538
|
+
// "index_price": "3.90248043",
|
539
|
+
// "last_funding_rate": "-0.00054285",
|
540
|
+
// "price_change_percent_24h": "-6.955",
|
541
|
+
// "volume_24h": "10450969.34602996",
|
542
|
+
// "url": "https://futures.bitmart.com/en?symbol=RAYUSDT",
|
543
|
+
// "high_price": "4.299",
|
544
|
+
// "low_price": "3.887",
|
545
|
+
// "legal_coin_price": "3.893056"
|
546
|
+
// },
|
547
|
+
// ...
|
548
|
+
// ]
|
549
|
+
// }
|
550
|
+
// }
|
551
|
+
//
|
552
|
+
const data = this.safeValue (response, 'data', {});
|
553
|
+
const tickers = this.safeValue (data, 'tickers', []);
|
554
|
+
const result = [];
|
555
|
+
for (let i = 0; i < tickers.length; i++) {
|
556
|
+
const market = tickers[i];
|
557
|
+
const id = this.safeString (market, 'contract_symbol');
|
558
|
+
const baseId = id.slice (0, -4);
|
559
|
+
const quoteId = id.slice (-4);
|
560
|
+
const base = this.safeCurrencyCode (baseId);
|
561
|
+
const quote = this.safeCurrencyCode (quoteId);
|
562
|
+
const splitId = id.split ('_');
|
563
|
+
const splitIdEnding = this.safeString (splitId, 1);
|
564
|
+
let settle = 'USDT';
|
565
|
+
let symbol = base + '/' + quote + ':' + settle;
|
566
|
+
let type = 'swap';
|
567
|
+
let swap = true;
|
568
|
+
let future = false;
|
569
|
+
let expiry = undefined;
|
570
|
+
if (splitIdEnding !== undefined) {
|
571
|
+
settle = 'BTC';
|
572
|
+
symbol = base + '/' + quote + ':' + settle;
|
573
|
+
if (splitIdEnding !== 'PERP') {
|
574
|
+
const date = this.iso8601 (this.milliseconds ());
|
575
|
+
const splitDate = date.split ('-');
|
576
|
+
const year = splitDate[0];
|
577
|
+
const shortYear = year.slice (0, 2);
|
578
|
+
const expiryMonth = splitIdEnding.slice (0, 2);
|
579
|
+
const expiryDay = splitIdEnding.slice (2, 4);
|
580
|
+
expiry = this.parse8601 (year + '-' + expiryMonth + '-' + expiryDay + 'T00:00:00Z');
|
581
|
+
symbol = symbol + '-' + shortYear + splitIdEnding;
|
582
|
+
type = 'future';
|
583
|
+
swap = false;
|
584
|
+
future = true;
|
585
|
+
}
|
586
|
+
}
|
587
|
+
result.push ({
|
588
|
+
'id': id,
|
589
|
+
'numericId': undefined,
|
590
|
+
'symbol': symbol,
|
591
|
+
'base': base,
|
592
|
+
'quote': quote,
|
593
|
+
'settle': settle,
|
594
|
+
'baseId': baseId,
|
595
|
+
'quoteId': quoteId,
|
596
|
+
'settleId': undefined,
|
597
|
+
'type': type,
|
598
|
+
'spot': false,
|
599
|
+
'margin': false,
|
600
|
+
'swap': swap,
|
601
|
+
'future': future,
|
602
|
+
'option': false,
|
603
|
+
'active': true,
|
604
|
+
'contract': true,
|
605
|
+
'linear': true,
|
606
|
+
'inverse': false,
|
607
|
+
'contractSize': undefined,
|
608
|
+
'expiry': expiry,
|
609
|
+
'expiryDatetime': this.iso8601 (expiry),
|
610
|
+
'strike': undefined,
|
611
|
+
'optionType': undefined,
|
612
|
+
'precision': {
|
613
|
+
'amount': undefined,
|
614
|
+
'price': undefined,
|
615
|
+
},
|
616
|
+
'limits': {
|
617
|
+
'leverage': {
|
618
|
+
'min': undefined,
|
619
|
+
'max': undefined,
|
620
|
+
},
|
621
|
+
'amount': {
|
622
|
+
'min': undefined,
|
623
|
+
'max': undefined,
|
624
|
+
},
|
625
|
+
'price': {
|
626
|
+
'min': undefined,
|
627
|
+
'max': undefined,
|
628
|
+
},
|
629
|
+
'cost': {
|
630
|
+
'min': undefined,
|
631
|
+
'max': undefined,
|
632
|
+
},
|
633
|
+
},
|
634
|
+
'info': market,
|
635
|
+
});
|
636
|
+
}
|
637
|
+
return result;
|
638
|
+
}
|
639
|
+
|
640
|
+
async fetchMarkets (params = {}) {
|
641
|
+
const spot = await this.fetchSpotMarkets (params);
|
642
|
+
const contract = await this.fetchContractMarkets (params);
|
643
|
+
return this.arrayConcat (spot, contract);
|
644
|
+
}
|
645
|
+
|
646
|
+
async fetchFundingFee (code, params = {}) {
|
647
|
+
await this.loadMarkets ();
|
648
|
+
const currency = this.currency (code);
|
649
|
+
const request = {
|
650
|
+
'currency': currency['id'],
|
651
|
+
};
|
652
|
+
const response = await this.privateAccountGetWithdrawCharge (this.extend (request, params));
|
653
|
+
//
|
654
|
+
// {
|
655
|
+
// message: 'OK',
|
656
|
+
// code: '1000',
|
657
|
+
// trace: '3ecc0adf-91bd-4de7-aca1-886c1122f54f',
|
658
|
+
// data: {
|
659
|
+
// today_available_withdraw_BTC: '100.0000',
|
660
|
+
// min_withdraw: '0.005',
|
661
|
+
// withdraw_precision: '8',
|
662
|
+
// withdraw_fee: '0.000500000000000000000000000000'
|
663
|
+
// }
|
664
|
+
// }
|
665
|
+
//
|
666
|
+
const data = response['data'];
|
667
|
+
const withdrawFees = {};
|
668
|
+
withdrawFees[code] = this.safeNumber (data, 'withdraw_fee');
|
669
|
+
return {
|
670
|
+
'info': response,
|
671
|
+
'withdraw': withdrawFees,
|
672
|
+
'deposit': {},
|
673
|
+
};
|
674
|
+
}
|
675
|
+
|
676
|
+
parseTicker (ticker, market = undefined) {
|
677
|
+
//
|
678
|
+
// spot
|
679
|
+
//
|
680
|
+
// {
|
681
|
+
// "symbol":"DOGE_USDT",
|
682
|
+
// "last_price":"0.128300",
|
683
|
+
// "quote_volume_24h":"2296619.060420",
|
684
|
+
// "base_volume_24h":"17508866.000000000000000000000000000000",
|
685
|
+
// "high_24h":"0.133900",
|
686
|
+
// "low_24h":"0.127799",
|
687
|
+
// "open_24h":"0.133100",
|
688
|
+
// "close_24h":"0.128300",
|
689
|
+
// "best_ask":"0.128530",
|
690
|
+
// "best_ask_size":"15170",
|
691
|
+
// "best_bid":"0.128200",
|
692
|
+
// "best_bid_size":"21232",
|
693
|
+
// "fluctuation":"-0.0361",
|
694
|
+
// "s_t": 1610936002, // ws only
|
695
|
+
// "url":"https://www.bitmart.com/trade?symbol=DOGE_USDT"
|
696
|
+
// }
|
697
|
+
//
|
698
|
+
// contract
|
699
|
+
//
|
700
|
+
// {
|
701
|
+
// "contract_symbol":"DOGEUSDT",
|
702
|
+
// "last_price":"0.130340",
|
703
|
+
// "index_price":"0.13048245",
|
704
|
+
// "last_funding_rate":"0.00002287",
|
705
|
+
// "price_change_percent_24h":"-2.074",
|
706
|
+
// "volume_24h":"113705028.59482228",
|
707
|
+
// "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT",
|
708
|
+
// "high_price":"0.134520",
|
709
|
+
// "low_price":"0.128570",
|
710
|
+
// "legal_coin_price":"0.1302699"
|
711
|
+
// }
|
712
|
+
//
|
713
|
+
const timestamp = this.safeTimestamp2 (ticker, 'timestamp', 's_t', this.milliseconds ());
|
714
|
+
const marketId = this.safeString2 (ticker, 'symbol', 'contract_symbol');
|
715
|
+
market = this.safeMarket (marketId, market);
|
716
|
+
const symbol = market['symbol'];
|
717
|
+
const last = this.safeString2 (ticker, 'close_24h', 'last_price');
|
718
|
+
let percentage = this.safeString (ticker, 'price_change_percent_24h');
|
719
|
+
if (percentage === undefined) {
|
720
|
+
const percentageRaw = this.safeString (ticker, 'fluctuation');
|
721
|
+
if ((percentageRaw !== undefined) && (percentageRaw !== '0')) { // a few tickers show strictly '0' in fluctuation field
|
722
|
+
const direction = percentageRaw[0];
|
723
|
+
percentage = direction + Precise.stringMul (percentageRaw.replace (direction, ''), '100');
|
724
|
+
} else if (percentageRaw === '0') {
|
725
|
+
percentage = '0';
|
726
|
+
}
|
727
|
+
}
|
728
|
+
const baseVolume = this.safeString (ticker, 'base_volume_24h');
|
729
|
+
let quoteVolume = this.safeString (ticker, 'quote_volume_24h');
|
730
|
+
quoteVolume = this.safeString (ticker, 'volume_24h', quoteVolume);
|
731
|
+
const average = this.safeString2 (ticker, 'avg_price', 'index_price');
|
732
|
+
const price = this.safeString (ticker, 'depth_price', ticker);
|
733
|
+
const high = this.safeString2 (ticker, 'high_24h', 'high_price');
|
734
|
+
const low = this.safeString2 (ticker, 'low_24h', 'low_price');
|
735
|
+
return this.safeTicker ({
|
736
|
+
'symbol': symbol,
|
737
|
+
'timestamp': timestamp,
|
738
|
+
'datetime': this.iso8601 (timestamp),
|
739
|
+
'high': high,
|
740
|
+
'low': low,
|
741
|
+
'bid': this.safeString (price, 'best_bid'),
|
742
|
+
'bidVolume': this.safeString (ticker, 'best_bid_size'),
|
743
|
+
'ask': this.safeString (price, 'best_ask'),
|
744
|
+
'askVolume': this.safeString (ticker, 'best_ask_size'),
|
745
|
+
'vwap': undefined,
|
746
|
+
'open': this.safeString (ticker, 'open_24h'),
|
747
|
+
'close': last,
|
748
|
+
'last': last,
|
749
|
+
'previousClose': undefined,
|
750
|
+
'change': undefined,
|
751
|
+
'percentage': percentage,
|
752
|
+
'average': average,
|
753
|
+
'baseVolume': baseVolume,
|
754
|
+
'quoteVolume': quoteVolume,
|
755
|
+
'info': ticker,
|
756
|
+
}, market, false);
|
757
|
+
}
|
758
|
+
|
759
|
+
async fetchTicker (symbol, params = {}) {
|
760
|
+
await this.loadMarkets ();
|
761
|
+
const market = this.market (symbol);
|
762
|
+
const request = {};
|
763
|
+
let method = undefined;
|
764
|
+
if (market['swap'] || market['future']) {
|
765
|
+
method = 'publicContractGetTickers';
|
766
|
+
request['contract_symbol'] = market['id'];
|
767
|
+
} else if (market['spot']) {
|
768
|
+
method = 'publicSpotGetTicker';
|
769
|
+
request['symbol'] = market['id'];
|
770
|
+
}
|
771
|
+
const response = await this[method] (this.extend (request, params));
|
772
|
+
//
|
773
|
+
// spot
|
774
|
+
//
|
775
|
+
// {
|
776
|
+
// "message":"OK",
|
777
|
+
// "code":1000,
|
778
|
+
// "trace":"6aa5b923-2f57-46e3-876d-feca190e0b82",
|
779
|
+
// "data":{
|
780
|
+
// "tickers":[
|
781
|
+
// {
|
782
|
+
// "symbol":"ETH_BTC",
|
783
|
+
// "last_price":"0.036037",
|
784
|
+
// "quote_volume_24h":"4380.6660000000",
|
785
|
+
// "base_volume_24h":"159.3582006712",
|
786
|
+
// "high_24h":"0.036972",
|
787
|
+
// "low_24h":"0.035524",
|
788
|
+
// "open_24h":"0.036561",
|
789
|
+
// "close_24h":"0.036037",
|
790
|
+
// "best_ask":"0.036077",
|
791
|
+
// "best_ask_size":"9.9500",
|
792
|
+
// "best_bid":"0.035983",
|
793
|
+
// "best_bid_size":"4.2792",
|
794
|
+
// "fluctuation":"-0.0143",
|
795
|
+
// "url":"https://www.bitmart.com/trade?symbol=ETH_BTC"
|
796
|
+
// }
|
797
|
+
// ]
|
798
|
+
// }
|
799
|
+
// }
|
800
|
+
//
|
801
|
+
// contract
|
802
|
+
//
|
803
|
+
// {
|
804
|
+
// "message":"OK",
|
805
|
+
// "code":1000,
|
806
|
+
// "trace":"4a0ebceb-d3f7-45a3-8feb-f61e230e24cd",
|
807
|
+
// "data":{
|
808
|
+
// "tickers":[
|
809
|
+
// {
|
810
|
+
// "contract_symbol":"DOGEUSDT",
|
811
|
+
// "last_price":"0.130180",
|
812
|
+
// "index_price":"0.13028635",
|
813
|
+
// "last_funding_rate":"0.00002025",
|
814
|
+
// "price_change_percent_24h":"-2.326",
|
815
|
+
// "volume_24h":"116789313.01797258",
|
816
|
+
// "url":"https://futures.bitmart.com/en?symbol=DOGEUSDT",
|
817
|
+
// "high_price":"0.134520",
|
818
|
+
// "low_price":"0.128570",
|
819
|
+
// "legal_coin_price":"0.13017401"
|
820
|
+
// }
|
821
|
+
// ]
|
822
|
+
// }
|
823
|
+
// }
|
824
|
+
//
|
825
|
+
const data = this.safeValue (response, 'data', {});
|
826
|
+
const tickers = this.safeValue (data, 'tickers', []);
|
827
|
+
// fails in naming for contract tickers 'contract_symbol'
|
828
|
+
let tickersById = undefined;
|
829
|
+
if (market['spot']) {
|
830
|
+
tickersById = this.indexBy (tickers, 'symbol');
|
831
|
+
} else if (market['swap'] || market['future']) {
|
832
|
+
tickersById = this.indexBy (tickers, 'contract_symbol');
|
833
|
+
}
|
834
|
+
const ticker = this.safeValue (tickersById, market['id']);
|
835
|
+
return this.parseTicker (ticker, market);
|
836
|
+
}
|
837
|
+
|
838
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
839
|
+
await this.loadMarkets ();
|
840
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchTickers', undefined, params);
|
841
|
+
const method = this.getSupportedMapping (marketType, {
|
842
|
+
'spot': 'publicSpotGetTicker',
|
843
|
+
'swap': 'publicContractGetTickers',
|
844
|
+
'future': 'publicContractGetTickers',
|
845
|
+
});
|
846
|
+
const response = await this[method] (query);
|
847
|
+
const data = this.safeValue (response, 'data', {});
|
848
|
+
const tickers = this.safeValue (data, 'tickers', []);
|
849
|
+
const result = {};
|
850
|
+
for (let i = 0; i < tickers.length; i++) {
|
851
|
+
const ticker = this.parseTicker (tickers[i]);
|
852
|
+
const symbol = ticker['symbol'];
|
853
|
+
result[symbol] = ticker;
|
854
|
+
}
|
855
|
+
return this.filterByArray (result, 'symbol', symbols);
|
856
|
+
}
|
857
|
+
|
858
|
+
async fetchCurrencies (params = {}) {
|
859
|
+
const response = await this.publicAccountGetCurrencies (params);
|
860
|
+
//
|
861
|
+
// {
|
862
|
+
// "message":"OK",
|
863
|
+
// "code":1000,
|
864
|
+
// "trace":"8c768b3c-025f-413f-bec5-6d6411d46883",
|
865
|
+
// "data":{
|
866
|
+
// "currencies":[
|
867
|
+
// {"currency":"MATIC","name":"Matic Network","withdraw_enabled":true,"deposit_enabled":true},
|
868
|
+
// {"currency":"KTN","name":"Kasoutuuka News","withdraw_enabled":true,"deposit_enabled":false},
|
869
|
+
// {"currency":"BRT","name":"Berith","withdraw_enabled":true,"deposit_enabled":true},
|
870
|
+
// ]
|
871
|
+
// }
|
872
|
+
// }
|
873
|
+
//
|
874
|
+
const data = this.safeValue (response, 'data', {});
|
875
|
+
const currencies = this.safeValue (data, 'currencies', []);
|
876
|
+
const result = {};
|
877
|
+
for (let i = 0; i < currencies.length; i++) {
|
878
|
+
const currency = currencies[i];
|
879
|
+
const id = this.safeString (currency, 'currency');
|
880
|
+
const code = this.safeCurrencyCode (id);
|
881
|
+
const name = this.safeString (currency, 'name');
|
882
|
+
const withdrawEnabled = this.safeValue (currency, 'withdraw_enabled');
|
883
|
+
const depositEnabled = this.safeValue (currency, 'deposit_enabled');
|
884
|
+
const active = withdrawEnabled && depositEnabled;
|
885
|
+
result[code] = {
|
886
|
+
'id': id,
|
887
|
+
'code': code,
|
888
|
+
'name': name,
|
889
|
+
'info': currency, // the original payload
|
890
|
+
'active': active,
|
891
|
+
'deposit': depositEnabled,
|
892
|
+
'withdraw': withdrawEnabled,
|
893
|
+
'fee': undefined,
|
894
|
+
'precision': undefined,
|
895
|
+
'limits': {
|
896
|
+
'amount': { 'min': undefined, 'max': undefined },
|
897
|
+
'withdraw': { 'min': undefined, 'max': undefined },
|
898
|
+
},
|
899
|
+
};
|
900
|
+
}
|
901
|
+
return result;
|
902
|
+
}
|
903
|
+
|
904
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
905
|
+
await this.loadMarkets ();
|
906
|
+
const market = this.market (symbol);
|
907
|
+
const request = {};
|
908
|
+
let method = undefined;
|
909
|
+
if (market['spot']) {
|
910
|
+
method = 'publicSpotGetSymbolsBook';
|
911
|
+
request['symbol'] = market['id'];
|
912
|
+
if (limit !== undefined) {
|
913
|
+
request['size'] = limit; // default 50, max 200
|
914
|
+
}
|
915
|
+
// request['precision'] = 4; // optional price precision / depth level whose range is defined in symbol details
|
916
|
+
} else if (market['swap'] || market['future']) {
|
917
|
+
method = 'publicContractGetDepth';
|
918
|
+
request['contractID'] = market['id'];
|
919
|
+
if (limit !== undefined) {
|
920
|
+
request['count'] = limit; // returns all records if size is omitted
|
921
|
+
}
|
922
|
+
}
|
923
|
+
const response = await this[method] (this.extend (request, params));
|
924
|
+
//
|
925
|
+
// spot
|
926
|
+
//
|
927
|
+
// {
|
928
|
+
// "message":"OK",
|
929
|
+
// "code":1000,
|
930
|
+
// "trace":"8254f8fc-431d-404f-ad9a-e716339f66c7",
|
931
|
+
// "data":{
|
932
|
+
// "buys":[
|
933
|
+
// {"amount":"4.7091","total":"4.71","price":"0.034047","count":"1"},
|
934
|
+
// {"amount":"5.7439","total":"10.45","price":"0.034039","count":"1"},
|
935
|
+
// {"amount":"2.5249","total":"12.98","price":"0.032937","count":"1"},
|
936
|
+
// ],
|
937
|
+
// "sells":[
|
938
|
+
// {"amount":"41.4365","total":"41.44","price":"0.034174","count":"1"},
|
939
|
+
// {"amount":"4.2317","total":"45.67","price":"0.034183","count":"1"},
|
940
|
+
// {"amount":"0.3000","total":"45.97","price":"0.034240","count":"1"},
|
941
|
+
// ]
|
942
|
+
// }
|
943
|
+
// }
|
944
|
+
//
|
945
|
+
// contract
|
946
|
+
//
|
947
|
+
// {
|
948
|
+
// "errno":"OK",
|
949
|
+
// "message":"OK",
|
950
|
+
// "code":1000,
|
951
|
+
// "trace":"c330dfca-ca5b-4f15-b350-9fef3f049b4f",
|
952
|
+
// "data":{
|
953
|
+
// "sells":[
|
954
|
+
// {"price":"347.6","vol":"6678"},
|
955
|
+
// {"price":"347.7","vol":"3452"},
|
956
|
+
// {"price":"347.8","vol":"6331"},
|
957
|
+
// ],
|
958
|
+
// "buys":[
|
959
|
+
// {"price":"347.5","vol":"6222"},
|
960
|
+
// {"price":"347.4","vol":"20979"},
|
961
|
+
// {"price":"347.3","vol":"15179"},
|
962
|
+
// ]
|
963
|
+
// }
|
964
|
+
// }
|
965
|
+
//
|
966
|
+
const data = this.safeValue (response, 'data', {});
|
967
|
+
if (market['spot']) {
|
968
|
+
return this.parseOrderBook (data, symbol, undefined, 'buys', 'sells', 'price', 'amount');
|
969
|
+
} else if (market['swap'] || market['future']) {
|
970
|
+
return this.parseOrderBook (data, symbol, undefined, 'buys', 'sells', 'price', 'vol');
|
971
|
+
}
|
972
|
+
}
|
973
|
+
|
974
|
+
parseTrade (trade, market = undefined) {
|
975
|
+
//
|
976
|
+
// public fetchTrades spot ( amount = count * price )
|
977
|
+
//
|
978
|
+
// {
|
979
|
+
// "amount": "818.94",
|
980
|
+
// "order_time": "1637601839035", // ETH/USDT
|
981
|
+
// "price": "4221.99",
|
982
|
+
// "count": "0.19397",
|
983
|
+
// "type": "buy"
|
984
|
+
// }
|
985
|
+
//
|
986
|
+
// public fetchTrades contract, private fetchMyTrades contract
|
987
|
+
//
|
988
|
+
// {
|
989
|
+
// "order_id":109159616160,
|
990
|
+
// "trade_id":109159616197,
|
991
|
+
// "contract_id":2,
|
992
|
+
// "deal_price":"347.6",
|
993
|
+
// "deal_vol":"5623",
|
994
|
+
// "make_fee":"-5.8636644",
|
995
|
+
// "take_fee":"9.772774",
|
996
|
+
// "created_at":"2020-09-09T11:49:50.749170536Z",
|
997
|
+
// "way":1,
|
998
|
+
// "fluctuation":"0"
|
999
|
+
// }
|
1000
|
+
//
|
1001
|
+
// private fetchMyTrades spot
|
1002
|
+
//
|
1003
|
+
// {
|
1004
|
+
// "detail_id":256348632,
|
1005
|
+
// "order_id":2147484350,
|
1006
|
+
// "symbol":"BTC_USDT",
|
1007
|
+
// "create_time":1590462303000,
|
1008
|
+
// "side":"buy",
|
1009
|
+
// "fees":"0.00001350",
|
1010
|
+
// "fee_coin_name":"BTC",
|
1011
|
+
// "notional":"88.00000000",
|
1012
|
+
// "price_avg":"8800.00",
|
1013
|
+
// "size":"0.01000",
|
1014
|
+
// "exec_type":"M"
|
1015
|
+
// }
|
1016
|
+
//
|
1017
|
+
const id = this.safeString2 (trade, 'trade_id', 'detail_id');
|
1018
|
+
let timestamp = this.safeInteger2 (trade, 'order_time', 'create_time');
|
1019
|
+
if (timestamp === undefined) {
|
1020
|
+
timestamp = this.safeTimestamp (trade, 's_t');
|
1021
|
+
}
|
1022
|
+
if (timestamp === undefined) {
|
1023
|
+
timestamp = this.parse8601 (this.safeString (trade, 'created_at'));
|
1024
|
+
}
|
1025
|
+
const type = undefined;
|
1026
|
+
const way = this.safeInteger (trade, 'way');
|
1027
|
+
let side = this.safeStringLower2 (trade, 'type', 'side');
|
1028
|
+
if ((side === undefined) && (way !== undefined)) {
|
1029
|
+
if (way < 5) {
|
1030
|
+
side = 'buy';
|
1031
|
+
} else {
|
1032
|
+
side = 'sell';
|
1033
|
+
}
|
1034
|
+
}
|
1035
|
+
let takerOrMaker = undefined;
|
1036
|
+
const execType = this.safeString (trade, 'exec_type');
|
1037
|
+
if (execType !== undefined) {
|
1038
|
+
takerOrMaker = (execType === 'M') ? 'maker' : 'taker';
|
1039
|
+
}
|
1040
|
+
let priceString = this.safeString2 (trade, 'price', 'deal_price');
|
1041
|
+
priceString = this.safeString (trade, 'price_avg', priceString);
|
1042
|
+
let amountString = this.safeString2 (trade, 'count', 'deal_vol');
|
1043
|
+
amountString = this.safeString (trade, 'size', amountString);
|
1044
|
+
const costString = this.safeString2 (trade, 'amount', 'notional');
|
1045
|
+
const orderId = this.safeInteger (trade, 'order_id');
|
1046
|
+
const marketId = this.safeString2 (trade, 'contract_id', 'symbol');
|
1047
|
+
market = this.safeMarket (marketId, market, '_');
|
1048
|
+
const feeCostString = this.safeString (trade, 'fees');
|
1049
|
+
let fee = undefined;
|
1050
|
+
if (feeCostString !== undefined) {
|
1051
|
+
const feeCurrencyId = this.safeString (trade, 'fee_coin_name');
|
1052
|
+
let feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
|
1053
|
+
if (feeCurrencyCode === undefined) {
|
1054
|
+
feeCurrencyCode = (side === 'buy') ? market['base'] : market['quote'];
|
1055
|
+
}
|
1056
|
+
fee = {
|
1057
|
+
'cost': feeCostString,
|
1058
|
+
'currency': feeCurrencyCode,
|
1059
|
+
};
|
1060
|
+
}
|
1061
|
+
return this.safeTrade ({
|
1062
|
+
'info': trade,
|
1063
|
+
'id': id,
|
1064
|
+
'order': orderId,
|
1065
|
+
'timestamp': timestamp,
|
1066
|
+
'datetime': this.iso8601 (timestamp),
|
1067
|
+
'symbol': market['symbol'],
|
1068
|
+
'type': type,
|
1069
|
+
'side': side,
|
1070
|
+
'price': priceString,
|
1071
|
+
'amount': amountString,
|
1072
|
+
'cost': costString,
|
1073
|
+
'takerOrMaker': takerOrMaker,
|
1074
|
+
'fee': fee,
|
1075
|
+
}, market);
|
1076
|
+
}
|
1077
|
+
|
1078
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
1079
|
+
await this.loadMarkets ();
|
1080
|
+
const market = this.market (symbol);
|
1081
|
+
const request = {
|
1082
|
+
'symbol': market['id'],
|
1083
|
+
};
|
1084
|
+
let method = undefined;
|
1085
|
+
if (market['spot']) {
|
1086
|
+
request['symbol'] = market['id'];
|
1087
|
+
method = 'publicSpotGetSymbolsTrades';
|
1088
|
+
} else if (market['swap'] || market['future']) {
|
1089
|
+
method = 'publicContractGetTrades';
|
1090
|
+
request['contractID'] = market['id'];
|
1091
|
+
}
|
1092
|
+
const response = await this[method] (this.extend (request, params));
|
1093
|
+
//
|
1094
|
+
// spot
|
1095
|
+
//
|
1096
|
+
// {
|
1097
|
+
// "message":"OK",
|
1098
|
+
// "code":1000,
|
1099
|
+
// "trace":"222d74c0-8f6d-49d9-8e1b-98118c50eeba",
|
1100
|
+
// "data":{
|
1101
|
+
// "trades":[
|
1102
|
+
// {
|
1103
|
+
// "amount":"0.005703",
|
1104
|
+
// "order_time":1599652045394,
|
1105
|
+
// "price":"0.034029",
|
1106
|
+
// "count":"0.1676",
|
1107
|
+
// "type":"sell"
|
1108
|
+
// },
|
1109
|
+
// ]
|
1110
|
+
// }
|
1111
|
+
// }
|
1112
|
+
//
|
1113
|
+
// contract
|
1114
|
+
//
|
1115
|
+
// {
|
1116
|
+
// "errno":"OK",
|
1117
|
+
// "message":"OK",
|
1118
|
+
// "code":1000,
|
1119
|
+
// "trace":"782bc746-b86e-43bf-8d1a-c68b479c9bdd",
|
1120
|
+
// "data":{
|
1121
|
+
// "trades":[
|
1122
|
+
// {
|
1123
|
+
// "order_id":109159616160,
|
1124
|
+
// "trade_id":109159616197,
|
1125
|
+
// "contract_id":2,
|
1126
|
+
// "deal_price":"347.6",
|
1127
|
+
// "deal_vol":"5623",
|
1128
|
+
// "make_fee":"-5.8636644",
|
1129
|
+
// "take_fee":"9.772774",
|
1130
|
+
// "created_at":"2020-09-09T11:49:50.749170536Z",
|
1131
|
+
// "way":1,
|
1132
|
+
// "fluctuation":"0"
|
1133
|
+
// }
|
1134
|
+
// ]
|
1135
|
+
// }
|
1136
|
+
// }
|
1137
|
+
//
|
1138
|
+
const data = this.safeValue (response, 'data', {});
|
1139
|
+
const trades = this.safeValue (data, 'trades', []);
|
1140
|
+
return this.parseTrades (trades, market, since, limit);
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
parseOHLCV (ohlcv, market = undefined) {
|
1144
|
+
//
|
1145
|
+
// spot
|
1146
|
+
//
|
1147
|
+
// {
|
1148
|
+
// "last_price":"0.034987",
|
1149
|
+
// "timestamp":1598787420,
|
1150
|
+
// "volume":"1.0198",
|
1151
|
+
// "open":"0.035007",
|
1152
|
+
// "close":"0.034987",
|
1153
|
+
// "high":"0.035007",
|
1154
|
+
// "low":"0.034986"
|
1155
|
+
// }
|
1156
|
+
//
|
1157
|
+
// contract
|
1158
|
+
//
|
1159
|
+
// {
|
1160
|
+
// "low":"404.4",
|
1161
|
+
// "high":"404.4",
|
1162
|
+
// "open":"404.4",
|
1163
|
+
// "close":"404.4",
|
1164
|
+
// "last_price":"404.4",
|
1165
|
+
// "avg_price":"404.4",
|
1166
|
+
// "volume":"7670",
|
1167
|
+
// "timestamp":1598758441,
|
1168
|
+
// "rise_fall_rate":"0",
|
1169
|
+
// "rise_fall_value":"0",
|
1170
|
+
// "base_coin_volume":"76.7",
|
1171
|
+
// "quote_coin_volume":"31017.48"
|
1172
|
+
// }
|
1173
|
+
//
|
1174
|
+
// ws
|
1175
|
+
//
|
1176
|
+
// [
|
1177
|
+
// 1631056350, // timestamp
|
1178
|
+
// '46532.83', // oopen
|
1179
|
+
// '46555.71', // high
|
1180
|
+
// '46511.41', // low
|
1181
|
+
// '46555.71', // close
|
1182
|
+
// '0.25', // volume
|
1183
|
+
// ]
|
1184
|
+
//
|
1185
|
+
if (Array.isArray (ohlcv)) {
|
1186
|
+
return [
|
1187
|
+
this.safeTimestamp (ohlcv, 0),
|
1188
|
+
this.safeNumber (ohlcv, 1),
|
1189
|
+
this.safeNumber (ohlcv, 2),
|
1190
|
+
this.safeNumber (ohlcv, 3),
|
1191
|
+
this.safeNumber (ohlcv, 4),
|
1192
|
+
this.safeNumber (ohlcv, 5),
|
1193
|
+
];
|
1194
|
+
} else {
|
1195
|
+
return [
|
1196
|
+
this.safeTimestamp (ohlcv, 'timestamp'),
|
1197
|
+
this.safeNumber (ohlcv, 'open'),
|
1198
|
+
this.safeNumber (ohlcv, 'high'),
|
1199
|
+
this.safeNumber (ohlcv, 'low'),
|
1200
|
+
this.safeNumber (ohlcv, 'close'),
|
1201
|
+
this.safeNumber (ohlcv, 'volume'),
|
1202
|
+
];
|
1203
|
+
}
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
1207
|
+
await this.loadMarkets ();
|
1208
|
+
const market = this.market (symbol);
|
1209
|
+
const type = market['type'];
|
1210
|
+
let method = undefined;
|
1211
|
+
const request = {};
|
1212
|
+
const duration = this.parseTimeframe (timeframe);
|
1213
|
+
if (type === 'spot') {
|
1214
|
+
method = 'publicSpotGetSymbolsKline';
|
1215
|
+
request['symbol'] = market['id'];
|
1216
|
+
request['step'] = this.timeframes[timeframe];
|
1217
|
+
// the exchange will return an empty array if more than 500 candles is requested
|
1218
|
+
const maxLimit = 500;
|
1219
|
+
if (limit === undefined) {
|
1220
|
+
limit = maxLimit;
|
1221
|
+
}
|
1222
|
+
limit = Math.min (maxLimit, limit);
|
1223
|
+
if (since === undefined) {
|
1224
|
+
const end = parseInt (this.milliseconds () / 1000);
|
1225
|
+
const start = end - limit * duration;
|
1226
|
+
request['from'] = start;
|
1227
|
+
request['to'] = end;
|
1228
|
+
} else {
|
1229
|
+
const start = parseInt (since / 1000) - 1;
|
1230
|
+
const end = this.sum (start, limit * duration);
|
1231
|
+
request['from'] = start;
|
1232
|
+
request['to'] = end;
|
1233
|
+
}
|
1234
|
+
} else if ((type === 'swap') || (type === 'future')) {
|
1235
|
+
method = 'publicContractGetQuote';
|
1236
|
+
request['contractID'] = market['id'];
|
1237
|
+
const defaultLimit = 500;
|
1238
|
+
if (limit === undefined) {
|
1239
|
+
limit = defaultLimit;
|
1240
|
+
}
|
1241
|
+
if (since === undefined) {
|
1242
|
+
const end = parseInt (this.milliseconds () / 1000);
|
1243
|
+
const start = end - limit * duration;
|
1244
|
+
request['startTime'] = start;
|
1245
|
+
request['endTime'] = end;
|
1246
|
+
} else {
|
1247
|
+
const start = parseInt (since / 1000) - 1;
|
1248
|
+
const end = this.sum (start, limit * duration);
|
1249
|
+
request['startTime'] = start;
|
1250
|
+
request['endTime'] = end;
|
1251
|
+
}
|
1252
|
+
request['unit'] = this.timeframes[timeframe];
|
1253
|
+
request['resolution'] = 'M';
|
1254
|
+
}
|
1255
|
+
const response = await this[method] (this.extend (request, params));
|
1256
|
+
//
|
1257
|
+
// spot
|
1258
|
+
//
|
1259
|
+
// {
|
1260
|
+
// "message":"OK",
|
1261
|
+
// "code":1000,
|
1262
|
+
// "trace":"80d86378-ab4e-4c70-819e-b42146cf87ad",
|
1263
|
+
// "data":{
|
1264
|
+
// "klines":[
|
1265
|
+
// {"last_price":"0.034987","timestamp":1598787420,"volume":"1.0198","open":"0.035007","close":"0.034987","high":"0.035007","low":"0.034986"},
|
1266
|
+
// {"last_price":"0.034986","timestamp":1598787480,"volume":"0.3959","open":"0.034982","close":"0.034986","high":"0.034986","low":"0.034980"},
|
1267
|
+
// {"last_price":"0.034978","timestamp":1598787540,"volume":"0.3259","open":"0.034987","close":"0.034978","high":"0.034987","low":"0.034977"},
|
1268
|
+
// ]
|
1269
|
+
// }
|
1270
|
+
// }
|
1271
|
+
//
|
1272
|
+
// swap
|
1273
|
+
//
|
1274
|
+
// {
|
1275
|
+
// "errno":"OK",
|
1276
|
+
// "message":"OK",
|
1277
|
+
// "code":1000,
|
1278
|
+
// "trace":"32965074-5804-4655-b693-e953e36026a0",
|
1279
|
+
// "data":[
|
1280
|
+
// {"low":"404.4","high":"404.4","open":"404.4","close":"404.4","last_price":"404.4","avg_price":"404.4","volume":"7670","timestamp":1598758441,"rise_fall_rate":"0","rise_fall_value":"0","base_coin_volume":"76.7","quote_coin_volume":"31017.48"},
|
1281
|
+
// {"low":"404.1","high":"404.4","open":"404.4","close":"404.1","last_price":"404.1","avg_price":"404.15881086","volume":"12076","timestamp":1598758501,"rise_fall_rate":"-0.000741839762611276","rise_fall_value":"-0.3","base_coin_volume":"120.76","quote_coin_volume":"48806.2179994536"},
|
1282
|
+
// {"low":"404","high":"404.3","open":"404.1","close":"404","last_price":"404","avg_price":"404.08918918","volume":"740","timestamp":1598758561,"rise_fall_rate":"-0.000247463499133878","rise_fall_value":"-0.1","base_coin_volume":"7.4","quote_coin_volume":"2990.259999932"},
|
1283
|
+
// ]
|
1284
|
+
// }
|
1285
|
+
//
|
1286
|
+
const data = this.safeValue (response, 'data', {});
|
1287
|
+
if (Array.isArray (data)) {
|
1288
|
+
return this.parseOHLCVs (data, market, timeframe, since, limit);
|
1289
|
+
} else {
|
1290
|
+
const klines = this.safeValue (data, 'klines', []);
|
1291
|
+
return this.parseOHLCVs (klines, market, timeframe, since, limit);
|
1292
|
+
}
|
1293
|
+
}
|
1294
|
+
|
1295
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1296
|
+
if (symbol === undefined) {
|
1297
|
+
throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument');
|
1298
|
+
}
|
1299
|
+
await this.loadMarkets ();
|
1300
|
+
const market = this.market (symbol);
|
1301
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchMyTrades', market, params);
|
1302
|
+
const request = {};
|
1303
|
+
if (market['spot']) {
|
1304
|
+
request['symbol'] = market['id'];
|
1305
|
+
request['offset'] = 1; // max offset * limit < 500
|
1306
|
+
if (limit === undefined) {
|
1307
|
+
limit = 100; // max 100
|
1308
|
+
}
|
1309
|
+
request['limit'] = limit;
|
1310
|
+
} else if (market['swap'] || market['future']) {
|
1311
|
+
request['contractID'] = market['id'];
|
1312
|
+
// request['offset'] = 1;
|
1313
|
+
if (limit !== undefined) {
|
1314
|
+
request['size'] = limit; // max 60
|
1315
|
+
}
|
1316
|
+
}
|
1317
|
+
const method = this.getSupportedMapping (marketType, {
|
1318
|
+
'spot': 'privateSpotGetTrades',
|
1319
|
+
'swap': 'privateContractGetUserTrades',
|
1320
|
+
'future': 'privateContractGetUserTrades',
|
1321
|
+
});
|
1322
|
+
const response = await this[method] (this.extend (request, query));
|
1323
|
+
//
|
1324
|
+
// spot
|
1325
|
+
//
|
1326
|
+
// {
|
1327
|
+
// "message":"OK",
|
1328
|
+
// "code":1000,
|
1329
|
+
// "trace":"a06a5c53-8e6f-42d6-8082-2ff4718d221c",
|
1330
|
+
// "data":{
|
1331
|
+
// "current_page":1,
|
1332
|
+
// "trades":[
|
1333
|
+
// {
|
1334
|
+
// "detail_id":256348632,
|
1335
|
+
// "order_id":2147484350,
|
1336
|
+
// "symbol":"BTC_USDT",
|
1337
|
+
// "create_time":1590462303000,
|
1338
|
+
// "side":"buy",
|
1339
|
+
// "fees":"0.00001350",
|
1340
|
+
// "fee_coin_name":"BTC",
|
1341
|
+
// "notional":"88.00000000",
|
1342
|
+
// "price_avg":"8800.00",
|
1343
|
+
// "size":"0.01000",
|
1344
|
+
// "exec_type":"M"
|
1345
|
+
// },
|
1346
|
+
// ]
|
1347
|
+
// }
|
1348
|
+
// }
|
1349
|
+
//
|
1350
|
+
// contract
|
1351
|
+
//
|
1352
|
+
// {
|
1353
|
+
// "code": 1000,
|
1354
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1355
|
+
// "message": "OK",
|
1356
|
+
// "data": {
|
1357
|
+
// "trades": [
|
1358
|
+
// {
|
1359
|
+
// "order_id": 10116361,
|
1360
|
+
// "trade_id": 10116363,
|
1361
|
+
// "contract_id": 1,
|
1362
|
+
// "deal_price": "16",
|
1363
|
+
// "deal_vol": "10",
|
1364
|
+
// "make_fee": "0.04",
|
1365
|
+
// "take_fee": "0.12",
|
1366
|
+
// "created_at": null,
|
1367
|
+
// "way": 5,
|
1368
|
+
// "fluctuation": "0"
|
1369
|
+
// }
|
1370
|
+
// ]
|
1371
|
+
// }
|
1372
|
+
// }
|
1373
|
+
//
|
1374
|
+
const data = this.safeValue (response, 'data', {});
|
1375
|
+
const trades = this.safeValue (data, 'trades', []);
|
1376
|
+
return this.parseTrades (trades, market, since, limit);
|
1377
|
+
}
|
1378
|
+
|
1379
|
+
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1380
|
+
if (symbol === undefined) {
|
1381
|
+
throw new ArgumentsRequired (this.id + ' fetchOrderTrades() requires a symbol argument');
|
1382
|
+
}
|
1383
|
+
await this.loadMarkets ();
|
1384
|
+
const market = this.market (symbol);
|
1385
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrderTrades', market, params);
|
1386
|
+
const request = {};
|
1387
|
+
if (market['spot']) {
|
1388
|
+
request['symbol'] = market['id'];
|
1389
|
+
request['order_id'] = id;
|
1390
|
+
} else if (market['swap'] || market['future']) {
|
1391
|
+
request['contractID'] = market['id'];
|
1392
|
+
request['orderID'] = id;
|
1393
|
+
}
|
1394
|
+
const method = this.getSupportedMapping (marketType, {
|
1395
|
+
'spot': 'privateSpotGetTrades',
|
1396
|
+
'swap': 'privateContractGetOrderTrades',
|
1397
|
+
'future': 'privateContractGetOrderTrades',
|
1398
|
+
});
|
1399
|
+
const response = await this[method] (this.extend (request, query));
|
1400
|
+
//
|
1401
|
+
// spot
|
1402
|
+
//
|
1403
|
+
// {
|
1404
|
+
// "message":"OK",
|
1405
|
+
// "code":1000,
|
1406
|
+
// "trace":"a06a5c53-8e6f-42d6-8082-2ff4718d221c",
|
1407
|
+
// "data":{
|
1408
|
+
// "current_page":1,
|
1409
|
+
// "trades":[
|
1410
|
+
// {
|
1411
|
+
// "detail_id":256348632,
|
1412
|
+
// "order_id":2147484350,
|
1413
|
+
// "symbol":"BTC_USDT",
|
1414
|
+
// "create_time":1590462303000,
|
1415
|
+
// "side":"buy",
|
1416
|
+
// "fees":"0.00001350",
|
1417
|
+
// "fee_coin_name":"BTC",
|
1418
|
+
// "notional":"88.00000000",
|
1419
|
+
// "price_avg":"8800.00",
|
1420
|
+
// "size":"0.01000",
|
1421
|
+
// "exec_type":"M"
|
1422
|
+
// },
|
1423
|
+
// ]
|
1424
|
+
// }
|
1425
|
+
// }
|
1426
|
+
//
|
1427
|
+
// contract
|
1428
|
+
//
|
1429
|
+
// {
|
1430
|
+
// "code": 1000,
|
1431
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1432
|
+
// "message": "OK",
|
1433
|
+
// "data": {
|
1434
|
+
// "trades": [
|
1435
|
+
// {
|
1436
|
+
// "order_id": 10116361,
|
1437
|
+
// "trade_id": 10116363,
|
1438
|
+
// "contract_id": 1,
|
1439
|
+
// "deal_price": "16",
|
1440
|
+
// "deal_vol": "10",
|
1441
|
+
// "make_fee": "0.04",
|
1442
|
+
// "take_fee": "0.12",
|
1443
|
+
// "created_at": null,
|
1444
|
+
// "way": 5,
|
1445
|
+
// "fluctuation": "0"
|
1446
|
+
// }
|
1447
|
+
// ]
|
1448
|
+
// }
|
1449
|
+
// }
|
1450
|
+
//
|
1451
|
+
const data = this.safeValue (response, 'data', {});
|
1452
|
+
const trades = this.safeValue (data, 'trades', []);
|
1453
|
+
return this.parseTrades (trades, market, since, limit);
|
1454
|
+
}
|
1455
|
+
|
1456
|
+
parseBalance (response) {
|
1457
|
+
const data = this.safeValue (response, 'data', {});
|
1458
|
+
const wallet = this.safeValue2 (data, 'wallet', 'accounts', []);
|
1459
|
+
const result = { 'info': response };
|
1460
|
+
for (let i = 0; i < wallet.length; i++) {
|
1461
|
+
const balance = wallet[i];
|
1462
|
+
let currencyId = this.safeString2 (balance, 'id', 'currency');
|
1463
|
+
currencyId = this.safeString (balance, 'coin_code', currencyId);
|
1464
|
+
const code = this.safeCurrencyCode (currencyId);
|
1465
|
+
const account = this.account ();
|
1466
|
+
account['free'] = this.safeString2 (balance, 'available', 'available_vol');
|
1467
|
+
account['used'] = this.safeString2 (balance, 'frozen', 'freeze_vol');
|
1468
|
+
result[code] = account;
|
1469
|
+
}
|
1470
|
+
return this.safeBalance (result);
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
async fetchBalance (params = {}) {
|
1474
|
+
await this.loadMarkets ();
|
1475
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchBalance', undefined, params);
|
1476
|
+
const method = this.getSupportedMapping (marketType, {
|
1477
|
+
'spot': 'privateSpotGetWallet',
|
1478
|
+
'swap': 'privateContractGetAccounts',
|
1479
|
+
'future': 'privateContractGetAccounts',
|
1480
|
+
'contract': 'privateContractGetAccounts',
|
1481
|
+
'account': 'privateAccountGetWallet',
|
1482
|
+
});
|
1483
|
+
const response = await this[method] (query);
|
1484
|
+
//
|
1485
|
+
// spot
|
1486
|
+
//
|
1487
|
+
// {
|
1488
|
+
// "message":"OK",
|
1489
|
+
// "code":1000,
|
1490
|
+
// "trace":"39069916-72f9-44c7-acde-2ad5afd21cad",
|
1491
|
+
// "data":{
|
1492
|
+
// "wallet":[
|
1493
|
+
// {"id":"BTC","name":"Bitcoin","available":"0.00000062","frozen":"0.00000000"},
|
1494
|
+
// {"id":"ETH","name":"Ethereum","available":"0.00002277","frozen":"0.00000000"},
|
1495
|
+
// {"id":"BMX","name":"BitMart Token","available":"0.00000000","frozen":"0.00000000"}
|
1496
|
+
// ]
|
1497
|
+
// }
|
1498
|
+
// }
|
1499
|
+
//
|
1500
|
+
// account
|
1501
|
+
//
|
1502
|
+
// {
|
1503
|
+
// "message":"OK",
|
1504
|
+
// "code":1000,
|
1505
|
+
// "trace":"5c3b7fc7-93b2-49ef-bb59-7fdc56915b59",
|
1506
|
+
// "data":{
|
1507
|
+
// "wallet":[
|
1508
|
+
// {"currency":"BTC","name":"Bitcoin","available":"0.00000062","frozen":"0.00000000"},
|
1509
|
+
// {"currency":"ETH","name":"Ethereum","available":"0.00002277","frozen":"0.00000000"}
|
1510
|
+
// ]
|
1511
|
+
// }
|
1512
|
+
// }
|
1513
|
+
//
|
1514
|
+
// contract
|
1515
|
+
//
|
1516
|
+
// {
|
1517
|
+
// "code": 1000,
|
1518
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1519
|
+
// "message": "OK",
|
1520
|
+
// "data": {
|
1521
|
+
// "accounts": [
|
1522
|
+
// {
|
1523
|
+
// "account_id": 10,
|
1524
|
+
// "coin_code": "USDT",
|
1525
|
+
// "freeze_vol": "1201.8",
|
1526
|
+
// "available_vol": "8397.65",
|
1527
|
+
// "cash_vol": "0",
|
1528
|
+
// "realised_vol": "-0.5",
|
1529
|
+
// "unrealised_vol": "-0.5",
|
1530
|
+
// "earnings_vol": "-0.5",
|
1531
|
+
// "created_at": "2018-07-13T16:48:49+08:00",
|
1532
|
+
// "updated_at": "2018-07-13T18:34:45.900387+08:00"
|
1533
|
+
// }
|
1534
|
+
// ]
|
1535
|
+
// }
|
1536
|
+
// }
|
1537
|
+
//
|
1538
|
+
return this.parseBalance (response);
|
1539
|
+
}
|
1540
|
+
|
1541
|
+
parseOrder (order, market = undefined) {
|
1542
|
+
//
|
1543
|
+
// createOrder
|
1544
|
+
//
|
1545
|
+
// {
|
1546
|
+
// "order_id": 2707217580
|
1547
|
+
// }
|
1548
|
+
//
|
1549
|
+
// cancelOrder
|
1550
|
+
//
|
1551
|
+
// '2707217580' // order id
|
1552
|
+
//
|
1553
|
+
// spot fetchOrder, fetchOrdersByStatus, fetchOpenOrders, fetchClosedOrders
|
1554
|
+
//
|
1555
|
+
// {
|
1556
|
+
// "order_id":1736871726781,
|
1557
|
+
// "symbol":"BTC_USDT",
|
1558
|
+
// "create_time":1591096004000,
|
1559
|
+
// "side":"sell",
|
1560
|
+
// "type":"market",
|
1561
|
+
// "price":"0.00",
|
1562
|
+
// "price_avg":"0.00",
|
1563
|
+
// "size":"0.02000",
|
1564
|
+
// "notional":"0.00000000",
|
1565
|
+
// "filled_notional":"0.00000000",
|
1566
|
+
// "filled_size":"0.00000",
|
1567
|
+
// "status":"8"
|
1568
|
+
// }
|
1569
|
+
//
|
1570
|
+
// contract fetchOrder, fetchOrdersByStatus, fetchOpenOrders, fetchClosedOrders, fetchOrders
|
1571
|
+
//
|
1572
|
+
// {
|
1573
|
+
// "order_id": 10539098,
|
1574
|
+
// "contract_id": 1,
|
1575
|
+
// "position_id": 10539088,
|
1576
|
+
// "account_id": 10,
|
1577
|
+
// "price": "16",
|
1578
|
+
// "vol": "1",
|
1579
|
+
// "done_avg_price": "16",
|
1580
|
+
// "done_vol": "1",
|
1581
|
+
// "way": 3,
|
1582
|
+
// "category": 1,
|
1583
|
+
// "open_type": 2,
|
1584
|
+
// "make_fee": "0.00025",
|
1585
|
+
// "take_fee": "0.012",
|
1586
|
+
// "origin": "",
|
1587
|
+
// "created_at": "2018-07-23T11:55:56.715305Z",
|
1588
|
+
// "finished_at": "2018-07-23T11:55:56.763941Z",
|
1589
|
+
// "status": 4,
|
1590
|
+
// "errno": 0
|
1591
|
+
// }
|
1592
|
+
//
|
1593
|
+
let id = undefined;
|
1594
|
+
if (typeof order === 'string') {
|
1595
|
+
id = order;
|
1596
|
+
order = {};
|
1597
|
+
}
|
1598
|
+
id = this.safeString (order, 'order_id', id);
|
1599
|
+
let timestamp = this.parse8601 (this.safeString (order, 'created_at'));
|
1600
|
+
timestamp = this.safeInteger (order, 'create_time', timestamp);
|
1601
|
+
const marketId = this.safeString2 (order, 'symbol', 'contract_id');
|
1602
|
+
const symbol = this.safeSymbol (marketId, market, '_');
|
1603
|
+
let status = undefined;
|
1604
|
+
if (market !== undefined) {
|
1605
|
+
status = this.parseOrderStatusByType (market['type'], this.safeString (order, 'status'));
|
1606
|
+
}
|
1607
|
+
const amount = this.safeString2 (order, 'size', 'vol');
|
1608
|
+
const filled = this.safeString2 (order, 'filled_size', 'done_vol');
|
1609
|
+
const average = this.safeString2 (order, 'price_avg', 'done_avg_price');
|
1610
|
+
const price = this.safeString (order, 'price');
|
1611
|
+
const side = this.safeString2 (order, 'way', 'side');
|
1612
|
+
// 1 = Open long
|
1613
|
+
// 2 = Close short
|
1614
|
+
// 3 = Close long
|
1615
|
+
// 4 = Open short
|
1616
|
+
const category = this.safeInteger (order, 'category');
|
1617
|
+
let type = this.safeString (order, 'type');
|
1618
|
+
if (category === 1) {
|
1619
|
+
type = 'limit';
|
1620
|
+
} else if (category === 2) {
|
1621
|
+
type = 'market';
|
1622
|
+
}
|
1623
|
+
return this.safeOrder ({
|
1624
|
+
'id': id,
|
1625
|
+
'clientOrderId': undefined,
|
1626
|
+
'info': order,
|
1627
|
+
'timestamp': timestamp,
|
1628
|
+
'datetime': this.iso8601 (timestamp),
|
1629
|
+
'lastTradeTimestamp': undefined,
|
1630
|
+
'symbol': symbol,
|
1631
|
+
'type': type,
|
1632
|
+
'timeInForce': undefined,
|
1633
|
+
'postOnly': undefined,
|
1634
|
+
'side': side,
|
1635
|
+
'price': price,
|
1636
|
+
'stopPrice': undefined,
|
1637
|
+
'amount': amount,
|
1638
|
+
'cost': undefined,
|
1639
|
+
'average': average,
|
1640
|
+
'filled': filled,
|
1641
|
+
'remaining': undefined,
|
1642
|
+
'status': status,
|
1643
|
+
'fee': undefined,
|
1644
|
+
'trades': undefined,
|
1645
|
+
}, market);
|
1646
|
+
}
|
1647
|
+
|
1648
|
+
parseOrderStatusByType (type, status) {
|
1649
|
+
const statusesByType = {
|
1650
|
+
'spot': {
|
1651
|
+
'1': 'failed', // Order failure
|
1652
|
+
'2': 'open', // Placing order
|
1653
|
+
'3': 'failed', // Order failure, Freeze failure
|
1654
|
+
'4': 'open', // Order success, Pending for fulfilment
|
1655
|
+
'5': 'open', // Partially filled
|
1656
|
+
'6': 'closed', // Fully filled
|
1657
|
+
'7': 'canceling', // Canceling
|
1658
|
+
'8': 'canceled', // Canceled
|
1659
|
+
},
|
1660
|
+
'swap': {
|
1661
|
+
'1': 'open', // Submitting
|
1662
|
+
'2': 'open', // Commissioned
|
1663
|
+
'4': 'closed', // Completed
|
1664
|
+
},
|
1665
|
+
};
|
1666
|
+
const statuses = this.safeValue (statusesByType, type, {});
|
1667
|
+
return this.safeString (statuses, status, status);
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
1671
|
+
await this.loadMarkets ();
|
1672
|
+
const market = this.market (symbol);
|
1673
|
+
const request = {};
|
1674
|
+
let method = undefined;
|
1675
|
+
if (market['spot']) {
|
1676
|
+
request['symbol'] = market['id'];
|
1677
|
+
request['side'] = side;
|
1678
|
+
request['type'] = type;
|
1679
|
+
method = 'privateSpotPostSubmitOrder';
|
1680
|
+
if (type === 'limit') {
|
1681
|
+
request['size'] = this.amountToPrecision (symbol, amount);
|
1682
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1683
|
+
} else if (type === 'market') {
|
1684
|
+
// for market buy it requires the amount of quote currency to spend
|
1685
|
+
if (side === 'buy') {
|
1686
|
+
let notional = this.safeNumber (params, 'notional');
|
1687
|
+
const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true);
|
1688
|
+
if (createMarketBuyOrderRequiresPrice) {
|
1689
|
+
if (price !== undefined) {
|
1690
|
+
if (notional === undefined) {
|
1691
|
+
notional = amount * price;
|
1692
|
+
}
|
1693
|
+
} else if (notional === undefined) {
|
1694
|
+
throw new InvalidOrder (this.id + " createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = false and supply the total cost value in the 'amount' argument or in the 'notional' extra parameter (the exchange-specific behaviour)");
|
1695
|
+
}
|
1696
|
+
} else {
|
1697
|
+
notional = (notional === undefined) ? amount : notional;
|
1698
|
+
}
|
1699
|
+
const precision = market['precision']['price'];
|
1700
|
+
request['notional'] = this.decimalToPrecision (notional, TRUNCATE, precision, this.precisionMode);
|
1701
|
+
} else if (side === 'sell') {
|
1702
|
+
request['size'] = this.amountToPrecision (symbol, amount);
|
1703
|
+
}
|
1704
|
+
}
|
1705
|
+
} else if (market['swap'] || market['future']) {
|
1706
|
+
method = 'privateContractPostSubmitOrder';
|
1707
|
+
request['contractID'] = market['id'];
|
1708
|
+
if (type === 'limit') {
|
1709
|
+
request['category'] = 1;
|
1710
|
+
} else if (type === 'market') {
|
1711
|
+
request['category'] = 2;
|
1712
|
+
}
|
1713
|
+
request['way'] = side; // 1 = open long, 2 = close short, 3 = close long, 4 = open short
|
1714
|
+
request['custom_id'] = this.nonce ();
|
1715
|
+
request['open_type'] = 1; // 1 = cross margin, 2 = fixed margin
|
1716
|
+
request['leverage'] = 1; // must meet the effective range of leverage configured in the contract
|
1717
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1718
|
+
request['vol'] = this.amountToPrecision (symbol, amount);
|
1719
|
+
}
|
1720
|
+
const timeInForce = this.safeString (params, 'timeInForce');
|
1721
|
+
const postOnly = this.safeValue (params, 'postOnly', false);
|
1722
|
+
if ((timeInForce !== undefined) || postOnly || (type === 'limit_maker') || (type === 'ioc')) {
|
1723
|
+
if (timeInForce === 'FOK') {
|
1724
|
+
throw new InvalidOrder (this.id + ' createOrder() only accepts timeInForce parameter values of IOC or PO');
|
1725
|
+
}
|
1726
|
+
const maker = ((timeInForce === 'PO') || postOnly || (type === 'limit_maker'));
|
1727
|
+
const ioc = ((timeInForce === 'IOC') || (type === 'ioc'));
|
1728
|
+
if (maker && ioc) {
|
1729
|
+
throw new InvalidOrder (this.id + ' createOrder() does not accept IOC postOnly orders, the order cannot be both postOnly and IOC');
|
1730
|
+
}
|
1731
|
+
if (type === 'market') {
|
1732
|
+
throw new InvalidOrder (this.id + ' createOrder() does not accept market postOnly orders or market IOC orders, only limit postOnly order or limit IOC orders are allowed');
|
1733
|
+
}
|
1734
|
+
if (maker) {
|
1735
|
+
request['type'] = 'limit_maker';
|
1736
|
+
} else if (ioc) {
|
1737
|
+
request['type'] = 'ioc';
|
1738
|
+
}
|
1739
|
+
params = this.omit (params, [ 'timeInForce', 'postOnly' ]);
|
1740
|
+
}
|
1741
|
+
const response = await this[method] (this.extend (request, params));
|
1742
|
+
//
|
1743
|
+
// spot and contract
|
1744
|
+
//
|
1745
|
+
// {
|
1746
|
+
// "code": 1000,
|
1747
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1748
|
+
// "message": "OK",
|
1749
|
+
// "data": {
|
1750
|
+
// "order_id": 2707217580
|
1751
|
+
// }
|
1752
|
+
// }
|
1753
|
+
//
|
1754
|
+
const data = this.safeValue (response, 'data', {});
|
1755
|
+
return this.parseOrder (data, market);
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
1759
|
+
if (symbol === undefined) {
|
1760
|
+
throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
|
1761
|
+
}
|
1762
|
+
await this.loadMarkets ();
|
1763
|
+
const market = this.market (symbol);
|
1764
|
+
const request = {};
|
1765
|
+
let method = undefined;
|
1766
|
+
if (market['spot']) {
|
1767
|
+
method = 'privateSpotPostCancelOrder';
|
1768
|
+
request['order_id'] = parseInt (id);
|
1769
|
+
request['symbol'] = market['id'];
|
1770
|
+
} else if (market['swap'] || market['future']) {
|
1771
|
+
method = 'privateContractPostCancelOrders';
|
1772
|
+
request['contractID'] = market['id'];
|
1773
|
+
request['orders'] = [ parseInt (id) ];
|
1774
|
+
}
|
1775
|
+
const response = await this[method] (this.extend (request, params));
|
1776
|
+
//
|
1777
|
+
// spot
|
1778
|
+
//
|
1779
|
+
// {
|
1780
|
+
// "code": 1000,
|
1781
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1782
|
+
// "message": "OK",
|
1783
|
+
// "data": {
|
1784
|
+
// "result": true
|
1785
|
+
// }
|
1786
|
+
// }
|
1787
|
+
//
|
1788
|
+
// spot alternative
|
1789
|
+
//
|
1790
|
+
// {
|
1791
|
+
// "code": 1000,
|
1792
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1793
|
+
// "message": "OK",
|
1794
|
+
// "data": true
|
1795
|
+
// }
|
1796
|
+
//
|
1797
|
+
// contract
|
1798
|
+
//
|
1799
|
+
// {
|
1800
|
+
// "code": 1000,
|
1801
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1802
|
+
// "message": "OK",
|
1803
|
+
// "data": {
|
1804
|
+
// "succeed": [
|
1805
|
+
// 2707219612
|
1806
|
+
// ],
|
1807
|
+
// "failed": []
|
1808
|
+
// }
|
1809
|
+
// }
|
1810
|
+
//
|
1811
|
+
const data = this.safeValue (response, 'data');
|
1812
|
+
if (data === true) {
|
1813
|
+
return this.parseOrder (id, market);
|
1814
|
+
}
|
1815
|
+
const succeeded = this.safeValue (data, 'succeed');
|
1816
|
+
if (succeeded !== undefined) {
|
1817
|
+
id = this.safeString (succeeded, 0);
|
1818
|
+
if (id === undefined) {
|
1819
|
+
throw new InvalidOrder (this.id + ' cancelOrder() failed to cancel ' + symbol + ' order id ' + id);
|
1820
|
+
}
|
1821
|
+
} else {
|
1822
|
+
const result = this.safeValue (data, 'result');
|
1823
|
+
if (!result) {
|
1824
|
+
throw new InvalidOrder (this.id + ' cancelOrder() ' + symbol + ' order id ' + id + ' is filled or canceled');
|
1825
|
+
}
|
1826
|
+
}
|
1827
|
+
const order = this.parseOrder (id, market);
|
1828
|
+
return this.extend (order, { 'id': id });
|
1829
|
+
}
|
1830
|
+
|
1831
|
+
async cancelAllOrders (symbol = undefined, params = {}) {
|
1832
|
+
if (symbol === undefined) {
|
1833
|
+
throw new ArgumentsRequired (this.id + ' cancelAllOrders() requires a symbol argument');
|
1834
|
+
}
|
1835
|
+
const side = this.safeString (params, 'side');
|
1836
|
+
if (side === undefined) {
|
1837
|
+
throw new ArgumentsRequired (this.id + " cancelAllOrders() requires a `side` parameter ('buy' or 'sell')");
|
1838
|
+
}
|
1839
|
+
await this.loadMarkets ();
|
1840
|
+
const market = this.market (symbol);
|
1841
|
+
if (!market['spot']) {
|
1842
|
+
throw new NotSupported (this.id + ' cancelAllOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted');
|
1843
|
+
}
|
1844
|
+
const request = {
|
1845
|
+
'symbol': market['id'],
|
1846
|
+
'side': side, // 'buy' or 'sell'
|
1847
|
+
};
|
1848
|
+
const response = await this.privateSpotPostCancelOrders (this.extend (request, params));
|
1849
|
+
//
|
1850
|
+
// {
|
1851
|
+
// "code": 1000,
|
1852
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1853
|
+
// "message": "OK",
|
1854
|
+
// "data": {}
|
1855
|
+
// }
|
1856
|
+
//
|
1857
|
+
return response;
|
1858
|
+
}
|
1859
|
+
|
1860
|
+
async cancelOrders (ids, symbol = undefined, params = {}) {
|
1861
|
+
if (symbol === undefined) {
|
1862
|
+
throw new ArgumentsRequired (this.id + ' canelOrders() requires a symbol argument');
|
1863
|
+
}
|
1864
|
+
await this.loadMarkets ();
|
1865
|
+
const market = this.market (symbol);
|
1866
|
+
if (!market['contract']) {
|
1867
|
+
throw new NotSupported (this.id + ' cancelOrders() does not support ' + market['type'] + ' orders, only contract orders are accepted');
|
1868
|
+
}
|
1869
|
+
const orders = [];
|
1870
|
+
for (let i = 0; i < ids.length; i++) {
|
1871
|
+
orders.push (parseInt (ids[i]));
|
1872
|
+
}
|
1873
|
+
const request = {
|
1874
|
+
'orders': orders,
|
1875
|
+
};
|
1876
|
+
const response = await this.privateContractPostCancelOrders (this.extend (request, params));
|
1877
|
+
//
|
1878
|
+
// spot
|
1879
|
+
//
|
1880
|
+
// {
|
1881
|
+
// "code": 1000,
|
1882
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1883
|
+
// "message": "OK",
|
1884
|
+
// "data": {
|
1885
|
+
// "result": true
|
1886
|
+
// }
|
1887
|
+
// }
|
1888
|
+
//
|
1889
|
+
// contract
|
1890
|
+
//
|
1891
|
+
// {
|
1892
|
+
// "code": 1000,
|
1893
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1894
|
+
// "message": "OK",
|
1895
|
+
// "data": {
|
1896
|
+
// "succeed": [
|
1897
|
+
// 2707219612
|
1898
|
+
// ],
|
1899
|
+
// "failed": []
|
1900
|
+
// }
|
1901
|
+
// }
|
1902
|
+
//
|
1903
|
+
return response;
|
1904
|
+
}
|
1905
|
+
|
1906
|
+
async fetchOrdersByStatus (status, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1907
|
+
if (symbol === undefined) {
|
1908
|
+
throw new ArgumentsRequired (this.id + ' fetchOrdersByStatus() requires a symbol argument');
|
1909
|
+
}
|
1910
|
+
await this.loadMarkets ();
|
1911
|
+
const market = this.market (symbol);
|
1912
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrdersByStatus', market, params);
|
1913
|
+
const request = {};
|
1914
|
+
if (market['spot']) {
|
1915
|
+
request['symbol'] = market['id'];
|
1916
|
+
request['offset'] = 1; // max offset * limit < 500
|
1917
|
+
request['limit'] = 100; // max limit is 100
|
1918
|
+
// 1 = Order failure
|
1919
|
+
// 2 = Placing order
|
1920
|
+
// 3 = Order failure, Freeze failure
|
1921
|
+
// 4 = Order success, Pending for fulfilment
|
1922
|
+
// 5 = Partially filled
|
1923
|
+
// 6 = Fully filled
|
1924
|
+
// 7 = Canceling
|
1925
|
+
// 8 = Canceled
|
1926
|
+
// 9 = Outstanding (4 and 5)
|
1927
|
+
// 10 = 6 and 8
|
1928
|
+
if (status === 'open') {
|
1929
|
+
request['status'] = 9;
|
1930
|
+
} else if (status === 'closed') {
|
1931
|
+
request['status'] = 6;
|
1932
|
+
} else if (status === 'canceled') {
|
1933
|
+
request['status'] = 8;
|
1934
|
+
} else {
|
1935
|
+
request['status'] = status;
|
1936
|
+
}
|
1937
|
+
} else if (market['swap'] || market['future']) {
|
1938
|
+
request['contractID'] = market['id'];
|
1939
|
+
// request['offset'] = 1;
|
1940
|
+
if (limit !== undefined) {
|
1941
|
+
request['size'] = limit; // max 60
|
1942
|
+
}
|
1943
|
+
// 0 = All
|
1944
|
+
// 1 = Submitting
|
1945
|
+
// 2 = Commissioned
|
1946
|
+
// 3 = 1 and 2
|
1947
|
+
// 4 = Completed
|
1948
|
+
if (status === 'open') {
|
1949
|
+
request['status'] = 3;
|
1950
|
+
} else if (status === 'closed') {
|
1951
|
+
request['status'] = 4;
|
1952
|
+
} else {
|
1953
|
+
request['status'] = status;
|
1954
|
+
}
|
1955
|
+
}
|
1956
|
+
const method = this.getSupportedMapping (marketType, {
|
1957
|
+
'spot': 'privateSpotGetOrders',
|
1958
|
+
'swap': 'privateContractGetUserOrders',
|
1959
|
+
'future': 'privateContractGetUserOrders',
|
1960
|
+
});
|
1961
|
+
const response = await this[method] (this.extend (request, query));
|
1962
|
+
//
|
1963
|
+
// spot
|
1964
|
+
//
|
1965
|
+
// {
|
1966
|
+
// "message":"OK",
|
1967
|
+
// "code":1000,
|
1968
|
+
// "trace":"70e7d427-7436-4fb8-8cdd-97e1f5eadbe9",
|
1969
|
+
// "data":{
|
1970
|
+
// "current_page":1,
|
1971
|
+
// "orders":[
|
1972
|
+
// {
|
1973
|
+
// "order_id":2147601241,
|
1974
|
+
// "symbol":"BTC_USDT",
|
1975
|
+
// "create_time":1591099963000,
|
1976
|
+
// "side":"sell",
|
1977
|
+
// "type":"limit",
|
1978
|
+
// "price":"9000.00",
|
1979
|
+
// "price_avg":"0.00",
|
1980
|
+
// "size":"1.00000",
|
1981
|
+
// "notional":"9000.00000000",
|
1982
|
+
// "filled_notional":"0.00000000",
|
1983
|
+
// "filled_size":"0.00000",
|
1984
|
+
// "status":"4"
|
1985
|
+
// }
|
1986
|
+
// ]
|
1987
|
+
// }
|
1988
|
+
// }
|
1989
|
+
//
|
1990
|
+
// contract
|
1991
|
+
//
|
1992
|
+
// {
|
1993
|
+
// "code": 1000,
|
1994
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
1995
|
+
// "message": "OK",
|
1996
|
+
// "data": {
|
1997
|
+
// "orders": [
|
1998
|
+
// {
|
1999
|
+
// "order_id": 10284160,
|
2000
|
+
// "contract_id": 1,
|
2001
|
+
// "price": "8",
|
2002
|
+
// "vol": "4",
|
2003
|
+
// "done_avg_price": "0",
|
2004
|
+
// "done_vol": "0",
|
2005
|
+
// "way": 1,
|
2006
|
+
// "category": 1,
|
2007
|
+
// "open_type": 2,
|
2008
|
+
// "make_fee": "0",
|
2009
|
+
// "take_fee": "0",
|
2010
|
+
// "origin": "",
|
2011
|
+
// "created_at": "2018-07-17T07:24:13.410507Z",
|
2012
|
+
// "finished_at": null,
|
2013
|
+
// "status": 2,
|
2014
|
+
// "errno": 0
|
2015
|
+
// }
|
2016
|
+
// ]
|
2017
|
+
// }
|
2018
|
+
// }
|
2019
|
+
//
|
2020
|
+
const data = this.safeValue (response, 'data', {});
|
2021
|
+
const orders = this.safeValue (data, 'orders', []);
|
2022
|
+
return this.parseOrders (orders, market, since, limit);
|
2023
|
+
}
|
2024
|
+
|
2025
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
2026
|
+
return await this.fetchOrdersByStatus ('open', symbol, since, limit, params);
|
2027
|
+
}
|
2028
|
+
|
2029
|
+
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
2030
|
+
return await this.fetchOrdersByStatus ('closed', symbol, since, limit, params);
|
2031
|
+
}
|
2032
|
+
|
2033
|
+
async fetchCanceledOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
2034
|
+
return await this.fetchOrdersByStatus ('canceled', symbol, since, limit, params);
|
2035
|
+
}
|
2036
|
+
|
2037
|
+
async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
2038
|
+
if (symbol === undefined) {
|
2039
|
+
throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
|
2040
|
+
}
|
2041
|
+
await this.loadMarkets ();
|
2042
|
+
const market = this.market (symbol);
|
2043
|
+
if (!(market['swap'] || market['future'])) {
|
2044
|
+
throw new NotSupported (this.id + ' fetchOrders() does not support ' + market['type'] + ' markets, only contracts are supported');
|
2045
|
+
}
|
2046
|
+
return await this.fetchOrdersByStatus (0, symbol, since, limit, params);
|
2047
|
+
}
|
2048
|
+
|
2049
|
+
async fetchOrder (id, symbol = undefined, params = {}) {
|
2050
|
+
if (symbol === undefined) {
|
2051
|
+
throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument');
|
2052
|
+
}
|
2053
|
+
await this.loadMarkets ();
|
2054
|
+
const request = {};
|
2055
|
+
const market = this.market (symbol);
|
2056
|
+
if (typeof id !== 'string') {
|
2057
|
+
id = id.toString ();
|
2058
|
+
}
|
2059
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrder', market, params);
|
2060
|
+
if (market['spot']) {
|
2061
|
+
request['symbol'] = market['id'];
|
2062
|
+
request['order_id'] = id;
|
2063
|
+
} else if (market['swap'] || market['future']) {
|
2064
|
+
request['contractID'] = market['id'];
|
2065
|
+
request['orderID'] = id;
|
2066
|
+
}
|
2067
|
+
const method = this.getSupportedMapping (marketType, {
|
2068
|
+
'spot': 'privateSpotGetOrderDetail',
|
2069
|
+
'swap': 'privateContractGetUserOrderInfo',
|
2070
|
+
'future': 'privateContractGetUserOrderInfo',
|
2071
|
+
});
|
2072
|
+
const response = await this[method] (this.extend (request, query));
|
2073
|
+
//
|
2074
|
+
// spot
|
2075
|
+
//
|
2076
|
+
// {
|
2077
|
+
// "message":"OK",
|
2078
|
+
// "code":1000,
|
2079
|
+
// "trace":"a27c2cb5-ead4-471d-8455-1cfeda054ea6",
|
2080
|
+
// "data": {
|
2081
|
+
// "order_id":1736871726781,
|
2082
|
+
// "symbol":"BTC_USDT",
|
2083
|
+
// "create_time":1591096004000,
|
2084
|
+
// "side":"sell",
|
2085
|
+
// "type":"market",
|
2086
|
+
// "price":"0.00",
|
2087
|
+
// "price_avg":"0.00",
|
2088
|
+
// "size":"0.02000",
|
2089
|
+
// "notional":"0.00000000",
|
2090
|
+
// "filled_notional":"0.00000000",
|
2091
|
+
// "filled_size":"0.00000",
|
2092
|
+
// "status":"8"
|
2093
|
+
// }
|
2094
|
+
// }
|
2095
|
+
//
|
2096
|
+
// contract
|
2097
|
+
//
|
2098
|
+
// {
|
2099
|
+
// "code": 1000,
|
2100
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
2101
|
+
// "message": "OK",
|
2102
|
+
// "data": {
|
2103
|
+
// "orders": [
|
2104
|
+
// {
|
2105
|
+
// "order_id": 10539098,
|
2106
|
+
// "contract_id": 1,
|
2107
|
+
// "position_id": 10539088,
|
2108
|
+
// "account_id": 10,
|
2109
|
+
// "price": "16",
|
2110
|
+
// "vol": "1",
|
2111
|
+
// "done_avg_price": "16",
|
2112
|
+
// "done_vol": "1",
|
2113
|
+
// "way": 3,
|
2114
|
+
// "category": 1,
|
2115
|
+
// "make_fee": "0.00025",
|
2116
|
+
// "take_fee": "0.012",
|
2117
|
+
// "origin": "",
|
2118
|
+
// "created_at": "2018-07-23T11:55:56.715305Z",
|
2119
|
+
// "finished_at": "2018-07-23T11:55:56.763941Z",
|
2120
|
+
// "status": 4,
|
2121
|
+
// "errno": 0
|
2122
|
+
// }
|
2123
|
+
// ]
|
2124
|
+
// }
|
2125
|
+
// }
|
2126
|
+
//
|
2127
|
+
const data = this.safeValue (response, 'data');
|
2128
|
+
if ('orders' in data) {
|
2129
|
+
const orders = this.safeValue (data, 'orders', []);
|
2130
|
+
const firstOrder = this.safeValue (orders, 0);
|
2131
|
+
if (firstOrder === undefined) {
|
2132
|
+
throw new OrderNotFound (this.id + ' fetchOrder() could not find ' + symbol + ' order id ' + id);
|
2133
|
+
}
|
2134
|
+
return this.parseOrder (firstOrder, market);
|
2135
|
+
} else {
|
2136
|
+
return this.parseOrder (data, market);
|
2137
|
+
}
|
2138
|
+
}
|
2139
|
+
|
2140
|
+
async fetchDepositAddress (code, params = {}) {
|
2141
|
+
await this.loadMarkets ();
|
2142
|
+
const currency = this.currency (code);
|
2143
|
+
const request = {
|
2144
|
+
'currency': currency['id'],
|
2145
|
+
};
|
2146
|
+
if (code === 'USDT') {
|
2147
|
+
const defaultNetworks = this.safeValue (this.options, 'defaultNetworks');
|
2148
|
+
const defaultNetwork = this.safeStringUpper (defaultNetworks, code);
|
2149
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
2150
|
+
let network = this.safeStringUpper (params, 'network', defaultNetwork); // this line allows the user to specify either ERC20 or ETH
|
2151
|
+
network = this.safeString (networks, network, network); // handle ERC20>ETH alias
|
2152
|
+
if (network !== undefined) {
|
2153
|
+
request['currency'] += '-' + network; // when network the currency need to be changed to currency + '-' + network https://developer-pro.bitmart.com/en/account/withdraw_apply.html on the end of page
|
2154
|
+
params = this.omit (params, 'network');
|
2155
|
+
}
|
2156
|
+
}
|
2157
|
+
const response = await this.privateAccountGetDepositAddress (this.extend (request, params));
|
2158
|
+
//
|
2159
|
+
// {
|
2160
|
+
// "message":"OK",
|
2161
|
+
// "code":1000,
|
2162
|
+
// "trace":"0e6edd79-f77f-4251-abe5-83ba75d06c1a",
|
2163
|
+
// "data":{
|
2164
|
+
// "currency":"USDT-TRC20",
|
2165
|
+
// "chain":"USDT-TRC20",
|
2166
|
+
// "address":"TGR3ghy2b5VLbyAYrmiE15jasR6aPHTvC5",
|
2167
|
+
// "address_memo":""
|
2168
|
+
// }
|
2169
|
+
// }
|
2170
|
+
//
|
2171
|
+
const data = this.safeValue (response, 'data', {});
|
2172
|
+
const address = this.safeString (data, 'address');
|
2173
|
+
const tag = this.safeString (data, 'address_memo');
|
2174
|
+
const chain = this.safeString (data, 'chain');
|
2175
|
+
let network = undefined;
|
2176
|
+
if (chain !== undefined) {
|
2177
|
+
const parts = chain.split ('-');
|
2178
|
+
const networkId = this.safeString (parts, 1);
|
2179
|
+
network = this.safeNetwork (networkId);
|
2180
|
+
}
|
2181
|
+
this.checkAddress (address);
|
2182
|
+
return {
|
2183
|
+
'currency': code,
|
2184
|
+
'address': address,
|
2185
|
+
'tag': tag,
|
2186
|
+
'network': network,
|
2187
|
+
'info': response,
|
2188
|
+
};
|
2189
|
+
}
|
2190
|
+
|
2191
|
+
safeNetwork (networkId) {
|
2192
|
+
// TODO: parse
|
2193
|
+
return networkId;
|
2194
|
+
}
|
2195
|
+
|
2196
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
2197
|
+
[ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
|
2198
|
+
this.checkAddress (address);
|
2199
|
+
await this.loadMarkets ();
|
2200
|
+
const currency = this.currency (code);
|
2201
|
+
const request = {
|
2202
|
+
'currency': currency['id'],
|
2203
|
+
'amount': amount,
|
2204
|
+
'destination': 'To Digital Address', // To Digital Address, To Binance, To OKEX
|
2205
|
+
'address': address,
|
2206
|
+
};
|
2207
|
+
if (tag !== undefined) {
|
2208
|
+
request['address_memo'] = tag;
|
2209
|
+
}
|
2210
|
+
if (code === 'USDT') {
|
2211
|
+
const defaultNetworks = this.safeValue (this.options, 'defaultNetworks');
|
2212
|
+
const defaultNetwork = this.safeStringUpper (defaultNetworks, code);
|
2213
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
2214
|
+
let network = this.safeStringUpper (params, 'network', defaultNetwork); // this line allows the user to specify either ERC20 or ETH
|
2215
|
+
network = this.safeString (networks, network, network); // handle ERC20>ETH alias
|
2216
|
+
if (network !== undefined) {
|
2217
|
+
request['currency'] += '-' + network; // when network the currency need to be changed to currency + '-' + network https://developer-pro.bitmart.com/en/account/withdraw_apply.html on the end of page
|
2218
|
+
params = this.omit (params, 'network');
|
2219
|
+
}
|
2220
|
+
}
|
2221
|
+
const response = await this.privateAccountPostWithdrawApply (this.extend (request, params));
|
2222
|
+
//
|
2223
|
+
// {
|
2224
|
+
// "code": 1000,
|
2225
|
+
// "trace":"886fb6ae-456b-4654-b4e0-d681ac05cea1",
|
2226
|
+
// "message": "OK",
|
2227
|
+
// "data": {
|
2228
|
+
// "withdraw_id": "121212"
|
2229
|
+
// }
|
2230
|
+
// }
|
2231
|
+
//
|
2232
|
+
const data = this.safeValue (response, 'data');
|
2233
|
+
const transaction = this.parseTransaction (data, currency);
|
2234
|
+
return this.extend (transaction, {
|
2235
|
+
'code': code,
|
2236
|
+
'address': address,
|
2237
|
+
'tag': tag,
|
2238
|
+
});
|
2239
|
+
}
|
2240
|
+
|
2241
|
+
async fetchTransactionsByType (type, code = undefined, since = undefined, limit = undefined, params = {}) {
|
2242
|
+
await this.loadMarkets ();
|
2243
|
+
if (limit === undefined) {
|
2244
|
+
limit = 50; // max 50
|
2245
|
+
}
|
2246
|
+
const request = {
|
2247
|
+
'operation_type': type, // deposit or withdraw
|
2248
|
+
'offset': 1,
|
2249
|
+
'limit': limit,
|
2250
|
+
};
|
2251
|
+
let currency = undefined;
|
2252
|
+
if (code !== undefined) {
|
2253
|
+
currency = this.currency (code);
|
2254
|
+
request['currency'] = currency['id'];
|
2255
|
+
}
|
2256
|
+
const response = await this.privateAccountGetDepositWithdrawHistory (this.extend (request, params));
|
2257
|
+
//
|
2258
|
+
// {
|
2259
|
+
// "message":"OK",
|
2260
|
+
// "code":1000,
|
2261
|
+
// "trace":"142bf92a-fc50-4689-92b6-590886f90b97",
|
2262
|
+
// "data":{
|
2263
|
+
// "records":[
|
2264
|
+
// {
|
2265
|
+
// "withdraw_id":"1679952",
|
2266
|
+
// "deposit_id":"",
|
2267
|
+
// "operation_type":"withdraw",
|
2268
|
+
// "currency":"BMX",
|
2269
|
+
// "apply_time":1588867374000,
|
2270
|
+
// "arrival_amount":"59.000000000000",
|
2271
|
+
// "fee":"1.000000000000",
|
2272
|
+
// "status":0,
|
2273
|
+
// "address":"0xe57b69a8776b37860407965B73cdFFBDFe668Bb5",
|
2274
|
+
// "address_memo":"",
|
2275
|
+
// "tx_id":""
|
2276
|
+
// },
|
2277
|
+
// ]
|
2278
|
+
// }
|
2279
|
+
// }
|
2280
|
+
//
|
2281
|
+
const data = this.safeValue (response, 'data', {});
|
2282
|
+
const records = this.safeValue (data, 'records', []);
|
2283
|
+
return this.parseTransactions (records, currency, since, limit);
|
2284
|
+
}
|
2285
|
+
|
2286
|
+
async fetchDeposit (id, code = undefined, params = {}) {
|
2287
|
+
await this.loadMarkets ();
|
2288
|
+
const request = {
|
2289
|
+
'id': id,
|
2290
|
+
};
|
2291
|
+
const response = await this.privateAccountGetDepositWithdrawDetail (this.extend (request, params));
|
2292
|
+
//
|
2293
|
+
// {
|
2294
|
+
// "message":"OK",
|
2295
|
+
// "code":1000,
|
2296
|
+
// "trace":"f7f74924-14da-42a6-b7f2-d3799dd9a612",
|
2297
|
+
// "data":{
|
2298
|
+
// "record":{
|
2299
|
+
// "withdraw_id":"",
|
2300
|
+
// "deposit_id":"1679952",
|
2301
|
+
// "operation_type":"deposit",
|
2302
|
+
// "currency":"BMX",
|
2303
|
+
// "apply_time":1588867374000,
|
2304
|
+
// "arrival_amount":"59.000000000000",
|
2305
|
+
// "fee":"1.000000000000",
|
2306
|
+
// "status":0,
|
2307
|
+
// "address":"0xe57b69a8776b37860407965B73cdFFBDFe668Bb5",
|
2308
|
+
// "address_memo":"",
|
2309
|
+
// "tx_id":""
|
2310
|
+
// }
|
2311
|
+
// }
|
2312
|
+
// }
|
2313
|
+
//
|
2314
|
+
const data = this.safeValue (response, 'data', {});
|
2315
|
+
const record = this.safeValue (data, 'record', {});
|
2316
|
+
return this.parseTransaction (record);
|
2317
|
+
}
|
2318
|
+
|
2319
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
2320
|
+
return await this.fetchTransactionsByType ('deposit', code, since, limit, params);
|
2321
|
+
}
|
2322
|
+
|
2323
|
+
async fetchWithdrawal (id, code = undefined, params = {}) {
|
2324
|
+
await this.loadMarkets ();
|
2325
|
+
const request = {
|
2326
|
+
'id': id,
|
2327
|
+
};
|
2328
|
+
const response = await this.privateAccountGetDepositWithdrawDetail (this.extend (request, params));
|
2329
|
+
//
|
2330
|
+
// {
|
2331
|
+
// "message":"OK",
|
2332
|
+
// "code":1000,
|
2333
|
+
// "trace":"f7f74924-14da-42a6-b7f2-d3799dd9a612",
|
2334
|
+
// "data":{
|
2335
|
+
// "record":{
|
2336
|
+
// "withdraw_id":"1679952",
|
2337
|
+
// "deposit_id":"",
|
2338
|
+
// "operation_type":"withdraw",
|
2339
|
+
// "currency":"BMX",
|
2340
|
+
// "apply_time":1588867374000,
|
2341
|
+
// "arrival_amount":"59.000000000000",
|
2342
|
+
// "fee":"1.000000000000",
|
2343
|
+
// "status":0,
|
2344
|
+
// "address":"0xe57b69a8776b37860407965B73cdFFBDFe668Bb5",
|
2345
|
+
// "address_memo":"",
|
2346
|
+
// "tx_id":""
|
2347
|
+
// }
|
2348
|
+
// }
|
2349
|
+
// }
|
2350
|
+
//
|
2351
|
+
const data = this.safeValue (response, 'data', {});
|
2352
|
+
const record = this.safeValue (data, 'record', {});
|
2353
|
+
return this.parseTransaction (record);
|
2354
|
+
}
|
2355
|
+
|
2356
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
2357
|
+
return await this.fetchTransactionsByType ('withdraw', code, since, limit, params);
|
2358
|
+
}
|
2359
|
+
|
2360
|
+
parseTransactionStatus (status) {
|
2361
|
+
const statuses = {
|
2362
|
+
'0': 'pending', // Create
|
2363
|
+
'1': 'pending', // Submitted, waiting for withdrawal
|
2364
|
+
'2': 'pending', // Processing
|
2365
|
+
'3': 'ok', // Success
|
2366
|
+
'4': 'canceled', // Cancel
|
2367
|
+
'5': 'failed', // Fail
|
2368
|
+
};
|
2369
|
+
return this.safeString (statuses, status, status);
|
2370
|
+
}
|
2371
|
+
|
2372
|
+
parseTransaction (transaction, currency = undefined) {
|
2373
|
+
//
|
2374
|
+
// withdraw
|
2375
|
+
//
|
2376
|
+
// {
|
2377
|
+
// "withdraw_id": "121212"
|
2378
|
+
// }
|
2379
|
+
//
|
2380
|
+
// fetchDeposits, fetchWithdrawals, fetchWithdrawal
|
2381
|
+
//
|
2382
|
+
// {
|
2383
|
+
// "withdraw_id":"1679952",
|
2384
|
+
// "deposit_id":"",
|
2385
|
+
// "operation_type":"withdraw",
|
2386
|
+
// "currency":"BMX",
|
2387
|
+
// "apply_time":1588867374000,
|
2388
|
+
// "arrival_amount":"59.000000000000",
|
2389
|
+
// "fee":"1.000000000000",
|
2390
|
+
// "status":0,
|
2391
|
+
// "address":"0xe57b69a8776b37860407965B73cdFFBDFe668Bb5",
|
2392
|
+
// "address_memo":"",
|
2393
|
+
// "tx_id":""
|
2394
|
+
// }
|
2395
|
+
//
|
2396
|
+
let id = undefined;
|
2397
|
+
const withdrawId = this.safeString (transaction, 'withdraw_id');
|
2398
|
+
const depositId = this.safeString (transaction, 'deposit_id');
|
2399
|
+
let type = undefined;
|
2400
|
+
if ((withdrawId !== undefined) && (withdrawId !== '')) {
|
2401
|
+
type = 'withdraw';
|
2402
|
+
id = withdrawId;
|
2403
|
+
} else if ((depositId !== undefined) && (depositId !== '')) {
|
2404
|
+
type = 'deposit';
|
2405
|
+
id = depositId;
|
2406
|
+
}
|
2407
|
+
const amount = this.safeNumber (transaction, 'arrival_amount');
|
2408
|
+
const timestamp = this.safeInteger (transaction, 'apply_time');
|
2409
|
+
const currencyId = this.safeString (transaction, 'currency');
|
2410
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
2411
|
+
const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
|
2412
|
+
const feeCost = this.safeNumber (transaction, 'fee');
|
2413
|
+
let fee = undefined;
|
2414
|
+
if (feeCost !== undefined) {
|
2415
|
+
fee = {
|
2416
|
+
'cost': feeCost,
|
2417
|
+
'currency': code,
|
2418
|
+
};
|
2419
|
+
}
|
2420
|
+
let txid = this.safeString (transaction, 'tx_id');
|
2421
|
+
if (txid === '') {
|
2422
|
+
txid = undefined;
|
2423
|
+
}
|
2424
|
+
const address = this.safeString (transaction, 'address');
|
2425
|
+
const tag = this.safeString (transaction, 'address_memo');
|
2426
|
+
return {
|
2427
|
+
'info': transaction,
|
2428
|
+
'id': id,
|
2429
|
+
'currency': code,
|
2430
|
+
'amount': amount,
|
2431
|
+
'network': undefined,
|
2432
|
+
'address': address,
|
2433
|
+
'addressFrom': undefined,
|
2434
|
+
'addressTo': undefined,
|
2435
|
+
'tag': tag,
|
2436
|
+
'tagFrom': undefined,
|
2437
|
+
'tagTo': undefined,
|
2438
|
+
'status': status,
|
2439
|
+
'type': type,
|
2440
|
+
'updated': undefined,
|
2441
|
+
'txid': txid,
|
2442
|
+
'timestamp': timestamp,
|
2443
|
+
'datetime': this.iso8601 (timestamp),
|
2444
|
+
'fee': fee,
|
2445
|
+
};
|
2446
|
+
}
|
2447
|
+
|
2448
|
+
nonce () {
|
2449
|
+
return this.milliseconds ();
|
2450
|
+
}
|
2451
|
+
|
2452
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
2453
|
+
const access = this.safeString (api, 0);
|
2454
|
+
const type = this.safeString (api, 1);
|
2455
|
+
const baseUrl = this.implodeHostname (this.urls['api']['rest']);
|
2456
|
+
let url = baseUrl + '/' + type;
|
2457
|
+
if (type !== 'system') {
|
2458
|
+
url += '/' + this.version;
|
2459
|
+
}
|
2460
|
+
url += '/' + this.implodeParams (path, params);
|
2461
|
+
const query = this.omit (params, this.extractParams (path));
|
2462
|
+
let queryString = '';
|
2463
|
+
const getOrDelete = (method === 'GET') || (method === 'DELETE');
|
2464
|
+
if (getOrDelete) {
|
2465
|
+
if (Object.keys (query).length) {
|
2466
|
+
queryString = this.urlencode (query);
|
2467
|
+
url += '?' + queryString;
|
2468
|
+
}
|
2469
|
+
}
|
2470
|
+
if (access === 'private') {
|
2471
|
+
this.checkRequiredCredentials ();
|
2472
|
+
const timestamp = this.milliseconds ().toString ();
|
2473
|
+
headers = {
|
2474
|
+
'X-BM-KEY': this.apiKey,
|
2475
|
+
'X-BM-TIMESTAMP': timestamp,
|
2476
|
+
'Content-Type': 'application/json',
|
2477
|
+
};
|
2478
|
+
if (!getOrDelete) {
|
2479
|
+
body = this.json (query);
|
2480
|
+
queryString = body;
|
2481
|
+
}
|
2482
|
+
const auth = timestamp + '#' + this.uid + '#' + queryString;
|
2483
|
+
const signature = this.hmac (this.encode (auth), this.encode (this.secret));
|
2484
|
+
headers['X-BM-SIGN'] = signature;
|
2485
|
+
}
|
2486
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
2487
|
+
}
|
2488
|
+
|
2489
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
2490
|
+
if (response === undefined) {
|
2491
|
+
return;
|
2492
|
+
}
|
2493
|
+
//
|
2494
|
+
// spot
|
2495
|
+
//
|
2496
|
+
// {"message":"Bad Request [to is empty]","code":50000,"trace":"f9d46e1b-4edb-4d07-a06e-4895fb2fc8fc","data":{}}
|
2497
|
+
// {"message":"Bad Request [from is empty]","code":50000,"trace":"579986f7-c93a-4559-926b-06ba9fa79d76","data":{}}
|
2498
|
+
// {"message":"Kline size over 500","code":50004,"trace":"d625caa8-e8ca-4bd2-b77c-958776965819","data":{}}
|
2499
|
+
// {"message":"Balance not enough","code":50020,"trace":"7c709d6a-3292-462c-98c5-32362540aeef","data":{}}
|
2500
|
+
//
|
2501
|
+
// contract
|
2502
|
+
//
|
2503
|
+
// {"errno":"OK","message":"INVALID_PARAMETER","code":49998,"trace":"eb5ebb54-23cd-4de2-9064-e090b6c3b2e3","data":null}
|
2504
|
+
//
|
2505
|
+
const message = this.safeString (response, 'message');
|
2506
|
+
const errorCode = this.safeString (response, 'code');
|
2507
|
+
if (((errorCode !== undefined) && (errorCode !== '1000')) || ((message !== undefined) && (message !== 'OK'))) {
|
2508
|
+
const feedback = this.id + ' ' + body;
|
2509
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
|
2510
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], errorCode, feedback);
|
2511
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
|
2512
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
|
2513
|
+
throw new ExchangeError (feedback); // unknown message
|
2514
|
+
}
|
2515
|
+
}
|
2516
|
+
};
|