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/kucoin.js
ADDED
@@ -0,0 +1,2571 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { ExchangeError, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, InvalidNonce, NotSupported, BadRequest, AuthenticationError, BadSymbol, RateLimitExceeded, PermissionDenied, InvalidAddress } = require ('./base/errors');
|
7
|
+
const Precise = require ('./base/Precise');
|
8
|
+
|
9
|
+
// ---------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = class kucoin extends Exchange {
|
12
|
+
describe () {
|
13
|
+
return this.deepExtend (super.describe (), {
|
14
|
+
'id': 'kucoin',
|
15
|
+
'name': 'KuCoin',
|
16
|
+
'countries': [ 'SC' ],
|
17
|
+
// note "only some endpoints are rate-limited"
|
18
|
+
// so I set the 'ratelimit' on those which supposedly 'arent ratelimited'
|
19
|
+
// to the limit of the cheapest endpoint
|
20
|
+
// 60 requests in 3 seconds = 20 requests per second => ( 1000ms / 20 ) = 50 ms between requests on average
|
21
|
+
'rateLimit': 50,
|
22
|
+
'version': 'v2',
|
23
|
+
'certified': false,
|
24
|
+
'pro': true,
|
25
|
+
'comment': 'Platform 2.0',
|
26
|
+
'quoteJsonNumbers': false,
|
27
|
+
'has': {
|
28
|
+
'CORS': undefined,
|
29
|
+
'spot': true,
|
30
|
+
'margin': undefined,
|
31
|
+
'swap': false,
|
32
|
+
'future': false,
|
33
|
+
'option': undefined,
|
34
|
+
'cancelAllOrders': true,
|
35
|
+
'cancelOrder': true,
|
36
|
+
'createDepositAddress': true,
|
37
|
+
'createOrder': true,
|
38
|
+
'createStopLimitOrder': true,
|
39
|
+
'createStopMarketOrder': true,
|
40
|
+
'createStopOrder': true,
|
41
|
+
'fetchAccounts': true,
|
42
|
+
'fetchBalance': true,
|
43
|
+
'fetchBorrowRate': false,
|
44
|
+
'fetchBorrowRates': false,
|
45
|
+
'fetchClosedOrders': true,
|
46
|
+
'fetchCurrencies': true,
|
47
|
+
'fetchDepositAddress': true,
|
48
|
+
'fetchDeposits': true,
|
49
|
+
'fetchFundingFee': true,
|
50
|
+
'fetchFundingHistory': false,
|
51
|
+
'fetchFundingRate': false,
|
52
|
+
'fetchFundingRateHistory': false,
|
53
|
+
'fetchFundingRates': false,
|
54
|
+
'fetchIndexOHLCV': false,
|
55
|
+
'fetchL3OrderBook': true,
|
56
|
+
'fetchLedger': true,
|
57
|
+
'fetchMarkets': true,
|
58
|
+
'fetchMarkOHLCV': false,
|
59
|
+
'fetchMyTrades': true,
|
60
|
+
'fetchOHLCV': true,
|
61
|
+
'fetchOpenOrders': true,
|
62
|
+
'fetchOrder': true,
|
63
|
+
'fetchOrderBook': true,
|
64
|
+
'fetchOrdersByStatus': true,
|
65
|
+
'fetchPremiumIndexOHLCV': false,
|
66
|
+
'fetchStatus': true,
|
67
|
+
'fetchTicker': true,
|
68
|
+
'fetchTickers': true,
|
69
|
+
'fetchTime': true,
|
70
|
+
'fetchTrades': true,
|
71
|
+
'fetchTradingFee': true,
|
72
|
+
'fetchTradingFees': false,
|
73
|
+
'fetchWithdrawals': true,
|
74
|
+
'transfer': true,
|
75
|
+
'withdraw': true,
|
76
|
+
},
|
77
|
+
'urls': {
|
78
|
+
'logo': 'https://user-images.githubusercontent.com/51840849/87295558-132aaf80-c50e-11ea-9801-a2fb0c57c799.jpg',
|
79
|
+
'referral': 'https://www.kucoin.com/?rcode=E5wkqe',
|
80
|
+
'api': {
|
81
|
+
'public': 'https://api.kucoin.com',
|
82
|
+
'private': 'https://api.kucoin.com',
|
83
|
+
'futuresPrivate': 'https://api-futures.kucoin.com',
|
84
|
+
'futuresPublic': 'https://api-futures.kucoin.com',
|
85
|
+
},
|
86
|
+
'test': {
|
87
|
+
'public': 'https://openapi-sandbox.kucoin.com',
|
88
|
+
'private': 'https://openapi-sandbox.kucoin.com',
|
89
|
+
'futuresPrivate': 'https://api-sandbox-futures.kucoin.com',
|
90
|
+
'futuresPublic': 'https://api-sandbox-futures.kucoin.com',
|
91
|
+
},
|
92
|
+
'www': 'https://www.kucoin.com',
|
93
|
+
'doc': [
|
94
|
+
'https://docs.kucoin.com',
|
95
|
+
],
|
96
|
+
},
|
97
|
+
'requiredCredentials': {
|
98
|
+
'apiKey': true,
|
99
|
+
'secret': true,
|
100
|
+
'password': true,
|
101
|
+
},
|
102
|
+
'api': {
|
103
|
+
'public': {
|
104
|
+
'get': {
|
105
|
+
'timestamp': 1,
|
106
|
+
'status': 1,
|
107
|
+
'symbols': 1,
|
108
|
+
'markets': 1,
|
109
|
+
'market/allTickers': 1,
|
110
|
+
'market/orderbook/level{level}_{limit}': 1,
|
111
|
+
'market/orderbook/level2_20': 1,
|
112
|
+
'market/orderbook/level2_100': 1,
|
113
|
+
'market/histories': 1,
|
114
|
+
'market/candles': 1,
|
115
|
+
'market/stats': 1,
|
116
|
+
'currencies': 1,
|
117
|
+
'currencies/{currency}': 1,
|
118
|
+
'prices': 1,
|
119
|
+
'mark-price/{symbol}/current': 1,
|
120
|
+
'margin/config': 1,
|
121
|
+
},
|
122
|
+
'post': {
|
123
|
+
'bullet-public': 1,
|
124
|
+
},
|
125
|
+
},
|
126
|
+
'private': {
|
127
|
+
'get': {
|
128
|
+
'market/orderbook/level{level}': 1,
|
129
|
+
'market/orderbook/level2': { 'v3': 2 }, // 30/3s = 10/s => cost = 20 / 10 = 2
|
130
|
+
'market/orderbook/level3': 1,
|
131
|
+
'accounts': 1,
|
132
|
+
'accounts/{accountId}': 1,
|
133
|
+
// 'accounts/{accountId}/ledgers': 1, Deprecated endpoint
|
134
|
+
'accounts/ledgers': 3.333, // 18/3s = 6/s => cost = 20 / 6 = 3.333
|
135
|
+
'accounts/{accountId}/holds': 1,
|
136
|
+
'accounts/transferable': 1,
|
137
|
+
'base-fee': 1,
|
138
|
+
'sub/user': 1,
|
139
|
+
'sub-accounts': 1,
|
140
|
+
'sub-accounts/{subUserId}': 1,
|
141
|
+
'deposit-addresses': 1,
|
142
|
+
'deposits': 10, // 6/3s = 2/s => cost = 20 / 2 = 10
|
143
|
+
'hist-deposits': 10, // 6/3 = 2/s => cost = 20 / 2 = 10
|
144
|
+
'hist-orders': 1,
|
145
|
+
'hist-withdrawals': 10, // 6/3 = 2/s => cost = 20 / 2 = 10
|
146
|
+
'withdrawals': 10, // 6/3 = 2/s => cost = 20 / 2 = 10
|
147
|
+
'withdrawals/quotas': 1,
|
148
|
+
'orders': 2, // 30/3s = 10/s => cost = 20 / 10 = 2
|
149
|
+
'order/client-order/{clientOid}': 1,
|
150
|
+
'orders/{orderId}': 1,
|
151
|
+
'limit/orders': 1,
|
152
|
+
'fills': 6.66667, // 9/3s = 3/s => cost = 20 / 3 = 6.666667
|
153
|
+
'limit/fills': 1,
|
154
|
+
'margin/account': 1,
|
155
|
+
'margin/borrow': 1,
|
156
|
+
'margin/borrow/outstanding': 1,
|
157
|
+
'margin/borrow/borrow/repaid': 1,
|
158
|
+
'margin/lend/active': 1,
|
159
|
+
'margin/lend/done': 1,
|
160
|
+
'margin/lend/trade/unsettled': 1,
|
161
|
+
'margin/lend/trade/settled': 1,
|
162
|
+
'margin/lend/assets': 1,
|
163
|
+
'margin/market': 1,
|
164
|
+
'margin/trade/last': 1,
|
165
|
+
'stop-order/{orderId}': 1,
|
166
|
+
'stop-order': 1,
|
167
|
+
'stop-order/queryOrderByClientOid': 1,
|
168
|
+
'trade-fees': 1.3333, // 45/3s = 15/s => cost = 20 / 15 = 1.333
|
169
|
+
},
|
170
|
+
'post': {
|
171
|
+
'accounts': 1,
|
172
|
+
'accounts/inner-transfer': { 'v2': 1 },
|
173
|
+
'accounts/sub-transfer': { 'v2': 25 }, // bad docs
|
174
|
+
'deposit-addresses': 1,
|
175
|
+
'withdrawals': 1,
|
176
|
+
'orders': 4, // 45/3s = 15/s => cost = 20 / 15 = 1.333333
|
177
|
+
'orders/multi': 20, // 3/3s = 1/s => cost = 20 / 1 = 20
|
178
|
+
'margin/borrow': 1,
|
179
|
+
'margin/order': 1,
|
180
|
+
'margin/repay/all': 1,
|
181
|
+
'margin/repay/single': 1,
|
182
|
+
'margin/lend': 1,
|
183
|
+
'margin/toggle-auto-lend': 1,
|
184
|
+
'bullet-private': 1,
|
185
|
+
'stop-order': 1,
|
186
|
+
},
|
187
|
+
'delete': {
|
188
|
+
'withdrawals/{withdrawalId}': 1,
|
189
|
+
'orders': 20, // 3/3s = 1/s => cost = 20/1
|
190
|
+
'orders/client-order/{clientOid}': 1,
|
191
|
+
'orders/{orderId}': 1, // rateLimit: 60/3s = 20/s => cost = 1
|
192
|
+
'margin/lend/{orderId}': 1,
|
193
|
+
'stop-order/cancelOrderByClientOid': 1,
|
194
|
+
'stop-order/{orderId}': 1,
|
195
|
+
'stop-order/cancel': 1,
|
196
|
+
},
|
197
|
+
},
|
198
|
+
'futuresPublic': {
|
199
|
+
// cheapest futures 'limited' endpoint is 40 requests per 3 seconds = 14.333 per second => cost = 20/14.333 = 1.3953
|
200
|
+
'get': {
|
201
|
+
'contracts/active': 1.3953,
|
202
|
+
'contracts/{symbol}': 1.3953,
|
203
|
+
'ticker': 1.3953,
|
204
|
+
'level2/snapshot': 2, // 30 requests per 3 seconds = 10 requests per second => cost = 20/10 = 2
|
205
|
+
'level2/depth20': 1.3953,
|
206
|
+
'level2/depth100': 1.3953,
|
207
|
+
'level2/message/query': 1.3953,
|
208
|
+
'level3/message/query': 1.3953, // deprecated,level3/snapshot is suggested
|
209
|
+
'level3/snapshot': 1.3953, // v2
|
210
|
+
'trade/history': 1.3953,
|
211
|
+
'interest/query': 1.3953,
|
212
|
+
'index/query': 1.3953,
|
213
|
+
'mark-price/{symbol}/current': 1.3953,
|
214
|
+
'premium/query': 1.3953,
|
215
|
+
'funding-rate/{symbol}/current': 1.3953,
|
216
|
+
'timestamp': 1.3953,
|
217
|
+
'status': 1.3953,
|
218
|
+
'kline/query': 1.3953,
|
219
|
+
},
|
220
|
+
'post': {
|
221
|
+
'bullet-public': 1.3953,
|
222
|
+
},
|
223
|
+
},
|
224
|
+
'futuresPrivate': {
|
225
|
+
'get': {
|
226
|
+
'account-overview': 2, // 30 requests per 3 seconds = 10 per second => cost = 20/10 = 2
|
227
|
+
'transaction-history': 6.666, // 9 requests per 3 seconds = 3 per second => cost = 20/3 = 6.666
|
228
|
+
'deposit-address': 1.3953,
|
229
|
+
'deposit-list': 1.3953,
|
230
|
+
'withdrawals/quotas': 1.3953,
|
231
|
+
'withdrawal-list': 1.3953,
|
232
|
+
'transfer-list': 1.3953,
|
233
|
+
'orders': 1.3953,
|
234
|
+
'stopOrders': 1.3953,
|
235
|
+
'recentDoneOrders': 1.3953,
|
236
|
+
'orders/{order-id}': 1.3953, // ?clientOid={client-order-id} // get order by orderId
|
237
|
+
'orders/byClientOid': 1.3953, // ?clientOid=eresc138b21023a909e5ad59 // get order by clientOid
|
238
|
+
'fills': 6.666, // 9 requests per 3 seconds = 3 per second => cost = 20/3 = 6.666
|
239
|
+
'recentFills': 6.666, // 9 requests per 3 seconds = 3 per second => cost = 20/3 = 6.666
|
240
|
+
'openOrderStatistics': 1.3953,
|
241
|
+
'position': 1.3953,
|
242
|
+
'positions': 6.666, // 9 requests per 3 seconds = 3 per second => cost = 20/3 = 6.666
|
243
|
+
'funding-history': 6.666, // 9 requests per 3 seconds = 3 per second => cost = 20/3 = 6.666
|
244
|
+
},
|
245
|
+
'post': {
|
246
|
+
'withdrawals': 1.3953,
|
247
|
+
'transfer-out': 1.3953, // v2
|
248
|
+
'orders': 1.3953,
|
249
|
+
'position/margin/auto-deposit-status': 1.3953,
|
250
|
+
'position/margin/deposit-margin': 1.3953,
|
251
|
+
'bullet-private': 1.3953,
|
252
|
+
},
|
253
|
+
'delete': {
|
254
|
+
'withdrawals/{withdrawalId}': 1.3953,
|
255
|
+
'cancel/transfer-out': 1.3953,
|
256
|
+
'orders/{order-id}': 1.3953, // 40 requests per 3 seconds = 14.333 per second => cost = 20/14.333 = 1.395
|
257
|
+
'orders': 6.666, // 9 requests per 3 seconds = 3 per second => cost = 20/3 = 6.666
|
258
|
+
'stopOrders': 1.3953,
|
259
|
+
},
|
260
|
+
},
|
261
|
+
},
|
262
|
+
'timeframes': {
|
263
|
+
'1m': '1min',
|
264
|
+
'3m': '3min',
|
265
|
+
'5m': '5min',
|
266
|
+
'15m': '15min',
|
267
|
+
'30m': '30min',
|
268
|
+
'1h': '1hour',
|
269
|
+
'2h': '2hour',
|
270
|
+
'4h': '4hour',
|
271
|
+
'6h': '6hour',
|
272
|
+
'8h': '8hour',
|
273
|
+
'12h': '12hour',
|
274
|
+
'1d': '1day',
|
275
|
+
'1w': '1week',
|
276
|
+
},
|
277
|
+
'exceptions': {
|
278
|
+
'exact': {
|
279
|
+
'order not exist': OrderNotFound,
|
280
|
+
'order not exist.': OrderNotFound, // duplicated error temporarily
|
281
|
+
'order_not_exist': OrderNotFound, // {"code":"order_not_exist","msg":"order_not_exist"} ¯\_(ツ)_/¯
|
282
|
+
'order_not_exist_or_not_allow_to_cancel': InvalidOrder, // {"code":"400100","msg":"order_not_exist_or_not_allow_to_cancel"}
|
283
|
+
'Order size below the minimum requirement.': InvalidOrder, // {"code":"400100","msg":"Order size below the minimum requirement."}
|
284
|
+
'The withdrawal amount is below the minimum requirement.': ExchangeError, // {"code":"400100","msg":"The withdrawal amount is below the minimum requirement."}
|
285
|
+
'Unsuccessful! Exceeded the max. funds out-transfer limit': InsufficientFunds, // {"code":"200000","msg":"Unsuccessful! Exceeded the max. funds out-transfer limit"}
|
286
|
+
'400': BadRequest,
|
287
|
+
'401': AuthenticationError,
|
288
|
+
'403': NotSupported,
|
289
|
+
'404': NotSupported,
|
290
|
+
'405': NotSupported,
|
291
|
+
'429': RateLimitExceeded,
|
292
|
+
'500': ExchangeNotAvailable, // Internal Server Error -- We had a problem with our server. Try again later.
|
293
|
+
'503': ExchangeNotAvailable,
|
294
|
+
'101030': PermissionDenied, // {"code":"101030","msg":"You haven't yet enabled the margin trading"}
|
295
|
+
'200004': InsufficientFunds,
|
296
|
+
'230003': InsufficientFunds, // {"code":"230003","msg":"Balance insufficient!"}
|
297
|
+
'260100': InsufficientFunds, // {"code":"260100","msg":"account.noBalance"}
|
298
|
+
'300000': InvalidOrder,
|
299
|
+
'400000': BadSymbol,
|
300
|
+
'400001': AuthenticationError,
|
301
|
+
'400002': InvalidNonce,
|
302
|
+
'400003': AuthenticationError,
|
303
|
+
'400004': AuthenticationError,
|
304
|
+
'400005': AuthenticationError,
|
305
|
+
'400006': AuthenticationError,
|
306
|
+
'400007': AuthenticationError,
|
307
|
+
'400008': NotSupported,
|
308
|
+
'400100': BadRequest,
|
309
|
+
'400200': InvalidOrder, // {"code":"400200","msg":"Forbidden to place an order"}
|
310
|
+
'400350': InvalidOrder, // {"code":"400350","msg":"Upper limit for holding: 10,000USDT, you can still buy 10,000USDT worth of coin."}
|
311
|
+
'400370': InvalidOrder, // {"code":"400370","msg":"Max. price: 0.02500000000000000000"}
|
312
|
+
'400500': InvalidOrder, // {"code":"400500","msg":"Your located country/region is currently not supported for the trading of this token"}
|
313
|
+
'400600': BadSymbol, // {"code":"400600","msg":"validation.createOrder.symbolNotAvailable"}
|
314
|
+
'401000': BadRequest, // {"code":"401000","msg":"The interface has been deprecated"}
|
315
|
+
'411100': AccountSuspended,
|
316
|
+
'415000': BadRequest, // {"code":"415000","msg":"Unsupported Media Type"}
|
317
|
+
'500000': ExchangeNotAvailable, // {"code":"500000","msg":"Internal Server Error"}
|
318
|
+
'260220': InvalidAddress, // { "code": "260220", "msg": "deposit.address.not.exists" }
|
319
|
+
},
|
320
|
+
'broad': {
|
321
|
+
'Exceeded the access frequency': RateLimitExceeded,
|
322
|
+
'require more permission': PermissionDenied,
|
323
|
+
},
|
324
|
+
},
|
325
|
+
'fees': {
|
326
|
+
'trading': {
|
327
|
+
'tierBased': true,
|
328
|
+
'percentage': true,
|
329
|
+
'taker': this.parseNumber ('0.001'),
|
330
|
+
'maker': this.parseNumber ('0.001'),
|
331
|
+
'tiers': {
|
332
|
+
'taker': [
|
333
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.001') ],
|
334
|
+
[ this.parseNumber ('50'), this.parseNumber ('0.001') ],
|
335
|
+
[ this.parseNumber ('200'), this.parseNumber ('0.0009') ],
|
336
|
+
[ this.parseNumber ('500'), this.parseNumber ('0.0008') ],
|
337
|
+
[ this.parseNumber ('1000'), this.parseNumber ('0.0007') ],
|
338
|
+
[ this.parseNumber ('2000'), this.parseNumber ('0.0007') ],
|
339
|
+
[ this.parseNumber ('4000'), this.parseNumber ('0.0006') ],
|
340
|
+
[ this.parseNumber ('8000'), this.parseNumber ('0.0005') ],
|
341
|
+
[ this.parseNumber ('15000'), this.parseNumber ('0.00045') ],
|
342
|
+
[ this.parseNumber ('25000'), this.parseNumber ('0.0004') ],
|
343
|
+
[ this.parseNumber ('40000'), this.parseNumber ('0.00035') ],
|
344
|
+
[ this.parseNumber ('60000'), this.parseNumber ('0.0003') ],
|
345
|
+
[ this.parseNumber ('80000'), this.parseNumber ('0.00025') ],
|
346
|
+
],
|
347
|
+
'maker': [
|
348
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.001') ],
|
349
|
+
[ this.parseNumber ('50'), this.parseNumber ('0.0009') ],
|
350
|
+
[ this.parseNumber ('200'), this.parseNumber ('0.0007') ],
|
351
|
+
[ this.parseNumber ('500'), this.parseNumber ('0.0005') ],
|
352
|
+
[ this.parseNumber ('1000'), this.parseNumber ('0.0003') ],
|
353
|
+
[ this.parseNumber ('2000'), this.parseNumber ('0') ],
|
354
|
+
[ this.parseNumber ('4000'), this.parseNumber ('0') ],
|
355
|
+
[ this.parseNumber ('8000'), this.parseNumber ('0') ],
|
356
|
+
[ this.parseNumber ('15000'), this.parseNumber ('-0.00005') ],
|
357
|
+
[ this.parseNumber ('25000'), this.parseNumber ('-0.00005') ],
|
358
|
+
[ this.parseNumber ('40000'), this.parseNumber ('-0.00005') ],
|
359
|
+
[ this.parseNumber ('60000'), this.parseNumber ('-0.00005') ],
|
360
|
+
[ this.parseNumber ('80000'), this.parseNumber ('-0.00005') ],
|
361
|
+
],
|
362
|
+
},
|
363
|
+
},
|
364
|
+
'funding': {
|
365
|
+
'tierBased': false,
|
366
|
+
'percentage': false,
|
367
|
+
'withdraw': {},
|
368
|
+
'deposit': {},
|
369
|
+
},
|
370
|
+
},
|
371
|
+
'commonCurrencies': {
|
372
|
+
'HOT': 'HOTNOW',
|
373
|
+
'EDGE': 'DADI', // https://github.com/ccxt/ccxt/issues/5756
|
374
|
+
'WAX': 'WAXP',
|
375
|
+
'TRY': 'Trias',
|
376
|
+
'VAI': 'VAIOT',
|
377
|
+
},
|
378
|
+
'options': {
|
379
|
+
'version': 'v1',
|
380
|
+
'symbolSeparator': '-',
|
381
|
+
'fetchMyTradesMethod': 'private_get_fills',
|
382
|
+
'fetchBalance': 'trade',
|
383
|
+
'fetchMarkets': {
|
384
|
+
'fetchTickersFees': true,
|
385
|
+
},
|
386
|
+
// endpoint versions
|
387
|
+
'versions': {
|
388
|
+
'public': {
|
389
|
+
'GET': {
|
390
|
+
'status': 'v1',
|
391
|
+
'market/orderbook/level2_20': 'v1',
|
392
|
+
'market/orderbook/level2_100': 'v1',
|
393
|
+
'market/orderbook/level{level}_{limit}': 'v1',
|
394
|
+
},
|
395
|
+
},
|
396
|
+
'private': {
|
397
|
+
'GET': {
|
398
|
+
'market/orderbook/level2': 'v3',
|
399
|
+
'market/orderbook/level3': 'v3',
|
400
|
+
'market/orderbook/level{level}': 'v3',
|
401
|
+
},
|
402
|
+
'POST': {
|
403
|
+
'accounts/inner-transfer': 'v2',
|
404
|
+
'accounts/sub-transfer': 'v2',
|
405
|
+
},
|
406
|
+
},
|
407
|
+
'futuresPrivate': {
|
408
|
+
'GET': {
|
409
|
+
'account-overview': 'v1',
|
410
|
+
'positions': 'v1',
|
411
|
+
},
|
412
|
+
'POST': {
|
413
|
+
'transfer-out': 'v2',
|
414
|
+
},
|
415
|
+
},
|
416
|
+
'futuresPublic': {
|
417
|
+
'GET': {
|
418
|
+
'level3/snapshot': 'v2',
|
419
|
+
},
|
420
|
+
},
|
421
|
+
},
|
422
|
+
'accountsByType': {
|
423
|
+
'spot': 'trade',
|
424
|
+
'margin': 'margin',
|
425
|
+
'main': 'main',
|
426
|
+
'funding': 'main',
|
427
|
+
'future': 'contract',
|
428
|
+
'mining': 'pool',
|
429
|
+
},
|
430
|
+
'networks': {
|
431
|
+
'ETH': 'eth',
|
432
|
+
'ERC20': 'eth',
|
433
|
+
'TRX': 'trx',
|
434
|
+
'TRC20': 'trx',
|
435
|
+
'KCC': 'kcc',
|
436
|
+
'TERRA': 'luna',
|
437
|
+
},
|
438
|
+
},
|
439
|
+
});
|
440
|
+
}
|
441
|
+
|
442
|
+
nonce () {
|
443
|
+
return this.milliseconds ();
|
444
|
+
}
|
445
|
+
|
446
|
+
async fetchTime (params = {}) {
|
447
|
+
const response = await this.publicGetTimestamp (params);
|
448
|
+
//
|
449
|
+
// {
|
450
|
+
// "code":"200000",
|
451
|
+
// "msg":"success",
|
452
|
+
// "data":1546837113087
|
453
|
+
// }
|
454
|
+
//
|
455
|
+
return this.safeInteger (response, 'data');
|
456
|
+
}
|
457
|
+
|
458
|
+
async fetchStatus (params = {}) {
|
459
|
+
const response = await this.publicGetStatus (params);
|
460
|
+
//
|
461
|
+
// {
|
462
|
+
// "code":"200000",
|
463
|
+
// "data":{
|
464
|
+
// "status":"open", //open, close, cancelonly
|
465
|
+
// "msg":"upgrade match engine" //remark for operation
|
466
|
+
// }
|
467
|
+
// }
|
468
|
+
//
|
469
|
+
const data = this.safeValue (response, 'data', {});
|
470
|
+
const status = this.safeString (data, 'status');
|
471
|
+
return {
|
472
|
+
'status': (status === 'open') ? 'ok' : 'maintenance',
|
473
|
+
'updated': this.milliseconds (),
|
474
|
+
'eta': undefined,
|
475
|
+
'url': undefined,
|
476
|
+
'info': response,
|
477
|
+
};
|
478
|
+
}
|
479
|
+
|
480
|
+
async fetchMarkets (params = {}) {
|
481
|
+
const response = await this.publicGetSymbols (params);
|
482
|
+
//
|
483
|
+
// {
|
484
|
+
// "code": "200000",
|
485
|
+
// "data": [
|
486
|
+
// {
|
487
|
+
// "symbol": "XLM-USDT",
|
488
|
+
// "name": "XLM-USDT",
|
489
|
+
// "baseCurrency": "XLM",
|
490
|
+
// "quoteCurrency": "USDT",
|
491
|
+
// "feeCurrency": "USDT",
|
492
|
+
// "market": "USDS",
|
493
|
+
// "baseMinSize": "0.1",
|
494
|
+
// "quoteMinSize": "0.01",
|
495
|
+
// "baseMaxSize": "10000000000",
|
496
|
+
// "quoteMaxSize": "99999999",
|
497
|
+
// "baseIncrement": "0.0001",
|
498
|
+
// "quoteIncrement": "0.000001",
|
499
|
+
// "priceIncrement": "0.000001",
|
500
|
+
// "priceLimitRate": "0.1",
|
501
|
+
// "isMarginEnabled": true,
|
502
|
+
// "enableTrading": true
|
503
|
+
// },
|
504
|
+
// ]
|
505
|
+
// }
|
506
|
+
//
|
507
|
+
const data = this.safeValue (response, 'data');
|
508
|
+
const options = this.safeValue (this.options, 'fetchMarkets', {});
|
509
|
+
const fetchTickersFees = this.safeValue (options, 'fetchTickersFees', true);
|
510
|
+
let tickersResponse = {};
|
511
|
+
if (fetchTickersFees) {
|
512
|
+
tickersResponse = await this.publicGetMarketAllTickers (params);
|
513
|
+
}
|
514
|
+
//
|
515
|
+
// {
|
516
|
+
// "code": "200000",
|
517
|
+
// "data": {
|
518
|
+
// "time":1602832092060,
|
519
|
+
// "ticker":[
|
520
|
+
// {
|
521
|
+
// "symbol": "BTC-USDT", // symbol
|
522
|
+
// "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
|
523
|
+
// "buy": "11328.9", // bestAsk
|
524
|
+
// "sell": "11329", // bestBid
|
525
|
+
// "changeRate": "-0.0055", // 24h change rate
|
526
|
+
// "changePrice": "-63.6", // 24h change price
|
527
|
+
// "high": "11610", // 24h highest price
|
528
|
+
// "low": "11200", // 24h lowest price
|
529
|
+
// "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
|
530
|
+
// "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
|
531
|
+
// "last": "11328.9", // last price
|
532
|
+
// "averagePrice": "11360.66065903", // 24h average transaction price yesterday
|
533
|
+
// "takerFeeRate": "0.001", // Basic Taker Fee
|
534
|
+
// "makerFeeRate": "0.001", // Basic Maker Fee
|
535
|
+
// "takerCoefficient": "1", // Taker Fee Coefficient
|
536
|
+
// "makerCoefficient": "1" // Maker Fee Coefficient
|
537
|
+
// }
|
538
|
+
// ]
|
539
|
+
// }
|
540
|
+
// }
|
541
|
+
//
|
542
|
+
const tickersData = this.safeValue (tickersResponse, 'data', {});
|
543
|
+
const tickers = this.safeValue (tickersData, 'ticker', []);
|
544
|
+
const tickersByMarketId = this.indexBy (tickers, 'symbol');
|
545
|
+
const result = [];
|
546
|
+
for (let i = 0; i < data.length; i++) {
|
547
|
+
const market = data[i];
|
548
|
+
const id = this.safeString (market, 'symbol');
|
549
|
+
const [ baseId, quoteId ] = id.split ('-');
|
550
|
+
const base = this.safeCurrencyCode (baseId);
|
551
|
+
const quote = this.safeCurrencyCode (quoteId);
|
552
|
+
const baseMaxSize = this.safeNumber (market, 'baseMaxSize');
|
553
|
+
const baseMinSizeString = this.safeString (market, 'baseMinSize');
|
554
|
+
const quoteMaxSizeString = this.safeString (market, 'quoteMaxSize');
|
555
|
+
const baseMinSize = this.parseNumber (baseMinSizeString);
|
556
|
+
const quoteMaxSize = this.parseNumber (quoteMaxSizeString);
|
557
|
+
const quoteMinSize = this.safeNumber (market, 'quoteMinSize');
|
558
|
+
// const quoteIncrement = this.safeNumber (market, 'quoteIncrement');
|
559
|
+
const ticker = this.safeValue (tickersByMarketId, id, {});
|
560
|
+
const makerFeeRate = this.safeString (ticker, 'makerFeeRate');
|
561
|
+
const takerFeeRate = this.safeString (ticker, 'makerFeeRate');
|
562
|
+
const makerCoefficient = this.safeString (ticker, 'makerCoefficient');
|
563
|
+
const takerCoefficient = this.safeString (ticker, 'takerCoefficient');
|
564
|
+
result.push ({
|
565
|
+
'id': id,
|
566
|
+
'symbol': base + '/' + quote,
|
567
|
+
'base': base,
|
568
|
+
'quote': quote,
|
569
|
+
'settle': undefined,
|
570
|
+
'baseId': baseId,
|
571
|
+
'quoteId': quoteId,
|
572
|
+
'settleId': undefined,
|
573
|
+
'type': 'spot',
|
574
|
+
'spot': true,
|
575
|
+
'margin': this.safeValue (market, 'isMarginEnabled'),
|
576
|
+
'swap': false,
|
577
|
+
'future': false,
|
578
|
+
'option': false,
|
579
|
+
'active': this.safeValue (market, 'enableTrading'),
|
580
|
+
'contract': false,
|
581
|
+
'linear': undefined,
|
582
|
+
'inverse': undefined,
|
583
|
+
'taker': this.parseNumber (Precise.stringMul (takerFeeRate, takerCoefficient)),
|
584
|
+
'maker': this.parseNumber (Precise.stringMul (makerFeeRate, makerCoefficient)),
|
585
|
+
'contractSize': undefined,
|
586
|
+
'expiry': undefined,
|
587
|
+
'expiryDatetime': undefined,
|
588
|
+
'strike': undefined,
|
589
|
+
'optionType': undefined,
|
590
|
+
'precision': {
|
591
|
+
'amount': this.precisionFromString (this.safeString (market, 'baseIncrement')),
|
592
|
+
'price': this.precisionFromString (this.safeString (market, 'priceIncrement')),
|
593
|
+
},
|
594
|
+
'limits': {
|
595
|
+
'leverage': {
|
596
|
+
'min': undefined,
|
597
|
+
'max': undefined,
|
598
|
+
},
|
599
|
+
'amount': {
|
600
|
+
'min': baseMinSize,
|
601
|
+
'max': baseMaxSize,
|
602
|
+
},
|
603
|
+
'price': {
|
604
|
+
'min': undefined,
|
605
|
+
'max': undefined,
|
606
|
+
},
|
607
|
+
'cost': {
|
608
|
+
'min': quoteMinSize,
|
609
|
+
'max': quoteMaxSize,
|
610
|
+
},
|
611
|
+
},
|
612
|
+
'info': market,
|
613
|
+
});
|
614
|
+
}
|
615
|
+
return result;
|
616
|
+
}
|
617
|
+
|
618
|
+
async fetchCurrencies (params = {}) {
|
619
|
+
const response = await this.publicGetCurrencies (params);
|
620
|
+
//
|
621
|
+
// {
|
622
|
+
// "currency": "OMG",
|
623
|
+
// "name": "OMG",
|
624
|
+
// "fullName": "OmiseGO",
|
625
|
+
// "precision": 8,
|
626
|
+
// "confirms": 12,
|
627
|
+
// "withdrawalMinSize": "4",
|
628
|
+
// "withdrawalMinFee": "1.25",
|
629
|
+
// "isWithdrawEnabled": false,
|
630
|
+
// "isDepositEnabled": false,
|
631
|
+
// "isMarginEnabled": false,
|
632
|
+
// "isDebitEnabled": false
|
633
|
+
// }
|
634
|
+
//
|
635
|
+
const data = this.safeValue (response, 'data', []);
|
636
|
+
const result = {};
|
637
|
+
for (let i = 0; i < data.length; i++) {
|
638
|
+
const entry = data[i];
|
639
|
+
const id = this.safeString (entry, 'currency');
|
640
|
+
const name = this.safeString (entry, 'fullName');
|
641
|
+
const code = this.safeCurrencyCode (id);
|
642
|
+
const precision = this.safeInteger (entry, 'precision');
|
643
|
+
const isWithdrawEnabled = this.safeValue (entry, 'isWithdrawEnabled', false);
|
644
|
+
const isDepositEnabled = this.safeValue (entry, 'isDepositEnabled', false);
|
645
|
+
const fee = this.safeNumber (entry, 'withdrawalMinFee');
|
646
|
+
const active = (isWithdrawEnabled && isDepositEnabled);
|
647
|
+
result[code] = {
|
648
|
+
'id': id,
|
649
|
+
'name': name,
|
650
|
+
'code': code,
|
651
|
+
'precision': precision,
|
652
|
+
'info': entry,
|
653
|
+
'active': active,
|
654
|
+
'deposit': isDepositEnabled,
|
655
|
+
'withdraw': isWithdrawEnabled,
|
656
|
+
'fee': fee,
|
657
|
+
'limits': this.limits,
|
658
|
+
};
|
659
|
+
}
|
660
|
+
return result;
|
661
|
+
}
|
662
|
+
|
663
|
+
async fetchAccounts (params = {}) {
|
664
|
+
const response = await this.privateGetAccounts (params);
|
665
|
+
//
|
666
|
+
// {
|
667
|
+
// code: "200000",
|
668
|
+
// data: [
|
669
|
+
// {
|
670
|
+
// balance: "0.00009788",
|
671
|
+
// available: "0.00009788",
|
672
|
+
// holds: "0",
|
673
|
+
// currency: "BTC",
|
674
|
+
// id: "5c6a4fd399a1d81c4f9cc4d0",
|
675
|
+
// type: "trade"
|
676
|
+
// },
|
677
|
+
// {
|
678
|
+
// balance: "0.00000001",
|
679
|
+
// available: "0.00000001",
|
680
|
+
// holds: "0",
|
681
|
+
// currency: "ETH",
|
682
|
+
// id: "5c6a49ec99a1d819392e8e9f",
|
683
|
+
// type: "trade"
|
684
|
+
// }
|
685
|
+
// ]
|
686
|
+
// }
|
687
|
+
//
|
688
|
+
const data = this.safeValue (response, 'data');
|
689
|
+
const result = [];
|
690
|
+
for (let i = 0; i < data.length; i++) {
|
691
|
+
const account = data[i];
|
692
|
+
const accountId = this.safeString (account, 'id');
|
693
|
+
const currencyId = this.safeString (account, 'currency');
|
694
|
+
const code = this.safeCurrencyCode (currencyId);
|
695
|
+
const type = this.safeString (account, 'type'); // main or trade
|
696
|
+
result.push ({
|
697
|
+
'id': accountId,
|
698
|
+
'type': type,
|
699
|
+
'currency': code,
|
700
|
+
'info': account,
|
701
|
+
});
|
702
|
+
}
|
703
|
+
return result;
|
704
|
+
}
|
705
|
+
|
706
|
+
async fetchFundingFee (code, params = {}) {
|
707
|
+
await this.loadMarkets ();
|
708
|
+
const currency = this.currency (code);
|
709
|
+
const request = {
|
710
|
+
'currency': currency['id'],
|
711
|
+
};
|
712
|
+
const response = await this.privateGetWithdrawalsQuotas (this.extend (request, params));
|
713
|
+
const data = response['data'];
|
714
|
+
const withdrawFees = {};
|
715
|
+
withdrawFees[code] = this.safeNumber (data, 'withdrawMinFee');
|
716
|
+
return {
|
717
|
+
'info': response,
|
718
|
+
'withdraw': withdrawFees,
|
719
|
+
'deposit': {},
|
720
|
+
};
|
721
|
+
}
|
722
|
+
|
723
|
+
isFuturesMethod (methodName, params) {
|
724
|
+
//
|
725
|
+
// Helper
|
726
|
+
// @methodName (string): The name of the method
|
727
|
+
// @params (dict): The parameters passed into {methodName}
|
728
|
+
// @return: true if the method used is meant for futures trading, false otherwise
|
729
|
+
//
|
730
|
+
const defaultType = this.safeString2 (this.options, methodName, 'defaultType', 'trade');
|
731
|
+
const requestedType = this.safeString (params, 'type', defaultType);
|
732
|
+
const accountsByType = this.safeValue (this.options, 'accountsByType');
|
733
|
+
const type = this.safeString (accountsByType, requestedType);
|
734
|
+
if (type === undefined) {
|
735
|
+
const keys = Object.keys (accountsByType);
|
736
|
+
throw new ExchangeError (this.id + ' isFuturesMethod() type must be one of ' + keys.join (', '));
|
737
|
+
}
|
738
|
+
params = this.omit (params, 'type');
|
739
|
+
return (type === 'contract') || (type === 'future') || (type === 'futures'); // * (type === 'futures') deprecated, use (type === 'future')
|
740
|
+
}
|
741
|
+
|
742
|
+
parseTicker (ticker, market = undefined) {
|
743
|
+
//
|
744
|
+
// {
|
745
|
+
// "symbol": "BTC-USDT", // symbol
|
746
|
+
// "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
|
747
|
+
// "buy": "11328.9", // bestAsk
|
748
|
+
// "sell": "11329", // bestBid
|
749
|
+
// "changeRate": "-0.0055", // 24h change rate
|
750
|
+
// "changePrice": "-63.6", // 24h change price
|
751
|
+
// "high": "11610", // 24h highest price
|
752
|
+
// "low": "11200", // 24h lowest price
|
753
|
+
// "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
|
754
|
+
// "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
|
755
|
+
// "last": "11328.9", // last price
|
756
|
+
// "averagePrice": "11360.66065903", // 24h average transaction price yesterday
|
757
|
+
// "takerFeeRate": "0.001", // Basic Taker Fee
|
758
|
+
// "makerFeeRate": "0.001", // Basic Maker Fee
|
759
|
+
// "takerCoefficient": "1", // Taker Fee Coefficient
|
760
|
+
// "makerCoefficient": "1" // Maker Fee Coefficient
|
761
|
+
// }
|
762
|
+
//
|
763
|
+
// {
|
764
|
+
// "trading": true,
|
765
|
+
// "symbol": "KCS-BTC",
|
766
|
+
// "buy": 0.00011,
|
767
|
+
// "sell": 0.00012,
|
768
|
+
// "sort": 100,
|
769
|
+
// "volValue": 3.13851792584, //total
|
770
|
+
// "baseCurrency": "KCS",
|
771
|
+
// "market": "BTC",
|
772
|
+
// "quoteCurrency": "BTC",
|
773
|
+
// "symbolCode": "KCS-BTC",
|
774
|
+
// "datetime": 1548388122031,
|
775
|
+
// "high": 0.00013,
|
776
|
+
// "vol": 27514.34842,
|
777
|
+
// "low": 0.0001,
|
778
|
+
// "changePrice": -1.0e-5,
|
779
|
+
// "changeRate": -0.0769,
|
780
|
+
// "lastTradedPrice": 0.00012,
|
781
|
+
// "board": 0,
|
782
|
+
// "mark": 0
|
783
|
+
// }
|
784
|
+
//
|
785
|
+
// market/ticker ws subscription
|
786
|
+
//
|
787
|
+
// {
|
788
|
+
// bestAsk: '62258.9',
|
789
|
+
// bestAskSize: '0.38579986',
|
790
|
+
// bestBid: '62258.8',
|
791
|
+
// bestBidSize: '0.0078381',
|
792
|
+
// price: '62260.7',
|
793
|
+
// sequence: '1621383297064',
|
794
|
+
// size: '0.00002841',
|
795
|
+
// time: 1634641777363
|
796
|
+
// }
|
797
|
+
//
|
798
|
+
let percentage = this.safeString (ticker, 'changeRate');
|
799
|
+
if (percentage !== undefined) {
|
800
|
+
percentage = Precise.stringMul (percentage, '100');
|
801
|
+
}
|
802
|
+
let last = this.safeString2 (ticker, 'last', 'lastTradedPrice');
|
803
|
+
last = this.safeString (ticker, 'price', last);
|
804
|
+
const marketId = this.safeString (ticker, 'symbol');
|
805
|
+
market = this.safeMarket (marketId, market, '-');
|
806
|
+
const symbol = market['symbol'];
|
807
|
+
const baseVolume = this.safeString (ticker, 'vol');
|
808
|
+
const quoteVolume = this.safeString (ticker, 'volValue');
|
809
|
+
const timestamp = this.safeInteger2 (ticker, 'time', 'datetime');
|
810
|
+
return this.safeTicker ({
|
811
|
+
'symbol': symbol,
|
812
|
+
'timestamp': timestamp,
|
813
|
+
'datetime': this.iso8601 (timestamp),
|
814
|
+
'high': this.safeString (ticker, 'high'),
|
815
|
+
'low': this.safeString (ticker, 'low'),
|
816
|
+
'bid': this.safeString2 (ticker, 'buy', 'bestBid'),
|
817
|
+
'bidVolume': this.safeString (ticker, 'bestBidSize'),
|
818
|
+
'ask': this.safeString2 (ticker, 'sell', 'bestAsk'),
|
819
|
+
'askVolume': this.safeString (ticker, 'bestAskSize'),
|
820
|
+
'vwap': undefined,
|
821
|
+
'open': this.safeString (ticker, 'open'),
|
822
|
+
'close': last,
|
823
|
+
'last': last,
|
824
|
+
'previousClose': undefined,
|
825
|
+
'change': this.safeString (ticker, 'changePrice'),
|
826
|
+
'percentage': percentage,
|
827
|
+
'average': this.safeString (ticker, 'averagePrice'),
|
828
|
+
'baseVolume': baseVolume,
|
829
|
+
'quoteVolume': quoteVolume,
|
830
|
+
'info': ticker,
|
831
|
+
}, market, false);
|
832
|
+
}
|
833
|
+
|
834
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
835
|
+
await this.loadMarkets ();
|
836
|
+
const response = await this.publicGetMarketAllTickers (params);
|
837
|
+
//
|
838
|
+
// {
|
839
|
+
// "code": "200000",
|
840
|
+
// "data": {
|
841
|
+
// "time":1602832092060,
|
842
|
+
// "ticker":[
|
843
|
+
// {
|
844
|
+
// "symbol": "BTC-USDT", // symbol
|
845
|
+
// "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
|
846
|
+
// "buy": "11328.9", // bestAsk
|
847
|
+
// "sell": "11329", // bestBid
|
848
|
+
// "changeRate": "-0.0055", // 24h change rate
|
849
|
+
// "changePrice": "-63.6", // 24h change price
|
850
|
+
// "high": "11610", // 24h highest price
|
851
|
+
// "low": "11200", // 24h lowest price
|
852
|
+
// "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
|
853
|
+
// "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
|
854
|
+
// "last": "11328.9", // last price
|
855
|
+
// "averagePrice": "11360.66065903", // 24h average transaction price yesterday
|
856
|
+
// "takerFeeRate": "0.001", // Basic Taker Fee
|
857
|
+
// "makerFeeRate": "0.001", // Basic Maker Fee
|
858
|
+
// "takerCoefficient": "1", // Taker Fee Coefficient
|
859
|
+
// "makerCoefficient": "1" // Maker Fee Coefficient
|
860
|
+
// }
|
861
|
+
// ]
|
862
|
+
// }
|
863
|
+
// }
|
864
|
+
//
|
865
|
+
const data = this.safeValue (response, 'data', {});
|
866
|
+
const tickers = this.safeValue (data, 'ticker', []);
|
867
|
+
const time = this.safeInteger (data, 'time');
|
868
|
+
const result = {};
|
869
|
+
for (let i = 0; i < tickers.length; i++) {
|
870
|
+
tickers[i]['time'] = time;
|
871
|
+
const ticker = this.parseTicker (tickers[i]);
|
872
|
+
const symbol = this.safeString (ticker, 'symbol');
|
873
|
+
if (symbol !== undefined) {
|
874
|
+
result[symbol] = ticker;
|
875
|
+
}
|
876
|
+
}
|
877
|
+
return this.filterByArray (result, 'symbol', symbols);
|
878
|
+
}
|
879
|
+
|
880
|
+
async fetchTicker (symbol, params = {}) {
|
881
|
+
await this.loadMarkets ();
|
882
|
+
const market = this.market (symbol);
|
883
|
+
const request = {
|
884
|
+
'symbol': market['id'],
|
885
|
+
};
|
886
|
+
const response = await this.publicGetMarketStats (this.extend (request, params));
|
887
|
+
//
|
888
|
+
// {
|
889
|
+
// "code": "200000",
|
890
|
+
// "data": {
|
891
|
+
// "time": 1602832092060, // time
|
892
|
+
// "symbol": "BTC-USDT", // symbol
|
893
|
+
// "buy": "11328.9", // bestAsk
|
894
|
+
// "sell": "11329", // bestBid
|
895
|
+
// "changeRate": "-0.0055", // 24h change rate
|
896
|
+
// "changePrice": "-63.6", // 24h change price
|
897
|
+
// "high": "11610", // 24h highest price
|
898
|
+
// "low": "11200", // 24h lowest price
|
899
|
+
// "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
|
900
|
+
// "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
|
901
|
+
// "last": "11328.9", // last price
|
902
|
+
// "averagePrice": "11360.66065903", // 24h average transaction price yesterday
|
903
|
+
// "takerFeeRate": "0.001", // Basic Taker Fee
|
904
|
+
// "makerFeeRate": "0.001", // Basic Maker Fee
|
905
|
+
// "takerCoefficient": "1", // Taker Fee Coefficient
|
906
|
+
// "makerCoefficient": "1" // Maker Fee Coefficient
|
907
|
+
// }
|
908
|
+
// }
|
909
|
+
//
|
910
|
+
return this.parseTicker (response['data'], market);
|
911
|
+
}
|
912
|
+
|
913
|
+
parseOHLCV (ohlcv, market = undefined) {
|
914
|
+
//
|
915
|
+
// [
|
916
|
+
// "1545904980", // Start time of the candle cycle
|
917
|
+
// "0.058", // opening price
|
918
|
+
// "0.049", // closing price
|
919
|
+
// "0.058", // highest price
|
920
|
+
// "0.049", // lowest price
|
921
|
+
// "0.018", // base volume
|
922
|
+
// "0.000945", // quote volume
|
923
|
+
// ]
|
924
|
+
//
|
925
|
+
return [
|
926
|
+
this.safeTimestamp (ohlcv, 0),
|
927
|
+
this.safeNumber (ohlcv, 1),
|
928
|
+
this.safeNumber (ohlcv, 3),
|
929
|
+
this.safeNumber (ohlcv, 4),
|
930
|
+
this.safeNumber (ohlcv, 2),
|
931
|
+
this.safeNumber (ohlcv, 5),
|
932
|
+
];
|
933
|
+
}
|
934
|
+
|
935
|
+
async fetchOHLCV (symbol, timeframe = '15m', since = undefined, limit = undefined, params = {}) {
|
936
|
+
await this.loadMarkets ();
|
937
|
+
const market = this.market (symbol);
|
938
|
+
const marketId = market['id'];
|
939
|
+
const request = {
|
940
|
+
'symbol': marketId,
|
941
|
+
'type': this.timeframes[timeframe],
|
942
|
+
};
|
943
|
+
const duration = this.parseTimeframe (timeframe) * 1000;
|
944
|
+
let endAt = this.milliseconds (); // required param
|
945
|
+
if (since !== undefined) {
|
946
|
+
request['startAt'] = parseInt (Math.floor (since / 1000));
|
947
|
+
if (limit === undefined) {
|
948
|
+
// https://docs.kucoin.com/#get-klines
|
949
|
+
// https://docs.kucoin.com/#details
|
950
|
+
// For each query, the system would return at most 1500 pieces of data.
|
951
|
+
// To obtain more data, please page the data by time.
|
952
|
+
limit = this.safeInteger (this.options, 'fetchOHLCVLimit', 1500);
|
953
|
+
}
|
954
|
+
endAt = this.sum (since, limit * duration);
|
955
|
+
} else if (limit !== undefined) {
|
956
|
+
since = endAt - limit * duration;
|
957
|
+
request['startAt'] = parseInt (Math.floor (since / 1000));
|
958
|
+
}
|
959
|
+
request['endAt'] = parseInt (Math.floor (endAt / 1000));
|
960
|
+
const response = await this.publicGetMarketCandles (this.extend (request, params));
|
961
|
+
//
|
962
|
+
// {
|
963
|
+
// "code":"200000",
|
964
|
+
// "data":[
|
965
|
+
// ["1591517700","0.025078","0.025069","0.025084","0.025064","18.9883256","0.4761861079404"],
|
966
|
+
// ["1591516800","0.025089","0.025079","0.025089","0.02506","99.4716622","2.494143499081"],
|
967
|
+
// ["1591515900","0.025079","0.02509","0.025091","0.025068","59.83701271","1.50060885172798"],
|
968
|
+
// ]
|
969
|
+
// }
|
970
|
+
//
|
971
|
+
const data = this.safeValue (response, 'data', []);
|
972
|
+
return this.parseOHLCVs (data, market, timeframe, since, limit);
|
973
|
+
}
|
974
|
+
|
975
|
+
async createDepositAddress (code, params = {}) {
|
976
|
+
await this.loadMarkets ();
|
977
|
+
const currency = this.currency (code);
|
978
|
+
const request = { 'currency': currency['id'] };
|
979
|
+
const response = await this.privatePostDepositAddresses (this.extend (request, params));
|
980
|
+
// BCH {"code":"200000","data":{"address":"bitcoincash:qza3m4nj9rx7l9r0cdadfqxts6f92shvhvr5ls4q7z","memo":""}}
|
981
|
+
// BTC {"code":"200000","data":{"address":"36SjucKqQpQSvsak9A7h6qzFjrVXpRNZhE","memo":""}}
|
982
|
+
const data = this.safeValue (response, 'data', {});
|
983
|
+
let address = this.safeString (data, 'address');
|
984
|
+
// BCH/BSV is returned with a "bitcoincash:" prefix, which we cut off here and only keep the address
|
985
|
+
if (address !== undefined) {
|
986
|
+
address = address.replace ('bitcoincash:', '');
|
987
|
+
}
|
988
|
+
const tag = this.safeString (data, 'memo');
|
989
|
+
if (code !== 'NIM') {
|
990
|
+
// contains spaces
|
991
|
+
this.checkAddress (address);
|
992
|
+
}
|
993
|
+
return {
|
994
|
+
'info': response,
|
995
|
+
'currency': code,
|
996
|
+
'address': address,
|
997
|
+
'tag': tag,
|
998
|
+
};
|
999
|
+
}
|
1000
|
+
|
1001
|
+
async fetchDepositAddress (code, params = {}) {
|
1002
|
+
await this.loadMarkets ();
|
1003
|
+
const currency = this.currency (code);
|
1004
|
+
const request = {
|
1005
|
+
'currency': currency['id'],
|
1006
|
+
// for USDT - OMNI, ERC20, TRC20, default is ERC20
|
1007
|
+
// for BTC - Native, Segwit, TRC20, the parameters are bech32, btc, trx, default is Native
|
1008
|
+
// 'chain': 'ERC20', // optional
|
1009
|
+
};
|
1010
|
+
// same as for withdraw
|
1011
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
1012
|
+
let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
|
1013
|
+
network = this.safeStringLower (networks, network, network); // handle ERC20>ETH alias
|
1014
|
+
if (network !== undefined) {
|
1015
|
+
request['chain'] = network;
|
1016
|
+
params = this.omit (params, 'network');
|
1017
|
+
}
|
1018
|
+
const response = await this.privateGetDepositAddresses (this.extend (request, params));
|
1019
|
+
// BCH {"code":"200000","data":{"address":"bitcoincash:qza3m4nj9rx7l9r0cdadfqxts6f92shvhvr5ls4q7z","memo":""}}
|
1020
|
+
// BTC {"code":"200000","data":{"address":"36SjucKqQpQSvsak9A7h6qzFjrVXpRNZhE","memo":""}}
|
1021
|
+
const data = this.safeValue (response, 'data', {});
|
1022
|
+
const address = this.safeString (data, 'address');
|
1023
|
+
const tag = this.safeString (data, 'memo');
|
1024
|
+
if (code !== 'NIM') {
|
1025
|
+
// contains spaces
|
1026
|
+
this.checkAddress (address);
|
1027
|
+
}
|
1028
|
+
return {
|
1029
|
+
'info': response,
|
1030
|
+
'currency': code,
|
1031
|
+
'address': address,
|
1032
|
+
'tag': tag,
|
1033
|
+
'network': undefined,
|
1034
|
+
};
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
1038
|
+
await this.loadMarkets ();
|
1039
|
+
const marketId = this.marketId (symbol);
|
1040
|
+
const level = this.safeInteger (params, 'level', 2);
|
1041
|
+
const request = { 'symbol': marketId };
|
1042
|
+
let method = 'publicGetMarketOrderbookLevelLevelLimit';
|
1043
|
+
const isAuthenticated = this.checkRequiredCredentials (false);
|
1044
|
+
let response = undefined;
|
1045
|
+
if (!isAuthenticated) {
|
1046
|
+
if (level === 2) {
|
1047
|
+
request['level'] = level;
|
1048
|
+
if (limit !== undefined) {
|
1049
|
+
if ((limit === 20) || (limit === 100)) {
|
1050
|
+
request['limit'] = limit;
|
1051
|
+
} else {
|
1052
|
+
throw new ExchangeError (this.id + ' fetchOrderBook() limit argument must be 20 or 100');
|
1053
|
+
}
|
1054
|
+
}
|
1055
|
+
request['limit'] = limit ? limit : 100;
|
1056
|
+
method = 'publicGetMarketOrderbookLevelLevelLimit';
|
1057
|
+
response = await this[method] (this.extend (request, params));
|
1058
|
+
}
|
1059
|
+
} else {
|
1060
|
+
method = 'privateGetMarketOrderbookLevel2'; // recommended (v3)
|
1061
|
+
response = await this[method] (this.extend (request, params));
|
1062
|
+
}
|
1063
|
+
//
|
1064
|
+
// public (v1) market/orderbook/level2_20 and market/orderbook/level2_100
|
1065
|
+
//
|
1066
|
+
// {
|
1067
|
+
// "sequence": "3262786978",
|
1068
|
+
// "time": 1550653727731,
|
1069
|
+
// "bids": [
|
1070
|
+
// ["6500.12", "0.45054140"],
|
1071
|
+
// ["6500.11", "0.45054140"],
|
1072
|
+
// ],
|
1073
|
+
// "asks": [
|
1074
|
+
// ["6500.16", "0.57753524"],
|
1075
|
+
// ["6500.15", "0.57753524"],
|
1076
|
+
// ]
|
1077
|
+
// }
|
1078
|
+
//
|
1079
|
+
// private (v3) market/orderbook/level2
|
1080
|
+
//
|
1081
|
+
// {
|
1082
|
+
// "sequence": "3262786978",
|
1083
|
+
// "time": 1550653727731,
|
1084
|
+
// "bids": [
|
1085
|
+
// ["6500.12", "0.45054140"],
|
1086
|
+
// ["6500.11", "0.45054140"],
|
1087
|
+
// ],
|
1088
|
+
// "asks": [
|
1089
|
+
// ["6500.16", "0.57753524"],
|
1090
|
+
// ["6500.15", "0.57753524"],
|
1091
|
+
// ]
|
1092
|
+
// }
|
1093
|
+
//
|
1094
|
+
const data = this.safeValue (response, 'data', {});
|
1095
|
+
const timestamp = this.safeInteger (data, 'time');
|
1096
|
+
const orderbook = this.parseOrderBook (data, symbol, timestamp, 'bids', 'asks', level - 2, level - 1);
|
1097
|
+
orderbook['nonce'] = this.safeInteger (data, 'sequence');
|
1098
|
+
return orderbook;
|
1099
|
+
}
|
1100
|
+
|
1101
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
1102
|
+
/**
|
1103
|
+
* @method
|
1104
|
+
* @name kucoin#createOrder
|
1105
|
+
* @description Create an order on the exchange
|
1106
|
+
* @param {str} symbol Unified CCXT market symbol
|
1107
|
+
* @param {str} type "limit" or "market"
|
1108
|
+
* @param {str} side "buy" or "sell"
|
1109
|
+
* @param {float} amount the amount of currency to trade
|
1110
|
+
* @param {float} price *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
|
1111
|
+
* @param {dict} params Extra parameters specific to the exchange API endpoint
|
1112
|
+
* @param {str} params.clientOid client order id, defaults to uuid if not passed
|
1113
|
+
* @param {str} params.remark remark for the order, length cannot exceed 100 utf8 characters
|
1114
|
+
* @param {str} params.tradeType 'TRADE', // TRADE, MARGIN_TRADE // not used with margin orders
|
1115
|
+
* limit orders ---------------------------------------------------
|
1116
|
+
* @param {str} params.timeInForce GTC, GTT, IOC, or FOK, default is GTC, limit orders only
|
1117
|
+
* @param {float} params.cancelAfter long, // cancel after n seconds, requires timeInForce to be GTT
|
1118
|
+
* @param {str} params.postOnly Post only flag, invalid when timeInForce is IOC or FOK
|
1119
|
+
* @param {bool} params.hidden false, // Order will not be displayed in the order book
|
1120
|
+
* @param {bool} params.iceberg false, // Only a portion of the order is displayed in the order book
|
1121
|
+
* @param {str} params.visibleSize this.amountToPrecision (symbol, visibleSize), // The maximum visible size of an iceberg order
|
1122
|
+
* market orders --------------------------------------------------
|
1123
|
+
* @param {str} params.funds // Amount of quote currency to use
|
1124
|
+
* stop orders ----------------------------------------------------
|
1125
|
+
* @param {str} params.stop Either loss or entry, the default is loss. Requires stopPrice to be defined
|
1126
|
+
* @param {float} params.stopPrice The price at which a trigger order is triggered at
|
1127
|
+
* margin orders --------------------------------------------------
|
1128
|
+
* @param {float} params.leverage Leverage size of the order
|
1129
|
+
* @param {str} params.stp '', // self trade prevention, CN, CO, CB or DC
|
1130
|
+
* @param {str} params.marginMode 'cross', // cross (cross mode) and isolated (isolated mode), set to cross by default, the isolated mode will be released soon, stay tuned
|
1131
|
+
* @param {bool} params.autoBorrow false, // The system will first borrow you funds at the optimal interest rate and then place an order for you
|
1132
|
+
* @returns an [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
|
1133
|
+
*/
|
1134
|
+
await this.loadMarkets ();
|
1135
|
+
const marketId = this.marketId (symbol);
|
1136
|
+
// required param, cannot be used twice
|
1137
|
+
const clientOrderId = this.safeString2 (params, 'clientOid', 'clientOrderId', this.uuid ());
|
1138
|
+
params = this.omit (params, [ 'clientOid', 'clientOrderId' ]);
|
1139
|
+
const request = {
|
1140
|
+
'clientOid': clientOrderId,
|
1141
|
+
'side': side,
|
1142
|
+
'symbol': marketId,
|
1143
|
+
'type': type, // limit or market
|
1144
|
+
};
|
1145
|
+
const quoteAmount = this.safeNumber2 (params, 'cost', 'funds');
|
1146
|
+
let amountString = undefined;
|
1147
|
+
let costString = undefined;
|
1148
|
+
if (type === 'market') {
|
1149
|
+
if (quoteAmount !== undefined) {
|
1150
|
+
params = this.omit (params, [ 'cost', 'funds' ]);
|
1151
|
+
// kucoin uses base precision even for quote values
|
1152
|
+
costString = this.amountToPrecision (symbol, quoteAmount);
|
1153
|
+
request['funds'] = costString;
|
1154
|
+
} else {
|
1155
|
+
amountString = this.amountToPrecision (symbol, amount);
|
1156
|
+
request['size'] = this.amountToPrecision (symbol, amount);
|
1157
|
+
}
|
1158
|
+
} else {
|
1159
|
+
amountString = this.amountToPrecision (symbol, amount);
|
1160
|
+
request['size'] = amountString;
|
1161
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1162
|
+
}
|
1163
|
+
const stopPrice = this.safeString (params, 'stopPrice');
|
1164
|
+
const tradeType = this.safeString (params, 'tradeType');
|
1165
|
+
params = this.omit (params, 'stopPrice');
|
1166
|
+
let method = 'privatePostOrders';
|
1167
|
+
if (stopPrice !== undefined) {
|
1168
|
+
request['stopPrice'] = this.priceToPrecision (symbol, stopPrice);
|
1169
|
+
request['stop'] = 'loss';
|
1170
|
+
method = 'privatePostStopOrder';
|
1171
|
+
} else if (tradeType === 'MARGIN_TRADE') {
|
1172
|
+
method = 'privatePostMarginOrder';
|
1173
|
+
}
|
1174
|
+
const response = await this[method] (this.extend (request, params));
|
1175
|
+
//
|
1176
|
+
// {
|
1177
|
+
// code: '200000',
|
1178
|
+
// data: {
|
1179
|
+
// "orderId": "5bd6e9286d99522a52e458de"
|
1180
|
+
// }
|
1181
|
+
// }
|
1182
|
+
//
|
1183
|
+
const data = this.safeValue (response, 'data', {});
|
1184
|
+
const timestamp = this.milliseconds ();
|
1185
|
+
const id = this.safeString (data, 'orderId');
|
1186
|
+
const order = {
|
1187
|
+
'id': id,
|
1188
|
+
'clientOrderId': clientOrderId,
|
1189
|
+
'info': data,
|
1190
|
+
'timestamp': timestamp,
|
1191
|
+
'datetime': this.iso8601 (timestamp),
|
1192
|
+
'lastTradeTimestamp': undefined,
|
1193
|
+
'symbol': symbol,
|
1194
|
+
'type': type,
|
1195
|
+
'side': side,
|
1196
|
+
'price': price,
|
1197
|
+
'amount': this.parseNumber (amountString),
|
1198
|
+
'cost': this.parseNumber (costString),
|
1199
|
+
'average': undefined,
|
1200
|
+
'filled': undefined,
|
1201
|
+
'remaining': undefined,
|
1202
|
+
'status': undefined,
|
1203
|
+
'fee': undefined,
|
1204
|
+
'trades': undefined,
|
1205
|
+
};
|
1206
|
+
return order;
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
1210
|
+
/**
|
1211
|
+
* @method
|
1212
|
+
* @name kucoin#cancelOrder
|
1213
|
+
* @description Cancels an order
|
1214
|
+
* @param {str} id Order id
|
1215
|
+
* @param {str} symbol Not used by kucoin
|
1216
|
+
* @param {dict} params Exchange specific parameters
|
1217
|
+
* @param {bool} params.stop True if cancelling a stop order
|
1218
|
+
* @returns Response fromt the exchange
|
1219
|
+
*/
|
1220
|
+
await this.loadMarkets ();
|
1221
|
+
const request = {};
|
1222
|
+
const clientOrderId = this.safeString2 (params, 'clientOid', 'clientOrderId');
|
1223
|
+
const stop = this.safeValue (params, 'stop');
|
1224
|
+
let method = 'privateDeleteOrdersOrderId';
|
1225
|
+
if (clientOrderId !== undefined) {
|
1226
|
+
request['clientOid'] = clientOrderId;
|
1227
|
+
if (stop) {
|
1228
|
+
method = 'privateDeleteStopOrderCancelOrderByClientOid';
|
1229
|
+
} else {
|
1230
|
+
method = 'privateDeleteOrdersClientOrderClientOid';
|
1231
|
+
}
|
1232
|
+
} else {
|
1233
|
+
if (stop) {
|
1234
|
+
method = 'privateDeleteStopOrderOrderId';
|
1235
|
+
}
|
1236
|
+
request['orderId'] = id;
|
1237
|
+
}
|
1238
|
+
params = this.omit (params, [ 'clientOid', 'clientOrderId', 'stop' ]);
|
1239
|
+
return await this[method] (this.extend (request, params));
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
async cancelAllOrders (symbol = undefined, params = {}) {
|
1243
|
+
/**
|
1244
|
+
* @method
|
1245
|
+
* @name kucoin#cancelAllOrders
|
1246
|
+
* @description Cancels all open orders, or cancels all orders in a market for one symbol, stop orders must be cancelled separately
|
1247
|
+
* @param {str} symbol Unified symbol indicating the market to cancel orders in
|
1248
|
+
* @param {dict} params Exchange specific parameters
|
1249
|
+
* @param {bool} params.stop true if cancelling all stop orders
|
1250
|
+
* @param {str} params.tradeType The type of trading, "TRADE" for Spot Trading, "MARGIN_TRADE" for Margin Trading
|
1251
|
+
* @param {str} params.orderIds *stop orders only* Comma seperated order IDs
|
1252
|
+
* @returns Response from the exchange
|
1253
|
+
*/
|
1254
|
+
await this.loadMarkets ();
|
1255
|
+
const request = {};
|
1256
|
+
let market = undefined;
|
1257
|
+
if (symbol !== undefined) {
|
1258
|
+
market = this.market (symbol);
|
1259
|
+
request['symbol'] = market['id'];
|
1260
|
+
}
|
1261
|
+
let method = 'privateDeleteOrders';
|
1262
|
+
const stop = this.safeValue (params, 'stop');
|
1263
|
+
if (stop) {
|
1264
|
+
method = 'privateDeleteStopOrderCancel';
|
1265
|
+
}
|
1266
|
+
return await this[method] (this.extend (request, params));
|
1267
|
+
}
|
1268
|
+
|
1269
|
+
async fetchOrdersByStatus (status, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1270
|
+
/**
|
1271
|
+
* @method
|
1272
|
+
* @name kucoin#fetchOrdersByStatus
|
1273
|
+
* @description fetch a list of orders
|
1274
|
+
* @param {str} status *not used for stop orders* 'open' or 'closed'
|
1275
|
+
* @param {str} symbol unified market symbol
|
1276
|
+
* @param {int} since timestamp in ms of the earliest order
|
1277
|
+
* @param {int} limit max number of orders to return
|
1278
|
+
* @param {dict} params exchange specific params
|
1279
|
+
* @param {int} params.till end time in ms
|
1280
|
+
* @param {bool} params.stop true if fetching stop orders
|
1281
|
+
* @param {str} params.side buy or sell
|
1282
|
+
* @param {str} params.type limit, market, limit_stop or market_stop
|
1283
|
+
* @param {str} params.tradeType TRADE for spot trading, MARGIN_TRADE for Margin Trading
|
1284
|
+
* @param {int} params.currentPage *stop orders only* current page
|
1285
|
+
* @param {str} params.orderIds *stop orders only* comma seperated order ID list
|
1286
|
+
* @returns An [array of order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
|
1287
|
+
*/
|
1288
|
+
await this.loadMarkets ();
|
1289
|
+
let lowercaseStatus = status.toLowerCase ();
|
1290
|
+
if (lowercaseStatus === 'open') {
|
1291
|
+
lowercaseStatus = 'active';
|
1292
|
+
} else if (lowercaseStatus === 'closed') {
|
1293
|
+
lowercaseStatus = 'done';
|
1294
|
+
}
|
1295
|
+
const request = {
|
1296
|
+
'status': lowercaseStatus,
|
1297
|
+
};
|
1298
|
+
let market = undefined;
|
1299
|
+
if (symbol !== undefined) {
|
1300
|
+
market = this.market (symbol);
|
1301
|
+
request['symbol'] = market['id'];
|
1302
|
+
}
|
1303
|
+
if (since !== undefined) {
|
1304
|
+
request['startAt'] = since;
|
1305
|
+
}
|
1306
|
+
if (limit !== undefined) {
|
1307
|
+
request['pageSize'] = limit;
|
1308
|
+
}
|
1309
|
+
const till = this.safeInteger (params, 'till');
|
1310
|
+
if (till) {
|
1311
|
+
request['endAt'] = till;
|
1312
|
+
}
|
1313
|
+
const stop = this.safeValue (params, 'stop');
|
1314
|
+
params = this.omit (params, 'stop');
|
1315
|
+
let method = 'privateGetOrders';
|
1316
|
+
if (stop) {
|
1317
|
+
method = 'privateGetStopOrder';
|
1318
|
+
}
|
1319
|
+
const response = await this[method] (this.extend (request, params));
|
1320
|
+
//
|
1321
|
+
// {
|
1322
|
+
// code: '200000',
|
1323
|
+
// data: {
|
1324
|
+
// "currentPage": 1,
|
1325
|
+
// "pageSize": 1,
|
1326
|
+
// "totalNum": 153408,
|
1327
|
+
// "totalPage": 153408,
|
1328
|
+
// "items": [
|
1329
|
+
// {
|
1330
|
+
// "id": "5c35c02703aa673ceec2a168", //orderid
|
1331
|
+
// "symbol": "BTC-USDT", //symbol
|
1332
|
+
// "opType": "DEAL", // operation type,deal is pending order,cancel is cancel order
|
1333
|
+
// "type": "limit", // order type,e.g. limit,markrt,stop_limit.
|
1334
|
+
// "side": "buy", // transaction direction,include buy and sell
|
1335
|
+
// "price": "10", // order price
|
1336
|
+
// "size": "2", // order quantity
|
1337
|
+
// "funds": "0", // order funds
|
1338
|
+
// "dealFunds": "0.166", // deal funds
|
1339
|
+
// "dealSize": "2", // deal quantity
|
1340
|
+
// "fee": "0", // fee
|
1341
|
+
// "feeCurrency": "USDT", // charge fee currency
|
1342
|
+
// "stp": "", // self trade prevention,include CN,CO,DC,CB
|
1343
|
+
// "stop": "", // stop type
|
1344
|
+
// "stopTriggered": false, // stop order is triggered
|
1345
|
+
// "stopPrice": "0", // stop price
|
1346
|
+
// "timeInForce": "GTC", // time InForce,include GTC,GTT,IOC,FOK
|
1347
|
+
// "postOnly": false, // postOnly
|
1348
|
+
// "hidden": false, // hidden order
|
1349
|
+
// "iceberg": false, // iceberg order
|
1350
|
+
// "visibleSize": "0", // display quantity for iceberg order
|
1351
|
+
// "cancelAfter": 0, // cancel orders time,requires timeInForce to be GTT
|
1352
|
+
// "channel": "IOS", // order source
|
1353
|
+
// "clientOid": "", // user-entered order unique mark
|
1354
|
+
// "remark": "", // remark
|
1355
|
+
// "tags": "", // tag order source
|
1356
|
+
// "isActive": false, // status before unfilled or uncancelled
|
1357
|
+
// "cancelExist": false, // order cancellation transaction record
|
1358
|
+
// "createdAt": 1547026471000 // time
|
1359
|
+
// },
|
1360
|
+
// ]
|
1361
|
+
// }
|
1362
|
+
// }
|
1363
|
+
const responseData = this.safeValue (response, 'data', {});
|
1364
|
+
const orders = this.safeValue (responseData, 'items', []);
|
1365
|
+
return this.parseOrders (orders, market, since, limit);
|
1366
|
+
}
|
1367
|
+
|
1368
|
+
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1369
|
+
/**
|
1370
|
+
* @method
|
1371
|
+
* @name kucoin#fetchClosedOrders
|
1372
|
+
* @description fetch a list of orders
|
1373
|
+
* @param {str} symbol unified market symbol
|
1374
|
+
* @param {int} since timestamp in ms of the earliest order
|
1375
|
+
* @param {int} limit max number of orders to return
|
1376
|
+
* @param {dict} params exchange specific params
|
1377
|
+
* @param {int} params.till end time in ms
|
1378
|
+
* @param {str} params.side buy or sell
|
1379
|
+
* @param {str} params.type limit, market, limit_stop or market_stop
|
1380
|
+
* @param {str} params.tradeType TRADE for spot trading, MARGIN_TRADE for Margin Trading
|
1381
|
+
* @returns An [array of order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
|
1382
|
+
*/
|
1383
|
+
return await this.fetchOrdersByStatus ('done', symbol, since, limit, params);
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1387
|
+
/**
|
1388
|
+
* @method
|
1389
|
+
* @name kucoin#fetchOrdersByStatus
|
1390
|
+
* @description fetch a list of orders
|
1391
|
+
* @param {str} symbol unified market symbol
|
1392
|
+
* @param {int} since timestamp in ms of the earliest order
|
1393
|
+
* @param {int} limit max number of orders to return
|
1394
|
+
* @param {dict} params exchange specific params
|
1395
|
+
* @param {int} params.till end time in ms
|
1396
|
+
* @param {bool} params.stop true if fetching stop orders
|
1397
|
+
* @param {str} params.side buy or sell
|
1398
|
+
* @param {str} params.type limit, market, limit_stop or market_stop
|
1399
|
+
* @param {str} params.tradeType TRADE for spot trading, MARGIN_TRADE for Margin Trading
|
1400
|
+
* @param {int} params.currentPage *stop orders only* current page
|
1401
|
+
* @param {str} params.orderIds *stop orders only* comma seperated order ID list
|
1402
|
+
* @returns An [array of order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
|
1403
|
+
*/
|
1404
|
+
return await this.fetchOrdersByStatus ('active', symbol, since, limit, params);
|
1405
|
+
}
|
1406
|
+
|
1407
|
+
async fetchOrder (id, symbol = undefined, params = {}) {
|
1408
|
+
/**
|
1409
|
+
* @method
|
1410
|
+
* @name kucoin#fetchOrder
|
1411
|
+
* @description fetch an order
|
1412
|
+
* @param {str} id Order id
|
1413
|
+
* @param {str} symbol not sent to exchange except for stop orders with clientOid, but used internally by CCXT to filter
|
1414
|
+
* @param {dict} params exchange specific parameters
|
1415
|
+
* @param {bool} params.stop true if fetching a stop order
|
1416
|
+
* @param {bool} params.clientOid unique order id created by users to identify their orders
|
1417
|
+
* @returns An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
|
1418
|
+
*/
|
1419
|
+
await this.loadMarkets ();
|
1420
|
+
const request = {};
|
1421
|
+
const clientOrderId = this.safeString2 (params, 'clientOid', 'clientOrderId');
|
1422
|
+
const stop = this.safeValue (params, 'stop');
|
1423
|
+
let market = undefined;
|
1424
|
+
if (symbol !== undefined) {
|
1425
|
+
market = this.market (symbol);
|
1426
|
+
}
|
1427
|
+
params = this.omit (params, 'stop');
|
1428
|
+
let method = 'privateGetOrdersOrderId';
|
1429
|
+
if (clientOrderId !== undefined) {
|
1430
|
+
request['clientOid'] = clientOrderId;
|
1431
|
+
if (stop) {
|
1432
|
+
method = 'privateGetStopOrderQueryOrderByClientOid';
|
1433
|
+
if (symbol !== undefined) {
|
1434
|
+
request['symbol'] = market['id'];
|
1435
|
+
}
|
1436
|
+
} else {
|
1437
|
+
method = 'privateGetOrderClientOrderClientOid';
|
1438
|
+
}
|
1439
|
+
} else {
|
1440
|
+
// a special case for undefined ids
|
1441
|
+
// otherwise a wrong endpoint for all orders will be triggered
|
1442
|
+
// https://github.com/ccxt/ccxt/issues/7234
|
1443
|
+
if (id === undefined) {
|
1444
|
+
throw new InvalidOrder (this.id + ' fetchOrder() requires an order id');
|
1445
|
+
}
|
1446
|
+
if (stop) {
|
1447
|
+
method = 'privateGetStopOrderOrderId';
|
1448
|
+
}
|
1449
|
+
request['orderId'] = id;
|
1450
|
+
}
|
1451
|
+
params = this.omit (params, [ 'clientOid', 'clientOrderId' ]);
|
1452
|
+
const response = await this[method] (this.extend (request, params));
|
1453
|
+
let responseData = this.safeValue (response, 'data');
|
1454
|
+
if (method === 'privateGetStopOrderQueryOrderByClientOid') {
|
1455
|
+
responseData = this.safeValue (responseData, 0);
|
1456
|
+
}
|
1457
|
+
return this.parseOrder (responseData, market);
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
parseOrder (order, market = undefined) {
|
1461
|
+
//
|
1462
|
+
// fetchOpenOrders, fetchClosedOrders
|
1463
|
+
//
|
1464
|
+
// {
|
1465
|
+
// "id": "5c35c02703aa673ceec2a168", //orderid
|
1466
|
+
// "symbol": "BTC-USDT", //symbol
|
1467
|
+
// "opType": "DEAL", // operation type,deal is pending order,cancel is cancel order
|
1468
|
+
// "type": "limit", // order type,e.g. limit,markrt,stop_limit.
|
1469
|
+
// "side": "buy", // transaction direction,include buy and sell
|
1470
|
+
// "price": "10", // order price
|
1471
|
+
// "size": "2", // order quantity
|
1472
|
+
// "funds": "0", // order funds
|
1473
|
+
// "dealFunds": "0.166", // deal funds
|
1474
|
+
// "dealSize": "2", // deal quantity
|
1475
|
+
// "fee": "0", // fee
|
1476
|
+
// "feeCurrency": "USDT", // charge fee currency
|
1477
|
+
// "stp": "", // self trade prevention,include CN,CO,DC,CB
|
1478
|
+
// "stop": "", // stop type
|
1479
|
+
// "stopTriggered": false, // stop order is triggered
|
1480
|
+
// "stopPrice": "0", // stop price
|
1481
|
+
// "timeInForce": "GTC", // time InForce,include GTC,GTT,IOC,FOK
|
1482
|
+
// "postOnly": false, // postOnly
|
1483
|
+
// "hidden": false, // hidden order
|
1484
|
+
// "iceberg": false, // iceberg order
|
1485
|
+
// "visibleSize": "0", // display quantity for iceberg order
|
1486
|
+
// "cancelAfter": 0, // cancel orders time,requires timeInForce to be GTT
|
1487
|
+
// "channel": "IOS", // order source
|
1488
|
+
// "clientOid": "", // user-entered order unique mark
|
1489
|
+
// "remark": "", // remark
|
1490
|
+
// "tags": "", // tag order source
|
1491
|
+
// "isActive": false, // status before unfilled or uncancelled
|
1492
|
+
// "cancelExist": false, // order cancellation transaction record
|
1493
|
+
// "createdAt": 1547026471000 // time
|
1494
|
+
// }
|
1495
|
+
//
|
1496
|
+
const marketId = this.safeString (order, 'symbol');
|
1497
|
+
const symbol = this.safeSymbol (marketId, market, '-');
|
1498
|
+
const orderId = this.safeString (order, 'id');
|
1499
|
+
const type = this.safeString (order, 'type');
|
1500
|
+
const timestamp = this.safeInteger (order, 'createdAt');
|
1501
|
+
const datetime = this.iso8601 (timestamp);
|
1502
|
+
const price = this.safeString (order, 'price');
|
1503
|
+
// price is zero for market order
|
1504
|
+
// omitZero is called in safeOrder2
|
1505
|
+
const side = this.safeString (order, 'side');
|
1506
|
+
const feeCurrencyId = this.safeString (order, 'feeCurrency');
|
1507
|
+
const feeCurrency = this.safeCurrencyCode (feeCurrencyId);
|
1508
|
+
const feeCost = this.safeNumber (order, 'fee');
|
1509
|
+
const amount = this.safeString (order, 'size');
|
1510
|
+
const filled = this.safeString (order, 'dealSize');
|
1511
|
+
const cost = this.safeString (order, 'dealFunds');
|
1512
|
+
// bool
|
1513
|
+
const isActive = this.safeValue (order, 'isActive', false);
|
1514
|
+
const cancelExist = this.safeValue (order, 'cancelExist', false);
|
1515
|
+
const stop = this.safeString (order, 'stop');
|
1516
|
+
const stopTriggered = this.safeValue (order, 'stopTriggered', false);
|
1517
|
+
let status = isActive ? 'open' : 'closed';
|
1518
|
+
const cancelExistWithStop = cancelExist || (!isActive && stop && !stopTriggered);
|
1519
|
+
status = cancelExistWithStop ? 'canceled' : status;
|
1520
|
+
const fee = {
|
1521
|
+
'currency': feeCurrency,
|
1522
|
+
'cost': feeCost,
|
1523
|
+
};
|
1524
|
+
const clientOrderId = this.safeString (order, 'clientOid');
|
1525
|
+
const timeInForce = this.safeString (order, 'timeInForce');
|
1526
|
+
const stopPrice = this.safeNumber (order, 'stopPrice');
|
1527
|
+
const postOnly = this.safeValue (order, 'postOnly');
|
1528
|
+
return this.safeOrder ({
|
1529
|
+
'id': orderId,
|
1530
|
+
'clientOrderId': clientOrderId,
|
1531
|
+
'symbol': symbol,
|
1532
|
+
'type': type,
|
1533
|
+
'timeInForce': timeInForce,
|
1534
|
+
'postOnly': postOnly,
|
1535
|
+
'side': side,
|
1536
|
+
'amount': amount,
|
1537
|
+
'price': price,
|
1538
|
+
'stopPrice': stopPrice,
|
1539
|
+
'cost': cost,
|
1540
|
+
'filled': filled,
|
1541
|
+
'remaining': undefined,
|
1542
|
+
'timestamp': timestamp,
|
1543
|
+
'datetime': datetime,
|
1544
|
+
'fee': fee,
|
1545
|
+
'status': status,
|
1546
|
+
'info': order,
|
1547
|
+
'lastTradeTimestamp': undefined,
|
1548
|
+
'average': undefined,
|
1549
|
+
'trades': undefined,
|
1550
|
+
}, market);
|
1551
|
+
}
|
1552
|
+
|
1553
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1554
|
+
await this.loadMarkets ();
|
1555
|
+
const request = {};
|
1556
|
+
let market = undefined;
|
1557
|
+
if (symbol !== undefined) {
|
1558
|
+
market = this.market (symbol);
|
1559
|
+
request['symbol'] = market['id'];
|
1560
|
+
}
|
1561
|
+
if (limit !== undefined) {
|
1562
|
+
request['pageSize'] = limit;
|
1563
|
+
}
|
1564
|
+
const method = this.options['fetchMyTradesMethod'];
|
1565
|
+
let parseResponseData = false;
|
1566
|
+
if (method === 'private_get_fills') {
|
1567
|
+
// does not return trades earlier than 2019-02-18T00:00:00Z
|
1568
|
+
if (since !== undefined) {
|
1569
|
+
// only returns trades up to one week after the since param
|
1570
|
+
request['startAt'] = since;
|
1571
|
+
}
|
1572
|
+
} else if (method === 'private_get_limit_fills') {
|
1573
|
+
// does not return trades earlier than 2019-02-18T00:00:00Z
|
1574
|
+
// takes no params
|
1575
|
+
// only returns first 1000 trades (not only "in the last 24 hours" as stated in the docs)
|
1576
|
+
parseResponseData = true;
|
1577
|
+
} else if (method === 'private_get_hist_orders') {
|
1578
|
+
// despite that this endpoint is called `HistOrders`
|
1579
|
+
// it returns historical trades instead of orders
|
1580
|
+
// returns trades earlier than 2019-02-18T00:00:00Z only
|
1581
|
+
if (since !== undefined) {
|
1582
|
+
request['startAt'] = parseInt (since / 1000);
|
1583
|
+
}
|
1584
|
+
} else {
|
1585
|
+
throw new ExchangeError (this.id + ' fetchMyTradesMethod() invalid method');
|
1586
|
+
}
|
1587
|
+
const response = await this[method] (this.extend (request, params));
|
1588
|
+
//
|
1589
|
+
// {
|
1590
|
+
// "currentPage": 1,
|
1591
|
+
// "pageSize": 50,
|
1592
|
+
// "totalNum": 1,
|
1593
|
+
// "totalPage": 1,
|
1594
|
+
// "items": [
|
1595
|
+
// {
|
1596
|
+
// "symbol":"BTC-USDT", // symbol
|
1597
|
+
// "tradeId":"5c35c02709e4f67d5266954e", // trade id
|
1598
|
+
// "orderId":"5c35c02703aa673ceec2a168", // order id
|
1599
|
+
// "counterOrderId":"5c1ab46003aa676e487fa8e3", // counter order id
|
1600
|
+
// "side":"buy", // transaction direction,include buy and sell
|
1601
|
+
// "liquidity":"taker", // include taker and maker
|
1602
|
+
// "forceTaker":true, // forced to become taker
|
1603
|
+
// "price":"0.083", // order price
|
1604
|
+
// "size":"0.8424304", // order quantity
|
1605
|
+
// "funds":"0.0699217232", // order funds
|
1606
|
+
// "fee":"0", // fee
|
1607
|
+
// "feeRate":"0", // fee rate
|
1608
|
+
// "feeCurrency":"USDT", // charge fee currency
|
1609
|
+
// "stop":"", // stop type
|
1610
|
+
// "type":"limit", // order type, e.g. limit, market, stop_limit.
|
1611
|
+
// "createdAt":1547026472000 // time
|
1612
|
+
// },
|
1613
|
+
// //------------------------------------------------------
|
1614
|
+
// // v1 (historical) trade response structure
|
1615
|
+
// {
|
1616
|
+
// "symbol": "SNOV-ETH",
|
1617
|
+
// "dealPrice": "0.0000246",
|
1618
|
+
// "dealValue": "0.018942",
|
1619
|
+
// "amount": "770",
|
1620
|
+
// "fee": "0.00001137",
|
1621
|
+
// "side": "sell",
|
1622
|
+
// "createdAt": 1540080199
|
1623
|
+
// "id":"5c4d389e4c8c60413f78e2e5",
|
1624
|
+
// }
|
1625
|
+
// ]
|
1626
|
+
// }
|
1627
|
+
//
|
1628
|
+
const data = this.safeValue (response, 'data', {});
|
1629
|
+
let trades = undefined;
|
1630
|
+
if (parseResponseData) {
|
1631
|
+
trades = data;
|
1632
|
+
} else {
|
1633
|
+
trades = this.safeValue (data, 'items', []);
|
1634
|
+
}
|
1635
|
+
return this.parseTrades (trades, market, since, limit);
|
1636
|
+
}
|
1637
|
+
|
1638
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
1639
|
+
await this.loadMarkets ();
|
1640
|
+
const market = this.market (symbol);
|
1641
|
+
const request = {
|
1642
|
+
'symbol': market['id'],
|
1643
|
+
};
|
1644
|
+
// pagination is not supported on the exchange side anymore
|
1645
|
+
// if (since !== undefined) {
|
1646
|
+
// request['startAt'] = Math.floor (since / 1000);
|
1647
|
+
// }
|
1648
|
+
// if (limit !== undefined) {
|
1649
|
+
// request['pageSize'] = limit;
|
1650
|
+
// }
|
1651
|
+
const response = await this.publicGetMarketHistories (this.extend (request, params));
|
1652
|
+
//
|
1653
|
+
// {
|
1654
|
+
// "code": "200000",
|
1655
|
+
// "data": [
|
1656
|
+
// {
|
1657
|
+
// "sequence": "1548764654235",
|
1658
|
+
// "side": "sell",
|
1659
|
+
// "size":"0.6841354",
|
1660
|
+
// "price":"0.03202",
|
1661
|
+
// "time":1548848575203567174
|
1662
|
+
// }
|
1663
|
+
// ]
|
1664
|
+
// }
|
1665
|
+
//
|
1666
|
+
const trades = this.safeValue (response, 'data', []);
|
1667
|
+
return this.parseTrades (trades, market, since, limit);
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
parseTrade (trade, market = undefined) {
|
1671
|
+
//
|
1672
|
+
// fetchTrades (public)
|
1673
|
+
//
|
1674
|
+
// {
|
1675
|
+
// "sequence": "1548764654235",
|
1676
|
+
// "side": "sell",
|
1677
|
+
// "size":"0.6841354",
|
1678
|
+
// "price":"0.03202",
|
1679
|
+
// "time":1548848575203567174
|
1680
|
+
// }
|
1681
|
+
//
|
1682
|
+
// {
|
1683
|
+
// sequence: '1568787654360',
|
1684
|
+
// symbol: 'BTC-USDT',
|
1685
|
+
// side: 'buy',
|
1686
|
+
// size: '0.00536577',
|
1687
|
+
// price: '9345',
|
1688
|
+
// takerOrderId: '5e356c4a9f1a790008f8d921',
|
1689
|
+
// time: '1580559434436443257',
|
1690
|
+
// type: 'match',
|
1691
|
+
// makerOrderId: '5e356bffedf0010008fa5d7f',
|
1692
|
+
// tradeId: '5e356c4aeefabd62c62a1ece'
|
1693
|
+
// }
|
1694
|
+
//
|
1695
|
+
// fetchMyTrades (private) v2
|
1696
|
+
//
|
1697
|
+
// {
|
1698
|
+
// "symbol":"BTC-USDT",
|
1699
|
+
// "tradeId":"5c35c02709e4f67d5266954e",
|
1700
|
+
// "orderId":"5c35c02703aa673ceec2a168",
|
1701
|
+
// "counterOrderId":"5c1ab46003aa676e487fa8e3",
|
1702
|
+
// "side":"buy",
|
1703
|
+
// "liquidity":"taker",
|
1704
|
+
// "forceTaker":true,
|
1705
|
+
// "price":"0.083",
|
1706
|
+
// "size":"0.8424304",
|
1707
|
+
// "funds":"0.0699217232",
|
1708
|
+
// "fee":"0",
|
1709
|
+
// "feeRate":"0",
|
1710
|
+
// "feeCurrency":"USDT",
|
1711
|
+
// "stop":"",
|
1712
|
+
// "type":"limit",
|
1713
|
+
// "createdAt":1547026472000
|
1714
|
+
// }
|
1715
|
+
//
|
1716
|
+
// fetchMyTrades v2 alternative format since 2019-05-21 https://github.com/ccxt/ccxt/pull/5162
|
1717
|
+
//
|
1718
|
+
// {
|
1719
|
+
// symbol: "OPEN-BTC",
|
1720
|
+
// forceTaker: false,
|
1721
|
+
// orderId: "5ce36420054b4663b1fff2c9",
|
1722
|
+
// fee: "0",
|
1723
|
+
// feeCurrency: "",
|
1724
|
+
// type: "",
|
1725
|
+
// feeRate: "0",
|
1726
|
+
// createdAt: 1558417615000,
|
1727
|
+
// size: "12.8206",
|
1728
|
+
// stop: "",
|
1729
|
+
// price: "0",
|
1730
|
+
// funds: "0",
|
1731
|
+
// tradeId: "5ce390cf6e0db23b861c6e80"
|
1732
|
+
// }
|
1733
|
+
//
|
1734
|
+
// fetchMyTrades (private) v1 (historical)
|
1735
|
+
//
|
1736
|
+
// {
|
1737
|
+
// "symbol": "SNOV-ETH",
|
1738
|
+
// "dealPrice": "0.0000246",
|
1739
|
+
// "dealValue": "0.018942",
|
1740
|
+
// "amount": "770",
|
1741
|
+
// "fee": "0.00001137",
|
1742
|
+
// "side": "sell",
|
1743
|
+
// "createdAt": 1540080199
|
1744
|
+
// "id":"5c4d389e4c8c60413f78e2e5",
|
1745
|
+
// }
|
1746
|
+
//
|
1747
|
+
const marketId = this.safeString (trade, 'symbol');
|
1748
|
+
market = this.safeMarket (marketId, market, '-');
|
1749
|
+
const id = this.safeString2 (trade, 'tradeId', 'id');
|
1750
|
+
const orderId = this.safeString (trade, 'orderId');
|
1751
|
+
const takerOrMaker = this.safeString (trade, 'liquidity');
|
1752
|
+
let timestamp = this.safeInteger (trade, 'time');
|
1753
|
+
if (timestamp !== undefined) {
|
1754
|
+
timestamp = parseInt (timestamp / 1000000);
|
1755
|
+
} else {
|
1756
|
+
timestamp = this.safeInteger (trade, 'createdAt');
|
1757
|
+
// if it's a historical v1 trade, the exchange returns timestamp in seconds
|
1758
|
+
if (('dealValue' in trade) && (timestamp !== undefined)) {
|
1759
|
+
timestamp = timestamp * 1000;
|
1760
|
+
}
|
1761
|
+
}
|
1762
|
+
const priceString = this.safeString2 (trade, 'price', 'dealPrice');
|
1763
|
+
const amountString = this.safeString2 (trade, 'size', 'amount');
|
1764
|
+
const side = this.safeString (trade, 'side');
|
1765
|
+
let fee = undefined;
|
1766
|
+
const feeCostString = this.safeString (trade, 'fee');
|
1767
|
+
if (feeCostString !== undefined) {
|
1768
|
+
const feeCurrencyId = this.safeString (trade, 'feeCurrency');
|
1769
|
+
let feeCurrency = this.safeCurrencyCode (feeCurrencyId);
|
1770
|
+
if (feeCurrency === undefined) {
|
1771
|
+
feeCurrency = (side === 'sell') ? market['quote'] : market['base'];
|
1772
|
+
}
|
1773
|
+
fee = {
|
1774
|
+
'cost': feeCostString,
|
1775
|
+
'currency': feeCurrency,
|
1776
|
+
'rate': this.safeString (trade, 'feeRate'),
|
1777
|
+
};
|
1778
|
+
}
|
1779
|
+
let type = this.safeString (trade, 'type');
|
1780
|
+
if (type === 'match') {
|
1781
|
+
type = undefined;
|
1782
|
+
}
|
1783
|
+
const costString = this.safeString2 (trade, 'funds', 'dealValue');
|
1784
|
+
return this.safeTrade ({
|
1785
|
+
'info': trade,
|
1786
|
+
'id': id,
|
1787
|
+
'order': orderId,
|
1788
|
+
'timestamp': timestamp,
|
1789
|
+
'datetime': this.iso8601 (timestamp),
|
1790
|
+
'symbol': market['symbol'],
|
1791
|
+
'type': type,
|
1792
|
+
'takerOrMaker': takerOrMaker,
|
1793
|
+
'side': side,
|
1794
|
+
'price': priceString,
|
1795
|
+
'amount': amountString,
|
1796
|
+
'cost': costString,
|
1797
|
+
'fee': fee,
|
1798
|
+
}, market);
|
1799
|
+
}
|
1800
|
+
|
1801
|
+
async fetchTradingFee (symbol, params = {}) {
|
1802
|
+
await this.loadMarkets ();
|
1803
|
+
const market = this.market (symbol);
|
1804
|
+
const request = {
|
1805
|
+
'symbols': market['id'],
|
1806
|
+
};
|
1807
|
+
const response = await this.privateGetTradeFees (this.extend (request, params));
|
1808
|
+
//
|
1809
|
+
// {
|
1810
|
+
// code: '200000',
|
1811
|
+
// data: [
|
1812
|
+
// {
|
1813
|
+
// symbol: 'BTC-USDT',
|
1814
|
+
// takerFeeRate: '0.001',
|
1815
|
+
// makerFeeRate: '0.001'
|
1816
|
+
// }
|
1817
|
+
// ]
|
1818
|
+
// }
|
1819
|
+
//
|
1820
|
+
const data = this.safeValue (response, 'data', []);
|
1821
|
+
const first = this.safeValue (data, 0);
|
1822
|
+
const marketId = this.safeString (first, 'symbol');
|
1823
|
+
return {
|
1824
|
+
'info': response,
|
1825
|
+
'symbol': this.safeSymbol (marketId, market),
|
1826
|
+
'maker': this.safeNumber (first, 'makerFeeRate'),
|
1827
|
+
'taker': this.safeNumber (first, 'takerFeeRate'),
|
1828
|
+
'percentage': true,
|
1829
|
+
'tierBased': true,
|
1830
|
+
};
|
1831
|
+
}
|
1832
|
+
|
1833
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
1834
|
+
[ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
|
1835
|
+
await this.loadMarkets ();
|
1836
|
+
this.checkAddress (address);
|
1837
|
+
const currency = this.currency (code);
|
1838
|
+
const request = {
|
1839
|
+
'currency': currency['id'],
|
1840
|
+
'address': address,
|
1841
|
+
'amount': amount,
|
1842
|
+
// 'memo': tag,
|
1843
|
+
// 'isInner': false, // internal transfer or external withdrawal
|
1844
|
+
// 'remark': 'optional',
|
1845
|
+
// 'chain': 'OMNI', // 'ERC20', 'TRC20', default is ERC20
|
1846
|
+
};
|
1847
|
+
if (tag !== undefined) {
|
1848
|
+
request['memo'] = tag;
|
1849
|
+
}
|
1850
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
1851
|
+
let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
|
1852
|
+
network = this.safeStringLower (networks, network, network); // handle ERC20>ETH alias
|
1853
|
+
if (network !== undefined) {
|
1854
|
+
request['chain'] = network;
|
1855
|
+
params = this.omit (params, 'network');
|
1856
|
+
}
|
1857
|
+
const response = await this.privatePostWithdrawals (this.extend (request, params));
|
1858
|
+
//
|
1859
|
+
// https://github.com/ccxt/ccxt/issues/5558
|
1860
|
+
//
|
1861
|
+
// {
|
1862
|
+
// "code": 200000,
|
1863
|
+
// "data": {
|
1864
|
+
// "withdrawalId": "5bffb63303aa675e8bbe18f9"
|
1865
|
+
// }
|
1866
|
+
// }
|
1867
|
+
//
|
1868
|
+
const data = this.safeValue (response, 'data', {});
|
1869
|
+
return this.parseTransaction (data, currency);
|
1870
|
+
}
|
1871
|
+
|
1872
|
+
parseTransactionStatus (status) {
|
1873
|
+
const statuses = {
|
1874
|
+
'SUCCESS': 'ok',
|
1875
|
+
'PROCESSING': 'ok',
|
1876
|
+
'FAILURE': 'failed',
|
1877
|
+
};
|
1878
|
+
return this.safeString (statuses, status);
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
parseTransaction (transaction, currency = undefined) {
|
1882
|
+
//
|
1883
|
+
// fetchDeposits
|
1884
|
+
//
|
1885
|
+
// {
|
1886
|
+
// "address": "0x5f047b29041bcfdbf0e4478cdfa753a336ba6989",
|
1887
|
+
// "memo": "5c247c8a03aa677cea2a251d",
|
1888
|
+
// "amount": 1,
|
1889
|
+
// "fee": 0.0001,
|
1890
|
+
// "currency": "KCS",
|
1891
|
+
// "isInner": false,
|
1892
|
+
// "walletTxId": "5bbb57386d99522d9f954c5a@test004",
|
1893
|
+
// "status": "SUCCESS",
|
1894
|
+
// "createdAt": 1544178843000,
|
1895
|
+
// "updatedAt": 1544178891000
|
1896
|
+
// "remark":"foobar"
|
1897
|
+
// }
|
1898
|
+
//
|
1899
|
+
// fetchWithdrawals
|
1900
|
+
//
|
1901
|
+
// {
|
1902
|
+
// "id": "5c2dc64e03aa675aa263f1ac",
|
1903
|
+
// "address": "0x5bedb060b8eb8d823e2414d82acce78d38be7fe9",
|
1904
|
+
// "memo": "",
|
1905
|
+
// "currency": "ETH",
|
1906
|
+
// "amount": 1.0000000,
|
1907
|
+
// "fee": 0.0100000,
|
1908
|
+
// "walletTxId": "3e2414d82acce78d38be7fe9",
|
1909
|
+
// "isInner": false,
|
1910
|
+
// "status": "FAILURE",
|
1911
|
+
// "createdAt": 1546503758000,
|
1912
|
+
// "updatedAt": 1546504603000
|
1913
|
+
// "remark":"foobar"
|
1914
|
+
// }
|
1915
|
+
//
|
1916
|
+
// withdraw
|
1917
|
+
//
|
1918
|
+
// {
|
1919
|
+
// "withdrawalId": "5bffb63303aa675e8bbe18f9"
|
1920
|
+
// }
|
1921
|
+
//
|
1922
|
+
const currencyId = this.safeString (transaction, 'currency');
|
1923
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
1924
|
+
let address = this.safeString (transaction, 'address');
|
1925
|
+
const amount = this.safeNumber (transaction, 'amount');
|
1926
|
+
let txid = this.safeString (transaction, 'walletTxId');
|
1927
|
+
if (txid !== undefined) {
|
1928
|
+
const txidParts = txid.split ('@');
|
1929
|
+
const numTxidParts = txidParts.length;
|
1930
|
+
if (numTxidParts > 1) {
|
1931
|
+
if (address === undefined) {
|
1932
|
+
if (txidParts[1].length > 1) {
|
1933
|
+
address = txidParts[1];
|
1934
|
+
}
|
1935
|
+
}
|
1936
|
+
}
|
1937
|
+
txid = txidParts[0];
|
1938
|
+
}
|
1939
|
+
let type = (txid === undefined) ? 'withdrawal' : 'deposit';
|
1940
|
+
const rawStatus = this.safeString (transaction, 'status');
|
1941
|
+
const status = this.parseTransactionStatus (rawStatus);
|
1942
|
+
let fee = undefined;
|
1943
|
+
const feeCost = this.safeNumber (transaction, 'fee');
|
1944
|
+
if (feeCost !== undefined) {
|
1945
|
+
let rate = undefined;
|
1946
|
+
if (amount !== undefined) {
|
1947
|
+
rate = feeCost / amount;
|
1948
|
+
}
|
1949
|
+
fee = {
|
1950
|
+
'cost': feeCost,
|
1951
|
+
'rate': rate,
|
1952
|
+
'currency': code,
|
1953
|
+
};
|
1954
|
+
}
|
1955
|
+
const tag = this.safeString (transaction, 'memo');
|
1956
|
+
let timestamp = this.safeInteger2 (transaction, 'createdAt', 'createAt');
|
1957
|
+
const id = this.safeString2 (transaction, 'id', 'withdrawalId');
|
1958
|
+
let updated = this.safeInteger (transaction, 'updatedAt');
|
1959
|
+
const isV1 = !('createdAt' in transaction);
|
1960
|
+
// if it's a v1 structure
|
1961
|
+
if (isV1) {
|
1962
|
+
type = ('address' in transaction) ? 'withdrawal' : 'deposit';
|
1963
|
+
if (timestamp !== undefined) {
|
1964
|
+
timestamp = timestamp * 1000;
|
1965
|
+
}
|
1966
|
+
if (updated !== undefined) {
|
1967
|
+
updated = updated * 1000;
|
1968
|
+
}
|
1969
|
+
}
|
1970
|
+
const comment = this.safeString (transaction, 'remark');
|
1971
|
+
return {
|
1972
|
+
'id': id,
|
1973
|
+
'info': transaction,
|
1974
|
+
'timestamp': timestamp,
|
1975
|
+
'datetime': this.iso8601 (timestamp),
|
1976
|
+
'network': undefined,
|
1977
|
+
'address': address,
|
1978
|
+
'addressTo': address,
|
1979
|
+
'addressFrom': undefined,
|
1980
|
+
'tag': tag,
|
1981
|
+
'tagTo': tag,
|
1982
|
+
'tagFrom': undefined,
|
1983
|
+
'currency': code,
|
1984
|
+
'amount': amount,
|
1985
|
+
'txid': txid,
|
1986
|
+
'type': type,
|
1987
|
+
'status': status,
|
1988
|
+
'comment': comment,
|
1989
|
+
'fee': fee,
|
1990
|
+
'updated': updated,
|
1991
|
+
};
|
1992
|
+
}
|
1993
|
+
|
1994
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1995
|
+
await this.loadMarkets ();
|
1996
|
+
const request = {};
|
1997
|
+
let currency = undefined;
|
1998
|
+
if (code !== undefined) {
|
1999
|
+
currency = this.currency (code);
|
2000
|
+
request['currency'] = currency['id'];
|
2001
|
+
}
|
2002
|
+
if (limit !== undefined) {
|
2003
|
+
request['pageSize'] = limit;
|
2004
|
+
}
|
2005
|
+
let method = 'privateGetDeposits';
|
2006
|
+
if (since !== undefined) {
|
2007
|
+
// if since is earlier than 2019-02-18T00:00:00Z
|
2008
|
+
if (since < 1550448000000) {
|
2009
|
+
request['startAt'] = parseInt (since / 1000);
|
2010
|
+
method = 'privateGetHistDeposits';
|
2011
|
+
} else {
|
2012
|
+
request['startAt'] = since;
|
2013
|
+
}
|
2014
|
+
}
|
2015
|
+
const response = await this[method] (this.extend (request, params));
|
2016
|
+
//
|
2017
|
+
// {
|
2018
|
+
// code: '200000',
|
2019
|
+
// data: {
|
2020
|
+
// "currentPage": 1,
|
2021
|
+
// "pageSize": 5,
|
2022
|
+
// "totalNum": 2,
|
2023
|
+
// "totalPage": 1,
|
2024
|
+
// "items": [
|
2025
|
+
// //--------------------------------------------------
|
2026
|
+
// // version 2 deposit response structure
|
2027
|
+
// {
|
2028
|
+
// "address": "0x5f047b29041bcfdbf0e4478cdfa753a336ba6989",
|
2029
|
+
// "memo": "5c247c8a03aa677cea2a251d",
|
2030
|
+
// "amount": 1,
|
2031
|
+
// "fee": 0.0001,
|
2032
|
+
// "currency": "KCS",
|
2033
|
+
// "isInner": false,
|
2034
|
+
// "walletTxId": "5bbb57386d99522d9f954c5a@test004",
|
2035
|
+
// "status": "SUCCESS",
|
2036
|
+
// "createdAt": 1544178843000,
|
2037
|
+
// "updatedAt": 1544178891000
|
2038
|
+
// "remark":"foobar"
|
2039
|
+
// },
|
2040
|
+
// //--------------------------------------------------
|
2041
|
+
// // version 1 (historical) deposit response structure
|
2042
|
+
// {
|
2043
|
+
// "currency": "BTC",
|
2044
|
+
// "createAt": 1528536998,
|
2045
|
+
// "amount": "0.03266638",
|
2046
|
+
// "walletTxId": "55c643bc2c68d6f17266383ac1be9e454038864b929ae7cee0bc408cc5c869e8@12ffGWmMMD1zA1WbFm7Ho3JZ1w6NYXjpFk@234",
|
2047
|
+
// "isInner": false,
|
2048
|
+
// "status": "SUCCESS",
|
2049
|
+
// }
|
2050
|
+
// ]
|
2051
|
+
// }
|
2052
|
+
// }
|
2053
|
+
//
|
2054
|
+
const responseData = response['data']['items'];
|
2055
|
+
return this.parseTransactions (responseData, currency, since, limit, { 'type': 'deposit' });
|
2056
|
+
}
|
2057
|
+
|
2058
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
2059
|
+
await this.loadMarkets ();
|
2060
|
+
const request = {};
|
2061
|
+
let currency = undefined;
|
2062
|
+
if (code !== undefined) {
|
2063
|
+
currency = this.currency (code);
|
2064
|
+
request['currency'] = currency['id'];
|
2065
|
+
}
|
2066
|
+
if (limit !== undefined) {
|
2067
|
+
request['pageSize'] = limit;
|
2068
|
+
}
|
2069
|
+
let method = 'privateGetWithdrawals';
|
2070
|
+
if (since !== undefined) {
|
2071
|
+
// if since is earlier than 2019-02-18T00:00:00Z
|
2072
|
+
if (since < 1550448000000) {
|
2073
|
+
request['startAt'] = parseInt (since / 1000);
|
2074
|
+
method = 'privateGetHistWithdrawals';
|
2075
|
+
} else {
|
2076
|
+
request['startAt'] = since;
|
2077
|
+
}
|
2078
|
+
}
|
2079
|
+
const response = await this[method] (this.extend (request, params));
|
2080
|
+
//
|
2081
|
+
// {
|
2082
|
+
// code: '200000',
|
2083
|
+
// data: {
|
2084
|
+
// "currentPage": 1,
|
2085
|
+
// "pageSize": 5,
|
2086
|
+
// "totalNum": 2,
|
2087
|
+
// "totalPage": 1,
|
2088
|
+
// "items": [
|
2089
|
+
// //--------------------------------------------------
|
2090
|
+
// // version 2 withdrawal response structure
|
2091
|
+
// {
|
2092
|
+
// "id": "5c2dc64e03aa675aa263f1ac",
|
2093
|
+
// "address": "0x5bedb060b8eb8d823e2414d82acce78d38be7fe9",
|
2094
|
+
// "memo": "",
|
2095
|
+
// "currency": "ETH",
|
2096
|
+
// "amount": 1.0000000,
|
2097
|
+
// "fee": 0.0100000,
|
2098
|
+
// "walletTxId": "3e2414d82acce78d38be7fe9",
|
2099
|
+
// "isInner": false,
|
2100
|
+
// "status": "FAILURE",
|
2101
|
+
// "createdAt": 1546503758000,
|
2102
|
+
// "updatedAt": 1546504603000
|
2103
|
+
// },
|
2104
|
+
// //--------------------------------------------------
|
2105
|
+
// // version 1 (historical) withdrawal response structure
|
2106
|
+
// {
|
2107
|
+
// "currency": "BTC",
|
2108
|
+
// "createAt": 1526723468,
|
2109
|
+
// "amount": "0.534",
|
2110
|
+
// "address": "33xW37ZSW4tQvg443Pc7NLCAs167Yc2XUV",
|
2111
|
+
// "walletTxId": "aeacea864c020acf58e51606169240e96774838dcd4f7ce48acf38e3651323f4",
|
2112
|
+
// "isInner": false,
|
2113
|
+
// "status": "SUCCESS"
|
2114
|
+
// }
|
2115
|
+
// ]
|
2116
|
+
// }
|
2117
|
+
// }
|
2118
|
+
//
|
2119
|
+
const responseData = response['data']['items'];
|
2120
|
+
return this.parseTransactions (responseData, currency, since, limit, { 'type': 'withdrawal' });
|
2121
|
+
}
|
2122
|
+
|
2123
|
+
async fetchBalance (params = {}) {
|
2124
|
+
await this.loadMarkets ();
|
2125
|
+
const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'spot');
|
2126
|
+
const requestedType = this.safeString (params, 'type', defaultType);
|
2127
|
+
const accountsByType = this.safeValue (this.options, 'accountsByType');
|
2128
|
+
const type = this.safeString (accountsByType, requestedType, requestedType);
|
2129
|
+
params = this.omit (params, 'type');
|
2130
|
+
const request = {
|
2131
|
+
'type': type,
|
2132
|
+
};
|
2133
|
+
const response = await this.privateGetAccounts (this.extend (request, params));
|
2134
|
+
//
|
2135
|
+
// {
|
2136
|
+
// "code":"200000",
|
2137
|
+
// "data":[
|
2138
|
+
// {"balance":"0.00009788","available":"0.00009788","holds":"0","currency":"BTC","id":"5c6a4fd399a1d81c4f9cc4d0","type":"trade"},
|
2139
|
+
// {"balance":"3.41060034","available":"3.41060034","holds":"0","currency":"SOUL","id":"5c6a4d5d99a1d8182d37046d","type":"trade"},
|
2140
|
+
// {"balance":"0.01562641","available":"0.01562641","holds":"0","currency":"NEO","id":"5c6a4f1199a1d8165a99edb1","type":"trade"},
|
2141
|
+
// ]
|
2142
|
+
// }
|
2143
|
+
//
|
2144
|
+
const data = this.safeValue (response, 'data', []);
|
2145
|
+
const result = {
|
2146
|
+
'info': response,
|
2147
|
+
'timestamp': undefined,
|
2148
|
+
'datetime': undefined,
|
2149
|
+
};
|
2150
|
+
for (let i = 0; i < data.length; i++) {
|
2151
|
+
const balance = data[i];
|
2152
|
+
const balanceType = this.safeString (balance, 'type');
|
2153
|
+
if (balanceType === type) {
|
2154
|
+
const currencyId = this.safeString (balance, 'currency');
|
2155
|
+
const code = this.safeCurrencyCode (currencyId);
|
2156
|
+
const account = this.account ();
|
2157
|
+
account['total'] = this.safeString (balance, 'balance');
|
2158
|
+
account['free'] = this.safeString (balance, 'available');
|
2159
|
+
account['used'] = this.safeString (balance, 'holds');
|
2160
|
+
result[code] = account;
|
2161
|
+
}
|
2162
|
+
}
|
2163
|
+
return this.safeBalance (result);
|
2164
|
+
}
|
2165
|
+
|
2166
|
+
async transfer (code, amount, fromAccount, toAccount, params = {}) {
|
2167
|
+
await this.loadMarkets ();
|
2168
|
+
const currency = this.currency (code);
|
2169
|
+
const requestedAmount = this.currencyToPrecision (code, amount);
|
2170
|
+
const accountsById = this.safeValue (this.options, 'accountsByType', {});
|
2171
|
+
const fromId = this.safeString (accountsById, fromAccount, fromAccount);
|
2172
|
+
const toId = this.safeString (accountsById, toAccount, toAccount);
|
2173
|
+
if (fromId === 'contract') {
|
2174
|
+
if (toId !== 'main') {
|
2175
|
+
throw new ExchangeError (this.id + ' transfer() only supports transferring from futures account to main account');
|
2176
|
+
}
|
2177
|
+
const request = {
|
2178
|
+
'currency': currency['id'],
|
2179
|
+
'amount': requestedAmount,
|
2180
|
+
};
|
2181
|
+
if (!('bizNo' in params)) {
|
2182
|
+
// it doesn't like more than 24 characters
|
2183
|
+
request['bizNo'] = this.uuid22 ();
|
2184
|
+
}
|
2185
|
+
const response = await this.futuresPrivatePostTransferOut (this.extend (request, params));
|
2186
|
+
//
|
2187
|
+
// {
|
2188
|
+
// 'code': '200000',
|
2189
|
+
// 'data': {
|
2190
|
+
// 'applyId': '605a87217dff1500063d485d',
|
2191
|
+
// 'bizNo': 'bcd6e5e1291f4905af84dc',
|
2192
|
+
// 'payAccountType': 'CONTRACT',
|
2193
|
+
// 'payTag': 'DEFAULT',
|
2194
|
+
// 'remark': '',
|
2195
|
+
// 'recAccountType': 'MAIN',
|
2196
|
+
// 'recTag': 'DEFAULT',
|
2197
|
+
// 'recRemark': '',
|
2198
|
+
// 'recSystem': 'KUCOIN',
|
2199
|
+
// 'status': 'PROCESSING',
|
2200
|
+
// 'currency': 'XBT',
|
2201
|
+
// 'amount': '0.00001',
|
2202
|
+
// 'fee': '0',
|
2203
|
+
// 'sn': '573688685663948',
|
2204
|
+
// 'reason': '',
|
2205
|
+
// 'createdAt': 1616545569000,
|
2206
|
+
// 'updatedAt': 1616545569000
|
2207
|
+
// }
|
2208
|
+
// }
|
2209
|
+
//
|
2210
|
+
const data = this.safeValue (response, 'data');
|
2211
|
+
return this.parseTransfer (data, currency);
|
2212
|
+
} else {
|
2213
|
+
const request = {
|
2214
|
+
'currency': currency['id'],
|
2215
|
+
'from': fromId,
|
2216
|
+
'to': toId,
|
2217
|
+
'amount': requestedAmount,
|
2218
|
+
};
|
2219
|
+
if (!('clientOid' in params)) {
|
2220
|
+
request['clientOid'] = this.uuid ();
|
2221
|
+
}
|
2222
|
+
const response = await this.privatePostAccountsInnerTransfer (this.extend (request, params));
|
2223
|
+
//
|
2224
|
+
// {
|
2225
|
+
// 'code': '200000',
|
2226
|
+
// 'data': {
|
2227
|
+
// 'orderId': '605a6211e657f00006ad0ad6'
|
2228
|
+
// }
|
2229
|
+
// }
|
2230
|
+
//
|
2231
|
+
const data = this.safeValue (response, 'data');
|
2232
|
+
return this.parseTransfer (data, currency);
|
2233
|
+
}
|
2234
|
+
}
|
2235
|
+
|
2236
|
+
parseTransfer (transfer, currency = undefined) {
|
2237
|
+
//
|
2238
|
+
// transfer (spot)
|
2239
|
+
//
|
2240
|
+
// {
|
2241
|
+
// 'orderId': '605a6211e657f00006ad0ad6'
|
2242
|
+
// }
|
2243
|
+
//
|
2244
|
+
//
|
2245
|
+
// transfer (futures)
|
2246
|
+
//
|
2247
|
+
// {
|
2248
|
+
// 'applyId': '605a87217dff1500063d485d',
|
2249
|
+
// 'bizNo': 'bcd6e5e1291f4905af84dc',
|
2250
|
+
// 'payAccountType': 'CONTRACT',
|
2251
|
+
// 'payTag': 'DEFAULT',
|
2252
|
+
// 'remark': '',
|
2253
|
+
// 'recAccountType': 'MAIN',
|
2254
|
+
// 'recTag': 'DEFAULT',
|
2255
|
+
// 'recRemark': '',
|
2256
|
+
// 'recSystem': 'KUCOIN',
|
2257
|
+
// 'status': 'PROCESSING',
|
2258
|
+
// 'currency': 'XBT',
|
2259
|
+
// 'amount': '0.00001',
|
2260
|
+
// 'fee': '0',
|
2261
|
+
// 'sn': '573688685663948',
|
2262
|
+
// 'reason': '',
|
2263
|
+
// 'createdAt': 1616545569000,
|
2264
|
+
// 'updatedAt': 1616545569000
|
2265
|
+
// }
|
2266
|
+
//
|
2267
|
+
const timestamp = this.safeInteger (transfer, 'createdAt');
|
2268
|
+
const currencyId = this.safeString (transfer, 'currency');
|
2269
|
+
const rawStatus = this.safeString (transfer, 'status');
|
2270
|
+
const accountFromRaw = this.safeString (transfer, 'payAccountType');
|
2271
|
+
const accountToRaw = this.safeString (transfer, 'recAccountType');
|
2272
|
+
const accountsByType = this.safeValue (this.options, 'accountsByType');
|
2273
|
+
const accountFrom = this.safeString (accountsByType, accountFromRaw.toLowerCase ());
|
2274
|
+
const accountTo = this.safeString (accountsByType, accountToRaw.toLowerCase ());
|
2275
|
+
return {
|
2276
|
+
'id': this.safeString2 (transfer, 'applyId', 'orderId'),
|
2277
|
+
'currency': this.safeCurrencyCode (currencyId, currency),
|
2278
|
+
'timestamp': timestamp,
|
2279
|
+
'datetime': this.iso8601 (timestamp),
|
2280
|
+
'amount': this.safeNumber (transfer, 'amount'),
|
2281
|
+
'fromAccount': accountFrom,
|
2282
|
+
'toAccount': accountTo,
|
2283
|
+
'status': this.parseTransferStatus (rawStatus),
|
2284
|
+
'info': transfer,
|
2285
|
+
};
|
2286
|
+
}
|
2287
|
+
|
2288
|
+
parseTransferStatus (status) {
|
2289
|
+
const statuses = {
|
2290
|
+
'PROCESSING': 'pending',
|
2291
|
+
};
|
2292
|
+
return this.safeString (statuses, status, status);
|
2293
|
+
}
|
2294
|
+
|
2295
|
+
parseLedgerEntryType (type) {
|
2296
|
+
const types = {
|
2297
|
+
'Assets Transferred in After Upgrading': 'transfer', // Assets Transferred in After V1 to V2 Upgrading
|
2298
|
+
'Deposit': 'transaction', // Deposit
|
2299
|
+
'Withdrawal': 'transaction', // Withdrawal
|
2300
|
+
'Transfer': 'transfer', // Transfer
|
2301
|
+
'Trade_Exchange': 'trade', // Trade
|
2302
|
+
// 'Vote for Coin': 'Vote for Coin', // Vote for Coin
|
2303
|
+
'KuCoin Bonus': 'bonus', // KuCoin Bonus
|
2304
|
+
'Referral Bonus': 'referral', // Referral Bonus
|
2305
|
+
'Rewards': 'bonus', // Activities Rewards
|
2306
|
+
// 'Distribution': 'Distribution', // Distribution, such as get GAS by holding NEO
|
2307
|
+
'Airdrop/Fork': 'airdrop', // Airdrop/Fork
|
2308
|
+
'Other rewards': 'bonus', // Other rewards, except Vote, Airdrop, Fork
|
2309
|
+
'Fee Rebate': 'rebate', // Fee Rebate
|
2310
|
+
'Buy Crypto': 'trade', // Use credit card to buy crypto
|
2311
|
+
'Sell Crypto': 'sell', // Use credit card to sell crypto
|
2312
|
+
'Public Offering Purchase': 'trade', // Public Offering Purchase for Spotlight
|
2313
|
+
// 'Send red envelope': 'Send red envelope', // Send red envelope
|
2314
|
+
// 'Open red envelope': 'Open red envelope', // Open red envelope
|
2315
|
+
// 'Staking': 'Staking', // Staking
|
2316
|
+
// 'LockDrop Vesting': 'LockDrop Vesting', // LockDrop Vesting
|
2317
|
+
// 'Staking Profits': 'Staking Profits', // Staking Profits
|
2318
|
+
// 'Redemption': 'Redemption', // Redemption
|
2319
|
+
'Refunded Fees': 'fee', // Refunded Fees
|
2320
|
+
'KCS Pay Fees': 'fee', // KCS Pay Fees
|
2321
|
+
'Margin Trade': 'trade', // Margin Trade
|
2322
|
+
'Loans': 'Loans', // Loans
|
2323
|
+
// 'Borrowings': 'Borrowings', // Borrowings
|
2324
|
+
// 'Debt Repayment': 'Debt Repayment', // Debt Repayment
|
2325
|
+
// 'Loans Repaid': 'Loans Repaid', // Loans Repaid
|
2326
|
+
// 'Lendings': 'Lendings', // Lendings
|
2327
|
+
// 'Pool transactions': 'Pool transactions', // Pool-X transactions
|
2328
|
+
'Instant Exchange': 'trade', // Instant Exchange
|
2329
|
+
'Sub-account transfer': 'transfer', // Sub-account transfer
|
2330
|
+
'Liquidation Fees': 'fee', // Liquidation Fees
|
2331
|
+
// 'Soft Staking Profits': 'Soft Staking Profits', // Soft Staking Profits
|
2332
|
+
// 'Voting Earnings': 'Voting Earnings', // Voting Earnings on Pool-X
|
2333
|
+
// 'Redemption of Voting': 'Redemption of Voting', // Redemption of Voting on Pool-X
|
2334
|
+
// 'Voting': 'Voting', // Voting on Pool-X
|
2335
|
+
// 'Convert to KCS': 'Convert to KCS', // Convert to KCS
|
2336
|
+
};
|
2337
|
+
return this.safeString (types, type, type);
|
2338
|
+
}
|
2339
|
+
|
2340
|
+
parseLedgerEntry (item, currency = undefined) {
|
2341
|
+
//
|
2342
|
+
// {
|
2343
|
+
// "id": "611a1e7c6a053300067a88d9", //unique key for each ledger entry
|
2344
|
+
// "currency": "USDT", //Currency
|
2345
|
+
// "amount": "10.00059547", //The total amount of assets (fees included) involved in assets changes such as transaction, withdrawal and bonus distribution.
|
2346
|
+
// "fee": "0", //Deposit or withdrawal fee
|
2347
|
+
// "balance": "0", //Total assets of a currency remaining funds after transaction
|
2348
|
+
// "accountType": "MAIN", //Account Type
|
2349
|
+
// "bizType": "Loans Repaid", //business type
|
2350
|
+
// "direction": "in", //side, in or out
|
2351
|
+
// "createdAt": 1629101692950, //Creation time
|
2352
|
+
// "context": "{\"borrowerUserId\":\"601ad03e50dc810006d242ea\",\"loanRepayDetailNo\":\"611a1e7cc913d000066cf7ec\"}" //Business core parameters
|
2353
|
+
// }
|
2354
|
+
//
|
2355
|
+
const id = this.safeString (item, 'id');
|
2356
|
+
const currencyId = this.safeString (item, 'currency');
|
2357
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
2358
|
+
const amount = this.safeNumber (item, 'amount');
|
2359
|
+
const balanceAfter = undefined;
|
2360
|
+
// const balanceAfter = this.safeNumber (item, 'balance'); only returns zero string
|
2361
|
+
const bizType = this.safeString (item, 'bizType');
|
2362
|
+
const type = this.parseLedgerEntryType (bizType);
|
2363
|
+
const direction = this.safeString (item, 'direction');
|
2364
|
+
const timestamp = this.safeInteger (item, 'createdAt');
|
2365
|
+
const datetime = this.iso8601 (timestamp);
|
2366
|
+
const account = this.safeString (item, 'accountType'); // MAIN, TRADE, MARGIN, or CONTRACT
|
2367
|
+
const context = this.safeString (item, 'context'); // contains other information about the ledger entry
|
2368
|
+
//
|
2369
|
+
// withdrawal transaction
|
2370
|
+
//
|
2371
|
+
// "{\"orderId\":\"617bb2d09e7b3b000196dac8\",\"txId\":\"0x79bb9855f86b351a45cab4dc69d78ca09586a94c45dde49475722b98f401b054\"}"
|
2372
|
+
//
|
2373
|
+
// deposit to MAIN, trade via MAIN
|
2374
|
+
//
|
2375
|
+
// "{\"orderId\":\"617ab9949e7b3b0001948081\",\"txId\":\"0x7a06b16bbd6b03dbc3d96df5683b15229fc35e7184fd7179a5f3a310bd67d1fa@default@0\"}"
|
2376
|
+
//
|
2377
|
+
// sell trade
|
2378
|
+
//
|
2379
|
+
// "{\"symbol\":\"ETH-USDT\",\"orderId\":\"617adcd1eb3fa20001dd29a1\",\"tradeId\":\"617adcd12e113d2b91222ff9\"}"
|
2380
|
+
//
|
2381
|
+
let referenceId = undefined;
|
2382
|
+
if (context !== undefined && context !== '') {
|
2383
|
+
const parsed = JSON.parse (context);
|
2384
|
+
const orderId = this.safeString (parsed, 'orderId');
|
2385
|
+
const tradeId = this.safeString (parsed, 'tradeId');
|
2386
|
+
// transactions only have an orderId but for trades we wish to use tradeId
|
2387
|
+
if (tradeId !== undefined) {
|
2388
|
+
referenceId = tradeId;
|
2389
|
+
} else {
|
2390
|
+
referenceId = orderId;
|
2391
|
+
}
|
2392
|
+
}
|
2393
|
+
let fee = undefined;
|
2394
|
+
const feeCost = this.safeNumber (item, 'fee');
|
2395
|
+
let feeCurrency = undefined;
|
2396
|
+
if (feeCost !== 0) {
|
2397
|
+
feeCurrency = code;
|
2398
|
+
fee = { 'cost': feeCost, 'currency': feeCurrency };
|
2399
|
+
}
|
2400
|
+
return {
|
2401
|
+
'id': id,
|
2402
|
+
'direction': direction,
|
2403
|
+
'account': account,
|
2404
|
+
'referenceId': referenceId,
|
2405
|
+
'referenceAccount': account,
|
2406
|
+
'type': type,
|
2407
|
+
'currency': code,
|
2408
|
+
'amount': amount,
|
2409
|
+
'timestamp': timestamp,
|
2410
|
+
'datetime': datetime,
|
2411
|
+
'before': undefined,
|
2412
|
+
'after': balanceAfter, // undefined
|
2413
|
+
'status': undefined,
|
2414
|
+
'fee': fee,
|
2415
|
+
'info': item,
|
2416
|
+
};
|
2417
|
+
}
|
2418
|
+
|
2419
|
+
async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
|
2420
|
+
await this.loadMarkets ();
|
2421
|
+
await this.loadAccounts ();
|
2422
|
+
const request = {
|
2423
|
+
// 'currency': currency['id'], // can choose up to 10, if not provided returns for all currencies by default
|
2424
|
+
// 'direction': 'in', // 'out'
|
2425
|
+
// 'bizType': 'DEPOSIT', // DEPOSIT, WITHDRAW, TRANSFER, SUB_TRANSFER,TRADE_EXCHANGE, MARGIN_EXCHANGE, KUCOIN_BONUS (optional)
|
2426
|
+
// 'startAt': since,
|
2427
|
+
// 'endAt': exchange.milliseconds (),
|
2428
|
+
};
|
2429
|
+
if (since !== undefined) {
|
2430
|
+
request['startAt'] = since;
|
2431
|
+
}
|
2432
|
+
// atm only single currency retrieval is supported
|
2433
|
+
let currency = undefined;
|
2434
|
+
if (code !== undefined) {
|
2435
|
+
currency = this.currency (code);
|
2436
|
+
request['currency'] = currency['id'];
|
2437
|
+
}
|
2438
|
+
const response = await this.privateGetAccountsLedgers (this.extend (request, params));
|
2439
|
+
//
|
2440
|
+
// {
|
2441
|
+
// "code":"200000",
|
2442
|
+
// "data":{
|
2443
|
+
// "currentPage":1,
|
2444
|
+
// "pageSize":50,
|
2445
|
+
// "totalNum":1,
|
2446
|
+
// "totalPage":1,
|
2447
|
+
// "items":[
|
2448
|
+
// {
|
2449
|
+
// "id":"617cc528729f5f0001c03ceb",
|
2450
|
+
// "currency":"GAS",
|
2451
|
+
// "amount":"0.00000339",
|
2452
|
+
// "fee":"0",
|
2453
|
+
// "balance":"0",
|
2454
|
+
// "accountType":"MAIN",
|
2455
|
+
// "bizType":"Distribution",
|
2456
|
+
// "direction":"in",
|
2457
|
+
// "createdAt":1635566888183,
|
2458
|
+
// "context":"{\"orderId\":\"617cc47a1c47ed0001ce3606\",\"description\":\"Holding NEO,distribute GAS(2021/10/30)\"}"
|
2459
|
+
// }
|
2460
|
+
// {
|
2461
|
+
// "id": "611a1e7c6a053300067a88d9",//unique key
|
2462
|
+
// "currency": "USDT", //Currency
|
2463
|
+
// "amount": "10.00059547", //Change amount of the funds
|
2464
|
+
// "fee": "0", //Deposit or withdrawal fee
|
2465
|
+
// "balance": "0", //Total assets of a currency
|
2466
|
+
// "accountType": "MAIN", //Account Type
|
2467
|
+
// "bizType": "Loans Repaid", //business type
|
2468
|
+
// "direction": "in", //side, in or out
|
2469
|
+
// "createdAt": 1629101692950, //Creation time
|
2470
|
+
// "context": "{\"borrowerUserId\":\"601ad03e50dc810006d242ea\",\"loanRepayDetailNo\":\"611a1e7cc913d000066cf7ec\"}"
|
2471
|
+
// },
|
2472
|
+
// ]
|
2473
|
+
// }
|
2474
|
+
// }
|
2475
|
+
//
|
2476
|
+
const data = this.safeValue (response, 'data');
|
2477
|
+
const items = this.safeValue (data, 'items');
|
2478
|
+
return this.parseLedger (items, currency, since, limit);
|
2479
|
+
}
|
2480
|
+
|
2481
|
+
calculateRateLimiterCost (api, method, path, params, config = {}, context = {}) {
|
2482
|
+
const versions = this.safeValue (this.options, 'versions', {});
|
2483
|
+
const apiVersions = this.safeValue (versions, api, {});
|
2484
|
+
const methodVersions = this.safeValue (apiVersions, method, {});
|
2485
|
+
const defaultVersion = this.safeString (methodVersions, path, this.options['version']);
|
2486
|
+
const version = this.safeString (params, 'version', defaultVersion);
|
2487
|
+
if (version === 'v3' && ('v3' in config)) {
|
2488
|
+
return config['v3'];
|
2489
|
+
} else if (version === 'v2' && ('v2' in config)) {
|
2490
|
+
return config['v2'];
|
2491
|
+
} else if (version === 'v1' && ('v1' in config)) {
|
2492
|
+
return config['v1'];
|
2493
|
+
}
|
2494
|
+
return this.safeInteger (config, 'cost', 1);
|
2495
|
+
}
|
2496
|
+
|
2497
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
2498
|
+
//
|
2499
|
+
// the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint
|
2500
|
+
// † ↑
|
2501
|
+
//
|
2502
|
+
const versions = this.safeValue (this.options, 'versions', {});
|
2503
|
+
const apiVersions = this.safeValue (versions, api, {});
|
2504
|
+
const methodVersions = this.safeValue (apiVersions, method, {});
|
2505
|
+
const defaultVersion = this.safeString (methodVersions, path, this.options['version']);
|
2506
|
+
const version = this.safeString (params, 'version', defaultVersion);
|
2507
|
+
params = this.omit (params, 'version');
|
2508
|
+
let endpoint = '/api/' + version + '/' + this.implodeParams (path, params);
|
2509
|
+
const query = this.omit (params, this.extractParams (path));
|
2510
|
+
let endpart = '';
|
2511
|
+
headers = (headers !== undefined) ? headers : {};
|
2512
|
+
if (Object.keys (query).length) {
|
2513
|
+
if ((method === 'GET') || (method === 'DELETE')) {
|
2514
|
+
endpoint += '?' + this.urlencode (query);
|
2515
|
+
} else {
|
2516
|
+
body = this.json (query);
|
2517
|
+
endpart = body;
|
2518
|
+
headers['Content-Type'] = 'application/json';
|
2519
|
+
}
|
2520
|
+
}
|
2521
|
+
const url = this.urls['api'][api] + endpoint;
|
2522
|
+
if ((api === 'private') || (api === 'futuresPrivate')) {
|
2523
|
+
this.checkRequiredCredentials ();
|
2524
|
+
const timestamp = this.nonce ().toString ();
|
2525
|
+
headers = this.extend ({
|
2526
|
+
'KC-API-KEY-VERSION': '2',
|
2527
|
+
'KC-API-KEY': this.apiKey,
|
2528
|
+
'KC-API-TIMESTAMP': timestamp,
|
2529
|
+
}, headers);
|
2530
|
+
const apiKeyVersion = this.safeString (headers, 'KC-API-KEY-VERSION');
|
2531
|
+
if (apiKeyVersion === '2') {
|
2532
|
+
const passphrase = this.hmac (this.encode (this.password), this.encode (this.secret), 'sha256', 'base64');
|
2533
|
+
headers['KC-API-PASSPHRASE'] = passphrase;
|
2534
|
+
} else {
|
2535
|
+
headers['KC-API-PASSPHRASE'] = this.password;
|
2536
|
+
}
|
2537
|
+
const payload = timestamp + method + endpoint + endpart;
|
2538
|
+
const signature = this.hmac (this.encode (payload), this.encode (this.secret), 'sha256', 'base64');
|
2539
|
+
headers['KC-API-SIGN'] = signature;
|
2540
|
+
const partner = this.safeValue (this.options, 'partner', {});
|
2541
|
+
const partnerId = this.safeString (partner, 'id');
|
2542
|
+
const partnerSecret = this.safeString (partner, 'secret');
|
2543
|
+
if ((partnerId !== undefined) && (partnerSecret !== undefined)) {
|
2544
|
+
const partnerPayload = timestamp + partnerId + this.apiKey;
|
2545
|
+
const partnerSignature = this.hmac (this.encode (partnerPayload), this.encode (partnerSecret), 'sha256', 'base64');
|
2546
|
+
headers['KC-API-PARTNER-SIGN'] = partnerSignature;
|
2547
|
+
headers['KC-API-PARTNER'] = partnerId;
|
2548
|
+
}
|
2549
|
+
}
|
2550
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
2551
|
+
}
|
2552
|
+
|
2553
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
2554
|
+
if (!response) {
|
2555
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], body, body);
|
2556
|
+
return;
|
2557
|
+
}
|
2558
|
+
//
|
2559
|
+
// bad
|
2560
|
+
// { "code": "400100", "msg": "validation.createOrder.clientOidIsRequired" }
|
2561
|
+
// good
|
2562
|
+
// { code: '200000', data: { ... }}
|
2563
|
+
//
|
2564
|
+
const errorCode = this.safeString (response, 'code');
|
2565
|
+
const message = this.safeString (response, 'msg', '');
|
2566
|
+
const feedback = this.id + ' ' + message;
|
2567
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
|
2568
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
|
2569
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
|
2570
|
+
}
|
2571
|
+
};
|