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/kraken.js
ADDED
@@ -0,0 +1,2179 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { BadSymbol, BadRequest, ExchangeNotAvailable, ArgumentsRequired, PermissionDenied, AuthenticationError, ExchangeError, OrderNotFound, DDoSProtection, InvalidNonce, InsufficientFunds, CancelPending, InvalidOrder, InvalidAddress, RateLimitExceeded, OnMaintenance } = require ('./base/errors');
|
7
|
+
const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number');
|
8
|
+
const Precise = require ('./base/Precise');
|
9
|
+
|
10
|
+
// ---------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module.exports = class kraken extends Exchange {
|
13
|
+
describe () {
|
14
|
+
return this.deepExtend (super.describe (), {
|
15
|
+
'id': 'kraken',
|
16
|
+
'name': 'Kraken',
|
17
|
+
'countries': [ 'US' ],
|
18
|
+
'version': '0',
|
19
|
+
'rateLimit': 3000,
|
20
|
+
'certified': false,
|
21
|
+
'pro': true,
|
22
|
+
'has': {
|
23
|
+
'CORS': undefined,
|
24
|
+
'spot': true,
|
25
|
+
'margin': true,
|
26
|
+
'swap': false,
|
27
|
+
'future': false,
|
28
|
+
'option': false,
|
29
|
+
'cancelAllOrders': true,
|
30
|
+
'cancelOrder': true,
|
31
|
+
'createDepositAddress': true,
|
32
|
+
'createOrder': true,
|
33
|
+
'createStopLimitOrder': true,
|
34
|
+
'createStopMarketOrder': true,
|
35
|
+
'createStopOrder': true,
|
36
|
+
'fetchBalance': true,
|
37
|
+
'fetchBorrowInterest': false,
|
38
|
+
'fetchBorrowRate': false,
|
39
|
+
'fetchBorrowRateHistories': false,
|
40
|
+
'fetchBorrowRateHistory': false,
|
41
|
+
'fetchBorrowRates': false,
|
42
|
+
'fetchClosedOrders': true,
|
43
|
+
'fetchCurrencies': true,
|
44
|
+
'fetchDepositAddress': true,
|
45
|
+
'fetchDeposits': true,
|
46
|
+
'fetchFundingHistory': false,
|
47
|
+
'fetchFundingRate': false,
|
48
|
+
'fetchFundingRateHistory': false,
|
49
|
+
'fetchFundingRates': false,
|
50
|
+
'fetchIndexOHLCV': false,
|
51
|
+
'fetchLedger': true,
|
52
|
+
'fetchLedgerEntry': true,
|
53
|
+
'fetchLeverageTiers': false,
|
54
|
+
'fetchMarkets': true,
|
55
|
+
'fetchMarkOHLCV': false,
|
56
|
+
'fetchMyTrades': true,
|
57
|
+
'fetchOHLCV': true,
|
58
|
+
'fetchOpenOrders': true,
|
59
|
+
'fetchOrder': true,
|
60
|
+
'fetchOrderBook': true,
|
61
|
+
'fetchOrderTrades': 'emulated',
|
62
|
+
'fetchPositions': true,
|
63
|
+
'fetchPremiumIndexOHLCV': false,
|
64
|
+
'fetchTicker': true,
|
65
|
+
'fetchTickers': true,
|
66
|
+
'fetchTime': true,
|
67
|
+
'fetchTrades': true,
|
68
|
+
'fetchTradingFee': true,
|
69
|
+
'fetchTradingFees': false,
|
70
|
+
'fetchWithdrawals': true,
|
71
|
+
'setLeverage': false,
|
72
|
+
'setMarginMode': false, // Kraken only supports cross margin
|
73
|
+
'withdraw': true,
|
74
|
+
},
|
75
|
+
'marketsByAltname': {},
|
76
|
+
'timeframes': {
|
77
|
+
'1m': 1,
|
78
|
+
'5m': 5,
|
79
|
+
'15m': 15,
|
80
|
+
'30m': 30,
|
81
|
+
'1h': 60,
|
82
|
+
'4h': 240,
|
83
|
+
'1d': 1440,
|
84
|
+
'1w': 10080,
|
85
|
+
'2w': 21600,
|
86
|
+
},
|
87
|
+
'urls': {
|
88
|
+
'logo': 'https://user-images.githubusercontent.com/51840849/76173629-fc67fb00-61b1-11ea-84fe-f2de582f58a3.jpg',
|
89
|
+
'api': {
|
90
|
+
'public': 'https://api.kraken.com',
|
91
|
+
'private': 'https://api.kraken.com',
|
92
|
+
'zendesk': 'https://kraken.zendesk.com/api/v2/help_center/en-us/articles', // use the public zendesk api to receive article bodies and bypass new anti-spam protections
|
93
|
+
},
|
94
|
+
'www': 'https://www.kraken.com',
|
95
|
+
'doc': 'https://www.kraken.com/features/api',
|
96
|
+
'fees': 'https://www.kraken.com/en-us/features/fee-schedule',
|
97
|
+
},
|
98
|
+
'fees': {
|
99
|
+
'trading': {
|
100
|
+
'tierBased': true,
|
101
|
+
'percentage': true,
|
102
|
+
'taker': 0.26 / 100,
|
103
|
+
'maker': 0.16 / 100,
|
104
|
+
'tiers': {
|
105
|
+
'taker': [
|
106
|
+
[ 0, 0.0026 ],
|
107
|
+
[ 50000, 0.0024 ],
|
108
|
+
[ 100000, 0.0022 ],
|
109
|
+
[ 250000, 0.0020 ],
|
110
|
+
[ 500000, 0.0018 ],
|
111
|
+
[ 1000000, 0.0016 ],
|
112
|
+
[ 2500000, 0.0014 ],
|
113
|
+
[ 5000000, 0.0012 ],
|
114
|
+
[ 10000000, 0.0001 ],
|
115
|
+
],
|
116
|
+
'maker': [
|
117
|
+
[ 0, 0.0016 ],
|
118
|
+
[ 50000, 0.0014 ],
|
119
|
+
[ 100000, 0.0012 ],
|
120
|
+
[ 250000, 0.0010 ],
|
121
|
+
[ 500000, 0.0008 ],
|
122
|
+
[ 1000000, 0.0006 ],
|
123
|
+
[ 2500000, 0.0004 ],
|
124
|
+
[ 5000000, 0.0002 ],
|
125
|
+
[ 10000000, 0.0 ],
|
126
|
+
],
|
127
|
+
},
|
128
|
+
},
|
129
|
+
},
|
130
|
+
'handleContentTypeApplicationZip': true,
|
131
|
+
'api': {
|
132
|
+
'zendesk': {
|
133
|
+
'get': [
|
134
|
+
// we should really refrain from putting fixed fee numbers and stop hardcoding
|
135
|
+
// we will be using their web APIs to scrape all numbers from these articles
|
136
|
+
'360000292886', // -What-are-the-deposit-fees-
|
137
|
+
'201893608', // -What-are-the-withdrawal-fees-
|
138
|
+
],
|
139
|
+
},
|
140
|
+
'public': {
|
141
|
+
'get': [
|
142
|
+
'Assets',
|
143
|
+
'AssetPairs',
|
144
|
+
'Depth',
|
145
|
+
'OHLC',
|
146
|
+
'Spread',
|
147
|
+
'Ticker',
|
148
|
+
'Time',
|
149
|
+
'Trades',
|
150
|
+
],
|
151
|
+
},
|
152
|
+
'private': {
|
153
|
+
'post': {
|
154
|
+
'AddOrder': 0,
|
155
|
+
'AddExport': 1,
|
156
|
+
'Balance': 1,
|
157
|
+
'CancelAll': 1,
|
158
|
+
'CancelOrder': 0,
|
159
|
+
'ClosedOrders': 2,
|
160
|
+
'DepositAddresses': 1,
|
161
|
+
'DepositMethods': 1,
|
162
|
+
'DepositStatus': 1,
|
163
|
+
'ExportStatus': 1,
|
164
|
+
'GetWebSocketsToken': 1,
|
165
|
+
'Ledgers': 2,
|
166
|
+
'OpenOrders': 1,
|
167
|
+
'OpenPositions': 1,
|
168
|
+
'QueryLedgers': 1,
|
169
|
+
'QueryOrders': 1,
|
170
|
+
'QueryTrades': 1,
|
171
|
+
'RetrieveExport': 1,
|
172
|
+
'RemoveExport': 1,
|
173
|
+
'TradeBalance': 1,
|
174
|
+
'TradesHistory': 2,
|
175
|
+
'TradeVolume': 1,
|
176
|
+
'Withdraw': 1,
|
177
|
+
'WithdrawCancel': 1,
|
178
|
+
'WithdrawInfo': 1,
|
179
|
+
'WithdrawStatus': 1,
|
180
|
+
// staking
|
181
|
+
'Stake': 1,
|
182
|
+
'Unstake': 1,
|
183
|
+
'Staking/Assets': 1,
|
184
|
+
'Staking/Pending': 1,
|
185
|
+
'Staking/Transactions': 1,
|
186
|
+
},
|
187
|
+
},
|
188
|
+
},
|
189
|
+
'commonCurrencies': {
|
190
|
+
'XBT': 'BTC',
|
191
|
+
'XBT.M': 'BTC.M', // https://support.kraken.com/hc/en-us/articles/360039879471-What-is-Asset-S-and-Asset-M-
|
192
|
+
'XDG': 'DOGE',
|
193
|
+
'REPV2': 'REP',
|
194
|
+
'REP': 'REPV1',
|
195
|
+
},
|
196
|
+
'options': {
|
197
|
+
'delistedMarketsById': {},
|
198
|
+
// cannot withdraw/deposit these
|
199
|
+
'inactiveCurrencies': [ 'CAD', 'USD', 'JPY', 'GBP' ],
|
200
|
+
'networks': {
|
201
|
+
'ETH': 'ERC20',
|
202
|
+
'TRX': 'TRC20',
|
203
|
+
},
|
204
|
+
'depositMethods': {
|
205
|
+
'1INCH': '1inch (1INCH)',
|
206
|
+
'AAVE': 'Aave',
|
207
|
+
'ADA': 'ADA',
|
208
|
+
'ALGO': 'Algorand',
|
209
|
+
'ANKR': 'ANKR (ANKR)',
|
210
|
+
'ANT': 'Aragon (ANT)',
|
211
|
+
'ATOM': 'Cosmos',
|
212
|
+
'AXS': 'Axie Infinity Shards (AXS)',
|
213
|
+
'BADGER': 'Bager DAO (BADGER)',
|
214
|
+
'BAL': 'Balancer (BAL)',
|
215
|
+
'BAND': 'Band Protocol (BAND)',
|
216
|
+
'BAT': 'BAT',
|
217
|
+
'BCH': 'Bitcoin Cash',
|
218
|
+
'BNC': 'Bifrost (BNC)',
|
219
|
+
'BNT': 'Bancor (BNT)',
|
220
|
+
'BTC': 'Bitcoin',
|
221
|
+
'CHZ': 'Chiliz (CHZ)',
|
222
|
+
'COMP': 'Compound (COMP)',
|
223
|
+
'CQT': '\tCovalent Query Token (CQT)',
|
224
|
+
'CRV': 'Curve DAO Token (CRV)',
|
225
|
+
'CTSI': 'Cartesi (CTSI)',
|
226
|
+
'DAI': 'Dai',
|
227
|
+
'DASH': 'Dash',
|
228
|
+
'DOGE': 'Dogecoin',
|
229
|
+
'DOT': 'Polkadot',
|
230
|
+
'DYDX': 'dYdX (DYDX)',
|
231
|
+
'ENJ': 'Enjin Coin (ENJ)',
|
232
|
+
'EOS': 'EOS',
|
233
|
+
'ETC': 'Ether Classic (Hex)',
|
234
|
+
'ETH': 'Ether (Hex)',
|
235
|
+
'EWT': 'Energy Web Token',
|
236
|
+
'FEE': 'Kraken Fee Credit',
|
237
|
+
'FIL': 'Filecoin',
|
238
|
+
'FLOW': 'Flow',
|
239
|
+
'GHST': 'Aavegotchi (GHST)',
|
240
|
+
'GNO': 'GNO',
|
241
|
+
'GRT': 'GRT',
|
242
|
+
'ICX': 'Icon',
|
243
|
+
'INJ': 'Injective Protocol (INJ)',
|
244
|
+
'KAR': 'Karura (KAR)',
|
245
|
+
'KAVA': 'Kava',
|
246
|
+
'KEEP': 'Keep Token (KEEP)',
|
247
|
+
'KNC': 'Kyber Network (KNC)',
|
248
|
+
'KSM': 'Kusama',
|
249
|
+
'LINK': 'Link',
|
250
|
+
'LPT': 'Livepeer Token (LPT)',
|
251
|
+
'LRC': 'Loopring (LRC)',
|
252
|
+
'LSK': 'Lisk',
|
253
|
+
'LTC': 'Litecoin',
|
254
|
+
'MANA': 'MANA',
|
255
|
+
'MATIC': 'Polygon (MATIC)',
|
256
|
+
'MINA': 'Mina', // inspected from webui
|
257
|
+
'MIR': 'Mirror Protocol (MIR)',
|
258
|
+
'MKR': 'Maker (MKR)',
|
259
|
+
'MLN': 'MLN',
|
260
|
+
'MOVR': 'Moonriver (MOVR)',
|
261
|
+
'NANO': 'NANO',
|
262
|
+
'OCEAN': 'OCEAN',
|
263
|
+
'OGN': 'Origin Protocol (OGN)',
|
264
|
+
'OMG': 'OMG',
|
265
|
+
'OXT': 'Orchid (OXT)',
|
266
|
+
'OXY': 'Oxygen (OXY)',
|
267
|
+
'PAXG': 'PAX (Gold)',
|
268
|
+
'PERP': 'Perpetual Protocol (PERP)',
|
269
|
+
'PHA': 'Phala (PHA)',
|
270
|
+
'QTUM': 'QTUM',
|
271
|
+
'RARI': 'Rarible (RARI)',
|
272
|
+
'RAY': 'Raydium (RAY)',
|
273
|
+
'REN': 'Ren Protocol (REN)',
|
274
|
+
'REP': 'REPv2',
|
275
|
+
'REPV1': 'REP',
|
276
|
+
'SAND': 'The Sandbox (SAND)',
|
277
|
+
'SC': 'Siacoin',
|
278
|
+
'SDN': 'Shiden (SDN)',
|
279
|
+
'SOL': 'Solana', // their deposit method api doesn't work for SOL - was guessed
|
280
|
+
'SNX': 'Synthetix Network (SNX)',
|
281
|
+
'SRM': 'Serum', // inspected from webui
|
282
|
+
'STORJ': 'Storj (STORJ)',
|
283
|
+
'SUSHI': 'Sushiswap (SUSHI)',
|
284
|
+
'TBTC': 'tBTC',
|
285
|
+
'TRX': 'Tron',
|
286
|
+
'UNI': 'UNI',
|
287
|
+
'USDC': 'USDC',
|
288
|
+
'USDT': 'Tether USD (ERC20)',
|
289
|
+
'USDT-TRC20': 'Tether USD (TRC20)',
|
290
|
+
'WAVES': 'Waves',
|
291
|
+
'WBTC': 'Wrapped Bitcoin (WBTC)',
|
292
|
+
'XLM': 'Stellar XLM',
|
293
|
+
'XMR': 'Monero',
|
294
|
+
'XRP': 'Ripple XRP',
|
295
|
+
'XTZ': 'XTZ',
|
296
|
+
'YFI': 'YFI',
|
297
|
+
'ZEC': 'Zcash (Transparent)',
|
298
|
+
'ZRX': '0x (ZRX)',
|
299
|
+
},
|
300
|
+
},
|
301
|
+
'exceptions': {
|
302
|
+
'EQuery:Invalid asset pair': BadSymbol, // {"error":["EQuery:Invalid asset pair"]}
|
303
|
+
'EAPI:Invalid key': AuthenticationError,
|
304
|
+
'EFunding:Unknown withdraw key': InvalidAddress, // {"error":["EFunding:Unknown withdraw key"]}
|
305
|
+
'EFunding:Invalid amount': InsufficientFunds,
|
306
|
+
'EService:Unavailable': ExchangeNotAvailable,
|
307
|
+
'EDatabase:Internal error': ExchangeNotAvailable,
|
308
|
+
'EService:Busy': ExchangeNotAvailable,
|
309
|
+
'EQuery:Unknown asset': BadSymbol, // {"error":["EQuery:Unknown asset"]}
|
310
|
+
'EAPI:Rate limit exceeded': DDoSProtection,
|
311
|
+
'EOrder:Rate limit exceeded': DDoSProtection,
|
312
|
+
'EGeneral:Internal error': ExchangeNotAvailable,
|
313
|
+
'EGeneral:Temporary lockout': DDoSProtection,
|
314
|
+
'EGeneral:Permission denied': PermissionDenied,
|
315
|
+
'EOrder:Unknown order': InvalidOrder,
|
316
|
+
'EOrder:Order minimum not met': InvalidOrder,
|
317
|
+
'EGeneral:Invalid arguments': BadRequest,
|
318
|
+
'ESession:Invalid session': AuthenticationError,
|
319
|
+
'EAPI:Invalid nonce': InvalidNonce,
|
320
|
+
'EFunding:No funding method': BadRequest, // {"error":"EFunding:No funding method"}
|
321
|
+
'EFunding:Unknown asset': BadSymbol, // {"error":["EFunding:Unknown asset"]}
|
322
|
+
'EService:Market in post_only mode': OnMaintenance, // {"error":["EService:Market in post_only mode"]}
|
323
|
+
},
|
324
|
+
});
|
325
|
+
}
|
326
|
+
|
327
|
+
costToPrecision (symbol, cost) {
|
328
|
+
return this.decimalToPrecision (cost, TRUNCATE, this.markets[symbol]['precision']['price'], DECIMAL_PLACES);
|
329
|
+
}
|
330
|
+
|
331
|
+
feeToPrecision (symbol, fee) {
|
332
|
+
return this.decimalToPrecision (fee, TRUNCATE, this.markets[symbol]['precision']['amount'], DECIMAL_PLACES);
|
333
|
+
}
|
334
|
+
|
335
|
+
async fetchMarkets (params = {}) {
|
336
|
+
const response = await this.publicGetAssetPairs (params);
|
337
|
+
//
|
338
|
+
// {
|
339
|
+
// "error":[],
|
340
|
+
// "result":{
|
341
|
+
// "ADAETH":{
|
342
|
+
// "altname":"ADAETH",
|
343
|
+
// "wsname":"ADA\/ETH",
|
344
|
+
// "aclass_base":"currency",
|
345
|
+
// "base":"ADA",
|
346
|
+
// "aclass_quote":"currency",
|
347
|
+
// "quote":"XETH",
|
348
|
+
// "lot":"unit",
|
349
|
+
// "pair_decimals":7,
|
350
|
+
// "lot_decimals":8,
|
351
|
+
// "lot_multiplier":1,
|
352
|
+
// "leverage_buy":[],
|
353
|
+
// "leverage_sell":[],
|
354
|
+
// "fees":[
|
355
|
+
// [0,0.26],
|
356
|
+
// [50000,0.24],
|
357
|
+
// [100000,0.22],
|
358
|
+
// [250000,0.2],
|
359
|
+
// [500000,0.18],
|
360
|
+
// [1000000,0.16],
|
361
|
+
// [2500000,0.14],
|
362
|
+
// [5000000,0.12],
|
363
|
+
// [10000000,0.1]
|
364
|
+
// ],
|
365
|
+
// "fees_maker":[
|
366
|
+
// [0,0.16],
|
367
|
+
// [50000,0.14],
|
368
|
+
// [100000,0.12],
|
369
|
+
// [250000,0.1],
|
370
|
+
// [500000,0.08],
|
371
|
+
// [1000000,0.06],
|
372
|
+
// [2500000,0.04],
|
373
|
+
// [5000000,0.02],
|
374
|
+
// [10000000,0]
|
375
|
+
// ],
|
376
|
+
// "fee_volume_currency":"ZUSD",
|
377
|
+
// "margin_call":80,
|
378
|
+
// "margin_stop":40,
|
379
|
+
// "ordermin": "1"
|
380
|
+
// },
|
381
|
+
// }
|
382
|
+
// }
|
383
|
+
//
|
384
|
+
const markets = this.safeValue (response, 'result', {});
|
385
|
+
const keys = Object.keys (markets);
|
386
|
+
let result = [];
|
387
|
+
for (let i = 0; i < keys.length; i++) {
|
388
|
+
const id = keys[i];
|
389
|
+
const market = markets[id];
|
390
|
+
const baseId = this.safeString (market, 'base');
|
391
|
+
const quoteId = this.safeString (market, 'quote');
|
392
|
+
const base = this.safeCurrencyCode (baseId);
|
393
|
+
const quote = this.safeCurrencyCode (quoteId);
|
394
|
+
const darkpool = id.indexOf ('.d') >= 0;
|
395
|
+
const altname = this.safeString (market, 'altname');
|
396
|
+
const makerFees = this.safeValue (market, 'fees_maker', []);
|
397
|
+
const firstMakerFee = this.safeValue (makerFees, 0, []);
|
398
|
+
const firstMakerFeeRate = this.safeNumber (firstMakerFee, 1);
|
399
|
+
let maker = undefined;
|
400
|
+
if (firstMakerFeeRate !== undefined) {
|
401
|
+
maker = parseFloat (firstMakerFeeRate) / 100;
|
402
|
+
}
|
403
|
+
const takerFees = this.safeValue (market, 'fees', []);
|
404
|
+
const firstTakerFee = this.safeValue (takerFees, 0, []);
|
405
|
+
const firstTakerFeeRate = this.safeNumber (firstTakerFee, 1);
|
406
|
+
let taker = undefined;
|
407
|
+
if (firstTakerFeeRate !== undefined) {
|
408
|
+
taker = parseFloat (firstTakerFeeRate) / 100;
|
409
|
+
}
|
410
|
+
const leverageBuy = this.safeValue (market, 'leverage_buy', []);
|
411
|
+
const leverageBuyLength = leverageBuy.length;
|
412
|
+
const precisionPrice = this.safeString (market, 'pair_decimals');
|
413
|
+
result.push ({
|
414
|
+
'id': id,
|
415
|
+
'symbol': darkpool ? altname : (base + '/' + quote),
|
416
|
+
'base': base,
|
417
|
+
'quote': quote,
|
418
|
+
'settle': undefined,
|
419
|
+
'baseId': baseId,
|
420
|
+
'quoteId': quoteId,
|
421
|
+
'settleId': undefined,
|
422
|
+
'darkpool': darkpool,
|
423
|
+
'altname': market['altname'],
|
424
|
+
'type': 'spot',
|
425
|
+
'spot': true,
|
426
|
+
'margin': (leverageBuyLength > 0),
|
427
|
+
'swap': false,
|
428
|
+
'future': false,
|
429
|
+
'option': false,
|
430
|
+
'active': true,
|
431
|
+
'contract': false,
|
432
|
+
'linear': undefined,
|
433
|
+
'inverse': undefined,
|
434
|
+
'taker': taker,
|
435
|
+
'maker': maker,
|
436
|
+
'contractSize': undefined,
|
437
|
+
'expiry': undefined,
|
438
|
+
'expiryDatetime': undefined,
|
439
|
+
'strike': undefined,
|
440
|
+
'optionType': undefined,
|
441
|
+
'precision': {
|
442
|
+
'amount': this.safeInteger (market, 'lot_decimals'),
|
443
|
+
'price': this.safeInteger (market, 'pair_decimals'),
|
444
|
+
},
|
445
|
+
'limits': {
|
446
|
+
'leverage': {
|
447
|
+
'min': this.parseNumber ('1'),
|
448
|
+
'max': this.safeNumber (leverageBuy, leverageBuyLength - 1, 1),
|
449
|
+
},
|
450
|
+
'amount': {
|
451
|
+
'min': this.safeNumber (market, 'ordermin'),
|
452
|
+
'max': undefined,
|
453
|
+
},
|
454
|
+
'price': {
|
455
|
+
'min': this.parseNumber (this.parsePrecision (precisionPrice)),
|
456
|
+
'max': undefined,
|
457
|
+
},
|
458
|
+
'cost': {
|
459
|
+
'min': undefined,
|
460
|
+
'max': undefined,
|
461
|
+
},
|
462
|
+
},
|
463
|
+
'info': market,
|
464
|
+
});
|
465
|
+
}
|
466
|
+
result = this.appendInactiveMarkets (result);
|
467
|
+
this.marketsByAltname = this.indexBy (result, 'altname');
|
468
|
+
return result;
|
469
|
+
}
|
470
|
+
|
471
|
+
safeCurrency (currencyId, currency = undefined) {
|
472
|
+
if (currencyId !== undefined) {
|
473
|
+
if (currencyId.length > 3) {
|
474
|
+
if ((currencyId.indexOf ('X') === 0) || (currencyId.indexOf ('Z') === 0)) {
|
475
|
+
if (currencyId.indexOf ('.') > 0) {
|
476
|
+
return super.safeCurrency (currencyId, currency);
|
477
|
+
} else {
|
478
|
+
currencyId = currencyId.slice (1);
|
479
|
+
}
|
480
|
+
}
|
481
|
+
}
|
482
|
+
}
|
483
|
+
return super.safeCurrency (currencyId, currency);
|
484
|
+
}
|
485
|
+
|
486
|
+
appendInactiveMarkets (result) {
|
487
|
+
// result should be an array to append to
|
488
|
+
const precision = { 'amount': 8, 'price': 8 };
|
489
|
+
const costLimits = { 'min': 0, 'max': undefined };
|
490
|
+
const priceLimits = { 'min': Math.pow (10, -precision['price']), 'max': undefined };
|
491
|
+
const amountLimits = { 'min': Math.pow (10, -precision['amount']), 'max': Math.pow (10, precision['amount']) };
|
492
|
+
const limits = { 'amount': amountLimits, 'price': priceLimits, 'cost': costLimits };
|
493
|
+
const defaults = {
|
494
|
+
'darkpool': false,
|
495
|
+
'info': undefined,
|
496
|
+
'maker': undefined,
|
497
|
+
'taker': undefined,
|
498
|
+
'active': false,
|
499
|
+
'precision': precision,
|
500
|
+
'limits': limits,
|
501
|
+
};
|
502
|
+
const markets = [
|
503
|
+
// { 'id': 'XXLMZEUR', 'symbol': 'XLM/EUR', 'base': 'XLM', 'quote': 'EUR', 'altname': 'XLMEUR' },
|
504
|
+
];
|
505
|
+
for (let i = 0; i < markets.length; i++) {
|
506
|
+
result.push (this.extend (defaults, markets[i]));
|
507
|
+
}
|
508
|
+
return result;
|
509
|
+
}
|
510
|
+
|
511
|
+
async fetchCurrencies (params = {}) {
|
512
|
+
const response = await this.publicGetAssets (params);
|
513
|
+
//
|
514
|
+
// {
|
515
|
+
// "error": [],
|
516
|
+
// "result": {
|
517
|
+
// "ADA": { "aclass": "currency", "altname": "ADA", "decimals": 8, "display_decimals": 6 },
|
518
|
+
// "BCH": { "aclass": "currency", "altname": "BCH", "decimals": 10, "display_decimals": 5 },
|
519
|
+
// ...
|
520
|
+
// },
|
521
|
+
// }
|
522
|
+
//
|
523
|
+
const currencies = this.safeValue (response, 'result');
|
524
|
+
const ids = Object.keys (currencies);
|
525
|
+
const result = {};
|
526
|
+
for (let i = 0; i < ids.length; i++) {
|
527
|
+
const id = ids[i];
|
528
|
+
const currency = currencies[id];
|
529
|
+
// todo: will need to rethink the fees
|
530
|
+
// see: https://support.kraken.com/hc/en-us/articles/201893608-What-are-the-withdrawal-fees-
|
531
|
+
// to add support for multiple withdrawal/deposit methods and
|
532
|
+
// differentiated fees for each particular method
|
533
|
+
const code = this.safeCurrencyCode (this.safeString (currency, 'altname'));
|
534
|
+
const precision = this.safeInteger (currency, 'decimals');
|
535
|
+
// assumes all currencies are active except those listed above
|
536
|
+
const active = !this.inArray (code, this.options['inactiveCurrencies']);
|
537
|
+
result[code] = {
|
538
|
+
'id': id,
|
539
|
+
'code': code,
|
540
|
+
'info': currency,
|
541
|
+
'name': code,
|
542
|
+
'active': active,
|
543
|
+
'deposit': undefined,
|
544
|
+
'withdraw': undefined,
|
545
|
+
'fee': undefined,
|
546
|
+
'precision': precision,
|
547
|
+
'limits': {
|
548
|
+
'amount': {
|
549
|
+
'min': Math.pow (10, -precision),
|
550
|
+
'max': Math.pow (10, precision),
|
551
|
+
},
|
552
|
+
'withdraw': {
|
553
|
+
'min': undefined,
|
554
|
+
'max': Math.pow (10, precision),
|
555
|
+
},
|
556
|
+
},
|
557
|
+
};
|
558
|
+
}
|
559
|
+
return result;
|
560
|
+
}
|
561
|
+
|
562
|
+
async fetchTradingFee (symbol, params = {}) {
|
563
|
+
await this.loadMarkets ();
|
564
|
+
const market = this.market (symbol);
|
565
|
+
const request = {
|
566
|
+
'pair': market['id'],
|
567
|
+
'fee-info': true,
|
568
|
+
};
|
569
|
+
const response = await this.privatePostTradeVolume (this.extend (request, params));
|
570
|
+
//
|
571
|
+
// {
|
572
|
+
// error: [],
|
573
|
+
// result: {
|
574
|
+
// currency: 'ZUSD',
|
575
|
+
// volume: '0.0000',
|
576
|
+
// fees: {
|
577
|
+
// XXBTZUSD: {
|
578
|
+
// fee: '0.2600',
|
579
|
+
// minfee: '0.1000',
|
580
|
+
// maxfee: '0.2600',
|
581
|
+
// nextfee: '0.2400',
|
582
|
+
// tiervolume: '0.0000',
|
583
|
+
// nextvolume: '50000.0000'
|
584
|
+
// }
|
585
|
+
// },
|
586
|
+
// fees_maker: {
|
587
|
+
// XXBTZUSD: {
|
588
|
+
// fee: '0.1600',
|
589
|
+
// minfee: '0.0000',
|
590
|
+
// maxfee: '0.1600',
|
591
|
+
// nextfee: '0.1400',
|
592
|
+
// tiervolume: '0.0000',
|
593
|
+
// nextvolume: '50000.0000'
|
594
|
+
// }
|
595
|
+
// }
|
596
|
+
// }
|
597
|
+
// }
|
598
|
+
//
|
599
|
+
const result = this.safeValue (response, 'result', {});
|
600
|
+
return this.parseTradingFee (result, market);
|
601
|
+
}
|
602
|
+
|
603
|
+
parseTradingFee (response, market) {
|
604
|
+
const makerFees = this.safeValue (response, 'fees_maker', {});
|
605
|
+
const takerFees = this.safeValue (response, 'fees', {});
|
606
|
+
const symbolMakerFee = this.safeValue (makerFees, market['id'], {});
|
607
|
+
const symbolTakerFee = this.safeValue (takerFees, market['id'], {});
|
608
|
+
return {
|
609
|
+
'info': response,
|
610
|
+
'symbol': market['symbol'],
|
611
|
+
'maker': this.safeNumber (symbolMakerFee, 'fee'),
|
612
|
+
'taker': this.safeNumber (symbolTakerFee, 'fee'),
|
613
|
+
'percentage': true,
|
614
|
+
'tierBased': true,
|
615
|
+
};
|
616
|
+
}
|
617
|
+
|
618
|
+
parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
|
619
|
+
const price = this.safeNumber (bidask, priceKey);
|
620
|
+
const amount = this.safeNumber (bidask, amountKey);
|
621
|
+
const timestamp = this.safeInteger (bidask, 2);
|
622
|
+
return [ price, amount, timestamp ];
|
623
|
+
}
|
624
|
+
|
625
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
626
|
+
await this.loadMarkets ();
|
627
|
+
const market = this.market (symbol);
|
628
|
+
if (market['darkpool']) {
|
629
|
+
throw new ExchangeError (this.id + ' fetchOrderBook() does not provide an order book for darkpool symbol ' + symbol);
|
630
|
+
}
|
631
|
+
const request = {
|
632
|
+
'pair': market['id'],
|
633
|
+
};
|
634
|
+
if (limit !== undefined) {
|
635
|
+
request['count'] = limit; // 100
|
636
|
+
}
|
637
|
+
const response = await this.publicGetDepth (this.extend (request, params));
|
638
|
+
//
|
639
|
+
// {
|
640
|
+
// "error":[],
|
641
|
+
// "result":{
|
642
|
+
// "XETHXXBT":{
|
643
|
+
// "asks":[
|
644
|
+
// ["0.023480","4.000",1586321307],
|
645
|
+
// ["0.023490","50.095",1586321306],
|
646
|
+
// ["0.023500","28.535",1586321302],
|
647
|
+
// ],
|
648
|
+
// "bids":[
|
649
|
+
// ["0.023470","59.580",1586321307],
|
650
|
+
// ["0.023460","20.000",1586321301],
|
651
|
+
// ["0.023440","67.832",1586321306],
|
652
|
+
// ]
|
653
|
+
// }
|
654
|
+
// }
|
655
|
+
// }
|
656
|
+
//
|
657
|
+
const result = this.safeValue (response, 'result', {});
|
658
|
+
let orderbook = this.safeValue (result, market['id']);
|
659
|
+
// sometimes kraken returns wsname instead of market id
|
660
|
+
// https://github.com/ccxt/ccxt/issues/8662
|
661
|
+
const marketInfo = this.safeValue (market, 'info', {});
|
662
|
+
const wsName = this.safeValue (marketInfo, 'wsname');
|
663
|
+
if (wsName !== undefined) {
|
664
|
+
orderbook = this.safeValue (result, wsName, orderbook);
|
665
|
+
}
|
666
|
+
return this.parseOrderBook (orderbook, symbol);
|
667
|
+
}
|
668
|
+
|
669
|
+
parseTicker (ticker, market = undefined) {
|
670
|
+
//
|
671
|
+
// {
|
672
|
+
// "a":["2432.77000","1","1.000"],
|
673
|
+
// "b":["2431.37000","2","2.000"],
|
674
|
+
// "c":["2430.58000","0.04408910"],
|
675
|
+
// "v":["4147.94474901","8896.96086304"],
|
676
|
+
// "p":["2456.22239","2568.63032"],
|
677
|
+
// "t":[3907,10056],
|
678
|
+
// "l":["2302.18000","2302.18000"],
|
679
|
+
// "h":["2621.14000","2860.01000"],
|
680
|
+
// "o":"2571.56000"
|
681
|
+
// }
|
682
|
+
//
|
683
|
+
const timestamp = this.milliseconds ();
|
684
|
+
const symbol = this.safeSymbol (undefined, market);
|
685
|
+
const v = this.safeValue (ticker, 'v', []);
|
686
|
+
const baseVolume = this.safeString (v, 1);
|
687
|
+
const p = this.safeValue (ticker, 'p', []);
|
688
|
+
const vwap = this.safeString (p, 1);
|
689
|
+
const quoteVolume = Precise.stringMul (baseVolume, vwap);
|
690
|
+
const c = this.safeValue (ticker, 'c', []);
|
691
|
+
const last = this.safeString (c, 0);
|
692
|
+
const high = this.safeValue (ticker, 'h', []);
|
693
|
+
const low = this.safeValue (ticker, 'l', []);
|
694
|
+
const bid = this.safeValue (ticker, 'b', []);
|
695
|
+
const ask = this.safeValue (ticker, 'a', []);
|
696
|
+
return this.safeTicker ({
|
697
|
+
'symbol': symbol,
|
698
|
+
'timestamp': timestamp,
|
699
|
+
'datetime': this.iso8601 (timestamp),
|
700
|
+
'high': this.safeString (high, 1),
|
701
|
+
'low': this.safeString (low, 1),
|
702
|
+
'bid': this.safeString (bid, 0),
|
703
|
+
'bidVolume': undefined,
|
704
|
+
'ask': this.safeString (ask, 0),
|
705
|
+
'askVolume': undefined,
|
706
|
+
'vwap': vwap,
|
707
|
+
'open': this.safeString (ticker, 'o'),
|
708
|
+
'close': last,
|
709
|
+
'last': last,
|
710
|
+
'previousClose': undefined,
|
711
|
+
'change': undefined,
|
712
|
+
'percentage': undefined,
|
713
|
+
'average': undefined,
|
714
|
+
'baseVolume': baseVolume,
|
715
|
+
'quoteVolume': quoteVolume,
|
716
|
+
'info': ticker,
|
717
|
+
}, market, false);
|
718
|
+
}
|
719
|
+
|
720
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
721
|
+
if (symbols === undefined) {
|
722
|
+
throw new ArgumentsRequired (this.id + ' fetchTickers() requires a symbols argument, an array of symbols');
|
723
|
+
}
|
724
|
+
await this.loadMarkets ();
|
725
|
+
const marketIds = [];
|
726
|
+
for (let i = 0; i < symbols.length; i++) {
|
727
|
+
const symbol = symbols[i];
|
728
|
+
const market = this.markets[symbol];
|
729
|
+
if (market['active'] && !market['darkpool']) {
|
730
|
+
marketIds.push (market['id']);
|
731
|
+
}
|
732
|
+
}
|
733
|
+
const request = {
|
734
|
+
'pair': marketIds.join (','),
|
735
|
+
};
|
736
|
+
const response = await this.publicGetTicker (this.extend (request, params));
|
737
|
+
const tickers = response['result'];
|
738
|
+
const ids = Object.keys (tickers);
|
739
|
+
const result = {};
|
740
|
+
for (let i = 0; i < ids.length; i++) {
|
741
|
+
const id = ids[i];
|
742
|
+
const market = this.markets_by_id[id];
|
743
|
+
const symbol = market['symbol'];
|
744
|
+
const ticker = tickers[id];
|
745
|
+
result[symbol] = this.parseTicker (ticker, market);
|
746
|
+
}
|
747
|
+
return this.filterByArray (result, 'symbol', symbols);
|
748
|
+
}
|
749
|
+
|
750
|
+
async fetchTicker (symbol, params = {}) {
|
751
|
+
await this.loadMarkets ();
|
752
|
+
const darkpool = symbol.indexOf ('.d') >= 0;
|
753
|
+
if (darkpool) {
|
754
|
+
throw new ExchangeError (this.id + ' fetchTicker() does not provide a ticker for darkpool symbol ' + symbol);
|
755
|
+
}
|
756
|
+
const market = this.market (symbol);
|
757
|
+
const request = {
|
758
|
+
'pair': market['id'],
|
759
|
+
};
|
760
|
+
const response = await this.publicGetTicker (this.extend (request, params));
|
761
|
+
const ticker = response['result'][market['id']];
|
762
|
+
return this.parseTicker (ticker, market);
|
763
|
+
}
|
764
|
+
|
765
|
+
parseOHLCV (ohlcv, market = undefined) {
|
766
|
+
//
|
767
|
+
// [
|
768
|
+
// 1591475640,
|
769
|
+
// "0.02500",
|
770
|
+
// "0.02500",
|
771
|
+
// "0.02500",
|
772
|
+
// "0.02500",
|
773
|
+
// "0.02500",
|
774
|
+
// "9.12201000",
|
775
|
+
// 5
|
776
|
+
// ]
|
777
|
+
//
|
778
|
+
return [
|
779
|
+
this.safeTimestamp (ohlcv, 0),
|
780
|
+
this.safeNumber (ohlcv, 1),
|
781
|
+
this.safeNumber (ohlcv, 2),
|
782
|
+
this.safeNumber (ohlcv, 3),
|
783
|
+
this.safeNumber (ohlcv, 4),
|
784
|
+
this.safeNumber (ohlcv, 6),
|
785
|
+
];
|
786
|
+
}
|
787
|
+
|
788
|
+
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
789
|
+
await this.loadMarkets ();
|
790
|
+
const market = this.market (symbol);
|
791
|
+
const request = {
|
792
|
+
'pair': market['id'],
|
793
|
+
'interval': this.timeframes[timeframe],
|
794
|
+
};
|
795
|
+
if (since !== undefined) {
|
796
|
+
request['since'] = parseInt ((since - 1) / 1000);
|
797
|
+
}
|
798
|
+
const response = await this.publicGetOHLC (this.extend (request, params));
|
799
|
+
//
|
800
|
+
// {
|
801
|
+
// "error":[],
|
802
|
+
// "result":{
|
803
|
+
// "XETHXXBT":[
|
804
|
+
// [1591475580,"0.02499","0.02499","0.02499","0.02499","0.00000","0.00000000",0],
|
805
|
+
// [1591475640,"0.02500","0.02500","0.02500","0.02500","0.02500","9.12201000",5],
|
806
|
+
// [1591475700,"0.02499","0.02499","0.02499","0.02499","0.02499","1.28681415",2],
|
807
|
+
// [1591475760,"0.02499","0.02499","0.02499","0.02499","0.02499","0.08800000",1],
|
808
|
+
// ],
|
809
|
+
// "last":1591517580
|
810
|
+
// }
|
811
|
+
// }
|
812
|
+
const result = this.safeValue (response, 'result', {});
|
813
|
+
const ohlcvs = this.safeValue (result, market['id'], []);
|
814
|
+
return this.parseOHLCVs (ohlcvs, market, timeframe, since, limit);
|
815
|
+
}
|
816
|
+
|
817
|
+
parseLedgerEntryType (type) {
|
818
|
+
const types = {
|
819
|
+
'trade': 'trade',
|
820
|
+
'withdrawal': 'transaction',
|
821
|
+
'deposit': 'transaction',
|
822
|
+
'transfer': 'transfer',
|
823
|
+
'margin': 'margin',
|
824
|
+
};
|
825
|
+
return this.safeString (types, type, type);
|
826
|
+
}
|
827
|
+
|
828
|
+
parseLedgerEntry (item, currency = undefined) {
|
829
|
+
//
|
830
|
+
// {
|
831
|
+
// 'LTFK7F-N2CUX-PNY4SX': {
|
832
|
+
// refid: "TSJTGT-DT7WN-GPPQMJ",
|
833
|
+
// time: 1520102320.555,
|
834
|
+
// type: "trade",
|
835
|
+
// aclass: "currency",
|
836
|
+
// asset: "XETH",
|
837
|
+
// amount: "0.1087194600",
|
838
|
+
// fee: "0.0000000000",
|
839
|
+
// balance: "0.2855851000"
|
840
|
+
// },
|
841
|
+
// ...
|
842
|
+
// }
|
843
|
+
//
|
844
|
+
const id = this.safeString (item, 'id');
|
845
|
+
let direction = undefined;
|
846
|
+
const account = undefined;
|
847
|
+
const referenceId = this.safeString (item, 'refid');
|
848
|
+
const referenceAccount = undefined;
|
849
|
+
const type = this.parseLedgerEntryType (this.safeString (item, 'type'));
|
850
|
+
const code = this.safeCurrencyCode (this.safeString (item, 'asset'), currency);
|
851
|
+
let amount = this.safeNumber (item, 'amount');
|
852
|
+
if (amount < 0) {
|
853
|
+
direction = 'out';
|
854
|
+
amount = Math.abs (amount);
|
855
|
+
} else {
|
856
|
+
direction = 'in';
|
857
|
+
}
|
858
|
+
const time = this.safeNumber (item, 'time');
|
859
|
+
let timestamp = undefined;
|
860
|
+
if (time !== undefined) {
|
861
|
+
timestamp = parseInt (time * 1000);
|
862
|
+
}
|
863
|
+
const fee = {
|
864
|
+
'cost': this.safeNumber (item, 'fee'),
|
865
|
+
'currency': code,
|
866
|
+
};
|
867
|
+
const before = undefined;
|
868
|
+
const after = this.safeNumber (item, 'balance');
|
869
|
+
const status = 'ok';
|
870
|
+
return {
|
871
|
+
'info': item,
|
872
|
+
'id': id,
|
873
|
+
'direction': direction,
|
874
|
+
'account': account,
|
875
|
+
'referenceId': referenceId,
|
876
|
+
'referenceAccount': referenceAccount,
|
877
|
+
'type': type,
|
878
|
+
'currency': code,
|
879
|
+
'amount': amount,
|
880
|
+
'before': before,
|
881
|
+
'after': after,
|
882
|
+
'status': status,
|
883
|
+
'timestamp': timestamp,
|
884
|
+
'datetime': this.iso8601 (timestamp),
|
885
|
+
'fee': fee,
|
886
|
+
};
|
887
|
+
}
|
888
|
+
|
889
|
+
async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
|
890
|
+
// https://www.kraken.com/features/api#get-ledgers-info
|
891
|
+
await this.loadMarkets ();
|
892
|
+
const request = {};
|
893
|
+
let currency = undefined;
|
894
|
+
if (code !== undefined) {
|
895
|
+
currency = this.currency (code);
|
896
|
+
request['asset'] = currency['id'];
|
897
|
+
}
|
898
|
+
if (since !== undefined) {
|
899
|
+
request['start'] = parseInt (since / 1000);
|
900
|
+
}
|
901
|
+
const response = await this.privatePostLedgers (this.extend (request, params));
|
902
|
+
// { error: [],
|
903
|
+
// result: { ledger: { 'LPUAIB-TS774-UKHP7X': { refid: "A2B4HBV-L4MDIE-JU4N3N",
|
904
|
+
// time: 1520103488.314,
|
905
|
+
// type: "withdrawal",
|
906
|
+
// aclass: "currency",
|
907
|
+
// asset: "XETH",
|
908
|
+
// amount: "-0.2805800000",
|
909
|
+
// fee: "0.0050000000",
|
910
|
+
// balance: "0.0000051000" },
|
911
|
+
const result = this.safeValue (response, 'result', {});
|
912
|
+
const ledger = this.safeValue (result, 'ledger', {});
|
913
|
+
const keys = Object.keys (ledger);
|
914
|
+
const items = [];
|
915
|
+
for (let i = 0; i < keys.length; i++) {
|
916
|
+
const key = keys[i];
|
917
|
+
const value = ledger[key];
|
918
|
+
value['id'] = key;
|
919
|
+
items.push (value);
|
920
|
+
}
|
921
|
+
return this.parseLedger (items, currency, since, limit);
|
922
|
+
}
|
923
|
+
|
924
|
+
async fetchLedgerEntriesByIds (ids, code = undefined, params = {}) {
|
925
|
+
// https://www.kraken.com/features/api#query-ledgers
|
926
|
+
await this.loadMarkets ();
|
927
|
+
ids = ids.join (',');
|
928
|
+
const request = this.extend ({
|
929
|
+
'id': ids,
|
930
|
+
}, params);
|
931
|
+
const response = await this.privatePostQueryLedgers (request);
|
932
|
+
// { error: [],
|
933
|
+
// result: { 'LPUAIB-TS774-UKHP7X': { refid: "A2B4HBV-L4MDIE-JU4N3N",
|
934
|
+
// time: 1520103488.314,
|
935
|
+
// type: "withdrawal",
|
936
|
+
// aclass: "currency",
|
937
|
+
// asset: "XETH",
|
938
|
+
// amount: "-0.2805800000",
|
939
|
+
// fee: "0.0050000000",
|
940
|
+
// balance: "0.0000051000" } } }
|
941
|
+
const result = response['result'];
|
942
|
+
const keys = Object.keys (result);
|
943
|
+
const items = [];
|
944
|
+
for (let i = 0; i < keys.length; i++) {
|
945
|
+
const key = keys[i];
|
946
|
+
const value = result[key];
|
947
|
+
value['id'] = key;
|
948
|
+
items.push (value);
|
949
|
+
}
|
950
|
+
return this.parseLedger (items);
|
951
|
+
}
|
952
|
+
|
953
|
+
async fetchLedgerEntry (id, code = undefined, params = {}) {
|
954
|
+
const items = await this.fetchLedgerEntriesByIds ([ id ], code, params);
|
955
|
+
return items[0];
|
956
|
+
}
|
957
|
+
|
958
|
+
parseTrade (trade, market = undefined) {
|
959
|
+
//
|
960
|
+
// fetchTrades (public)
|
961
|
+
//
|
962
|
+
// [
|
963
|
+
// "0.032310", // price
|
964
|
+
// "4.28169434", // amount
|
965
|
+
// 1541390792.763, // timestamp
|
966
|
+
// "s", // sell or buy
|
967
|
+
// "l", // limit or market
|
968
|
+
// ""
|
969
|
+
// ]
|
970
|
+
//
|
971
|
+
// fetchOrderTrades (private)
|
972
|
+
//
|
973
|
+
// {
|
974
|
+
// id: 'TIMIRG-WUNNE-RRJ6GT', // injected from outside
|
975
|
+
// ordertxid: 'OQRPN2-LRHFY-HIFA7D',
|
976
|
+
// postxid: 'TKH2SE-M7IF5-CFI7LT',
|
977
|
+
// pair: 'USDCUSDT',
|
978
|
+
// time: 1586340086.457,
|
979
|
+
// type: 'sell',
|
980
|
+
// ordertype: 'market',
|
981
|
+
// price: '0.99860000',
|
982
|
+
// cost: '22.16892001',
|
983
|
+
// fee: '0.04433784',
|
984
|
+
// vol: '22.20000000',
|
985
|
+
// margin: '0.00000000',
|
986
|
+
// misc: ''
|
987
|
+
// }
|
988
|
+
//
|
989
|
+
let timestamp = undefined;
|
990
|
+
let side = undefined;
|
991
|
+
let type = undefined;
|
992
|
+
let price = undefined;
|
993
|
+
let amount = undefined;
|
994
|
+
let id = undefined;
|
995
|
+
let orderId = undefined;
|
996
|
+
let fee = undefined;
|
997
|
+
let symbol = undefined;
|
998
|
+
if (Array.isArray (trade)) {
|
999
|
+
timestamp = this.safeTimestamp (trade, 2);
|
1000
|
+
side = (trade[3] === 's') ? 'sell' : 'buy';
|
1001
|
+
type = (trade[4] === 'l') ? 'limit' : 'market';
|
1002
|
+
price = this.safeString (trade, 0);
|
1003
|
+
amount = this.safeString (trade, 1);
|
1004
|
+
const tradeLength = trade.length;
|
1005
|
+
if (tradeLength > 6) {
|
1006
|
+
id = this.safeString (trade, 6); // artificially added as per #1794
|
1007
|
+
}
|
1008
|
+
} else if (typeof trade === 'string') {
|
1009
|
+
id = trade;
|
1010
|
+
} else if ('ordertxid' in trade) {
|
1011
|
+
const marketId = this.safeString (trade, 'pair');
|
1012
|
+
const foundMarket = this.findMarketByAltnameOrId (marketId);
|
1013
|
+
if (foundMarket !== undefined) {
|
1014
|
+
market = foundMarket;
|
1015
|
+
} else if (marketId !== undefined) {
|
1016
|
+
// delisted market ids go here
|
1017
|
+
market = this.getDelistedMarketById (marketId);
|
1018
|
+
}
|
1019
|
+
orderId = this.safeString (trade, 'ordertxid');
|
1020
|
+
id = this.safeString2 (trade, 'id', 'postxid');
|
1021
|
+
timestamp = this.safeTimestamp (trade, 'time');
|
1022
|
+
side = this.safeString (trade, 'type');
|
1023
|
+
type = this.safeString (trade, 'ordertype');
|
1024
|
+
price = this.safeString (trade, 'price');
|
1025
|
+
amount = this.safeString (trade, 'vol');
|
1026
|
+
if ('fee' in trade) {
|
1027
|
+
let currency = undefined;
|
1028
|
+
if (market !== undefined) {
|
1029
|
+
currency = market['quote'];
|
1030
|
+
}
|
1031
|
+
fee = {
|
1032
|
+
'cost': this.safeString (trade, 'fee'),
|
1033
|
+
'currency': currency,
|
1034
|
+
};
|
1035
|
+
}
|
1036
|
+
}
|
1037
|
+
if (market !== undefined) {
|
1038
|
+
symbol = market['symbol'];
|
1039
|
+
}
|
1040
|
+
const cost = this.safeString (trade, 'cost');
|
1041
|
+
return this.safeTrade ({
|
1042
|
+
'id': id,
|
1043
|
+
'order': orderId,
|
1044
|
+
'info': trade,
|
1045
|
+
'timestamp': timestamp,
|
1046
|
+
'datetime': this.iso8601 (timestamp),
|
1047
|
+
'symbol': symbol,
|
1048
|
+
'type': type,
|
1049
|
+
'side': side,
|
1050
|
+
'takerOrMaker': undefined,
|
1051
|
+
'price': price,
|
1052
|
+
'amount': amount,
|
1053
|
+
'cost': cost,
|
1054
|
+
'fee': fee,
|
1055
|
+
}, market);
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
1059
|
+
await this.loadMarkets ();
|
1060
|
+
const market = this.market (symbol);
|
1061
|
+
const id = market['id'];
|
1062
|
+
const request = {
|
1063
|
+
'pair': id,
|
1064
|
+
};
|
1065
|
+
// https://support.kraken.com/hc/en-us/articles/218198197-How-to-pull-all-trade-data-using-the-Kraken-REST-API
|
1066
|
+
// https://github.com/ccxt/ccxt/issues/5677
|
1067
|
+
if (since !== undefined) {
|
1068
|
+
// php does not format it properly
|
1069
|
+
// therefore we use string concatenation here
|
1070
|
+
request['since'] = since * 1e6;
|
1071
|
+
request['since'] = since.toString () + '000000'; // expected to be in nanoseconds
|
1072
|
+
}
|
1073
|
+
// https://github.com/ccxt/ccxt/issues/5698
|
1074
|
+
if (limit !== undefined && limit !== 1000) {
|
1075
|
+
const fetchTradesWarning = this.safeValue (this.options, 'fetchTradesWarning', true);
|
1076
|
+
if (fetchTradesWarning) {
|
1077
|
+
throw new ExchangeError (this.id + ' fetchTrades() cannot serve ' + limit.toString () + " trades without breaking the pagination, see https://github.com/ccxt/ccxt/issues/5698 for more details. Set exchange.options['fetchTradesWarning'] to acknowledge this warning and silence it.");
|
1078
|
+
}
|
1079
|
+
}
|
1080
|
+
const response = await this.publicGetTrades (this.extend (request, params));
|
1081
|
+
//
|
1082
|
+
// {
|
1083
|
+
// "error": [],
|
1084
|
+
// "result": {
|
1085
|
+
// "XETHXXBT": [
|
1086
|
+
// ["0.032310","4.28169434",1541390792.763,"s","l",""]
|
1087
|
+
// ],
|
1088
|
+
// "last": "1541439421200678657"
|
1089
|
+
// }
|
1090
|
+
// }
|
1091
|
+
//
|
1092
|
+
const result = response['result'];
|
1093
|
+
const trades = result[id];
|
1094
|
+
// trades is a sorted array: last (most recent trade) goes last
|
1095
|
+
const length = trades.length;
|
1096
|
+
if (length <= 0) {
|
1097
|
+
return [];
|
1098
|
+
}
|
1099
|
+
const lastTrade = trades[length - 1];
|
1100
|
+
const lastTradeId = this.safeString (result, 'last');
|
1101
|
+
lastTrade.push (lastTradeId);
|
1102
|
+
return this.parseTrades (trades, market, since, limit);
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
parseBalance (response) {
|
1106
|
+
const balances = this.safeValue (response, 'result', {});
|
1107
|
+
const result = {
|
1108
|
+
'info': response,
|
1109
|
+
'timestamp': undefined,
|
1110
|
+
'datetime': undefined,
|
1111
|
+
};
|
1112
|
+
const currencyIds = Object.keys (balances);
|
1113
|
+
for (let i = 0; i < currencyIds.length; i++) {
|
1114
|
+
const currencyId = currencyIds[i];
|
1115
|
+
const code = this.safeCurrencyCode (currencyId);
|
1116
|
+
const account = this.account ();
|
1117
|
+
account['total'] = this.safeString (balances, currencyId);
|
1118
|
+
result[code] = account;
|
1119
|
+
}
|
1120
|
+
return this.safeBalance (result);
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
async fetchBalance (params = {}) {
|
1124
|
+
await this.loadMarkets ();
|
1125
|
+
const response = await this.privatePostBalance (params);
|
1126
|
+
//
|
1127
|
+
// {
|
1128
|
+
// "error":[],
|
1129
|
+
// "result":{
|
1130
|
+
// "ZUSD":"58.8649",
|
1131
|
+
// "KFEE":"4399.43",
|
1132
|
+
// "XXBT":"0.0000034506",
|
1133
|
+
// }
|
1134
|
+
// }
|
1135
|
+
//
|
1136
|
+
return this.parseBalance (response);
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
1140
|
+
await this.loadMarkets ();
|
1141
|
+
const market = this.market (symbol);
|
1142
|
+
const request = {
|
1143
|
+
'pair': market['id'],
|
1144
|
+
'type': side,
|
1145
|
+
'ordertype': type,
|
1146
|
+
'volume': this.amountToPrecision (symbol, amount),
|
1147
|
+
};
|
1148
|
+
const clientOrderId = this.safeString2 (params, 'userref', 'clientOrderId');
|
1149
|
+
params = this.omit (params, [ 'userref', 'clientOrderId' ]);
|
1150
|
+
if (clientOrderId !== undefined) {
|
1151
|
+
request['userref'] = clientOrderId;
|
1152
|
+
}
|
1153
|
+
//
|
1154
|
+
// market
|
1155
|
+
// limit (price = limit price)
|
1156
|
+
// stop-loss (price = stop loss price)
|
1157
|
+
// take-profit (price = take profit price)
|
1158
|
+
// stop-loss-limit (price = stop loss trigger price, price2 = triggered limit price)
|
1159
|
+
// take-profit-limit (price = take profit trigger price, price2 = triggered limit price)
|
1160
|
+
// settle-position
|
1161
|
+
//
|
1162
|
+
if (type === 'limit') {
|
1163
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1164
|
+
} else if ((type === 'stop-loss') || (type === 'take-profit')) {
|
1165
|
+
const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice', price);
|
1166
|
+
if (stopPrice === undefined) {
|
1167
|
+
throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument or a price/stopPrice parameter for a ' + type + ' order');
|
1168
|
+
} else {
|
1169
|
+
request['price'] = this.priceToPrecision (symbol, stopPrice);
|
1170
|
+
}
|
1171
|
+
} else if ((type === 'stop-loss-limit') || (type === 'take-profit-limit')) {
|
1172
|
+
const stopPrice = this.safeNumber2 (params, 'price', 'stopPrice');
|
1173
|
+
const limitPrice = this.safeNumber (params, 'price2');
|
1174
|
+
const stopPriceDefined = (stopPrice !== undefined);
|
1175
|
+
const limitPriceDefined = (limitPrice !== undefined);
|
1176
|
+
if (stopPriceDefined && limitPriceDefined) {
|
1177
|
+
request['price'] = this.priceToPrecision (symbol, stopPrice);
|
1178
|
+
request['price2'] = this.priceToPrecision (symbol, limitPrice);
|
1179
|
+
} else if ((price === undefined) || (!(stopPriceDefined || limitPriceDefined))) {
|
1180
|
+
throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument and/or price/stopPrice/price2 parameters for a ' + type + ' order');
|
1181
|
+
} else {
|
1182
|
+
if (stopPriceDefined) {
|
1183
|
+
request['price'] = this.priceToPrecision (symbol, stopPrice);
|
1184
|
+
request['price2'] = this.priceToPrecision (symbol, price);
|
1185
|
+
} else if (limitPriceDefined) {
|
1186
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1187
|
+
request['price2'] = this.priceToPrecision (symbol, limitPrice);
|
1188
|
+
}
|
1189
|
+
}
|
1190
|
+
}
|
1191
|
+
let close = this.safeValue (params, 'close');
|
1192
|
+
if (close !== undefined) {
|
1193
|
+
close = this.extend ({}, close);
|
1194
|
+
const closePrice = this.safeValue (close, 'price');
|
1195
|
+
if (closePrice !== undefined) {
|
1196
|
+
close['price'] = this.priceToPrecision (symbol, closePrice);
|
1197
|
+
}
|
1198
|
+
const closePrice2 = this.safeValue (close, 'price2'); // stopPrice
|
1199
|
+
if (closePrice2 !== undefined) {
|
1200
|
+
close['price2'] = this.priceToPrecision (symbol, closePrice2);
|
1201
|
+
}
|
1202
|
+
request['close'] = close;
|
1203
|
+
}
|
1204
|
+
params = this.omit (params, [ 'price', 'stopPrice', 'price2', 'close' ]);
|
1205
|
+
const response = await this.privatePostAddOrder (this.extend (request, params));
|
1206
|
+
//
|
1207
|
+
// {
|
1208
|
+
// error: [],
|
1209
|
+
// result: {
|
1210
|
+
// descr: { order: 'buy 0.02100000 ETHUSDT @ limit 330.00' },
|
1211
|
+
// txid: [ 'OEKVV2-IH52O-TPL6GZ' ]
|
1212
|
+
// }
|
1213
|
+
// }
|
1214
|
+
//
|
1215
|
+
const result = this.safeValue (response, 'result');
|
1216
|
+
return this.parseOrder (result);
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
findMarketByAltnameOrId (id) {
|
1220
|
+
if (id in this.marketsByAltname) {
|
1221
|
+
return this.marketsByAltname[id];
|
1222
|
+
} else if (id in this.markets_by_id) {
|
1223
|
+
return this.markets_by_id[id];
|
1224
|
+
}
|
1225
|
+
return undefined;
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
getDelistedMarketById (id) {
|
1229
|
+
if (id === undefined) {
|
1230
|
+
return id;
|
1231
|
+
}
|
1232
|
+
let market = this.safeValue (this.options['delistedMarketsById'], id);
|
1233
|
+
if (market !== undefined) {
|
1234
|
+
return market;
|
1235
|
+
}
|
1236
|
+
const baseIdStart = 0;
|
1237
|
+
let baseIdEnd = 3;
|
1238
|
+
let quoteIdStart = 3;
|
1239
|
+
let quoteIdEnd = 6;
|
1240
|
+
if (id.length === 8) {
|
1241
|
+
baseIdEnd = 4;
|
1242
|
+
quoteIdStart = 4;
|
1243
|
+
quoteIdEnd = 8;
|
1244
|
+
} else if (id.length === 7) {
|
1245
|
+
baseIdEnd = 4;
|
1246
|
+
quoteIdStart = 4;
|
1247
|
+
quoteIdEnd = 7;
|
1248
|
+
}
|
1249
|
+
const baseId = id.slice (baseIdStart, baseIdEnd);
|
1250
|
+
const quoteId = id.slice (quoteIdStart, quoteIdEnd);
|
1251
|
+
const base = this.safeCurrencyCode (baseId);
|
1252
|
+
const quote = this.safeCurrencyCode (quoteId);
|
1253
|
+
const symbol = base + '/' + quote;
|
1254
|
+
market = {
|
1255
|
+
'symbol': symbol,
|
1256
|
+
'base': base,
|
1257
|
+
'quote': quote,
|
1258
|
+
'baseId': baseId,
|
1259
|
+
'quoteId': quoteId,
|
1260
|
+
};
|
1261
|
+
this.options['delistedMarketsById'][id] = market;
|
1262
|
+
return market;
|
1263
|
+
}
|
1264
|
+
|
1265
|
+
parseOrderStatus (status) {
|
1266
|
+
const statuses = {
|
1267
|
+
'pending': 'open', // order pending book entry
|
1268
|
+
'open': 'open',
|
1269
|
+
'closed': 'closed',
|
1270
|
+
'canceled': 'canceled',
|
1271
|
+
'expired': 'expired',
|
1272
|
+
};
|
1273
|
+
return this.safeString (statuses, status, status);
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
parseOrder (order, market = undefined) {
|
1277
|
+
//
|
1278
|
+
// createOrder for regular orders
|
1279
|
+
//
|
1280
|
+
// {
|
1281
|
+
// descr: { order: 'buy 0.02100000 ETHUSDT @ limit 330.00' },
|
1282
|
+
// txid: [ 'OEKVV2-IH52O-TPL6GZ' ]
|
1283
|
+
// }
|
1284
|
+
// {
|
1285
|
+
// "txid": [ "TX_ID_HERE" ],
|
1286
|
+
// "descr": { "order":"buy 0.12345678 ETHEUR @ market" },
|
1287
|
+
// }
|
1288
|
+
//
|
1289
|
+
//
|
1290
|
+
// createOrder for stop orders
|
1291
|
+
//
|
1292
|
+
// {
|
1293
|
+
// "txid":["OSILNC-VQI5Q-775ZDQ"],
|
1294
|
+
// "descr":{"order":"sell 167.28002676 ADAXBT @ stop loss 0.00003280 -> limit 0.00003212"}
|
1295
|
+
// }
|
1296
|
+
//
|
1297
|
+
//
|
1298
|
+
// {
|
1299
|
+
// "txid":["OVHMJV-BZW2V-6NZFWF"],
|
1300
|
+
// "descr":{"order":"sell 0.00100000 ETHUSD @ stop loss 2677.00 -> limit 2577.00 with 5:1 leverage"}
|
1301
|
+
// }
|
1302
|
+
//
|
1303
|
+
const description = this.safeValue (order, 'descr', {});
|
1304
|
+
const orderDescription = this.safeString (description, 'order');
|
1305
|
+
let side = undefined;
|
1306
|
+
let type = undefined;
|
1307
|
+
let marketId = undefined;
|
1308
|
+
let price = undefined;
|
1309
|
+
let amount = undefined;
|
1310
|
+
let stopPrice = undefined;
|
1311
|
+
if (orderDescription !== undefined) {
|
1312
|
+
const parts = orderDescription.split (' ');
|
1313
|
+
side = this.safeString (parts, 0);
|
1314
|
+
amount = this.safeString (parts, 1);
|
1315
|
+
marketId = this.safeString (parts, 2);
|
1316
|
+
type = this.safeString (parts, 4);
|
1317
|
+
if (type === 'stop') {
|
1318
|
+
stopPrice = this.safeString (parts, 6);
|
1319
|
+
price = this.safeString (parts, 9);
|
1320
|
+
} else if (type === 'limit') {
|
1321
|
+
price = this.safeString (parts, 5);
|
1322
|
+
}
|
1323
|
+
}
|
1324
|
+
side = this.safeString (description, 'type', side);
|
1325
|
+
type = this.safeString (description, 'ordertype', type);
|
1326
|
+
marketId = this.safeString (description, 'pair', marketId);
|
1327
|
+
const foundMarket = this.findMarketByAltnameOrId (marketId);
|
1328
|
+
let symbol = undefined;
|
1329
|
+
if (foundMarket !== undefined) {
|
1330
|
+
market = foundMarket;
|
1331
|
+
} else if (marketId !== undefined) {
|
1332
|
+
// delisted market ids go here
|
1333
|
+
market = this.getDelistedMarketById (marketId);
|
1334
|
+
}
|
1335
|
+
const timestamp = this.safeTimestamp (order, 'opentm');
|
1336
|
+
amount = this.safeString (order, 'vol', amount);
|
1337
|
+
const filled = this.safeString (order, 'vol_exec');
|
1338
|
+
let fee = undefined;
|
1339
|
+
// kraken truncates the cost in the api response so we will ignore it and calculate it from average & filled
|
1340
|
+
// const cost = this.safeString (order, 'cost');
|
1341
|
+
price = this.safeString (description, 'price', price);
|
1342
|
+
if ((price === undefined) || Precise.stringEquals (price, '0')) {
|
1343
|
+
price = this.safeString (description, 'price2');
|
1344
|
+
}
|
1345
|
+
if ((price === undefined) || Precise.stringEquals (price, '0')) {
|
1346
|
+
price = this.safeString (order, 'price', price);
|
1347
|
+
}
|
1348
|
+
const average = this.safeNumber (order, 'price');
|
1349
|
+
if (market !== undefined) {
|
1350
|
+
symbol = market['symbol'];
|
1351
|
+
if ('fee' in order) {
|
1352
|
+
const flags = order['oflags'];
|
1353
|
+
const feeCost = this.safeString (order, 'fee');
|
1354
|
+
fee = {
|
1355
|
+
'cost': feeCost,
|
1356
|
+
'rate': undefined,
|
1357
|
+
};
|
1358
|
+
if (flags.indexOf ('fciq') >= 0) {
|
1359
|
+
fee['currency'] = market['quote'];
|
1360
|
+
} else if (flags.indexOf ('fcib') >= 0) {
|
1361
|
+
fee['currency'] = market['base'];
|
1362
|
+
}
|
1363
|
+
}
|
1364
|
+
}
|
1365
|
+
const status = this.parseOrderStatus (this.safeString (order, 'status'));
|
1366
|
+
let id = this.safeString (order, 'id');
|
1367
|
+
if (id === undefined) {
|
1368
|
+
const txid = this.safeValue (order, 'txid');
|
1369
|
+
id = this.safeString (txid, 0);
|
1370
|
+
}
|
1371
|
+
const clientOrderId = this.safeString (order, 'userref');
|
1372
|
+
const rawTrades = this.safeValue (order, 'trades');
|
1373
|
+
stopPrice = this.safeNumber (order, 'stopprice', stopPrice);
|
1374
|
+
return this.safeOrder ({
|
1375
|
+
'id': id,
|
1376
|
+
'clientOrderId': clientOrderId,
|
1377
|
+
'info': order,
|
1378
|
+
'timestamp': timestamp,
|
1379
|
+
'datetime': this.iso8601 (timestamp),
|
1380
|
+
'lastTradeTimestamp': undefined,
|
1381
|
+
'status': status,
|
1382
|
+
'symbol': symbol,
|
1383
|
+
'type': type,
|
1384
|
+
'timeInForce': undefined,
|
1385
|
+
'postOnly': undefined,
|
1386
|
+
'side': side,
|
1387
|
+
'price': price,
|
1388
|
+
'stopPrice': stopPrice,
|
1389
|
+
'cost': undefined,
|
1390
|
+
'amount': amount,
|
1391
|
+
'filled': filled,
|
1392
|
+
'average': average,
|
1393
|
+
'remaining': undefined,
|
1394
|
+
'fee': fee,
|
1395
|
+
'trades': rawTrades,
|
1396
|
+
}, market);
|
1397
|
+
}
|
1398
|
+
|
1399
|
+
async fetchOrder (id, symbol = undefined, params = {}) {
|
1400
|
+
await this.loadMarkets ();
|
1401
|
+
const clientOrderId = this.safeValue2 (params, 'userref', 'clientOrderId');
|
1402
|
+
const request = {
|
1403
|
+
'trades': true, // whether or not to include trades in output (optional, default false)
|
1404
|
+
// 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
|
1405
|
+
// 'userref': 'optional', // restrict results to given user reference id (optional)
|
1406
|
+
};
|
1407
|
+
let query = params;
|
1408
|
+
if (clientOrderId !== undefined) {
|
1409
|
+
request['userref'] = clientOrderId;
|
1410
|
+
query = this.omit (params, [ 'userref', 'clientOrderId' ]);
|
1411
|
+
} else {
|
1412
|
+
request['txid'] = id;
|
1413
|
+
}
|
1414
|
+
const response = await this.privatePostQueryOrders (this.extend (request, query));
|
1415
|
+
//
|
1416
|
+
// {
|
1417
|
+
// "error":[],
|
1418
|
+
// "result":{
|
1419
|
+
// "OTLAS3-RRHUF-NDWH5A":{
|
1420
|
+
// "refid":null,
|
1421
|
+
// "userref":null,
|
1422
|
+
// "status":"closed",
|
1423
|
+
// "reason":null,
|
1424
|
+
// "opentm":1586822919.3342,
|
1425
|
+
// "closetm":1586822919.365,
|
1426
|
+
// "starttm":0,
|
1427
|
+
// "expiretm":0,
|
1428
|
+
// "descr":{
|
1429
|
+
// "pair":"XBTUSDT",
|
1430
|
+
// "type":"sell",
|
1431
|
+
// "ordertype":"market",
|
1432
|
+
// "price":"0",
|
1433
|
+
// "price2":"0",
|
1434
|
+
// "leverage":"none",
|
1435
|
+
// "order":"sell 0.21804000 XBTUSDT @ market",
|
1436
|
+
// "close":""
|
1437
|
+
// },
|
1438
|
+
// "vol":"0.21804000",
|
1439
|
+
// "vol_exec":"0.21804000",
|
1440
|
+
// "cost":"1493.9",
|
1441
|
+
// "fee":"3.8",
|
1442
|
+
// "price":"6851.5",
|
1443
|
+
// "stopprice":"0.00000",
|
1444
|
+
// "limitprice":"0.00000",
|
1445
|
+
// "misc":"",
|
1446
|
+
// "oflags":"fciq",
|
1447
|
+
// "trades":["TT5UC3-GOIRW-6AZZ6R"]
|
1448
|
+
// }
|
1449
|
+
// }
|
1450
|
+
// }
|
1451
|
+
//
|
1452
|
+
const result = this.safeValue (response, 'result', []);
|
1453
|
+
if (!(id in result)) {
|
1454
|
+
throw new OrderNotFound (this.id + ' fetchOrder() could not find order id ' + id);
|
1455
|
+
}
|
1456
|
+
const order = this.parseOrder (this.extend ({ 'id': id }, result[id]));
|
1457
|
+
return this.extend ({ 'info': response }, order);
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1461
|
+
const orderTrades = this.safeValue (params, 'trades');
|
1462
|
+
const tradeIds = [];
|
1463
|
+
if (orderTrades === undefined) {
|
1464
|
+
throw new ArgumentsRequired (this.id + " fetchOrderTrades() requires a unified order structure in the params argument or a 'trades' param (an array of trade id strings)");
|
1465
|
+
} else {
|
1466
|
+
for (let i = 0; i < orderTrades.length; i++) {
|
1467
|
+
const orderTrade = orderTrades[i];
|
1468
|
+
if (typeof orderTrade === 'string') {
|
1469
|
+
tradeIds.push (orderTrade);
|
1470
|
+
} else {
|
1471
|
+
tradeIds.push (orderTrade['id']);
|
1472
|
+
}
|
1473
|
+
}
|
1474
|
+
}
|
1475
|
+
await this.loadMarkets ();
|
1476
|
+
const options = this.safeValue (this.options, 'fetchOrderTrades', {});
|
1477
|
+
const batchSize = this.safeInteger (options, 'batchSize', 20);
|
1478
|
+
const numTradeIds = tradeIds.length;
|
1479
|
+
let numBatches = parseInt (numTradeIds / batchSize);
|
1480
|
+
numBatches = this.sum (numBatches, 1);
|
1481
|
+
let result = [];
|
1482
|
+
for (let j = 0; j < numBatches; j++) {
|
1483
|
+
const requestIds = [];
|
1484
|
+
for (let k = 0; k < batchSize; k++) {
|
1485
|
+
const index = this.sum (j * batchSize, k);
|
1486
|
+
if (index < numTradeIds) {
|
1487
|
+
requestIds.push (tradeIds[index]);
|
1488
|
+
}
|
1489
|
+
}
|
1490
|
+
const request = {
|
1491
|
+
'txid': requestIds.join (','),
|
1492
|
+
};
|
1493
|
+
const response = await this.privatePostQueryTrades (request);
|
1494
|
+
//
|
1495
|
+
// {
|
1496
|
+
// error: [],
|
1497
|
+
// result: {
|
1498
|
+
// 'TIMIRG-WUNNE-RRJ6GT': {
|
1499
|
+
// ordertxid: 'OQRPN2-LRHFY-HIFA7D',
|
1500
|
+
// postxid: 'TKH2SE-M7IF5-CFI7LT',
|
1501
|
+
// pair: 'USDCUSDT',
|
1502
|
+
// time: 1586340086.457,
|
1503
|
+
// type: 'sell',
|
1504
|
+
// ordertype: 'market',
|
1505
|
+
// price: '0.99860000',
|
1506
|
+
// cost: '22.16892001',
|
1507
|
+
// fee: '0.04433784',
|
1508
|
+
// vol: '22.20000000',
|
1509
|
+
// margin: '0.00000000',
|
1510
|
+
// misc: ''
|
1511
|
+
// }
|
1512
|
+
// }
|
1513
|
+
// }
|
1514
|
+
//
|
1515
|
+
const rawTrades = this.safeValue (response, 'result');
|
1516
|
+
const ids = Object.keys (rawTrades);
|
1517
|
+
for (let i = 0; i < ids.length; i++) {
|
1518
|
+
rawTrades[ids[i]]['id'] = ids[i];
|
1519
|
+
}
|
1520
|
+
const trades = this.parseTrades (rawTrades, undefined, since, limit);
|
1521
|
+
const tradesFilteredBySymbol = this.filterBySymbol (trades, symbol);
|
1522
|
+
result = this.arrayConcat (result, tradesFilteredBySymbol);
|
1523
|
+
}
|
1524
|
+
return result;
|
1525
|
+
}
|
1526
|
+
|
1527
|
+
async fetchOrdersByIds (ids, symbol = undefined, params = {}) {
|
1528
|
+
await this.loadMarkets ();
|
1529
|
+
const response = await this.privatePostQueryOrders (this.extend ({
|
1530
|
+
'trades': true, // whether or not to include trades in output (optional, default false)
|
1531
|
+
'txid': ids.join (','), // comma delimited list of transaction ids to query info about (20 maximum)
|
1532
|
+
}, params));
|
1533
|
+
const result = this.safeValue (response, 'result', {});
|
1534
|
+
const orders = [];
|
1535
|
+
const orderIds = Object.keys (result);
|
1536
|
+
for (let i = 0; i < orderIds.length; i++) {
|
1537
|
+
const id = orderIds[i];
|
1538
|
+
const item = result[id];
|
1539
|
+
const order = this.parseOrder (this.extend ({ 'id': id }, item));
|
1540
|
+
orders.push (order);
|
1541
|
+
}
|
1542
|
+
return orders;
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1546
|
+
await this.loadMarkets ();
|
1547
|
+
const request = {
|
1548
|
+
// 'type': 'all', // any position, closed position, closing position, no position
|
1549
|
+
// 'trades': false, // whether or not to include trades related to position in output
|
1550
|
+
// 'start': 1234567890, // starting unix timestamp or trade tx id of results (exclusive)
|
1551
|
+
// 'end': 1234567890, // ending unix timestamp or trade tx id of results (inclusive)
|
1552
|
+
// 'ofs' = result offset
|
1553
|
+
};
|
1554
|
+
if (since !== undefined) {
|
1555
|
+
request['start'] = parseInt (since / 1000);
|
1556
|
+
}
|
1557
|
+
const response = await this.privatePostTradesHistory (this.extend (request, params));
|
1558
|
+
//
|
1559
|
+
// {
|
1560
|
+
// "error": [],
|
1561
|
+
// "result": {
|
1562
|
+
// "trades": {
|
1563
|
+
// "GJ3NYQ-XJRTF-THZABF": {
|
1564
|
+
// "ordertxid": "TKH2SE-ZIF5E-CFI7LT",
|
1565
|
+
// "postxid": "OEN3VX-M7IF5-JNBJAM",
|
1566
|
+
// "pair": "XICNXETH",
|
1567
|
+
// "time": 1527213229.4491,
|
1568
|
+
// "type": "sell",
|
1569
|
+
// "ordertype": "limit",
|
1570
|
+
// "price": "0.001612",
|
1571
|
+
// "cost": "0.025792",
|
1572
|
+
// "fee": "0.000026",
|
1573
|
+
// "vol": "16.00000000",
|
1574
|
+
// "margin": "0.000000",
|
1575
|
+
// "misc": ""
|
1576
|
+
// },
|
1577
|
+
// ...
|
1578
|
+
// },
|
1579
|
+
// "count": 9760,
|
1580
|
+
// },
|
1581
|
+
// }
|
1582
|
+
//
|
1583
|
+
const trades = response['result']['trades'];
|
1584
|
+
const ids = Object.keys (trades);
|
1585
|
+
for (let i = 0; i < ids.length; i++) {
|
1586
|
+
trades[ids[i]]['id'] = ids[i];
|
1587
|
+
}
|
1588
|
+
let market = undefined;
|
1589
|
+
if (symbol !== undefined) {
|
1590
|
+
market = this.market (symbol);
|
1591
|
+
}
|
1592
|
+
return this.parseTrades (trades, market, since, limit);
|
1593
|
+
}
|
1594
|
+
|
1595
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
1596
|
+
await this.loadMarkets ();
|
1597
|
+
let response = undefined;
|
1598
|
+
const clientOrderId = this.safeValue2 (params, 'userref', 'clientOrderId', id);
|
1599
|
+
const request = {
|
1600
|
+
'txid': clientOrderId, // order id or userref
|
1601
|
+
};
|
1602
|
+
params = this.omit (params, [ 'userref', 'clientOrderId' ]);
|
1603
|
+
try {
|
1604
|
+
response = await this.privatePostCancelOrder (this.extend (request, params));
|
1605
|
+
} catch (e) {
|
1606
|
+
if (this.last_http_response) {
|
1607
|
+
if (this.last_http_response.indexOf ('EOrder:Unknown order') >= 0) {
|
1608
|
+
throw new OrderNotFound (this.id + ' cancelOrder() error ' + this.last_http_response);
|
1609
|
+
}
|
1610
|
+
}
|
1611
|
+
throw e;
|
1612
|
+
}
|
1613
|
+
return response;
|
1614
|
+
}
|
1615
|
+
|
1616
|
+
async cancelAllOrders (symbol = undefined, params = {}) {
|
1617
|
+
await this.loadMarkets ();
|
1618
|
+
return await this.privatePostCancelAll (params);
|
1619
|
+
}
|
1620
|
+
|
1621
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1622
|
+
await this.loadMarkets ();
|
1623
|
+
const request = {};
|
1624
|
+
if (since !== undefined) {
|
1625
|
+
request['start'] = parseInt (since / 1000);
|
1626
|
+
}
|
1627
|
+
let query = params;
|
1628
|
+
const clientOrderId = this.safeValue2 (params, 'userref', 'clientOrderId');
|
1629
|
+
if (clientOrderId !== undefined) {
|
1630
|
+
request['userref'] = clientOrderId;
|
1631
|
+
query = this.omit (params, [ 'userref', 'clientOrderId' ]);
|
1632
|
+
}
|
1633
|
+
const response = await this.privatePostOpenOrders (this.extend (request, query));
|
1634
|
+
let market = undefined;
|
1635
|
+
if (symbol !== undefined) {
|
1636
|
+
market = this.market (symbol);
|
1637
|
+
}
|
1638
|
+
const result = this.safeValue (response, 'result', {});
|
1639
|
+
const orders = this.safeValue (result, 'open', []);
|
1640
|
+
return this.parseOrders (orders, market, since, limit);
|
1641
|
+
}
|
1642
|
+
|
1643
|
+
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1644
|
+
await this.loadMarkets ();
|
1645
|
+
const request = {};
|
1646
|
+
if (since !== undefined) {
|
1647
|
+
request['start'] = parseInt (since / 1000);
|
1648
|
+
}
|
1649
|
+
let query = params;
|
1650
|
+
const clientOrderId = this.safeValue2 (params, 'userref', 'clientOrderId');
|
1651
|
+
if (clientOrderId !== undefined) {
|
1652
|
+
request['userref'] = clientOrderId;
|
1653
|
+
query = this.omit (params, [ 'userref', 'clientOrderId' ]);
|
1654
|
+
}
|
1655
|
+
const response = await this.privatePostClosedOrders (this.extend (request, query));
|
1656
|
+
//
|
1657
|
+
// {
|
1658
|
+
// "error":[],
|
1659
|
+
// "result":{
|
1660
|
+
// "closed":{
|
1661
|
+
// "OETZYO-UL524-QJMXCT":{
|
1662
|
+
// "refid":null,
|
1663
|
+
// "userref":null,
|
1664
|
+
// "status":"canceled",
|
1665
|
+
// "reason":"User requested",
|
1666
|
+
// "opentm":1601489313.3898,
|
1667
|
+
// "closetm":1601489346.5507,
|
1668
|
+
// "starttm":0,
|
1669
|
+
// "expiretm":0,
|
1670
|
+
// "descr":{
|
1671
|
+
// "pair":"ETHUSDT",
|
1672
|
+
// "type":"buy",
|
1673
|
+
// "ordertype":"limit",
|
1674
|
+
// "price":"330.00",
|
1675
|
+
// "price2":"0",
|
1676
|
+
// "leverage":"none",
|
1677
|
+
// "order":"buy 0.02100000 ETHUSDT @ limit 330.00",
|
1678
|
+
// "close":""
|
1679
|
+
// },
|
1680
|
+
// "vol":"0.02100000",
|
1681
|
+
// "vol_exec":"0.00000000",
|
1682
|
+
// "cost":"0.00000",
|
1683
|
+
// "fee":"0.00000",
|
1684
|
+
// "price":"0.00000",
|
1685
|
+
// "stopprice":"0.00000",
|
1686
|
+
// "limitprice":"0.00000",
|
1687
|
+
// "misc":"",
|
1688
|
+
// "oflags":"fciq"
|
1689
|
+
// },
|
1690
|
+
// },
|
1691
|
+
// "count":16
|
1692
|
+
// }
|
1693
|
+
// }
|
1694
|
+
//
|
1695
|
+
let market = undefined;
|
1696
|
+
if (symbol !== undefined) {
|
1697
|
+
market = this.market (symbol);
|
1698
|
+
}
|
1699
|
+
const result = this.safeValue (response, 'result', {});
|
1700
|
+
const orders = this.safeValue (result, 'closed', []);
|
1701
|
+
return this.parseOrders (orders, market, since, limit);
|
1702
|
+
}
|
1703
|
+
|
1704
|
+
parseTransactionStatus (status) {
|
1705
|
+
// IFEX transaction states
|
1706
|
+
const statuses = {
|
1707
|
+
'Initial': 'pending',
|
1708
|
+
'Pending': 'pending',
|
1709
|
+
'Success': 'ok',
|
1710
|
+
'Settled': 'pending',
|
1711
|
+
'Failure': 'failed',
|
1712
|
+
'Partial': 'ok',
|
1713
|
+
};
|
1714
|
+
return this.safeString (statuses, status, status);
|
1715
|
+
}
|
1716
|
+
|
1717
|
+
parseTransaction (transaction, currency = undefined) {
|
1718
|
+
//
|
1719
|
+
// fetchDeposits
|
1720
|
+
//
|
1721
|
+
// {
|
1722
|
+
// method: "Ether (Hex)",
|
1723
|
+
// aclass: "currency",
|
1724
|
+
// asset: "XETH",
|
1725
|
+
// refid: "Q2CANKL-LBFVEE-U4Y2WQ",
|
1726
|
+
// txid: "0x57fd704dab1a73c20e24c8696099b695d596924b401b261513cfdab23…",
|
1727
|
+
// info: "0x615f9ba7a9575b0ab4d571b2b36b1b324bd83290",
|
1728
|
+
// amount: "7.9999257900",
|
1729
|
+
// fee: "0.0000000000",
|
1730
|
+
// time: 1529223212,
|
1731
|
+
// status: "Success"
|
1732
|
+
// }
|
1733
|
+
//
|
1734
|
+
// there can be an additional 'status-prop' field present
|
1735
|
+
// deposit pending review by exchange => 'on-hold'
|
1736
|
+
// the deposit is initiated by the exchange => 'return'
|
1737
|
+
//
|
1738
|
+
// {
|
1739
|
+
// type: 'deposit',
|
1740
|
+
// method: 'Fidor Bank AG (Wire Transfer)',
|
1741
|
+
// aclass: 'currency',
|
1742
|
+
// asset: 'ZEUR',
|
1743
|
+
// refid: 'xxx-xxx-xxx',
|
1744
|
+
// txid: '12341234',
|
1745
|
+
// info: 'BANKCODEXXX',
|
1746
|
+
// amount: '38769.08',
|
1747
|
+
// fee: '0.0000',
|
1748
|
+
// time: 1644306552,
|
1749
|
+
// status: 'Success',
|
1750
|
+
// status-prop: 'on-hold'
|
1751
|
+
// }
|
1752
|
+
//
|
1753
|
+
//
|
1754
|
+
// fetchWithdrawals
|
1755
|
+
//
|
1756
|
+
// {
|
1757
|
+
// method: "Ether",
|
1758
|
+
// aclass: "currency",
|
1759
|
+
// asset: "XETH",
|
1760
|
+
// refid: "A2BF34S-O7LBNQ-UE4Y4O",
|
1761
|
+
// txid: "0x288b83c6b0904d8400ef44e1c9e2187b5c8f7ea3d838222d53f701a15b5c274d",
|
1762
|
+
// info: "0x7cb275a5e07ba943fee972e165d80daa67cb2dd0",
|
1763
|
+
// amount: "9.9950000000",
|
1764
|
+
// fee: "0.0050000000",
|
1765
|
+
// time: 1530481750,
|
1766
|
+
// status: "Success"
|
1767
|
+
// status-prop: 'on-hold' // this field might not be present in some cases
|
1768
|
+
// }
|
1769
|
+
//
|
1770
|
+
// withdraw
|
1771
|
+
//
|
1772
|
+
// {
|
1773
|
+
// "refid": "AGBSO6T-UFMTTQ-I7KGS6"
|
1774
|
+
// }
|
1775
|
+
//
|
1776
|
+
const id = this.safeString (transaction, 'refid');
|
1777
|
+
const txid = this.safeString (transaction, 'txid');
|
1778
|
+
const timestamp = this.safeTimestamp (transaction, 'time');
|
1779
|
+
const currencyId = this.safeString (transaction, 'asset');
|
1780
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
1781
|
+
const address = this.safeString (transaction, 'info');
|
1782
|
+
const amount = this.safeNumber (transaction, 'amount');
|
1783
|
+
let status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
|
1784
|
+
const statusProp = this.safeString (transaction, 'status-prop');
|
1785
|
+
const isOnHoldDeposit = statusProp === 'on-hold';
|
1786
|
+
const isCancellationRequest = statusProp === 'cancel-pending';
|
1787
|
+
const isOnHoldWithdrawal = statusProp === 'onhold';
|
1788
|
+
if (isOnHoldDeposit || isCancellationRequest || isOnHoldWithdrawal) {
|
1789
|
+
status = 'pending';
|
1790
|
+
}
|
1791
|
+
const type = this.safeString (transaction, 'type'); // injected from the outside
|
1792
|
+
let feeCost = this.safeNumber (transaction, 'fee');
|
1793
|
+
if (feeCost === undefined) {
|
1794
|
+
if (type === 'deposit') {
|
1795
|
+
feeCost = 0;
|
1796
|
+
}
|
1797
|
+
}
|
1798
|
+
return {
|
1799
|
+
'info': transaction,
|
1800
|
+
'id': id,
|
1801
|
+
'currency': code,
|
1802
|
+
'amount': amount,
|
1803
|
+
'network': undefined,
|
1804
|
+
'address': address,
|
1805
|
+
'addressTo': undefined,
|
1806
|
+
'addressFrom': undefined,
|
1807
|
+
'tag': undefined,
|
1808
|
+
'tagTo': undefined,
|
1809
|
+
'tagFrom': undefined,
|
1810
|
+
'status': status,
|
1811
|
+
'type': type,
|
1812
|
+
'updated': undefined,
|
1813
|
+
'txid': txid,
|
1814
|
+
'timestamp': timestamp,
|
1815
|
+
'datetime': this.iso8601 (timestamp),
|
1816
|
+
'fee': {
|
1817
|
+
'currency': code,
|
1818
|
+
'cost': feeCost,
|
1819
|
+
},
|
1820
|
+
};
|
1821
|
+
}
|
1822
|
+
|
1823
|
+
parseTransactionsByType (type, transactions, code = undefined, since = undefined, limit = undefined) {
|
1824
|
+
const result = [];
|
1825
|
+
for (let i = 0; i < transactions.length; i++) {
|
1826
|
+
const transaction = this.parseTransaction (this.extend ({
|
1827
|
+
'type': type,
|
1828
|
+
}, transactions[i]));
|
1829
|
+
result.push (transaction);
|
1830
|
+
}
|
1831
|
+
return this.filterByCurrencySinceLimit (result, code, since, limit);
|
1832
|
+
}
|
1833
|
+
|
1834
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1835
|
+
// https://www.kraken.com/en-us/help/api#deposit-status
|
1836
|
+
if (code === undefined) {
|
1837
|
+
throw new ArgumentsRequired (this.id + ' fetchDeposits() requires a currency code argument');
|
1838
|
+
}
|
1839
|
+
await this.loadMarkets ();
|
1840
|
+
const currency = this.currency (code);
|
1841
|
+
const request = {
|
1842
|
+
'asset': currency['id'],
|
1843
|
+
};
|
1844
|
+
const response = await this.privatePostDepositStatus (this.extend (request, params));
|
1845
|
+
//
|
1846
|
+
// { error: [],
|
1847
|
+
// result: [ { method: "Ether (Hex)",
|
1848
|
+
// aclass: "currency",
|
1849
|
+
// asset: "XETH",
|
1850
|
+
// refid: "Q2CANKL-LBFVEE-U4Y2WQ",
|
1851
|
+
// txid: "0x57fd704dab1a73c20e24c8696099b695d596924b401b261513cfdab23…",
|
1852
|
+
// info: "0x615f9ba7a9575b0ab4d571b2b36b1b324bd83290",
|
1853
|
+
// amount: "7.9999257900",
|
1854
|
+
// fee: "0.0000000000",
|
1855
|
+
// time: 1529223212,
|
1856
|
+
// status: "Success" } ] }
|
1857
|
+
//
|
1858
|
+
return this.parseTransactionsByType ('deposit', response['result'], code, since, limit);
|
1859
|
+
}
|
1860
|
+
|
1861
|
+
async fetchTime (params = {}) {
|
1862
|
+
// https://www.kraken.com/en-us/features/api#get-server-time
|
1863
|
+
const response = await this.publicGetTime (params);
|
1864
|
+
//
|
1865
|
+
// {
|
1866
|
+
// "error": [],
|
1867
|
+
// "result": {
|
1868
|
+
// "unixtime": 1591502873,
|
1869
|
+
// "rfc1123": "Sun, 7 Jun 20 04:07:53 +0000"
|
1870
|
+
// }
|
1871
|
+
// }
|
1872
|
+
//
|
1873
|
+
const result = this.safeValue (response, 'result', {});
|
1874
|
+
return this.safeTimestamp (result, 'unixtime');
|
1875
|
+
}
|
1876
|
+
|
1877
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1878
|
+
// https://www.kraken.com/en-us/help/api#withdraw-status
|
1879
|
+
if (code === undefined) {
|
1880
|
+
throw new ArgumentsRequired (this.id + ' fetchWithdrawals() requires a currency code argument');
|
1881
|
+
}
|
1882
|
+
await this.loadMarkets ();
|
1883
|
+
const currency = this.currency (code);
|
1884
|
+
const request = {
|
1885
|
+
'asset': currency['id'],
|
1886
|
+
};
|
1887
|
+
const response = await this.privatePostWithdrawStatus (this.extend (request, params));
|
1888
|
+
//
|
1889
|
+
// { error: [],
|
1890
|
+
// result: [ { method: "Ether",
|
1891
|
+
// aclass: "currency",
|
1892
|
+
// asset: "XETH",
|
1893
|
+
// refid: "A2BF34S-O7LBNQ-UE4Y4O",
|
1894
|
+
// txid: "0x298c83c7b0904d8400ef43e1c9e2287b518f7ea3d838822d53f704a1565c274d",
|
1895
|
+
// info: "0x7cb275a5e07ba943fee972e165d80daa67cb2dd0",
|
1896
|
+
// amount: "9.9950000000",
|
1897
|
+
// fee: "0.0050000000",
|
1898
|
+
// time: 1530481750,
|
1899
|
+
// status: "Success" } ] }
|
1900
|
+
//
|
1901
|
+
return this.parseTransactionsByType ('withdrawal', response['result'], code, since, limit);
|
1902
|
+
}
|
1903
|
+
|
1904
|
+
async createDepositAddress (code, params = {}) {
|
1905
|
+
const request = {
|
1906
|
+
'new': 'true',
|
1907
|
+
};
|
1908
|
+
return await this.fetchDepositAddress (code, this.extend (request, params));
|
1909
|
+
}
|
1910
|
+
|
1911
|
+
async fetchDepositMethods (code, params = {}) {
|
1912
|
+
await this.loadMarkets ();
|
1913
|
+
const currency = this.currency (code);
|
1914
|
+
const request = {
|
1915
|
+
'asset': currency['id'],
|
1916
|
+
};
|
1917
|
+
const response = await this.privatePostDepositMethods (this.extend (request, params));
|
1918
|
+
//
|
1919
|
+
// {
|
1920
|
+
// "error":[],
|
1921
|
+
// "result":[
|
1922
|
+
// {"method":"Ether (Hex)","limit":false,"gen-address":true}
|
1923
|
+
// ]
|
1924
|
+
// }
|
1925
|
+
//
|
1926
|
+
// {
|
1927
|
+
// "error":[],
|
1928
|
+
// "result":[
|
1929
|
+
// {"method":"Tether USD (ERC20)","limit":false,"address-setup-fee":"0.00000000","gen-address":true},
|
1930
|
+
// {"method":"Tether USD (TRC20)","limit":false,"address-setup-fee":"0.00000000","gen-address":true}
|
1931
|
+
// ]
|
1932
|
+
// }
|
1933
|
+
//
|
1934
|
+
// {
|
1935
|
+
// "error":[],
|
1936
|
+
// "result":[
|
1937
|
+
// {"method":"Bitcoin","limit":false,"fee":"0.0000000000","gen-address":true}
|
1938
|
+
// ]
|
1939
|
+
// }
|
1940
|
+
//
|
1941
|
+
return this.safeValue (response, 'result');
|
1942
|
+
}
|
1943
|
+
|
1944
|
+
async fetchDepositAddress (code, params = {}) {
|
1945
|
+
await this.loadMarkets ();
|
1946
|
+
const currency = this.currency (code);
|
1947
|
+
let network = this.safeStringUpper (params, 'network');
|
1948
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
1949
|
+
network = this.safeString (networks, network, network); // support ETH > ERC20 aliases
|
1950
|
+
params = this.omit (params, 'network');
|
1951
|
+
if ((code === 'USDT') && (network === 'TRC20')) {
|
1952
|
+
code = code + '-' + network;
|
1953
|
+
}
|
1954
|
+
const defaultDepositMethods = this.safeValue (this.options, 'depositMethods', {});
|
1955
|
+
const defaultDepositMethod = this.safeString (defaultDepositMethods, code);
|
1956
|
+
let depositMethod = this.safeString (params, 'method', defaultDepositMethod);
|
1957
|
+
// if the user has specified an exchange-specific method in params
|
1958
|
+
// we pass it as is, otherwise we take the 'network' unified param
|
1959
|
+
if (depositMethod === undefined) {
|
1960
|
+
const depositMethods = await this.fetchDepositMethods (code);
|
1961
|
+
if (network !== undefined) {
|
1962
|
+
// find best matching deposit method, or fallback to the first one
|
1963
|
+
for (let i = 0; i < depositMethods.length; i++) {
|
1964
|
+
const entry = this.safeString (depositMethods[i], 'method');
|
1965
|
+
if (entry.indexOf (network) >= 0) {
|
1966
|
+
depositMethod = entry;
|
1967
|
+
break;
|
1968
|
+
}
|
1969
|
+
}
|
1970
|
+
}
|
1971
|
+
// if depositMethod was not specified, fallback to the first available deposit method
|
1972
|
+
if (depositMethod === undefined) {
|
1973
|
+
const firstDepositMethod = this.safeValue (depositMethods, 0, {});
|
1974
|
+
depositMethod = this.safeString (firstDepositMethod, 'method');
|
1975
|
+
}
|
1976
|
+
}
|
1977
|
+
const request = {
|
1978
|
+
'asset': currency['id'],
|
1979
|
+
'method': depositMethod,
|
1980
|
+
};
|
1981
|
+
const response = await this.privatePostDepositAddresses (this.extend (request, params));
|
1982
|
+
//
|
1983
|
+
// {
|
1984
|
+
// "error":[],
|
1985
|
+
// "result":[
|
1986
|
+
// {"address":"0x77b5051f97efa9cc52c9ad5b023a53fc15c200d3","expiretm":"0"}
|
1987
|
+
// ]
|
1988
|
+
// }
|
1989
|
+
//
|
1990
|
+
const result = this.safeValue (response, 'result', []);
|
1991
|
+
const firstResult = this.safeValue (result, 0, {});
|
1992
|
+
if (firstResult === undefined) {
|
1993
|
+
throw new InvalidAddress (this.id + ' privatePostDepositAddresses() returned no addresses for ' + code);
|
1994
|
+
}
|
1995
|
+
return this.parseDepositAddress (firstResult, currency);
|
1996
|
+
}
|
1997
|
+
|
1998
|
+
parseDepositAddress (depositAddress, currency = undefined) {
|
1999
|
+
//
|
2000
|
+
// {
|
2001
|
+
// "address":"0x77b5051f97efa9cc52c9ad5b023a53fc15c200d3",
|
2002
|
+
// "expiretm":"0"
|
2003
|
+
// }
|
2004
|
+
//
|
2005
|
+
const address = this.safeString (depositAddress, 'address');
|
2006
|
+
const tag = this.safeString (depositAddress, 'tag');
|
2007
|
+
currency = this.safeCurrency (undefined, currency);
|
2008
|
+
const code = currency['code'];
|
2009
|
+
this.checkAddress (address);
|
2010
|
+
return {
|
2011
|
+
'currency': code,
|
2012
|
+
'address': address,
|
2013
|
+
'tag': tag,
|
2014
|
+
'network': undefined,
|
2015
|
+
'info': depositAddress,
|
2016
|
+
};
|
2017
|
+
}
|
2018
|
+
|
2019
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
2020
|
+
[ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
|
2021
|
+
this.checkAddress (address);
|
2022
|
+
if ('key' in params) {
|
2023
|
+
await this.loadMarkets ();
|
2024
|
+
const currency = this.currency (code);
|
2025
|
+
const request = {
|
2026
|
+
'asset': currency['id'],
|
2027
|
+
'amount': amount,
|
2028
|
+
// 'address': address, // they don't allow withdrawals to direct addresses
|
2029
|
+
};
|
2030
|
+
const response = await this.privatePostWithdraw (this.extend (request, params));
|
2031
|
+
//
|
2032
|
+
// {
|
2033
|
+
// "error": [],
|
2034
|
+
// "result": {
|
2035
|
+
// "refid": "AGBSO6T-UFMTTQ-I7KGS6"
|
2036
|
+
// }
|
2037
|
+
// }
|
2038
|
+
//
|
2039
|
+
const result = this.safeValue (response, 'result', {});
|
2040
|
+
return this.parseTransaction (result, currency);
|
2041
|
+
}
|
2042
|
+
throw new ExchangeError (this.id + " withdraw() requires a 'key' parameter (withdrawal key name, as set up on your account)");
|
2043
|
+
}
|
2044
|
+
|
2045
|
+
async fetchPositions (symbols = undefined, params = {}) {
|
2046
|
+
await this.loadMarkets ();
|
2047
|
+
const request = {
|
2048
|
+
// 'txid': 'comma delimited list of transaction ids to restrict output to',
|
2049
|
+
// 'docalcs': false, // whether or not to include profit/loss calculations
|
2050
|
+
// 'consolidation': 'market', // what to consolidate the positions data around, market will consolidate positions based on market pair
|
2051
|
+
};
|
2052
|
+
const response = await this.privatePostOpenPositions (this.extend (request, params));
|
2053
|
+
//
|
2054
|
+
// no consolidation
|
2055
|
+
//
|
2056
|
+
// {
|
2057
|
+
// error: [],
|
2058
|
+
// result: {
|
2059
|
+
// 'TGUFMY-FLESJ-VYIX3J': {
|
2060
|
+
// ordertxid: "O3LRNU-ZKDG5-XNCDFR",
|
2061
|
+
// posstatus: "open",
|
2062
|
+
// pair: "ETHUSDT",
|
2063
|
+
// time: 1611557231.4584,
|
2064
|
+
// type: "buy",
|
2065
|
+
// ordertype: "market",
|
2066
|
+
// cost: "28.49800",
|
2067
|
+
// fee: "0.07979",
|
2068
|
+
// vol: "0.02000000",
|
2069
|
+
// vol_closed: "0.00000000",
|
2070
|
+
// margin: "14.24900",
|
2071
|
+
// terms: "0.0200% per 4 hours",
|
2072
|
+
// rollovertm: "1611571631",
|
2073
|
+
// misc: "",
|
2074
|
+
// oflags: ""
|
2075
|
+
// }
|
2076
|
+
// }
|
2077
|
+
// }
|
2078
|
+
//
|
2079
|
+
// consolidation by market
|
2080
|
+
//
|
2081
|
+
// {
|
2082
|
+
// error: [],
|
2083
|
+
// result: [
|
2084
|
+
// {
|
2085
|
+
// pair: "ETHUSDT",
|
2086
|
+
// positions: "1",
|
2087
|
+
// type: "buy",
|
2088
|
+
// leverage: "2.00000",
|
2089
|
+
// cost: "28.49800",
|
2090
|
+
// fee: "0.07979",
|
2091
|
+
// vol: "0.02000000",
|
2092
|
+
// vol_closed: "0.00000000",
|
2093
|
+
// margin: "14.24900"
|
2094
|
+
// }
|
2095
|
+
// ]
|
2096
|
+
// }
|
2097
|
+
//
|
2098
|
+
const result = this.safeValue (response, 'result');
|
2099
|
+
// todo unify parsePosition/parsePositions
|
2100
|
+
return result;
|
2101
|
+
}
|
2102
|
+
|
2103
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
2104
|
+
let url = '/' + this.version + '/' + api + '/' + path;
|
2105
|
+
if (api === 'public') {
|
2106
|
+
if (Object.keys (params).length) {
|
2107
|
+
// urlencodeNested is used to address https://github.com/ccxt/ccxt/issues/12872
|
2108
|
+
url += '?' + this.urlencodeNested (params);
|
2109
|
+
}
|
2110
|
+
} else if (api === 'private') {
|
2111
|
+
this.checkRequiredCredentials ();
|
2112
|
+
const nonce = this.nonce ().toString ();
|
2113
|
+
// urlencodeNested is used to address https://github.com/ccxt/ccxt/issues/12872
|
2114
|
+
body = this.urlencodeNested (this.extend ({ 'nonce': nonce }, params));
|
2115
|
+
const auth = this.encode (nonce + body);
|
2116
|
+
const hash = this.hash (auth, 'sha256', 'binary');
|
2117
|
+
const binary = this.stringToBinary (this.encode (url));
|
2118
|
+
const binhash = this.binaryConcat (binary, hash);
|
2119
|
+
const secret = this.base64ToBinary (this.secret);
|
2120
|
+
const signature = this.hmac (binhash, secret, 'sha512', 'base64');
|
2121
|
+
headers = {
|
2122
|
+
'API-Key': this.apiKey,
|
2123
|
+
'API-Sign': signature,
|
2124
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
2125
|
+
};
|
2126
|
+
} else {
|
2127
|
+
url = '/' + path;
|
2128
|
+
}
|
2129
|
+
url = this.urls['api'][api] + url;
|
2130
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
2131
|
+
}
|
2132
|
+
|
2133
|
+
nonce () {
|
2134
|
+
return this.milliseconds ();
|
2135
|
+
}
|
2136
|
+
|
2137
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
2138
|
+
if (code === 520) {
|
2139
|
+
throw new ExchangeNotAvailable (this.id + ' ' + code.toString () + ' ' + reason);
|
2140
|
+
}
|
2141
|
+
// todo: rewrite this for "broad" exceptions matching
|
2142
|
+
if (body.indexOf ('Invalid order') >= 0) {
|
2143
|
+
throw new InvalidOrder (this.id + ' ' + body);
|
2144
|
+
}
|
2145
|
+
if (body.indexOf ('Invalid nonce') >= 0) {
|
2146
|
+
throw new InvalidNonce (this.id + ' ' + body);
|
2147
|
+
}
|
2148
|
+
if (body.indexOf ('Insufficient funds') >= 0) {
|
2149
|
+
throw new InsufficientFunds (this.id + ' ' + body);
|
2150
|
+
}
|
2151
|
+
if (body.indexOf ('Cancel pending') >= 0) {
|
2152
|
+
throw new CancelPending (this.id + ' ' + body);
|
2153
|
+
}
|
2154
|
+
if (body.indexOf ('Invalid arguments:volume') >= 0) {
|
2155
|
+
throw new InvalidOrder (this.id + ' ' + body);
|
2156
|
+
}
|
2157
|
+
if (body.indexOf ('Rate limit exceeded') >= 0) {
|
2158
|
+
throw new RateLimitExceeded (this.id + ' ' + body);
|
2159
|
+
}
|
2160
|
+
if (response === undefined) {
|
2161
|
+
return;
|
2162
|
+
}
|
2163
|
+
if (body[0] === '{') {
|
2164
|
+
if (typeof response !== 'string') {
|
2165
|
+
if ('error' in response) {
|
2166
|
+
const numErrors = response['error'].length;
|
2167
|
+
if (numErrors) {
|
2168
|
+
const message = this.id + ' ' + body;
|
2169
|
+
for (let i = 0; i < response['error'].length; i++) {
|
2170
|
+
const error = response['error'][i];
|
2171
|
+
this.throwExactlyMatchedException (this.exceptions, error, message);
|
2172
|
+
}
|
2173
|
+
throw new ExchangeError (message);
|
2174
|
+
}
|
2175
|
+
}
|
2176
|
+
}
|
2177
|
+
}
|
2178
|
+
}
|
2179
|
+
};
|